diff options
author | Nathan Craddock <nzcraddock@gmail.com> | 2019-08-09 07:00:57 +0300 |
---|---|---|
committer | Nathan Craddock <nzcraddock@gmail.com> | 2019-08-16 21:30:54 +0300 |
commit | 252fb4899735ca154cae9147be819f2362f2ba51 (patch) | |
tree | fd8f9ef96ebb5b21528657d3a1c527221b2e2027 /source/blender/editors/space_outliner/outliner_edit.c | |
parent | eb92ac05d6f850ccdbc0ed636763669f5d1e765e (diff) |
Outliner: walk navigation operator and openclose fixes
Adds a keyboard walk navigation and selection operator to the
outliner. Up and down arrow keys walk up and down the list of
elements, and left and right will open and close elements if
the elements are closed or opened respectively. Holding shift
while walking up and down the tree expands the selection.
Holding shift while clicking or pressing left and right arrows
will expand or collapse all children elements recursively.
Pressing enter to openclose the hovered element is removed.
Also allows click+drag for openclose of element subtrees.
This moves openclose toggling to the openclose operator to
remove duplicate code. The outliner tree building is tweaked
slightly to set the proper parents in scene display mode for walk
select to walk to parents without errors.
Diffstat (limited to 'source/blender/editors/space_outliner/outliner_edit.c')
-rw-r--r-- | source/blender/editors/space_outliner/outliner_edit.c | 122 |
1 files changed, 86 insertions, 36 deletions
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 842502ec82f..60b5dbdfc50 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -140,59 +140,108 @@ void OUTLINER_OT_highlight_update(wmOperatorType *ot) /* Toggle Open/Closed ------------------------------------------- */ -static int do_outliner_item_openclose( - bContext *C, SpaceOutliner *soops, TreeElement *te, const bool all, const float mval[2]) +/* Open or close a tree element, optionally toggling all children recursively */ +void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all) { + TreeStoreElem *tselem = TREESTORE(te); - if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) { - TreeStoreElem *tselem = TREESTORE(te); + if (open) { + tselem->flag &= ~TSE_CLOSED; + } + else { + tselem->flag |= TSE_CLOSED; + } - /* all below close/open? */ - if (all) { - tselem->flag &= ~TSE_CLOSED; - outliner_flag_set( - &te->subtree, TSE_CLOSED, !outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1)); - } - else { - if (tselem->flag & TSE_CLOSED) { - tselem->flag &= ~TSE_CLOSED; - } - else { - tselem->flag |= TSE_CLOSED; + if (toggle_all) { + outliner_flag_set(&te->subtree, TSE_CLOSED, !open); + } +} + +typedef struct OpenCloseData { + TreeStoreElem *prev_tselem; + bool open; + int x_location; +} OpenCloseData; + +static int outliner_item_openclose_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + SpaceOutliner *soops = CTX_wm_space_outliner(C); + + float view_mval[2]; + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]); + + if (event->type == MOUSEMOVE) { + TreeElement *te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]); + + OpenCloseData *data = (OpenCloseData *)op->customdata; + + /* Only openclose if mouse is not over the previously toggled element */ + if (te && TREESTORE(te) != data->prev_tselem) { + + /* Only toggle openclose on the same level as the first clicked element */ + if (te->xs == data->x_location) { + outliner_item_openclose(te, data->open, false); + ED_region_tag_redraw(ar); } } - return 1; + if (te) { + data->prev_tselem = TREESTORE(te); + } + else { + data->prev_tselem = NULL; + } } + else if (event->val == KM_RELEASE) { + MEM_freeN(op->customdata); - for (te = te->subtree.first; te; te = te->next) { - if (do_outliner_item_openclose(C, soops, te, all, mval)) { - return 1; - } + return OPERATOR_FINISHED; } - return 0; + + return OPERATOR_RUNNING_MODAL; } -/* event can enterkey, then it opens/closes */ -static int outliner_item_openclose(bContext *C, wmOperator *op, const wmEvent *event) +static int outliner_item_openclose_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); SpaceOutliner *soops = CTX_wm_space_outliner(C); - TreeElement *te; - float fmval[2]; - const bool all = RNA_boolean_get(op->ptr, "all"); - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); + const bool toggle_all = RNA_boolean_get(op->ptr, "all"); - for (te = soops->tree.first; te; te = te->next) { - if (do_outliner_item_openclose(C, soops, te, all, fmval)) { - break; + float view_mval[2]; + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]); + + TreeElement *te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]); + + if (te && outliner_item_is_co_within_close_toggle(te, view_mval[0])) { + TreeStoreElem *tselem = TREESTORE(te); + + const bool open = (tselem->flag & TSE_CLOSED) || + (toggle_all && (outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1))); + + outliner_item_openclose(te, open, toggle_all); + ED_region_tag_redraw(ar); + + /* Only toggle once for single click toggling */ + if (event->type == LEFTMOUSE) { + return OPERATOR_FINISHED; } - } - ED_region_tag_redraw(ar); + /* Store last expanded tselem and x coordinate of disclosure triangle */ + OpenCloseData *toggle_data = MEM_callocN(sizeof(OpenCloseData), "open_close_data"); + toggle_data->prev_tselem = tselem; + toggle_data->open = open; + toggle_data->x_location = te->xs; - return OPERATOR_FINISHED; + /* Store the first clicked on element */ + op->customdata = toggle_data; + + WM_event_add_modal_handler(C, op); + return OPERATOR_RUNNING_MODAL; + } + + return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; } void OUTLINER_OT_item_openclose(wmOperatorType *ot) @@ -201,11 +250,12 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot) ot->idname = "OUTLINER_OT_item_openclose"; ot->description = "Toggle whether item under cursor is enabled or closed"; - ot->invoke = outliner_item_openclose; + ot->invoke = outliner_item_openclose_invoke; + ot->modal = outliner_item_openclose_modal; ot->poll = ED_operator_outliner_active; - RNA_def_boolean(ot->srna, "all", 1, "All", "Close or open all items"); + RNA_def_boolean(ot->srna, "all", false, "All", "Close or open all items"); } /* -------------------------------------------------------------------- */ |