Commit: 379ffa75aa0cf80ece0b831fdf6b3d2994743740
Author: Bastien Montagne
Date:   Tue Aug 24 12:23:39 2021 +0200
Branches: blender-v2.93-release
https://developer.blender.org/rB379ffa75aa0cf80ece0b831fdf6b3d2994743740

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 62a39abf755..560fc71ff0e 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -168,8 +168,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 2813f535eb5..cc8a930b147 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -692,15 +692,19 @@ 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_tag_all(bmain, LIB_TAG_NEW, false);
     BKE_main_id_clear_newpoins(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 34c77cd9155..a814781d11b 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -2631,18 +2631,22 @@ 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_tag_all(bmain, LIB_TAG_NEW, false);
     BKE_main_id_clear_newpoins(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 66d4b18fb83..649878fe59b 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -1984,10 +1984,13 @@ 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_tag_all(bmain, LIB_TAG_NEW, false);
       BKE_main_id_clear_newpoins(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 df3968b2424..429c34333a4 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -3316,8 +3316,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;
   }
@@ -3353,8 +3358,13 @@ static int duplicate_exec(bContext *C, wmOperator *op)
   BKE_main_id_clear_newpoins(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 */
@@ -3458,7 +3468,7 @@ static int object_add_named_exec(bContext *C, wmOperator 
*op)
        * function will only work if the object is already linked in the view 
layer, which is not
        * 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);
 
   if (basen == NULL) {
     BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated");
diff --git a/source/blender/editors/space_outliner/outliner_collections.c 
b/source/blender/editors/space_outliner/outliner_collections.c
index 062d2e2b5d1..59f36967e18 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));

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to