Animation Editors: Select Linked Operator
[blender.git] / source / blender / editors / space_graph / graph_select.c
index 8cb124422cb35f8f5a07cb1f1d95225d566253f0..a81de25f265d8a4e6333f16b6ef859bdd592b733 100644 (file)
@@ -95,8 +95,8 @@ static void deselect_graph_keys (bAnimContext *ac, short test, short sel)
        int filter;
        
        SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first;
-       BeztEditData bed;
-       BeztEditFunc test_cb, sel_cb;
+       KeyframeEditData ked;
+       KeyframeEditFunc test_cb, sel_cb;
        
        /* determine type-based settings */
        filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
@@ -105,13 +105,13 @@ static void deselect_graph_keys (bAnimContext *ac, short test, short sel)
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* init BezTriple looping data */
-       memset(&bed, 0, sizeof(BeztEditData));
+       memset(&ked, 0, sizeof(KeyframeEditData));
        test_cb= ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
        
        /* See if we should be selecting or deselecting */
        if (test) {
                for (ale= anim_data.first; ale; ale= ale->next) {
-                       if (ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, test_cb, NULL)) {
+                       if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
                                sel= SELECT_SUBTRACT;
                                break;
                        }
@@ -126,7 +126,7 @@ static void deselect_graph_keys (bAnimContext *ac, short test, short sel)
                FCurve *fcu= (FCurve *)ale->key_data;
                
                /* Keyframes First */
-               ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, sel_cb, NULL);
+               ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
                
                /* only change selection of channel when the visibility of keyframes doesn't depend on this */
                if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
@@ -196,18 +196,19 @@ void GRAPH_OT_select_all_toggle (wmOperatorType *ot)
  */
 
 /* Borderselect only selects keyframes now, as overshooting handles often get caught too,
- * which means that they may be inadvertantly moved as well.
- * Also, for convenience, handles should get same status as keyframe (if it was within bounds)
+ * which means that they may be inadvertantly moved as well. However, incl_handles overrides
+ * this, and allow handles to be considered independently too.
+ * Also, for convenience, handles should get same status as keyframe (if it was within bounds).
  */
-static void borderselect_graphkeys (bAnimContext *ac, rcti rect, short mode, short selectmode)
+static void borderselect_graphkeys (bAnimContext *ac, rcti rect, short mode, short selectmode, short incl_handles)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
        int filter;
        
        SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first;
-       BeztEditData bed;
-       BeztEditFunc ok_cb, select_cb;
+       KeyframeEditData ked;
+       KeyframeEditFunc ok_cb, select_cb;
        View2D *v2d= &ac->ar->v2d;
        rctf rectf;
        
@@ -224,8 +225,12 @@ static void borderselect_graphkeys (bAnimContext *ac, rcti rect, short mode, sho
        ok_cb= ANIM_editkeyframes_ok(mode);
        
        /* init editing data */
-       memset(&bed, 0, sizeof(BeztEditData));
-       bed.data= &rectf;
+       memset(&ked, 0, sizeof(KeyframeEditData));
+       ked.data= &rectf;
+       
+       /* treat handles separately? */
+       if (incl_handles)
+               ked.iterflags |= KEYFRAME_ITER_INCL_HANDLES;
        
        /* loop over data, doing border select */
        for (ale= anim_data.first; ale; ale= ale->next) {
@@ -243,21 +248,21 @@ static void borderselect_graphkeys (bAnimContext *ac, rcti rect, short mode, sho
                
                /* set horizontal range (if applicable) 
                 * NOTE: these values are only used for x-range and y-range but not region 
-                *              (which uses bed.data, i.e. rectf)
+                *              (which uses ked.data, i.e. rectf)
                 */
                if (mode != BEZT_OK_VALUERANGE) {
-                       bed.f1= rectf.xmin;
-                       bed.f2= rectf.xmax;
+                       ked.f1= rectf.xmin;
+                       ked.f2= rectf.xmax;
                }
                else {
-                       bed.f1= rectf.ymin;
-                       bed.f2= rectf.ymax;
+                       ked.f1= rectf.ymin;
+                       ked.f2= rectf.ymax;
                }
                
                /* firstly, check if any keyframes will be hit by this */
-               if (ANIM_fcurve_keys_bezier_loop(&bed, fcu, NULL, ok_cb, NULL)) {
+               if (ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, ok_cb, NULL)) {
                        /* select keyframes that are in the appropriate places */
-                       ANIM_fcurve_keys_bezier_loop(&bed, fcu, ok_cb, select_cb, NULL);
+                       ANIM_fcurve_keyframes_loop(&ked, fcu, ok_cb, select_cb, NULL);
                        
                        /* only change selection of channel when the visibility of keyframes doesn't depend on this */
                        if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
@@ -286,16 +291,23 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op)
        bAnimContext ac;
        rcti rect;
        short mode=0, selectmode=0;
+       short incl_handles;
        
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
-
+       
+       /* get select mode 
+        *      - 'gesture_mode' from the operator specifies how to select
+        *      - 'include_handles' from the operator specifies whether to include handles in the selection
+        */
        if (RNA_int_get(op->ptr, "gesture_mode")==GESTURE_MODAL_SELECT)
                selectmode= SELECT_ADD;
        else
                selectmode= SELECT_SUBTRACT;
-
+               
+       incl_handles = RNA_boolean_get(op->ptr, "include_handles");
+       
        /* get settings from operator */
        rect.xmin= RNA_int_get(op->ptr, "xmin");
        rect.ymin= RNA_int_get(op->ptr, "ymin");
@@ -318,7 +330,7 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op)
                mode= BEZT_OK_REGION;
        
        /* apply borderselect action */
-       borderselect_graphkeys(&ac, rect, mode, selectmode);
+       borderselect_graphkeys(&ac, rect, mode, selectmode, incl_handles);
        
        /* send notifier that keyframe selection has changed */
        WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL);
@@ -347,6 +359,7 @@ void GRAPH_OT_select_border(wmOperatorType *ot)
        WM_operator_properties_gesture_border(ot, FALSE);
        
        ot->prop= RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
+       RNA_def_boolean(ot->srna, "include_handles", 0, "Include Handles", "Are handles tested individually against the selection criteria");
 }
 
 /* ******************** Column Select Operator **************************** */
@@ -375,8 +388,8 @@ static void markers_selectkeys_between (bAnimContext *ac)
        bAnimListElem *ale;
        int filter;
        
-       BeztEditFunc ok_cb, select_cb;
-       BeztEditData bed;
+       KeyframeEditFunc ok_cb, select_cb;
+       KeyframeEditData ked;
        float min, max;
        
        /* get extreme markers */
@@ -388,9 +401,9 @@ static void markers_selectkeys_between (bAnimContext *ac)
        ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
        select_cb= ANIM_editkeyframes_select(SELECT_ADD);
        
-       memset(&bed, 0, sizeof(BeztEditData));
-       bed.f1= min; 
-       bed.f2= max;
+       memset(&ked, 0, sizeof(KeyframeEditData));
+       ked.f1= min; 
+       ked.f2= max;
        
        /* filter data */
        filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
@@ -402,11 +415,11 @@ static void markers_selectkeys_between (bAnimContext *ac)
                
                if (adt) {      
                        ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
-                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+                       ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
                        ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
                }
                else {
-                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+                       ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
                }
        }
        
@@ -424,11 +437,11 @@ static void columnselect_graph_keys (bAnimContext *ac, short mode)
        
        Scene *scene= ac->scene;
        CfraElem *ce;
-       BeztEditFunc select_cb, ok_cb;
-       BeztEditData bed;
+       KeyframeEditFunc select_cb, ok_cb;
+       KeyframeEditData ked;
        
        /* initialise keyframe editing data */
-       memset(&bed, 0, sizeof(BeztEditData));
+       memset(&ked, 0, sizeof(KeyframeEditData));
        
        /* build list of columns */
        switch (mode) {
@@ -437,7 +450,7 @@ static void columnselect_graph_keys (bAnimContext *ac, short mode)
                        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
                        
                        for (ale= anim_data.first; ale; ale= ale->next)
-                               ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_to_cfraelem, NULL);
+                               ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL);
                        
                        BLI_freelistN(&anim_data);
                        break;
@@ -445,13 +458,13 @@ static void columnselect_graph_keys (bAnimContext *ac, short mode)
                case GRAPHKEYS_COLUMNSEL_CFRA: /* current frame */
                        /* make a single CfraElem for storing this */
                        ce= MEM_callocN(sizeof(CfraElem), "cfraElem");
-                       BLI_addtail(&bed.list, ce);
+                       BLI_addtail(&ked.list, ce);
                        
                        ce->cfra= (float)CFRA;
                        break;
                        
                case GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
-                       ED_markers_make_cfra_list(ac->markers, &bed.list, 1);
+                       ED_markers_make_cfra_list(ac->markers, &ked.list, 1);
                        break;
                        
                default: /* invalid option */
@@ -471,23 +484,23 @@ static void columnselect_graph_keys (bAnimContext *ac, short mode)
        for (ale= anim_data.first; ale; ale= ale->next) {
                AnimData *adt= ANIM_nla_mapping_get(ac, ale);
                
-               /* loop over cfraelems (stored in the BeztEditData->list)
+               /* loop over cfraelems (stored in the KeyframeEditData->list)
                 *      - we need to do this here, as we can apply fewer NLA-mapping conversions
                 */
-               for (ce= bed.list.first; ce; ce= ce->next) {
+               for (ce= ked.list.first; ce; ce= ce->next) {
                        /* set frame for validation callback to refer to */
                        if (ale)
-                               bed.f1= BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);
+                               ked.f1= BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);
                        else
-                               bed.f1= ce->cfra;
+                               ked.f1= ce->cfra;
                        
                        /* select elements with frame number matching cfraelem */
-                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+                       ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
                }
        }
        
        /* free elements */
-       BLI_freelistN(&bed.list);
+       BLI_freelistN(&ked.list);
        BLI_freelistN(&anim_data);
 }
 
@@ -534,6 +547,61 @@ void GRAPH_OT_select_column (wmOperatorType *ot)
        ot->prop= RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
 }
 
+/* ******************** Select Linked Operator *********************** */
+
+static int graphkeys_select_linked_exec (bContext *C, wmOperator *op)
+{
+       bAnimContext ac;
+       
+       ListBase anim_data= {NULL, NULL};
+       bAnimListElem *ale;
+       int filter;
+       
+       KeyframeEditFunc ok_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
+       KeyframeEditFunc sel_cb = ANIM_editkeyframes_select(SELECT_ADD);
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+       
+       /* loop through all of the keys and select additional keyframes based on these */
+       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
+       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+       
+       for (ale= anim_data.first; ale; ale= ale->next) {
+               FCurve *fcu= (FCurve *)ale->key_data;
+               
+               /* check if anything selected? */
+               if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ok_cb, NULL)) {
+                       /* select every keyframe in this curve then */
+                       ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL);
+               }
+       }
+       
+       /* Cleanup */
+       BLI_freelistN(&anim_data);
+       
+       /* set notifier that keyframe selection has changed */
+       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+void GRAPH_OT_select_linked (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Select Linked";
+       ot->idname= "GRAPH_OT_select_linked";
+       ot->description = "Select keyframes occurring the same F-Curves as selected ones";
+       
+       /* api callbacks */
+       ot->exec= graphkeys_select_linked_exec;
+       ot->poll= graphop_visible_keyframes_poll;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+}
+
 /* ******************** Select More/Less Operators *********************** */
 
 /* Common code to perform selection */
@@ -543,13 +611,13 @@ static void select_moreless_graph_keys (bAnimContext *ac, short mode)
        bAnimListElem *ale;
        int filter;
        
-       BeztEditData bed;
-       BeztEditFunc build_cb;
+       KeyframeEditData ked;
+       KeyframeEditFunc build_cb;
        
        
        /* init selmap building data */
        build_cb= ANIM_editkeyframes_buildselmap(mode);
-       memset(&bed, 0, sizeof(BeztEditData)); 
+       memset(&ked, 0, sizeof(KeyframeEditData)); 
        
        /* loop through all of the keys and select additional keyframes based on these */
        filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
@@ -563,15 +631,15 @@ static void select_moreless_graph_keys (bAnimContext *ac, short mode)
                        continue;
                
                /* build up map of whether F-Curve's keyframes should be selected or not */
-               bed.data= MEM_callocN(fcu->totvert, "selmap graphEdit");
-               ANIM_fcurve_keys_bezier_loop(&bed, fcu, NULL, build_cb, NULL);
+               ked.data= MEM_callocN(fcu->totvert, "selmap graphEdit");
+               ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, build_cb, NULL);
                
                /* based on this map, adjust the selection status of the keyframes */
-               ANIM_fcurve_keys_bezier_loop(&bed, fcu, NULL, bezt_selmap_flush, NULL);
+               ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, bezt_selmap_flush, NULL);
                
                /* free the selmap used here */
-               MEM_freeN(bed.data);
-               bed.data= NULL;
+               MEM_freeN(ked.data);
+               ked.data= NULL;
        }
        
        /* Cleanup */
@@ -968,17 +1036,17 @@ static void mouse_graph_keys (bAnimContext *ac, int mval[], short select_mode, s
                }
        }
        else {
-               BeztEditFunc select_cb;
-               BeztEditData bed;
+               KeyframeEditFunc select_cb;
+               KeyframeEditData ked;
                
                /* initialise keyframe editing data */
-               memset(&bed, 0, sizeof(BeztEditData));
+               memset(&ked, 0, sizeof(KeyframeEditData));
                
                /* set up BezTriple edit callbacks */
                select_cb= ANIM_editkeyframes_select(select_mode);
                
                /* select all keyframes */
-               ANIM_fcurve_keys_bezier_loop(&bed, nvi->fcu, NULL, select_cb, NULL);
+               ANIM_fcurve_keyframes_loop(&ked, nvi->fcu, NULL, select_cb, NULL);
        }
        
        /* only change selection of channel when the visibility of keyframes doesn't depend on this */
@@ -1008,8 +1076,8 @@ static void graphkeys_mselect_leftright (bAnimContext *ac, short leftright, shor
        int filter;
        
        SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first;
-       BeztEditFunc ok_cb, select_cb;
-       BeztEditData bed;
+       KeyframeEditFunc ok_cb, select_cb;
+       KeyframeEditData ked;
        Scene *scene= ac->scene;
        
        /* if select mode is replace, deselect all keyframes (and channels) first */
@@ -1032,14 +1100,14 @@ static void graphkeys_mselect_leftright (bAnimContext *ac, short leftright, shor
        ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
        select_cb= ANIM_editkeyframes_select(select_mode);
        
-       memset(&bed, 0, sizeof(BeztEditFunc));
+       memset(&ked, 0, sizeof(KeyframeEditFunc));
        if (leftright == GRAPHKEYS_LRSEL_LEFT) {
-               bed.f1 = MINAFRAMEF;
-               bed.f2 = (float)(CFRA + 0.1f);
+               ked.f1 = MINAFRAMEF;
+               ked.f2 = (float)(CFRA + 0.1f);
        } 
        else {
-               bed.f1 = (float)(CFRA - 0.1f);
-               bed.f2 = MAXFRAMEF;
+               ked.f1 = (float)(CFRA - 0.1f);
+               ked.f2 = MAXFRAMEF;
        }
        
        /* filter data */
@@ -1052,11 +1120,11 @@ static void graphkeys_mselect_leftright (bAnimContext *ac, short leftright, shor
                
                if (adt) {
                        ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
-                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+                       ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
                        ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
                }
                else
-                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+                       ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
        }
        
        /* Cleanup */
@@ -1071,8 +1139,8 @@ static void graphkeys_mselect_column (bAnimContext *ac, int mval[2], short selec
        int filter;
        
        SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first;
-       BeztEditFunc select_cb, ok_cb;
-       BeztEditData bed;
+       KeyframeEditFunc select_cb, ok_cb;
+       KeyframeEditData ked;
        tNearestVertInfo *nvi;
        float selx = (float)ac->scene->r.cfra;
        
@@ -1107,7 +1175,7 @@ static void graphkeys_mselect_column (bAnimContext *ac, int mval[2], short selec
        }
        
        /* initialise keyframe editing data */
-       memset(&bed, 0, sizeof(BeztEditData));
+       memset(&ked, 0, sizeof(KeyframeEditData));
        
        /* set up BezTriple edit callbacks */
        select_cb= ANIM_editkeyframes_select(select_mode);
@@ -1124,17 +1192,17 @@ static void graphkeys_mselect_column (bAnimContext *ac, int mval[2], short selec
                
                /* set frame for validation callback to refer to */
                if (adt)
-                       bed.f1= BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
+                       ked.f1= BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
                else
-                       bed.f1= selx;
+                       ked.f1= selx;
                
                /* select elements with frame number matching cfra */
-               ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+               ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
        }
        
        /* free elements */
        MEM_freeN(nvi);
-       BLI_freelistN(&bed.list);
+       BLI_freelistN(&ked.list);
        BLI_freelistN(&anim_data);
 }