diff options
author | Dalai Felinto <dfelinto@gmail.com> | 2018-02-06 23:27:26 +0300 |
---|---|---|
committer | Dalai Felinto <dfelinto@gmail.com> | 2018-02-06 23:39:14 +0300 |
commit | 77b61b554ca10353b408645e3316e06c8d240388 (patch) | |
tree | 91d3c613b5b47e85ca7163c06673f5b63ea00602 /source/blender | |
parent | 107486e67378779cd53d13c91df5afb1c858c1fa (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.
Diffstat (limited to 'source/blender')
3 files changed, 101 insertions, 24 deletions
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); } |