DopeSheet: Add menu entries and hotkeys to select all keyframes
authorJoshua Leung <aligorith@gmail.com>
Mon, 14 Feb 2011 02:30:33 +0000 (02:30 +0000)
committerJoshua Leung <aligorith@gmail.com>
Mon, 14 Feb 2011 02:30:33 +0000 (02:30 +0000)
left/right to current frame in dope sheet

This commit separates out this selection functionality out of the
click-selection operator into a separate operator, so that hotkeys and
menu entries can be assigned to it.

This is based on an idea+patch (#23738) submitted by Torsten Rupp
(rupp), though I've ultimately decided not to go with the suggested
implementation as I don't think this fits that well under the "column"
select operator.

Todo: Graph Editor support will be coming shortly...

release/scripts/ui/space_dopesheet.py
source/blender/editors/space_action/action_intern.h
source/blender/editors/space_action/action_ops.c
source/blender/editors/space_action/action_select.c

index 9a1acfd76b831cce0be5735c9b8639f685455912..3a3f3f4033e36becacda0b9716a5f545016f1fc7 100644 (file)
@@ -187,6 +187,10 @@ class DOPESHEET_MT_select(bpy.types.Menu):
         layout.operator("action.select_column", text="Columns on Selected Markers").mode = 'MARKERS_COLUMN'
         layout.operator("action.select_column", text="Between Selected Markers").mode = 'MARKERS_BETWEEN'
 
+        layout.separator()
+        layout.operator("action.select_leftright", text="Before Current Frame").mode = 'LEFT'
+        layout.operator("action.select_leftright", text="After Current Frame").mode = 'RIGHT'
+
         # FIXME: grease pencil mode isn't supported for these yet, so skip for that mode only
         if context.space_data.mode != 'GPENCIL':
             layout.separator()
index cc363b764791cc683923b0f0fac45df66b9f5eb5..b483a3edbdc18259e657372a0327027b6588fdd3 100644 (file)
@@ -59,14 +59,14 @@ void ACTION_OT_select_column(struct wmOperatorType *ot);
 void ACTION_OT_select_linked(struct wmOperatorType *ot);
 void ACTION_OT_select_more(struct wmOperatorType *ot);
 void ACTION_OT_select_less(struct wmOperatorType *ot);
+void ACTION_OT_select_leftright(struct wmOperatorType *ot);
 void ACTION_OT_clickselect(struct wmOperatorType *ot);
 
 /* defines for left-right select tool */
 enum {
-       ACTKEYS_LRSEL_TEST      = -1,
-       ACTKEYS_LRSEL_NONE,
+       ACTKEYS_LRSEL_TEST      = 0,
        ACTKEYS_LRSEL_LEFT,
-       ACTKEYS_LRSEL_RIGHT,
+       ACTKEYS_LRSEL_RIGHT
 } eActKeys_LeftRightSelect_Mode;
 
 /* defines for column-select mode */
index ea36ce98ecba813138492c5682ff10c1f053b56a..3b448becf8b1fdbdb4f1ff7e7131f4ff428d2c4b 100644 (file)
@@ -58,6 +58,7 @@ void action_operatortypes(void)
        WM_operatortype_append(ACTION_OT_select_linked);
        WM_operatortype_append(ACTION_OT_select_more);
        WM_operatortype_append(ACTION_OT_select_less);
+       WM_operatortype_append(ACTION_OT_select_leftright);
        
                /* editing */
        WM_operatortype_append(ACTION_OT_snap);
@@ -96,8 +97,16 @@ static void action_keymap_keyframes (wmKeyConfig *keyconf, wmKeyMap *keymap)
        kmi= WM_keymap_add_item(keymap, "ACTION_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT|KM_SHIFT, 0);
                RNA_boolean_set(kmi->ptr, "extend", 1);
                RNA_boolean_set(kmi->ptr, "column", 1);
-       kmi= WM_keymap_add_item(keymap, "ACTION_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
-               RNA_enum_set(kmi->ptr, "left_right", ACTKEYS_LRSEL_TEST);
+               
+               /* select left/right */
+       WM_keymap_add_item(keymap, "ACTION_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
+       kmi= WM_keymap_add_item(keymap, "ACTION_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
+               RNA_boolean_set(kmi->ptr, "extend", 1);
+       
+       kmi= WM_keymap_add_item(keymap, "ACTION_OT_select_leftright", LEFTBRACKETKEY, KM_PRESS, 0, 0);
+               RNA_enum_set(kmi->ptr, "mode", ACTKEYS_LRSEL_LEFT);
+       kmi= WM_keymap_add_item(keymap, "ACTION_OT_select_leftright", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
+               RNA_enum_set(kmi->ptr, "mode", ACTKEYS_LRSEL_RIGHT);
        
                /* deselect all */
        WM_keymap_add_item(keymap, "ACTION_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
index 365c17d45c08e34d64369cc718d4e865a4e9977f..4e12833f8b89938f726b73ca065ce89bf7cc1e1d 100644 (file)
@@ -705,53 +705,20 @@ void ACTION_OT_select_less (wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
 }
 
-/* ******************** Mouse-Click Select Operator *********************** */
-/* This operator works in one of three ways:
- *     - 1) keyframe under mouse - no special modifiers
- *     - 2) all keyframes on the same side of current frame indicator as mouse - ALT modifier
- *     - 3) column select all keyframes in frame under mouse - CTRL modifier
- *
- * In addition to these basic options, the SHIFT modifier can be used to toggle the 
- * selection mode between replacing the selection (without) and inverting the selection (with).
- */
+/* ******************** Select Left/Right Operator ************************* */
+/* Select keyframes left/right of the current frame indicator */
 
 /* defines for left-right select tool */
 static EnumPropertyItem prop_actkeys_leftright_select_types[] = {
        {ACTKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
-       {ACTKEYS_LRSEL_NONE, "OFF", 0, "Don't select", ""},
        {ACTKEYS_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""},
        {ACTKEYS_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""},
        {0, NULL, 0, NULL, NULL}
 };
 
-/* sensitivity factor for frame-selections */
-#define FRAME_CLICK_THRESH             0.1f
+/* --------------------------------- */
 
-/* ------------------- */
-/* option 1) select keyframe directly under mouse */
-static void actkeys_mselect_single (bAnimContext *ac, bAnimListElem *ale, short select_mode, float selx)
-{
-       bDopeSheet *ads= (ac->datatype == ANIMCONT_DOPESHEET) ? ac->data : NULL;
-       int ds_filter = ((ads) ? (ads->filterflag) : (0));
-       
-       KeyframeEditData ked= {{0}};
-       KeyframeEditFunc select_cb, ok_cb;
-       
-       /* get functions for selecting keyframes */
-       select_cb= ANIM_editkeyframes_select(select_mode);
-       ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAME);
-       ked.f1= selx;
-       
-       /* select the nominated keyframe on the given frame */
-       if (ale->type == ANIMTYPE_GPLAYER)
-               select_gpencil_frame(ale->data, selx, select_mode);
-       else
-               ANIM_animchannel_keyframes_loop(&ked, ale, ok_cb, select_cb, NULL, ds_filter);
-}
-
-/* Option 2) Selects all the keyframes on either side of the current frame (depends on which side the mouse is on) */
-static void actkeys_mselect_leftright (bAnimContext *ac, short leftright, short select_mode)
+static void actkeys_select_leftright (bAnimContext *ac, short leftright, short select_mode)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
@@ -773,13 +740,16 @@ static void actkeys_mselect_leftright (bAnimContext *ac, short leftright, short
        /* set callbacks and editing data */
        ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
        select_cb= ANIM_editkeyframes_select(select_mode);
-
+       
+       /* NOTE: we used to include FRAME_CLICK_THRESH in the tolerance for the current frame, 
+        * but this has now been remove, since it is not so relevant anymore
+        */
        if (leftright == ACTKEYS_LRSEL_LEFT) {
                ked.f1 = MINAFRAMEF;
-               ked.f2 = (float)(CFRA + FRAME_CLICK_THRESH);
+               ked.f2 = (float)(CFRA);
        } 
        else {
-               ked.f1 = (float)(CFRA - FRAME_CLICK_THRESH);
+               ked.f1 = (float)(CFRA);
                ked.f2 = MAXFRAMEF;
        }
        
@@ -790,7 +760,7 @@ static void actkeys_mselect_leftright (bAnimContext *ac, short leftright, short
                filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
                
-       /* select keys on the side where most data occurs */
+       /* select keys */
        for (ale= anim_data.first; ale; ale= ale->next) {
                AnimData *adt= ANIM_nla_mapping_get(ac, ale);
                
@@ -806,7 +776,7 @@ static void actkeys_mselect_leftright (bAnimContext *ac, short leftright, short
        }
        
        /* Sync marker support */
-       if ((select_mode==SELECT_ADD) && ELEM(leftright, ACTKEYS_LRSEL_LEFT, ACTKEYS_LRSEL_RIGHT)) {
+       if (select_mode==SELECT_ADD) {
                SpaceAction *saction= ac->sa->spacedata.first;
                
                if ((saction) && (saction->flag & SACTION_MARKERS_MOVE)) {
@@ -830,6 +800,130 @@ static void actkeys_mselect_leftright (bAnimContext *ac, short leftright, short
        BLI_freelistN(&anim_data);
 }
 
+/* ----------------- */
+
+static int actkeys_select_leftright_exec (bContext *C, wmOperator *op)
+{
+       bAnimContext ac;
+       short leftright = RNA_enum_get(op->ptr, "mode");
+       short selectmode;
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+       
+       /* select mode is either replace (deselect all, then add) or add/extend */
+       if (RNA_boolean_get(op->ptr, "extend"))
+               selectmode= SELECT_INVERT;
+       else
+               selectmode= SELECT_REPLACE;
+               
+       /* if "test" mode is set, we don't have any info to set this with */
+       if (leftright == ACTKEYS_LRSEL_TEST)
+               return OPERATOR_CANCELLED;
+       
+       /* do the selecting now */
+       actkeys_select_leftright(&ac, leftright, selectmode);
+       
+       /* set notifier that keyframe selection (and channels too) have changed */
+       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|ND_ANIMCHAN|NA_SELECTED, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+static int actkeys_select_leftright_invoke (bContext *C, wmOperator *op, wmEvent *event)
+{
+       bAnimContext ac;
+       short leftright = RNA_enum_get(op->ptr, "mode");
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+               
+       /* handle mode-based testing */
+       if (leftright == ACTKEYS_LRSEL_TEST) {
+               Scene *scene= ac.scene;
+               ARegion *ar= ac.ar;
+               View2D *v2d= &ar->v2d;
+               
+               short mval[2];
+               float x;
+               
+               /* get mouse coordinates (in region coordinates) */
+               mval[0]= (event->x - ar->winrct.xmin);
+               mval[1]= (event->y - ar->winrct.ymin);
+               
+               /* determine which side of the current frame mouse is on */
+               UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, NULL);
+               if (x < CFRA)
+                       RNA_int_set(op->ptr, "mode", ACTKEYS_LRSEL_LEFT);
+               else    
+                       RNA_int_set(op->ptr, "mode", ACTKEYS_LRSEL_RIGHT);
+       }
+       
+       /* perform selection */
+       return actkeys_select_leftright_exec(C, op);
+}
+
+void ACTION_OT_select_leftright (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Select Left/Right";
+       ot->idname= "ACTION_OT_select_leftright";
+       ot->description= "Select keyframes to the left or the right of the current keyframe ";
+       
+       /* api callbacks  */
+       ot->invoke= actkeys_select_leftright_invoke;
+       ot->exec= actkeys_select_leftright_exec;
+       ot->poll= ED_operator_action_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* id-props */
+       ot->prop= RNA_def_enum(ot->srna, "mode", prop_actkeys_leftright_select_types, ACTKEYS_LRSEL_TEST, "Mode", "");
+       RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
+}
+
+/* ******************** Mouse-Click Select Operator *********************** */
+/* This operator works in one of three ways:
+ *     - 1) keyframe under mouse - no special modifiers
+ *     - 2) all keyframes on the same side of current frame indicator as mouse - ALT modifier
+ *     - 3) column select all keyframes in frame under mouse - CTRL modifier
+ *
+ * In addition to these basic options, the SHIFT modifier can be used to toggle the 
+ * selection mode between replacing the selection (without) and inverting the selection (with).
+ */
+
+/* sensitivity factor for frame-selections */
+#define FRAME_CLICK_THRESH             0.1f
+
+/* ------------------- */
+/* option 1) select keyframe directly under mouse */
+static void actkeys_mselect_single (bAnimContext *ac, bAnimListElem *ale, short select_mode, float selx)
+{
+       bDopeSheet *ads= (ac->datatype == ANIMCONT_DOPESHEET) ? ac->data : NULL;
+       int ds_filter = ((ads) ? (ads->filterflag) : (0));
+       
+       KeyframeEditData ked= {{0}};
+       KeyframeEditFunc select_cb, ok_cb;
+       
+       /* get functions for selecting keyframes */
+       select_cb= ANIM_editkeyframes_select(select_mode);
+       ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAME);
+       ked.f1= selx;
+       
+       /* select the nominated keyframe on the given frame */
+       if (ale->type == ANIMTYPE_GPLAYER)
+               select_gpencil_frame(ale->data, selx, select_mode);
+       else
+               ANIM_animchannel_keyframes_loop(&ked, ale, ok_cb, select_cb, NULL, ds_filter);
+}
+
+/* Option 2) Selects all the keyframes on either side of the current frame (depends on which side the mouse is on) */
+/* (see actkeys_select_leftright) */
+
 /* Option 3) Selects all visible keyframes in the same frame as the mouse click */
 static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float selx)
 {
@@ -1089,23 +1183,8 @@ static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *even
        /* column selection */
        column= RNA_boolean_get(op->ptr, "column");
        
-       /* figure out action to take */
-       if (RNA_enum_get(op->ptr, "left_right")) {
-               /* select all keys on same side of current frame as mouse */
-               float x;
-               
-               UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, NULL);
-               if (x < CFRA)
-                       RNA_int_set(op->ptr, "left_right", ACTKEYS_LRSEL_LEFT);
-               else    
-                       RNA_int_set(op->ptr, "left_right", ACTKEYS_LRSEL_RIGHT);
-               
-               actkeys_mselect_leftright(&ac, RNA_enum_get(op->ptr, "left_right"), selectmode);
-       }
-       else {
-               /* select keyframe(s) based upon mouse position*/
-               mouse_action_keys(&ac, mval, selectmode, column);
-       }
+       /* select keyframe(s) based upon mouse position*/
+       mouse_action_keys(&ac, mval, selectmode, column);
        
        /* set notifier that keyframe selection (and channels too) have changed */
        WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|ND_ANIMCHAN|NA_SELECTED, NULL);
@@ -1129,8 +1208,6 @@ void ACTION_OT_clickselect (wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* id-props */
-       // XXX should we make this into separate operators?
-       RNA_def_enum(ot->srna, "left_right", prop_actkeys_leftright_select_types, 0, "Left Right", ""); // CTRLKEY
        RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
        RNA_def_boolean(ot->srna, "column", 0, "Column Select", ""); // ALTKEY
 }