diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index f087727dd9c..90e40dd50fb 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1277,8 +1277,12 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, value += data->coefficients[i] * powers[i]; /* only if something changed, write *cvalue in one go */ - if (data->poly_order) - *cvalue= value; + if (data->poly_order) { + if (data->flag & FCM_GENERATOR_ADDITIVE) + *cvalue += value; + else + *cvalue= value; + } /* cleanup */ if (powers) @@ -1296,8 +1300,12 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, value *= (cp[0]*evaltime + cp[1]); /* only if something changed, write *cvalue in one go */ - if (data->poly_order) - *cvalue= value; + if (data->poly_order) { + if (data->flag & FCM_GENERATOR_ADDITIVE) + *cvalue += value; + else + *cvalue= value; + } } break; @@ -1323,8 +1331,10 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, case FCM_GENERATOR_FN_TAN: /* tangent wave */ { /* check that argument is not on one of the discontinuities (i.e. 90deg, 270 deg, etc) */ - if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) - *cvalue= 0.0f; /* no value possible here */ + if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } else fn= tan; } @@ -1332,19 +1342,25 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, case FCM_GENERATOR_FN_LN: /* natural log */ { /* check that value is greater than 1? */ - if (arg > 1.0f) + if (arg > 1.0f) { fn= log; - else - *cvalue= 0.0f; /* no value possible here */ + } + else { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } } break; case FCM_GENERATOR_FN_SQRT: /* square root */ { /* no negative numbers */ - if (arg > 0.0f) + if (arg > 0.0f) { fn= sqrt; - else - *cvalue= 0.0f; /* no vlaue possible here */ + } + else { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } } break; @@ -1353,8 +1369,14 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, } /* execute function callback to set value if appropriate */ - if (fn) - *cvalue= data->coefficients[0]*fn(arg) + data->coefficients[3]; + if (fn) { + float value= data->coefficients[0]*fn(arg) + data->coefficients[3]; + + if (data->flag & FCM_GENERATOR_ADDITIVE) + *cvalue += value; + else + *cvalue= value; + } } break; @@ -1446,6 +1468,7 @@ static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, f } else { /* evaltime occurs somewhere between segments */ + // TODO: implement binary search for this to make it faster? for (a=0; prevfed && fed && (a < env->totvert-1); a++, prevfed=fed, fed++) { /* evaltime occurs within the interval defined by these two envelope points */ if ((prevfed->time <= evaltime) && (fed->time >= evaltime)) { diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 7892fe029b6..5207d4843f7 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -284,7 +284,7 @@ static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm uiBut *but; /* set the height */ - (*height) = 70; + (*height) = 90; switch (data->mode) { case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */ (*height) += 20*(data->poly_order+1) + 35; @@ -302,9 +302,14 @@ static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm /* basic settings (backdrop + mode selector + some padding) */ //DRAW_BACKDROP((*height)); // XXX buggy... - but= uiDefButS(block, MENU, B_FMODIFIER_REDRAW, gen_mode, 10,cy,width-30,19, &data->mode, 0, 0, 0, 0, "Selects type of generator algorithm."); - uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm); - cy -= 35; + uiBlockBeginAlign(block); + but= uiDefButS(block, MENU, B_FMODIFIER_REDRAW, gen_mode, 10,cy,width-30,19, &data->mode, 0, 0, 0, 0, "Selects type of generator algorithm."); + uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm); + cy -= 20; + + uiDefButBitS(block, TOG, FCM_GENERATOR_ADDITIVE, B_FMODIFIER_REDRAW, "Additive", 10,cy,width-30,19, &data->flag, 0, 0, 0, 0, "Values generated by this modifier are applied on top of the existing values instead of overwriting them"); + cy -= 35; + uiBlockEndAlign(block); /* now add settings for individual modes */ switch (data->mode) { diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index f51300e5f7b..9112a714857 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -91,6 +91,12 @@ enum { FCM_GENERATOR_EXPRESSION, } eFMod_Generator_Modes; +/* generator flags */ +enum { + /* generator works in conjunction with other modifiers (i.e. doesn't replace those before it) */ + FCM_GENERATOR_ADDITIVE = (1<<0), +} eFMod_Generator_Flags; + /* 'function' generator types */ enum { FCM_GENERATOR_FN_SIN = 0, @@ -231,7 +237,7 @@ typedef struct FCurve { /* motion data */ BezTriple *bezt; /* user-editable keyframes (array) */ FPoint *fpt; /* 'baked/imported' motion samples (array) */ - int totvert; /* total number of points which define the curve (i.e. size of arrays in FPoints) */ + unsigned int totvert; /* total number of points which define the curve (i.e. size of arrays in FPoints) */ /* value cache + settings */ float curval; /* value stored from last time curve was evaluated */