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-04-14 15:53:41 +0400
committerJoshua Leung <aligorith@gmail.com>2009-04-14 15:53:41 +0400
commit3ef247eed953ea28aca2bc92879ff1c32f04b7f4 (patch)
tree6b645679dd5046a483ec766105bb4c8144c3784b /source/blender/blenkernel/intern/fcurve.c
parent2d17d8623910b7cbcb353d410a47b9c758d8bc41 (diff)
FCurve Modifiers - "Limits" Modifier:
This new modifier clamps the values of the F-Curve to lie within specified bounds, much like Limit Location/Rotation/Scale constraints do. You can limit by time range(s) and/or value range(s).
Diffstat (limited to 'source/blender/blenkernel/intern/fcurve.c')
-rw-r--r--source/blender/blenkernel/intern/fcurve.c86
1 files changed, 73 insertions, 13 deletions
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 3e1b6f29403..2783c135cb9 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1135,6 +1135,43 @@ static FModifierTypeInfo FMI_MODNAME = {
};
#endif
+/* Utilities For F-Curve Modifiers ---------------------- */
+
+/* Recalculate the F-Curve at evaltime, as modified by the given F-Curve */
+// TODO: this isn't really such an elegant solution for time-modifying F-Modifiers, but it gets too difficult otherwise for now...
+static float fcm_reevaluate_fcurve (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
+{
+ ListBase modifiers = {NULL, NULL};
+ float new_value = 0.0f;
+
+ /* sanity checking */
+ if ELEM(NULL, fcu, fcm)
+ return cvalue;
+
+ /* unlink given modifier from previous modifiers, keeping the previous ones on the F-Curve,
+ * but ones after off the F-Curve (so that we avoid the infinitely re-entrant situation).
+ */
+ modifiers.first= fcm;
+ modifiers.last= fcu->modifiers.last;
+
+ if (fcm->prev) {
+ fcm->prev->next= NULL;
+ fcu->modifiers.last= fcm->prev;
+ }
+ else
+ fcu->modifiers.first= fcu->modifiers.last= NULL;
+ fcm->prev= NULL;
+
+ /* re-enter the evaluation loop (but without the burden of evaluating any modifiers, so 'should' be relatively quick) */
+ new_value= evaluate_fcurve(fcu, evaltime);
+
+ /* restore modifiers (don't assume everything is still ok after being re-entrant) */
+ addlisttolist(&fcu->modifiers, &modifiers);
+
+ /* return the new value */
+ return new_value;
+}
+
/* Generator F-Curve Modifier --------------------------- */
/* Generators available:
@@ -1547,9 +1584,7 @@ static void fcm_cycles_new_data (void *mdata)
static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
{
FMod_Cycles *data= (FMod_Cycles *)fcm->data;
- ListBase mods = {NULL, NULL};
float prevkey[2], lastkey[2], cycyofs=0.0f;
- float new_value;
short side=0, mode=0;
int cycles=0;
@@ -1644,17 +1679,8 @@ static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, flo
if (evaltime < ofs) evaltime += cycdx;
}
-
- /* store modifiers after (and including ourself) before recalculating curve with new evaltime */
- mods= fcu->modifiers;
- fcu->modifiers.first= fcu->modifiers.last= NULL;
-
- /* re-enter the evaluation loop (but without the burden of evaluating any modifiers, so 'should' be relatively quick) */
- new_value= evaluate_fcurve(fcu, evaltime);
-
- /* restore modifiers, and set new value (don't assume everything is still ok after being re-entrant) */
- fcu->modifiers= mods;
- *cvalue= new_value + cycyofs;
+ /* reevaluate F-Curve at the new time that we've decided on */
+ *cvalue= fcm_reevaluate_fcurve(fcu, fcm, *cvalue, evaltime) + cycyofs;
}
static FModifierTypeInfo FMI_CYCLES = {
@@ -1762,6 +1788,39 @@ static FModifierTypeInfo FMI_PYTHON = {
};
+/* Limits F-Curve Modifier --------------------------- */
+
+static void fcm_limits_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+{
+ FMod_Limits *data= (FMod_Limits *)fcm->data;
+
+ /* time limits first */
+ if ((data->flag & FCM_LIMIT_XMIN) && (evaltime < data->rect.xmin))
+ *cvalue= fcm_reevaluate_fcurve(fcu, fcm, *cvalue, data->rect.xmin);
+ if ((data->flag & FCM_LIMIT_XMAX) && (evaltime > data->rect.xmax))
+ *cvalue= fcm_reevaluate_fcurve(fcu, fcm, *cvalue, data->rect.xmax);
+
+ /* 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 /*fcm_python_verify*/, /* verify */
+ 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.
@@ -1781,6 +1840,7 @@ static void fmods_init_typeinfo ()
fmodifiersTypeInfo[4]= NULL/*&FMI_NOISE*/; /* Apply-Noise F-Curve Modifier */ // XXX unimplemented
fmodifiersTypeInfo[5]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented
fmodifiersTypeInfo[6]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */
+ fmodifiersTypeInfo[7]= &FMI_LIMITS; /* Limits F-Curve Modifier */
}
/* This function should be used for getting the appropriate type-info when only