Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/collection.c
| Show First 20 Lines • Show All 185 Lines • ▼ Show 20 Lines | static ID *collection_owner_get(Main *bmain, ID *id) | ||||
| BLI_assert((master_collection->flag & COLLECTION_IS_MASTER) != 0); | BLI_assert((master_collection->flag & COLLECTION_IS_MASTER) != 0); | ||||
| for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { | for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { | ||||
| if (scene->master_collection == master_collection) { | if (scene->master_collection == master_collection) { | ||||
| return &scene->id; | return &scene->id; | ||||
| } | } | ||||
| } | } | ||||
| BLI_assert(!"Embedded collection with no owner. Critical Main inconsistency."); | BLI_assert_msg(0, "Embedded collection with no owner. Critical Main inconsistency."); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| void BKE_collection_blend_write_nolib(BlendWriter *writer, Collection *collection) | void BKE_collection_blend_write_nolib(BlendWriter *writer, Collection *collection) | ||||
| { | { | ||||
| BKE_id_blend_write(writer, &collection->id); | BKE_id_blend_write(writer, &collection->id); | ||||
| /* Shared function for collection data-blocks and scene master collection. */ | /* Shared function for collection data-blocks and scene master collection. */ | ||||
| ▲ Show 20 Lines • Show All 314 Lines • ▼ Show 20 Lines | |||||
| /** | /** | ||||
| * Remove a collection, optionally removing its child objects or moving | * Remove a collection, optionally removing its child objects or moving | ||||
| * them to parent collections. | * them to parent collections. | ||||
| */ | */ | ||||
| bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy) | bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy) | ||||
| { | { | ||||
| /* Master collection is not real datablock, can't be removed. */ | /* Master collection is not real datablock, can't be removed. */ | ||||
| if (collection->flag & COLLECTION_IS_MASTER) { | if (collection->flag & COLLECTION_IS_MASTER) { | ||||
| BLI_assert(!"Scene master collection can't be deleted"); | BLI_assert_msg(0, "Scene master collection can't be deleted"); | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (hierarchy) { | if (hierarchy) { | ||||
| /* Remove child objects. */ | /* Remove child objects. */ | ||||
| CollectionObject *cob = collection->gobject.first; | CollectionObject *cob = collection->gobject.first; | ||||
| while (cob != NULL) { | while (cob != NULL) { | ||||
| collection_object_remove(bmain, collection, cob->ob, true); | collection_object_remove(bmain, collection, cob->ob, true); | ||||
| ▲ Show 20 Lines • Show All 1,270 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 | |||||