diff options
Diffstat (limited to 'source/blender')
3 files changed, 70 insertions, 23 deletions
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index 64315120afd..34128942382 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -99,9 +99,26 @@ Collection *outliner_collection_from_tree_element(const TreeElement *te) return NULL; } +TreeTraversalAction outliner_find_selected_collections(TreeElement *te, void *customdata) +{ + struct IDsSelectedData *data = customdata; + TreeStoreElem *tselem = TREESTORE(te); + + if (outliner_is_collection_tree_element(te)) { + BLI_addtail(&data->selected_array, BLI_genericNodeN(te)); + return TRAVERSE_CONTINUE; + } + + if (tselem->type || (tselem->id && GS(tselem->id->name) != ID_GR)) { + return TRAVERSE_SKIP_CHILDS; + } + + return TRAVERSE_CONTINUE; +} + TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *customdata) { - struct ObjectsSelectedData *data = customdata; + struct IDsSelectedData *data = customdata; TreeStoreElem *tselem = TREESTORE(te); if (outliner_is_collection_tree_element(te)) { @@ -112,7 +129,7 @@ TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *custom return TRAVERSE_SKIP_CHILDS; } - BLI_addtail(&data->objects_selected_array, BLI_genericNodeN(te)); + BLI_addtail(&data->selected_array, BLI_genericNodeN(te)); return TRAVERSE_CONTINUE; } @@ -811,12 +828,12 @@ void OUTLINER_OT_collection_indirect_only_clear(wmOperatorType *ot) void ED_outliner_selected_objects_get(const bContext *C, ListBase *objects) { SpaceOops *soops = CTX_wm_space_outliner(C); - struct ObjectsSelectedData data = {{NULL}}; + struct IDsSelectedData data = {{NULL}}; outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data); - LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) { + LISTBASE_FOREACH (LinkData *, link, &data.selected_array) { TreeElement *ten_selected = (TreeElement *)link->data; Object *ob = (Object *)TREESTORE(ten_selected)->id; BLI_addtail(objects, BLI_genericNodeN(ob)); } - BLI_freelistN(&data.objects_selected_array); + BLI_freelistN(&data.selected_array); } diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c index 1c19bb4d3b8..60f02dd9529 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.c +++ b/source/blender/editors/space_outliner/outliner_dragdrop.c @@ -883,26 +883,55 @@ static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *UNUSED(op), c wmDrag *drag = WM_event_start_drag(C, data.icon, WM_DRAG_ID, NULL, 0.0, WM_DRAG_NOP); - if (GS(data.drag_id->name) == ID_OB) { - /* For objects we cheat and drag all selected objects. */ + if (ELEM(GS(data.drag_id->name), ID_OB, ID_GR)) { + /* For collections and objects we cheat and drag all selected. */ TREESTORE(te)->flag |= TSE_SELECTED; - struct ObjectsSelectedData selected = { - .objects_selected_array = {NULL, NULL}, + /* Gather all selected elements. */ + struct IDsSelectedData selected = { + .selected_array = {NULL, NULL}, }; - outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &selected); - LISTBASE_FOREACH (LinkData *, link, &selected.objects_selected_array) { - TreeElement *ten_selected = (TreeElement *)link->data; - Object *ob = (Object *)TREESTORE(ten_selected)->id; + if (GS(data.drag_id->name) == ID_OB) { + outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &selected); + } + else { + outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_collections, &selected); + } + + LISTBASE_FOREACH (LinkData *, link, &selected.selected_array) { + TreeElement *te_selected = (TreeElement *)link->data; + ID *id; + + if (GS(data.drag_id->name) == ID_OB) { + id = TREESTORE(te_selected)->id; + } + else { + /* Keep collection hierarchies intact when dragging. */ + bool parent_selected = false; + for (TreeElement *te_parent = te_selected->parent; te_parent; te_parent = te_parent->parent) { + if (outliner_is_collection_tree_element(te_parent)) { + if (TREESTORE(te_parent)->flag & TSE_SELECTED) { + parent_selected = true; + break; + } + } + } + + if (parent_selected) { + continue; + } + + id = &outliner_collection_from_tree_element(te_selected)->id; + } - /* Find parent collection of object. */ + /* Find parent collection. */ Collection *parent = NULL; - if (ten_selected->parent) { - for (TreeElement *te_ob_parent = ten_selected->parent; te_ob_parent; te_ob_parent = te_ob_parent->parent) { - if (outliner_is_collection_tree_element(te_ob_parent)) { - parent = outliner_collection_from_tree_element(te_ob_parent); + if (te_selected->parent) { + for (TreeElement *te_parent = te_selected->parent; te_parent; te_parent = te_parent->parent) { + if (outliner_is_collection_tree_element(te_parent)) { + parent = outliner_collection_from_tree_element(te_parent); break; } } @@ -912,10 +941,10 @@ static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *UNUSED(op), c parent = BKE_collection_master(scene); } - WM_drag_add_ID(drag, &ob->id, &parent->id); + WM_drag_add_ID(drag, id, &parent->id); } - BLI_freelistN(&selected.objects_selected_array); + BLI_freelistN(&selected.selected_array); } else { /* Add single ID. */ diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index f8dc41b8d37..99411df3fda 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -176,10 +176,11 @@ void outliner_build_tree( struct Scene *scene, struct ViewLayer *view_layer, struct SpaceOops *soops, struct ARegion *ar); -typedef struct ObjectsSelectedData { - struct ListBase objects_selected_array; -} ObjectsSelectedData; +typedef struct IDsSelectedData { + struct ListBase selected_array; +} IDsSelectedData; +TreeTraversalAction outliner_find_selected_collections(struct TreeElement *te, void *customdata); TreeTraversalAction outliner_find_selected_objects(struct TreeElement *te, void *customdata); /* outliner_draw.c ---------------------------------------------- */ |