diff options
-rw-r--r-- | source/blender/blenkernel/BKE_lib_override.h | 13 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/lib_override.cc | 28 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_templates.c | 40 |
3 files changed, 62 insertions, 19 deletions
diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h index b2162e651fd..9ad5a32e6f0 100644 --- a/source/blender/blenkernel/BKE_lib_override.h +++ b/source/blender/blenkernel/BKE_lib_override.h @@ -60,6 +60,19 @@ void BKE_lib_override_library_clear(struct IDOverrideLibrary *override, bool do_ void BKE_lib_override_library_free(struct IDOverrideLibrary **override, bool do_id_user); /** + * Return the actual #IDOverrideLibrary data 'controlling' the given `id`, and the acutal ID owning + * it. + * + * \note This is especially useful when `id` is a non-real override (e.g. embedded ID like a master + * collection or root node tree, or a shape key). + * + * \param r_owner_id If given, will be set with the actual ID owning the return liboverride data. + */ +IDOverrideLibrary *BKE_lib_override_library_get(struct Main *bmain, + struct ID *id, + struct ID **r_owner_id); + +/** * Check if given ID has some override rules that actually indicate the user edited it. */ bool BKE_lib_override_library_is_user_edited(const struct ID *id); diff --git a/source/blender/blenkernel/intern/lib_override.cc b/source/blender/blenkernel/intern/lib_override.cc index 6afbb9064a8..5618d0f6aac 100644 --- a/source/blender/blenkernel/intern/lib_override.cc +++ b/source/blender/blenkernel/intern/lib_override.cc @@ -92,9 +92,9 @@ BLI_INLINE void lib_override_object_posemode_transfer(ID *id_dst, ID *id_src) } /** Get override data for a given ID. Needed because of our beloved shape keys snowflake. */ -BLI_INLINE const IDOverrideLibrary *lib_override_get(const Main *bmain, - const ID *id, - const ID **r_owner_id) +BLI_INLINE const IDOverrideLibrary *BKE_lib_override_library_get(const Main *bmain, + const ID *id, + const ID **r_owner_id) { if (r_owner_id != nullptr) { *r_owner_id = id; @@ -115,13 +115,14 @@ BLI_INLINE const IDOverrideLibrary *lib_override_get(const Main *bmain, return id->override_library; } -BLI_INLINE IDOverrideLibrary *lib_override_get(Main *bmain, ID *id, ID **r_owner_id) +IDOverrideLibrary *BKE_lib_override_library_get(Main *bmain, ID *id, ID **r_owner_id) { /* Reuse the implementation of the const access function, which does not change the arguments. * Add const explicitly to make it clear to the compiler to avoid just calling this function. */ - return const_cast<IDOverrideLibrary *>(lib_override_get(const_cast<const Main *>(bmain), - const_cast<const ID *>(id), - const_cast<const ID **>(r_owner_id))); + return const_cast<IDOverrideLibrary *>( + BKE_lib_override_library_get(const_cast<const Main *>(bmain), + const_cast<const ID *>(id), + const_cast<const ID **>(r_owner_id))); } IDOverrideLibrary *BKE_lib_override_library_init(ID *local_id, ID *reference_id) @@ -318,7 +319,7 @@ bool BKE_lib_override_library_is_system_defined(const Main *bmain, const ID *id) { if (ID_IS_OVERRIDE_LIBRARY(id)) { const ID *override_owner_id; - lib_override_get(bmain, id, &override_owner_id); + BKE_lib_override_library_get(bmain, id, &override_owner_id); return (override_owner_id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) != 0; } @@ -1085,8 +1086,9 @@ static void lib_override_overrides_group_tag_recursive(LibOverrideGroupTagData * continue; } - const Library *reference_lib = lib_override_get(bmain, id_owner, nullptr)->reference->lib; - const ID *to_id_reference = lib_override_get(bmain, to_id, nullptr)->reference; + const Library *reference_lib = + BKE_lib_override_library_get(bmain, id_owner, nullptr)->reference->lib; + const ID *to_id_reference = BKE_lib_override_library_get(bmain, to_id, nullptr)->reference; if (to_id_reference->lib != reference_lib) { /* We do not override data-blocks from other libraries, nor do we process them. */ continue; @@ -1434,7 +1436,7 @@ static ID *lib_override_root_find(Main *bmain, ID *id, const int curr_level, int BLI_assert(id->flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE); ID *id_owner; int best_level_placeholder = 0; - lib_override_get(bmain, id, &id_owner); + BKE_lib_override_library_get(bmain, id, &id_owner); return lib_override_root_find(bmain, id_owner, curr_level + 1, &best_level_placeholder); } /* This way we won't process again that ID, should we encounter it again through another @@ -1473,7 +1475,7 @@ static ID *lib_override_root_find(Main *bmain, ID *id, const int curr_level, int BLI_assert(id->flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE); ID *id_owner; int best_level_placeholder = 0; - lib_override_get(bmain, best_root_id_candidate, &id_owner); + BKE_lib_override_library_get(bmain, best_root_id_candidate, &id_owner); best_root_id_candidate = lib_override_root_find( bmain, id_owner, curr_level + 1, &best_level_placeholder); } @@ -1790,7 +1792,7 @@ static bool lib_override_library_resync(Main *bmain, /* While this should not happen in typical cases (and won't be properly supported here), * user is free to do all kind of very bad things, including having different local * overrides of a same linked ID in a same hierarchy. */ - IDOverrideLibrary *id_override_library = lib_override_get(bmain, id, nullptr); + IDOverrideLibrary *id_override_library = BKE_lib_override_library_get(bmain, id, nullptr); if (id_override_library->hierarchy_root != id_root->override_library->hierarchy_root) { continue; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index a9de095a2a8..f566299960a 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -659,6 +659,27 @@ static void template_id_liboverride_hierarchy_create(bContext *C, ID *id = idptr->data; ID *owner_id = template_ui->ptr.owner_id; + /* If this is called on an already local override, 'toggle' between user-editable state, and + * system override with reset. */ + if (!ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY(id)) { + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + BKE_lib_override_library_get(bmain, id, &id); + } + if (id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) { + id->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED; + *r_undo_push_label = "Make Library Override Hierarchy Editable"; + } + else { + BKE_lib_override_library_id_reset(bmain, id, true); + *r_undo_push_label = "Clear Library Override Hierarchy"; + } + + WM_event_add_notifier(C, NC_WM | ND_DATACHANGED, 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; + } + /* Attempt to perform a hierarchy override, based on contextual data available. * NOTE: do not attempt to perform such hierarchy override at all cost, if there is not enough * context, better to abort than create random overrides all over the place. */ @@ -918,12 +939,19 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) break; case UI_ID_OVERRIDE: if (id && ID_IS_OVERRIDE_LIBRARY(id)) { - BKE_lib_override_library_make_local(id); - /* Reassign to get proper updates/notifiers. */ - idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); - RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); - RNA_property_update(C, &template_ui->ptr, template_ui->prop); - undo_push_label = "Make Local"; + Main *bmain = CTX_data_main(C); + if (CTX_wm_window(C)->eventstate->modifier & KM_SHIFT) { + template_id_liboverride_hierarchy_create( + C, bmain, template_ui, &idptr, &undo_push_label); + } + else { + BKE_lib_override_library_make_local(id); + /* Reassign to get proper updates/notifiers. */ + idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); + RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); + RNA_property_update(C, &template_ui->ptr, template_ui->prop); + undo_push_label = "Make Local"; + } } break; case UI_ID_ALONE: |