Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorBastien Montagne <bastien@blender.org>2022-02-18 18:06:15 +0300
committerBastien Montagne <bastien@blender.org>2022-02-18 18:06:15 +0300
commitd9fe565c852135edbe51ec632df593db2579cc9b (patch)
tree53e57c35eb42d4abf9d5ffbca40106ab58415fb1 /source
parent303b566b10f9008f6608a3cce08dbac3c64b6b4a (diff)
LibOverride: Fix potential broken cases re ShapeKeys when finding hierarchy root ID.
In some cases broken files could lead to selecting a shapekey as hierarchy root ID, which is not allowed. Found while investigating Blender studio issues in Snow parkour short.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/intern/lib_override.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 8a988bd30b5..08ff1eb80de 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -72,12 +72,19 @@ static void lib_override_library_property_operation_clear(
IDOverrideLibraryPropertyOperation *opop);
/** Get override data for a given ID. Needed because of our beloved shape keys snowflake. */
-BLI_INLINE IDOverrideLibrary *lib_override_get(Main *bmain, ID *id)
+BLI_INLINE IDOverrideLibrary *lib_override_get(Main *bmain, ID *id, ID **r_owner_id)
{
+ if (r_owner_id != NULL) {
+ *r_owner_id = id;
+ }
if (id->flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE) {
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
if (id_type->owner_get != NULL) {
- return id_type->owner_get(bmain, id)->override_library;
+ ID *owner_id = id_type->owner_get(bmain, id);
+ if (r_owner_id != NULL) {
+ *r_owner_id = owner_id;
+ }
+ return owner_id->override_library;
}
BLI_assert_msg(0, "IDTypeInfo of liboverride-embedded ID with no owner getter");
}
@@ -832,8 +839,8 @@ static void lib_override_overrides_group_tag_recursive(LibOverrideGroupTagData *
continue;
}
- Library *reference_lib = lib_override_get(bmain, id_owner)->reference->lib;
- ID *to_id_reference = lib_override_get(bmain, to_id)->reference;
+ Library *reference_lib = lib_override_get(bmain, id_owner, NULL)->reference->lib;
+ ID *to_id_reference = lib_override_get(bmain, to_id, NULL)->reference;
if (to_id_reference->lib != reference_lib) {
/* We do not override data-blocks from other libraries, nor do we process them. */
continue;
@@ -1102,11 +1109,18 @@ static ID *lib_override_root_find(Main *bmain, ID *id, const int curr_level, int
MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id);
BLI_assert(entry != NULL);
- if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED && ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
- /* This ID has already been processed. */
- BLI_assert(id->override_library != NULL);
- *r_best_level = curr_level;
- return id->override_library->hierarchy_root;
+ if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) {
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ /* This ID has already been processed. */
+ *r_best_level = curr_level;
+ return id->override_library->hierarchy_root;
+ }
+
+ BLI_assert(id->flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE);
+ ID *id_owner;
+ int best_level_placeholder = 0;
+ lib_override_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
* relationship hierarchy. */
@@ -1140,7 +1154,17 @@ static ID *lib_override_root_find(Main *bmain, ID *id, const int curr_level, int
}
}
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(best_root_id_candidate)) {
+ 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);
+ best_root_id_candidate = lib_override_root_find(
+ bmain, id_owner, curr_level + 1, &best_level_placeholder);
+ }
+
BLI_assert(best_root_id_candidate != NULL);
+ BLI_assert((best_root_id_candidate->flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE) == 0);
*r_best_level = best_level_candidate;
return best_root_id_candidate;
@@ -1430,7 +1454,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);
+ IDOverrideLibrary *id_override_library = lib_override_get(bmain, id, NULL);
ID *reference_id = id_override_library->reference;
if (GS(reference_id->name) != GS(id->name)) {
switch (GS(id->name)) {