Commit: aeaf87bbeb011e9a571eefa12d81fa6fb2b8bd5b
Author: Dalai Felinto
Date:   Fri Dec 1 12:23:05 2017 -0200
Branches: blender2.8
https://developer.blender.org/rBaeaf87bbeb011e9a571eefa12d81fa6fb2b8bd5b

Groups and collection: create group from collection

You could still create groups as before, with Ctl + G. This will create a group
with a single visible collection.

However you can also create a group from an existing collection. Just go to
the menu you get in the outliner when clicking in a collection and pick
"Create Group".

Remember to instance the group afterwards, or link it into a new scene or file.

The group and the collection are not kept in sync afterwards. You need to 
manually
edit the group for further changes.

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

M       source/blender/blenkernel/BKE_collection.h
M       source/blender/blenkernel/intern/collection.c
M       source/blender/editors/space_outliner/outliner_tools.c
M       source/blender/makesrna/intern/rna_layer.c
M       tests/python/view_layer/CMakeLists.txt
A       tests/python/view_layer/test_group_a.py
A       tests/python/view_layer/test_group_b.py
A       tests/python/view_layer/test_group_c.py
A       tests/python/view_layer/test_group_d.py

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

diff --git a/source/blender/blenkernel/BKE_collection.h 
b/source/blender/blenkernel/BKE_collection.h
index c305a05ddd0..48b4ff881ae 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -58,6 +58,8 @@ bool BKE_collection_object_remove(struct Main *bmain, struct 
ID *owner_id, struc
 bool BKE_collections_object_remove(struct Main *bmain, struct ID *owner_id, 
struct Object *object, const bool free_us);
 void BKE_collection_object_move(struct ID *owner_id, struct SceneCollection 
*sc_dst, struct SceneCollection *sc_src, struct Object *ob);
 
+struct Group *BKE_collection_group_create(struct Main *bmain, struct Scene 
*scene, struct LayerCollection *lc);
+
 void BKE_collection_reinsert_after(const struct Scene *scene, struct 
SceneCollection *sc_reinsert, struct SceneCollection *sc_after);
 void BKE_collection_reinsert_into(struct SceneCollection *sc_reinsert, struct 
SceneCollection *sc_into);
 
diff --git a/source/blender/blenkernel/intern/collection.c 
b/source/blender/blenkernel/intern/collection.c
index aa5b9e7eb25..8d69563f5ff 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -34,6 +34,7 @@
 #include "BLI_string_utils.h"
 
 #include "BKE_collection.h"
+#include "BKE_group.h"
 #include "BKE_idprop.h"
 #include "BKE_layer.h"
 #include "BKE_library.h"
@@ -48,6 +49,9 @@
 
 #include "MEM_guardedalloc.h"
 
+/* Prototypes. */
+static bool is_collection_in_tree(const struct SceneCollection *sc_reference, 
struct SceneCollection *sc_parent);
+
 static SceneCollection *collection_master_from_id(const ID *owner_id)
 {
        switch (GS(owner_id->name)) {
@@ -407,6 +411,82 @@ bool BKE_collections_object_remove(Main *bmain, ID 
*owner_id, Object *ob, const
        return removed;
 }
 
+static void layer_collection_sync(LayerCollection *lc_dst, LayerCollection 
*lc_src)
+{
+       lc_dst->flag = lc_src->flag;
+
+       /* Pending: sync overrides. */
+       IDP_MergeGroup(lc_dst->properties, lc_src->properties, true);
+
+       /* Continue recursively. */
+       LayerCollection *lc_dst_nested, *lc_src_nested;
+       lc_src_nested = lc_src->layer_collections.first;
+       for (lc_dst_nested = lc_dst->layer_collections.first;
+            lc_dst_nested && lc_src_nested;
+            lc_dst_nested = lc_dst_nested->next, lc_src_nested = 
lc_src_nested->next)
+       {
+               layer_collection_sync(lc_dst_nested, lc_src_nested);
+       }
+}
+
+/**
+ * Leave only the master collection in, remove everything else.
+ * @param group
+ */
+static void collection_group_cleanup(Group *group)
+{
+       /* Unlink all the LayerCollections. */
+       while (group->view_layer->layer_collections.last != NULL) {
+               BKE_collection_unlink(group->view_layer, 
group->view_layer->layer_collections.last);
+       }
+
+       /* Remove all the SceneCollections but the master. */
+       collection_free(group->collection, false);
+}
+
+/**
+ * Create a group from a collection
+ *
+ * Any ViewLayer that may have this the related SceneCollection linked is 
converted
+ * to a Group Collection.
+ */
+Group *BKE_collection_group_create(Main *bmain, Scene *scene, LayerCollection 
*lc_src)
+{
+       SceneCollection *sc_dst, *sc_src = lc_src->scene_collection;
+       LayerCollection *lc_dst;
+
+       /* The master collection can't be converted. */
+       if (sc_src == BKE_collection_master(&scene->id)) {
+               return NULL;
+       }
+
+       /* If a sub-collection of sc_dst is directly linked into a ViewLayer we 
can't convert. */
+       for (ViewLayer *view_layer = scene->view_layers.first; view_layer; 
view_layer = view_layer->next) {
+               for (LayerCollection *lc_child = 
view_layer->layer_collections.first; lc_child; lc_child = lc_child->next) {
+                       if (is_collection_in_tree(lc_child->scene_collection, 
sc_src)) {
+                               return NULL;
+                       }
+               }
+       }
+
+       /* Create new group with the same data as the original collection. */
+       Group *group = BKE_group_add(bmain, sc_src->name);
+       collection_group_cleanup(group);
+
+       sc_dst = BKE_collection_add(&group->id, NULL, 
COLLECTION_TYPE_GROUP_INTERNAL, sc_src->name);
+       BKE_collection_copy_data(sc_dst, sc_src, 0);
+       FOREACH_SCENE_COLLECTION(&group->id, sc_group)
+       {
+               sc_group->type = COLLECTION_TYPE_GROUP_INTERNAL;
+       }
+       FOREACH_SCENE_COLLECTION_END
+
+       lc_dst = BKE_collection_link(group->view_layer, sc_dst);
+       layer_collection_sync(lc_dst, lc_src);
+
+       return group;
+}
+
 /* ---------------------------------------------------------------------- */
 /* Outliner drag and drop */
 
diff --git a/source/blender/editors/space_outliner/outliner_tools.c 
b/source/blender/editors/space_outliner/outliner_tools.c
index 203942b3c9b..99fd539293f 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -664,6 +664,7 @@ typedef enum eOutliner_PropCollectionOps {
        OL_COLLECTION_OP_COLLECTION_NEW,
        OL_COLLECTION_OP_COLLECTION_DEL,
        OL_COLLECTION_OP_COLLECTION_UNLINK,
+       OL_COLLECTION_OP_GROUP_CREATE,
 } eOutliner_PropCollectionOps;
 
 static void pchan_cb(int event, TreeElement *te, TreeStoreElem 
*UNUSED(tselem), void *UNUSED(arg))
@@ -878,6 +879,17 @@ static void collection_cb(int event, TreeElement *te, 
TreeStoreElem *UNUSED(tsel
                        TODO_LAYER_OPERATORS; /* this shouldn't be in the menu 
in those cases */
                }
        }
+       else if (event == OL_COLLECTION_OP_GROUP_CREATE) {
+               Main *bmain = CTX_data_main(C);
+               BKE_collection_group_create(bmain, scene, lc);
+               DEG_relations_tag_update(bmain);
+               /* TODO(sergey): Use proper flag for tagging here. */
+               DEG_id_tag_update(&scene->id, 0);
+               WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+       }
+       else {
+               BLI_assert(!"Collection operation not fully implemented!");
+       }
 }
 
 static void outliner_do_data_operation(SpaceOops *soops, int type, int event, 
ListBase *lb,
@@ -1808,6 +1820,7 @@ static EnumPropertyItem prop_collection_op_none_types[] = 
{
        {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New 
Collection", "Add a new nested collection"},
        {OL_COLLECTION_OP_COLLECTION_UNLINK, "COLLECTION_UNLINK", 
ICON_UNLINKED, "Unlink", "Unlink collection"},
        {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_DEL", ICON_X, "Delete 
Collection", "Delete the collection"},
+       {OL_COLLECTION_OP_GROUP_CREATE, "GROUP_CREATE", ICON_GROUP, "Create 
Group", "Turn the collection into a group collection"},
        {0, NULL, 0, NULL, NULL}
 };
 
diff --git a/source/blender/makesrna/intern/rna_layer.c 
b/source/blender/makesrna/intern/rna_layer.c
index df6c2188799..557b9a11997 100644
--- a/source/blender/makesrna/intern/rna_layer.c
+++ b/source/blender/makesrna/intern/rna_layer.c
@@ -738,6 +738,32 @@ static void rna_LayerCollection_enable_set(
        WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
 }
 
+static Group *rna_LayerCollection_create_group(
+        ID *id, LayerCollection *layer_collection, Main *bmain, bContext *C, 
ReportList *reports)
+{
+       Group *group;
+       Scene *scene = (Scene *)id;
+       SceneCollection *scene_collection = layer_collection->scene_collection;
+
+       /* The master collection can't be converted. */
+       if (scene_collection == BKE_collection_master(&scene->id)) {
+               BKE_report(reports, RPT_ERROR, "The master collection can't be 
converted to group");
+               return NULL;
+       }
+
+       group = BKE_collection_group_create(bmain, scene, layer_collection);
+       if (group == NULL) {
+               BKE_reportf(reports, RPT_ERROR, "Failed to convert collection 
%s", scene_collection->name);
+               return NULL;
+       }
+
+       DEG_relations_tag_update(bmain);
+       /* TODO(sergey): Use proper flag for tagging here. */
+       DEG_id_tag_update(&scene->id, 0);
+       WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+       return group;
+}
+
 static int rna_LayerCollections_active_collection_index_get(PointerRNA *ptr)
 {
        ViewLayer *view_layer = (ViewLayer *)ptr->data;
@@ -2019,6 +2045,12 @@ static void rna_def_layer_collection(BlenderRNA *brna)
        parm = RNA_def_boolean(func, "value", 1, "Enable", "");
        RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | 
FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
 
+       func = RNA_def_function(srna, "create_group", 
"rna_LayerCollection_create_group");
+       RNA_def_function_ui_description(func, "Enable or disable a collection");
+       RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | 
FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+       parm = RNA_def_pointer(func, "result", "Group", "", "Newly created 
Group");
+       RNA_def_function_return(func, parm);
+
        /* Flags */
        prop = RNA_def_property(srna, "is_enabled", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", 
COLLECTION_DISABLED);
diff --git a/tests/python/view_layer/CMakeLists.txt 
b/tests/python/view_layer/CMakeLists.txt
index e5b271dcb1e..22cfcd344f3 100644
--- a/tests/python/view_layer/CMakeLists.txt
+++ b/tests/python/view_layer/CMakeLists.txt
@@ -87,6 +87,10 @@ VIEW_LAYER_TEST(evaluation_selectability_c)
 VIEW_LAYER_TEST(evaluation_selectability_d)
 VIEW_LAYER_TEST(evaluation_selectability_e)
 VIEW_LAYER_TEST(evaluation_selectability_f)
+VIEW_LAYER_TEST(group_a)
+VIEW_LAYER_TEST(group_b)
+VIEW_LAYER_TEST(group_c)
+VIEW_LAYER_TEST(group_d)
 VIEW_LAYER_TEST(object_add_cylinder)
 VIEW_LAYER_TEST(object_add_empty)
 VIEW_LAYER_TEST(object_add_torus)
diff --git a/tests/python/view_layer/test_group_a.py 
b/tests/python/view_layer/test_group_a.py
new file mode 100644
index 00000000000..6e1b83efbe5
--- /dev/null
+++ b/tests/python/view_layer/test_group_a.py
@@ -0,0 +1,46 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+from view_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(ViewLayerTesting):
+    def test_group_create_basic(self):
+        """
+        See if the creation of new groups is not crashing anything.
+        """
+        import bpy
+        scene = bpy.context.scene
+        layer_collection = bpy.context.layer_collection
+
+        # Cleanup Viewport view layer
+        # technically this shouldn't be needed but
+        # for now we need it because depsgraph build all the view layers
+        # at once.
+
+        while l

@@ 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