[Bf-blender-cvs] [6a8cac16ada] temp-soc-2019-outliner-sync: Outliner: walk navigation operator

Nathan Craddock noreply at git.blender.org
Fri Aug 9 06:02:02 CEST 2019


Commit: 6a8cac16ada9220ef070ffb109852932b4209730
Author: Nathan Craddock
Date:   Thu Aug 8 22:00:57 2019 -0600
Branches: temp-soc-2019-outliner-sync
https://developer.blender.org/rB6a8cac16ada9220ef070ffb109852932b4209730

Outliner: walk navigation operator

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 walk in and out or open and close
elements if the elements are open or closed.

Also moves opencolose toggling to the openclose operator to
remove duplicate code.

Also allows click+drag for openclose of element subtrees.

The outliner tree building is tweaked slightly to set the proper
parents in scene display mode for walk select to function
correctly.

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

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 fc0a00ae31e..f70c4cc9175 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..e0c57fabc73 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -140,59 +140,120 @@ 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 */
+bool outliner_item_openclose(TreeElement *te, bool toggle_all)
 {
+  TreeStoreElem *tselem = TREESTORE(te);
 
-  if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
-    TreeStoreElem *tselem = TREESTORE(te);
+  if (toggle_all) {
+    /* Open all children if this element is closed, or if any children are closed */
+    const bool open = (tselem->flag & TSE_CLOSED) ||
+                      (outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1));
 
-    /* all below close/open? */
-    if (all) {
+    if (open) {
       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;
-      }
+      tselem->flag |= TSE_CLOSED;
     }
 
-    return 1;
-  }
+    outliner_flag_set(&te->subtree, TSE_CLOSED, !open);
 
-  for (te = te->subtree.first; te; te = te->next) {
-    if (do_outliner_item_openclose(C, soops, te, all, mval)) {
-      return 1;
+    return true;
+  }
+  else {
+    if (tselem->flag & TSE_CLOSED) {
+      tselem->flag &= ~TSE_CLOSED;
+    }
+    else {
+      tselem->flag |= TSE_CLOSED;
     }
+
+    return true;
   }
-  return 0;
+
+  return false;
 }
 
-/* event can enterkey, then it opens/closes */
-static int outliner_item_openclose(bContext *C, wmOperator *op, const wmEvent *event)
+typedef struct OpenCloseData {
+  TreeStoreElem *prev_tselem;
+  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);
-  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]);
+  float view_mval[2];
+  UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
 
-  for (te = soops->tree.first; te; te = te->next) {
-    if (do_outliner_item_openclose(C, soops, te, all, fmval)) {
-      break;
+  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) {
+        if (outliner_item_openclose(te, false)) {
+          ED_region_tag_redraw(ar);
+        }
+      }
+    }
+
+    if (te) {
+      data->prev_tselem = TREESTORE(te);
+    }
+    else {
+      data->prev_tselem = NULL;
     }
   }
+  else if (event->val == KM_RELEASE) {
+    MEM_freeN(op->customdata);
 
-  ED_region_tag_redraw(ar);
+    return OPERATOR_FINISHED;
+  }
 
-  return OPERATOR_FINISHED;
+  return OPERATOR_RUNNING_MODAL;
+}
+
+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);
+
+  const bool toggle_all = RNA_boolean_get(op->ptr, "all");
+
+  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])) {
+    outliner_item_openclose(te, toggle_all);
+    ED_region_tag_redraw(ar);
+
+    /* Only toggle once for single click toggling */
+    if (event->type == LEFTMOUSE) {
+      return OPERATOR_FINISHED;
+    }
+
+    /* Store last expanded tselem and x coordinate of disclosure triangle */
+    OpenCloseData *toggle_data = MEM_callocN(sizeof(OpenCloseData), "open_close_data");
+    toggle_data->prev_tselem = TREESTORE(te);
+    toggle_data->x_location = te->xs;
+
+    /* 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 +262,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..2dc0276e9a3 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);
 
+bool outliner_item_openclose(TreeElement *te, 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/spac

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list