NLA Editor: drag in empty region to invoke box-select
authorJacques Lucke <mail@jlucke.com>
Tue, 4 Jun 2019 14:20:30 +0000 (16:20 +0200)
committerJacques Lucke <mail@jlucke.com>
Tue, 4 Jun 2019 14:20:30 +0000 (16:20 +0200)
Reviewers: brecht, billreynish

Differential Revision: https://developer.blender.org/D5010

release/scripts/presets/keyconfig/keymap_data/blender_default.py
source/blender/editors/space_nla/nla_select.c

index ef466c2f3c5b29a80776996c3bf7b0146819c040..8ea69369760962c50e6a482bd636f1f38654c626 100644 (file)
@@ -2029,6 +2029,10 @@ def km_nla_editor(params):
          {"properties": [("axis_range", False)]}),
         ("nla.select_box", {"type": 'B', "value": 'PRESS', "alt": True},
          {"properties": [("axis_range", True)]}),
+        ("nla.select_box", {"type": params.select_tweak, "value": 'ANY'},
+         {"properties": [("tweak", True), ("mode", 'SET')]}),
+        ("nla.select_box", {"type": params.select_tweak, "value": 'ANY', "shift": True},
+         {"properties": [("tweak", True), ("mode", 'ADD')]}),
         ("nla.previewrange_set", {"type": 'P', "value": 'PRESS', "ctrl": True, "alt": True}, None),
         ("nla.view_all", {"type": 'HOME', "value": 'PRESS'}, None),
         ("nla.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
index eecb17cc185c8a6a7d92761f6b992676b8f3b6f9..1abf1a6426393ccd77b7242de8eb5a7e2ae0ecad 100644 (file)
@@ -278,6 +278,78 @@ static void box_select_nla_strips(bAnimContext *ac, rcti rect, short mode, short
 
 /* ------------------- */
 
+static void nlaedit_strip_at_region_position(
+    bAnimContext *ac, float region_x, float region_y, bAnimListElem **r_ale, NlaStrip **r_strip)
+{
+  *r_ale = NULL;
+  *r_strip = NULL;
+
+  SpaceNla *snla = (SpaceNla *)ac->sl;
+  View2D *v2d = &ac->ar->v2d;
+
+  float view_x, view_y;
+  int channel_index;
+  UI_view2d_region_to_view(v2d, region_x, region_y, &view_x, &view_y);
+  UI_view2d_listview_view_to_cell(
+      0, NLACHANNEL_STEP(snla), 0, NLACHANNEL_FIRST_TOP(ac), view_x, view_y, NULL, &channel_index);
+
+  ListBase anim_data = {NULL, NULL};
+  int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+  /* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click
+   * (that is the size of keyframe icons, so user should be expecting similar tolerances)
+   */
+  float xmin = UI_view2d_region_to_view_x(v2d, region_x - 7);
+  float xmax = UI_view2d_region_to_view_x(v2d, region_x + 7);
+
+  bAnimListElem *ale = BLI_findlink(&anim_data, channel_index);
+  if (ale != NULL) {
+    if (ale->type == ANIMTYPE_NLATRACK) {
+      NlaTrack *nlt = (NlaTrack *)ale->data;
+
+      for (NlaStrip *strip = nlt->strips.first; strip; strip = strip->next) {
+        if (BKE_nlastrip_within_bounds(strip, xmin, xmax)) {
+          *r_ale = ale;
+          *r_strip = strip;
+
+          BLI_remlink(&anim_data, ale);
+        }
+      }
+    }
+  }
+
+  ANIM_animdata_freelist(&anim_data);
+}
+
+static bool nlaedit_mouse_is_over_strip(bAnimContext *ac, const int mval[2])
+{
+  bAnimListElem *ale;
+  NlaStrip *strip;
+  nlaedit_strip_at_region_position(ac, mval[0], mval[1], &ale, &strip);
+
+  if (ale != NULL) {
+    BLI_assert(strip != NULL);
+    MEM_freeN(ale);
+    return true;
+  }
+  return false;
+}
+
+static int nlaedit_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+  bAnimContext ac;
+  if (ANIM_animdata_get_context(C, &ac) == 0) {
+    return OPERATOR_CANCELLED;
+  }
+
+  bool tweak = RNA_boolean_get(op->ptr, "tweak");
+  if (tweak && nlaedit_mouse_is_over_strip(&ac, event->mval)) {
+    return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+  }
+  return WM_gesture_box_invoke(C, op, event);
+}
+
 static int nlaedit_box_select_exec(bContext *C, wmOperator *op)
 {
   bAnimContext ac;
@@ -335,7 +407,7 @@ void NLA_OT_select_box(wmOperatorType *ot)
   ot->description = "Use box selection to grab NLA-Strips";
 
   /* api callbacks */
-  ot->invoke = WM_gesture_box_invoke;
+  ot->invoke = nlaedit_box_select_invoke;
   ot->exec = nlaedit_box_select_exec;
   ot->modal = WM_gesture_box_modal;
   ot->cancel = WM_gesture_box_cancel;
@@ -348,6 +420,10 @@ void NLA_OT_select_box(wmOperatorType *ot)
   /* properties */
   RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
 
+  PropertyRNA *prop = RNA_def_boolean(
+      ot->srna, "tweak", 0, "Tweak", "Operator has been activated using a tweak event");
+  RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
   WM_operator_properties_gesture_box(ot);
   WM_operator_properties_select_operation_simple(ot);
 }
@@ -524,57 +600,11 @@ void NLA_OT_select_leftright(wmOperatorType *ot)
 static void mouse_nla_strips(
     bContext *C, bAnimContext *ac, const int mval[2], short select_mode, const bool deselect_all)
 {
-  ListBase anim_data = {NULL, NULL};
-  bAnimListElem *ale = NULL;
-  int filter;
-
-  SpaceNla *snla = (SpaceNla *)ac->sl;
-  View2D *v2d = &ac->ar->v2d;
   Scene *scene = ac->scene;
-  NlaStrip *strip = NULL;
-  int channel_index;
-  float xmin, xmax;
-  float x, y;
-
-  /* use View2D to determine the index of the channel
-   * (i.e a row in the list) where keyframe was */
-  UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
-  UI_view2d_listview_view_to_cell(
-      0, NLACHANNEL_STEP(snla), 0, NLACHANNEL_FIRST_TOP(ac), x, y, NULL, &channel_index);
-
-  /* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click
-   * (that is the size of keyframe icons, so user should be expecting similar tolerances)
-   */
-  xmin = UI_view2d_region_to_view_x(v2d, mval[0] - 7);
-  xmax = UI_view2d_region_to_view_x(v2d, mval[0] + 7);
 
-  /* filter data */
-  filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
-  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
-
-  /* try to get channel */
-  ale = BLI_findlink(&anim_data, channel_index);
-  if (ale != NULL) {
-    /* found some channel - we only really should do something when its an Nla-Track */
-    if (ale->type == ANIMTYPE_NLATRACK) {
-      NlaTrack *nlt = (NlaTrack *)ale->data;
-
-      /* loop over NLA-strips in this track,
-       * trying to find one which occurs in the necessary bounds */
-      for (strip = nlt->strips.first; strip; strip = strip->next) {
-        if (BKE_nlastrip_within_bounds(strip, xmin, xmax)) {
-          break;
-        }
-      }
-    }
-
-    /* remove active channel from list of channels for separate treatment
-     * (since it's needed later on) */
-    BLI_remlink(&anim_data, ale);
-  }
-
-  /* free list of channels, since it's not used anymore */
-  ANIM_animdata_freelist(&anim_data);
+  bAnimListElem *ale = NULL;
+  NlaStrip *strip = NULL;
+  nlaedit_strip_at_region_position(ac, mval[0], mval[1], &ale, &strip);
 
   /* if currently in tweakmode, exit tweakmode before changing selection states
    * now that we've found our target...
@@ -618,6 +648,8 @@ static void mouse_nla_strips(
           NlaTrack *nlt = (NlaTrack *)ale->data;
 
           nlt->flag |= NLATRACK_SELECTED;
+          int filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE |
+                       ANIMFILTER_LIST_CHANNELS;
           ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK);
         }
       }