From e3842d1ca4dd2fdc58b8d7819a8a02a688753146 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 17 Mar 2011 10:02:37 +0000 Subject: Bugfix [#26505] zoom in selected keys on graph editor 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. --- source/blender/blenkernel/BKE_fcurve.h | 4 +- source/blender/blenkernel/intern/action.c | 3 +- source/blender/blenkernel/intern/fcurve.c | 87 +++++++++++++++++++--- source/blender/blenlib/BLI_utildefines.h | 3 + source/blender/editors/space_action/action_edit.c | 41 ++++++++-- .../blender/editors/space_action/action_intern.h | 1 + source/blender/editors/space_action/action_ops.c | 2 + source/blender/editors/space_graph/graph_edit.c | 53 ++++++++++--- source/blender/editors/space_graph/graph_intern.h | 3 +- source/blender/editors/space_graph/graph_ops.c | 2 + source/blender/editors/space_graph/space_graph.c | 2 +- source/blender/makesrna/intern/rna_fcurve.c | 2 +- 12 files changed, 167 insertions(+), 36 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index f81acf4b11e..b791e29a38e 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -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); /* .............. */ diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 4c5b7f5fcaf..5b42948072f 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -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); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index a1ed16fc1e5..a5391ee20cc 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -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]); diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index b2129a6ab76..eff70b46157 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -130,6 +130,9 @@ #define IN_RANGE(a, b, c) ((b < c)? ((b= 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) { \ diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 27148a87471..0a98178a890 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -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 */ diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index e80b82fcf79..512b6e329dd 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -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); diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 6c3258e8639..b6fbc34550f 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -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 diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index d3e53a11c10..fdd43aa0566 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -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 diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index f0a3f797a2b..feb17827db7 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -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); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index b1dae57b574..da7de7ca003 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -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); diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index e5c605c0a83..554d2e36ccf 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -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; diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 05d96c6d6ea..d43de0acdc5 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -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 -- cgit v1.2.3