Commit: c7c070c2ece0f41772cbcfe3445f3e0be684dd1d
Author: Dalai Felinto
Date:   Thu Feb 1 21:11:59 2018 -0200
Branches: blender2.8
https://developer.blender.org/rBc7c070c2ece0f41772cbcfe3445f3e0be684dd1d

Collections: Operator to duplicate a collection

When duplicating a layer collection directly linked to the view layer we copy
the collection and link it.

For all the not directly linked layer collectionns, we try to sync the layer
collection flags, overrides, ...

Also we make sure the new collection is right after the original collection.

We also expose this in RNA, via collection.duplicate().

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

M       release/scripts/startup/bl_ui/space_outliner.py
M       source/blender/blenkernel/BKE_collection.h
M       source/blender/blenkernel/BKE_layer.h
M       source/blender/blenkernel/intern/collection.c
M       source/blender/blenkernel/intern/layer.c
M       source/blender/editors/space_outliner/outliner_collections.c
M       source/blender/editors/space_outliner/outliner_intern.h
M       source/blender/editors/space_outliner/outliner_ops.c
M       source/blender/editors/space_outliner/outliner_tools.c
M       source/blender/makesrna/intern/rna_layer.c

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

diff --git a/release/scripts/startup/bl_ui/space_outliner.py 
b/release/scripts/startup/bl_ui/space_outliner.py
index 28644428cf8..122fe84763d 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -195,6 +195,7 @@ class OUTLINER_MT_context_scene_collection(Menu):
         layout = self.layout
 
         layout.operator("outliner.collection_nested_new", text="New 
Collection", icon='NEW')
+        layout.operator("outliner.collection_duplicate", text="Duplicate 
Collection")
         layout.operator("outliner.collection_delete_selected", text="Delete 
Collections", icon='X')
         layout.separator()
         layout.operator("outliner.collection_objects_add", text="Add 
Selected", icon='ZOOMIN')
diff --git a/source/blender/blenkernel/BKE_collection.h 
b/source/blender/blenkernel/BKE_collection.h
index 48b4ff881ae..618e60550b7 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -49,6 +49,7 @@ struct SceneCollection *BKE_collection_add(
         struct ID *owner_id, struct SceneCollection *sc_parent, const int 
type, const char *name);
 bool BKE_collection_remove(struct ID *owner_id, struct SceneCollection *sc);
 void BKE_collection_copy_data(struct SceneCollection *sc_dst, struct 
SceneCollection *sc_src, const int flag);
+struct SceneCollection *BKE_collection_duplicate(struct ID *owner_id, struct 
SceneCollection *scene_collection);
 struct SceneCollection *BKE_collection_master(const struct ID *owner_id);
 void BKE_collection_rename(const struct Scene *scene, struct SceneCollection 
*sc, const char *name);
 void BKE_collection_master_free(struct ID *owner_id, const bool do_id_user);
diff --git a/source/blender/blenkernel/BKE_layer.h 
b/source/blender/blenkernel/BKE_layer.h
index f098a7e7468..633cb2c6044 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -78,11 +78,18 @@ struct Base *BKE_view_layer_base_find(struct ViewLayer 
*view_layer, struct Objec
 void BKE_view_layer_base_deselect_all(struct ViewLayer *view_layer);
 void BKE_view_layer_base_select(struct ViewLayer *view_layer, struct Base 
*selbase);
 
+void BKE_layer_collection_sync_flags(
+        struct ID *owner_id,
+        struct SceneCollection *scene_collection_dst,
+        struct SceneCollection *scene_collection_src);
+
 void BKE_view_layer_copy_data(
         struct ViewLayer *view_layer_dst, struct ViewLayer *view_layer_src,
         struct SceneCollection *mc_dst, struct SceneCollection *mc_src,
         const int flag);
 
+struct LayerCollection *BKE_layer_collection_duplicate(struct ID *owner_id, 
struct LayerCollection *layer_collection);
+
 void BKE_layer_collection_free(struct ViewLayer *view_layer, struct 
LayerCollection *lc);
 
 struct LayerCollection *BKE_layer_collection_get_active(struct ViewLayer 
*view_layer);
diff --git a/source/blender/blenkernel/intern/collection.c 
b/source/blender/blenkernel/intern/collection.c
index ca77969ccaa..729be02bfc7 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -68,10 +68,9 @@ static SceneCollection *collection_master_from_id(const ID 
*owner_id)
 }
 
 /**
- * Add a collection to a collection ListBase and syncronize all render layers
- * The ListBase is NULL when the collection is to be added to the master 
collection
+ * Add a new collection, but don't handle syncing with layer collections
  */
-SceneCollection *BKE_collection_add(ID *owner_id, SceneCollection *sc_parent, 
const int type, const char *name_custom)
+static SceneCollection *collection_add(ID *owner_id, SceneCollection 
*sc_parent, const int type, const char *name_custom)
 {
        SceneCollection *sc_master = collection_master_from_id(owner_id);
        SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New 
Collection");
@@ -99,8 +98,6 @@ SceneCollection *BKE_collection_add(ID *owner_id, 
SceneCollection *sc_parent, co
        BLI_addtail(&sc_parent->scene_collections, sc);
        BKE_collection_rename((Scene *)owner_id, sc, name);
 
-       BKE_layer_sync_new_scene_collection(owner_id, sc_parent, sc);
-
        if (name != name_custom) {
                MEM_freeN((char *)name);
        }
@@ -108,6 +105,17 @@ SceneCollection *BKE_collection_add(ID *owner_id, 
SceneCollection *sc_parent, co
        return sc;
 }
 
+/**
+ * Add a collection to a collection ListBase and syncronize all render layers
+ * The ListBase is NULL when the collection is to be added to the master 
collection
+ */
+SceneCollection *BKE_collection_add(ID *owner_id, SceneCollection *sc_parent, 
const int type, const char *name_custom)
+{
+       SceneCollection *scene_collection = collection_add(owner_id, sc_parent, 
type, name_custom);
+       BKE_layer_sync_new_scene_collection(owner_id, sc_parent, 
scene_collection);
+       return scene_collection;
+}
+
 /**
  * Free the collection items recursively
  */
@@ -270,6 +278,43 @@ void BKE_collection_copy_data(SceneCollection *sc_dst, 
SceneCollection *sc_src,
        }
 }
 
+/**
+ * Makes a shallow copy of a SceneCollection
+ *
+ * Add a new collection in the same level as the old one, copy any nested 
collections
+ * but link the objects to the new collection (as oppose to copy them).
+ */
+SceneCollection *BKE_collection_duplicate(ID *owner_id, SceneCollection 
*scene_collection)
+{
+       SceneCollection *scene_collection_master = 
BKE_collection_master(owner_id);
+       SceneCollection *scene_collection_parent = 
find_collection_parent(scene_collection, scene_collection_master);
+
+       /* It's not allowed to copy the master collection. */
+       if (scene_collection_master == scene_collection) {
+               return NULL;
+       }
+
+       SceneCollection *scene_collection_new = collection_add(
+                                                   owner_id,
+                                                   scene_collection_parent,
+                                                   scene_collection->type,
+                                                   scene_collection->name);
+
+       if (scene_collection_new != scene_collection->next) {
+               BLI_remlink(&scene_collection_parent->scene_collections, 
scene_collection_new);
+               
BLI_insertlinkafter(&scene_collection_parent->scene_collections, 
scene_collection, scene_collection_new);
+       }
+
+       BKE_collection_copy_data(scene_collection_new, scene_collection, 0);
+       BKE_layer_sync_new_scene_collection(owner_id, scene_collection_parent, 
scene_collection_new);
+
+       /* Make sure every linked instance of the new collection has the same 
values (flags, overrides, ...) as the
+        * corresponding original collection. */
+       BKE_layer_collection_sync_flags(owner_id, scene_collection_new, 
scene_collection);
+
+       return scene_collection_new;
+}
+
 static SceneCollection *master_collection_from_id(const ID *owner_id)
 {
        switch (GS(owner_id->name)) {
diff --git a/source/blender/blenkernel/intern/layer.c 
b/source/blender/blenkernel/intern/layer.c
index 4333faea863..9807c6e4f10 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -61,6 +61,7 @@
 
 /* prototype */
 struct EngineSettingsCB_Type;
+static void layer_collections_sync_flags(ListBase *layer_collections_dst, 
const ListBase *layer_collections_src);
 static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc);
 static void layer_collection_objects_populate(ViewLayer *view_layer, 
LayerCollection *lc, ListBase *objects);
 static LayerCollection *layer_collection_add(ViewLayer *view_layer, 
LayerCollection *parent, SceneCollection *sc);
@@ -353,27 +354,94 @@ static SceneCollection *scene_collection_from_new_tree(
        return NULL;
 }
 
+static void layer_collection_sync_flags(
+        LayerCollection *layer_collection_dst,
+        const LayerCollection *layer_collection_src)
+{
+       layer_collection_dst->flag = layer_collection_src->flag;
+
+       if (layer_collection_dst->properties != NULL) {
+               IDP_FreeProperty(layer_collection_dst->properties);
+               MEM_SAFE_FREE(layer_collection_dst->properties);
+       }
+
+       if (layer_collection_src->properties != NULL) {
+               layer_collection_dst->properties = 
IDP_CopyProperty(layer_collection_src->properties);
+       }
+
+       layer_collections_sync_flags(&layer_collection_dst->layer_collections,
+                                    &layer_collection_src->layer_collections);
+}
+
 static void layer_collections_sync_flags(ListBase *layer_collections_dst, 
const ListBase *layer_collections_src)
 {
        LayerCollection *layer_collection_dst = (LayerCollection 
*)layer_collections_dst->first;
        const LayerCollection *layer_collection_src = (const LayerCollection 
*)layer_collections_src->first;
        while (layer_collection_dst != NULL) {
-               layer_collection_dst->flag = layer_collection_src->flag;
+               layer_collection_sync_flags(layer_collection_dst, 
layer_collection_src);
+               layer_collection_dst = layer_collection_dst->next;
+               layer_collection_src = layer_collection_src->next;
+       }
+}
 
-               if (layer_collection_dst->properties != NULL) {
-                       IDP_FreeProperty(layer_collection_dst->properties);
-                       MEM_SAFE_FREE(layer_collection_dst->properties);
+static bool layer_collection_sync_if_match(
+        ListBase *lb,
+        const SceneCollection *scene_collection_dst,
+        const SceneCollection *scene_collection_src)
+{
+       for (LayerCollection *layer_collection = lb->first;
+            layer_collection;
+            layer_collection = layer_collection->next)
+       {
+               if (layer_collection->scene_collection == scene_collection_src) 
{
+                       LayerCollection *layer_collection_dst =
+                               BLI_findptr(
+                                   lb,
+                                   scene_collection_dst,
+                                   offsetof(LayerCollection, 
scene_collection));
+
+                       if (layer_collection_dst != NULL) {
+                               
layer_collection_sync_flags(layer_collection_dst, layer_collection);
+                       }
+                       return true;
                }
-
-               if (layer_collection_src->properties != NULL) {
-                       layer_collection_dst->properties = 
IDP_CopyProperty(layer_collection_src->properties);
+               else {
+                       if (layer_collection_sync_if_match(
+                               &layer_collection->layer_collections,
+                               scene_collection_dst,
+                               scene_collection_src))
+                       {
+                               return true;
+                       }
                }
+       }
+       return false;
+}
 
-               
layer_collections_sync_flags(&layer_collection_dst->layer_collections,
-                                            &layer_collection_src->layer_co

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to