[Bf-blender-cvs] [252fb489973] master: Outliner: walk navigation operator and openclose fixes

Nathan Craddock noreply at git.blender.org
Fri Aug 16 20:31:47 CEST 2019


Commit: 252fb4899735ca154cae9147be819f2362f2ba51
Author: Nathan Craddock
Date:   Thu Aug 8 22:00:57 2019 -0600
Branches: master
https://developer.blender.org/rB252fb4899735ca154cae9147be819f2362f2ba51

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.

===================================================================

M	release/scripts/presets/keyconfig/keymap_data/blender_default.py
M	source/blender/editors/space_outliner/outliner_edit.c
M	source/blender/editors/space_outliner/outliner_intern.h
M	source/blender/editors/space_outliner/outliner_ops.c
M	source/blender/editors/space_outliner/outliner_select.c
M	source/blender/editors/space_outliner/outliner_tree.c
M	source/blender/editors/space_outliner/outliner_utils.c
M	source/blender/editors/space_outliner/space_outliner.c
M	source/blender/makesdna/DNA_outliner_types.h

===================================================================

diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 3f6a5f0a514..798bdc1fe01 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -709,11 +709,24 @@ def km_outliner(params):
         ("outliner.item_activate", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True, "ctrl": True},
          {"properties": [("extend", True), ("recursive", True)]}),
         ("outliner.select_box", {"type": 'B', "value": 'PRESS'}, None),
-        ("outliner.item_openclose", {"type": 'RET', "value": 'PRESS'},
+        ("outliner.select_walk", {"type": 'UP_ARROW', "value": 'PRESS'}, {"properties": [("direction", 'UP')]}),
+        ("outliner.select_walk", {"type": 'UP_ARROW', "value": 'PRESS', "shift": True},
+         {"properties": [("direction", 'UP'), ("extend", True)]}),
+        ("outliner.select_walk", {"type": 'DOWN_ARROW', "value": 'PRESS'}, {"properties": [("direction", 'DOWN')]}),
+        ("outliner.select_walk", {"type": 'DOWN_ARROW', "value": 'PRESS', "shift": True},
+         {"properties": [("direction", 'DOWN'), ("extend", True)]}),
+        ("outliner.select_walk", {"type": 'LEFT_ARROW', "value": 'PRESS'}, {"properties": [("direction", 'LEFT')]}),
+        ("outliner.select_walk", {"type": 'LEFT_ARROW', "value": 'PRESS', "shift": True},
+         {"properties": [("direction", 'LEFT'), ("toggle_all", True)]}),
+        ("outliner.select_walk", {"type": 'RIGHT_ARROW', "value": 'PRESS'}, {"properties": [("direction", 'RIGHT')]}),
+        ("outliner.select_walk", {"type": 'RIGHT_ARROW', "value": 'PRESS', "shift": True},
+         {"properties": [("direction", 'RIGHT'), ("toggle_all", True)]}),
+        ("outliner.item_openclose", {"type": 'LEFTMOUSE', "value": 'CLICK'},
          {"properties": [("all", False)]}),
-        ("outliner.item_openclose", {"type": 'RET', "value": 'PRESS', "shift": True},
+        ("outliner.item_openclose", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True},
          {"properties": [("all", True)]}),
-        ("outliner.item_rename", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True}, None),
+        ("outliner.item_openclose", {"type": 'EVT_TWEAK_L', "value": 'ANY'},
+         {"properties": [("all", False)]}),
         ("outliner.operation", {"type": 'RIGHTMOUSE', "value": 'PRESS'}, None),
         ("outliner.item_drag_drop", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, None),
         ("outliner.item_drag_drop", {"type": 'EVT_TWEAK_L', "value": 'ANY', "shift": True}, None),
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");
 }
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 72cd8dc6424..e37f3519653 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -50,6 +50,14 @@ typedef enum TreeElementInsertType {
   TE_INSERT_INTO,
 } TreeElementInsertType;
 
+/* Use generic walk select after D4771 is committed */
+typedef enum WalkSelectDirection {
+  OUTLINER_SELECT_WALK_UP,
+  OUTLINER_SELECT_WALK_DOWN,
+  OUTLINER_SELECT_WALK_LEFT,
+  OUTLINER_SELECT_WALK_RIGHT,
+} WalkSelectDirection;
+
 typedef enum TreeTraversalAction {
   /* Continue traversal regularly, don't skip children. */
   TRAVERSE_CONTINUE = 0,
@@ -346,6 +354,8 @@ void item_object_mode_exit_cb(struct bContext *C,
 
 void outliner_set_coordinates(struct ARegion *ar, struct SpaceOutliner *soops);
 
+void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all);
+
 /* outliner_dragdrop.c */
 void outliner_dropboxes(void);
 
@@ -373,6 +383,7 @@ void OUTLINER_OT_show_active(struct wmOperatorType *ot);
 void OUTLINER_OT_show_hierarchy(struct wmOperatorType *ot);
 
 void OUTLINER_OT_select_box(struct wmOperatorType *ot);
+void OUTLINER_OT_select_walk(struct wmOperatorType *ot);
 
 void OUTLINER_OT_select_all(struct wmOperatorType *ot);
 void OUTLINER_OT_expanded_toggle(struct wmOperatorType *ot);
@@ -470,6 +481,9 @@ bool outliner_tree_traverse(const SpaceOutliner *soops,
                             TreeTraversalFunc func,
                             void *customdata);
 float outliner_restrict_columns_width(const struct SpaceOutliner *soops);
+TreeElement *outliner_find_element_with_flag(const ListBase *lb, short flag);
+bool outliner_is_element_visible(const TreeElement *te);
+void outliner_scroll_view(struct ARegion *ar, int delta_y);
 
 /* outliner_sync.c ---------------------------------------------- */
 
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index f155a2d5f89..4b57d4ad771 100644
--- a/source/b

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list