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.
This commit is contained in:
Joshua Leung 2011-03-17 10:02:37 +00:00
parent 58c8dca7a6
commit e3842d1ca4
14 changed files with 169 additions and 36 deletions

@ -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")

@ -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")

@ -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);
/* .............. */

@ -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);

@ -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]);

@ -130,6 +130,9 @@
#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) { \

@ -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 */

@ -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);

@ -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

@ -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

@ -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);

@ -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);

@ -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;

@ -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