Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/collection.c
| Show First 20 Lines • Show All 1,803 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Collection move (outliner drag & drop) | /** \name Collection move (outliner drag & drop) | ||||
| * \{ */ | * \{ */ | ||||
| /* Local temporary storage for layer collection flags. */ | |||||
| typedef struct LayerCollectionFlag { | |||||
| struct LayerCollectionFlag *next, *prev; | |||||
| /** The view layer for the collections being moved, NULL for their children. */ | |||||
| ViewLayer *view_layer; | |||||
| /** The original #LayerCollection's collection field. */ | |||||
| Collection *collection; | |||||
| /** The original #LayerCollection's flag. */ | |||||
| int flag; | |||||
| /** Corresponds to #LayerCollection->layer_collections. */ | |||||
| ListBase children; | |||||
| } LayerCollectionFlag; | |||||
| static void layer_collection_flags_store_recursive(const LayerCollection *layer_collection, | |||||
| LayerCollectionFlag *flag) | |||||
| { | |||||
| flag->collection = layer_collection->collection; | |||||
| flag->flag = layer_collection->flag; | |||||
| LISTBASE_FOREACH (const LayerCollection *, child, &layer_collection->layer_collections) { | |||||
| LayerCollectionFlag *child_flag = MEM_callocN(sizeof(LayerCollectionFlag), __func__); | |||||
| BLI_addtail(&flag->children, child_flag); | |||||
| layer_collection_flags_store_recursive(child, child_flag); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * For every view layer, find the \a collection and save flags | |||||
| * for it and its children in a temporary tree structure. | |||||
| */ | |||||
| static void layer_collection_flags_store(Main *bmain, | |||||
| const Collection *collection, | |||||
| ListBase *r_layer_level_list) | |||||
| { | |||||
| BLI_listbase_clear(r_layer_level_list); | |||||
| LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { | |||||
| LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { | |||||
| LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection( | |||||
| view_layer, collection); | |||||
| /* Skip this view layer if the collection isn't found for some reason. */ | |||||
| if (layer_collection == NULL) { | |||||
| continue; | |||||
| } | |||||
| /* Store the flags for the collection and all of its children. */ | |||||
| LayerCollectionFlag *flag = MEM_callocN(sizeof(LayerCollectionFlag), __func__); | |||||
| flag->view_layer = view_layer; | |||||
| /* Recursively save flags from collection children. */ | |||||
| layer_collection_flags_store_recursive(layer_collection, flag); | |||||
| BLI_addtail(r_layer_level_list, flag); | |||||
| } | |||||
| } | |||||
| } | |||||
| static void layer_collection_flags_free_recursive(LayerCollectionFlag *flag) | |||||
| { | |||||
| LISTBASE_FOREACH (LayerCollectionFlag *, child, &flag->children) { | |||||
| layer_collection_flags_free_recursive(child); | |||||
| } | |||||
| BLI_freelistN(&flag->children); | |||||
| } | |||||
| static void layer_collection_flags_restore_recursive(LayerCollection *layer_collection, | |||||
| LayerCollectionFlag *flag) | |||||
| { | |||||
| /* There should be a flag struct for every layer collection. */ | |||||
| BLI_assert(BLI_listbase_count(&layer_collection->layer_collections) == | |||||
| BLI_listbase_count(&flag->children)); | |||||
| /* The flag and the layer collection should actually correspond. */ | |||||
| BLI_assert(flag->collection == layer_collection->collection); | |||||
| LayerCollectionFlag *child_flag = flag->children.first; | |||||
| LISTBASE_FOREACH (LayerCollection *, child, &layer_collection->layer_collections) { | |||||
| layer_collection_flags_restore_recursive(child, child_flag); | |||||
| child_flag = child_flag->next; | |||||
| } | |||||
| /* We treat exclude as a special case. | |||||
| * | |||||
| * If in a different view layer the parent collection was disabled (e.g., background) | |||||
| * and now we moved a new collection to be part of the background this collection should | |||||
| * probably be disabled. | |||||
| * | |||||
| * NOTE: If we were to also keep the exclude flag we would need to re-sync the collections. | |||||
| */ | |||||
| layer_collection->flag = flag->flag | (layer_collection->flag & LAYER_COLLECTION_EXCLUDE); | |||||
| } | |||||
| /** | |||||
| * Restore a collection's (and its children's) flags for each view layer | |||||
| * from the structure built in #layer_collection_flags_store. | |||||
| */ | |||||
| static void layer_collection_flags_restore(ListBase *flags, const Collection *collection) | |||||
| { | |||||
| LISTBASE_FOREACH (LayerCollectionFlag *, flag, flags) { | |||||
| ViewLayer *view_layer = flag->view_layer; | |||||
| /* The top level of flag structs must have this set. */ | |||||
| BLI_assert(view_layer != NULL); | |||||
| LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection( | |||||
| view_layer, collection); | |||||
| /* Check that the collection is still in the scene (and therefore its view layers). In most | |||||
| * cases this is true, but if we move a sub-collection shared by several scenes to a collection | |||||
| * local to the target scene, it is effectively removed from every other scene's hierarchy | |||||
| * (e.g. moving into current scene's master collection). Then the other scene's view layers | |||||
| * won't contain a matching layer collection anymore, so there is nothing to restore to. */ | |||||
| if (layer_collection != NULL) { | |||||
| layer_collection_flags_restore_recursive(layer_collection, flag); | |||||
| } | |||||
| layer_collection_flags_free_recursive(flag); | |||||
| } | |||||
| BLI_freelistN(flags); | |||||
| } | |||||
| bool BKE_collection_move(Main *bmain, | bool BKE_collection_move(Main *bmain, | ||||
| Collection *to_parent, | Collection *to_parent, | ||||
| Collection *from_parent, | Collection *from_parent, | ||||
| Collection *relative, | Collection *relative, | ||||
| bool relative_after, | bool relative_after, | ||||
| Collection *collection) | Collection *collection) | ||||
| { | { | ||||
| if (collection->flag & COLLECTION_IS_MASTER) { | if (collection->flag & COLLECTION_IS_MASTER) { | ||||
| Show All 24 Lines | if (relative_child) { | ||||
| else { | else { | ||||
| BLI_insertlinkbefore(&to_parent->children, relative_child, child); | BLI_insertlinkbefore(&to_parent->children, relative_child, child); | ||||
| } | } | ||||
| BKE_collection_object_cache_free(to_parent); | BKE_collection_object_cache_free(to_parent); | ||||
| } | } | ||||
| } | } | ||||
| /* Make sure we store the flag of the layer collections before we remove and re-create them. | /* Update layer collections. */ | ||||
| * Otherwise they will get lost and everything will be copied from the new parent collection. | |||||
| * Don't use flag syncing when moving a collection to a different scene, as it no longer exists | |||||
| * in the same view layers anyway. */ | |||||
| const bool do_flag_sync = BKE_scene_find_from_collection(bmain, to_parent) == | |||||
| BKE_scene_find_from_collection(bmain, collection); | |||||
| ListBase layer_flags; | |||||
| if (do_flag_sync) { | |||||
| layer_collection_flags_store(bmain, collection, &layer_flags); | |||||
| } | |||||
| /* Create and remove layer collections. */ | |||||
| BKE_main_collection_sync(bmain); | |||||
| /* Restore the original layer collection flags and free their temporary storage. */ | |||||
| if (do_flag_sync) { | |||||
| layer_collection_flags_restore(&layer_flags, collection); | |||||
| } | |||||
| /* We need to sync it again to pass the correct flags to the collections objects. */ | |||||
| BKE_main_collection_sync(bmain); | BKE_main_collection_sync(bmain); | ||||
| return true; | return true; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| ▲ Show 20 Lines • Show All 229 Lines • Show Last 20 Lines | |||||