Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_outliner/outliner_dragdrop.c
| Show All 25 Lines | |||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "DNA_collection_types.h" | #include "DNA_collection_types.h" | ||||
| #include "DNA_material_types.h" | #include "DNA_material_types.h" | ||||
| #include "DNA_object_types.h" | #include "DNA_object_types.h" | ||||
| #include "DNA_space_types.h" | #include "DNA_space_types.h" | ||||
| #include "BLI_listbase.h" | #include "BLI_listbase.h" | ||||
| #include "BLI_string.h" | |||||
| #include "BLT_translation.h" | #include "BLT_translation.h" | ||||
| #include "BKE_collection.h" | #include "BKE_collection.h" | ||||
| #include "BKE_context.h" | #include "BKE_context.h" | ||||
| #include "BKE_layer.h" | #include "BKE_layer.h" | ||||
| #include "BKE_main.h" | #include "BKE_main.h" | ||||
| #include "BKE_material.h" | #include "BKE_material.h" | ||||
| ▲ Show 20 Lines • Show All 269 Lines • ▼ Show 20 Lines | case SO_VIEW_LAYER: | ||||
| return space_outliner->filter & SO_FILTER_NO_COLLECTION; | return space_outliner->filter & SO_FILTER_NO_COLLECTION; | ||||
| case SO_SCENES: | case SO_SCENES: | ||||
| return true; | return true; | ||||
| default: | default: | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| static bool parent_drop_poll(bContext *C, | static bool parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) | ||||
| wmDrag *drag, | |||||
| const wmEvent *event, | |||||
| const char **UNUSED(r_tooltip)) | |||||
| { | { | ||||
| SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); | SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); | ||||
| bool changed = outliner_flag_set(&space_outliner->tree, TSE_DRAG_ANY, false); | bool changed = outliner_flag_set(&space_outliner->tree, TSE_DRAG_ANY, false); | ||||
| if (changed) { | if (changed) { | ||||
| ED_region_tag_redraw_no_rebuild(CTX_wm_region(C)); | ED_region_tag_redraw_no_rebuild(CTX_wm_region(C)); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 119 Lines • ▼ Show 20 Lines | void OUTLINER_OT_parent_drop(wmOperatorType *ot) | ||||
| ot->poll = ED_operator_outliner_active; | ot->poll = ED_operator_outliner_active; | ||||
| /* flags */ | /* flags */ | ||||
| ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; | ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; | ||||
| } | } | ||||
| /* ******************** Parent Clear Operator *********************** */ | /* ******************** Parent Clear Operator *********************** */ | ||||
| static bool parent_clear_poll(bContext *C, | static bool parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *event) | ||||
| wmDrag *drag, | |||||
| const wmEvent *event, | |||||
| const char **UNUSED(r_tooltip)) | |||||
| { | { | ||||
| SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); | SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); | ||||
| if (!allow_parenting_without_modifier_key(space_outliner)) { | if (!allow_parenting_without_modifier_key(space_outliner)) { | ||||
| if (!event->shift) { | if (!event->shift) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | void OUTLINER_OT_parent_clear(wmOperatorType *ot) | ||||
| ot->poll = ED_operator_outliner_active; | ot->poll = ED_operator_outliner_active; | ||||
| /* flags */ | /* flags */ | ||||
| ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; | ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; | ||||
| } | } | ||||
| /* ******************** Scene Drop Operator *********************** */ | /* ******************** Scene Drop Operator *********************** */ | ||||
| static bool scene_drop_poll(bContext *C, | static bool scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) | ||||
| wmDrag *drag, | |||||
| const wmEvent *event, | |||||
| const char **UNUSED(r_tooltip)) | |||||
| { | { | ||||
| /* Ensure item under cursor is valid drop target */ | /* Ensure item under cursor is valid drop target */ | ||||
| Object *ob = (Object *)WM_drag_get_local_ID(drag, ID_OB); | Object *ob = (Object *)WM_drag_get_local_ID(drag, ID_OB); | ||||
| return (ob && (outliner_ID_drop_find(C, event, ID_SCE) != NULL)); | return (ob && (outliner_ID_drop_find(C, event, ID_SCE) != NULL)); | ||||
| } | } | ||||
| static int scene_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) | static int scene_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | void OUTLINER_OT_scene_drop(wmOperatorType *ot) | ||||
| ot->poll = ED_operator_outliner_active; | ot->poll = ED_operator_outliner_active; | ||||
| /* flags */ | /* flags */ | ||||
| ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; | ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; | ||||
| } | } | ||||
| /* ******************** Material Drop Operator *********************** */ | /* ******************** Material Drop Operator *********************** */ | ||||
| static bool material_drop_poll(bContext *C, | static bool material_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) | ||||
| wmDrag *drag, | |||||
| const wmEvent *event, | |||||
| const char **UNUSED(r_tooltip)) | |||||
| { | { | ||||
| /* Ensure item under cursor is valid drop target */ | /* Ensure item under cursor is valid drop target */ | ||||
| Material *ma = (Material *)WM_drag_get_local_ID(drag, ID_MA); | Material *ma = (Material *)WM_drag_get_local_ID(drag, ID_MA); | ||||
| return (ma && (outliner_ID_drop_find(C, event, ID_OB) != NULL)); | return (ma && (outliner_ID_drop_find(C, event, ID_OB) != NULL)); | ||||
| } | } | ||||
| static int material_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) | static int material_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 204 Lines • ▼ Show 20 Lines | switch (drop_data->drag_tselem->type) { | ||||
| case TSE_GPENCIL_EFFECT: | case TSE_GPENCIL_EFFECT: | ||||
| return ob_parent->type == OB_GPENCIL && ob_dst->type == OB_GPENCIL; | return ob_parent->type == OB_GPENCIL && ob_dst->type == OB_GPENCIL; | ||||
| break; | break; | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| static bool datastack_drop_poll(bContext *C, | static bool datastack_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) | ||||
| wmDrag *drag, | |||||
| const wmEvent *event, | |||||
| const char **r_tooltip) | |||||
| { | { | ||||
| if (drag->type != WM_DRAG_DATASTACK) { | if (drag->type != WM_DRAG_DATASTACK) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); | SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); | ||||
| ARegion *region = CTX_wm_region(C); | ARegion *region = CTX_wm_region(C); | ||||
| bool changed = outliner_flag_set( | bool changed = outliner_flag_set( | ||||
| Show All 20 Lines | switch (drop_data->insert_type) { | ||||
| case TE_INSERT_AFTER: | case TE_INSERT_AFTER: | ||||
| tselem_target->flag |= TSE_DRAG_AFTER; | tselem_target->flag |= TSE_DRAG_AFTER; | ||||
| break; | break; | ||||
| case TE_INSERT_INTO: | case TE_INSERT_INTO: | ||||
| tselem_target->flag |= TSE_DRAG_INTO; | tselem_target->flag |= TSE_DRAG_INTO; | ||||
| break; | break; | ||||
| } | } | ||||
| if (changed) { | |||||
| ED_region_tag_redraw_no_rebuild(region); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| static char *datastack_drop_tooltip(bContext *UNUSED(C), | |||||
| wmDrag *drag, | |||||
| const wmEvent *UNUSED(event)) | |||||
| { | |||||
| StackDropData *drop_data = drag->poin; | |||||
| switch (drop_data->drop_action) { | switch (drop_data->drop_action) { | ||||
| case DATA_STACK_DROP_REORDER: | case DATA_STACK_DROP_REORDER: | ||||
| *r_tooltip = TIP_("Reorder"); | return BLI_strdup(TIP_("Reorder")); | ||||
| break; | break; | ||||
| case DATA_STACK_DROP_COPY: | case DATA_STACK_DROP_COPY: | ||||
| if (drop_data->pchan_parent) { | if (drop_data->pchan_parent) { | ||||
| *r_tooltip = TIP_("Copy to bone"); | return BLI_strdup(TIP_("Copy to bone")); | ||||
| } | } | ||||
| else { | else { | ||||
| *r_tooltip = TIP_("Copy to object"); | return BLI_strdup(TIP_("Copy to object")); | ||||
| } | } | ||||
| break; | break; | ||||
| case DATA_STACK_DROP_LINK: | case DATA_STACK_DROP_LINK: | ||||
| if (drop_data->pchan_parent) { | if (drop_data->pchan_parent) { | ||||
| *r_tooltip = TIP_("Link all to bone"); | return BLI_strdup(TIP_("Link all to bone")); | ||||
| } | } | ||||
| else { | else { | ||||
| *r_tooltip = TIP_("Link all to object"); | return BLI_strdup(TIP_("Link all to object")); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| return NULL; | |||||
| if (changed) { | |||||
| ED_region_tag_redraw_no_rebuild(region); | |||||
| } | |||||
| return true; | |||||
| } | } | ||||
| static void datastack_drop_link(bContext *C, StackDropData *drop_data) | static void datastack_drop_link(bContext *C, StackDropData *drop_data) | ||||
| { | { | ||||
| Main *bmain = CTX_data_main(C); | Main *bmain = CTX_data_main(C); | ||||
| TreeStoreElem *tselem = TREESTORE(drop_data->drop_te); | TreeStoreElem *tselem = TREESTORE(drop_data->drop_te); | ||||
| Object *ob_dst = (Object *)tselem->id; | Object *ob_dst = (Object *)tselem->id; | ||||
| ▲ Show 20 Lines • Show All 239 Lines • ▼ Show 20 Lines | static bool collection_drop_init(bContext *C, | ||||
| data->from = from_collection; | data->from = from_collection; | ||||
| data->to = to_collection; | data->to = to_collection; | ||||
| data->te = te; | data->te = te; | ||||
| data->insert_type = insert_type; | data->insert_type = insert_type; | ||||
| return true; | return true; | ||||
| } | } | ||||
| static bool collection_drop_poll(bContext *C, | static bool collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) | ||||
| wmDrag *drag, | |||||
| const wmEvent *event, | |||||
| const char **r_tooltip) | |||||
| { | { | ||||
| SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); | SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); | ||||
| ARegion *region = CTX_wm_region(C); | ARegion *region = CTX_wm_region(C); | ||||
| bool changed = outliner_flag_set( | bool changed = outliner_flag_set( | ||||
| &space_outliner->tree, TSE_HIGHLIGHTED_ANY | TSE_DRAG_ANY, false); | &space_outliner->tree, TSE_HIGHLIGHTED_ANY | TSE_DRAG_ANY, false); | ||||
| CollectionDrop data; | CollectionDrop data; | ||||
| if (!event->shift && collection_drop_init(C, drag, event, &data)) { | if (!event->shift && collection_drop_init(C, drag, event, &data)) { | ||||
| TreeElement *te = data.te; | TreeElement *te = data.te; | ||||
| TreeStoreElem *tselem = TREESTORE(te); | TreeStoreElem *tselem = TREESTORE(te); | ||||
| if (!data.from || event->ctrl) { | if (!data.from || event->ctrl) { | ||||
| tselem->flag |= TSE_DRAG_INTO; | tselem->flag |= TSE_DRAG_INTO; | ||||
| changed = true; | changed = true; | ||||
| *r_tooltip = TIP_("Link inside Collection"); | |||||
| } | } | ||||
| else { | else { | ||||
| switch (data.insert_type) { | switch (data.insert_type) { | ||||
| case TE_INSERT_BEFORE: | case TE_INSERT_BEFORE: | ||||
| tselem->flag |= TSE_DRAG_BEFORE; | tselem->flag |= TSE_DRAG_BEFORE; | ||||
| changed = true; | changed = true; | ||||
| break; | |||||
| case TE_INSERT_AFTER: | |||||
| tselem->flag |= TSE_DRAG_AFTER; | |||||
| changed = true; | |||||
| break; | |||||
| case TE_INSERT_INTO: { | |||||
| tselem->flag |= TSE_DRAG_INTO; | |||||
| changed = true; | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| if (changed) { | |||||
| ED_region_tag_redraw_no_rebuild(region); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| if (changed) { | |||||
| ED_region_tag_redraw_no_rebuild(region); | |||||
| } | |||||
| return false; | |||||
| } | |||||
| static char *collection_drop_tooltip(bContext *C, wmDrag *drag, const wmEvent *event) | |||||
| { | |||||
| CollectionDrop data; | |||||
| if (!event->shift && collection_drop_init(C, drag, event, &data)) { | |||||
| TreeElement *te = data.te; | |||||
| if (!data.from || event->ctrl) { | |||||
| return BLI_strdup(TIP_("Link inside Collection")); | |||||
| } | |||||
| switch (data.insert_type) { | |||||
| case TE_INSERT_BEFORE: | |||||
| if (te->prev && outliner_is_collection_tree_element(te->prev)) { | if (te->prev && outliner_is_collection_tree_element(te->prev)) { | ||||
| *r_tooltip = TIP_("Move between collections"); | return BLI_strdup(TIP_("Move between collections")); | ||||
| } | } | ||||
| else { | else { | ||||
| *r_tooltip = TIP_("Move before collection"); | return BLI_strdup(TIP_("Move before collection")); | ||||
| } | } | ||||
| break; | break; | ||||
| case TE_INSERT_AFTER: | case TE_INSERT_AFTER: | ||||
| tselem->flag |= TSE_DRAG_AFTER; | |||||
| changed = true; | |||||
| if (te->next && outliner_is_collection_tree_element(te->next)) { | if (te->next && outliner_is_collection_tree_element(te->next)) { | ||||
| *r_tooltip = TIP_("Move between collections"); | return BLI_strdup(TIP_("Move between collections")); | ||||
| } | } | ||||
| else { | else { | ||||
| *r_tooltip = TIP_("Move after collection"); | return BLI_strdup(TIP_("Move after collection")); | ||||
| } | } | ||||
| break; | break; | ||||
| case TE_INSERT_INTO: { | case TE_INSERT_INTO: { | ||||
| tselem->flag |= TSE_DRAG_INTO; | |||||
| changed = true; | |||||
| /* Check the type of the drag IDs to avoid the incorrect "Shift to parent" | /* Check the type of the drag IDs to avoid the incorrect "Shift to parent" | ||||
| * for collections. Checking the type of the first ID works fine here since | * for collections. Checking the type of the first ID works fine here since | ||||
| * all drag IDs are the same type. */ | * all drag IDs are the same type. */ | ||||
| wmDragID *drag_id = (wmDragID *)drag->ids.first; | wmDragID *drag_id = (wmDragID *)drag->ids.first; | ||||
| const bool is_object = (GS(drag_id->id->name) == ID_OB); | const bool is_object = (GS(drag_id->id->name) == ID_OB); | ||||
| if (is_object) { | if (is_object) { | ||||
| *r_tooltip = TIP_("Move inside collection (Ctrl to link, Shift to parent)"); | return BLI_strdup(TIP_("Move inside collection (Ctrl to link, Shift to parent)")); | ||||
| } | |||||
| else { | |||||
| *r_tooltip = TIP_("Move inside collection (Ctrl to link)"); | |||||
| } | } | ||||
| return BLI_strdup(TIP_("Move inside collection (Ctrl to link)")); | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (changed) { | return NULL; | ||||
| ED_region_tag_redraw_no_rebuild(region); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| if (changed) { | |||||
| ED_region_tag_redraw_no_rebuild(region); | |||||
| } | |||||
| return false; | |||||
| } | } | ||||
| static int collection_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) | static int collection_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) | ||||
| { | { | ||||
| Main *bmain = CTX_data_main(C); | Main *bmain = CTX_data_main(C); | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| if (event->custom != EVT_DATA_DRAGDROP) { | if (event->custom != EVT_DATA_DRAGDROP) { | ||||
| ▲ Show 20 Lines • Show All 259 Lines • ▼ Show 20 Lines | |||||
| /* *************************** Drop Boxes ************************** */ | /* *************************** Drop Boxes ************************** */ | ||||
| /* region dropbox definition */ | /* region dropbox definition */ | ||||
| void outliner_dropboxes(void) | void outliner_dropboxes(void) | ||||
| { | { | ||||
| ListBase *lb = WM_dropboxmap_find("Outliner", SPACE_OUTLINER, RGN_TYPE_WINDOW); | ListBase *lb = WM_dropboxmap_find("Outliner", SPACE_OUTLINER, RGN_TYPE_WINDOW); | ||||
| WM_dropbox_add(lb, "OUTLINER_OT_parent_drop", parent_drop_poll, NULL, NULL); | WM_dropbox_add(lb, "OUTLINER_OT_parent_drop", parent_drop_poll, NULL, NULL, NULL); | ||||
| WM_dropbox_add(lb, "OUTLINER_OT_parent_clear", parent_clear_poll, NULL, NULL); | WM_dropbox_add(lb, "OUTLINER_OT_parent_clear", parent_clear_poll, NULL, NULL, NULL); | ||||
| WM_dropbox_add(lb, "OUTLINER_OT_scene_drop", scene_drop_poll, NULL, NULL); | WM_dropbox_add(lb, "OUTLINER_OT_scene_drop", scene_drop_poll, NULL, NULL, NULL); | ||||
| WM_dropbox_add(lb, "OUTLINER_OT_material_drop", material_drop_poll, NULL, NULL); | WM_dropbox_add(lb, "OUTLINER_OT_material_drop", material_drop_poll, NULL, NULL, NULL); | ||||
| WM_dropbox_add(lb, "OUTLINER_OT_datastack_drop", datastack_drop_poll, NULL, NULL); | WM_dropbox_add( | ||||
| WM_dropbox_add(lb, "OUTLINER_OT_collection_drop", collection_drop_poll, NULL, NULL); | lb, "OUTLINER_OT_datastack_drop", datastack_drop_poll, NULL, NULL, datastack_drop_tooltip); | ||||
| WM_dropbox_add(lb, | |||||
| "OUTLINER_OT_collection_drop", | |||||
| collection_drop_poll, | |||||
| NULL, | |||||
| NULL, | |||||
| collection_drop_tooltip); | |||||
| } | } | ||||