[Bf-blender-cvs] [d9fe565c852] master: LibOverride: Fix potential broken cases re ShapeKeys when finding hierarchy root ID.

Bastien Montagne noreply at git.blender.org
Fri Feb 18 16:10:49 CET 2022


Commit: d9fe565c852135edbe51ec632df593db2579cc9b
Author: Bastien Montagne
Date:   Fri Feb 18 16:06:15 2022 +0100
Branches: master
https://developer.blender.org/rBd9fe565c852135edbe51ec632df593db2579cc9b

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.

===================================================================

M	source/blender/blenkernel/intern/lib_override.c

===================================================================

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)) {



More information about the Bf-blender-cvs mailing list