diff options
author | Bastien Montagne <bastien@blender.org> | 2022-08-24 18:07:43 +0300 |
---|---|---|
committer | Bastien Montagne <bastien@blender.org> | 2022-08-24 18:11:36 +0300 |
commit | 8b7293eb4168908945d562fdd1c3f8cd4d4944e5 (patch) | |
tree | c3ace31427895a2602a51a1c928cffa64e5e5c45 /source/blender/editors/interface | |
parent | 24dc84f15668129c7a7fe0a284f6b2376a473e15 (diff) |
LibOverride: Fix (unreported) crashes in some cases, preserve active object on Clear, general cleanup.
Inconsistencies in update/tagging code between different code doing the
same 'Clear. liboverride operation lead to crashes in some cases.
Unify deg tagging and WM notifiers accross the three editor-level
codepaths performing the common Make/Reset/Clear operations.
Preserve if possible the active object accross Clear operation.
Several cleanup/rename/re-arangement of code to make it more consistent.
Diffstat (limited to 'source/blender/editors/interface')
-rw-r--r-- | source/blender/editors/interface/interface_ops.c | 63 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_templates.c | 14 |
2 files changed, 54 insertions, 23 deletions
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index e170cb46925..3a5ba9acaac 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -820,19 +820,26 @@ static int override_idtemplate_make_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - if (ID_IS_OVERRIDE_LIBRARY_REAL(owner_id)) { - PointerRNA idptr; - /* `idptr` is re-assigned to owner property to ensure proper updates etc. Here we also use it - * to ensure remapping of the owner property from the linked data to the newly created - * liboverride (note that in theory this remapping has already been done by code above), but - * only in case owner ID was already an existing liboverride. - * - * Otherwise, owner ID will also have been overridden, and remapped already to use it's - * override of the data too. */ + PointerRNA idptr; + /* `idptr` is re-assigned to owner property to ensure proper updates etc. Here we also use it + * to ensure remapping of the owner property from the linked data to the newly created + * liboverride (note that in theory this remapping has already been done by code above), but + * only in case owner ID was already local ID (override or pure local data). + * + * Otherwise, owner ID will also have been overridden, and remapped already to use it's + * override of the data too. */ + if (!ID_IS_LINKED(owner_id)) { RNA_id_pointer_create(id_override, &idptr); RNA_property_pointer_set(&owner_ptr, prop, idptr, NULL); - RNA_property_update(C, &owner_ptr, prop); } + RNA_property_update(C, &owner_ptr, prop); + + /* 'Security' extra tagging, since this process may also affect the owner ID and not only the + * used ID, relying on the property update code only is not always enough. */ + DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_WINDOW, NULL); + WM_event_add_notifier(C, NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); return OPERATOR_FINISHED; } @@ -881,6 +888,9 @@ static int override_idtemplate_reset_exec(bContext *C, wmOperator *UNUSED(op)) RNA_property_pointer_set(&owner_ptr, prop, idptr, NULL); RNA_property_update(C, &owner_ptr, prop); + /* No need for 'security' extra tagging here, since this process will never affect the owner ID. + */ + return OPERATOR_FINISHED; } @@ -919,24 +929,45 @@ static int override_idtemplate_clear_exec(bContext *C, wmOperator *UNUSED(op)) } Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Scene *scene = CTX_data_scene(C); ID *id_new = id; + if (BKE_lib_override_library_is_hierarchy_leaf(bmain, id)) { id_new = id->override_library->reference; + bool do_remap_active = false; + if (OBACT(view_layer) == (Object *)id) { + BLI_assert(GS(id->name) == ID_OB); + BLI_assert(GS(id_new->name) == ID_OB); + do_remap_active = true; + } BKE_libblock_remap(bmain, id, id_new, ID_REMAP_SKIP_INDIRECT_USAGE); + if (do_remap_active) { + Object *ref_object = (Object *)id_new; + Base *basact = BKE_view_layer_base_find(view_layer, ref_object); + if (basact != NULL) { + view_layer->basact = basact; + } + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + } BKE_id_delete(bmain, id); } else { BKE_lib_override_library_id_reset(bmain, id, true); } - PointerRNA idptr; - /* `idptr` is re-assigned to owner property to ensure proper updates etc. Here we also use it to - * ensure remapping of the owner property from the linked data to the newly created liboverride - * (note that in theory this remapping has already been done by code above). */ - RNA_id_pointer_create(id_new, &idptr); - RNA_property_pointer_set(&owner_ptr, prop, idptr, NULL); + /* Here the affected ID may remain the same, or be replaced by its linked reference. In either + * case, the owner ID remains unchanged, and remapping is already handled by internal code, so + * calling `RNA_property_update` on it is enough to ensure proper notifiers are sent. */ RNA_property_update(C, &owner_ptr, prop); + /* 'Security' extra tagging, since this process may also affect the owner ID and not only the + * used ID, relying on the property update code only is not always enough. */ + DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_WINDOW, NULL); + WM_event_add_notifier(C, NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 95952b6e8c8..7d27af7220e 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -885,14 +885,14 @@ static void template_id_liboverride_hierarchy_make(bContext *C, C, bmain, owner_id, id, r_undo_push_label); if (id_override != NULL) { - /* Given `idptr` is re-assigned to owner property by caller to ensure proper updates etc. Here - * we also use it to ensure remapping of the owner property from the linked data to the newly - * created liboverride (note that in theory this remapping has already been done by code - * above), but only in case owner ID was already an existing liboverride. + /* `idptr` is re-assigned to owner property to ensure proper updates etc. Here we also use it + * to ensure remapping of the owner property from the linked data to the newly created + * liboverride (note that in theory this remapping has already been done by code above), but + * only in case owner ID was already local ID (override or pure local data). * - * Otherwise, owner ID will also have been overridden, and remapped already to use - * it's override of the data too. */ - if (ID_IS_OVERRIDE_LIBRARY_REAL(owner_id)) { + * Otherwise, owner ID will also have been overridden, and remapped already to use it's + * override of the data too. */ + if (!ID_IS_LINKED(owner_id)) { RNA_id_pointer_create(id_override, idptr); } } |