diff options
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); } |