[Bf-blender-cvs] [5057b28a2fb] master: LibOverride: move most of 'complete override creation' from ED_object to BKE_lib_override.

Bastien Montagne noreply at git.blender.org
Wed Jul 15 18:17:40 CEST 2020


Commit: 5057b28a2fbc6eebcd65bf9fa2e443ae644ca4ce
Author: Bastien Montagne
Date:   Wed Jul 15 18:09:30 2020 +0200
Branches: master
https://developer.blender.org/rB5057b28a2fbc6eebcd65bf9fa2e443ae644ca4ce

LibOverride: move most of 'complete override creation' from ED_object to BKE_lib_override.

This code is fairly complex and can be used in more places, better not
duplicate that logic and just have it in BKE area.

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

M	source/blender/blenkernel/BKE_lib_override.h
M	source/blender/blenkernel/intern/lib_override.c
M	source/blender/editors/object/object_relations.c

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

diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h
index 8f6603e28ae..ba8f2eb3399 100644
--- a/source/blender/blenkernel/BKE_lib_override.h
+++ b/source/blender/blenkernel/BKE_lib_override.h
@@ -50,6 +50,8 @@ struct IDOverrideLibraryPropertyOperation;
 struct Main;
 struct PointerRNA;
 struct PropertyRNA;
+struct Scene;
+struct ViewLayer;
 
 struct IDOverrideLibrary *BKE_lib_override_library_init(struct ID *local_id,
                                                         struct ID *reference_id);
@@ -67,6 +69,11 @@ void BKE_lib_override_library_dependencies_tag(struct Main *bmain,
                                                struct ID *id_root,
                                                const uint tag,
                                                const bool do_create_main_relashionships);
+bool BKE_lib_override_library_create(struct Main *bmain,
+                                     struct Scene *scene,
+                                     struct ViewLayer *view_layer,
+                                     struct ID *id_root,
+                                     struct ID *id_reference);
 
 struct IDOverrideLibraryProperty *BKE_lib_override_library_property_find(
     struct IDOverrideLibrary *override, const char *rna_path);
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 58856729f24..02f5ac66c64 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -27,20 +27,25 @@
 #include "MEM_guardedalloc.h"
 
 #include "DNA_ID.h"
+#include "DNA_collection_types.h"
 #include "DNA_key_types.h"
 #include "DNA_object_types.h"
+#include "DNA_scene_types.h"
 
 #include "DEG_depsgraph.h"
 #include "DEG_depsgraph_build.h"
 
 #include "BKE_armature.h"
+#include "BKE_collection.h"
 #include "BKE_idtype.h"
 #include "BKE_key.h"
+#include "BKE_layer.h"
 #include "BKE_lib_id.h"
 #include "BKE_lib_override.h"
 #include "BKE_lib_query.h"
 #include "BKE_lib_remap.h"
 #include "BKE_main.h"
+#include "BKE_scene.h"
 
 #include "BLI_ghash.h"
 #include "BLI_listbase.h"
@@ -355,7 +360,7 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain)
   return success;
 }
 
-static bool lib_override_hierarchy_recursive_tag(Main *bmain, ID *id)
+static bool lib_override_hierarchy_recursive_tag(Main *bmain, ID *id, const uint tag)
 {
   MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->id_user_to_used, id);
 
@@ -368,13 +373,13 @@ static bool lib_override_hierarchy_recursive_tag(Main *bmain, ID *id)
   for (; entry != NULL; entry = entry->next) {
     /* We only consider IDs from the same library. */
     if (entry->id_pointer != NULL && (*entry->id_pointer)->lib == id->lib) {
-      if (lib_override_hierarchy_recursive_tag(bmain, *entry->id_pointer)) {
-        id->tag |= LIB_TAG_DOIT;
+      if (lib_override_hierarchy_recursive_tag(bmain, *entry->id_pointer, tag)) {
+        id->tag |= tag;
       }
     }
   }
 
-  return (id->tag & LIB_TAG_DOIT) != 0;
+  return (id->tag & tag) != 0;
 }
 
 /**
@@ -391,8 +396,6 @@ void BKE_lib_override_library_dependencies_tag(struct Main *bmain,
                                                const uint tag,
                                                const bool do_create_main_relashionships)
 {
-  id_root->tag |= tag;
-
   if (do_create_main_relashionships) {
     BKE_main_relations_create(bmain, 0);
   }
@@ -400,11 +403,207 @@ void BKE_lib_override_library_dependencies_tag(struct Main *bmain,
   /* Then we tag all intermediary data-blocks in-between two overridden ones (e.g. if a shapekey
    * has a driver using an armature object's bone, we need to override the shapekey/obdata, the
    * objects using them, etc.) */
-  lib_override_hierarchy_recursive_tag(bmain, id_root);
+  lib_override_hierarchy_recursive_tag(bmain, id_root, tag);
 
   BKE_main_relations_free(bmain);
 }
 
+static int lib_override_library_make_tag_ids_cb(LibraryIDLinkCallbackData *cb_data)
+{
+  if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_LOOPBACK)) {
+    return IDWALK_RET_STOP_RECURSION;
+  }
+
+  ID *id_root = cb_data->user_data;
+  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->lib != NULL);
+  BLI_assert(id_owner->lib == library_root);
+
+  if (id->tag & LIB_TAG_DOIT) {
+    /* Already processed, but maybe not with the same chain of dependency, so we need to check that
+     * one nonetheless. */
+    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;
+  }
+
+  /* We tag all collections and objects for override. And we also tag all other data-blocks which
+   * would user one of those. */
+  if (ELEM(GS(id->name), ID_OB, ID_GR)) {
+    id->tag |= LIB_TAG_DOIT;
+  }
+
+  return IDWALK_RET_NOP;
+}
+
+/**
+ * Advanced 'smart' function to create fully functionnal overrides.
+ *
+ * \note Currently it only does special things if given \a id_root is an object of collection, more
+ * specific behaviors may be added in the future for other ID types.
+ *
+ * \note It will overrides all IDs tagged with \a LIB_TAG_DOIT, and it does not clear that tag at
+ * its beginning, so caller code can add extra data-blocks to be overridden as well.
+ *
+ * \note In the future that same function may be extended to support 'refresh' of overrides
+ * (rebuilding overrides from linked data, trying to preserve local overrides already defined).
+ *
+ * \param id_root The root ID to create an override from.
+ * \param id_reference some reference ID used to do some post-processing after overrides have been
+ *                     created, may be NULL. Typically, the Empty object instantiating the linked
+ * collection we override, currently. \return true if override was successfully created.
+ */
+bool BKE_lib_override_library_create(
+    Main *bmain, Scene *scene, ViewLayer *view_layer, ID *id_root, ID *id_reference)
+{
+  /* Tag all collections and objects, as well as other IDs using them. */
+  id_root->tag |= LIB_TAG_DOIT;
+
+  BKE_main_relations_create(bmain, 0);
+
+  if (ELEM(GS(id_root->name), ID_OB, ID_GR)) {
+    BKE_library_foreach_ID_link(bmain,
+                                id_root,
+                                lib_override_library_make_tag_ids_cb,
+                                id_root,
+                                IDWALK_READONLY | IDWALK_RECURSE);
+
+    /* Then, we remove (untag) bone shape objects, you shall never want to override those
+     * (hopefully)... */
+    LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+      if (ob->type == OB_ARMATURE && ob->pose != NULL && (ob->id.tag & LIB_TAG_DOIT)) {
+        for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
+          if (pchan->custom != NULL) {
+            pchan->custom->id.tag &= ~LIB_TAG_DOIT;
+          }
+        }
+      }
+    }
+  }
+
+  /* Note that this call will also free the main relations data we created above. */
+  BKE_lib_override_library_dependencies_tag(bmain, id_root, LIB_TAG_DOIT, false);
+
+  const bool success = BKE_lib_override_library_create_from_tag(bmain);
+
+  if (success) {
+    BKE_main_collection_sync(bmain);
+
+    switch (GS(id_root->name)) {
+      case ID_GR: {
+        Object *ob_reference = id_reference != NULL && GS(id_reference->name) == ID_OB ?
+                                   (Object *)id_reference :
+                                   NULL;
+        Collection *collection_new = ((Collection *)id_root->newid);
+        if (ob_reference != NULL) {
+          BKE_collection_add_from_object(bmain, scene, ob_reference, collection_new);
+        }
+        else {
+          BKE_collection_add_from_collection(
+              bmain, scene, ((Collection *)id_root), collection_new);
+        }
+
+        FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection_new, ob_new) {
+          if (ob_new != NULL && ob_new->id.override_library != NULL) {
+            if (ob_reference != NULL) {
+              Base *base;
+              if ((base = BKE_view_layer_base_find(view_layer, ob_new)) == NULL) {
+                BKE_collection_object_add_from(bmain, scene, ob_reference, ob_new);
+                base = BKE_view_layer_base_find(view_layer, ob_new);
+                DEG_id_tag_update_ex(
+                    bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS);
+              }
+
+              if (ob_new == (Object *)ob_reference->id.newid) {
+                /* TODO: is setting active needed? */
+                BKE_view_layer_base_select_and_set_active(view_layer, base);
+              }
+            }
+            else if (BKE_view_layer_base_find(view_layer, ob_new) == NULL) {
+              BKE_collection_object_add(bmain, collection_new, ob_new);
+              DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS);
+            }
+          }
+        }
+        FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+        break;
+      }
+      case ID_OB: {
+        BKE_collection_object_add_from(
+            bmain, scene, (Object *)id_root, ((Object *)id_root->newid));
+        break;
+      }
+      default:
+        break;
+    }
+
+    /* We need to ensure all new overrides of objects are properly instantiated. */
+    LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+      Object *ob_new = (Object *)ob->id.newid;
+      if (ob_new != NULL) {
+        BLI_assert(ob_new->id.override_library != NULL &&
+                   ob_new->id.override_library->reference == &ob->id);
+
+        Collection *default_instantiating_collection = NULL;
+        if (BKE_view_layer_base_find(view_layer, ob_new) == NULL) {
+          if (default_instantiating_collection == NULL) {
+            switch (GS(id_root->name)) {
+              case ID_GR: {
+                default_instantiating_collection = BKE_collection_add(
+                    bmain,

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list