[Bf-blender-cvs] [67b18739ea0] temp-group-collections: Groups and collections 3/3

Dalai Felinto noreply at git.blender.org
Wed Nov 1 18:14:30 CET 2017


Commit: 67b18739ea0c7241ac565ca303d554d6a8d4e944
Author: Dalai Felinto
Date:   Thu Oct 26 17:19:52 2017 -0200
Branches: temp-group-collections
https://developer.blender.org/rB67b18739ea0c7241ac565ca303d554d6a8d4e944

Groups and collections 3/3

This allows you to create a group from a collection.
It is i the Menu when you click in the collections in the Outliner.

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

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/group.c
M	source/blender/blenkernel/intern/layer.c
M	source/blender/editors/space_outliner/outliner_tools.c

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

diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index c2d6fe3feeb..f5a0270b6a1 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -36,6 +36,7 @@ extern "C" {
 #endif
 
 struct BLI_Iterator;
+struct LayerCollection;
 struct SceneCollection;
 struct Object;
 struct Base;
@@ -60,6 +61,7 @@ bool BKE_collections_object_remove(struct Main *bmain, struct ID *id, struct Obj
 void BKE_collection_object_move(struct Scene *scene, struct SceneCollection *sc_dst, struct SceneCollection *sc_src, struct Object *ob);
 
 void BKE_collection_group_set(struct Scene *scene, struct SceneCollection *sc, struct Group *group);
+void 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/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index 3d3bf011791..1ef8ffec99a 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -79,6 +79,7 @@ void BKE_scene_layer_copy_data(struct SceneLayer *sl_dst, struct SceneLayer *sl_
                                const int flag);
 
 void BKE_layer_collection_free(struct SceneLayer *sl, struct LayerCollection *lc);
+void BKE_layer_collection_convert(struct SceneLayer *sl, struct LayerCollection *lc, const int type);
 
 struct LayerCollection *BKE_layer_collection_get_active(struct SceneLayer *sl);
 struct LayerCollection *BKE_layer_collection_get_active_ensure(struct Scene *scene, struct SceneLayer *sl);
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 912b6c28543..08b6c341ae7 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 *id)
 {
 	switch (GS(id->name)) {
@@ -442,6 +446,108 @@ void BKE_collection_group_set(Scene *UNUSED(scene), SceneCollection *sc, Group *
 	sc->group = group;
 }
 
+/**
+ * @brief collection_group_convert_layer_collections
+ * \param lb: ListBase of LayerCollection elements.
+ */
+static void collection_group_convert_layer_collections(const Group *group, SceneLayer *sl,
+                                                       const SceneCollection *sc, ListBase *lb)
+{
+	for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+		if (lc->scene_collection == sc) {
+			BKE_layer_collection_convert(sl, lc, COLLECTION_TYPE_GROUP);
+		}
+		else {
+			collection_group_convert_layer_collections(group, sl, sc, &lc->layer_collections);
+		}
+	}
+}
+
+static void layer_collection_sync(LayerCollection *lc_dst, LayerCollection *lc_src)
+{
+	lc_dst->flag = lc_src->flag;
+	lc_dst->flag_evaluated = lc_src->flag_evaluated;
+
+	/* Pending: sync overrides. */
+	TODO_LAYER_OVERRIDE;
+
+	/* 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->scene_layer->layer_collections.last != NULL) {
+		BKE_collection_unlink(group->scene_layer, group->scene_layer->layer_collections.last);
+	}
+
+	/* Remove all the SceneCollections but the master. */
+	collection_free(group->collection, false);
+}
+
+/**
+ * Convert a collection into a group
+ *
+ * Any SceneLayer that may have this the related SceneCollection linked is converted
+ * to a Group Collection.
+ */
+void BKE_collection_group_create(Main *bmain, Scene *scene, LayerCollection *lc_src)
+{
+	SceneCollection *sc_dst, *sc_src = lc_src->scene_collection;
+	LayerCollection *lc_dst;
+
+	/* We can't convert group collections into groups. */
+	if (sc_src->type == COLLECTION_TYPE_GROUP) {
+		return;
+	}
+
+	/* The master collection can't be converted. */
+	if (sc_src == BKE_collection_master(scene)) {
+		return;
+	}
+
+	/* If a sub-collection of sc_dst is directly linked into a SceneLayer we can't convert. */
+	for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+		for (LayerCollection *lc_child = sl->layer_collections.first; lc_child; lc_child = lc_child->next) {
+			if (is_collection_in_tree(lc_child->scene_collection, sc_src)) {
+				return;
+			}
+		}
+	}
+
+	/* 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, LIB_ID_CREATE_NO_USER_REFCOUNT);
+
+	lc_dst = BKE_collection_link(group->scene_layer, sc_dst);
+	layer_collection_sync(lc_dst, lc_src);
+
+	/* Convert existing collections into group collections. */
+	for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+		collection_group_convert_layer_collections(group, sl, sc_src, &sl->layer_collections);
+	}
+
+	/* Convert original SceneCollection into a group collection. */
+	BKE_collection_group_set(scene, sc_src, group);
+	sc_src->type = COLLECTION_TYPE_GROUP;
+	collection_free(sc_src, true);
+}
+
 /* ---------------------------------------------------------------------- */
 /* Outliner drag and drop */
 
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 72321ae31b1..34109572436 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -89,7 +89,6 @@ void BKE_group_init(Group *group)
 	/* Create and link a new default collection. */
 	SceneCollection *defaut_collection = BKE_collection_add(&group->id, NULL, COLLECTION_TYPE_NONE, "Default Collection");
 	BKE_collection_link(group->scene_layer, defaut_collection);
-
 }
 
 Group *BKE_group_add(Main *bmain, const char *name)
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 2869e683680..58211d16205 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -311,7 +311,7 @@ static void layer_collections_recreate(
 }
 
 /**
- * Only copy internal data of SceneLayer rom source to already allocated/initialized destination.
+ * Only copy internal data of SceneLayer from source to already allocated/initialized destination.
  *
  * \param mc_src Master Collection the source SceneLayer links in.
  * \param mc_dst Master Collection the destination SceneLayer links in.
@@ -411,6 +411,9 @@ static void layer_collection_objects_unpopulate(SceneLayer *sl, LayerCollection
 /**
  * When freeing the entire SceneLayer at once we don't bother with unref
  * otherwise SceneLayer is passed to keep the syncing of the LayerCollection tree
+ *
+ * \note
+ * Keep it in sync with BKE_layer_collection_convert.
  */
 static void layer_collection_free(SceneLayer *sl, LayerCollection *lc)
 {
@@ -443,6 +446,29 @@ void BKE_layer_collection_free(SceneLayer *sl, LayerCollection *lc)
 	layer_collection_free(sl, lc);
 }
 
+/**
+ * Convert a layer collection to a new type
+ *
+ * \param lc: LayerCollection to be converted.
+ * \param type: New type for the LayerCollection->scene_collection.
+ *
+ * \note
+ * Keep it in sync with BKE_layer_collection_free.
+ */
+void BKE_layer_collection_convert(SceneLayer *sl, LayerCollection *lc, const int type)
+{
+	/* Support group convertion only at the moment. */
+	BLI_assert(type == COLLECTION_TYPE_GROUP);
+
+	layer_collection_objects_unpopulate(sl, lc);
+	BLI_freelistN(&lc->overrides);
+
+	for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+		BKE_layer_collection_convert(sl, nlc, type);
+	}
+	BLI_freelistN(&lc->layer_collections);
+}
+
 /* LayerCollection */
 
 /**
@@ -2132,9 +2158,10 @@ void BKE_layer_eval_layer_collection(const struct EvaluationContext *eval_ctx,
 	switch (scene_collection->type) {
 		case COLLECTION_TYPE_GROUP:
 		{
-			if (scene_collection->group) {
+			Group *group = scene_collection->group;
+			if (group) {
 				LayerCollection *group_layer_collection;
-				for (group_layer_collection = scene_collection->group->scene_layer->layer_collections.first;
+				for (group_layer_collection = group->scene_layer->layer_collections.first;
 				     group_layer_collection;
 				     group_layer_collection = group_layer_collection->next)
 				{
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 0e23b70da69..d492bb189a5 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -667,6 +667,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))
@@ -874,6 +875,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,

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list