Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2009-07-02 09:25:14 +0400
committerJoshua Leung <aligorith@gmail.com>2009-07-02 09:25:14 +0400
commitf3c47a66b0cb3bb70505ed46522e6c557769eaa5 (patch)
tree843833bd2ec06f5250004f2462b25d4d7f879e67
parentb47605d841d0c01b31199bce4499548ecf259bf1 (diff)
NLA SoC: Separating out F-Modifier API
* F-Modifier API is now in its own file in blenkernel * Renamed and refactored these so that they're no dependent on F-Curves, since all they really used was the fcu->modifiers list * Added missing license blocks to a few files
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h14
-rw-r--r--source/blender/blenkernel/intern/fcurve.c1137
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c1197
-rw-r--r--source/blender/blenkernel/intern/ipo.c2
-rw-r--r--source/blender/blenkernel/intern/nla.c13
-rw-r--r--source/blender/editors/animation/drivers.c31
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c21
-rw-r--r--source/blender/editors/animation/keyframing.c29
-rw-r--r--source/blender/editors/animation/keyingsets.c29
-rw-r--r--source/blender/editors/space_graph/graph_draw.c2
-rw-r--r--source/blender/editors/space_graph/graph_edit.c4
-rw-r--r--source/blender/editors/space_graph/graph_utils.c4
12 files changed, 1310 insertions, 1173 deletions
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 5c77e3c2ae4..cfc4e9077f6 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -104,15 +104,15 @@ FModifierTypeInfo *get_fmodifier_typeinfo(int type);
/* ---------------------- */
-struct FModifier *fcurve_add_modifier(struct FCurve *fcu, int type);
-void fcurve_copy_modifiers(ListBase *dst, ListBase *src);
-void fcurve_remove_modifier(struct FCurve *fcu, struct FModifier *fcm);
-void fcurve_free_modifiers(struct FCurve *fcu);
+struct FModifier *add_fmodifier(ListBase *modifiers, int type);
+void copy_fmodifiers(ListBase *dst, ListBase *src);
+void remove_fmodifier(ListBase *modifiers, struct FModifier *fcm);
+void free_fmodifiers(ListBase *modifiers);
-struct FModifier *fcurve_find_active_modifier(struct FCurve *fcu);
-void fcurve_set_active_modifier(struct FCurve *fcu, struct FModifier *fcm);
+struct FModifier *find_active_fmodifier(ListBase *modifiers);
+void set_active_fmodifier(ListBase *modifiers, struct FModifier *fcm);
-short fcurve_has_suitable_modifier(struct FCurve *fcu, int mtype, short acttype);
+short list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype);
float evaluate_time_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float cvalue, float evaltime);
void evaluate_value_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float *cvalue, float evaltime);
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index e52c63d1b21..4c2ba61fc71 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -56,7 +56,7 @@
#include "RNA_types.h"
#ifndef DISABLE_PYTHON
-#include "BPY_extern.h" /* for BPY_pydriver_eval() */
+#include "BPY_extern.h"
#endif
#define SMALL -1.0e-10
@@ -84,7 +84,7 @@ void free_fcurve (FCurve *fcu)
/* free extra data - i.e. modifiers, and driver */
fcurve_free_driver(fcu);
- fcurve_free_modifiers(fcu);
+ free_fmodifiers(&fcu->modifiers);
/* free f-curve itself */
MEM_freeN(fcu);
@@ -140,7 +140,7 @@ FCurve *copy_fcurve (FCurve *fcu)
fcu_d->driver= fcurve_copy_driver(fcu_d->driver);
/* copy modifiers */
- fcurve_copy_modifiers(&fcu_d->modifiers, &fcu->modifiers);
+ copy_fmodifiers(&fcu_d->modifiers, &fcu->modifiers);
/* return new data */
return fcu_d;
@@ -1270,1135 +1270,6 @@ static float fcurve_eval_samples (FCurve *fcu, FPoint *fpts, float evaltime)
return cvalue;
}
-/* ******************************** F-Curve Modifiers ********************************* */
-
-/* Template --------------------------- */
-
-/* Each modifier defines a set of functions, which will be called at the appropriate
- * times. In addition to this, each modifier should have a type-info struct, where
- * its functions are attached for use.
- */
-
-/* Template for type-info data:
- * - make a copy of this when creating new modifiers, and just change the functions
- * pointed to as necessary
- * - although the naming of functions doesn't matter, it would help for code
- * readability, to follow the same naming convention as is presented here
- * - any functions that a constraint doesn't need to define, don't define
- * for such cases, just use NULL
- * - these should be defined after all the functions have been defined, so that
- * forward-definitions/prototypes don't need to be used!
- * - keep this copy #if-def'd so that future constraints can get based off this
- */
-#if 0
-static FModifierTypeInfo FMI_MODNAME = {
- FMODIFIER_TYPE_MODNAME, /* type */
- sizeof(FMod_ModName), /* size */
- FMI_TYPE_SOME_ACTION, /* action type */
- FMI_REQUIRES_SOME_REQUIREMENT, /* requirements */
- "Modifier Name", /* name */
- "FMod_ModName", /* struct name */
- fcm_modname_free, /* free data */
- fcm_modname_relink, /* relink data */
- fcm_modname_copy, /* copy data */
- fcm_modname_new_data, /* new data */
- fcm_modname_verify, /* verify */
- fcm_modname_time, /* evaluate time */
- fcm_modname_evaluate /* evaluate */
-};
-#endif
-
-/* Generator F-Curve Modifier --------------------------- */
-
-/* Generators available:
- * 1) simple polynomial generator:
- * - Exanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n])
- * - Factorised form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1]))
- */
-
-static void fcm_generator_free (FModifier *fcm)
-{
- FMod_Generator *data= (FMod_Generator *)fcm->data;
-
- /* free polynomial coefficients array */
- if (data->coefficients)
- MEM_freeN(data->coefficients);
-}
-
-static void fcm_generator_copy (FModifier *fcm, FModifier *src)
-{
- FMod_Generator *gen= (FMod_Generator *)fcm->data;
- FMod_Generator *ogen= (FMod_Generator *)src->data;
-
- /* copy coefficients array? */
- if (ogen->coefficients)
- gen->coefficients= MEM_dupallocN(ogen->coefficients);
-}
-
-static void fcm_generator_new_data (void *mdata)
-{
- FMod_Generator *data= (FMod_Generator *)mdata;
- float *cp;
-
- /* set default generator to be linear 0-1 (gradient = 1, y-offset = 0) */
- data->poly_order= 1;
- data->arraysize= 2;
- cp= data->coefficients= MEM_callocN(sizeof(float)*2, "FMod_Generator_Coefs");
- cp[0] = 0; // y-offset
- cp[1] = 1; // gradient
-}
-
-static void fcm_generator_verify (FModifier *fcm)
-{
- FMod_Generator *data= (FMod_Generator *)fcm->data;
-
- /* requirements depend on mode */
- switch (data->mode) {
- case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
- {
- /* arraysize needs to be order+1, so resize if not */
- if (data->arraysize != (data->poly_order+1)) {
- float *nc;
-
- /* make new coefficients array, and copy over as much data as can fit */
- nc= MEM_callocN(sizeof(float)*(data->poly_order+1), "FMod_Generator_Coefs");
-
- if (data->coefficients) {
- if (data->arraysize > (data->poly_order+1))
- memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order+1));
- else
- memcpy(nc, data->coefficients, sizeof(float)*data->arraysize);
-
- /* free the old data */
- MEM_freeN(data->coefficients);
- }
-
- /* set the new data */
- data->coefficients= nc;
- data->arraysize= data->poly_order+1;
- }
- }
- break;
-
- case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* expanded polynomial expression */
- {
- /* arraysize needs to be 2*order, so resize if not */
- if (data->arraysize != (data->poly_order * 2)) {
- float *nc;
-
- /* make new coefficients array, and copy over as much data as can fit */
- nc= MEM_callocN(sizeof(float)*(data->poly_order*2), "FMod_Generator_Coefs");
-
- if (data->coefficients) {
- if (data->arraysize > (data->poly_order * 2))
- memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order * 2));
- else
- memcpy(nc, data->coefficients, sizeof(float)*data->arraysize);
-
- /* free the old data */
- MEM_freeN(data->coefficients);
- }
-
- /* set the new data */
- data->coefficients= nc;
- data->arraysize= data->poly_order * 2;
- }
- }
- break;
- }
-}
-
-static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
-{
- FMod_Generator *data= (FMod_Generator *)fcm->data;
-
- /* behaviour depends on mode
- * NOTE: the data in its default state is fine too
- */
- switch (data->mode) {
- case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
- {
- /* we overwrite cvalue with the sum of the polynomial */
- float *powers = MEM_callocN(sizeof(float)*data->arraysize, "Poly Powers");
- float value= 0.0f;
- unsigned int i;
-
- /* for each x^n, precalculate value based on previous one first... this should be
- * faster that calling pow() for each entry
- */
- for (i=0; i < data->arraysize; i++) {
- /* first entry is x^0 = 1, otherwise, calculate based on previous */
- if (i)
- powers[i]= powers[i-1] * evaltime;
- else
- powers[0]= 1;
- }
-
- /* for each coefficient, add to value, which we'll write to *cvalue in one go */
- for (i=0; i < data->arraysize; i++)
- value += data->coefficients[i] * powers[i];
-
- /* only if something changed, write *cvalue in one go */
- if (data->poly_order) {
- if (data->flag & FCM_GENERATOR_ADDITIVE)
- *cvalue += value;
- else
- *cvalue= value;
- }
-
- /* cleanup */
- if (powers)
- MEM_freeN(powers);
- }
- break;
-
- case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */
- {
- float value= 1.0f, *cp=NULL;
- unsigned int i;
-
- /* for each coefficient pair, solve for that bracket before accumulating in value by multiplying */
- for (cp=data->coefficients, i=0; (cp) && (i < data->poly_order); cp+=2, i++)
- value *= (cp[0]*evaltime + cp[1]);
-
- /* only if something changed, write *cvalue in one go */
- if (data->poly_order) {
- if (data->flag & FCM_GENERATOR_ADDITIVE)
- *cvalue += value;
- else
- *cvalue= value;
- }
- }
- break;
- }
-}
-
-static FModifierTypeInfo FMI_GENERATOR = {
- FMODIFIER_TYPE_GENERATOR, /* type */
- sizeof(FMod_Generator), /* size */
- FMI_TYPE_GENERATE_CURVE, /* action type */
- FMI_REQUIRES_NOTHING, /* requirements */
- "Generator", /* name */
- "FMod_Generator", /* struct name */
- fcm_generator_free, /* free data */
- fcm_generator_copy, /* copy data */
- fcm_generator_new_data, /* new data */
- fcm_generator_verify, /* verify */
- NULL, /* evaluate time */
- fcm_generator_evaluate /* evaluate */
-};
-
-/* Built-In Function Generator F-Curve Modifier --------------------------- */
-
-/* This uses the general equation for equations:
- * y = amplitude * fn(phase_multiplier*x + phase_offset) + y_offset
- *
- * where amplitude, phase_multiplier/offset, y_offset are user-defined coefficients,
- * x is the evaluation 'time', and 'y' is the resultant value
- *
- * Functions available are
- * sin, cos, tan, sinc (normalised sin), natural log, square root
- */
-
-static void fcm_fn_generator_new_data (void *mdata)
-{
- FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)mdata;
-
- /* set amplitude and phase multiplier to 1.0f so that something is generated */
- data->amplitude= 1.0f;
- data->phase_multiplier= 1.0f;
-}
-
-/* Unary 'normalised sine' function
- * y = sin(PI + x) / (PI * x),
- * except for x = 0 when y = 1.
- */
-static double sinc (double x)
-{
- if (fabs(x) < 0.0001)
- return 1.0;
- else
- return sin(M_PI * x) / (M_PI * x);
-}
-
-static void fcm_fn_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
-{
- FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data;
- double arg= data->phase_multiplier*evaltime + data->phase_offset;
- double (*fn)(double v) = NULL;
-
- /* get function pointer to the func to use:
- * WARNING: must perform special argument validation hereto guard against crashes
- */
- switch (data->type)
- {
- /* simple ones */
- case FCM_GENERATOR_FN_SIN: /* sine wave */
- fn= sin;
- break;
- case FCM_GENERATOR_FN_COS: /* cosine wave */
- fn= cos;
- break;
- case FCM_GENERATOR_FN_SINC: /* normalised sine wave */
- fn= sinc;
- break;
-
- /* validation required */
- 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) {
- if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
- *cvalue = 0.0f; /* no value possible here */
- }
- else
- fn= tan;
- }
- break;
- case FCM_GENERATOR_FN_LN: /* natural log */
- {
- /* check that value is greater than 1? */
- if (arg > 1.0f) {
- fn= log;
- }
- 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) {
- fn= sqrt;
- }
- else {
- if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
- *cvalue = 0.0f; /* no value possible here */
- }
- }
- break;
-
- default:
- printf("Invalid Function-Generator for F-Modifier - %d \n", data->type);
- }
-
- /* execute function callback to set value if appropriate */
- if (fn) {
- float value= (float)(data->amplitude*fn(arg) + data->value_offset);
-
- if (data->flag & FCM_GENERATOR_ADDITIVE)
- *cvalue += value;
- else
- *cvalue= value;
- }
-}
-
-static FModifierTypeInfo FMI_FN_GENERATOR = {
- FMODIFIER_TYPE_FN_GENERATOR, /* type */
- sizeof(FMod_FunctionGenerator), /* size */
- FMI_TYPE_GENERATE_CURVE, /* action type */
- FMI_REQUIRES_NOTHING, /* requirements */
- "Built-In Function", /* name */
- "FMod_FunctionGenerator", /* struct name */
- NULL, /* free data */
- NULL, /* copy data */
- fcm_fn_generator_new_data, /* new data */
- NULL, /* verify */
- NULL, /* evaluate time */
- fcm_fn_generator_evaluate /* evaluate */
-};
-
-/* Envelope F-Curve Modifier --------------------------- */
-
-static void fcm_envelope_free (FModifier *fcm)
-{
- FMod_Envelope *env= (FMod_Envelope *)fcm->data;
-
- /* free envelope data array */
- if (env->data)
- MEM_freeN(env->data);
-}
-
-static void fcm_envelope_copy (FModifier *fcm, FModifier *src)
-{
- FMod_Envelope *env= (FMod_Envelope *)fcm->data;
- FMod_Envelope *oenv= (FMod_Envelope *)src->data;
-
- /* copy envelope data array */
- if (oenv->data)
- env->data= MEM_dupallocN(oenv->data);
-}
-
-static void fcm_envelope_new_data (void *mdata)
-{
- FMod_Envelope *env= (FMod_Envelope *)mdata;
-
- /* set default min/max ranges */
- env->min= -1.0f;
- env->max= 1.0f;
-}
-
-static void fcm_envelope_verify (FModifier *fcm)
-{
- FMod_Envelope *env= (FMod_Envelope *)fcm->data;
-
- /* if the are points, perform bubble-sort on them, as user may have changed the order */
- if (env->data) {
- // XXX todo...
- }
-}
-
-static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
-{
- FMod_Envelope *env= (FMod_Envelope *)fcm->data;
- FCM_EnvelopeData *fed, *prevfed, *lastfed;
- float min=0.0f, max=0.0f, fac=0.0f;
- int a;
-
- /* get pointers */
- if (env->data == NULL) return;
- prevfed= env->data;
- fed= prevfed + 1;
- lastfed= prevfed + (env->totvert-1);
-
- /* get min/max values for envelope at evaluation time (relative to mid-value) */
- if (prevfed->time >= evaltime) {
- /* before or on first sample, so just extend value */
- min= prevfed->min;
- max= prevfed->max;
- }
- else if (lastfed->time <= evaltime) {
- /* after or on last sample, so just extend value */
- min= lastfed->min;
- max= lastfed->max;
- }
- 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)) {
- float afac, bfac, diff;
-
- diff= fed->time - prevfed->time;
- afac= (evaltime - prevfed->time) / diff;
- bfac= (fed->time - evaltime) / diff;
-
- min= bfac*prevfed->min + afac*fed->min;
- max= bfac*prevfed->max + afac*fed->max;
-
- break;
- }
- }
- }
-
- /* adjust *cvalue
- * - fac is the ratio of how the current y-value corresponds to the reference range
- * - thus, the new value is found by mapping the old range to the new!
- */
- fac= (*cvalue - (env->midval + env->min)) / (env->max - env->min);
- *cvalue= min + fac*(max - min);
-}
-
-static FModifierTypeInfo FMI_ENVELOPE = {
- FMODIFIER_TYPE_ENVELOPE, /* type */
- sizeof(FMod_Envelope), /* size */
- FMI_TYPE_REPLACE_VALUES, /* action type */
- 0, /* requirements */
- "Envelope", /* name */
- "FMod_Envelope", /* struct name */
- fcm_envelope_free, /* free data */
- fcm_envelope_copy, /* copy data */
- fcm_envelope_new_data, /* new data */
- fcm_envelope_verify, /* verify */
- NULL, /* evaluate time */
- fcm_envelope_evaluate /* evaluate */
-};
-
-/* Cycles F-Curve Modifier --------------------------- */
-
-/* This modifier changes evaltime to something that exists within the curve's frame-range,
- * then re-evaluates modifier stack up to this point using the new time. This re-entrant behaviour
- * is very likely to be more time-consuming than the original approach... (which was tighly integrated into
- * the calculation code...).
- *
- * NOTE: this needs to be at the start of the stack to be of use, as it needs to know the extents of the keyframes/sample-data
- * Possible TODO - store length of cycle information that can be initialised from the extents of the keyframes/sample-data, and adjusted
- * as appropriate
- */
-
-/* temp data used during evaluation */
-typedef struct tFCMED_Cycles {
- float cycyofs; /* y-offset to apply */
-} tFCMED_Cycles;
-
-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 float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
-{
- FMod_Cycles *data= (FMod_Cycles *)fcm->data;
- float prevkey[2], lastkey[2], cycyofs=0.0f;
- short side=0, mode=0;
- int cycles=0;
-
- /* check if modifier is first in stack, otherwise disable ourself... */
- // FIXME...
- if (fcm->prev) {
- fcm->flag |= FMODIFIER_FLAG_DISABLED;
- return evaltime;
- }
-
- /* calculate new evaltime due to cyclic interpolation */
- if (fcu && fcu->bezt) {
- BezTriple *prevbezt= fcu->bezt;
- BezTriple *lastbezt= prevbezt + fcu->totvert-1;
-
- prevkey[0]= prevbezt->vec[1][0];
- prevkey[1]= prevbezt->vec[1][1];
-
- lastkey[0]= lastbezt->vec[1][0];
- lastkey[1]= lastbezt->vec[1][1];
- }
- else if (fcu && fcu->fpt) {
- FPoint *prevfpt= fcu->fpt;
- FPoint *lastfpt= prevfpt + fcu->totvert-1;
-
- prevkey[0]= prevfpt->vec[0];
- prevkey[1]= prevfpt->vec[1];
-
- lastkey[0]= lastfpt->vec[0];
- lastkey[1]= lastfpt->vec[1];
- }
- else
- return evaltime;
-
- /* check if modifier will do anything
- * 1) if in data range, definitely don't do anything
- * 2) if before first frame or after last frame, make sure some cycling is in use
- */
- if (evaltime < prevkey[0]) {
- if (data->before_mode) {
- side= -1;
- mode= data->before_mode;
- cycles= data->before_cycles;
- }
- }
- else if (evaltime > lastkey[0]) {
- if (data->after_mode) {
- side= 1;
- mode= data->after_mode;
- cycles= data->after_cycles;
- }
- }
- if ELEM(0, side, mode)
- return evaltime;
-
- /* find relative place within a cycle */
- {
- float cycdx=0, cycdy=0, ofs=0;
- float cycle= 0;
-
- /* ofs is start frame of cycle */
- ofs= prevkey[0];
-
- /* calculate period and amplitude (total height) of a cycle */
- cycdx= lastkey[0] - prevkey[0];
- cycdy= lastkey[1] - prevkey[1];
-
- /* check if cycle is infinitely small, to be point of being impossible to use */
- if (cycdx == 0)
- return evaltime;
-
- /* calculate the 'number' of the cycle */
- cycle= ((float)side * (evaltime - ofs) / cycdx);
-
- /* 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 (cycle > (cycles+1)) {
- /* we are too far away from range to evaluate
- * TODO: but we should still hold last value...
- */
- return evaltime;
- }
-
- /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */
- if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
- cycyofs = (float)floor((evaltime - ofs) / cycdx);
- cycyofs *= cycdy;
- }
-
- /* calculate where in the cycle we are (overwrite evaltime to reflect this) */
- if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle) % 2)) {
- /* when 'mirror' option is used and cycle number is odd, this cycle is played in reverse
- * - for 'before' extrapolation, we need to flip in a different way, otherwise values past
- * then end of the curve get referenced (result of fmod will be negative, and with different phase)
- */
- if (side < 0)
- evaltime= (float)(prevkey[0] - fmod(evaltime-ofs, cycdx));
- else
- evaltime= (float)(lastkey[0] - fmod(evaltime-ofs, cycdx));
- }
- else {
- /* the cycle is played normally... */
- evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs);
- }
- if (evaltime < ofs) evaltime += cycdx;
- }
-
- /* store temp data if needed */
- if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
- tFCMED_Cycles *edata;
-
- /* for now, this is just a float, but we could get more stuff... */
- fcm->edata= edata= MEM_callocN(sizeof(tFCMED_Cycles), "tFCMED_Cycles");
- edata->cycyofs= cycyofs;
- }
-
- /* return the new frame to evaluate */
- return evaltime;
-}
-
-static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
-{
- tFCMED_Cycles *edata= (tFCMED_Cycles *)fcm->edata;
-
- /* use temp data */
- if (edata) {
- /* add cyclic offset - no need to check for now, otherwise the data wouldn't exist! */
- *cvalue += edata->cycyofs;
-
- /* free temp data */
- MEM_freeN(edata);
- fcm->edata= NULL;
- }
-}
-
-static FModifierTypeInfo FMI_CYCLES = {
- FMODIFIER_TYPE_CYCLES, /* type */
- sizeof(FMod_Cycles), /* size */
- FMI_TYPE_EXTRAPOLATION, /* action type */
- FMI_REQUIRES_ORIGINAL_DATA, /* requirements */
- "Cycles", /* name */
- "FMod_Cycles", /* struct name */
- NULL, /* free data */
- NULL, /* copy data */
- fcm_cycles_new_data, /* new data */
- NULL /*fcm_cycles_verify*/, /* verify */
- fcm_cycles_time, /* evaluate time */
- fcm_cycles_evaluate /* evaluate */
-};
-
-/* Noise F-Curve Modifier --------------------------- */
-
-static void fcm_noise_new_data (void *mdata)
-{
- FMod_Noise *data= (FMod_Noise *)mdata;
-
- /* defaults */
- data->size= 1.0f;
- data->strength= 1.0f;
- data->phase= 1.0f;
- data->depth = 0;
- data->modification = FCM_NOISE_MODIF_REPLACE;
-}
-
-static void fcm_noise_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
-{
- FMod_Noise *data= (FMod_Noise *)fcm->data;
- float noise;
-
- noise = BLI_turbulence(data->size, evaltime, data->phase, 0.f, data->depth);
-
- switch (data->modification) {
- case FCM_NOISE_MODIF_ADD:
- *cvalue= *cvalue + noise * data->strength;
- break;
- case FCM_NOISE_MODIF_SUBTRACT:
- *cvalue= *cvalue - noise * data->strength;
- break;
- case FCM_NOISE_MODIF_MULTIPLY:
- *cvalue= *cvalue * noise * data->strength;
- break;
- case FCM_NOISE_MODIF_REPLACE:
- default:
- *cvalue= *cvalue + (noise - 0.5f) * data->strength;
- break;
- }
-}
-
-static FModifierTypeInfo FMI_NOISE = {
- FMODIFIER_TYPE_NOISE, /* type */
- sizeof(FMod_Noise), /* size */
- FMI_TYPE_REPLACE_VALUES, /* action type */
- 0, /* requirements */
- "Noise", /* name */
- "FMod_Noise", /* struct name */
- NULL, /* free data */
- NULL, /* copy data */
- fcm_noise_new_data, /* new data */
- NULL /*fcm_noise_verify*/, /* verify */
- NULL, /* evaluate time */
- fcm_noise_evaluate /* evaluate */
-};
-
-/* Filter F-Curve Modifier --------------------------- */
-
-#if 0 // XXX not yet implemented
-static FModifierTypeInfo FMI_FILTER = {
- FMODIFIER_TYPE_FILTER, /* type */
- sizeof(FMod_Filter), /* size */
- FMI_TYPE_REPLACE_VALUES, /* action type */
- 0, /* requirements */
- "Filter", /* name */
- "FMod_Filter", /* struct name */
- NULL, /* free data */
- NULL, /* copy data */
- NULL, /* new data */
- NULL /*fcm_filter_verify*/, /* verify */
- NULL, /* evlauate time */
- fcm_filter_evaluate /* evaluate */
-};
-#endif // XXX not yet implemented
-
-
-/* Python F-Curve Modifier --------------------------- */
-
-static void fcm_python_free (FModifier *fcm)
-{
- FMod_Python *data= (FMod_Python *)fcm->data;
-
- /* id-properties */
- IDP_FreeProperty(data->prop);
- MEM_freeN(data->prop);
-}
-
-static void fcm_python_new_data (void *mdata)
-{
- FMod_Python *data= (FMod_Python *)mdata;
-
- /* everything should be set correctly by calloc, except for the prop->type constant.*/
- data->prop = MEM_callocN(sizeof(IDProperty), "PyFModifierProps");
- data->prop->type = IDP_GROUP;
-}
-
-static void fcm_python_copy (FModifier *fcm, FModifier *src)
-{
- FMod_Python *pymod = (FMod_Python *)fcm->data;
- FMod_Python *opymod = (FMod_Python *)src->data;
-
- pymod->prop = IDP_CopyProperty(opymod->prop);
-}
-
-static void fcm_python_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
-{
-#ifndef DISABLE_PYTHON
- //FMod_Python *data= (FMod_Python *)fcm->data;
-
- /* FIXME... need to implement this modifier...
- * It will need it execute a script using the custom properties
- */
-#endif /* DISABLE_PYTHON */
-}
-
-static FModifierTypeInfo FMI_PYTHON = {
- FMODIFIER_TYPE_PYTHON, /* type */
- sizeof(FMod_Python), /* size */
- FMI_TYPE_GENERATE_CURVE, /* action type */
- FMI_REQUIRES_RUNTIME_CHECK, /* requirements */
- "Python", /* name */
- "FMod_Python", /* struct name */
- fcm_python_free, /* free data */
- fcm_python_copy, /* copy data */
- fcm_python_new_data, /* new data */
- NULL /*fcm_python_verify*/, /* verify */
- NULL /*fcm_python_time*/, /* evaluate time */
- fcm_python_evaluate /* evaluate */
-};
-
-
-/* Limits F-Curve Modifier --------------------------- */
-
-static float fcm_limits_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
-{
- FMod_Limits *data= (FMod_Limits *)fcm->data;
-
- /* check for the time limits */
- if ((data->flag & FCM_LIMIT_XMIN) && (evaltime < data->rect.xmin))
- return data->rect.xmin;
- if ((data->flag & FCM_LIMIT_XMAX) && (evaltime > data->rect.xmax))
- return data->rect.xmax;
-
- /* modifier doesn't change time */
- return evaltime;
-}
-
-static void fcm_limits_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
-{
- FMod_Limits *data= (FMod_Limits *)fcm->data;
-
- /* value limits now */
- if ((data->flag & FCM_LIMIT_YMIN) && (*cvalue < data->rect.ymin))
- *cvalue= data->rect.ymin;
- if ((data->flag & FCM_LIMIT_YMAX) && (*cvalue > data->rect.ymax))
- *cvalue= data->rect.ymax;
-}
-
-static FModifierTypeInfo FMI_LIMITS = {
- FMODIFIER_TYPE_LIMITS, /* type */
- sizeof(FMod_Limits), /* size */
- FMI_TYPE_GENERATE_CURVE, /* action type */ /* XXX... err... */
- FMI_REQUIRES_RUNTIME_CHECK, /* requirements */
- "Limits", /* name */
- "FMod_Limits", /* struct name */
- NULL, /* free data */
- NULL, /* copy data */
- NULL, /* new data */
- NULL, /* verify */
- fcm_limits_time, /* evaluate time */
- fcm_limits_evaluate /* evaluate */
-};
-
-/* F-Curve Modifier API --------------------------- */
-/* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out
- * and operations that involve F-Curve modifier specific code.
- */
-
-/* These globals only ever get directly accessed in this file */
-static FModifierTypeInfo *fmodifiersTypeInfo[FMODIFIER_NUM_TYPES];
-static short FMI_INIT= 1; /* when non-zero, the list needs to be updated */
-
-/* This function only gets called when FMI_INIT is non-zero */
-static void fmods_init_typeinfo ()
-{
- fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */
- fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */
- fmodifiersTypeInfo[2]= &FMI_FN_GENERATOR; /* Built-In Function Generator F-Curve Modifier */
- fmodifiersTypeInfo[3]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */
- fmodifiersTypeInfo[4]= &FMI_CYCLES; /* Cycles F-Curve Modifier */
- fmodifiersTypeInfo[5]= &FMI_NOISE; /* Apply-Noise F-Curve Modifier */
- fmodifiersTypeInfo[6]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented
- fmodifiersTypeInfo[7]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */
- fmodifiersTypeInfo[8]= &FMI_LIMITS; /* Limits F-Curve Modifier */
-}
-
-/* This function should be used for getting the appropriate type-info when only
- * a F-Curve modifier type is known
- */
-FModifierTypeInfo *get_fmodifier_typeinfo (int type)
-{
- /* initialise the type-info list? */
- if (FMI_INIT) {
- fmods_init_typeinfo();
- FMI_INIT = 0;
- }
-
- /* only return for valid types */
- if ( (type >= FMODIFIER_TYPE_NULL) &&
- (type <= FMODIFIER_NUM_TYPES ) )
- {
- /* there shouldn't be any segfaults here... */
- return fmodifiersTypeInfo[type];
- }
- else {
- printf("No valid F-Curve Modifier type-info data available. Type = %i \n", type);
- }
-
- return NULL;
-}
-
-/* This function should always be used to get the appropriate type-info, as it
- * has checks which prevent segfaults in some weird cases.
- */
-FModifierTypeInfo *fmodifier_get_typeinfo (FModifier *fcm)
-{
- /* only return typeinfo for valid modifiers */
- if (fcm)
- return get_fmodifier_typeinfo(fcm->type);
- else
- return NULL;
-}
-
-/* API --------------------------- */
-
-/* Add a new F-Curve Modifier to the given F-Curve of a certain type */
-FModifier *fcurve_add_modifier (FCurve *fcu, int type)
-{
- FModifierTypeInfo *fmi= get_fmodifier_typeinfo(type);
- FModifier *fcm;
-
- /* sanity checks */
- if ELEM(NULL, fcu, fmi)
- return NULL;
-
- /* special checks for whether modifier can be added */
- if ((fcu->modifiers.first) && (type == FMODIFIER_TYPE_CYCLES)) {
- /* cycles modifier must be first in stack, so for now, don't add if it can't be */
- // TODO: perhaps there is some better way, but for now,
- printf("Error: Cannot add 'Cycles' modifier to F-Curve, as 'Cycles' modifier can only be first in stack. \n");
- return NULL;
- }
-
- /* add modifier itself */
- fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier");
- fcm->type = type;
- fcm->flag = FMODIFIER_FLAG_EXPANDED;
- BLI_addtail(&fcu->modifiers, fcm);
-
- /* add modifier's data */
- fcm->data= MEM_callocN(fmi->size, fmi->structName);
-
- /* init custom settings if necessary */
- if (fmi->new_data)
- fmi->new_data(fcm->data);
-
- /* return modifier for further editing */
- return fcm;
-}
-
-/* Duplicate all of the F-Curve Modifiers in the Modifier stacks */
-void fcurve_copy_modifiers (ListBase *dst, ListBase *src)
-{
- FModifier *fcm, *srcfcm;
-
- if ELEM(NULL, dst, src)
- return;
-
- dst->first= dst->last= NULL;
- BLI_duplicatelist(dst, src);
-
- for (fcm=dst->first, srcfcm=src->first; fcm && srcfcm; srcfcm=srcfcm->next, fcm=fcm->next) {
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
-
- /* make a new copy of the F-Modifier's data */
- fcm->data = MEM_dupallocN(fcm->data);
-
- /* only do specific constraints if required */
- if (fmi && fmi->copy_data)
- fmi->copy_data(fcm, srcfcm);
- }
-}
-
-/* Remove and free the given F-Curve Modifier from the given F-Curve's stack */
-void fcurve_remove_modifier (FCurve *fcu, FModifier *fcm)
-{
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
-
- /* sanity check */
- if (fcm == NULL)
- return;
-
- /* free modifier's special data (stored inside fcm->data) */
- if (fcm->data) {
- if (fmi && fmi->free_data)
- fmi->free_data(fcm);
-
- /* free modifier's data (fcm->data) */
- MEM_freeN(fcm->data);
- }
-
- /* remove modifier from stack */
- if (fcu)
- BLI_freelinkN(&fcu->modifiers, fcm);
- else {
- // XXX this case can probably be removed some day, as it shouldn't happen...
- printf("fcurve_remove_modifier() - no fcurve \n");
- MEM_freeN(fcm);
- }
-}
-
-/* Remove all of a given F-Curve's modifiers */
-void fcurve_free_modifiers (FCurve *fcu)
-{
- FModifier *fcm, *fmn;
-
- /* sanity check */
- if (fcu == NULL)
- return;
-
- /* free each modifier in order - modifier is unlinked from list and freed */
- for (fcm= fcu->modifiers.first; fcm; fcm= fmn) {
- fmn= fcm->next;
- fcurve_remove_modifier(fcu, fcm);
- }
-}
-
-/* Find the active F-Curve Modifier */
-FModifier *fcurve_find_active_modifier (FCurve *fcu)
-{
- FModifier *fcm;
-
- /* sanity checks */
- if ELEM(NULL, fcu, fcu->modifiers.first)
- return NULL;
-
- /* loop over modifiers until 'active' one is found */
- for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
- if (fcm->flag & FMODIFIER_FLAG_ACTIVE)
- return fcm;
- }
-
- /* no modifier is active */
- return NULL;
-}
-
-/* Set the active F-Curve Modifier */
-void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm)
-{
- FModifier *fm;
-
- /* sanity checks */
- if ELEM(NULL, fcu, fcu->modifiers.first)
- return;
-
- /* deactivate all, and set current one active */
- for (fm= fcu->modifiers.first; fm; fm= fm->next)
- fm->flag &= ~FMODIFIER_FLAG_ACTIVE;
-
- /* make given modifier active */
- if (fcm)
- fcm->flag |= FMODIFIER_FLAG_ACTIVE;
-}
-
-/* Do we have any modifiers which match certain criteria
- * - mtype - type of modifier (if 0, doesn't matter)
- * - acttype - type of action to perform (if -1, doesn't matter)
- */
-short fcurve_has_suitable_modifier (FCurve *fcu, int mtype, short acttype)
-{
- FModifier *fcm;
-
- /* if there are no specific filtering criteria, just skip */
- if ((mtype == 0) && (acttype == 0))
- return (fcu && fcu->modifiers.first);
-
- /* sanity checks */
- if ELEM(NULL, fcu, fcu->modifiers.first)
- return 0;
-
- /* find the first mdifier fitting these criteria */
- for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
- short mOk=1, aOk=1; /* by default 1, so that when only one test, won't fail */
-
- /* check if applicable ones are fullfilled */
- if (mtype)
- mOk= (fcm->type == mtype);
- if (acttype > -1)
- aOk= (fmi->acttype == acttype);
-
- /* if both are ok, we've found a hit */
- if (mOk && aOk)
- return 1;
- }
-
- /* no matches */
- return 0;
-}
-
-/* Evaluation API --------------------------- */
-
-/* evaluate time modifications imposed by some F-Curve Modifiers
- * - this step acts as an optimisation to prevent the F-Curve stack being evaluated
- * several times by modifiers requesting the time be modified, as the final result
- * would have required using the modified time
- * - modifiers only ever recieve the unmodified time, as subsequent modifiers should be
- * working on the 'global' result of the modified curve, not some localised segment,
- * so nevaltime gets set to whatever the last time-modifying modifier likes...
- * - we start from the end of the stack, as only the last one matters for now
- */
-float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue, float evaltime)
-{
- FModifier *fcm;
- float m_evaltime= evaltime;
-
- /* sanity checks */
- if ELEM(NULL, modifiers, modifiers->first)
- return evaltime;
-
- /* find the first modifier from end of stack that modifies time, and calculate the time the modifier
- * would calculate time at
- */
- for (fcm= fcu->modifiers.last; fcm; fcm= fcm->prev) {
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
-
- /* only evaluate if there's a callback for this */
- // TODO: implement the 'influence' control feature...
- if (fmi && fmi->evaluate_modifier_time) {
- if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
- m_evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime);
- break;
- }
- }
-
- /* return the modified evaltime */
- return m_evaltime;
-}
-
-/* Evalautes the given set of F-Curve Modifiers using the given data
- * Should only be called after evaluate_time_fmodifiers() has been called...
- */
-void evaluate_value_fmodifiers (ListBase *modifiers, FCurve *fcu, float *cvalue, float evaltime)
-{
- FModifier *fcm;
-
- /* sanity checks */
- if ELEM(NULL, modifiers, modifiers->first)
- return;
-
- /* evaluate modifiers */
- for (fcm= modifiers->first; fcm; fcm= fcm->next) {
- FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
-
- /* only evaluate if there's a callback for this */
- // TODO: implement the 'influence' control feature...
- if (fmi && fmi->evaluate_modifier) {
- if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
- fmi->evaluate_modifier(fcu, fcm, cvalue, evaltime);
- }
- }
-}
-
-
-/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined
- * by start and end (inclusive).
- */
-void fcurve_bake_modifiers (FCurve *fcu, int start, int end)
-{
- ChannelDriver *driver;
-
- /* sanity checks */
- // TODO: make these tests report errors using reports not printf's
- if ELEM(NULL, fcu, fcu->modifiers.first) {
- printf("Error: No F-Curve with F-Curve Modifiers to Bake\n");
- return;
- }
-
- /* temporarily, disable driver while we sample, so that they don't influence the outcome */
- driver= fcu->driver;
- fcu->driver= NULL;
-
- /* bake the modifiers, by sampling the curve at each frame */
- fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve);
-
- /* free the modifiers now */
- fcurve_free_modifiers(fcu);
-
- /* restore driver */
- fcu->driver= driver;
-}
-
/* ***************************** F-Curve - Evaluation ********************************* */
/* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime")
@@ -2450,7 +1321,7 @@ void calculate_fcurve (FCurve *fcu, float ctime)
* any data which warrants this...
*/
if ( (fcu->totvert) || (fcu->driver && !(fcu->driver->flag & DRIVER_FLAG_INVALID)) ||
- fcurve_has_suitable_modifier(fcu, 0, FMI_TYPE_GENERATE_CURVE) )
+ list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) )
{
/* calculate and set curval (evaluates driver too if necessary) */
fcu->curval= evaluate_fcurve(fcu, ctime);
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
new file mode 100644
index 00000000000..aa5214979d9
--- /dev/null
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -0,0 +1,1197 @@
+/**
+ * $Id: fcurve.c 21299 2009-07-02 02:12:37Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
+ * All rights reserved.
+ *
+ * Contributor(s): Joshua Leung (full recode)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+#include <math.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <float.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_anim_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_noise.h"
+
+#include "BKE_fcurve.h"
+#include "BKE_curve.h"
+#include "BKE_global.h"
+#include "BKE_idprop.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+
+#ifndef DISABLE_PYTHON
+#include "BPY_extern.h" /* for BPY_pydriver_eval() */
+#endif
+
+#define SMALL -1.0e-10
+#define SELECT 1
+
+/* ******************************** F-Modifiers ********************************* */
+
+/* Info ------------------------------- */
+
+/* F-Modifiers are modifiers which operate on F-Curves. However, they can also be defined
+ * on NLA-Strips to affect all of the F-Curves referenced by the NLA-Strip.
+ */
+
+/* Template --------------------------- */
+
+/* Each modifier defines a set of functions, which will be called at the appropriate
+ * times. In addition to this, each modifier should have a type-info struct, where
+ * its functions are attached for use.
+ */
+
+/* Template for type-info data:
+ * - make a copy of this when creating new modifiers, and just change the functions
+ * pointed to as necessary
+ * - although the naming of functions doesn't matter, it would help for code
+ * readability, to follow the same naming convention as is presented here
+ * - any functions that a constraint doesn't need to define, don't define
+ * for such cases, just use NULL
+ * - these should be defined after all the functions have been defined, so that
+ * forward-definitions/prototypes don't need to be used!
+ * - keep this copy #if-def'd so that future constraints can get based off this
+ */
+#if 0
+static FModifierTypeInfo FMI_MODNAME = {
+ FMODIFIER_TYPE_MODNAME, /* type */
+ sizeof(FMod_ModName), /* size */
+ FMI_TYPE_SOME_ACTION, /* action type */
+ FMI_REQUIRES_SOME_REQUIREMENT, /* requirements */
+ "Modifier Name", /* name */
+ "FMod_ModName", /* struct name */
+ fcm_modname_free, /* free data */
+ fcm_modname_relink, /* relink data */
+ fcm_modname_copy, /* copy data */
+ fcm_modname_new_data, /* new data */
+ fcm_modname_verify, /* verify */
+ fcm_modname_time, /* evaluate time */
+ fcm_modname_evaluate /* evaluate */
+};
+#endif
+
+/* Generator F-Curve Modifier --------------------------- */
+
+/* Generators available:
+ * 1) simple polynomial generator:
+ * - Exanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n])
+ * - Factorised form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1]))
+ */
+
+static void fcm_generator_free (FModifier *fcm)
+{
+ FMod_Generator *data= (FMod_Generator *)fcm->data;
+
+ /* free polynomial coefficients array */
+ if (data->coefficients)
+ MEM_freeN(data->coefficients);
+}
+
+static void fcm_generator_copy (FModifier *fcm, FModifier *src)
+{
+ FMod_Generator *gen= (FMod_Generator *)fcm->data;
+ FMod_Generator *ogen= (FMod_Generator *)src->data;
+
+ /* copy coefficients array? */
+ if (ogen->coefficients)
+ gen->coefficients= MEM_dupallocN(ogen->coefficients);
+}
+
+static void fcm_generator_new_data (void *mdata)
+{
+ FMod_Generator *data= (FMod_Generator *)mdata;
+ float *cp;
+
+ /* set default generator to be linear 0-1 (gradient = 1, y-offset = 0) */
+ data->poly_order= 1;
+ data->arraysize= 2;
+ cp= data->coefficients= MEM_callocN(sizeof(float)*2, "FMod_Generator_Coefs");
+ cp[0] = 0; // y-offset
+ cp[1] = 1; // gradient
+}
+
+static void fcm_generator_verify (FModifier *fcm)
+{
+ FMod_Generator *data= (FMod_Generator *)fcm->data;
+
+ /* requirements depend on mode */
+ switch (data->mode) {
+ case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
+ {
+ /* arraysize needs to be order+1, so resize if not */
+ if (data->arraysize != (data->poly_order+1)) {
+ float *nc;
+
+ /* make new coefficients array, and copy over as much data as can fit */
+ nc= MEM_callocN(sizeof(float)*(data->poly_order+1), "FMod_Generator_Coefs");
+
+ if (data->coefficients) {
+ if (data->arraysize > (data->poly_order+1))
+ memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order+1));
+ else
+ memcpy(nc, data->coefficients, sizeof(float)*data->arraysize);
+
+ /* free the old data */
+ MEM_freeN(data->coefficients);
+ }
+
+ /* set the new data */
+ data->coefficients= nc;
+ data->arraysize= data->poly_order+1;
+ }
+ }
+ break;
+
+ case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* expanded polynomial expression */
+ {
+ /* arraysize needs to be 2*order, so resize if not */
+ if (data->arraysize != (data->poly_order * 2)) {
+ float *nc;
+
+ /* make new coefficients array, and copy over as much data as can fit */
+ nc= MEM_callocN(sizeof(float)*(data->poly_order*2), "FMod_Generator_Coefs");
+
+ if (data->coefficients) {
+ if (data->arraysize > (data->poly_order * 2))
+ memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order * 2));
+ else
+ memcpy(nc, data->coefficients, sizeof(float)*data->arraysize);
+
+ /* free the old data */
+ MEM_freeN(data->coefficients);
+ }
+
+ /* set the new data */
+ data->coefficients= nc;
+ data->arraysize= data->poly_order * 2;
+ }
+ }
+ break;
+ }
+}
+
+static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+{
+ FMod_Generator *data= (FMod_Generator *)fcm->data;
+
+ /* behaviour depends on mode
+ * NOTE: the data in its default state is fine too
+ */
+ switch (data->mode) {
+ case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
+ {
+ /* we overwrite cvalue with the sum of the polynomial */
+ float *powers = MEM_callocN(sizeof(float)*data->arraysize, "Poly Powers");
+ float value= 0.0f;
+ unsigned int i;
+
+ /* for each x^n, precalculate value based on previous one first... this should be
+ * faster that calling pow() for each entry
+ */
+ for (i=0; i < data->arraysize; i++) {
+ /* first entry is x^0 = 1, otherwise, calculate based on previous */
+ if (i)
+ powers[i]= powers[i-1] * evaltime;
+ else
+ powers[0]= 1;
+ }
+
+ /* for each coefficient, add to value, which we'll write to *cvalue in one go */
+ for (i=0; i < data->arraysize; i++)
+ value += data->coefficients[i] * powers[i];
+
+ /* only if something changed, write *cvalue in one go */
+ if (data->poly_order) {
+ if (data->flag & FCM_GENERATOR_ADDITIVE)
+ *cvalue += value;
+ else
+ *cvalue= value;
+ }
+
+ /* cleanup */
+ if (powers)
+ MEM_freeN(powers);
+ }
+ break;
+
+ case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */
+ {
+ float value= 1.0f, *cp=NULL;
+ unsigned int i;
+
+ /* for each coefficient pair, solve for that bracket before accumulating in value by multiplying */
+ for (cp=data->coefficients, i=0; (cp) && (i < data->poly_order); cp+=2, i++)
+ value *= (cp[0]*evaltime + cp[1]);
+
+ /* only if something changed, write *cvalue in one go */
+ if (data->poly_order) {
+ if (data->flag & FCM_GENERATOR_ADDITIVE)
+ *cvalue += value;
+ else
+ *cvalue= value;
+ }
+ }
+ break;
+ }
+}
+
+static FModifierTypeInfo FMI_GENERATOR = {
+ FMODIFIER_TYPE_GENERATOR, /* type */
+ sizeof(FMod_Generator), /* size */
+ FMI_TYPE_GENERATE_CURVE, /* action type */
+ FMI_REQUIRES_NOTHING, /* requirements */
+ "Generator", /* name */
+ "FMod_Generator", /* struct name */
+ fcm_generator_free, /* free data */
+ fcm_generator_copy, /* copy data */
+ fcm_generator_new_data, /* new data */
+ fcm_generator_verify, /* verify */
+ NULL, /* evaluate time */
+ fcm_generator_evaluate /* evaluate */
+};
+
+/* Built-In Function Generator F-Curve Modifier --------------------------- */
+
+/* This uses the general equation for equations:
+ * y = amplitude * fn(phase_multiplier*x + phase_offset) + y_offset
+ *
+ * where amplitude, phase_multiplier/offset, y_offset are user-defined coefficients,
+ * x is the evaluation 'time', and 'y' is the resultant value
+ *
+ * Functions available are
+ * sin, cos, tan, sinc (normalised sin), natural log, square root
+ */
+
+static void fcm_fn_generator_new_data (void *mdata)
+{
+ FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)mdata;
+
+ /* set amplitude and phase multiplier to 1.0f so that something is generated */
+ data->amplitude= 1.0f;
+ data->phase_multiplier= 1.0f;
+}
+
+/* Unary 'normalised sine' function
+ * y = sin(PI + x) / (PI * x),
+ * except for x = 0 when y = 1.
+ */
+static double sinc (double x)
+{
+ if (fabs(x) < 0.0001)
+ return 1.0;
+ else
+ return sin(M_PI * x) / (M_PI * x);
+}
+
+static void fcm_fn_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+{
+ FMod_FunctionGenerator *data= (FMod_FunctionGenerator *)fcm->data;
+ double arg= data->phase_multiplier*evaltime + data->phase_offset;
+ double (*fn)(double v) = NULL;
+
+ /* get function pointer to the func to use:
+ * WARNING: must perform special argument validation hereto guard against crashes
+ */
+ switch (data->type)
+ {
+ /* simple ones */
+ case FCM_GENERATOR_FN_SIN: /* sine wave */
+ fn= sin;
+ break;
+ case FCM_GENERATOR_FN_COS: /* cosine wave */
+ fn= cos;
+ break;
+ case FCM_GENERATOR_FN_SINC: /* normalised sine wave */
+ fn= sinc;
+ break;
+
+ /* validation required */
+ 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) {
+ if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
+ *cvalue = 0.0f; /* no value possible here */
+ }
+ else
+ fn= tan;
+ }
+ break;
+ case FCM_GENERATOR_FN_LN: /* natural log */
+ {
+ /* check that value is greater than 1? */
+ if (arg > 1.0f) {
+ fn= log;
+ }
+ 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) {
+ fn= sqrt;
+ }
+ else {
+ if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
+ *cvalue = 0.0f; /* no value possible here */
+ }
+ }
+ break;
+
+ default:
+ printf("Invalid Function-Generator for F-Modifier - %d \n", data->type);
+ }
+
+ /* execute function callback to set value if appropriate */
+ if (fn) {
+ float value= (float)(data->amplitude*fn(arg) + data->value_offset);
+
+ if (data->flag & FCM_GENERATOR_ADDITIVE)
+ *cvalue += value;
+ else
+ *cvalue= value;
+ }
+}
+
+static FModifierTypeInfo FMI_FN_GENERATOR = {
+ FMODIFIER_TYPE_FN_GENERATOR, /* type */
+ sizeof(FMod_FunctionGenerator), /* size */
+ FMI_TYPE_GENERATE_CURVE, /* action type */
+ FMI_REQUIRES_NOTHING, /* requirements */
+ "Built-In Function", /* name */
+ "FMod_FunctionGenerator", /* struct name */
+ NULL, /* free data */
+ NULL, /* copy data */
+ fcm_fn_generator_new_data, /* new data */
+ NULL, /* verify */
+ NULL, /* evaluate time */
+ fcm_fn_generator_evaluate /* evaluate */
+};
+
+/* Envelope F-Curve Modifier --------------------------- */
+
+static void fcm_envelope_free (FModifier *fcm)
+{
+ FMod_Envelope *env= (FMod_Envelope *)fcm->data;
+
+ /* free envelope data array */
+ if (env->data)
+ MEM_freeN(env->data);
+}
+
+static void fcm_envelope_copy (FModifier *fcm, FModifier *src)
+{
+ FMod_Envelope *env= (FMod_Envelope *)fcm->data;
+ FMod_Envelope *oenv= (FMod_Envelope *)src->data;
+
+ /* copy envelope data array */
+ if (oenv->data)
+ env->data= MEM_dupallocN(oenv->data);
+}
+
+static void fcm_envelope_new_data (void *mdata)
+{
+ FMod_Envelope *env= (FMod_Envelope *)mdata;
+
+ /* set default min/max ranges */
+ env->min= -1.0f;
+ env->max= 1.0f;
+}
+
+static void fcm_envelope_verify (FModifier *fcm)
+{
+ FMod_Envelope *env= (FMod_Envelope *)fcm->data;
+
+ /* if the are points, perform bubble-sort on them, as user may have changed the order */
+ if (env->data) {
+ // XXX todo...
+ }
+}
+
+static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+{
+ FMod_Envelope *env= (FMod_Envelope *)fcm->data;
+ FCM_EnvelopeData *fed, *prevfed, *lastfed;
+ float min=0.0f, max=0.0f, fac=0.0f;
+ int a;
+
+ /* get pointers */
+ if (env->data == NULL) return;
+ prevfed= env->data;
+ fed= prevfed + 1;
+ lastfed= prevfed + (env->totvert-1);
+
+ /* get min/max values for envelope at evaluation time (relative to mid-value) */
+ if (prevfed->time >= evaltime) {
+ /* before or on first sample, so just extend value */
+ min= prevfed->min;
+ max= prevfed->max;
+ }
+ else if (lastfed->time <= evaltime) {
+ /* after or on last sample, so just extend value */
+ min= lastfed->min;
+ max= lastfed->max;
+ }
+ 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)) {
+ float afac, bfac, diff;
+
+ diff= fed->time - prevfed->time;
+ afac= (evaltime - prevfed->time) / diff;
+ bfac= (fed->time - evaltime) / diff;
+
+ min= bfac*prevfed->min + afac*fed->min;
+ max= bfac*prevfed->max + afac*fed->max;
+
+ break;
+ }
+ }
+ }
+
+ /* adjust *cvalue
+ * - fac is the ratio of how the current y-value corresponds to the reference range
+ * - thus, the new value is found by mapping the old range to the new!
+ */
+ fac= (*cvalue - (env->midval + env->min)) / (env->max - env->min);
+ *cvalue= min + fac*(max - min);
+}
+
+static FModifierTypeInfo FMI_ENVELOPE = {
+ FMODIFIER_TYPE_ENVELOPE, /* type */
+ sizeof(FMod_Envelope), /* size */
+ FMI_TYPE_REPLACE_VALUES, /* action type */
+ 0, /* requirements */
+ "Envelope", /* name */
+ "FMod_Envelope", /* struct name */
+ fcm_envelope_free, /* free data */
+ fcm_envelope_copy, /* copy data */
+ fcm_envelope_new_data, /* new data */
+ fcm_envelope_verify, /* verify */
+ NULL, /* evaluate time */
+ fcm_envelope_evaluate /* evaluate */
+};
+
+/* Cycles F-Curve Modifier --------------------------- */
+
+/* This modifier changes evaltime to something that exists within the curve's frame-range,
+ * then re-evaluates modifier stack up to this point using the new time. This re-entrant behaviour
+ * is very likely to be more time-consuming than the original approach... (which was tighly integrated into
+ * the calculation code...).
+ *
+ * NOTE: this needs to be at the start of the stack to be of use, as it needs to know the extents of the keyframes/sample-data
+ * Possible TODO - store length of cycle information that can be initialised from the extents of the keyframes/sample-data, and adjusted
+ * as appropriate
+ */
+
+/* temp data used during evaluation */
+typedef struct tFCMED_Cycles {
+ float cycyofs; /* y-offset to apply */
+} tFCMED_Cycles;
+
+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 float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
+{
+ FMod_Cycles *data= (FMod_Cycles *)fcm->data;
+ float prevkey[2], lastkey[2], cycyofs=0.0f;
+ short side=0, mode=0;
+ int cycles=0;
+
+ /* check if modifier is first in stack, otherwise disable ourself... */
+ // FIXME...
+ if (fcm->prev) {
+ fcm->flag |= FMODIFIER_FLAG_DISABLED;
+ return evaltime;
+ }
+
+ /* calculate new evaltime due to cyclic interpolation */
+ if (fcu && fcu->bezt) {
+ BezTriple *prevbezt= fcu->bezt;
+ BezTriple *lastbezt= prevbezt + fcu->totvert-1;
+
+ prevkey[0]= prevbezt->vec[1][0];
+ prevkey[1]= prevbezt->vec[1][1];
+
+ lastkey[0]= lastbezt->vec[1][0];
+ lastkey[1]= lastbezt->vec[1][1];
+ }
+ else if (fcu && fcu->fpt) {
+ FPoint *prevfpt= fcu->fpt;
+ FPoint *lastfpt= prevfpt + fcu->totvert-1;
+
+ prevkey[0]= prevfpt->vec[0];
+ prevkey[1]= prevfpt->vec[1];
+
+ lastkey[0]= lastfpt->vec[0];
+ lastkey[1]= lastfpt->vec[1];
+ }
+ else
+ return evaltime;
+
+ /* check if modifier will do anything
+ * 1) if in data range, definitely don't do anything
+ * 2) if before first frame or after last frame, make sure some cycling is in use
+ */
+ if (evaltime < prevkey[0]) {
+ if (data->before_mode) {
+ side= -1;
+ mode= data->before_mode;
+ cycles= data->before_cycles;
+ }
+ }
+ else if (evaltime > lastkey[0]) {
+ if (data->after_mode) {
+ side= 1;
+ mode= data->after_mode;
+ cycles= data->after_cycles;
+ }
+ }
+ if ELEM(0, side, mode)
+ return evaltime;
+
+ /* find relative place within a cycle */
+ {
+ float cycdx=0, cycdy=0, ofs=0;
+ float cycle= 0;
+
+ /* ofs is start frame of cycle */
+ ofs= prevkey[0];
+
+ /* calculate period and amplitude (total height) of a cycle */
+ cycdx= lastkey[0] - prevkey[0];
+ cycdy= lastkey[1] - prevkey[1];
+
+ /* check if cycle is infinitely small, to be point of being impossible to use */
+ if (cycdx == 0)
+ return evaltime;
+
+ /* calculate the 'number' of the cycle */
+ cycle= ((float)side * (evaltime - ofs) / cycdx);
+
+ /* 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 (cycle > (cycles+1)) {
+ /* we are too far away from range to evaluate
+ * TODO: but we should still hold last value...
+ */
+ return evaltime;
+ }
+
+ /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */
+ if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
+ cycyofs = (float)floor((evaltime - ofs) / cycdx);
+ cycyofs *= cycdy;
+ }
+
+ /* calculate where in the cycle we are (overwrite evaltime to reflect this) */
+ if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle) % 2)) {
+ /* when 'mirror' option is used and cycle number is odd, this cycle is played in reverse
+ * - for 'before' extrapolation, we need to flip in a different way, otherwise values past
+ * then end of the curve get referenced (result of fmod will be negative, and with different phase)
+ */
+ if (side < 0)
+ evaltime= (float)(prevkey[0] - fmod(evaltime-ofs, cycdx));
+ else
+ evaltime= (float)(lastkey[0] - fmod(evaltime-ofs, cycdx));
+ }
+ else {
+ /* the cycle is played normally... */
+ evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs);
+ }
+ if (evaltime < ofs) evaltime += cycdx;
+ }
+
+ /* store temp data if needed */
+ if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
+ tFCMED_Cycles *edata;
+
+ /* for now, this is just a float, but we could get more stuff... */
+ fcm->edata= edata= MEM_callocN(sizeof(tFCMED_Cycles), "tFCMED_Cycles");
+ edata->cycyofs= cycyofs;
+ }
+
+ /* return the new frame to evaluate */
+ return evaltime;
+}
+
+static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+{
+ tFCMED_Cycles *edata= (tFCMED_Cycles *)fcm->edata;
+
+ /* use temp data */
+ if (edata) {
+ /* add cyclic offset - no need to check for now, otherwise the data wouldn't exist! */
+ *cvalue += edata->cycyofs;
+
+ /* free temp data */
+ MEM_freeN(edata);
+ fcm->edata= NULL;
+ }
+}
+
+static FModifierTypeInfo FMI_CYCLES = {
+ FMODIFIER_TYPE_CYCLES, /* type */
+ sizeof(FMod_Cycles), /* size */
+ FMI_TYPE_EXTRAPOLATION, /* action type */
+ FMI_REQUIRES_ORIGINAL_DATA, /* requirements */
+ "Cycles", /* name */
+ "FMod_Cycles", /* struct name */
+ NULL, /* free data */
+ NULL, /* copy data */
+ fcm_cycles_new_data, /* new data */
+ NULL /*fcm_cycles_verify*/, /* verify */
+ fcm_cycles_time, /* evaluate time */
+ fcm_cycles_evaluate /* evaluate */
+};
+
+/* Noise F-Curve Modifier --------------------------- */
+
+static void fcm_noise_new_data (void *mdata)
+{
+ FMod_Noise *data= (FMod_Noise *)mdata;
+
+ /* defaults */
+ data->size= 1.0f;
+ data->strength= 1.0f;
+ data->phase= 1.0f;
+ data->depth = 0;
+ data->modification = FCM_NOISE_MODIF_REPLACE;
+}
+
+static void fcm_noise_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+{
+ FMod_Noise *data= (FMod_Noise *)fcm->data;
+ float noise;
+
+ noise = BLI_turbulence(data->size, evaltime, data->phase, 0.f, data->depth);
+
+ switch (data->modification) {
+ case FCM_NOISE_MODIF_ADD:
+ *cvalue= *cvalue + noise * data->strength;
+ break;
+ case FCM_NOISE_MODIF_SUBTRACT:
+ *cvalue= *cvalue - noise * data->strength;
+ break;
+ case FCM_NOISE_MODIF_MULTIPLY:
+ *cvalue= *cvalue * noise * data->strength;
+ break;
+ case FCM_NOISE_MODIF_REPLACE:
+ default:
+ *cvalue= *cvalue + (noise - 0.5f) * data->strength;
+ break;
+ }
+}
+
+static FModifierTypeInfo FMI_NOISE = {
+ FMODIFIER_TYPE_NOISE, /* type */
+ sizeof(FMod_Noise), /* size */
+ FMI_TYPE_REPLACE_VALUES, /* action type */
+ 0, /* requirements */
+ "Noise", /* name */
+ "FMod_Noise", /* struct name */
+ NULL, /* free data */
+ NULL, /* copy data */
+ fcm_noise_new_data, /* new data */
+ NULL /*fcm_noise_verify*/, /* verify */
+ NULL, /* evaluate time */
+ fcm_noise_evaluate /* evaluate */
+};
+
+/* Filter F-Curve Modifier --------------------------- */
+
+#if 0 // XXX not yet implemented
+static FModifierTypeInfo FMI_FILTER = {
+ FMODIFIER_TYPE_FILTER, /* type */
+ sizeof(FMod_Filter), /* size */
+ FMI_TYPE_REPLACE_VALUES, /* action type */
+ 0, /* requirements */
+ "Filter", /* name */
+ "FMod_Filter", /* struct name */
+ NULL, /* free data */
+ NULL, /* copy data */
+ NULL, /* new data */
+ NULL /*fcm_filter_verify*/, /* verify */
+ NULL, /* evlauate time */
+ fcm_filter_evaluate /* evaluate */
+};
+#endif // XXX not yet implemented
+
+
+/* Python F-Curve Modifier --------------------------- */
+
+static void fcm_python_free (FModifier *fcm)
+{
+ FMod_Python *data= (FMod_Python *)fcm->data;
+
+ /* id-properties */
+ IDP_FreeProperty(data->prop);
+ MEM_freeN(data->prop);
+}
+
+static void fcm_python_new_data (void *mdata)
+{
+ FMod_Python *data= (FMod_Python *)mdata;
+
+ /* everything should be set correctly by calloc, except for the prop->type constant.*/
+ data->prop = MEM_callocN(sizeof(IDProperty), "PyFModifierProps");
+ data->prop->type = IDP_GROUP;
+}
+
+static void fcm_python_copy (FModifier *fcm, FModifier *src)
+{
+ FMod_Python *pymod = (FMod_Python *)fcm->data;
+ FMod_Python *opymod = (FMod_Python *)src->data;
+
+ pymod->prop = IDP_CopyProperty(opymod->prop);
+}
+
+static void fcm_python_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+{
+#ifndef DISABLE_PYTHON
+ //FMod_Python *data= (FMod_Python *)fcm->data;
+
+ /* FIXME... need to implement this modifier...
+ * It will need it execute a script using the custom properties
+ */
+#endif /* DISABLE_PYTHON */
+}
+
+static FModifierTypeInfo FMI_PYTHON = {
+ FMODIFIER_TYPE_PYTHON, /* type */
+ sizeof(FMod_Python), /* size */
+ FMI_TYPE_GENERATE_CURVE, /* action type */
+ FMI_REQUIRES_RUNTIME_CHECK, /* requirements */
+ "Python", /* name */
+ "FMod_Python", /* struct name */
+ fcm_python_free, /* free data */
+ fcm_python_copy, /* copy data */
+ fcm_python_new_data, /* new data */
+ NULL /*fcm_python_verify*/, /* verify */
+ NULL /*fcm_python_time*/, /* evaluate time */
+ fcm_python_evaluate /* evaluate */
+};
+
+
+/* Limits F-Curve Modifier --------------------------- */
+
+static float fcm_limits_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
+{
+ FMod_Limits *data= (FMod_Limits *)fcm->data;
+
+ /* check for the time limits */
+ if ((data->flag & FCM_LIMIT_XMIN) && (evaltime < data->rect.xmin))
+ return data->rect.xmin;
+ if ((data->flag & FCM_LIMIT_XMAX) && (evaltime > data->rect.xmax))
+ return data->rect.xmax;
+
+ /* modifier doesn't change time */
+ return evaltime;
+}
+
+static void fcm_limits_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+{
+ FMod_Limits *data= (FMod_Limits *)fcm->data;
+
+ /* value limits now */
+ if ((data->flag & FCM_LIMIT_YMIN) && (*cvalue < data->rect.ymin))
+ *cvalue= data->rect.ymin;
+ if ((data->flag & FCM_LIMIT_YMAX) && (*cvalue > data->rect.ymax))
+ *cvalue= data->rect.ymax;
+}
+
+static FModifierTypeInfo FMI_LIMITS = {
+ FMODIFIER_TYPE_LIMITS, /* type */
+ sizeof(FMod_Limits), /* size */
+ FMI_TYPE_GENERATE_CURVE, /* action type */ /* XXX... err... */
+ FMI_REQUIRES_RUNTIME_CHECK, /* requirements */
+ "Limits", /* name */
+ "FMod_Limits", /* struct name */
+ NULL, /* free data */
+ NULL, /* copy data */
+ NULL, /* new data */
+ NULL, /* verify */
+ fcm_limits_time, /* evaluate time */
+ fcm_limits_evaluate /* evaluate */
+};
+
+/* F-Curve Modifier API --------------------------- */
+/* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out
+ * and operations that involve F-Curve modifier specific code.
+ */
+
+/* These globals only ever get directly accessed in this file */
+static FModifierTypeInfo *fmodifiersTypeInfo[FMODIFIER_NUM_TYPES];
+static short FMI_INIT= 1; /* when non-zero, the list needs to be updated */
+
+/* This function only gets called when FMI_INIT is non-zero */
+static void fmods_init_typeinfo ()
+{
+ fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */
+ fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */
+ fmodifiersTypeInfo[2]= &FMI_FN_GENERATOR; /* Built-In Function Generator F-Curve Modifier */
+ fmodifiersTypeInfo[3]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */
+ fmodifiersTypeInfo[4]= &FMI_CYCLES; /* Cycles F-Curve Modifier */
+ fmodifiersTypeInfo[5]= &FMI_NOISE; /* Apply-Noise F-Curve Modifier */
+ fmodifiersTypeInfo[6]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented
+ fmodifiersTypeInfo[7]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */
+ fmodifiersTypeInfo[8]= &FMI_LIMITS; /* Limits F-Curve Modifier */
+}
+
+/* This function should be used for getting the appropriate type-info when only
+ * a F-Curve modifier type is known
+ */
+FModifierTypeInfo *get_fmodifier_typeinfo (int type)
+{
+ /* initialise the type-info list? */
+ if (FMI_INIT) {
+ fmods_init_typeinfo();
+ FMI_INIT = 0;
+ }
+
+ /* only return for valid types */
+ if ( (type >= FMODIFIER_TYPE_NULL) &&
+ (type <= FMODIFIER_NUM_TYPES ) )
+ {
+ /* there shouldn't be any segfaults here... */
+ return fmodifiersTypeInfo[type];
+ }
+ else {
+ printf("No valid F-Curve Modifier type-info data available. Type = %i \n", type);
+ }
+
+ return NULL;
+}
+
+/* This function should always be used to get the appropriate type-info, as it
+ * has checks which prevent segfaults in some weird cases.
+ */
+FModifierTypeInfo *fmodifier_get_typeinfo (FModifier *fcm)
+{
+ /* only return typeinfo for valid modifiers */
+ if (fcm)
+ return get_fmodifier_typeinfo(fcm->type);
+ else
+ return NULL;
+}
+
+/* API --------------------------- */
+
+/* Add a new F-Curve Modifier to the given F-Curve of a certain type */
+FModifier *add_fmodifier (ListBase *modifiers, int type)
+{
+ FModifierTypeInfo *fmi= get_fmodifier_typeinfo(type);
+ FModifier *fcm;
+
+ /* sanity checks */
+ if ELEM(NULL, modifiers, fmi)
+ return NULL;
+
+ /* special checks for whether modifier can be added */
+ if ((modifiers->first) && (type == FMODIFIER_TYPE_CYCLES)) {
+ /* cycles modifier must be first in stack, so for now, don't add if it can't be */
+ // TODO: perhaps there is some better way, but for now,
+ printf("Error: Cannot add 'Cycles' modifier to F-Curve, as 'Cycles' modifier can only be first in stack. \n");
+ return NULL;
+ }
+
+ /* add modifier itself */
+ fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier");
+ fcm->type = type;
+ fcm->flag = FMODIFIER_FLAG_EXPANDED;
+ BLI_addtail(modifiers, fcm);
+
+ /* add modifier's data */
+ fcm->data= MEM_callocN(fmi->size, fmi->structName);
+
+ /* init custom settings if necessary */
+ if (fmi->new_data)
+ fmi->new_data(fcm->data);
+
+ /* return modifier for further editing */
+ return fcm;
+}
+
+/* Duplicate all of the F-Modifiers in the Modifier stacks */
+void copy_fmodifiers (ListBase *dst, ListBase *src)
+{
+ FModifier *fcm, *srcfcm;
+
+ if ELEM(NULL, dst, src)
+ return;
+
+ dst->first= dst->last= NULL;
+ BLI_duplicatelist(dst, src);
+
+ for (fcm=dst->first, srcfcm=src->first; fcm && srcfcm; srcfcm=srcfcm->next, fcm=fcm->next) {
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+
+ /* make a new copy of the F-Modifier's data */
+ fcm->data = MEM_dupallocN(fcm->data);
+
+ /* only do specific constraints if required */
+ if (fmi && fmi->copy_data)
+ fmi->copy_data(fcm, srcfcm);
+ }
+}
+
+/* Remove and free the given F-Modifier from the given stack */
+void remove_fmodifier (ListBase *modifiers, FModifier *fcm)
+{
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+
+ /* sanity check */
+ if (fcm == NULL)
+ return;
+
+ /* free modifier's special data (stored inside fcm->data) */
+ if (fcm->data) {
+ if (fmi && fmi->free_data)
+ fmi->free_data(fcm);
+
+ /* free modifier's data (fcm->data) */
+ MEM_freeN(fcm->data);
+ }
+
+ /* remove modifier from stack */
+ if (modifiers)
+ BLI_freelinkN(modifiers, fcm);
+ else {
+ // XXX this case can probably be removed some day, as it shouldn't happen...
+ printf("remove_fmodifier() - no modifier stack given \n");
+ MEM_freeN(fcm);
+ }
+}
+
+/* Remove all of a given F-Curve's modifiers */
+void free_fmodifiers (ListBase *modifiers)
+{
+ FModifier *fcm, *fmn;
+
+ /* sanity check */
+ if (modifiers == NULL)
+ return;
+
+ /* free each modifier in order - modifier is unlinked from list and freed */
+ for (fcm= modifiers->first; fcm; fcm= fmn) {
+ fmn= fcm->next;
+ remove_fmodifier(modifiers, fcm);
+ }
+}
+
+/* Find the active F-Modifier */
+FModifier *find_active_fmodifier (ListBase *modifiers)
+{
+ FModifier *fcm;
+
+ /* sanity checks */
+ if ELEM(NULL, modifiers, modifiers->first)
+ return NULL;
+
+ /* loop over modifiers until 'active' one is found */
+ for (fcm= modifiers->first; fcm; fcm= fcm->next) {
+ if (fcm->flag & FMODIFIER_FLAG_ACTIVE)
+ return fcm;
+ }
+
+ /* no modifier is active */
+ return NULL;
+}
+
+/* Set the active F-Modifier */
+void set_active_fmodifier (ListBase *modifiers, FModifier *fcm)
+{
+ FModifier *fm;
+
+ /* sanity checks */
+ if ELEM(NULL, modifiers, modifiers->first)
+ return;
+
+ /* deactivate all, and set current one active */
+ for (fm= modifiers->first; fm; fm= fm->next)
+ fm->flag &= ~FMODIFIER_FLAG_ACTIVE;
+
+ /* make given modifier active */
+ if (fcm)
+ fcm->flag |= FMODIFIER_FLAG_ACTIVE;
+}
+
+/* Do we have any modifiers which match certain criteria
+ * - mtype - type of modifier (if 0, doesn't matter)
+ * - acttype - type of action to perform (if -1, doesn't matter)
+ */
+short list_has_suitable_fmodifier (ListBase *modifiers, int mtype, short acttype)
+{
+ FModifier *fcm;
+
+ /* if there are no specific filtering criteria, just skip */
+ if ((mtype == 0) && (acttype == 0))
+ return (modifiers && modifiers->first);
+
+ /* sanity checks */
+ if ELEM(NULL, modifiers, modifiers->first)
+ return 0;
+
+ /* find the first mdifier fitting these criteria */
+ for (fcm= modifiers->first; fcm; fcm= fcm->next) {
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+ short mOk=1, aOk=1; /* by default 1, so that when only one test, won't fail */
+
+ /* check if applicable ones are fullfilled */
+ if (mtype)
+ mOk= (fcm->type == mtype);
+ if (acttype > -1)
+ aOk= (fmi->acttype == acttype);
+
+ /* if both are ok, we've found a hit */
+ if (mOk && aOk)
+ return 1;
+ }
+
+ /* no matches */
+ return 0;
+}
+
+/* Evaluation API --------------------------- */
+
+/* evaluate time modifications imposed by some F-Curve Modifiers
+ * - this step acts as an optimisation to prevent the F-Curve stack being evaluated
+ * several times by modifiers requesting the time be modified, as the final result
+ * would have required using the modified time
+ * - modifiers only ever recieve the unmodified time, as subsequent modifiers should be
+ * working on the 'global' result of the modified curve, not some localised segment,
+ * so nevaltime gets set to whatever the last time-modifying modifier likes...
+ * - we start from the end of the stack, as only the last one matters for now
+ */
+float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue, float evaltime)
+{
+ FModifier *fcm;
+ float m_evaltime= evaltime;
+
+ /* sanity checks */
+ if ELEM(NULL, modifiers, modifiers->last)
+ return evaltime;
+
+ /* find the first modifier from end of stack that modifies time, and calculate the time the modifier
+ * would calculate time at
+ */
+ for (fcm= modifiers->last; fcm; fcm= fcm->prev) {
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+
+ /* only evaluate if there's a callback for this */
+ // TODO: implement the 'influence' control feature...
+ if (fmi && fmi->evaluate_modifier_time) {
+ if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
+ m_evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime);
+ break;
+ }
+ }
+
+ /* return the modified evaltime */
+ return m_evaltime;
+}
+
+/* Evalautes the given set of F-Curve Modifiers using the given data
+ * Should only be called after evaluate_time_fmodifiers() has been called...
+ */
+void evaluate_value_fmodifiers (ListBase *modifiers, FCurve *fcu, float *cvalue, float evaltime)
+{
+ FModifier *fcm;
+
+ /* sanity checks */
+ if ELEM(NULL, modifiers, modifiers->first)
+ return;
+
+ /* evaluate modifiers */
+ for (fcm= modifiers->first; fcm; fcm= fcm->next) {
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+
+ /* only evaluate if there's a callback for this */
+ // TODO: implement the 'influence' control feature...
+ if (fmi && fmi->evaluate_modifier) {
+ if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
+ fmi->evaluate_modifier(fcu, fcm, cvalue, evaltime);
+ }
+ }
+}
+
+/* ---------- */
+
+/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined
+ * by start and end (inclusive).
+ */
+void fcurve_bake_modifiers (FCurve *fcu, int start, int end)
+{
+ ChannelDriver *driver;
+
+ /* sanity checks */
+ // TODO: make these tests report errors using reports not printf's
+ if ELEM(NULL, fcu, fcu->modifiers.first) {
+ printf("Error: No F-Curve with F-Curve Modifiers to Bake\n");
+ return;
+ }
+
+ /* temporarily, disable driver while we sample, so that they don't influence the outcome */
+ driver= fcu->driver;
+ fcu->driver= NULL;
+
+ /* bake the modifiers, by sampling the curve at each frame */
+ fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve);
+
+ /* free the modifiers now */
+ free_fmodifiers(&fcu->modifiers);
+
+ /* restore driver */
+ fcu->driver= driver;
+}
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 968a0e68fb9..c3c5483574e 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -1153,7 +1153,7 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha
/* Add a new FModifier (Cyclic) instead of setting extend value
* as that's the new equivilant of that option.
*/
- FModifier *fcm= fcurve_add_modifier(fcu, FMODIFIER_TYPE_CYCLES);
+ FModifier *fcm= add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES);
FMod_Cycles *data= (FMod_Cycles *)fcm->data;
/* if 'offset' one is in use, set appropriate settings */
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index 2b95584dc25..14e658b3903 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -69,8 +69,6 @@
// TODO: with things like transitions, should these get freed too? Maybe better as a UI tool
void free_nlastrip (ListBase *strips, NlaStrip *strip)
{
- FModifier *fcm, *fmn;
-
/* sanity checks */
if (strip == NULL)
return;
@@ -86,13 +84,8 @@ void free_nlastrip (ListBase *strips, NlaStrip *strip)
/* free own F-Curves */
free_fcurves(&strip->fcurves);
- /* free F-Modifiers */
- for (fcm= strip->modifiers.first; fcm; fcm= fmn) {
- fmn= fcm->next;
-
- BLI_remlink(&strip->modifiers, fcm);
- fcurve_remove_modifier(NULL, fcm);
- }
+ /* free own F-Modifiers */
+ free_fmodifiers(&strip->modifiers);
/* free the strip itself */
if (strips)
@@ -167,7 +160,7 @@ NlaStrip *copy_nlastrip (NlaStrip *strip)
/* copy F-Curves and modifiers */
copy_fcurves(&strip_d->fcurves, &strip->fcurves);
- fcurve_copy_modifiers(&strip_d->modifiers, &strip->modifiers);
+ copy_fmodifiers(&strip_d->modifiers, &strip->modifiers);
/* return the strip */
return strip_d;
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 9c401289011..fdce0965ce3 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -1,5 +1,30 @@
-/* Testing code for 2.5 animation system
- * Copyright 2009, Joshua Leung
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung (full recode)
+ *
+ * ***** END GPL LICENSE BLOCK *****
*/
#include <stdio.h>
@@ -94,7 +119,7 @@ FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_ind
fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
/* add simple generator modifier for driver so that there is some visible representation */
- fcurve_add_modifier(fcu, FMODIFIER_TYPE_GENERATOR);
+ add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR);
/* just add F-Curve to end of driver list */
BLI_addtail(&adt->drivers, fcu);
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index 5968817a9a6..b5a99877247 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -112,23 +112,23 @@ static void validate_fmodifier_cb (bContext *C, void *fcm_v, void *dummy)
}
/* callback to set the active modifier */
-static void activate_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v)
+static void activate_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v)
{
- FCurve *fcu= (FCurve *)fcu_v;
+ ListBase *modifiers = (ListBase *)fmods_v;
FModifier *fcm= (FModifier *)fcm_v;
- /* call API function to set the active modifier for active F-Curve */
- fcurve_set_active_modifier(fcu, fcm);
+ /* call API function to set the active modifier for active modifier-stack */
+ set_active_fmodifier(modifiers, fcm);
}
/* callback to remove the given modifier */
-static void delete_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v)
+static void delete_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v)
{
- FCurve *fcu= (FCurve *)fcu_v;
+ ListBase *modifiers = (ListBase *)fmods_v;
FModifier *fcm= (FModifier *)fcm_v;
- /* remove the given F-Modifier from the F-Curve */
- fcurve_remove_modifier(fcu, fcm);
+ /* remove the given F-Modifier from the active modifier-stack */
+ remove_fmodifier(modifiers, fcm);
}
/* --------------- */
@@ -588,6 +588,7 @@ static void draw_modifier__limits(uiBlock *block, FModifier *fcm, int *yco, shor
void ANIM_uiTemplate_fmodifier_draw (uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco)
{
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+ ListBase *modifiers= &fcu->modifiers; // XXX fixme... should be arg
uiBut *but;
short active= (fcm->flag & FMODIFIER_FLAG_ACTIVE);
short width= 314;
@@ -607,7 +608,7 @@ void ANIM_uiTemplate_fmodifier_draw (uiBlock *block, FCurve *fcu, FModifier *fcm
/* checkbox for 'active' status (for now) */
but= uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_ACTIVE, B_REDR, ICON_RADIOBUT_OFF, 25, *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is active one.");
- uiButSetFunc(but, activate_fmodifier_cb, fcu, fcm);
+ uiButSetFunc(but, activate_fmodifier_cb, modifiers, fcm);
/* name */
if (fmi)
@@ -620,7 +621,7 @@ void ANIM_uiTemplate_fmodifier_draw (uiBlock *block, FCurve *fcu, FModifier *fcm
/* 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 F-Curve Modifier.");
- uiButSetFunc(but, delete_fmodifier_cb, fcu, fcm);
+ uiButSetFunc(but, delete_fmodifier_cb, modifiers, fcm);
uiBlockSetEmboss(block, UI_EMBOSS);
}
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 90804052370..331e2d0894e 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -1,5 +1,30 @@
-/* Testing code for 2.5 animation system
- * Copyright 2009, Joshua Leung
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung (full recode)
+ *
+ * ***** END GPL LICENSE BLOCK *****
*/
#include <stdio.h>
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index 1813c76d0c4..240089d26a6 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -1,5 +1,30 @@
-/* Testing code for 2.5 animation system
- * Copyright 2009, Joshua Leung
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung (full recode)
+ *
+ * ***** END GPL LICENSE BLOCK *****
*/
#include <stdio.h>
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 66168f2ed87..0d7dafe2938 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -795,7 +795,7 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGri
*/
for (ale=anim_data.first; ale; ale=ale->next) {
FCurve *fcu= (FCurve *)ale->key_data;
- FModifier *fcm= fcurve_find_active_modifier(fcu);
+ FModifier *fcm= find_active_fmodifier(&fcu->modifiers);
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
/* map keyframes for drawing if scaled F-Curve */
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index ca47e69cc75..a82699ac1e5 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -1769,9 +1769,9 @@ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
type= RNA_enum_get(op->ptr, "type");
/* add F-Modifier of specified type to active F-Curve, and make it the active one */
- fcm= fcurve_add_modifier(fcu, type);
+ fcm= add_fmodifier(&fcu->modifiers, type);
if (fcm)
- fcurve_set_active_modifier(fcu, fcm);
+ set_active_fmodifier(&fcu->modifiers, fcm);
else {
BKE_report(op->reports, RPT_ERROR, "Modifier couldn't be added. See console for details.");
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c
index b1ec795a089..f00e7845549 100644
--- a/source/blender/editors/space_graph/graph_utils.c
+++ b/source/blender/editors/space_graph/graph_utils.c
@@ -194,7 +194,7 @@ int graphop_visible_keyframes_poll (bContext *C)
*/
if (fcu->bezt == NULL)
continue;
- fcm= fcurve_find_active_modifier(fcu);
+ fcm= find_active_fmodifier(&fcu->modifiers);
found= (fcurve_needs_draw_fmodifier_controls(fcu, fcm) == 0);
if (found) break;
@@ -244,7 +244,7 @@ int graphop_editable_keyframes_poll (bContext *C)
*/
if (fcu->bezt == NULL)
continue;
- fcm= fcurve_find_active_modifier(fcu);
+ fcm= find_active_fmodifier(&fcu->modifiers);
found= (fcurve_needs_draw_fmodifier_controls(fcu, fcm) == 0);
if (found) break;