Bugfix [#26505] zoom in selected keys on graph editor
authorJoshua Leung <aligorith@gmail.com>
Thu, 17 Mar 2011 10:02:37 +0000 (10:02 +0000)
committerJoshua Leung <aligorith@gmail.com>
Thu, 17 Mar 2011 10:02:37 +0000 (10:02 +0000)
Not really a "bug", but it was on my todo anyways. Based on patch
[#26508] by Campbell, with a few modifications including extending
this to the Action/DopeSheet editor too.

14 files changed:
release/scripts/ui/space_dopesheet.py
release/scripts/ui/space_graph.py
source/blender/blenkernel/BKE_fcurve.h
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/fcurve.c
source/blender/blenlib/BLI_utildefines.h
source/blender/editors/space_action/action_edit.c
source/blender/editors/space_action/action_intern.h
source/blender/editors/space_action/action_ops.c
source/blender/editors/space_graph/graph_edit.c
source/blender/editors/space_graph/graph_intern.h
source/blender/editors/space_graph/graph_ops.c
source/blender/editors/space_graph/space_graph.c
source/blender/makesrna/intern/rna_fcurve.c

index 24c98982de1e6fc9fd657c6b9ed7ff33b06ae42f..57b5a1fb97f414de6ecec20a4f9f6c894ea7784e 100644 (file)
@@ -159,6 +159,7 @@ class DOPESHEET_MT_view(bpy.types.Menu):
         layout.separator()
         layout.operator("action.frame_jump")
         layout.operator("action.view_all")
+        layout.operator("action.view_selected")
 
         layout.separator()
         layout.operator("screen.area_dupli")
index 6bc47ffce86b7f4371950af78196d3f9ba1535f9..f536e4cace024947de8a585aac6680415dda907f 100644 (file)
@@ -100,6 +100,7 @@ class GRAPH_MT_view(bpy.types.Menu):
         layout.separator()
         layout.operator("graph.frame_jump")
         layout.operator("graph.view_all")
+        layout.operator("graph.view_selected")
 
         layout.separator()
         layout.operator("screen.area_dupli")
index f81acf4b11e5fd387b1b1eaae449b7392b5e705c..b791e29a38ead1bb11e1f6aeffa5ce0fe0c5d386 100644 (file)
@@ -215,10 +215,10 @@ struct FCurve *rna_get_fcurve(struct PointerRNA *ptr, struct PropertyRNA *prop,
 int binarysearch_bezt_index(struct BezTriple array[], float frame, int arraylen, short *replace);
 
 /* get the time extents for F-Curve */
-void calc_fcurve_range(struct FCurve *fcu, float *min, float *max);
+void calc_fcurve_range(struct FCurve *fcu, float *min, float *max, const short selOnly);
 
 /* get the bounding-box extents for F-Curve */
-void calc_fcurve_bounds(struct FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax);
+void calc_fcurve_bounds(struct FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax, const short selOnly);
 
 /* .............. */
 
index 4c5b7f5fcafc994fc880f55c561f6ac3c54c6ddf..5b42948072ff56f7f463b7b25596d03b761dbed8 100644 (file)
@@ -867,7 +867,8 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_
                                float nmin, nmax;
                                
                                /* get extents for this curve */
-                               calc_fcurve_range(fcu, &nmin, &nmax);
+                               // TODO: allow enabling/disabling this?
+                               calc_fcurve_range(fcu, &nmin, &nmax, FALSE);
                                
                                /* compare to the running tally */
                                min= MIN2(min, nmin);
index a1ed16fc1e5eabf53775ad571bc837fe8a04257b..a5391ee20cc6b7130c5a7a1dcbff407ebf1de538 100644 (file)
@@ -426,8 +426,52 @@ int binarysearch_bezt_index (BezTriple array[], float frame, int arraylen, short
        return start;
 }
 
+/* ...................................... */
+
+/* helper for calc_fcurve_* functions -> find first and last BezTriple to be used */
+static void get_fcurve_end_keyframes (FCurve *fcu, BezTriple **first, BezTriple **last, const short selOnly)
+{
+       /* init outputs */
+       *first = NULL;
+       *last = NULL;
+       
+       /* sanity checks */
+       if (fcu->bezt == NULL)
+               return;
+       
+       /* only include selected items? */
+       if (selOnly) {
+               BezTriple *bezt;
+               unsigned int i;
+               
+               /* find first selected */
+               bezt = fcu->bezt;
+               for (i=0; i < fcu->totvert; bezt++, i++) {
+                       if (BEZSELECTED(bezt)) {
+                               *first= bezt;
+                               break;
+                       }
+               }
+               
+               /* find last selected */
+               bezt = ARRAY_LAST_ITEM(fcu->bezt, BezTriple, sizeof(BezTriple), fcu->totvert);
+               for (i=0; i < fcu->totvert; bezt--, i++) {
+                       if (BEZSELECTED(bezt)) {
+                               *last= bezt;
+                               break;
+                       }
+               }
+       }
+       else {
+               /* just full array */
+               *first = fcu->bezt;
+               *last = ARRAY_LAST_ITEM(fcu->bezt, BezTriple, sizeof(BezTriple), fcu->totvert);
+       }
+}
+
+
 /* Calculate the extents of F-Curve's data */
-void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax)
+void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax, const short selOnly)
 {
        float xminv=999999999.0f, xmaxv=-999999999.0f;
        float yminv=999999999.0f, ymaxv=-999999999.0f;
@@ -436,21 +480,31 @@ void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, flo
        
        if (fcu->totvert) {
                if (fcu->bezt) {
-                       /* frame range can be directly calculated from end verts */
+                       BezTriple *bezt_first= NULL, *bezt_last= NULL;
+                       
                        if (xmin || xmax) {
-                               xminv= MIN2(xminv, fcu->bezt[0].vec[1][0]);
-                               xmaxv= MAX2(xmaxv, fcu->bezt[fcu->totvert-1].vec[1][0]);
+                               /* get endpoint keyframes */
+                               get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, selOnly);
+                               
+                               if (bezt_first) {
+                                       BLI_assert(bezt_last != NULL);
+                                       
+                                       xminv= MIN2(xminv, bezt_first->vec[1][0]);
+                                       xmaxv= MAX2(xmaxv, bezt_last->vec[1][0]);
+                               }
                        }
                        
                        /* only loop over keyframes to find extents for values if needed */
-                       if (ymin || ymax) {
+                       if (ymin || ymax) {     
                                BezTriple *bezt;
                                
                                for (bezt=fcu->bezt, i=0; i < fcu->totvert; bezt++, i++) {
-                                       if (bezt->vec[1][1] < yminv)
-                                               yminv= bezt->vec[1][1];
-                                       if (bezt->vec[1][1] > ymaxv)
-                                               ymaxv= bezt->vec[1][1];
+                                       if ((selOnly == 0) || BEZSELECTED(bezt)) {
+                                               if (bezt->vec[1][1] < yminv)
+                                                       yminv= bezt->vec[1][1];
+                                               if (bezt->vec[1][1] > ymaxv)
+                                                       ymaxv= bezt->vec[1][1];
+                                       }
                                }
                        }
                }
@@ -497,15 +551,24 @@ void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, flo
 }
 
 /* Calculate the extents of F-Curve's keyframes */
-void calc_fcurve_range (FCurve *fcu, float *start, float *end)
+void calc_fcurve_range (FCurve *fcu, float *start, float *end, const short selOnly)
 {
        float min=999999999.0f, max=-999999999.0f;
        short foundvert=0;
 
        if (fcu->totvert) {
                if (fcu->bezt) {
-                       min= MIN2(min, fcu->bezt[0].vec[1][0]);
-                       max= MAX2(max, fcu->bezt[fcu->totvert-1].vec[1][0]);
+                       BezTriple *bezt_first= NULL, *bezt_last= NULL;
+                       
+                       /* get endpoint keyframes */
+                       get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, selOnly);
+                       
+                       if (bezt_first) {
+                               BLI_assert(bezt_last != NULL);
+                               
+                               min= MIN2(min, bezt_first->vec[1][0]);
+                               max= MAX2(max, bezt_last->vec[1][0]);
+                       }
                }
                else if (fcu->fpt) {
                        min= MIN2(min, fcu->fpt[0].vec[0]);
index b2129a6ab76369a80804134e914b1f73dc12f192..eff70b46157d6970af81752551ce325999a6d11d 100644 (file)
 #define IN_RANGE(a, b, c) ((b < c)? ((b<a && a<c)? 1:0) : ((c<a && a<b)? 1:0))
 #define IN_RANGE_INCL(a, b, c) ((b < c)? ((b<=a && a<=c)? 1:0) : ((c<=a && a<=b)? 1:0))
 
+/* array helpers */
+#define ARRAY_LAST_ITEM(arr_start, arr_dtype, elem_size, tot)          (arr_dtype *)((char*)arr_start + (elem_size*tot))
+#define ARRAY_HAS_ITEM(item, arr_start, arr_dtype, elem_size, tot)     ((item >= arr_start) && (item <= ARRAY_LAST_ITEM(arr_start, arr_dtype, elem_size, tot)))
 
 /* This one rotates the bytes in an int64, int (32) and short (16) */
 #define SWITCH_INT64(a) { \
index 27148a874719a8e670641e05f5116d57e437ff37..0a98178a8908b6b289dda52d569d01dbfaf97371 100644 (file)
@@ -227,7 +227,7 @@ void ACTION_OT_markers_make_local (wmOperatorType *ot)
 /* *************************** Calculate Range ************************** */
 
 /* Get the min/max keyframes*/
-static void get_keyframe_extents (bAnimContext *ac, float *min, float *max)
+static void get_keyframe_extents (bAnimContext *ac, float *min, float *max, const short onlySel)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
@@ -249,8 +249,8 @@ static void get_keyframe_extents (bAnimContext *ac, float *min, float *max)
                        FCurve *fcu= (FCurve *)ale->key_data;
                        float tmin, tmax;
                        
-                       /* get range and apply necessary scaling before */
-                       calc_fcurve_range(fcu, &tmin, &tmax);
+                       /* get range and apply necessary scaling before processing */
+                       calc_fcurve_range(fcu, &tmin, &tmax, onlySel);
                        
                        if (adt) {
                                tmin= BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP);
@@ -295,7 +295,7 @@ static int actkeys_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
                scene= ac.scene;
        
        /* set the range directly */
-       get_keyframe_extents(&ac, &min, &max);
+       get_keyframe_extents(&ac, &min, &max, FALSE);
        scene->r.flag |= SCER_PRV_RANGE;
        scene->r.psfra= (int)floor(min + 0.5f);
        scene->r.pefra= (int)floor(max + 0.5f);
@@ -324,7 +324,7 @@ void ACTION_OT_previewrange_set (wmOperatorType *ot)
 
 /* ****************** View-All Operator ****************** */
 
-static int actkeys_viewall_exec(bContext *C, wmOperator *UNUSED(op))
+static int actkeys_viewall(bContext *C, const short onlySel)
 {
        bAnimContext ac;
        View2D *v2d;
@@ -336,7 +336,7 @@ static int actkeys_viewall_exec(bContext *C, wmOperator *UNUSED(op))
        v2d= &ac.ar->v2d;
        
        /* set the horizontal range, with an extra offset so that the extreme keys will be in view */
-       get_keyframe_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax);
+       get_keyframe_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, onlySel);
        
        extra= 0.1f * (v2d->cur.xmax - v2d->cur.xmin);
        v2d->cur.xmin -= extra;
@@ -354,6 +354,20 @@ static int actkeys_viewall_exec(bContext *C, wmOperator *UNUSED(op))
        
        return OPERATOR_FINISHED;
 }
+
+/* ......... */
+
+static int actkeys_viewall_exec(bContext *C, wmOperator *UNUSED(op))
+{      
+       /* whole range */
+       return actkeys_viewall(C, FALSE);
+}
+
+static int actkeys_viewsel_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       /* only selected */
+       return actkeys_viewall(C, TRUE);
+}
  
 void ACTION_OT_view_all (wmOperatorType *ot)
 {
@@ -370,6 +384,21 @@ void ACTION_OT_view_all (wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+void ACTION_OT_view_selected (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "View Selected";
+       ot->idname= "ACTION_OT_view_selected";
+       ot->description= "Reset viewable area to show selected keyframes range";
+       
+       /* api callbacks */
+       ot->exec= actkeys_viewsel_exec;
+       ot->poll= ED_operator_action_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
 /* ************************************************************************** */
 /* GENERAL STUFF */
 
index e80b82fcf79b337ffa277ad1cae1d3ad805402d3..512b6e329dd01d7537b3e36c0b5628bb6ed1d453 100644 (file)
@@ -87,6 +87,7 @@ enum {
 
 void ACTION_OT_previewrange_set(struct wmOperatorType *ot);
 void ACTION_OT_view_all(struct wmOperatorType *ot);
+void ACTION_OT_view_selected(struct wmOperatorType *ot);
 
 void ACTION_OT_copy(struct wmOperatorType *ot);
 void ACTION_OT_paste(struct wmOperatorType *ot);
index 6c3258e863910af5e640b6ae616dedfc65229584..b6fbc34550f2d8dd9f8c14a5208875bf00b73e72 100644 (file)
@@ -84,6 +84,7 @@ void action_operatortypes(void)
        
        WM_operatortype_append(ACTION_OT_previewrange_set);
        WM_operatortype_append(ACTION_OT_view_all);
+       WM_operatortype_append(ACTION_OT_view_selected);
        
        WM_operatortype_append(ACTION_OT_markers_make_local);
 }
@@ -181,6 +182,7 @@ static void action_keymap_keyframes (wmKeyConfig *keyconf, wmKeyMap *keymap)
                /* auto-set range */
        WM_keymap_add_item(keymap, "ACTION_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
        WM_keymap_add_item(keymap, "ACTION_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "ACTION_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
        
        /* animation module */
                /* channels list 
index d3e53a11c10cd48ea53971c8f29509f08c2c5d82..fdd43aa05664aaed86896463e4f0782989754052 100644 (file)
@@ -81,7 +81,7 @@
 
 /* Get the min/max keyframes*/
 /* note: it should return total boundbox, filter for selection only can be argument... */
-void get_graph_keyframe_extents (bAnimContext *ac, float *xmin, float *xmax, float *ymin, float *ymax)
+void get_graph_keyframe_extents (bAnimContext *ac, float *xmin, float *xmax, float *ymin, float *ymax, const short selOnly)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
@@ -107,7 +107,7 @@ void get_graph_keyframe_extents (bAnimContext *ac, float *xmin, float *xmax, flo
                        float unitFac;
                        
                        /* get range */
-                       calc_fcurve_bounds(fcu, &txmin, &txmax, &tymin, &tymax);
+                       calc_fcurve_bounds(fcu, &txmin, &txmax, &tymin, &tymax, selOnly);
                        
                        /* apply NLA scaling */
                        if (adt) {
@@ -167,7 +167,7 @@ static int graphkeys_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
                scene= ac.scene;
        
        /* set the range directly */
-       get_graph_keyframe_extents(&ac, &min, &max, NULL, NULL);
+       get_graph_keyframe_extents(&ac, &min, &max, NULL, NULL, FALSE);
        scene->r.flag |= SCER_PRV_RANGE;
        scene->r.psfra= (int)floor(min + 0.5f);
        scene->r.pefra= (int)floor(max + 0.5f);
@@ -196,37 +196,51 @@ void GRAPH_OT_previewrange_set (wmOperatorType *ot)
 
 /* ****************** View-All Operator ****************** */
 
-static int graphkeys_viewall_exec(bContext *C, wmOperator *UNUSED(op))
+static int graphkeys_viewall(bContext *C, const short selOnly)
 {
        bAnimContext ac;
        View2D *v2d;
        float extra;
-       
+
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
        v2d= &ac.ar->v2d;
-       
+
        /* set the horizontal range, with an extra offset so that the extreme keys will be in view */
-       get_graph_keyframe_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, &v2d->cur.ymin, &v2d->cur.ymax);
-       
+       get_graph_keyframe_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, &v2d->cur.ymin, &v2d->cur.ymax, selOnly);
+
        extra= 0.1f * (v2d->cur.xmax - v2d->cur.xmin);
        v2d->cur.xmin -= extra;
        v2d->cur.xmax += extra;
-       
+
        extra= 0.1f * (v2d->cur.ymax - v2d->cur.ymin);
        v2d->cur.ymin -= extra;
        v2d->cur.ymax += extra;
-       
+
        /* do View2D syncing */
        UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
-       
+
        /* set notifier that things have changed */
        ED_area_tag_redraw(CTX_wm_area(C));
-       
+
        return OPERATOR_FINISHED;
 }
+
+/* ......... */
+
+static int graphkeys_viewall_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       /* whole range */
+       return graphkeys_viewall(C, FALSE);
+}
  
+static int graphkeys_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       /* only selected */
+       return graphkeys_viewall(C, TRUE);
+}
+
 void GRAPH_OT_view_all (wmOperatorType *ot)
 {
        /* identifiers */
@@ -242,6 +256,21 @@ void GRAPH_OT_view_all (wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+void GRAPH_OT_view_selected (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "View Selected";
+       ot->idname= "GRAPH_OT_view_selected";
+       ot->description= "Reset viewable area to show selected keyframe range";
+
+       /* api callbacks */
+       ot->exec= graphkeys_view_selected_exec;
+       ot->poll= ED_operator_graphedit_active; // XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier...
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
 /* ******************** Create Ghost-Curves Operator *********************** */
 /* This operator samples the data of the selected F-Curves to F-Points, storing them
  * as 'ghost curves' in the active Graph Editor
index f0a3f797a2b520fa92d907bc1ba76012993c25bb..feb17827db78458eb0d789cab576ea331f107ffa 100644 (file)
@@ -92,10 +92,11 @@ enum {
 /* ***************************************** */
 /* graph_edit.c */
 
-void get_graph_keyframe_extents (struct bAnimContext *ac, float *xmin, float *xmax, float *ymin, float *ymax);
+void get_graph_keyframe_extents (struct bAnimContext *ac, float *xmin, float *xmax, float *ymin, float *ymax, const short do_selected);
 
 void GRAPH_OT_previewrange_set(struct wmOperatorType *ot);
 void GRAPH_OT_view_all(struct wmOperatorType *ot);
+void GRAPH_OT_view_selected(struct wmOperatorType *ot);
 
 void GRAPH_OT_click_insert(struct wmOperatorType *ot);
 void GRAPH_OT_keyframe_insert(struct wmOperatorType *ot);
index b1dae57b574df2cb40d7b44c3f740085535d2e3d..da7de7ca003c57527c37d494c55746f670ea1ace 100644 (file)
@@ -226,6 +226,7 @@ void graphedit_operatortypes(void)
        
        WM_operatortype_append(GRAPH_OT_previewrange_set);
        WM_operatortype_append(GRAPH_OT_view_all);
+       WM_operatortype_append(GRAPH_OT_view_selected);
        WM_operatortype_append(GRAPH_OT_properties);
        
        WM_operatortype_append(GRAPH_OT_ghost_curves_create);
@@ -387,6 +388,7 @@ static void graphedit_keymap_keyframes (wmKeyConfig *keyconf, wmKeyMap *keymap)
                /* auto-set range */
        WM_keymap_add_item(keymap, "GRAPH_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
        WM_keymap_add_item(keymap, "GRAPH_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "GRAPH_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
        
                /* F-Modifiers */
        RNA_boolean_set(WM_keymap_add_item(keymap, "GRAPH_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "only_active", 0);
index e5c605c0a837ec75b66e992caadeb225e47d89f5..554d2e36ccf59492d8c9fc45db402f04f2e594a4 100644 (file)
@@ -253,7 +253,7 @@ static void graph_main_area_draw(const bContext *C, ARegion *ar)
                graph_draw_curves(&ac, sipo, ar, grid, 1);
                
                /* XXX the slow way to set tot rect... but for nice sliders needed (ton) */
-               get_graph_keyframe_extents(&ac, &v2d->tot.xmin, &v2d->tot.xmax, &v2d->tot.ymin, &v2d->tot.ymax);
+               get_graph_keyframe_extents(&ac, &v2d->tot.xmin, &v2d->tot.xmax, &v2d->tot.ymin, &v2d->tot.ymax, FALSE);
                /* extra offset so that these items are visible */
                v2d->tot.xmin -= 10.0f;
                v2d->tot.xmax += 10.0f;
index 05d96c6d6ea563d2921ed13da024dbe7fb973c63..d43de0acdc532b1c3ff8d45d8d0b83e8ce79a973 100644 (file)
@@ -598,7 +598,7 @@ static void rna_FKeyframe_points_remove(FCurve *fcu, ReportList *reports, BezTri
 
 static void rna_fcurve_range(FCurve *fcu, float range[2])
 {
-       calc_fcurve_range(fcu, range, range+1);
+       calc_fcurve_range(fcu, range, range+1, FALSE);
 }
 
 #else