[Bf-blender-cvs] [f68288a8746] override-recursive-resync: LibOverride: refactor recursive resync.

Bastien Montagne noreply at git.blender.org
Thu May 27 18:31:03 CEST 2021


Commit: f68288a8746fb03b41a6dc08741eb0447c918c12
Author: Bastien Montagne
Date:   Thu May 27 15:54:26 2021 +0200
Branches: override-recursive-resync
https://developer.blender.org/rBf68288a8746fb03b41a6dc08741eb0447c918c12

LibOverride: refactor recursive resync.

We need to re-evaluate what needs to be resynced after each step of
processing overrides from a given 'indirect level' of libraries.
Otherwise, recusrive overrides (overrides of linked overrides) won't
work.

Note that this should not change too much in practice currently, since
there are other issues with recursive overrides yet.

Also, checks (CLOG errors) added show that some ID (node trees) seem to
be detected as needing resynced even after beig just resynced, this
needs further investigation still. Could be though that it is due to
limit currently set on nodetrees, those are always complicated
snowflakes to deal with...

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

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 0066aab03c2..aeef6c04944 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -1277,100 +1277,19 @@ bool BKE_lib_override_library_resync(Main *bmain,
   return success;
 }
 
-static int lib_override_sort_libraries_func(LibraryIDLinkCallbackData *cb_data)
-{
-  if (cb_data->cb_flag & IDWALK_CB_LOOPBACK) {
-    return IDWALK_RET_NOP;
-  }
-  ID *id_owner = cb_data->id_owner;
-  ID *id = *cb_data->id_pointer;
-  if (id != NULL && ID_IS_LINKED(id) && id->lib != id_owner->lib) {
-    const int owner_library_indirect_level = id_owner->lib != NULL ? id_owner->lib->temp_index : 0;
-    if (owner_library_indirect_level > 10000) {
-      CLOG_ERROR(
-          &LOG,
-          "Levels of indirect usages of libraries is way too high, skipping further building "
-          "loops (Involves at least '%s' and '%s')",
-          id_owner->lib->filepath,
-          id->lib->filepath);
-      BLI_assert(0);
-      return IDWALK_RET_NOP;
-    }
-
-    if (owner_library_indirect_level >= id->lib->temp_index) {
-      id->lib->temp_index = owner_library_indirect_level + 1;
-      *(bool *)cb_data->user_data = true;
-    }
-  }
-  return IDWALK_RET_NOP;
-}
-
-/** Define the `temp_index` of libraries from their highest level of indirect usage.
+/* Ensure resync of all overrides at one level of indirect usage.
  *
- * E.g. if lib_a uses lib_b, lib_c and lib_d, and lib_b also uses lib_d, then lib_a has an index of
- * 1, lib_b and lib_c an index of 2, and lib_d an index of 3. */
-static int lib_override_libraries_index_define(Main *bmain)
-{
-  LISTBASE_FOREACH (Library *, library, &bmain->libraries) {
-    /* index 0 is reserved for local data. */
-    library->temp_index = 1;
-  }
-  bool do_continue = true;
-  while (do_continue) {
-    do_continue = false;
-    ID *id;
-    FOREACH_MAIN_ID_BEGIN (bmain, id) {
-      BKE_library_foreach_ID_link(
-          bmain, id, lib_override_sort_libraries_func, &do_continue, IDWALK_READONLY);
-    }
-    FOREACH_MAIN_ID_END;
-  }
-
-  int library_indirect_level_max = 0;
-  LISTBASE_FOREACH (Library *, library, &bmain->libraries) {
-    if (library->temp_index > library_indirect_level_max) {
-      library_indirect_level_max = library->temp_index;
-    }
-  }
-  return library_indirect_level_max;
-}
-
-/**
- * Detect and handle required resync of overrides data, when relations between reference linked IDs
- * have changed.
- *
- * This is a fairly complex and costly operation, typically it should be called after
- * #BKE_lib_override_library_main_update, which would already detect and tag a lot of cases.
- *
- * This function will first detect the remaining cases requiring a resync (namely, either when an
- * existing linked ID that did not require to be overridden before now would be, or when new IDs
- * are added to the hierarchy).
- *
- * Then it will handle the resync of necessary IDs (through calls to
- * #BKE_lib_override_library_resync).
+ * We need to handle each level independently, since an override at level n may be affected by
+ * other overrides from level n + 1 etc. (i.e. from linked overrides it may use).
  */
-void BKE_lib_override_library_main_resync(Main *bmain,
-                                          Scene *scene,
-                                          ViewLayer *view_layer,
-                                          ReportList *reports)
+static void lib_override_library_main_resync_on_library_indirect_level(
+    Main *bmain,
+    Scene *scene,
+    ViewLayer *view_layer,
+    Collection *override_resync_residual_storage,
+    const int library_indirect_level,
+    ReportList *reports)
 {
-  /* We use a specific collection to gather/store all 'orphaned' override collections and objects
-   * generated by re-sync-process. This avoids putting them in scene's master collection. */
-#define OVERRIDE_RESYNC_RESIDUAL_STORAGE_NAME "OVERRIDE_RESYNC_LEFTOVERS"
-  Collection *override_resync_residual_storage = BLI_findstring(
-      &bmain->collections, OVERRIDE_RESYNC_RESIDUAL_STORAGE_NAME, offsetof(ID, name) + 2);
-  if (override_resync_residual_storage != NULL &&
-      override_resync_residual_storage->id.lib != NULL) {
-    override_resync_residual_storage = NULL;
-  }
-  if (override_resync_residual_storage == NULL) {
-    override_resync_residual_storage = BKE_collection_add(
-        bmain, scene->master_collection, OVERRIDE_RESYNC_RESIDUAL_STORAGE_NAME);
-    /* Hide the collection from viewport and render. */
-    override_resync_residual_storage->flag |= COLLECTION_RESTRICT_VIEWPORT |
-                                              COLLECTION_RESTRICT_RENDER;
-  }
-
   BKE_main_relations_create(bmain, 0);
   BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
 
@@ -1410,6 +1329,16 @@ void BKE_lib_override_library_main_resync(Main *bmain,
 
     if (id->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) {
       CLOG_INFO(&LOG, 4, "ID %s (%p) was already tagged as needing resync", id->name, id->lib);
+      if (id->lib->temp_index > library_indirect_level) {
+        CLOG_ERROR(
+            &LOG,
+            "While processing indirect level %d, ID %s from lib %s of indirect level %d detected "
+            "as needing resync.",
+            library_indirect_level,
+            id->name,
+            id->lib ? id->lib->filepath : "<LOCAL>",
+            id->lib ? id->lib->temp_index : 0);
+      }
       continue;
     }
 
@@ -1434,6 +1363,16 @@ void BKE_lib_override_library_main_resync(Main *bmain,
                   id->lib,
                   id_to->name,
                   id_to->lib);
+        if (id->lib->temp_index > library_indirect_level) {
+          CLOG_ERROR(&LOG,
+                     "While processing indirect level %d, ID %s from lib %s of indirect level %d "
+                     "detected "
+                     "as needing resync.",
+                     library_indirect_level,
+                     id->name,
+                     id->lib ? id->lib->filepath : "<LOCAL>",
+                     id->lib ? id->lib->temp_index : 0);
+        }
         break;
       }
     }
@@ -1443,15 +1382,13 @@ void BKE_lib_override_library_main_resync(Main *bmain,
   BKE_main_relations_free(bmain);
   BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
 
-  int library_indirect_level = lib_override_libraries_index_define(bmain);
-
   /* And do the actual resync for all IDs detected as needing it.
    * NOTE: Since this changes `bmain` (adding **and** removing IDs), we cannot use
    * `FOREACH_MAIN_ID_BEGIN/END` here, and need special multi-loop processing. */
   bool do_continue = true;
   while (do_continue) {
-    ListBase *lb;
     do_continue = false;
+    ListBase *lb;
     FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) {
       FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id) {
         if ((id->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) == 0 ||
@@ -1481,14 +1418,114 @@ void BKE_lib_override_library_main_resync(Main *bmain,
       }
     }
     FOREACH_MAIN_LISTBASE_END;
+  }
+}
+
+static int lib_override_sort_libraries_func(LibraryIDLinkCallbackData *cb_data)
+{
+  if (cb_data->cb_flag & IDWALK_CB_LOOPBACK) {
+    return IDWALK_RET_NOP;
+  }
+  ID *id_owner = cb_data->id_owner;
+  ID *id = *cb_data->id_pointer;
+  if (id != NULL && ID_IS_LINKED(id) && id->lib != id_owner->lib) {
+    const int owner_library_indirect_level = id_owner->lib != NULL ? id_owner->lib->temp_index : 0;
+    if (owner_library_indirect_level > 10000) {
+      CLOG_ERROR(
+          &LOG,
+          "Levels of indirect usages of libraries is way too high, skipping further building "
+          "loops (Involves at least '%s' and '%s')",
+          id_owner->lib->filepath,
+          id->lib->filepath);
+      BLI_assert(0);
+      return IDWALK_RET_NOP;
+    }
+
+    if (owner_library_indirect_level >= id->lib->temp_index) {
+      id->lib->temp_index = owner_library_indirect_level + 1;
+      *(bool *)cb_data->user_data = true;
+    }
+  }
+  return IDWALK_RET_NOP;
+}
+
+/** Define the `temp_index` of libraries from their highest level of indirect usage.
+ *
+ * E.g. if lib_a uses lib_b, lib_c and lib_d, and lib_b also uses lib_d, then lib_a has an index of
+ * 1, lib_b and lib_c an index of 2, and lib_d an index of 3. */
+static int lib_override_libraries_index_define(Main *bmain)
+{
+  LISTBASE_FOREACH (Library *, library, &bmain->libraries) {
+    /* index 0 is reserved for local data. */
+    library->temp_index = 1;
+  }
+  bool do_continue = true;
+  while (do_continue) {
+    do_continue = false;
+    ID *id;
+    FOREACH_MAIN_ID_BEGIN (bmain, id) {
+      BKE_library_foreach_ID_link(
+          bmain, id, lib_override_sort_libraries_func, &do_continue, IDWALK_READONLY);
+    }
+    FOREACH_MAIN_ID_END;
+  }
 
-    if (!do_continue && library_indirect_level != 0) {
-      /* We are done with overrides from that level of indirect linking, we can keep going with
-       * those 'less' indirectly linked now. */
-      library_indirect_level--;
-      do_continue = true;
+  int library_indirect_level_max = 0;
+  LISTBASE_FOREACH (Library *, library, &bmain->libraries) {
+    if (library->temp_index > library_indirect_level_max) {
+      library_indirect_level_max = library->temp_index;
     }
   }
+  return library_indirect_level_max;
+}
+
+/**
+ * Detect and handle required resync of overrides data, when relations between reference linked IDs
+ * have changed.
+ *
+ * This is a fairly complex and costly operation, typically it should be called after
+ * #BKE_lib_override_library_main_update, which would already detect and tag a lot of cases.
+ *
+ * This function will first detect the remaining cases requiring a resync (namely, either when an
+ * existing linked ID that did not require to be overridden before now would be, or when new IDs
+ * are added to the hierarchy).
+ *
+ * Then it will handle the resync of necessary IDs (through calls to
+ * #BKE_lib_override_library_resync).
+ */
+void BKE_lib_override_library_main_resync(Main *bmain,
+                                          Scene *scene,
+                                          ViewLayer *view_layer,
+       

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list