diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-08-07 11:23:07 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-08-10 18:53:00 +0300 |
commit | 367ada71a0d1fab75701c30895726e3f7f315f3a (patch) | |
tree | d9b68427c64ae0f4041018688f0b9352c1689cec /source/blender/editors/space_outliner/outliner_ops.c | |
parent | 71bd30d8c02ab5670902f8955d24a5c127d76108 (diff) |
Cleanup: move most outliner drag & drop code into one file.
Diffstat (limited to 'source/blender/editors/space_outliner/outliner_ops.c')
-rw-r--r-- | source/blender/editors/space_outliner/outliner_ops.c | 347 |
1 files changed, 0 insertions, 347 deletions
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index 576038979d3..a4aad11a821 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -55,353 +55,6 @@ #include "outliner_intern.h" -typedef struct OutlinerDragDropTooltip { - TreeElement *te; - void *handle; -} OutlinerDragDropTooltip; - -enum { - OUTLINER_ITEM_DRAG_CANCEL, - OUTLINER_ITEM_DRAG_CONFIRM, -}; - -static bool outliner_item_drag_drop_poll(bContext *C) -{ - SpaceOops *soops = CTX_wm_space_outliner(C); - return ED_operator_outliner_active(C) && - /* Only collection display modes supported for now. Others need more design work */ - ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_LIBRARIES); -} - -static TreeElement *outliner_item_drag_element_find(SpaceOops *soops, ARegion *ar, const wmEvent *event) -{ - /* note: using EVT_TWEAK_ events to trigger dragging is fine, - * it sends coordinates from where dragging was started */ - const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]); - return outliner_find_item_at_y(soops, &soops->tree, my); -} - -static void outliner_item_drag_end(wmWindow *win, OutlinerDragDropTooltip *data) -{ - MEM_SAFE_FREE(data->te->drag_data); - - if (data->handle) { - WM_draw_cb_exit(win, data->handle); - } - - MEM_SAFE_FREE(data); -} - -static void outliner_item_drag_get_insert_data( - const SpaceOops *soops, ARegion *ar, const wmEvent *event, TreeElement *te_dragged, - TreeElement **r_te_insert_handle, TreeElementInsertType *r_insert_type) -{ - TreeElement *te_hovered; - float view_mval[2]; - - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]); - te_hovered = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]); - - if (te_hovered) { - /* mouse hovers an element (ignoring x-axis), now find out how to insert the dragged item exactly */ - - if (te_hovered == te_dragged) { - *r_te_insert_handle = te_dragged; - } - else if (te_hovered != te_dragged) { - const float margin = UI_UNIT_Y * (1.0f / 4); - - *r_te_insert_handle = te_hovered; - if (view_mval[1] < (te_hovered->ys + margin)) { - if (TSELEM_OPEN(TREESTORE(te_hovered), soops)) { - /* inserting after a open item means we insert into it, but as first child */ - if (BLI_listbase_is_empty(&te_hovered->subtree)) { - *r_insert_type = TE_INSERT_INTO; - } - else { - *r_insert_type = TE_INSERT_BEFORE; - *r_te_insert_handle = te_hovered->subtree.first; - } - } - else { - *r_insert_type = TE_INSERT_AFTER; - } - } - else if (view_mval[1] > (te_hovered->ys + (3 * margin))) { - *r_insert_type = TE_INSERT_BEFORE; - } - else { - *r_insert_type = TE_INSERT_INTO; - } - } - } - else { - /* mouse doesn't hover any item (ignoring x-axis), so it's either above list bounds or below. */ - - TreeElement *first = soops->tree.first; - TreeElement *last = soops->tree.last; - - if (view_mval[1] < last->ys) { - *r_te_insert_handle = last; - *r_insert_type = TE_INSERT_AFTER; - } - else if (view_mval[1] > (first->ys + UI_UNIT_Y)) { - *r_te_insert_handle = first; - *r_insert_type = TE_INSERT_BEFORE; - } - else { - BLI_assert(0); - } - } -} - -static void outliner_item_drag_handle( - SpaceOops *soops, ARegion *ar, const wmEvent *event, TreeElement *te_dragged) -{ - TreeElement *te_insert_handle; - TreeElementInsertType insert_type; - - outliner_item_drag_get_insert_data(soops, ar, event, te_dragged, &te_insert_handle, &insert_type); - - if (!te_dragged->reinsert_poll && - /* there is no reinsert_poll, so we do some generic checks (same types and reinsert callback is available) */ - (TREESTORE(te_dragged)->type == TREESTORE(te_insert_handle)->type) && - te_dragged->reinsert) - { - /* pass */ - } - else if (te_dragged == te_insert_handle) { - /* nothing will happen anyway, no need to do poll check */ - } - else if (!te_dragged->reinsert_poll || - !te_dragged->reinsert_poll(te_dragged, &te_insert_handle, &insert_type)) - { - te_insert_handle = NULL; - } - te_dragged->drag_data->insert_type = insert_type; - te_dragged->drag_data->insert_handle = te_insert_handle; -} - -/** - * Returns true if it is a collection and empty. - */ -static bool is_empty_collection(TreeElement *te) -{ - Collection *collection = outliner_collection_from_tree_element(te); - - if (!collection) { - return false; - } - - return BLI_listbase_is_empty(&collection->gobject) && - BLI_listbase_is_empty(&collection->children); -} - -static bool outliner_item_drag_drop_apply( - Main *bmain, - Scene *scene, - SpaceOops *soops, - OutlinerDragDropTooltip *data, - const wmEvent *event) -{ - TreeElement *dragged_te = data->te; - TreeElement *insert_handle = dragged_te->drag_data->insert_handle; - TreeElementInsertType insert_type = dragged_te->drag_data->insert_type; - - if ((insert_handle == dragged_te) || !insert_handle) { - /* No need to do anything */ - } - else if (dragged_te->reinsert) { - BLI_assert(!dragged_te->reinsert_poll || dragged_te->reinsert_poll(dragged_te, &insert_handle, - &insert_type)); - /* call of assert above should not have changed insert_handle and insert_type at this point */ - BLI_assert(dragged_te->drag_data->insert_handle == insert_handle && - dragged_te->drag_data->insert_type == insert_type); - - /* If the collection was just created and you moved objects/collections inside it, - * it is strange to have it closed and we not see the newly dragged elements. */ - const bool should_open_collection = (insert_type == TE_INSERT_INTO) && is_empty_collection(insert_handle); - - dragged_te->reinsert(bmain, scene, soops, dragged_te, insert_handle, insert_type, event); - - if (should_open_collection && !is_empty_collection(insert_handle)) { - TREESTORE(insert_handle)->flag &= ~TSE_CLOSED; - } - return true; - } - - return false; -} - -static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEvent *event) -{ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ARegion *ar = CTX_wm_region(C); - SpaceOops *soops = CTX_wm_space_outliner(C); - OutlinerDragDropTooltip *data = op->customdata; - TreeElement *te_dragged = data->te; - int retval = OPERATOR_RUNNING_MODAL; - bool redraw = false; - bool skip_rebuild = true; - - switch (event->type) { - case EVT_MODAL_MAP: - if (event->val == OUTLINER_ITEM_DRAG_CONFIRM) { - if (outliner_item_drag_drop_apply(bmain, scene, soops, data, event)) { - skip_rebuild = false; - } - retval = OPERATOR_FINISHED; - } - else if (event->val == OUTLINER_ITEM_DRAG_CANCEL) { - retval = OPERATOR_CANCELLED; - } - else { - BLI_assert(0); - } - WM_event_add_mousemove(C); /* update highlight */ - outliner_item_drag_end(CTX_wm_window(C), data); - redraw = true; - break; - case MOUSEMOVE: - outliner_item_drag_handle(soops, ar, event, te_dragged); - redraw = true; - break; - } - - if (redraw) { - if (skip_rebuild) { - ED_region_tag_redraw_no_rebuild(ar); - } - else { - ED_region_tag_redraw(ar); - } - } - - return retval; -} - -static const char *outliner_drag_drop_tooltip_get( - const TreeElement *te_float) -{ - const char *name = NULL; - - const TreeElement *te_insert = te_float->drag_data->insert_handle; - if (te_float && outliner_is_collection_tree_element(te_float)) { - if (te_insert == NULL) { - name = TIP_("Move collection"); - } - else { - switch (te_float->drag_data->insert_type) { - case TE_INSERT_BEFORE: - if (te_insert->prev && outliner_is_collection_tree_element(te_insert->prev)) { - name = TIP_("Move between collections"); - } - else { - name = TIP_("Move before collection"); - } - break; - case TE_INSERT_AFTER: - if (te_insert->next && outliner_is_collection_tree_element(te_insert->next)) { - name = TIP_("Move between collections"); - } - else { - name = TIP_("Move after collection"); - } - break; - case TE_INSERT_INTO: - name = TIP_("Move inside collection"); - break; - } - } - } - else if ((TREESTORE(te_float)->type == 0) && (te_float->idcode == ID_OB)) { - name = TIP_("Move to collection (Ctrl to link)"); - } - - return name; -} - -static void outliner_drag_drop_tooltip_cb(const wmWindow *win, void *vdata) -{ - OutlinerDragDropTooltip *data = vdata; - const char *tooltip; - - int cursorx, cursory; - int x, y; - - tooltip = outliner_drag_drop_tooltip_get(data->te); - if (tooltip == NULL) { - return; - } - - cursorx = win->eventstate->x; - cursory = win->eventstate->y; - - x = cursorx + U.widget_unit; - y = cursory - U.widget_unit; - - /* Drawing. */ - const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; - - const float col_fg[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - const float col_bg[4] = {0.0f, 0.0f, 0.0f, 0.2f}; - - GPU_blend(true); - UI_fontstyle_draw_simple_backdrop(fstyle, x, y, tooltip, col_fg, col_bg); - GPU_blend(false); -} - -static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - ARegion *ar = CTX_wm_region(C); - SpaceOops *soops = CTX_wm_space_outliner(C); - TreeElement *te_dragged = outliner_item_drag_element_find(soops, ar, event); - - if (!te_dragged) { - return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH); - } - - OutlinerDragDropTooltip *data = MEM_mallocN(sizeof(OutlinerDragDropTooltip), __func__); - data->te = te_dragged; - - op->customdata = data; - te_dragged->drag_data = MEM_callocN(sizeof(*te_dragged->drag_data), __func__); - /* by default we don't change the item position */ - te_dragged->drag_data->insert_handle = te_dragged; - /* unset highlighted tree element, dragged one will be highlighted instead */ - outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED, false); - - ED_region_tag_redraw_no_rebuild(ar); - - WM_event_add_modal_handler(C, op); - - data->handle = WM_draw_cb_activate(CTX_wm_window(C), outliner_drag_drop_tooltip_cb, data); - - return OPERATOR_RUNNING_MODAL; -} - -/** - * Notes about Outliner Item Drag 'n Drop: - * Right now only collections display mode is supported. But ideally all/most modes would support this. There are - * just some open design questions that have to be answered: do we want to allow mixing order of different data types - * (like render-layers and objects)? Would that be a purely visual change or would that have any other effect? ... - */ -static void OUTLINER_OT_item_drag_drop(wmOperatorType *ot) -{ - ot->name = "Drag and Drop"; - ot->idname = "OUTLINER_OT_item_drag_drop"; - ot->description = "Change the hierarchical position of an item by repositioning it using drag and drop"; - - ot->invoke = outliner_item_drag_drop_invoke; - ot->modal = outliner_item_drag_drop_modal; - - ot->poll = outliner_item_drag_drop_poll; - - ot->flag = OPTYPE_UNDO; -} - - /* ************************** registration **********************************/ void outliner_operatortypes(void) |