[Bf-blender-cvs] [7b1c406b543] master: Implement T77959: Never duplicate linked data during deep-copy.

Bastien Montagne noreply at git.blender.org
Thu Jul 9 17:56:14 CEST 2020


Commit: 7b1c406b5431ce65d84ddb5f2c53977c25c18373
Author: Bastien Montagne
Date:   Thu Jul 9 15:33:34 2020 +0200
Branches: master
https://developer.blender.org/rB7b1c406b5431ce65d84ddb5f2c53977c25c18373

Implement T77959: Never duplicate linked data during deep-copy.

Note that this behavior is enforced on user level for now, but on code
side it is controlled with a flag, which should make it easy to refine
that behavior if needed.

Only exception is when we duplicate a linked ID directly (then we assume
user wants a local deep-copy of that linked data, and we always also
duplicate linked sub-data-blocks).

Note that this commit also slightly refactor the handling of actions of
animdata, by simplifying `BKE_animdata_copy_id_action()` and adding an
explicit new `BKE_animdata_duplicate_id_action()` to be used during ID
duplication (deep copy).

This also allows us to get rid of the special case for liboverrides.

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

M	source/blender/blenkernel/BKE_anim_data.h
M	source/blender/blenkernel/BKE_lib_id.h
M	source/blender/blenkernel/BKE_object.h
M	source/blender/blenkernel/intern/anim_data.c
M	source/blender/blenkernel/intern/collection.c
M	source/blender/blenkernel/intern/lib_id.c
M	source/blender/blenkernel/intern/object.c
M	source/blender/blenkernel/intern/scene.c
M	source/blender/editors/object/object_relations.c
M	source/blender/makesdna/DNA_userdef_types.h

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

diff --git a/source/blender/blenkernel/BKE_anim_data.h b/source/blender/blenkernel/BKE_anim_data.h
index 5aeaf4405f5..48e95740b9d 100644
--- a/source/blender/blenkernel/BKE_anim_data.h
+++ b/source/blender/blenkernel/BKE_anim_data.h
@@ -71,7 +71,11 @@ bool BKE_animdata_copy_id(struct Main *bmain,
                           const int flag);
 
 /* Copy AnimData Actions */
-void BKE_animdata_copy_id_action(struct Main *bmain, struct ID *id, const bool set_newid);
+void BKE_animdata_copy_id_action(struct Main *bmain, struct ID *id);
+
+void BKE_animdata_duplicate_id_action(struct Main *bmain,
+                                      struct ID *id,
+                                      const uint duplicate_flags);
 
 /* Merge copies of data from source AnimData block */
 typedef enum eAnimData_MergeCopy_Modes {
diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
index bc72afdd08d..76bae6fa909 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -229,7 +229,6 @@ bool BKE_id_copy(struct Main *bmain, const struct ID *id, struct ID **newid);
 bool BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag);
 struct ID *BKE_id_copy_for_duplicate(struct Main *bmain,
                                      struct ID *id,
-                                     const bool is_owner_id_liboverride,
                                      const uint duplicate_flags);
 
 void BKE_lib_id_swap(struct Main *bmain, struct ID *id_a, struct ID *id_b);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index d830a35dda0..f2a022c84a3 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -139,7 +139,7 @@ bool BKE_object_obdata_is_libdata(const struct Object *ob);
 
 struct Object *BKE_object_duplicate(struct Main *bmain,
                                     struct Object *ob,
-                                    const uint dupflag,
+                                    uint dupflag,
                                     const uint duplicate_options);
 
 void BKE_object_obdata_size_init(struct Object *ob, const float scale);
diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c
index 3e2c69fbcea..61181278c60 100644
--- a/source/blender/blenkernel/intern/anim_data.c
+++ b/source/blender/blenkernel/intern/anim_data.c
@@ -375,17 +375,19 @@ bool BKE_animdata_copy_id(Main *bmain, ID *id_to, ID *id_from, const int flag)
   return true;
 }
 
-void BKE_animdata_copy_id_action(Main *bmain, ID *id, const bool set_newid)
+static void animdata_copy_id_action(Main *bmain,
+                                    ID *id,
+                                    const bool set_newid,
+                                    const bool do_linked_id)
 {
-  const bool is_id_liboverride = ID_IS_OVERRIDE_LIBRARY(id);
   AnimData *adt = BKE_animdata_from_id(id);
   if (adt) {
-    if (adt->action && (!is_id_liboverride || !ID_IS_LINKED(adt->action))) {
+    if (adt->action && (do_linked_id || !ID_IS_LINKED(adt->action))) {
       id_us_min((ID *)adt->action);
       adt->action = set_newid ? ID_NEW_SET(adt->action, BKE_action_copy(bmain, adt->action)) :
                                 BKE_action_copy(bmain, adt->action);
     }
-    if (adt->tmpact && (!is_id_liboverride || !ID_IS_LINKED(adt->tmpact))) {
+    if (adt->tmpact && (do_linked_id || !ID_IS_LINKED(adt->tmpact))) {
       id_us_min((ID *)adt->tmpact);
       adt->tmpact = set_newid ? ID_NEW_SET(adt->tmpact, BKE_action_copy(bmain, adt->tmpact)) :
                                 BKE_action_copy(bmain, adt->tmpact);
@@ -393,12 +395,27 @@ void BKE_animdata_copy_id_action(Main *bmain, ID *id, const bool set_newid)
   }
   bNodeTree *ntree = ntreeFromID(id);
   if (ntree) {
-    BKE_animdata_copy_id_action(bmain, &ntree->id, set_newid);
+    animdata_copy_id_action(bmain, &ntree->id, set_newid, do_linked_id);
   }
   /* Note that collections are not animatable currently, so no need to handle scenes' master
    * collection here. */
 }
 
+void BKE_animdata_copy_id_action(Main *bmain, ID *id)
+{
+  const bool is_id_liboverride = ID_IS_OVERRIDE_LIBRARY(id);
+  animdata_copy_id_action(bmain, id, false, !is_id_liboverride);
+}
+
+void BKE_animdata_duplicate_id_action(struct Main *bmain,
+                                      struct ID *id,
+                                      const eDupli_ID_Flags duplicate_flags)
+{
+  if (duplicate_flags & USER_DUP_ACT) {
+    animdata_copy_id_action(bmain, id, true, (duplicate_flags & USER_DUP_LINKED_ID) != 0);
+  }
+}
+
 /* Merge copies of the data from the src AnimData into the destination AnimData */
 void BKE_animdata_merge_copy(
     Main *bmain, ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes action_mode, bool fix_drivers)
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 080d61f1500..7e22048379b 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -333,7 +333,6 @@ static Collection *collection_duplicate_recursive(Main *bmain,
   Collection *collection_new;
   bool do_full_process = false;
   const bool is_collection_master = (collection_old->flag & COLLECTION_IS_MASTER) != 0;
-  const bool is_collection_liboverride = ID_IS_OVERRIDE_LIBRARY(collection_old);
 
   const bool do_objects = (duplicate_flags & USER_DUP_OBJECT) != 0;
 
@@ -346,7 +345,12 @@ static Collection *collection_duplicate_recursive(Main *bmain,
   }
   else if (collection_old->id.newid == NULL) {
     collection_new = (Collection *)BKE_id_copy_for_duplicate(
-        bmain, (ID *)collection_old, is_collection_liboverride, duplicate_flags);
+        bmain, (ID *)collection_old, duplicate_flags);
+
+    if (collection_new == collection_old) {
+      return collection_new;
+    }
+
     do_full_process = true;
   }
   else {
@@ -382,17 +386,15 @@ static Collection *collection_duplicate_recursive(Main *bmain,
       Object *ob_old = cob->ob;
       Object *ob_new = (Object *)ob_old->id.newid;
 
-      /* If collection is an override, we do not want to duplicate any linked data-block, as that
-       * would generate a purely local data. */
-      if (is_collection_liboverride && ID_IS_LINKED(ob_old)) {
-        continue;
-      }
-
       if (ob_new == NULL) {
         ob_new = BKE_object_duplicate(
             bmain, ob_old, duplicate_flags, duplicate_options | LIB_ID_DUPLICATE_IS_SUBPROCESS);
       }
 
+      if (ob_new == ob_old) {
+        continue;
+      }
+
       collection_object_add(bmain, collection_new, ob_new, 0, true);
       collection_object_remove(bmain, collection_new, ob_old, false);
     }
@@ -403,13 +405,11 @@ static Collection *collection_duplicate_recursive(Main *bmain,
   LISTBASE_FOREACH_MUTABLE (CollectionChild *, child, &collection_old->children) {
     Collection *child_collection_old = child->collection;
 
-    if (is_collection_liboverride && ID_IS_LINKED(child_collection_old)) {
-      continue;
-    }
-
-    collection_duplicate_recursive(
+    Collection *child_collection_new = collection_duplicate_recursive(
         bmain, collection_new, child_collection_old, duplicate_flags, duplicate_options);
-    collection_child_remove(collection_new, child_collection_old);
+    if (child_collection_new != child_collection_old) {
+      collection_child_remove(collection_new, child_collection_old);
+    }
   }
 
   return collection_new;
@@ -434,6 +434,11 @@ Collection *BKE_collection_duplicate(Main *bmain,
   if (!is_subprocess) {
     BKE_main_id_tag_all(bmain, LIB_TAG_NEW, false);
     BKE_main_id_clear_newpoins(bmain);
+    /* In case root duplicated ID is linked, assume we want to get a local copy of it and duplicate
+     * all expected linked data. */
+    if (ID_IS_LINKED(collection)) {
+      duplicate_flags |= USER_DUP_LINKED_ID;
+    }
   }
 
   Collection *collection_new = collection_duplicate_recursive(
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 7c09ae51344..eb440de1a6f 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -611,41 +611,39 @@ bool BKE_id_copy(Main *bmain, const ID *id, ID **newid)
  * Invokes the appropriate copy method for the block and returns the result in
  * newid, unless test. Returns true if the block can be copied.
  */
-ID *BKE_id_copy_for_duplicate(Main *bmain,
-                              ID *id,
-                              const bool is_owner_id_liboverride,
-                              const eDupli_ID_Flags duplicate_flags)
+ID *BKE_id_copy_for_duplicate(Main *bmain, ID *id, const eDupli_ID_Flags duplicate_flags)
 {
   if (id == NULL) {
-    return NULL;
+    return id;
   }
   if (id->newid == NULL) {
-    if (!is_owner_id_liboverride || !ID_IS_LINKED(id)) {
-      ID *id_new;
-      BKE_id_copy(bmain, id, &id_new);
-      /* Copying add one user by default, need to get rid of that one. */
-      id_us_min(id_new);
-      ID_NEW_SET(id, id_new);
-
-      /* Shape keys are always copied with their owner ID, by default. */
-      ID *key_new = (ID *)BKE_key_from_id(id_new);
-      ID *key = (ID *)BKE_key_from_id(id);
-      if (key != NULL) {
-        ID_NEW_SET(key, key_new);
-      }
+    const bool do_linked_id = (duplicate_flags & USER_DUP_LINKED_ID) != 0;
+    if (!(do_linked_id || !ID_IS_LINKED(id))) {
+      return id;
+    }
 
-      /* Note: embedded data (root nodetrees and master collections) should never be referenced by
-       * anything else, so we do not need to set their newid pointer and flag. */
+    ID *id_new;
+    BKE_id_copy(bmain, id, &id_new);
+    /* Copying add one user by default, need to get rid of that one. */
+    id_us_min(id_new);
+    ID_NEW_SET(id, id_new);
 
-      if (duplicate_flags & USER_DUP_ACT) {
-        BKE_animdata_copy_id_action(bmain, id_new, true);
-        if (key_new != NULL) {
-          BKE_animdata_copy_id_action(bmain, key_new, true);
-        }
-        /* Note that actions of embedded data (root nodetrees and master collections) are han

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list