diff options
author | Bastien Montagne <bastien@blender.org> | 2021-04-08 12:27:05 +0300 |
---|---|---|
committer | Bastien Montagne <bastien@blender.org> | 2021-04-08 12:45:55 +0300 |
commit | e92a7800b57620df0a5d7619aead572667f27994 (patch) | |
tree | 22023baab0e8a340958391069d09bec3e526eddc /source | |
parent | c1b1ed4d5b2f90b48296055e817fded0f8ee8f38 (diff) |
LibOverride: Fix several issues with resync code.
This commit essentially touches to post-processing of collections and
objects after resync itself has been done, to ensure their proper
instantiation in the scene:
- Remove a lot of the process in resync case (resynced data are assumed
to be already instantiated in the scene, unlike override creation
case).
- For auto-resync, only do post-processing once after all overrides
have been resynced (doing it after each individual resynced was
causing a lot of instantiation glitches, with a lot of unwanted
extra objects and collections being added to the master collection).
It also deals in a much more reliable way with detection of objects
missing from the scene, by using the new `BKE_scene_objects_as_gset`
utils.
As a bonus this makes auto-resync process slightly faster (only by a few
percents, but that's always good to get).
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_lib_override.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/lib_override.c | 121 | ||||
-rw-r--r-- | source/blender/editors/space_outliner/outliner_tools.c | 2 |
3 files changed, 49 insertions, 77 deletions
diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h index 0750a3332a8..b9a478f8227 100644 --- a/source/blender/blenkernel/BKE_lib_override.h +++ b/source/blender/blenkernel/BKE_lib_override.h @@ -84,7 +84,8 @@ bool BKE_lib_override_library_resync(struct Main *bmain, struct ViewLayer *view_layer, struct ID *id_root, struct Collection *override_resync_residual_storage, - const bool do_hierarchy_enforce); + const bool do_hierarchy_enforce, + const bool do_post_process); void BKE_lib_override_library_main_resync(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer); diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 112c4c21a27..150b9ee8868 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -650,18 +650,6 @@ static bool lib_override_library_create_do(Main *bmain, ID *id_root) return BKE_lib_override_library_create_from_tag(bmain); } -BLI_INLINE bool lib_override_library_create_post_process_object_is_instantiated( - ViewLayer *view_layer, Object *object, const bool is_resync) -{ - /* We cannot rely on check for object being actually instantiated in resync case, because often - * the overridden collection is 'excluded' from the current view-layer. - * - * Fallback to a basic user-count check then, this is weak (since it could lead to some object - * not being instantiated at all), but it should work fine in most common cases. */ - return ((is_resync && ID_REAL_USERS(object) >= 1) || - (!is_resync && BKE_view_layer_base_find(view_layer, object) != NULL)); -} - static void lib_override_library_create_post_process(Main *bmain, Scene *scene, ViewLayer *view_layer, @@ -672,13 +660,23 @@ static void lib_override_library_create_post_process(Main *bmain, { BKE_main_collection_sync(bmain); - if (id_root->newid != NULL) { + /* We create a set of all objects referenced into the scene by its hierarchy of collections. + * NOTE: This is different that the list of bases, since objects in excluded collections etc. + * won't have a base, but are still considered as instanced from our point of view. */ + GSet *all_objects_in_scene = BKE_scene_objects_as_gset(scene, NULL); + + /* Instantiating the root collection or object should never be needed in resync case, since the + * old override would be remapped to the new one. */ + if (!is_resync && id_root != NULL && id_root->newid != NULL) { switch (GS(id_root->name)) { case ID_GR: { Object *ob_reference = id_reference != NULL && GS(id_reference->name) == ID_OB ? (Object *)id_reference : NULL; Collection *collection_new = ((Collection *)id_root->newid); + if (is_resync && BKE_collection_is_in_scene(collection_new)) { + break; + } if (ob_reference != NULL) { BKE_collection_add_from_object(bmain, scene, ob_reference, collection_new); } @@ -692,52 +690,16 @@ static void lib_override_library_create_post_process(Main *bmain, bmain, scene, ((Collection *)id_root), collection_new); } - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection_new, ob_new) { - if (ob_new != NULL && ob_new->id.override_library != NULL) { - if (ob_reference != NULL) { - Base *base = BKE_view_layer_base_find(view_layer, ob_new); - if (!lib_override_library_create_post_process_object_is_instantiated( - view_layer, ob_new, is_resync)) { - BKE_collection_object_add_from(bmain, scene, ob_reference, ob_new); - base = BKE_view_layer_base_find(view_layer, ob_new); - DEG_id_tag_update_ex( - bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); - if (is_resync) { - ob_new->id.flag |= LIB_LIB_OVERRIDE_RESYNC_LEFTOVER; - } - } + BLI_assert(BKE_collection_is_in_scene(collection_new)); - if (ob_new == (Object *)ob_reference->id.newid && base != NULL) { - /* TODO: is setting active needed? */ - BKE_view_layer_base_select_and_set_active(view_layer, base); - } - } - else if (!lib_override_library_create_post_process_object_is_instantiated( - view_layer, ob_new, is_resync)) { - BKE_collection_object_add(bmain, collection_new, ob_new); - DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); - if (is_resync) { - ob_new->id.flag |= LIB_LIB_OVERRIDE_RESYNC_LEFTOVER; - } - } - } - } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + all_objects_in_scene = BKE_scene_objects_as_gset(scene, all_objects_in_scene); break; } case ID_OB: { Object *ob_new = (Object *)id_root->newid; - if (!lib_override_library_create_post_process_object_is_instantiated( - view_layer, ob_new, is_resync)) { - if (is_resync && residual_storage != NULL) { - BKE_collection_object_add(bmain, residual_storage, ob_new); - } - else { - BKE_collection_object_add_from(bmain, scene, (Object *)id_root, ob_new); - } - if (is_resync) { - ob_new->id.flag |= LIB_LIB_OVERRIDE_RESYNC_LEFTOVER; - } + if (BLI_gset_lookup(all_objects_in_scene, ob_new) == NULL) { + BKE_collection_object_add_from(bmain, scene, (Object *)id_root, ob_new); + all_objects_in_scene = BKE_scene_objects_as_gset(scene, all_objects_in_scene); } break; } @@ -747,16 +709,15 @@ static void lib_override_library_create_post_process(Main *bmain, } /* We need to ensure all new overrides of objects are properly instantiated. */ + Collection *default_instantiating_collection = residual_storage; LISTBASE_FOREACH (Object *, ob, &bmain->objects) { Object *ob_new = (Object *)ob->id.newid; if (ob_new != NULL) { BLI_assert(ob_new->id.override_library != NULL && ob_new->id.override_library->reference == &ob->id); - Collection *default_instantiating_collection = residual_storage; - if (!lib_override_library_create_post_process_object_is_instantiated( - view_layer, ob_new, is_resync)) { - if (default_instantiating_collection == NULL) { + if (BLI_gset_lookup(all_objects_in_scene, ob_new) == NULL) { + if (id_root != NULL && default_instantiating_collection == NULL) { switch (GS(id_root->name)) { case ID_GR: { default_instantiating_collection = BKE_collection_add( @@ -777,21 +738,23 @@ static void lib_override_library_create_post_process(Main *bmain, default_instantiating_collection = collection; } } - if (default_instantiating_collection == NULL) { - default_instantiating_collection = scene->master_collection; - } break; } default: BLI_assert(0); } } + if (default_instantiating_collection == NULL) { + default_instantiating_collection = scene->master_collection; + } BKE_collection_object_add(bmain, default_instantiating_collection, ob_new); DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); } } } + + BLI_gset_free(all_objects_in_scene, NULL); } /** @@ -902,7 +865,8 @@ bool BKE_lib_override_library_resync(Main *bmain, ViewLayer *view_layer, ID *id_root, Collection *override_resync_residual_storage, - const bool do_hierarchy_enforce) + const bool do_hierarchy_enforce, + const bool do_post_process) { BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root)); BLI_assert(!ID_IS_LINKED(id_root)); @@ -1109,18 +1073,20 @@ bool BKE_lib_override_library_resync(Main *bmain, */ id_root = id_root_reference->newid; - /* Essentially ensures that potentially new overrides of new objects will be instantiated. */ - /* Note: Here 'reference' collection and 'newly added' collection are the same, which is fine - * since we already relinked old root override collection to new resync'ed one above. So this - * call is not expected to instantiate this new resync'ed collection anywhere, just to ensure - * that we do not have any stray objects. */ - lib_override_library_create_post_process(bmain, - scene, - view_layer, - id_root_reference, - id_root, - override_resync_residual_storage, - true); + if (do_post_process) { + /* Essentially ensures that potentially new overrides of new objects will be instantiated. */ + /* Note: Here 'reference' collection and 'newly added' collection are the same, which is fine + * since we already relinked old root override collection to new resync'ed one above. So this + * call is not expected to instantiate this new resync'ed collection anywhere, just to ensure + * that we do not have any stray objects. */ + lib_override_library_create_post_process(bmain, + scene, + view_layer, + id_root_reference, + id_root, + override_resync_residual_storage, + true); + } /* Cleanup. */ BLI_ghash_free(linkedref_to_old_override, NULL, NULL); @@ -1252,9 +1218,10 @@ void BKE_lib_override_library_main_resync(Main *bmain, Scene *scene, ViewLayer * continue; } do_continue = true; + CLOG_INFO(&LOG, 2, "Resyncing %s...", id->name); const bool success = BKE_lib_override_library_resync( - bmain, scene, view_layer, id, override_resync_residual_storage, false); + bmain, scene, view_layer, id, override_resync_residual_storage, false, false); CLOG_INFO(&LOG, 2, "\tSuccess: %d", success); break; } @@ -1266,6 +1233,10 @@ void BKE_lib_override_library_main_resync(Main *bmain, Scene *scene, ViewLayer * FOREACH_MAIN_LISTBASE_END; } + /* Essentially ensures that potentially new overrides of new objects will be instantiated. */ + lib_override_library_create_post_process( + bmain, scene, view_layer, NULL, NULL, override_resync_residual_storage, true); + if (BKE_collection_is_empty(override_resync_residual_storage)) { BKE_collection_delete(bmain, override_resync_residual_storage, true); } diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 66eb6ab15dc..4159074df9c 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -925,7 +925,7 @@ static void id_override_library_resync_fn(bContext *C, } BKE_lib_override_library_resync( - bmain, scene, CTX_data_view_layer(C), id_root, NULL, do_hierarchy_enforce); + bmain, scene, CTX_data_view_layer(C), id_root, NULL, do_hierarchy_enforce, true); WM_event_add_notifier(C, NC_WINDOW, NULL); } |