[Bf-blender-cvs] [77b61b554ca] blender2.8: Outliner: Add object(s) to new collection

Dalai Felinto noreply at git.blender.org
Tue Feb 6 21:41:24 CET 2018


Commit: 77b61b554ca10353b408645e3316e06c8d240388
Author: Dalai Felinto
Date:   Tue Feb 6 18:27:26 2018 -0200
Branches: blender2.8
https://developer.blender.org/rB77b61b554ca10353b408645e3316e06c8d240388

Outliner: Add object(s) to new collection

Suggested by Pablo Vazquez (venomgfx).

The idea here is that it should be easy to work in the outliner by picking a
bunch of objects and adding them to a new collection.
Where is the new collection? In the same level as the "outliner active" object.

Note, since the outliner has no pure concept of an active object, I'm using
the highlight tag for this. Hopefully it works fine.

It should work in "Collections", "View Layer", and "Groups".
Only when collections are not filtered out.

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

M	release/scripts/startup/bl_ui/space_outliner.py
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

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

diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index b0cdc101c6b..6682e792d6c 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -223,6 +223,16 @@ class OUTLINER_MT_context_object_delete(Menu):
         layout.operator("outliner.object_operation", text="Delete Hierarchy").type='DELETE_HIERARCHY'
 
 
+class OUTLINER_MT_context_object_collection(Menu):
+    bl_label = "Object Operation Collection"
+
+    def draw(self, context):
+        layout = self.layout
+
+        layout.operator("outliner.object_add_to_new_collection", text="Add to New Collection", icon='ZOOMIN')
+        layout.operator("outliner.object_remove_from_collection", text="Remove from Collection", icon='ZOOMOUT')
+
+
 class OUTLINER_MT_context_object(Menu):
     bl_label = "Object"
 
@@ -231,11 +241,10 @@ class OUTLINER_MT_context_object(Menu):
 
         layout.menu("OUTLINER_MT_context_object_select", text="Select")
         layout.menu("OUTLINER_MT_context_object_delete", text="Delete")
+        layout.menu("OUTLINER_MT_context_object_collection", text="Collection")
         layout.separator()
         layout.operator("outliner.object_operation", text="Remap Users").type='REMAP'
         layout.operator("outliner.object_operation", text="Rename").type='RENAME'
-        layout.separator()
-        layout.operator("outliner.object_remove_from_collection", text="Remove from Collection")
 
 
 classes = (
@@ -249,6 +258,7 @@ classes = (
     OUTLINER_MT_context_object,
     OUTLINER_MT_context_object_delete,
     OUTLINER_MT_context_object_select,
+    OUTLINER_MT_context_object_collection,
 )
 
 if __name__ == "__main__":  # only for live edit.
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index ed01e003030..be4c8f62085 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -98,6 +98,24 @@ static int outliner_either_collection_editor_poll(bContext *C)
 	return (so != NULL) && (ELEM(so->outlinevis, SO_VIEW_LAYER, SO_COLLECTIONS));
 }
 
+static int outliner_objects_collection_poll(bContext *C)
+{
+	SpaceOops *so = CTX_wm_space_outliner(C);
+	if (so == NULL) {
+		return 0;
+	}
+
+	/* Groups don't support filtering. */
+	if ((so->outlinevis != SO_GROUPS) &&
+	    ((so->filter & (SO_FILTER_ENABLE | SO_FILTER_NO_COLLECTION)) ==
+	    (SO_FILTER_ENABLE | SO_FILTER_NO_COLLECTION)))
+	{
+		return 0;
+	}
+
+	return ELEM(so->outlinevis, SO_VIEW_LAYER, SO_COLLECTIONS, SO_GROUPS);
+}
+
 /* -------------------------------------------------------------------- */
 /* collection manager operators */
 
@@ -564,22 +582,15 @@ void OUTLINER_OT_collection_objects_remove(wmOperatorType *ot)
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
-static int object_collection_remove_poll(bContext *C)
+static TreeElement *outliner_collection_parent_element_get(TreeElement *te)
 {
-	SpaceOops *so = CTX_wm_space_outliner(C);
-	if (so == NULL) {
-		return 0;
-	}
-
-	/* Groups don't support filtering. */
-	if ((so->outlinevis != SO_GROUPS) &&
-	    ((so->filter & (SO_FILTER_ENABLE | SO_FILTER_NO_COLLECTION)) ==
-	    (SO_FILTER_ENABLE | SO_FILTER_NO_COLLECTION)))
-	{
-		return 0;
+	TreeElement *te_parent = te;
+	while ((te_parent = te_parent->parent)) {
+		if (outliner_scene_collection_from_tree_element(te->parent)) {
+			return te_parent;
+		}
 	}
-
-	return ELEM(so->outlinevis, SO_VIEW_LAYER, SO_COLLECTIONS, SO_GROUPS);
+	return NULL;
 }
 
 static int object_collection_remove_exec(bContext *C, wmOperator *UNUSED(op))
@@ -598,15 +609,9 @@ static int object_collection_remove_exec(bContext *C, wmOperator *UNUSED(op))
 		Object *ob = (Object *)TREESTORE(te)->id;
 		SceneCollection *scene_collection = NULL;
 
-		TreeElement *te_parent = te;
-		while ((te_parent = te_parent->parent)) {
-			scene_collection = outliner_scene_collection_from_tree_element(te->parent);
-			if (scene_collection != NULL) {
-				break;
-			}
-		}
-
-		if (scene_collection != NULL) {
+		TreeElement *te_parent = outliner_collection_parent_element_get(te);
+		if (te_parent != NULL) {
+			scene_collection = outliner_scene_collection_from_tree_element(te_parent);
 			ID *owner_id = TREESTORE(te_parent)->id;
 			BKE_collection_object_remove(bmain, owner_id, scene_collection, ob, true);
 			DEG_id_tag_update(owner_id, DEG_TAG_BASE_FLAGS_UPDATE);
@@ -634,7 +639,77 @@ void OUTLINER_OT_object_remove_from_collection(wmOperatorType *ot)
 
 	/* api callbacks */
 	ot->exec = object_collection_remove_exec;
-	ot->poll = object_collection_remove_poll;
+	ot->poll = outliner_objects_collection_poll;
+
+	/* flags */
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int object_add_to_new_collection_exec(bContext *C, wmOperator *op)
+{
+	int operator_result = OPERATOR_CANCELLED;
+
+	SpaceOops *soops = CTX_wm_space_outliner(C);
+	Main *bmain = CTX_data_main(C);
+
+	SceneCollection *scene_collection_parent, *scene_collection_new;
+	TreeElement *te_active, *te_parent;
+
+	struct ObjectsSelectedData data = {NULL}, active = {NULL};
+
+	outliner_tree_traverse(soops, &soops->tree, 0, TSE_HIGHLIGHTED, outliner_find_selected_objects, &active);
+	if (BLI_listbase_is_empty(&active.objects_selected_array)) {
+		BKE_report(op->reports, RPT_ERROR, "No object is selected");
+		goto cleanup;
+	}
+
+	outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data);
+	if (BLI_listbase_is_empty(&data.objects_selected_array)) {
+		BKE_report(op->reports, RPT_ERROR, "No objects are selected");
+		goto cleanup;
+	}
+
+	/* Heuristic to get the "active" / "last object" */
+	te_active = ((LinkData *)active.objects_selected_array.first)->data;
+	te_parent = outliner_collection_parent_element_get(te_active);
+
+	if (te_parent == NULL) {
+		BKE_reportf(op->reports, RPT_ERROR, "Couldn't find collection of \"%s\" object", te_active->name);
+		goto cleanup;
+	}
+
+	ID *owner_id = TREESTORE(te_parent)->id;
+	scene_collection_parent = outliner_scene_collection_from_tree_element(te_parent);
+	scene_collection_new = BKE_collection_add(owner_id, scene_collection_parent, scene_collection_parent->type, NULL);
+
+	BLI_LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) {
+		TreeElement *te = (TreeElement *)link->data;
+		Object *ob = (Object *)TREESTORE(te)->id;
+		BKE_collection_object_add(owner_id, scene_collection_new, ob);
+	}
+
+	outliner_cleanup_tree(soops);
+	DEG_relations_tag_update(bmain);
+
+	WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+	operator_result = OPERATOR_FINISHED;
+cleanup:
+	BLI_freelistN(&active.objects_selected_array);
+	BLI_freelistN(&data.objects_selected_array);
+	return operator_result;
+}
+
+void OUTLINER_OT_object_add_to_new_collection(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Add Objects to New Collection";
+	ot->idname = "OUTLINER_OT_object_add_to_new_collection";
+	ot->description = "Add objects to a new collection";
+
+	/* api callbacks */
+	ot->exec = object_add_to_new_collection_exec;
+	ot->poll = outliner_objects_collection_poll;
 
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 78ed6b07571..148af52050d 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -356,6 +356,7 @@ void OUTLINER_OT_collection_new(struct wmOperatorType *ot);
 void OUTLINER_OT_collection_duplicate(struct wmOperatorType *ot);
 void OUTLINER_OT_collection_objects_remove(struct wmOperatorType *ot);
 void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot);
+void OUTLINER_OT_object_add_to_new_collection(struct wmOperatorType *ot);
 void OUTLINER_OT_object_remove_from_collection(struct wmOperatorType *ot);
 
 void OUTLINER_OT_collection_objects_add(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index cddd6ff22cb..ba501ac7db5 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -481,6 +481,7 @@ void outliner_operatortypes(void)
 	WM_operatortype_append(OUTLINER_OT_collection_objects_add);
 	WM_operatortype_append(OUTLINER_OT_collection_objects_remove);
 	WM_operatortype_append(OUTLINER_OT_collection_objects_select);
+	WM_operatortype_append(OUTLINER_OT_object_add_to_new_collection);
 	WM_operatortype_append(OUTLINER_OT_object_remove_from_collection);
 }



More information about the Bf-blender-cvs mailing list