[Bf-blender-cvs] [46913bf0a08] master: Fix T90840: Can't duplicate or copy (Ctrl-C) object from linked file.

Bastien Montagne noreply at git.blender.org
Tue Aug 24 12:27:55 CEST 2021


Commit: 46913bf0a08c7e9ae5525ff95af0c7dc3b2f622f
Author: Bastien Montagne
Date:   Tue Aug 24 12:23:39 2021 +0200
Branches: master
https://developer.blender.org/rB46913bf0a08c7e9ae5525ff95af0c7dc3b2f622f

Fix T90840: Can't duplicate or copy (Ctrl-C) object from linked file.

We need to separate the flag telling duplicate code to not handle
remapping to new IDs etc., from the one telling the code that we are
currently duplicating a 'root' ID (i.e. not a dependency of another
duplicated ID).

This whole duplicate code/logic is still fairly unsatisfying, think it
will need further refactor, or maybe even re-design, at some point...

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

M	source/blender/blenkernel/BKE_lib_id.h
M	source/blender/blenkernel/intern/collection.c
M	source/blender/blenkernel/intern/object.c
M	source/blender/blenkernel/intern/scene.c
M	source/blender/editors/object/object_add.c
M	source/blender/editors/space_outliner/outliner_collections.c

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

diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
index bb875f8d1c9..a50faedcc3c 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -166,8 +166,14 @@ struct ID *BKE_libblock_find_name(struct Main *bmain,
  */
 typedef enum eLibIDDuplicateFlags {
   /** This call to a duplicate function is part of another call for some parent ID.
-   * Therefore, this sub-process should not clear `newid` pointers, nor handle remapping itself. */
+   * Therefore, this sub-process should not clear `newid` pointers, nor handle remapping itself.
+   * NOTE: In some cases (like Object one), the duplicate function may be called on the root ID
+   * with this flag set, as remapping and/or other similar tasks need to be handled by the caller.
+   */
   LIB_ID_DUPLICATE_IS_SUBPROCESS = 1 << 0,
+  /** This call is performed on a 'root' ID, and should therefore perform some decisions regarding
+   * sub-IDs (dependencies), check for linked vs. locale data, etc. */
+  LIB_ID_DUPLICATE_IS_ROOT_ID = 1 << 1,
 } eLibIDDuplicateFlags;
 
 /* lib_remap.c (keep here since they're general functions) */
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index d36e9b67d00..2d172f23428 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -692,14 +692,18 @@ Collection *BKE_collection_duplicate(Main *bmain,
                                      eLibIDDuplicateFlags duplicate_options)
 {
   const bool is_subprocess = (duplicate_options & LIB_ID_DUPLICATE_IS_SUBPROCESS) != 0;
+  const bool is_root_id = (duplicate_options & LIB_ID_DUPLICATE_IS_ROOT_ID) != 0;
 
   if (!is_subprocess) {
     BKE_main_id_newptr_and_tag_clear(bmain);
+  }
+  if (is_root_id) {
     /* 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;
     }
+    duplicate_options &= ~LIB_ID_DUPLICATE_IS_ROOT_ID;
   }
 
   Collection *collection_new = collection_duplicate_recursive(
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 1c08a46adc3..6e26ed4925d 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -2614,17 +2614,21 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
 Object *BKE_object_duplicate(Main *bmain,
                              Object *ob,
                              eDupli_ID_Flags dupflag,
-                             const eLibIDDuplicateFlags duplicate_options)
+                             eLibIDDuplicateFlags duplicate_options)
 {
   const bool is_subprocess = (duplicate_options & LIB_ID_DUPLICATE_IS_SUBPROCESS) != 0;
+  const bool is_root_id = (duplicate_options & LIB_ID_DUPLICATE_IS_ROOT_ID) != 0;
 
   if (!is_subprocess) {
     BKE_main_id_newptr_and_tag_clear(bmain);
+  }
+  if (is_root_id) {
     /* 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(ob)) {
       dupflag |= USER_DUP_LINKED_ID;
     }
+    duplicate_options &= ~LIB_ID_DUPLICATE_IS_ROOT_ID;
   }
 
   Material ***matarar;
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index a6190efbf75..5a668746956 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -1984,9 +1984,12 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
   if (type == SCE_COPY_FULL) {
     /* Scene duplication is always root of duplication currently. */
     const bool is_subprocess = false;
+    const bool is_root_id = true;
 
     if (!is_subprocess) {
       BKE_main_id_newptr_and_tag_clear(bmain);
+    }
+    if (is_root_id) {
       /* 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(sce)) {
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 12b52907057..34400462d38 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -3359,8 +3359,13 @@ Base *ED_object_add_duplicate(
   Base *basen;
   Object *ob;
 
-  basen = object_add_duplicate_internal(
-      bmain, scene, view_layer, base->object, dupflag, LIB_ID_DUPLICATE_IS_SUBPROCESS);
+  basen = object_add_duplicate_internal(bmain,
+                                        scene,
+                                        view_layer,
+                                        base->object,
+                                        dupflag,
+                                        LIB_ID_DUPLICATE_IS_SUBPROCESS |
+                                            LIB_ID_DUPLICATE_IS_ROOT_ID);
   if (basen == NULL) {
     return NULL;
   }
@@ -3395,8 +3400,13 @@ static int duplicate_exec(bContext *C, wmOperator *op)
   BKE_main_id_newptr_and_tag_clear(bmain);
 
   CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
-    Base *basen = object_add_duplicate_internal(
-        bmain, scene, view_layer, base->object, dupflag, LIB_ID_DUPLICATE_IS_SUBPROCESS);
+    Base *basen = object_add_duplicate_internal(bmain,
+                                                scene,
+                                                view_layer,
+                                                base->object,
+                                                dupflag,
+                                                LIB_ID_DUPLICATE_IS_SUBPROCESS |
+                                                    LIB_ID_DUPLICATE_IS_ROOT_ID);
 
     /* note that this is safe to do with this context iterator,
      * the list is made in advance */
@@ -3516,7 +3526,7 @@ static int object_add_named_exec(bContext *C, wmOperator *op)
          * the case here. So we have to do the new-ID relinking ourselves
          * (#copy_object_set_idnew()).
          */
-        LIB_ID_DUPLICATE_IS_SUBPROCESS);
+        LIB_ID_DUPLICATE_IS_SUBPROCESS | LIB_ID_DUPLICATE_IS_ROOT_ID);
   }
   else {
     /* basen is actually not a new base in this case. */
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 1ec1afe86fc..ff0bd533671 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -625,7 +625,7 @@ static int collection_duplicate_exec(bContext *C, wmOperator *op)
   }
 
   const eDupli_ID_Flags dupli_flags = USER_DUP_OBJECT | (linked ? 0 : U.dupflag);
-  BKE_collection_duplicate(bmain, parent, collection, dupli_flags, 0);
+  BKE_collection_duplicate(bmain, parent, collection, dupli_flags, LIB_ID_DUPLICATE_IS_ROOT_ID);
 
   DEG_relations_tag_update(bmain);
   WM_main_add_notifier(NC_SCENE | ND_LAYER, CTX_data_scene(C));



More information about the Bf-blender-cvs mailing list