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

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to