Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDalai Felinto <dfelinto@gmail.com>2018-02-06 23:27:26 +0300
committerDalai Felinto <dfelinto@gmail.com>2018-02-06 23:39:14 +0300
commit77b61b554ca10353b408645e3316e06c8d240388 (patch)
tree91d3c613b5b47e85ca7163c06673f5b63ea00602
parent107486e67378779cd53d13c91df5afb1c858c1fa (diff)
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.
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py14
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c123
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h1
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c1
4 files changed, 113 insertions, 26 deletions
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);
}