Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/fmodifier.c
| Show First 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
| #include "BKE_fcurve.h" | #include "BKE_fcurve.h" | ||||
| #include "BKE_idprop.h" | #include "BKE_idprop.h" | ||||
| static CLG_LogRef LOG = {"bke.fmodifier"}; | static CLG_LogRef LOG = {"bke.fmodifier"}; | ||||
| /* ******************************** F-Modifiers ********************************* */ | /* ******************************** F-Modifiers ********************************* */ | ||||
| /* Forward declarations. */ | |||||
| void fmodifiers_storage_put(FModifierStackStorage *storage, FModifier *fcm, void *data); | |||||
| void fmodifiers_storage_remove(FModifierStackStorage *storage, FModifier *fcm); | |||||
| void *fmodifiers_storage_get(FModifierStackStorage *storage, FModifier *fcm); | |||||
| /* Info ------------------------------- */ | /* Info ------------------------------- */ | ||||
| /* F-Modifiers are modifiers which operate on F-Curves. However, they can also be defined | /* 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. | * on NLA-Strips to affect all of the F-Curves referenced by the NLA-Strip. | ||||
| */ | */ | ||||
| /* Template --------------------------- */ | /* Template --------------------------- */ | ||||
| /* Each modifier defines a set of functions, which will be called at the appropriate | /* 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 | * times. In addition to this, each modifier should have a type-info struct, where | ||||
| * its functions are attached for use. | * its functions are attached for use. | ||||
| */ | */ | ||||
| /* Template for type-info data: | /* Template for type-info data: | ||||
| * - make a copy of this when creating new modifiers, and just change the functions | * - make a copy of this when creating new modifiers, and just change the functions | ||||
| * pointed to as necessary | * pointed to as necessary | ||||
| * - although the naming of functions doesn't matter, it would help for code | * - although the naming of functions doesn't matter, it would help for code | ||||
| * readability, to follow the same naming convention as is presented here | * readability, to follow the same naming convention as is presented here | ||||
| * - any functions that a constraint doesn't need to define, don't define | * - any functions that a constraint doesn't need to define, don't define | ||||
| * for such cases, just use NULL | * for such cases, just use NULL | ||||
| * - these should be defined after all the functions have been defined, so that | * - these should be defined after all the functions have been defined, so that | ||||
| * forward-definitions/prototypes don't need to be used! | * forward-definitions/prototypes don't need to be used! | ||||
| * - keep this copy #if-def'd so that future constraints can get based off this | * - keep this copy #if-def'd so that future modifier can get based off this | ||||
| */ | */ | ||||
| #if 0 | #if 0 | ||||
| static FModifierTypeInfo FMI_MODNAME = { | static FModifierTypeInfo FMI_MODNAME = { | ||||
| FMODIFIER_TYPE_MODNAME, /* type */ | FMODIFIER_TYPE_MODNAME, /* type */ | ||||
| sizeof(FMod_ModName), /* size */ | sizeof(FMod_ModName), /* size */ | ||||
| FMI_TYPE_SOME_ACTION, /* action type */ | FMI_TYPE_SOME_ACTION, /* action type */ | ||||
| FMI_REQUIRES_SOME_REQUIREMENT, /* requirements */ | FMI_REQUIRES_SOME_REQUIREMENT, /* requirements */ | ||||
| "Modifier Name", /* name */ | "Modifier Name", /* name */ | ||||
| "FMod_ModName", /* struct name */ | "FMod_ModName", /* struct name */ | ||||
| 0, /* storage size */ | |||||
| fcm_modname_free, /* free data */ | fcm_modname_free, /* free data */ | ||||
| fcm_modname_relink, /* relink data */ | fcm_modname_relink, /* relink data */ | ||||
| fcm_modname_copy, /* copy data */ | fcm_modname_copy, /* copy data */ | ||||
| fcm_modname_new_data, /* new data */ | fcm_modname_new_data, /* new data */ | ||||
| fcm_modname_verify, /* verify */ | fcm_modname_verify, /* verify */ | ||||
| fcm_modname_time, /* evaluate time */ | fcm_modname_time, /* evaluate time */ | ||||
| fcm_modname_evaluate, /* evaluate */ | fcm_modname_evaluate, /* evaluate */ | ||||
| fcm_modname_time_storage, /* evaluate time with storage */ | |||||
| fcm_modname_evaluate_storage, /* evaluate with storage */ | |||||
| }; | }; | ||||
| #endif | #endif | ||||
| /* Generator F-Curve Modifier --------------------------- */ | /* Generator F-Curve Modifier --------------------------- */ | ||||
| /* Generators available: | /* Generators available: | ||||
| * 1) simple polynomial generator: | * 1) simple polynomial generator: | ||||
| * - Expanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n]) | * - Expanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n]) | ||||
| ▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* expanded polynomial expression */ | ||||
| data->coefficients = MEM_recallocN(data->coefficients, sizeof(float) * arraysize_new); | data->coefficients = MEM_recallocN(data->coefficients, sizeof(float) * arraysize_new); | ||||
| data->arraysize = arraysize_new; | data->arraysize = arraysize_new; | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void fcm_generator_evaluate(FCurve *UNUSED(fcu), | static void fcm_generator_evaluate( | ||||
| FModifier *fcm, | FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float evaltime, void *UNUSED(storage)) | ||||
| float *cvalue, | |||||
| float evaltime) | |||||
| { | { | ||||
| FMod_Generator *data = (FMod_Generator *)fcm->data; | FMod_Generator *data = (FMod_Generator *)fcm->data; | ||||
| /* behavior depends on mode | /* behavior depends on mode | ||||
| * NOTE: the data in its default state is fine too | * NOTE: the data in its default state is fine too | ||||
| */ | */ | ||||
| switch (data->mode) { | switch (data->mode) { | ||||
| case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */ | case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */ | ||||
| ▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | |||||
| static FModifierTypeInfo FMI_GENERATOR = { | static FModifierTypeInfo FMI_GENERATOR = { | ||||
| FMODIFIER_TYPE_GENERATOR, /* type */ | FMODIFIER_TYPE_GENERATOR, /* type */ | ||||
| sizeof(FMod_Generator), /* size */ | sizeof(FMod_Generator), /* size */ | ||||
| FMI_TYPE_GENERATE_CURVE, /* action type */ | FMI_TYPE_GENERATE_CURVE, /* action type */ | ||||
| FMI_REQUIRES_NOTHING, /* requirements */ | FMI_REQUIRES_NOTHING, /* requirements */ | ||||
| N_("Generator"), /* name */ | N_("Generator"), /* name */ | ||||
| "FMod_Generator", /* struct name */ | "FMod_Generator", /* struct name */ | ||||
| 0, /* storage size */ | |||||
| fcm_generator_free, /* free data */ | fcm_generator_free, /* free data */ | ||||
| fcm_generator_copy, /* copy data */ | fcm_generator_copy, /* copy data */ | ||||
| fcm_generator_new_data, /* new data */ | fcm_generator_new_data, /* new data */ | ||||
| fcm_generator_verify, /* verify */ | fcm_generator_verify, /* verify */ | ||||
| NULL, /* evaluate time */ | NULL, /* evaluate time */ | ||||
| fcm_generator_evaluate, /* evaluate */ | fcm_generator_evaluate, /* evaluate */ | ||||
| NULL, /* evaluate time with storage */ | |||||
| NULL, /* evaluate with storage */ | |||||
| }; | }; | ||||
| /* Built-In Function Generator F-Curve Modifier --------------------------- */ | /* Built-In Function Generator F-Curve Modifier --------------------------- */ | ||||
| /* This uses the general equation for equations: | /* This uses the general equation for equations: | ||||
| * y = amplitude * fn(phase_multiplier * x + phase_offset) + y_offset | * y = amplitude * fn(phase_multiplier * x + phase_offset) + y_offset | ||||
| * | * | ||||
| * where amplitude, phase_multiplier/offset, y_offset are user-defined coefficients, | * where amplitude, phase_multiplier/offset, y_offset are user-defined coefficients, | ||||
| Show All 19 Lines | |||||
| static double sinc(double x) | static double sinc(double x) | ||||
| { | { | ||||
| if (fabs(x) < 0.0001) | if (fabs(x) < 0.0001) | ||||
| return 1.0; | return 1.0; | ||||
| else | else | ||||
| return sin(M_PI * x) / (M_PI * x); | return sin(M_PI * x) / (M_PI * x); | ||||
| } | } | ||||
| static void fcm_fn_generator_evaluate(FCurve *UNUSED(fcu), | static void fcm_fn_generator_evaluate( | ||||
| FModifier *fcm, | FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float evaltime, void *UNUSED(storage)) | ||||
| float *cvalue, | |||||
| float evaltime) | |||||
| { | { | ||||
| FMod_FunctionGenerator *data = (FMod_FunctionGenerator *)fcm->data; | FMod_FunctionGenerator *data = (FMod_FunctionGenerator *)fcm->data; | ||||
| double arg = data->phase_multiplier * evaltime + data->phase_offset; | double arg = data->phase_multiplier * evaltime + data->phase_offset; | ||||
| double (*fn)(double v) = NULL; | double (*fn)(double v) = NULL; | ||||
| /* get function pointer to the func to use: | /* get function pointer to the func to use: | ||||
| * WARNING: must perform special argument validation hereto guard against crashes | * WARNING: must perform special argument validation hereto guard against crashes | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | |||||
| static FModifierTypeInfo FMI_FN_GENERATOR = { | static FModifierTypeInfo FMI_FN_GENERATOR = { | ||||
| FMODIFIER_TYPE_FN_GENERATOR, /* type */ | FMODIFIER_TYPE_FN_GENERATOR, /* type */ | ||||
| sizeof(FMod_FunctionGenerator), /* size */ | sizeof(FMod_FunctionGenerator), /* size */ | ||||
| FMI_TYPE_GENERATE_CURVE, /* action type */ | FMI_TYPE_GENERATE_CURVE, /* action type */ | ||||
| FMI_REQUIRES_NOTHING, /* requirements */ | FMI_REQUIRES_NOTHING, /* requirements */ | ||||
| N_("Built-In Function"), /* name */ | N_("Built-In Function"), /* name */ | ||||
| "FMod_FunctionGenerator", /* struct name */ | "FMod_FunctionGenerator", /* struct name */ | ||||
| 0, /* storage size */ | |||||
| NULL, /* free data */ | NULL, /* free data */ | ||||
| NULL, /* copy data */ | NULL, /* copy data */ | ||||
| fcm_fn_generator_new_data, /* new data */ | fcm_fn_generator_new_data, /* new data */ | ||||
| NULL, /* verify */ | NULL, /* verify */ | ||||
| NULL, /* evaluate time */ | NULL, /* evaluate time */ | ||||
| fcm_fn_generator_evaluate, /* evaluate */ | fcm_fn_generator_evaluate, /* evaluate */ | ||||
| NULL, /* evaluate time with storage */ | |||||
| NULL, /* evaluate with storage */ | |||||
| }; | }; | ||||
| /* Envelope F-Curve Modifier --------------------------- */ | /* Envelope F-Curve Modifier --------------------------- */ | ||||
| static void fcm_envelope_free(FModifier *fcm) | static void fcm_envelope_free(FModifier *fcm) | ||||
| { | { | ||||
| FMod_Envelope *env = (FMod_Envelope *)fcm->data; | FMod_Envelope *env = (FMod_Envelope *)fcm->data; | ||||
| Show All 26 Lines | static void fcm_envelope_verify(FModifier *fcm) | ||||
| FMod_Envelope *env = (FMod_Envelope *)fcm->data; | FMod_Envelope *env = (FMod_Envelope *)fcm->data; | ||||
| /* if the are points, perform bubble-sort on them, as user may have changed the order */ | /* if the are points, perform bubble-sort on them, as user may have changed the order */ | ||||
| if (env->data) { | if (env->data) { | ||||
| /* XXX todo... */ | /* XXX todo... */ | ||||
| } | } | ||||
| } | } | ||||
| static void fcm_envelope_evaluate(FCurve *UNUSED(fcu), | static void fcm_envelope_evaluate( | ||||
| FModifier *fcm, | FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float evaltime, void *UNUSED(storage)) | ||||
| float *cvalue, | |||||
| float evaltime) | |||||
| { | { | ||||
| FMod_Envelope *env = (FMod_Envelope *)fcm->data; | FMod_Envelope *env = (FMod_Envelope *)fcm->data; | ||||
| FCM_EnvelopeData *fed, *prevfed, *lastfed; | FCM_EnvelopeData *fed, *prevfed, *lastfed; | ||||
| float min = 0.0f, max = 0.0f, fac = 0.0f; | float min = 0.0f, max = 0.0f, fac = 0.0f; | ||||
| int a; | int a; | ||||
| /* get pointers */ | /* get pointers */ | ||||
| if (env->data == NULL) | if (env->data == NULL) | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
| static FModifierTypeInfo FMI_ENVELOPE = { | static FModifierTypeInfo FMI_ENVELOPE = { | ||||
| FMODIFIER_TYPE_ENVELOPE, /* type */ | FMODIFIER_TYPE_ENVELOPE, /* type */ | ||||
| sizeof(FMod_Envelope), /* size */ | sizeof(FMod_Envelope), /* size */ | ||||
| FMI_TYPE_REPLACE_VALUES, /* action type */ | FMI_TYPE_REPLACE_VALUES, /* action type */ | ||||
| 0, /* requirements */ | 0, /* requirements */ | ||||
| N_("Envelope"), /* name */ | N_("Envelope"), /* name */ | ||||
| "FMod_Envelope", /* struct name */ | "FMod_Envelope", /* struct name */ | ||||
| 0, /* storage size */ | |||||
| fcm_envelope_free, /* free data */ | fcm_envelope_free, /* free data */ | ||||
| fcm_envelope_copy, /* copy data */ | fcm_envelope_copy, /* copy data */ | ||||
| fcm_envelope_new_data, /* new data */ | fcm_envelope_new_data, /* new data */ | ||||
| fcm_envelope_verify, /* verify */ | fcm_envelope_verify, /* verify */ | ||||
| NULL, /* evaluate time */ | NULL, /* evaluate time */ | ||||
| fcm_envelope_evaluate, /* evaluate */ | fcm_envelope_evaluate, /* evaluate */ | ||||
| NULL, /* evaluate time with storage */ | |||||
| NULL, /* evaluate with storage */ | |||||
| }; | }; | ||||
| /* exported function for finding points */ | /* exported function for finding points */ | ||||
| /* Binary search algorithm for finding where to insert Envelope Data Point. | /* Binary search algorithm for finding where to insert Envelope Data Point. | ||||
| * Returns the index to insert at (data already at that index will be offset if replace is 0) | * Returns the index to insert at (data already at that index will be offset if replace is 0) | ||||
| */ | */ | ||||
| #define BINARYSEARCH_FRAMEEQ_THRESH 0.0001f | #define BINARYSEARCH_FRAMEEQ_THRESH 0.0001f | ||||
| ▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | |||||
| static void fcm_cycles_new_data(void *mdata) | static void fcm_cycles_new_data(void *mdata) | ||||
| { | { | ||||
| FMod_Cycles *data = (FMod_Cycles *)mdata; | FMod_Cycles *data = (FMod_Cycles *)mdata; | ||||
| /* turn on cycles by default */ | /* turn on cycles by default */ | ||||
| data->before_mode = data->after_mode = FCM_EXTRAPOLATE_CYCLIC; | data->before_mode = data->after_mode = FCM_EXTRAPOLATE_CYCLIC; | ||||
| } | } | ||||
| static float fcm_cycles_time(FModifierStackStorage *storage, | static float fcm_cycles_time( | ||||
| FCurve *fcu, | FCurve *fcu, FModifier *fcm, float UNUSED(cvalue), float evaltime, void *storage_) | ||||
| FModifier *fcm, | |||||
| float UNUSED(cvalue), | |||||
| float evaltime) | |||||
| { | { | ||||
| FMod_Cycles *data = (FMod_Cycles *)fcm->data; | FMod_Cycles *data = (FMod_Cycles *)fcm->data; | ||||
| tFCMED_Cycles *storage = storage_; | |||||
| float prevkey[2], lastkey[2], cycyofs = 0.0f; | float prevkey[2], lastkey[2], cycyofs = 0.0f; | ||||
| short side = 0, mode = 0; | short side = 0, mode = 0; | ||||
| int cycles = 0; | int cycles = 0; | ||||
| float ofs = 0; | float ofs = 0; | ||||
| /* Initialize storage. */ | |||||
| storage->cycyofs = 0; | |||||
| /* check if modifier is first in stack, otherwise disable ourself... */ | /* check if modifier is first in stack, otherwise disable ourself... */ | ||||
| /* FIXME... */ | /* FIXME... */ | ||||
| if (fcm->prev) { | if (fcm->prev) { | ||||
| fcm->flag |= FMODIFIER_FLAG_DISABLED; | fcm->flag |= FMODIFIER_FLAG_DISABLED; | ||||
| return evaltime; | return evaltime; | ||||
| } | } | ||||
| /* calculate new evaltime due to cyclic interpolation */ | /* calculate new evaltime due to cyclic interpolation */ | ||||
| ▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | else { | ||||
| evaltime = prevkey[0] + cyct; | evaltime = prevkey[0] + cyct; | ||||
| } | } | ||||
| if (evaltime < prevkey[0]) | if (evaltime < prevkey[0]) | ||||
| evaltime += cycdx; | evaltime += cycdx; | ||||
| } | } | ||||
| /* store temp data if needed */ | /* store temp data if needed */ | ||||
| if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { | if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { | ||||
| tFCMED_Cycles *edata; | storage->cycyofs = cycyofs; | ||||
| /* for now, this is just a float, but we could get more stuff... */ | |||||
| edata = MEM_callocN(sizeof(tFCMED_Cycles), "tFCMED_Cycles"); | |||||
| edata->cycyofs = cycyofs; | |||||
| fmodifiers_storage_put(storage, fcm, edata); | |||||
| } | } | ||||
| /* return the new frame to evaluate */ | /* return the new frame to evaluate */ | ||||
| return evaltime; | return evaltime; | ||||
| } | } | ||||
| static void fcm_cycles_evaluate(FModifierStackStorage *storage, | static void fcm_cycles_evaluate(FCurve *UNUSED(fcu), | ||||
| FCurve *UNUSED(fcu), | FModifier *UNUSED(fcm), | ||||
| FModifier *fcm, | |||||
| float *cvalue, | float *cvalue, | ||||
| float UNUSED(evaltime)) | float UNUSED(evaltime), | ||||
| void *storage_) | |||||
| { | { | ||||
| tFCMED_Cycles *edata = fmodifiers_storage_get(storage, fcm); | tFCMED_Cycles *storage = storage_; | ||||
| *cvalue += storage->cycyofs; | |||||
| /* 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); | |||||
| fmodifiers_storage_remove(storage, fcm); | |||||
| } | |||||
| } | } | ||||
| static FModifierTypeInfo FMI_CYCLES = { | static FModifierTypeInfo FMI_CYCLES = { | ||||
| FMODIFIER_TYPE_CYCLES, /* type */ | FMODIFIER_TYPE_CYCLES, /* type */ | ||||
| sizeof(FMod_Cycles), /* size */ | sizeof(FMod_Cycles), /* size */ | ||||
| FMI_TYPE_EXTRAPOLATION, /* action type */ | FMI_TYPE_EXTRAPOLATION, /* action type */ | ||||
| FMI_REQUIRES_ORIGINAL_DATA | FMI_REQUIRES_STORAGE, /* requirements */ | FMI_REQUIRES_ORIGINAL_DATA, /* requirements */ | ||||
| N_("Cycles"), /* name */ | N_("Cycles"), /* name */ | ||||
| "FMod_Cycles", /* struct name */ | "FMod_Cycles", /* struct name */ | ||||
| sizeof(tFCMED_Cycles), /* storage size */ | |||||
| NULL, /* free data */ | NULL, /* free data */ | ||||
| NULL, /* copy data */ | NULL, /* copy data */ | ||||
| fcm_cycles_new_data, /* new data */ | fcm_cycles_new_data, /* new data */ | ||||
| NULL /*fcm_cycles_verify*/, /* verify */ | NULL /*fcm_cycles_verify*/, /* verify */ | ||||
| NULL, /* evaluate time */ | fcm_cycles_time, /* evaluate time */ | ||||
| NULL, /* evaluate */ | fcm_cycles_evaluate, /* evaluate */ | ||||
| fcm_cycles_time, /* evaluate time with storage */ | |||||
| fcm_cycles_evaluate, /* evaluate with storage */ | |||||
| }; | }; | ||||
| /* Noise F-Curve Modifier --------------------------- */ | /* Noise F-Curve Modifier --------------------------- */ | ||||
| static void fcm_noise_new_data(void *mdata) | static void fcm_noise_new_data(void *mdata) | ||||
| { | { | ||||
| FMod_Noise *data = (FMod_Noise *)mdata; | FMod_Noise *data = (FMod_Noise *)mdata; | ||||
| /* defaults */ | /* defaults */ | ||||
| data->size = 1.0f; | data->size = 1.0f; | ||||
| data->strength = 1.0f; | data->strength = 1.0f; | ||||
| data->phase = 1.0f; | data->phase = 1.0f; | ||||
| data->offset = 0.0f; | data->offset = 0.0f; | ||||
| data->depth = 0; | data->depth = 0; | ||||
| data->modification = FCM_NOISE_MODIF_REPLACE; | data->modification = FCM_NOISE_MODIF_REPLACE; | ||||
| } | } | ||||
| static void fcm_noise_evaluate(FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float evaltime) | static void fcm_noise_evaluate( | ||||
| FCurve *UNUSED(fcu), FModifier *fcm, float *cvalue, float evaltime, void *UNUSED(storage)) | |||||
| { | { | ||||
| FMod_Noise *data = (FMod_Noise *)fcm->data; | FMod_Noise *data = (FMod_Noise *)fcm->data; | ||||
| float noise; | float noise; | ||||
| /* generate noise using good ol' Blender Noise | /* generate noise using good ol' Blender Noise | ||||
| * - 0.1 is passed as the 'z' value, otherwise evaluation fails for size = phase = 1 | * - 0.1 is passed as the 'z' value, otherwise evaluation fails for size = phase = 1 | ||||
| * with evaltime being an integer (which happens when evaluating on frame by frame basis) | * with evaltime being an integer (which happens when evaluating on frame by frame basis) | ||||
| */ | */ | ||||
| Show All 19 Lines | |||||
| static FModifierTypeInfo FMI_NOISE = { | static FModifierTypeInfo FMI_NOISE = { | ||||
| FMODIFIER_TYPE_NOISE, /* type */ | FMODIFIER_TYPE_NOISE, /* type */ | ||||
| sizeof(FMod_Noise), /* size */ | sizeof(FMod_Noise), /* size */ | ||||
| FMI_TYPE_REPLACE_VALUES, /* action type */ | FMI_TYPE_REPLACE_VALUES, /* action type */ | ||||
| 0, /* requirements */ | 0, /* requirements */ | ||||
| N_("Noise"), /* name */ | N_("Noise"), /* name */ | ||||
| "FMod_Noise", /* struct name */ | "FMod_Noise", /* struct name */ | ||||
| 0, /* storage size */ | |||||
| NULL, /* free data */ | NULL, /* free data */ | ||||
| NULL, /* copy data */ | NULL, /* copy data */ | ||||
| fcm_noise_new_data, /* new data */ | fcm_noise_new_data, /* new data */ | ||||
| NULL /*fcm_noise_verify*/, /* verify */ | NULL /*fcm_noise_verify*/, /* verify */ | ||||
| NULL, /* evaluate time */ | NULL, /* evaluate time */ | ||||
| fcm_noise_evaluate, /* evaluate */ | fcm_noise_evaluate, /* evaluate */ | ||||
| NULL, /* evaluate time with storage */ | |||||
| NULL, /* evaluate with storage */ | |||||
| }; | }; | ||||
| /* Python F-Curve Modifier --------------------------- */ | /* Python F-Curve Modifier --------------------------- */ | ||||
| static void fcm_python_free(FModifier *fcm) | static void fcm_python_free(FModifier *fcm) | ||||
| { | { | ||||
| FMod_Python *data = (FMod_Python *)fcm->data; | FMod_Python *data = (FMod_Python *)fcm->data; | ||||
| Show All 17 Lines | static void fcm_python_copy(FModifier *fcm, const FModifier *src) | ||||
| FMod_Python *opymod = (FMod_Python *)src->data; | FMod_Python *opymod = (FMod_Python *)src->data; | ||||
| pymod->prop = IDP_CopyProperty(opymod->prop); | pymod->prop = IDP_CopyProperty(opymod->prop); | ||||
| } | } | ||||
| static void fcm_python_evaluate(FCurve *UNUSED(fcu), | static void fcm_python_evaluate(FCurve *UNUSED(fcu), | ||||
| FModifier *UNUSED(fcm), | FModifier *UNUSED(fcm), | ||||
| float *UNUSED(cvalue), | float *UNUSED(cvalue), | ||||
| float UNUSED(evaltime)) | float UNUSED(evaltime), | ||||
| void *UNUSED(storage)) | |||||
| { | { | ||||
| #ifdef WITH_PYTHON | #ifdef WITH_PYTHON | ||||
| //FMod_Python *data = (FMod_Python *)fcm->data; | //FMod_Python *data = (FMod_Python *)fcm->data; | ||||
| /* FIXME... need to implement this modifier... | /* FIXME... need to implement this modifier... | ||||
| * It will need it execute a script using the custom properties | * It will need it execute a script using the custom properties | ||||
| */ | */ | ||||
| #endif /* WITH_PYTHON */ | #endif /* WITH_PYTHON */ | ||||
| } | } | ||||
| static FModifierTypeInfo FMI_PYTHON = { | static FModifierTypeInfo FMI_PYTHON = { | ||||
| FMODIFIER_TYPE_PYTHON, /* type */ | FMODIFIER_TYPE_PYTHON, /* type */ | ||||
| sizeof(FMod_Python), /* size */ | sizeof(FMod_Python), /* size */ | ||||
| FMI_TYPE_GENERATE_CURVE, /* action type */ | FMI_TYPE_GENERATE_CURVE, /* action type */ | ||||
| FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ | FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ | ||||
| N_("Python"), /* name */ | N_("Python"), /* name */ | ||||
| "FMod_Python", /* struct name */ | "FMod_Python", /* struct name */ | ||||
| 0, /* storage size */ | |||||
| fcm_python_free, /* free data */ | fcm_python_free, /* free data */ | ||||
| fcm_python_copy, /* copy data */ | fcm_python_copy, /* copy data */ | ||||
| fcm_python_new_data, /* new data */ | fcm_python_new_data, /* new data */ | ||||
| NULL /*fcm_python_verify*/, /* verify */ | NULL /*fcm_python_verify*/, /* verify */ | ||||
| NULL /*fcm_python_time*/, /* evaluate time */ | NULL /*fcm_python_time*/, /* evaluate time */ | ||||
| fcm_python_evaluate, /* evaluate */ | fcm_python_evaluate, /* evaluate */ | ||||
| NULL, /* evaluate time with storage */ | |||||
| NULL, /* evaluate with storage */ | |||||
| }; | }; | ||||
| /* Limits F-Curve Modifier --------------------------- */ | /* Limits F-Curve Modifier --------------------------- */ | ||||
| static float fcm_limits_time(FCurve *UNUSED(fcu), | static float fcm_limits_time(FCurve *UNUSED(fcu), | ||||
| FModifier *fcm, | FModifier *fcm, | ||||
| float UNUSED(cvalue), | float UNUSED(cvalue), | ||||
| float evaltime) | float evaltime, | ||||
| void *UNUSED(storage)) | |||||
| { | { | ||||
| FMod_Limits *data = (FMod_Limits *)fcm->data; | FMod_Limits *data = (FMod_Limits *)fcm->data; | ||||
| /* check for the time limits */ | /* check for the time limits */ | ||||
| if ((data->flag & FCM_LIMIT_XMIN) && (evaltime < data->rect.xmin)) | if ((data->flag & FCM_LIMIT_XMIN) && (evaltime < data->rect.xmin)) | ||||
| return data->rect.xmin; | return data->rect.xmin; | ||||
| if ((data->flag & FCM_LIMIT_XMAX) && (evaltime > data->rect.xmax)) | if ((data->flag & FCM_LIMIT_XMAX) && (evaltime > data->rect.xmax)) | ||||
| return data->rect.xmax; | return data->rect.xmax; | ||||
| /* modifier doesn't change time */ | /* modifier doesn't change time */ | ||||
| return evaltime; | return evaltime; | ||||
| } | } | ||||
| static void fcm_limits_evaluate(FCurve *UNUSED(fcu), | static void fcm_limits_evaluate(FCurve *UNUSED(fcu), | ||||
| FModifier *fcm, | FModifier *fcm, | ||||
| float *cvalue, | float *cvalue, | ||||
| float UNUSED(evaltime)) | float UNUSED(evaltime), | ||||
| void *UNUSED(storage)) | |||||
| { | { | ||||
| FMod_Limits *data = (FMod_Limits *)fcm->data; | FMod_Limits *data = (FMod_Limits *)fcm->data; | ||||
| /* value limits now */ | /* value limits now */ | ||||
| if ((data->flag & FCM_LIMIT_YMIN) && (*cvalue < data->rect.ymin)) | if ((data->flag & FCM_LIMIT_YMIN) && (*cvalue < data->rect.ymin)) | ||||
| *cvalue = data->rect.ymin; | *cvalue = data->rect.ymin; | ||||
| if ((data->flag & FCM_LIMIT_YMAX) && (*cvalue > data->rect.ymax)) | if ((data->flag & FCM_LIMIT_YMAX) && (*cvalue > data->rect.ymax)) | ||||
| *cvalue = data->rect.ymax; | *cvalue = data->rect.ymax; | ||||
| } | } | ||||
| static FModifierTypeInfo FMI_LIMITS = { | static FModifierTypeInfo FMI_LIMITS = { | ||||
| FMODIFIER_TYPE_LIMITS, /* type */ | FMODIFIER_TYPE_LIMITS, /* type */ | ||||
| sizeof(FMod_Limits), /* size */ | sizeof(FMod_Limits), /* size */ | ||||
| FMI_TYPE_GENERATE_CURVE, | FMI_TYPE_GENERATE_CURVE, | ||||
| /* action type */ /* XXX... err... */ | /* action type */ /* XXX... err... */ | ||||
| FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ | FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ | ||||
| N_("Limits"), /* name */ | N_("Limits"), /* name */ | ||||
| "FMod_Limits", /* struct name */ | "FMod_Limits", /* struct name */ | ||||
| 0, /* storage size */ | |||||
| NULL, /* free data */ | NULL, /* free data */ | ||||
| NULL, /* copy data */ | NULL, /* copy data */ | ||||
| NULL, /* new data */ | NULL, /* new data */ | ||||
| NULL, /* verify */ | NULL, /* verify */ | ||||
| fcm_limits_time, /* evaluate time */ | fcm_limits_time, /* evaluate time */ | ||||
| fcm_limits_evaluate, /* evaluate */ | fcm_limits_evaluate, /* evaluate */ | ||||
| NULL, /* evaluate time with storage */ | |||||
| NULL, /* evaluate with storage */ | |||||
| }; | }; | ||||
| /* Stepped F-Curve Modifier --------------------------- */ | /* Stepped F-Curve Modifier --------------------------- */ | ||||
| static void fcm_stepped_new_data(void *mdata) | static void fcm_stepped_new_data(void *mdata) | ||||
| { | { | ||||
| FMod_Stepped *data = (FMod_Stepped *)mdata; | FMod_Stepped *data = (FMod_Stepped *)mdata; | ||||
| /* just need to set the step-size to 2-frames by default */ | /* just need to set the step-size to 2-frames by default */ | ||||
| /* XXX: or would 5 be more normal? */ | /* XXX: or would 5 be more normal? */ | ||||
| data->step_size = 2.0f; | data->step_size = 2.0f; | ||||
| } | } | ||||
| static float fcm_stepped_time(FCurve *UNUSED(fcu), | static float fcm_stepped_time(FCurve *UNUSED(fcu), | ||||
| FModifier *fcm, | FModifier *fcm, | ||||
| float UNUSED(cvalue), | float UNUSED(cvalue), | ||||
| float evaltime) | float evaltime, | ||||
| void *UNUSED(storage)) | |||||
| { | { | ||||
| FMod_Stepped *data = (FMod_Stepped *)fcm->data; | FMod_Stepped *data = (FMod_Stepped *)fcm->data; | ||||
| int snapblock; | int snapblock; | ||||
| /* check range clamping to see if we should alter the timing to achieve the desired results */ | /* check range clamping to see if we should alter the timing to achieve the desired results */ | ||||
| if (data->flag & FCM_STEPPED_NO_BEFORE) { | if (data->flag & FCM_STEPPED_NO_BEFORE) { | ||||
| if (evaltime < data->start_frame) | if (evaltime < data->start_frame) | ||||
| return evaltime; | return evaltime; | ||||
| Show All 18 Lines | |||||
| static FModifierTypeInfo FMI_STEPPED = { | static FModifierTypeInfo FMI_STEPPED = { | ||||
| FMODIFIER_TYPE_STEPPED, /* type */ | FMODIFIER_TYPE_STEPPED, /* type */ | ||||
| sizeof(FMod_Limits), /* size */ | sizeof(FMod_Limits), /* size */ | ||||
| FMI_TYPE_GENERATE_CURVE, | FMI_TYPE_GENERATE_CURVE, | ||||
| /* action type */ /* XXX... err... */ | /* action type */ /* XXX... err... */ | ||||
| FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ | FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ | ||||
| N_("Stepped"), /* name */ | N_("Stepped"), /* name */ | ||||
| "FMod_Stepped", /* struct name */ | "FMod_Stepped", /* struct name */ | ||||
| 0, /* storage size */ | |||||
| NULL, /* free data */ | NULL, /* free data */ | ||||
| NULL, /* copy data */ | NULL, /* copy data */ | ||||
| fcm_stepped_new_data, /* new data */ | fcm_stepped_new_data, /* new data */ | ||||
| NULL, /* verify */ | NULL, /* verify */ | ||||
| fcm_stepped_time, /* evaluate time */ | fcm_stepped_time, /* evaluate time */ | ||||
| NULL, /* evaluate */ | NULL, /* evaluate */ | ||||
| NULL, /* evaluate time with storage */ | |||||
| NULL, /* evaluate with storage */ | |||||
| }; | }; | ||||
| /* F-Curve Modifier API --------------------------- */ | /* F-Curve Modifier API --------------------------- */ | ||||
| /* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out | /* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out | ||||
| * and operations that involve F-Curve modifier specific code. | * and operations that involve F-Curve modifier specific code. | ||||
| */ | */ | ||||
| /* These globals only ever get directly accessed in this file */ | /* These globals only ever get directly accessed in this file */ | ||||
| ▲ Show 20 Lines • Show All 275 Lines • ▼ Show 20 Lines | bool list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype) | ||||
| } | } | ||||
| /* no matches */ | /* no matches */ | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* Evaluation API --------------------------- */ | /* Evaluation API --------------------------- */ | ||||
| FModifierStackStorage *evaluate_fmodifiers_storage_new(ListBase *modifiers) | uint evaluate_fmodifiers_storage_size_per_modifier(ListBase *modifiers) | ||||
| { | { | ||||
| FModifier *fcm; | |||||
| /* Sanity checks. */ | /* Sanity checks. */ | ||||
| if (ELEM(NULL, modifiers, modifiers->last)) { | if (ELEM(NULL, modifiers, modifiers->first)) { | ||||
| return NULL; | return 0; | ||||
| } | } | ||||
| for (fcm = modifiers->last; fcm; fcm = fcm->prev) { | uint max_size = 0; | ||||
| for (FModifier *fcm = modifiers->first; fcm; fcm = fcm->next) { | |||||
angavrilov: <blank line> | |||||
| const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); | const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); | ||||
| if (fmi == NULL) { | if (fmi == NULL) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (fmi->requires & FMI_REQUIRES_STORAGE) { | max_size = MAX2(max_size, fmi->storage_size); | ||||
Done Inline ActionsUsing a max macro would probably be more obvious: max_size = MAX2(max_size, fmi->storage_size); angavrilov: Using a max macro would probably be more obvious: max_size = MAX2(max_size, fmi->storage_size); | |||||
| return (FModifierStackStorage *)BLI_ghash_new( | |||||
| BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "fmodifier stack temp storage"); | |||||
| } | |||||
| } | |||||
| return NULL; | |||||
| } | } | ||||
| void evaluate_fmodifiers_storage_free(FModifierStackStorage *storage) | return max_size; | ||||
| { | |||||
| if (storage != NULL) { | |||||
| BLI_ghash_free((GHash *)storage, NULL, NULL); | |||||
| } | |||||
| } | |||||
| void fmodifiers_storage_put(FModifierStackStorage *storage, FModifier *fcm, void *data) | |||||
| { | |||||
| BLI_assert(storage != NULL); | |||||
| BLI_ghash_insert((GHash *)storage, fcm, data); | |||||
| } | |||||
| void fmodifiers_storage_remove(FModifierStackStorage *storage, FModifier *fcm) | |||||
| { | |||||
| BLI_assert(storage != NULL); | |||||
| BLI_ghash_remove((GHash *)storage, fcm, NULL, NULL); | |||||
| } | |||||
| void *fmodifiers_storage_get(FModifierStackStorage *storage, FModifier *fcm) | |||||
| { | |||||
| BLI_assert(storage != NULL); | |||||
| return BLI_ghash_lookup((GHash *)storage, fcm); | |||||
| } | } | ||||
| /* helper function - calculate influence of FModifier */ | /* helper function - calculate influence of FModifier */ | ||||
| static float eval_fmodifier_influence(FModifier *fcm, float evaltime) | static float eval_fmodifier_influence(FModifier *fcm, float evaltime) | ||||
| { | { | ||||
| float influence; | float influence; | ||||
| /* sanity check */ | /* sanity check */ | ||||
| Show All 38 Lines | |||||
| * would have required using the modified time | * would have required using the modified time | ||||
| * - modifiers only ever receive the unmodified time, as subsequent modifiers should be | * - modifiers only ever receive the unmodified time, as subsequent modifiers should be | ||||
| * working on the 'global' result of the modified curve, not some localised segment, | * 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... | * 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 | * - we start from the end of the stack, as only the last one matters for now | ||||
| * | * | ||||
| * Note: *fcu might be NULL | * Note: *fcu might be NULL | ||||
| */ | */ | ||||
| float evaluate_time_fmodifiers( | float evaluate_time_fmodifiers(FModifiersStackStorage *storage, | ||||
| FModifierStackStorage *storage, ListBase *modifiers, FCurve *fcu, float cvalue, float evaltime) | ListBase *modifiers, | ||||
| FCurve *fcu, | |||||
| float cvalue, | |||||
| float evaltime) | |||||
| { | { | ||||
| FModifier *fcm; | |||||
| /* sanity checks */ | /* sanity checks */ | ||||
| if (ELEM(NULL, modifiers, modifiers->last)) | if (ELEM(NULL, modifiers, modifiers->last)) | ||||
| return evaltime; | return evaltime; | ||||
| if (fcu && fcu->flag & FCURVE_MOD_OFF) | if (fcu && fcu->flag & FCURVE_MOD_OFF) | ||||
| return evaltime; | return evaltime; | ||||
| /* Starting from the end of the stack, calculate the time effects of various stacked modifiers | /* Starting from the end of the stack, calculate the time effects of various stacked modifiers | ||||
| * on the time the F-Curve should be evaluated at. | * on the time the F-Curve should be evaluated at. | ||||
| * | * | ||||
| * This is done in reverse order to standard evaluation, as when this is done in standard | * This is done in reverse order to standard evaluation, as when this is done in standard | ||||
| * order, each modifier would cause jumps to other points in the curve, forcing all | * order, each modifier would cause jumps to other points in the curve, forcing all | ||||
| * previous ones to be evaluated again for them to be correct. However, if we did in the | * previous ones to be evaluated again for them to be correct. However, if we did in the | ||||
| * reverse order as we have here, we can consider them a macro to micro type of waterfall | * reverse order as we have here, we can consider them a macro to micro type of waterfall | ||||
| * effect, which should get us the desired effects when using layered time manipulations | * effect, which should get us the desired effects when using layered time manipulations | ||||
| * (such as multiple 'stepped' modifiers in sequence, causing different stepping rates) | * (such as multiple 'stepped' modifiers in sequence, causing different stepping rates) | ||||
| */ | */ | ||||
| for (fcm = modifiers->last; fcm; fcm = fcm->prev) { | uint fcm_index = storage->modifier_count - 1; | ||||
| for (FModifier *fcm = modifiers->last; fcm; fcm = fcm->prev, fcm_index--) { | |||||
| const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); | const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); | ||||
| if (fmi == NULL) | if (fmi == NULL) | ||||
| continue; | continue; | ||||
| /* if modifier cannot be applied on this frame (whatever scale it is on, it won't affect the results) | /* if modifier cannot be applied on this frame (whatever scale it is on, it won't affect the results) | ||||
| * hence we shouldn't bother seeing what it would do given the chance | * hence we shouldn't bother seeing what it would do given the chance | ||||
| */ | */ | ||||
| if ((fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) == 0 || | if ((fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) == 0 || | ||||
| ((fcm->sfra <= evaltime) && (fcm->efra >= evaltime))) { | ((fcm->sfra <= evaltime) && (fcm->efra >= evaltime))) { | ||||
| /* only evaluate if there's a callback for this */ | /* only evaluate if there's a callback for this */ | ||||
| if (fmi->evaluate_modifier_time || fmi->evaluate_modifier_time_storage) { | if (fmi->evaluate_modifier_time) { | ||||
| if ((fcm->flag & (FMODIFIER_FLAG_DISABLED | FMODIFIER_FLAG_MUTED)) == 0) { | if ((fcm->flag & (FMODIFIER_FLAG_DISABLED | FMODIFIER_FLAG_MUTED)) == 0) { | ||||
| float influence = eval_fmodifier_influence(fcm, evaltime); | void *storage_ptr = POINTER_OFFSET(storage->buffer, | ||||
| float nval; | fcm_index * storage->size_per_modifier); | ||||
| if ((fmi->requires & FMI_REQUIRES_STORAGE) == 0) { | float nval = fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime, storage_ptr); | ||||
| nval = fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime); | |||||
| } | |||||
| else { | |||||
| nval = fmi->evaluate_modifier_time_storage(storage, fcu, fcm, cvalue, evaltime); | |||||
| } | |||||
| float influence = eval_fmodifier_influence(fcm, evaltime); | |||||
Done Inline ActionsMaybe use the POINTER_OFFSET macro to make this more clear. Also, maybe move this before nval and don't remove blank lines surrounding the call below. The same for the function below. angavrilov: Maybe use the POINTER_OFFSET macro to make this more clear. Also, maybe move this before nval… | |||||
| evaltime = interpf(nval, evaltime, influence); | evaltime = interpf(nval, evaltime, influence); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* return the modified evaltime */ | /* return the modified evaltime */ | ||||
| return evaltime; | return evaltime; | ||||
| } | } | ||||
| /* Evaluates the given set of F-Curve Modifiers using the given data | /* Evaluates the given set of F-Curve Modifiers using the given data | ||||
| * Should only be called after evaluate_time_fmodifiers() has been called... | * Should only be called after evaluate_time_fmodifiers() has been called... | ||||
| */ | */ | ||||
| void evaluate_value_fmodifiers(FModifierStackStorage *storage, | void evaluate_value_fmodifiers(FModifiersStackStorage *storage, | ||||
| ListBase *modifiers, | ListBase *modifiers, | ||||
| FCurve *fcu, | FCurve *fcu, | ||||
| float *cvalue, | float *cvalue, | ||||
| float evaltime) | float evaltime) | ||||
| { | { | ||||
| FModifier *fcm; | FModifier *fcm; | ||||
| /* sanity checks */ | /* sanity checks */ | ||||
| if (ELEM(NULL, modifiers, modifiers->first)) | if (ELEM(NULL, modifiers, modifiers->first)) | ||||
| return; | return; | ||||
| if (fcu->flag & FCURVE_MOD_OFF) | if (fcu->flag & FCURVE_MOD_OFF) | ||||
| return; | return; | ||||
| /* evaluate modifiers */ | /* evaluate modifiers */ | ||||
| for (fcm = modifiers->first; fcm; fcm = fcm->next) { | uint fcm_index = 0; | ||||
| for (fcm = modifiers->first; fcm; fcm = fcm->next, fcm_index++) { | |||||
| const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); | const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm); | ||||
| if (fmi == NULL) | if (fmi == NULL) | ||||
| continue; | continue; | ||||
| /* only evaluate if there's a callback for this, and if F-Modifier can be evaluated on this frame */ | /* only evaluate if there's a callback for this, and if F-Modifier can be evaluated on this frame */ | ||||
| if ((fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) == 0 || | if ((fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) == 0 || | ||||
| ((fcm->sfra <= evaltime) && (fcm->efra >= evaltime))) { | ((fcm->sfra <= evaltime) && (fcm->efra >= evaltime))) { | ||||
| if (fmi->evaluate_modifier || fmi->evaluate_modifier_storage) { | if (fmi->evaluate_modifier) { | ||||
| if ((fcm->flag & (FMODIFIER_FLAG_DISABLED | FMODIFIER_FLAG_MUTED)) == 0) { | if ((fcm->flag & (FMODIFIER_FLAG_DISABLED | FMODIFIER_FLAG_MUTED)) == 0) { | ||||
| float influence = eval_fmodifier_influence(fcm, evaltime); | void *storage_ptr = POINTER_OFFSET(storage->buffer, | ||||
| float nval = *cvalue; | fcm_index * storage->size_per_modifier); | ||||
| if ((fmi->requires & FMI_REQUIRES_STORAGE) == 0) { | float nval = *cvalue; | ||||
| fmi->evaluate_modifier(fcu, fcm, &nval, evaltime); | fmi->evaluate_modifier(fcu, fcm, &nval, evaltime, storage_ptr); | ||||
| } | |||||
| else { | |||||
| fmi->evaluate_modifier_storage(storage, fcu, fcm, &nval, evaltime); | |||||
| } | |||||
| float influence = eval_fmodifier_influence(fcm, evaltime); | |||||
| *cvalue = interpf(nval, *cvalue, influence); | *cvalue = interpf(nval, *cvalue, influence); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* ---------- */ | /* ---------- */ | ||||
| Show All 28 Lines | |||||
<blank line>