[Bf-blender-cvs] [2a81d948ad0] master: LibOverride: refactor of relationships handling in library overrides.

Bastien Montagne noreply at git.blender.org
Mon Jan 25 14:48:56 CET 2021


Commit: 2a81d948ad00c5099ecdbdf2505c8732c99a1fba
Author: Bastien Montagne
Date:   Thu Dec 24 18:11:46 2020 +0100
Branches: master
https://developer.blender.org/rB2a81d948ad00c5099ecdbdf2505c8732c99a1fba

LibOverride: refactor of relationships handling in library overrides.

First step towards a better handling of relationships between IDs in
override context, especially when a resync is needed.

First, introduce a new flag to override operations,
`IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE`, for ID pointers.
It keeps track of whether an RNA ID pointer has been kept to its
'natural overriden ID' (in override hierarchy context), or has actually
been re-assigned to some other data-block.

Second, refactor how we deal with relationships between IDs in override
hierarchy code, especially in resync case. This will fixe several cases
listed in T83811, especially the case where an ID pointer to an existing
override needs to be updated to a new one due to a matching change in
linked data.

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

M	source/blender/blenkernel/BKE_lib_override.h
M	source/blender/blenkernel/intern/lib_override.c
M	source/blender/makesdna/DNA_ID.h
M	source/blender/makesrna/intern/rna_rna.c

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

diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h
index c9a9c26e222..5fd451dc986 100644
--- a/source/blender/blenkernel/BKE_lib_override.h
+++ b/source/blender/blenkernel/BKE_lib_override.h
@@ -65,15 +65,6 @@ struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain,
                                                    struct ID *reference_id,
                                                    const bool do_tagged_remap);
 bool BKE_lib_override_library_create_from_tag(struct Main *bmain);
-void BKE_lib_override_library_dependencies_tag(struct Main *bmain,
-                                               struct ID *id_root,
-                                               const uint tag,
-                                               const bool do_create_main_relashionships);
-void BKE_lib_override_library_override_group_tag(struct Main *bmain,
-                                                 struct ID *id_root,
-                                                 const uint tag,
-                                                 const uint missing_tag,
-                                                 const bool do_create_main_relashionships);
 bool BKE_lib_override_library_create(struct Main *bmain,
                                      struct Scene *scene,
                                      struct ViewLayer *view_layer,
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 388f50e12cf..b0438500413 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -368,29 +368,50 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain)
   return success;
 }
 
-static bool lib_override_hierarchy_recursive_tag(Main *bmain,
-                                                 ID *id,
-                                                 const uint tag,
-                                                 const uint missing_tag,
-                                                 Library *override_group_lib_reference)
+typedef struct LibOverrideGroupTagData {
+  ID *id_root;
+  uint tag;
+  uint missing_tag;
+} LibOverrideGroupTagData;
+
+static int lib_override_linked_group_tag_cb(LibraryIDLinkCallbackData *cb_data)
 {
-  void **entry_vp = BLI_ghash_lookup_p(bmain->relations->relations_from_pointers, id);
-  if (entry_vp == NULL) {
-    /* This ID is not used by nor using any other ID. */
-    return (id->tag & tag) != 0;
+  if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_LOOPBACK)) {
+    return IDWALK_RET_STOP_RECURSION;
   }
 
-  MainIDRelationsEntry *entry = *entry_vp;
-  if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) {
-    /* This ID has already been processed. */
-    return (id->tag & tag) != 0;
+  LibOverrideGroupTagData *data = cb_data->user_data;
+  const uint tag = data->tag;
+  const uint missing_tag = data->missing_tag;
+
+  ID *id_root = data->id_root;
+  Library *library_root = id_root->lib;
+  ID *id = *cb_data->id_pointer;
+  ID *id_owner = cb_data->id_owner;
+
+  BLI_assert(id_owner == cb_data->id_self);
+
+  if (ELEM(id, NULL, id_owner)) {
+    return IDWALK_RET_NOP;
+  }
+
+  BLI_assert(id_owner->lib == library_root);
+
+  if (*(uint *)&id->tag & (tag | missing_tag)) {
+    /* Already processed and tagged, nothing else to do here. */
+    return IDWALK_RET_STOP_RECURSION;
+  }
+
+  if (id->lib != library_root) {
+    /* We do not override data-blocks from other libraries, nor do we process them. */
+    return IDWALK_RET_STOP_RECURSION;
   }
 
-  /* Note: in case some reference ID is missing from linked data (and therefore its override uses
-   * a placeholder as reference), use `missing_tag` instead of `tag` for this override. */
-  if (override_group_lib_reference != NULL && ID_IS_OVERRIDE_LIBRARY_REAL(id) &&
-      id->override_library->reference->lib == override_group_lib_reference) {
-    if (id->override_library->reference->tag & LIB_TAG_MISSING) {
+  /* We tag all collections and objects for override. And we also tag all other data-blocks which
+   * would use one of those.
+   * Note: missing IDs (aka placeholders) are never overridden. */
+  if (ELEM(GS(id->name), ID_OB, ID_GR)) {
+    if ((id->tag & LIB_TAG_MISSING)) {
       id->tag |= missing_tag;
     }
     else {
@@ -398,6 +419,26 @@ static bool lib_override_hierarchy_recursive_tag(Main *bmain,
     }
   }
 
+  return IDWALK_RET_NOP;
+}
+
+/* Tag all IDs in dependency relationships whithin an override hierarchy/group.
+ *
+ * Note: this is typically called to complete `lib_override_linked_group_tag()`.
+ * Note: BMain's relations mapping won't be valid anymore after that call.
+ */
+static bool lib_override_hierarchy_dependencies_recursive_tag(Main *bmain,
+                                                              ID *id,
+                                                              const uint tag,
+                                                              const uint missing_tag)
+{
+  MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id);
+  BLI_assert(entry != NULL);
+
+  if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) {
+    /* This ID has already been processed. */
+    return (*(uint *)&id->tag & tag) != 0;
+  }
   /* This way we won't process again that ID, should we encounter it again through another
    * relationship hierarchy. */
   entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED;
@@ -410,81 +451,69 @@ static bool lib_override_hierarchy_recursive_tag(Main *bmain,
       continue;
     }
     /* We only consider IDs from the same library. */
-    if (*to_id_entry->id_pointer.to != NULL && (*to_id_entry->id_pointer.to)->lib == id->lib) {
-      const bool needs_tag = lib_override_hierarchy_recursive_tag(
-          bmain, *to_id_entry->id_pointer.to, tag, missing_tag, override_group_lib_reference);
-      if (needs_tag && override_group_lib_reference == NULL) {
+    ID *to_id = *to_id_entry->id_pointer.to;
+    if (to_id != NULL && to_id->lib == id->lib) {
+      if (lib_override_hierarchy_dependencies_recursive_tag(bmain, to_id, tag, missing_tag)) {
         id->tag |= tag;
       }
     }
   }
 
-  return (id->tag & tag) != 0;
+  return (*(uint *)&id->tag & tag) != 0;
 }
 
-/**
- * Tag all IDs in given \a bmain that are being used by given \a id_root ID or its dependencies,
- * recursively.
- * It detects and tag only chains of dependencies marked at both ends by given tag.
+/* This will tag at least all 'boundary' linked IDs for a potential override group.
  *
- * This will include all local IDs, and all IDs from the same library as the \a id_root.
+ * Note that you will then need to call `lib_override_hierarchy_dependencies_recursive_tag` to
+ * complete tagging of all dependencies whitin theoverride group.
  *
- * \param id_root: The root of the hierarchy of dependencies to be tagged.
- * \param do_create_main_relashionships: Whether main relations needs to be created or already
- * exist (in any case, they will be freed by this function).
+ * We currently only consider Collections and Objects (that are not used as bone shapes) as valid
+ * boundary IDs to define an override group.
  */
-void BKE_lib_override_library_dependencies_tag(Main *bmain,
-                                               ID *id_root,
-                                               const uint tag,
-                                               const bool do_create_main_relashionships)
+static void lib_override_linked_group_tag(Main *bmain,
+                                          ID *id,
+                                          const uint tag,
+                                          const uint missing_tag)
 {
-  if (do_create_main_relashionships) {
-    BKE_main_relations_create(bmain, 0);
-  }
-
-  /* We tag all intermediary data-blocks in-between two overridden ones (e.g. if a shape-key
-   * has a driver using an armature object's bone, we need to override the shape-key/obdata,
-   * the objects using them, etc.) */
-  lib_override_hierarchy_recursive_tag(bmain, id_root, tag, 0, NULL);
+  BKE_main_relations_create(bmain, 0);
 
-  BKE_main_relations_free(bmain);
-}
+  if (ELEM(GS(id->name), ID_OB, ID_GR)) {
+    LibOverrideGroupTagData data = {.id_root = id, .tag = tag, .missing_tag = missing_tag};
+    /* Tag all collections and objects. */
+    BKE_library_foreach_ID_link(
+        bmain, id, lib_override_linked_group_tag_cb, &data, IDWALK_READONLY | IDWALK_RECURSE);
 
-/**
- * Tag all IDs in given \a bmain that are part of the same \a id_root liboverride ID group.
- * That is, all other liboverride IDs (in)directly used by \a is_root one, and sharing the same
- * library for their reference IDs.
- *
- * \param id_root: The root of the hierarchy of liboverride dependencies to be tagged.
- * \param do_create_main_relashionships: Whether main relations needs to be created or already
- * exist (in any case, they will be freed by this function).
- */
-void BKE_lib_override_library_override_group_tag(Main *bmain,
-                                                 ID *id_root,
-                                                 const uint tag,
-                                                 const uint missing_tag,
-                                                 const bool do_create_main_relashionships)
-{
-  if (do_create_main_relashionships) {
-    BKE_main_relations_create(bmain, 0);
+    /* Then, we remove (untag) bone shape objects, you shall never want to directly/explicitely
+     * override those. */
+    LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+      if (ob->type == OB_ARMATURE && ob->pose != NULL && (ob->id.tag & tag)) {
+        for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
+          if (pchan->custom != NULL) {
+            pchan->custom->id.tag &= ~(tag | missing_tag);
+          }
+        }
+      }
+    }
   }
 
-  /* We tag all liboverride data-blocks from the same library as reference one,
-   * being used by the root ID. */
-  lib_override_hierarchy_recursive_tag(
-      bmain, id_root, tag, missing_tag, id_root->override_library->reference->lib);
+  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list