From 12b36168957dd27c253251555c29e8523b94fbe8 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 12 Aug 2022 10:39:03 +0200 Subject: IDType `get_owner`: add an optional hint about owner ID. In some cases, there is a chance code already knows who might be the owner of the given ID, in which case it can be more efficient to check it first (especially in cases like embedded node trees or scene collections, where the only other way is to loop over all possible owners currently). Will be used in next commit in some Outliner fix. --- source/blender/editors/space_outliner/outliner_collections.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/editors/space_outliner') diff --git a/source/blender/editors/space_outliner/outliner_collections.cc b/source/blender/editors/space_outliner/outliner_collections.cc index 8ca2ffe6a9c..b29d20f9f9c 100644 --- a/source/blender/editors/space_outliner/outliner_collections.cc +++ b/source/blender/editors/space_outliner/outliner_collections.cc @@ -364,7 +364,7 @@ void outliner_collection_delete( const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(&parent->id); BLI_assert(id_type->owner_get != nullptr); - ID *scene_owner = id_type->owner_get(bmain, &parent->id); + ID *scene_owner = id_type->owner_get(bmain, &parent->id, NULL); BLI_assert(GS(scene_owner->name) == ID_SCE); if (ID_IS_LINKED(scene_owner) || ID_IS_OVERRIDE_LIBRARY(scene_owner)) { skip = true; @@ -597,7 +597,7 @@ static int collection_duplicate_exec(bContext *C, wmOperator *op) const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(&parent->id); BLI_assert(id_type->owner_get != nullptr); - Scene *scene_owner = (Scene *)id_type->owner_get(bmain, &parent->id); + Scene *scene_owner = (Scene *)id_type->owner_get(bmain, &parent->id, NULL); BLI_assert(scene_owner != nullptr); BLI_assert(GS(scene_owner->id.name) == ID_SCE); -- cgit v1.2.3 From 7f44dc79a60eddf2f81a513ca4581fc2658dc9e8 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 12 Aug 2022 10:43:13 +0200 Subject: Fix (unreported) crashes in Outliner override hierarchy view. Fix wrong assumption that 'embedded' IDs are only ever used by their owners. This is especially not true with shape keys. Also small optimization by adding an eraly abort when both IDs are the same (i.e. an ID has a pointer to itself). --- .../tree_display_override_library_hierarchies.cc | 42 +++++++++++----------- 1 file changed, 22 insertions(+), 20 deletions(-) (limited to 'source/blender/editors/space_outliner') diff --git a/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc b/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc index f8705c3f0ad..e0a1958795a 100644 --- a/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc +++ b/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc @@ -15,6 +15,7 @@ #include "BLT_translation.h" +#include "BKE_lib_override.h" #include "BKE_lib_query.h" #include "BKE_main.h" @@ -80,6 +81,7 @@ ListBase TreeDisplayOverrideLibraryHierarchies::buildTree(const TreeSourceData & class OverrideIDHierarchyBuilder { SpaceOutliner &space_outliner_; + Main &bmain_; MainIDRelations &id_relations_; struct HierarchyBuildData { @@ -93,8 +95,10 @@ class OverrideIDHierarchyBuilder { }; public: - OverrideIDHierarchyBuilder(SpaceOutliner &space_outliner, MainIDRelations &id_relations) - : space_outliner_(space_outliner), id_relations_(id_relations) + OverrideIDHierarchyBuilder(SpaceOutliner &space_outliner, + Main &bmain, + MainIDRelations &id_relations) + : space_outliner_(space_outliner), bmain_(bmain), id_relations_(id_relations) { } @@ -115,7 +119,7 @@ ListBase TreeDisplayOverrideLibraryHierarchies::build_hierarchy_for_lib_or_main( * returning. */ BKE_main_relations_create(bmain, 0); - OverrideIDHierarchyBuilder builder(space_outliner_, *bmain->relations); + OverrideIDHierarchyBuilder builder(space_outliner_, *bmain, *bmain->relations); /* Keep track over which ID base elements were already added, and expand them once added. */ Map id_base_te_map; @@ -165,7 +169,8 @@ void OverrideIDHierarchyBuilder::build_hierarchy_for_ID(ID &override_root_id, static void foreach_natural_hierarchy_child(const MainIDRelations &id_relations, const ID &parent_id, FunctionRef fn); -static bool id_is_in_override_hierarchy(const ID &id, +static bool id_is_in_override_hierarchy(const Main &bmain, + const ID &id, const ID &relationship_parent_id, const ID &override_root_id); @@ -177,7 +182,11 @@ void OverrideIDHierarchyBuilder::build_hierarchy_for_ID_recursive(const ID &pare build_data.parent_ids.add(&parent_id); foreach_natural_hierarchy_child(id_relations_, parent_id, [&](ID &id) { - if (!id_is_in_override_hierarchy(id, parent_id, build_data.override_root_id_)) { + /* Some IDs can use themselves, early abort. */ + if (&id == &parent_id) { + return; + } + if (!id_is_in_override_hierarchy(bmain_, id, parent_id, build_data.override_root_id_)) { return; } @@ -276,7 +285,8 @@ static void foreach_natural_hierarchy_child(const MainIDRelations &id_relations, } } -static bool id_is_in_override_hierarchy(const ID &id, +static bool id_is_in_override_hierarchy(const Main &bmain, + const ID &id, const ID &relationship_parent_id, const ID &override_root_id) { @@ -286,20 +296,12 @@ static bool id_is_in_override_hierarchy(const ID &id, const ID *real_override_id = &id; if (ID_IS_OVERRIDE_LIBRARY_VIRTUAL(&id)) { - /* This assumes that the parent ID is always the owner of the 'embedded' one, I.e. that no - * other ID directly uses the embedded one. Should be true, but the debug code adds some checks - * to validate this assumption. */ - real_override_id = &relationship_parent_id; - -#ifndef NDEBUG - if (GS(id.name) == ID_KE) { - const Key *key = (Key *)&id; - BLI_assert(real_override_id == key->from); - } - else { - BLI_assert((id.flag & LIB_EMBEDDED_DATA) != 0); - } -#endif + /* In many cases, `relationship_parent_id` is the owner, but not always (e.g. there can be + * drivers directly between an object and a shapekey). */ + BKE_lib_override_library_get(const_cast
(&bmain), + const_cast(&id), + const_cast(&relationship_parent_id), + const_cast(&real_override_id)); } if (!ID_IS_OVERRIDE_LIBRARY(real_override_id)) { -- cgit v1.2.3