diff options
Diffstat (limited to 'source/blender/blenkernel/intern/collection.c')
-rw-r--r-- | source/blender/blenkernel/intern/collection.c | 98 |
1 files changed, 68 insertions, 30 deletions
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 4967e3482c6..98b1e3d0039 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -7,6 +7,8 @@ /* Allow using deprecated functionality for .blend file I/O. */ #define DNA_DEPRECATED_ALLOW +#include "CLG_log.h" + #include <string.h> #include "BLI_blenlib.h" @@ -46,6 +48,8 @@ #include "BLO_read_write.h" +static CLG_LogRef LOG = {"bke.collection"}; + /* -------------------------------------------------------------------- */ /** \name Prototypes * \{ */ @@ -143,6 +147,9 @@ static void collection_foreach_id(ID *id, LibraryForeachIDData *data) { Collection *collection = (Collection *)id; + BKE_LIB_FOREACHID_PROCESS_ID( + data, collection->owner_id, IDWALK_CB_LOOPBACK | IDWALK_CB_NEVER_SELF); + LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, cob->ob, IDWALK_CB_USER); } @@ -162,29 +169,20 @@ static void collection_foreach_id(ID *id, LibraryForeachIDData *data) } } -static ID *collection_owner_get(Main *bmain, ID *id, ID *owner_id_hint) +static ID **collection_owner_pointer_get(ID *id) { if ((id->flag & LIB_EMBEDDED_DATA) == 0) { - return id; + return NULL; } BLI_assert((id->tag & LIB_TAG_NO_MAIN) == 0); Collection *master_collection = (Collection *)id; BLI_assert((master_collection->flag & COLLECTION_IS_MASTER) != 0); + BLI_assert(master_collection->owner_id != NULL); + BLI_assert(GS(master_collection->owner_id->name) == ID_SCE); + BLI_assert(((Scene *)master_collection->owner_id)->master_collection == master_collection); - if (owner_id_hint != NULL && GS(owner_id_hint->name) == ID_SCE && - ((Scene *)owner_id_hint)->master_collection == master_collection) { - return owner_id_hint; - } - - LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { - if (scene->master_collection == master_collection) { - return &scene->id; - } - } - - BLI_assert_msg(0, "Embedded collection with no owner. Critical Main inconsistency."); - return NULL; + return &master_collection->owner_id; } void BKE_collection_blend_write_nolib(BlendWriter *writer, Collection *collection) @@ -233,8 +231,35 @@ void BKE_collection_compat_blend_read_data(BlendDataReader *reader, SceneCollect } #endif -void BKE_collection_blend_read_data(BlendDataReader *reader, Collection *collection) -{ +void BKE_collection_blend_read_data(BlendDataReader *reader, Collection *collection, ID *owner_id) +{ + /* Special case for this pointer, do not rely on regular `lib_link` process here. Avoids needs + * for do_versioning, and ensures coherence of data in any case. + * + * NOTE: Old versions are very often 'broken' here, just fix it silently in these cases. + */ + if (BLO_read_fileversion_get(reader) > 300) { + BLI_assert((collection->id.flag & LIB_EMBEDDED_DATA) != 0 || owner_id == NULL); + } + BLI_assert(owner_id == NULL || owner_id->lib == collection->id.lib); + if (owner_id != NULL && (collection->id.flag & LIB_EMBEDDED_DATA) == 0) { + /* This is unfortunate, but currently a lot of existing files (including startup ones) have + * missing `LIB_EMBEDDED_DATA` flag. + * + * NOTE: Using do_version is not a solution here, since this code will be called before any + * do_version takes place. Keeping it here also ensures future (or unknown existing) similar + * bugs won't go easily unnoticed. */ + if (BLO_read_fileversion_get(reader) > 300) { + CLOG_WARN(&LOG, + "Fixing root node tree '%s' owned by '%s' missing EMBEDDED tag, please consider " + "re-saving your (startup) file", + collection->id.name, + owner_id->name); + } + collection->id.flag |= LIB_EMBEDDED_DATA; + } + collection->owner_id = owner_id; + BLO_read_list(reader, &collection->gobject); BLO_read_list(reader, &collection->children); @@ -265,7 +290,7 @@ void BKE_collection_blend_read_data(BlendDataReader *reader, Collection *collect static void collection_blend_read_data(BlendDataReader *reader, ID *id) { Collection *collection = (Collection *)id; - BKE_collection_blend_read_data(reader, collection); + BKE_collection_blend_read_data(reader, collection, NULL); } static void lib_link_collection_data(BlendLibReader *reader, Library *lib, Collection *collection) @@ -375,7 +400,7 @@ IDTypeInfo IDType_ID_GR = { .foreach_id = collection_foreach_id, .foreach_cache = NULL, .foreach_path = NULL, - .owner_get = collection_owner_get, + .owner_pointer_get = collection_owner_pointer_get, .blend_write = collection_blend_write, .blend_read_data = collection_blend_read_data, @@ -466,8 +491,8 @@ void BKE_collection_add_from_collection(Main *bmain, is_instantiated = true; } else if (!is_instantiated && collection_find_child(collection, collection_dst)) { - /* If given collection_dst is already instantiated in scene, even if its 'model' src one is - * not, do not add it to master scene collection. */ + /* If given collection_dst is already instantiated in scene, even if its 'model' + * collection_src one is not, do not add it to master scene collection. */ is_instantiated = true; } } @@ -834,13 +859,15 @@ void BKE_collection_object_cache_free(Collection *collection) collection_object_cache_free(collection); } -Base *BKE_collection_or_layer_objects(const ViewLayer *view_layer, Collection *collection) +Base *BKE_collection_or_layer_objects(const Scene *scene, + ViewLayer *view_layer, + Collection *collection) { if (collection) { return BKE_collection_object_cache_get(collection).first; } - - return FIRSTBASE(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + return BKE_view_layer_object_bases_get(view_layer)->first; } /** \} */ @@ -849,14 +876,18 @@ Base *BKE_collection_or_layer_objects(const ViewLayer *view_layer, Collection *c /** \name Scene Master Collection * \{ */ -Collection *BKE_collection_master_add() +Collection *BKE_collection_master_add(Scene *scene) { + BLI_assert(scene != NULL && scene->master_collection == NULL); + /* Not an actual datablock, but owned by scene. */ Collection *master_collection = BKE_libblock_alloc( NULL, ID_GR, BKE_SCENE_COLLECTION_NAME, LIB_ID_CREATE_NO_MAIN); master_collection->id.flag |= LIB_EMBEDDED_DATA; + master_collection->owner_id = &scene->id; master_collection->flag |= COLLECTION_IS_MASTER; master_collection->color_tag = COLLECTION_COLOR_NONE; + return master_collection; } @@ -1720,7 +1751,10 @@ Collection *BKE_collection_from_index(Scene *scene, const int index) return collection_from_index_recursive(master_collection, index, &index_current); } -static bool collection_objects_select(ViewLayer *view_layer, Collection *collection, bool deselect) +static bool collection_objects_select(const Scene *scene, + ViewLayer *view_layer, + Collection *collection, + bool deselect) { bool changed = false; @@ -1728,6 +1762,7 @@ static bool collection_objects_select(ViewLayer *view_layer, Collection *collect return false; } + BKE_view_layer_synced_ensure(scene, view_layer); LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { Base *base = BKE_view_layer_base_find(view_layer, cob->ob); @@ -1748,7 +1783,7 @@ static bool collection_objects_select(ViewLayer *view_layer, Collection *collect } LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { - if (collection_objects_select(view_layer, collection, deselect)) { + if (collection_objects_select(scene, view_layer, collection, deselect)) { changed = true; } } @@ -1756,16 +1791,19 @@ static bool collection_objects_select(ViewLayer *view_layer, Collection *collect return changed; } -bool BKE_collection_objects_select(ViewLayer *view_layer, Collection *collection, bool deselect) +bool BKE_collection_objects_select(const Scene *scene, + ViewLayer *view_layer, + Collection *collection, + bool deselect) { LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection(view_layer, collection); if (layer_collection != NULL) { - return BKE_layer_collection_objects_select(view_layer, layer_collection, deselect); + return BKE_layer_collection_objects_select(scene, view_layer, layer_collection, deselect); } - return collection_objects_select(view_layer, collection, deselect); + return collection_objects_select(scene, view_layer, collection, deselect); } /** \} */ |