From 1ac0d54fea831c485e8e27e8bfa887e15beb58de Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 17 Mar 2009 06:37:50 +0000 Subject: F-Curve Modifiers: Cycles Modifier * Added GUI and fixed bugs in the Cycles Modifier. This replaces the old Cyclic Extrapolation settings, giving more fine-grained control over the results. You can now specify whether the keyframes are repeated before and/or after the range independently, also, the maximum number of cycles on either side can be controlled. * TODO: it would be nice to have the last value held for cyclic+offset. * Deleting modifiers now works --- source/blender/blenkernel/intern/fcurve.c | 25 +++++++---- source/blender/editors/space_graph/graph_buttons.c | 49 ++++++++++++++++++++-- 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 570af95f267..6f6d40c33ba 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -59,7 +59,7 @@ void free_fcurve (FCurve *fcu) fcurve_free_driver(fcu); fcurve_free_modifiers(fcu); - /* free f-cruve itself */ + /* free f-curve itself */ MEM_freeN(fcu); } @@ -1477,6 +1477,14 @@ static FModifierTypeInfo FMI_ENVELOPE = { * as appropriate */ +static void fcm_cycles_new_data (void *mdata) +{ + FMod_Cycles *data= (FMod_Cycles *)mdata; + + /* turn on cycles by default */ + data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC; +} + static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) { FMod_Cycles *data= (FMod_Cycles *)fcm->data; @@ -1522,7 +1530,7 @@ static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, flo * 2) if before first frame or after last frame, make sure some cycling is in use */ if (evaltime < prevkey[0]) { - if (data->before_mode) { + if (data->before_mode) { side= -1; mode= data->before_mode; cycles= data->before_cycles; @@ -1538,8 +1546,7 @@ static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, flo if ELEM(0, side, mode) return; - /* extrapolation mode is 'cyclic' - find relative place within a cycle */ - // FIXME: adding the more fine-grained control of extrpolation mode + /* find relative place within a cycle */ { float cycdx=0, cycdy=0, ofs=0; @@ -1553,15 +1560,19 @@ static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, flo /* check if cycle is infinitely small, to be point of being impossible to use */ if (cycdx == 0) return; + /* check that cyclic is still enabled for the specified time */ if (cycles == 0) { /* catch this case so that we don't exit when we have cycles=0 * as this indicates infinite cycles... */ } - else if ( ((float)side * (evaltime - ofs) / cycdx) > cycles ) + else if ( ((float)side * (evaltime - ofs) / cycdx) > (cycles+1) ) { + /* we are too far away from range to evaluate + * TODO: but we should still hold last value... + */ return; - + } /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */ if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { @@ -1596,7 +1607,7 @@ static FModifierTypeInfo FMI_CYCLES = { "FMod_Cycles", /* struct name */ NULL, /* free data */ NULL, /* copy data */ - NULL, /* new data */ + fcm_cycles_new_data, /* new data */ NULL /*fcm_cycles_verify*/, /* verify */ fcm_cycles_evaluate /* evaluate */ }; diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 59e0fe0ef95..0ec2070902c 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -251,9 +251,19 @@ static void validate_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v) if (fmi && fmi->verify_data) fmi->verify_data(fcm); } + +/* callback to remove the given modifier */ +static void delete_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v) +{ + FCurve *fcu= (FCurve *)fcu_v; + FModifier *fcm= (FModifier *)fcm_v; + + /* remove the given F-Modifier from the F-Curve */ + fcurve_remove_modifier(fcu, fcm); +} /* draw settings for generator modifier */ -static void _draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) { FMod_Generator *data= (FMod_Generator *)fcm->data; char gen_mode[]="Generator Type%t|Expanded Polynomial%x0|Factorised Polynomial%x1|Built-In Function%x2|Expression%x3"; @@ -284,7 +294,7 @@ static void _draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fc uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm); cy -= 35; - /* now add settings for individual modifiers */ + /* now add settings for individual modes */ switch (data->mode) { case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */ { @@ -428,6 +438,33 @@ static void _draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fc } } +/* draw settings for generator modifier */ +static void draw_modifier__cycles(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +{ + FMod_Cycles *data= (FMod_Cycles *)fcm->data; + char cyc_mode[]="Cycling Mode%t|No Cycles%x0|Repeat Motion%x1|Repeat with Offset%x2"; + int cy= (*yco - 30), cy1= (*yco - 50), cy2= (*yco - 70); + + /* set the height */ + (*height) = 90; + + /* basic settings (backdrop + some padding) */ + //DRAW_BACKDROP((*height)); // XXX buggy... + + /* 'before' range */ + uiDefBut(block, LABEL, 1, "Before:", 10, cy, 80, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling before first keyframe"); + uiBlockBeginAlign(block); + uiDefButS(block, MENU, B_FMODIFIER_REDRAW, cyc_mode, 10,cy1,150,20, &data->before_mode, 0, 0, 0, 0, "Cycling mode to use before first keyframe"); + uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Max Cycles:", 10, cy2, 150, 20, &data->before_cycles, 0, 10000, 10, 3, "Maximum number of cycles to allow (0 = infinite)"); + uiBlockEndAlign(block); + + /* 'after' range */ + uiDefBut(block, LABEL, 1, "After:", 160, cy, 80, 20, NULL, 0.0, 0.0, 0, 0, "Settings for cycling after last keyframe"); + uiBlockBeginAlign(block); + uiDefButS(block, MENU, B_FMODIFIER_REDRAW, cyc_mode, 170,cy1,150,20, &data->after_mode, 0, 0, 0, 0, "Cycling mode to use after first keyframe"); + uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Max Cycles:", 170, cy2, 150, 20, &data->after_cycles, 0, 10000, 10, 3, "Maximum number of cycles to allow (0 = infinite)"); + uiBlockEndAlign(block); +} static void graph_panel_modifier_draw(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco) { @@ -461,7 +498,7 @@ static void graph_panel_modifier_draw(uiBlock *block, FCurve *fcu, FModifier *fc /* delete button */ but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 10+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete layer"); - //uiButSetFunc(but, gp_ui_dellayer_cb, gpd, NULL); + uiButSetFunc(but, delete_fmodifier_cb, fcu, fcm); uiBlockSetEmboss(block, UI_EMBOSS); } @@ -471,7 +508,11 @@ static void graph_panel_modifier_draw(uiBlock *block, FCurve *fcu, FModifier *fc /* draw settings for individual modifiers */ switch (fcm->type) { case FMODIFIER_TYPE_GENERATOR: /* Generator */ - _draw_modifier__generator(block, fcu, fcm, yco, &height, width, active, rb_col); + draw_modifier__generator(block, fcu, fcm, yco, &height, width, active, rb_col); + break; + + case FMODIFIER_TYPE_CYCLES: /* Cycles */ + draw_modifier__cycles(block, fcu, fcm, yco, &height, width, active, rb_col); break; default: /* unknown type */ -- cgit v1.2.3