From a149c4aaeee2d4ad5a2b094b0a3860585d8af88b Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 18 Aug 2022 15:01:41 +0200 Subject: [PATCH 1/2] LibOverride: Fix more crashes when creating overrides from IDTemplates. Assigning to RNA ID pointer properties will not _always_ trigger a rebuild of the outliner tree, so try to enforce this when actually creating overrides. --- .../blender/editors/interface/interface_templates.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index bec4506ca41..94a7296d558 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -796,7 +796,6 @@ ID *ui_template_id_liboverride_hierarchy_create( BKE_lib_override_library_create( bmain, scene, view_layer, NULL, id, NULL, NULL, &id_override, false); BKE_scene_collections_object_remove(bmain, scene, (Object *)id, true); - WM_event_add_notifier(C, NC_ID | NA_REMOVED, NULL); } break; case ID_ME: @@ -854,6 +853,18 @@ ID *ui_template_id_liboverride_hierarchy_create( if (id_override != NULL) { id_override->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED; *r_undo_push_label = "Make Library Override Hierarchy"; + + /* In theory we could rely on setting/updating the RNA ID pointer property (as done by calling + * code) to be enough. + * + * However, some rare ID pointers properties (like the 'active object in viewlayer' one used + * for the Object templateID in the Object properties) use notifiers that do not enforce a + * rebuild of outliner trees, leading to crashes. + * + * So for now, add some extra notifiers here. */ + WM_event_add_notifier(C, NC_ID | NA_REMOVED, NULL); + WM_event_add_notifier(C, NC_ID | NA_ADDED, NULL); + WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL); } return id_override; } From 582704a75837e33c4cec4f55cb9dfd23be1ae4e9 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 18 Aug 2022 15:49:29 +0200 Subject: [PATCH 2/2] LibOverride: Preserve active object when creating overrides. --- .../blender/blenkernel/intern/lib_override.cc | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/lib_override.cc b/source/blender/blenkernel/intern/lib_override.cc index 58846aab4df..03ad4b1cd5f 100644 --- a/source/blender/blenkernel/intern/lib_override.cc +++ b/source/blender/blenkernel/intern/lib_override.cc @@ -1212,6 +1212,7 @@ static void lib_override_library_create_post_process(Main *bmain, ID *id_root, ID *id_instance_hint, Collection *residual_storage, + const Object *old_active_object, const bool is_resync) { /* NOTE: We only care about local IDs here, if a linked object is not instantiated in any way we @@ -1284,6 +1285,14 @@ static void lib_override_library_create_post_process(Main *bmain, BLI_assert(ob_new->id.override_library != nullptr && ob_new->id.override_library->reference == &ob->id); + if (old_active_object == ob) { + Base *basact = BKE_view_layer_base_find(view_layer, ob_new); + if (basact != nullptr) { + view_layer->basact = basact; + } + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + } + if (BLI_gset_lookup(all_objects_in_scene, ob_new) == nullptr) { if (id_root != nullptr && default_instantiating_collection == nullptr) { ID *id_ref = id_root->newid != nullptr ? id_root->newid : id_root; @@ -1374,6 +1383,8 @@ bool BKE_lib_override_library_create(Main *bmain, id_hierarchy_root_reference = id_root_reference; } + const Object *old_active_object = OBACT(view_layer); + const bool success = lib_override_library_create_do(bmain, scene, owner_library, @@ -1396,6 +1407,7 @@ bool BKE_lib_override_library_create(Main *bmain, id_root_reference, id_instance_hint, nullptr, + old_active_object, false); /* Cleanup. */ @@ -1709,6 +1721,7 @@ static bool lib_override_library_resync(Main *bmain, ID *id_root_reference = id_root->override_library->reference; ID *id; + const Object *old_active_object = OBACT(view_layer); if (id_root_reference->tag & LIB_TAG_MISSING) { BKE_reportf(reports != nullptr ? reports->reports : nullptr, @@ -2133,6 +2146,7 @@ static bool lib_override_library_resync(Main *bmain, id_root_reference, id_root, override_resync_residual_storage, + old_active_object, true); } @@ -2653,6 +2667,8 @@ void BKE_lib_override_library_main_resync(Main *bmain, override_resync_residual_storage->flag |= COLLECTION_HIDE_VIEWPORT | COLLECTION_HIDE_RENDER; } + const Object *old_active_object = OBACT(view_layer); + /* Necessary to improve performances, and prevent layers matching override sub-collections to be * lost when re-syncing the parent override collection. * Ref. T73411. */ @@ -2673,8 +2689,15 @@ void BKE_lib_override_library_main_resync(Main *bmain, BKE_layer_collection_resync_allow(); /* Essentially ensures that potentially new overrides of new objects will be instantiated. */ - lib_override_library_create_post_process( - bmain, scene, view_layer, nullptr, nullptr, nullptr, override_resync_residual_storage, true); + lib_override_library_create_post_process(bmain, + scene, + view_layer, + nullptr, + nullptr, + nullptr, + override_resync_residual_storage, + old_active_object, + true); if (BKE_collection_is_empty(override_resync_residual_storage)) { BKE_collection_delete(bmain, override_resync_residual_storage, true);