[Bf-blender-cvs] [fb4cd136a7c] blender2.8: Outliner: Support multiple-objects drag'n'drop into collections

Dalai Felinto noreply at git.blender.org
Fri Jan 5 21:32:02 CET 2018


Commit: fb4cd136a7cf94f2fda2d3a2c8fb01d73eb878cb
Author: Dalai Felinto
Date:   Fri Jan 5 18:09:58 2018 -0200
Branches: blender2.8
https://developer.blender.org/rBfb4cd136a7cf94f2fda2d3a2c8fb01d73eb878cb

Outliner: Support multiple-objects drag'n'drop into collections

We now can drag multiple objects at once in the outliner. You we restricted to
working within a single outliner. Be sure to drag from the objects name, not
from its icon (otherwise it will try to parent it).

We don't use the same drag'n'drop system as IDs here. Which although I dislike
allowed for this solution to be local, and not dependent on the entire
drag'n'drop system of Blender.

This is a feature Andy Goralczyk has requested a long time ago.
Kudos for him for his request.

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

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_tree.c

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

diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index f5687456663..f2457b30a15 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -69,6 +69,7 @@ typedef enum TreeTraversalAction {
  * Callback type for reinserting elements at a different position, used to allow user customizable element order.
  */
 typedef void (*TreeElementReinsertFunc)(struct Main *bmain,
+                                        struct SpaceOops *soops,
                                         struct TreeElement *insert_element,
                                         struct TreeElement *insert_handle, TreeElementInsertType action);
 /**
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index a40abb5fd3b..57c93e19612 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -164,7 +164,7 @@ static void outliner_item_drag_handle(
 	te_dragged->drag_data->insert_handle = te_insert_handle;
 }
 
-static bool outliner_item_drag_drop_apply(Main *bmain, TreeElement *dragged_te)
+static bool outliner_item_drag_drop_apply(Main *bmain, SpaceOops *soops, TreeElement *dragged_te)
 {
 	TreeElement *insert_handle = dragged_te->drag_data->insert_handle;
 	TreeElementInsertType insert_type = dragged_te->drag_data->insert_type;
@@ -178,7 +178,7 @@ static bool outliner_item_drag_drop_apply(Main *bmain, TreeElement *dragged_te)
 		/* call of assert above should not have changed insert_handle and insert_type at this point */
 		BLI_assert(dragged_te->drag_data->insert_handle == insert_handle &&
 		           dragged_te->drag_data->insert_type == insert_type);
-		dragged_te->reinsert(bmain, dragged_te, insert_handle, insert_type);
+		dragged_te->reinsert(bmain, soops, dragged_te, insert_handle, insert_type);
 		return true;
 	}
 
@@ -198,7 +198,7 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
 	switch (event->type) {
 		case EVT_MODAL_MAP:
 			if (event->val == OUTLINER_ITEM_DRAG_CONFIRM) {
-				if (outliner_item_drag_drop_apply(bmain, te_dragged)) {
+				if (outliner_item_drag_drop_apply(bmain, soops, te_dragged)) {
 					skip_rebuild = false;
 				}
 				retval = OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 5ea83515f51..3a97964e538 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -387,12 +387,38 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s
 #endif
 }
 
+struct ObjectsSelectedData {
+	ListBase objects_selected_array;
+};
+
+static TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *customdata)
+{
+	struct ObjectsSelectedData *data = customdata;
+	TreeStoreElem *tselem = TREESTORE(te);
+
+	if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
+		return TRAVERSE_CONTINUE;
+	}
+
+	if (tselem->type || (tselem->id == NULL) || (GS(tselem->id->name) != ID_OB)) {
+		return TRAVERSE_SKIP_CHILDS;
+	}
+
+	BLI_addtail(&data->objects_selected_array, BLI_genericNodeN(te));
+
+	return TRAVERSE_CONTINUE;
+}
+
+/**
+ * Move objects from a collection to another.
+ * We ignore the original object being inserted, we used it for polling only.
+ * Instead we move all the selected objects around.
+ */
 static void outliner_object_reorder(
-        Main *UNUSED(bmain),
-        TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
+        Main *bmain, SpaceOops *soops,
+        TreeElement *insert_element,
+        TreeElement *insert_handle, TreeElementInsertType action)
 {
-	TreeStoreElem *tselem_insert = TREESTORE(insert_element);
-	Object *ob = (Object *)tselem_insert->id;
 	SceneCollection *sc = outliner_scene_collection_from_tree_element(insert_handle);
 	SceneCollection *sc_ob_parent = NULL;
 	ID *id = insert_handle->store_elem->id;
@@ -400,19 +426,36 @@ static void outliner_object_reorder(
 	BLI_assert(action == TE_INSERT_INTO);
 	UNUSED_VARS_NDEBUG(action);
 
-	/* find parent scene-collection of object */
-	if (insert_element->parent) {
-		for (TreeElement *te_ob_parent = insert_element->parent; te_ob_parent; te_ob_parent = te_ob_parent->parent) {
-			if (ELEM(TREESTORE(te_ob_parent)->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION)) {
-				sc_ob_parent = outliner_scene_collection_from_tree_element(te_ob_parent);
-				break;
+	struct ObjectsSelectedData data = {
+		.objects_selected_array  = {NULL, NULL},
+	};
+
+	/* Make sure we include the originally inserted element as well. */
+	TREESTORE(insert_element)->flag |= TSE_SELECTED;
+
+	outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data);
+	LINKLIST_FOREACH(LinkData *, link, &data.objects_selected_array) {
+		TreeElement *ten_selected = (TreeElement *)link->data;
+		/* Find parent scene-collection of object. */
+		if (ten_selected->parent) {
+			for (TreeElement *te_ob_parent = ten_selected->parent; te_ob_parent; te_ob_parent = te_ob_parent->parent) {
+				if (ELEM(TREESTORE(te_ob_parent)->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION)) {
+					sc_ob_parent = outliner_scene_collection_from_tree_element(te_ob_parent);
+					break;
+				}
 			}
 		}
+		else {
+			sc_ob_parent = BKE_collection_master(id);
+		}
+		Object *ob = (Object *)TREESTORE(ten_selected)->id;
+		BKE_collection_object_move(id, sc, sc_ob_parent, ob);
 	}
-	else {
-		sc_ob_parent = BKE_collection_master(id);
-	}
-	BKE_collection_object_move(id, sc, sc_ob_parent, ob);
+
+	BLI_freelistN(&data.objects_selected_array);
+
+	DEG_relations_tag_update(bmain);
+	WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
 }
 
 static bool outliner_object_reorder_poll(
@@ -1358,6 +1401,7 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
 
 static void outliner_layer_collections_reorder(
         Main *bmain,
+        SpaceOops *UNUSED(soops),
         TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
 {
 	LayerCollection *lc_insert = insert_element->directdata;
@@ -1419,6 +1463,7 @@ static void outliner_add_collections_act_layer(SpaceOops *soops, Scene *scene, V
 
 static void outliner_scene_collections_reorder(
         Main *bmain,
+        SpaceOops *UNUSED(soops),
         TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
 {
 	SceneCollection *sc_insert = insert_element->directdata;



More information about the Bf-blender-cvs mailing list