[Bf-blender-cvs] [b79976a9bd9] master: Dopesheet: drag to box select in dopesheet
Jacques Lucke
noreply at git.blender.org
Wed Jun 5 15:51:39 CEST 2019
Commit: b79976a9bd94dc372bb8f215c766d4ef03d67bcb
Author: Jacques Lucke
Date: Wed Jun 5 15:48:30 2019 +0200
Branches: master
https://developer.blender.org/rBb79976a9bd94dc372bb8f215c766d4ef03d67bcb
Dopesheet: drag to box select in dopesheet
This includes refactoring of the `mouse_action_keys` to
make it easier to just detect if there is a key under
the mouse. The refactoring mostly consists of extracting
methods and reducing vertical scope of variables.
Reviewers: billreynish, brecht
Differential Revision: https://developer.blender.org/D5024
===================================================================
M release/scripts/presets/keyconfig/keymap_data/blender_default.py
M source/blender/editors/space_action/action_select.c
===================================================================
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 2a803c2284a..d940e81980d 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -1894,6 +1894,10 @@ def km_dopesheet(params):
{"properties": [("axis_range", False)]}),
("action.select_box", {"type": 'B', "value": 'PRESS', "alt": True},
{"properties": [("axis_range", True)]}),
+ ("action.select_box", {"type": params.select_tweak, "value": 'ANY'},
+ {"properties": [("tweak", True), ("mode", 'SET')]}),
+ ("action.select_box", {"type": params.select_tweak, "value": 'ANY', "shift": True},
+ {"properties": [("tweak", True), ("mode", 'ADD')]}),
("action.select_lasso", {"type": params.action_tweak, "value": 'ANY', "ctrl": True},
{"properties": [("mode", 'ADD')]}),
("action.select_lasso", {"type": params.action_tweak, "value": 'ANY', "shift": True, "ctrl": True},
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 3560b0e1c7a..fc2970f4c31 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -66,6 +66,163 @@
/* ************************************************************************** */
/* KEYFRAMES STUFF */
+static bAnimListElem *actkeys_find_list_element_at_position(bAnimContext *ac,
+ int filter,
+ float region_x,
+ float region_y)
+{
+ 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, ACHANNEL_STEP(ac), 0, ACHANNEL_FIRST_TOP(ac), view_x, view_y, NULL, &channel_index);
+
+ ListBase anim_data = {NULL, NULL};
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ bAnimListElem *ale = BLI_findlink(&anim_data, channel_index);
+ if (ale != NULL) {
+ BLI_remlink(&anim_data, ale);
+ ale->next = ale->prev = NULL;
+ }
+ ANIM_animdata_freelist(&anim_data);
+
+ return ale;
+}
+
+static void actkeys_list_element_to_keylist(bAnimContext *ac,
+ DLRBT_Tree *anim_keys,
+ bAnimListElem *ale)
+{
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ bDopeSheet *ads = NULL;
+ if (ELEM(ac->datatype, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE)) {
+ ads = ac->data;
+ }
+
+ if (ale->key_data) {
+ switch (ale->datatype) {
+ case ALE_SCE: {
+ Scene *scene = (Scene *)ale->key_data;
+ scene_to_keylist(ads, scene, anim_keys, 0);
+ break;
+ }
+ case ALE_OB: {
+ Object *ob = (Object *)ale->key_data;
+ ob_to_keylist(ads, ob, anim_keys, 0);
+ break;
+ }
+ case ALE_ACT: {
+ bAction *act = (bAction *)ale->key_data;
+ action_to_keylist(adt, act, anim_keys, 0);
+ break;
+ }
+ case ALE_FCURVE: {
+ FCurve *fcu = (FCurve *)ale->key_data;
+ fcurve_to_keylist(adt, fcu, anim_keys, 0);
+ break;
+ }
+ }
+ }
+ else if (ale->type == ANIMTYPE_SUMMARY) {
+ /* dopesheet summary covers everything */
+ summary_to_keylist(ac, anim_keys, 0);
+ }
+ else if (ale->type == ANIMTYPE_GROUP) {
+ // TODO: why don't we just give groups key_data too?
+ bActionGroup *agrp = (bActionGroup *)ale->data;
+ agroup_to_keylist(adt, agrp, anim_keys, 0);
+ }
+ else if (ale->type == ANIMTYPE_GPLAYER) {
+ // TODO: why don't we just give gplayers key_data too?
+ bGPDlayer *gpl = (bGPDlayer *)ale->data;
+ gpl_to_keylist(ads, gpl, anim_keys);
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ // TODO: why don't we just give masklayers key_data too?
+ MaskLayer *masklay = (MaskLayer *)ale->data;
+ mask_to_keylist(ads, masklay, anim_keys);
+ }
+}
+
+static void actkeys_find_key_in_list_element(bAnimContext *ac,
+ bAnimListElem *ale,
+ float region_x,
+ float *r_selx,
+ float *r_frame,
+ bool *r_found)
+{
+ *r_found = false;
+
+ View2D *v2d = &ac->ar->v2d;
+
+ DLRBT_Tree anim_keys;
+ BLI_dlrbTree_init(&anim_keys);
+ actkeys_list_element_to_keylist(ac, &anim_keys, ale);
+
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ /* standard channel height (to allow for some slop) */
+ float key_hsize = ACHANNEL_HEIGHT(ac) * 0.8f;
+ /* half-size (for either side), but rounded up to nearest int (for easier targeting) */
+ key_hsize = roundf(key_hsize / 2.0f);
+
+ float xmin = UI_view2d_region_to_view_x(v2d, region_x - (int)key_hsize);
+ float xmax = UI_view2d_region_to_view_x(v2d, region_x + (int)key_hsize);
+
+ for (ActKeyColumn *ak = anim_keys.root; ak; ak = (ak->cfra < xmin) ? ak->right : ak->left) {
+ if (IN_RANGE(ak->cfra, xmin, xmax)) {
+ /* set the frame to use, and apply inverse-correction for NLA-mapping
+ * so that the frame will get selected by the selection functions without
+ * requiring to map each frame once again...
+ */
+ *r_selx = BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP);
+ *r_frame = ak->cfra;
+ *r_found = true;
+ break;
+ }
+ }
+
+ /* cleanup temporary lists */
+ BLI_dlrbTree_free(&anim_keys);
+}
+
+static void actkeys_find_key_at_position(bAnimContext *ac,
+ int filter,
+ float region_x,
+ float region_y,
+ bAnimListElem **r_ale,
+ float *r_selx,
+ float *r_frame,
+ bool *r_found)
+
+{
+ *r_found = false;
+ *r_ale = actkeys_find_list_element_at_position(ac, filter, region_x, region_y);
+
+ if (*r_ale != NULL) {
+ actkeys_find_key_in_list_element(ac, *r_ale, region_x, r_selx, r_frame, r_found);
+ }
+}
+
+static bool actkeys_is_key_at_position(bAnimContext *ac, float region_x, float region_y)
+{
+ bAnimListElem *ale;
+ float selx, frame;
+ bool found;
+
+ int filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS;
+ actkeys_find_key_at_position(ac, filter, region_x, region_y, &ale, &selx, &frame, &found);
+
+ if (ale != NULL) {
+ MEM_freeN(ale);
+ }
+ return found;
+}
+
/* ******************** Deselect All Operator ***************************** */
/* This operator works in one of three ways:
* 1) (de)select all (AKEY) - test if select all or deselect all
@@ -355,6 +512,21 @@ static void box_select_action(bAnimContext *ac, const rcti rect, short mode, sho
/* ------------------- */
+static int actkeys_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 && actkeys_is_key_at_position(&ac, event->mval[0], event->mval[1])) {
+ return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+ }
+
+ return WM_gesture_box_invoke(C, op, event);
+}
+
static int actkeys_box_select_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
@@ -412,7 +584,7 @@ void ACTION_OT_select_box(wmOperatorType *ot)
ot->description = "Select all keyframes within the specified region";
/* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
+ ot->invoke = actkeys_box_select_invoke;
ot->exec = actkeys_box_select_exec;
ot->modal = WM_gesture_box_modal;
ot->cancel = WM_gesture_box_cancel;
@@ -428,6 +600,10 @@ void ACTION_OT_select_box(wmOperatorType *ot)
/* properties */
WM_operator_properties_gesture_box(ot);
WM_operator_properties_select_operation_simple(ot);
+
+ 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);
}
/* ******************** Region Select Operators ***************************** */
@@ -1491,133 +1667,13 @@ static void mouse_action_keys(bAnimContext *ac,
const bool column,
const bool same_channel)
{
- ListBase anim_data = {NULL, NULL};
- DLRBT_Tree anim_keys;
- bAnimListElem *ale;
- int filter;
+ int filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS;
- View2D *v2d = &ac->ar->v2d;
- bDopeSheet *ads = NULL;
- int channel_index;
+ bAnimListElem *ale = NULL;
bool found = false;
float frame = 0.0f; /* frame of keyframe under mouse - NLA corrections not applied/included */
float selx = 0.0f; /* frame of keyframe under mouse */
- float key_hsize;
- float x, y;
- rctf rectf;
-
- /* get dopesheet info */
- if (ELEM(ac->datatype, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE)) {
- ads = ac->data;
- }
-
- /* 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, ACHANNEL_STEP(ac), 0, ACHANNEL_FIRST_TOP(ac), x, y, NULL, &channel_index);
-
- /* x-range to check is +/- 7px for standard keyframe under standard dpi/y-scale
- * (in screen/region-space), on either side of mouse click (size of keyframe icon).
- */
-
- /* standard channel height (to allow for some slop) */
- key_hsize = ACHANNEL_HEIGHT(ac) * 0.8f;
- /* half-size (for either side), but rounded up to nearest int (for easier targeting) */
- key_hsize = roundf(key_hsize / 2.0f);
-
- UI_view2d_region_to_view(v2d, mval[0] - (int)key_hsize, mval[1], &rectf.xmin, &rectf.ymin
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list