[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [19345] branches/blender2.5/blender/source /blender: F-Curve Modifiers: Envelope Modifier
Joshua Leung
aligorith at gmail.com
Sat Mar 21 04:49:24 CET 2009
Revision: 19345
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=19345
Author: aligorith
Date: 2009-03-21 04:49:22 +0100 (Sat, 21 Mar 2009)
Log Message:
-----------
F-Curve Modifiers: Envelope Modifier
Got the basic envelope modifier code working, including primitive drawing of relevant helper info in the graph view. It doesn't work in a very intuitive way yet, so I will recode it soon.
Modified Paths:
--------------
branches/blender2.5/blender/source/blender/blenkernel/intern/fcurve.c
branches/blender2.5/blender/source/blender/blenloader/intern/readfile.c
branches/blender2.5/blender/source/blender/blenloader/intern/writefile.c
branches/blender2.5/blender/source/blender/editors/space_graph/graph_buttons.c
branches/blender2.5/blender/source/blender/editors/space_graph/graph_draw.c
Modified: branches/blender2.5/blender/source/blender/blenkernel/intern/fcurve.c
===================================================================
--- branches/blender2.5/blender/source/blender/blenkernel/intern/fcurve.c 2009-03-20 23:19:47 UTC (rev 19344)
+++ branches/blender2.5/blender/source/blender/blenkernel/intern/fcurve.c 2009-03-21 03:49:22 UTC (rev 19345)
@@ -1384,23 +1384,42 @@
static void fcm_envelope_free (FModifier *fcm)
{
- FMod_Envelope *data= (FMod_Envelope *)fcm->data;
+ FMod_Envelope *env= (FMod_Envelope *)fcm->data;
/* free envelope data array */
- if (data->data)
- MEM_freeN(data->data);
+ if (env->data)
+ MEM_freeN(env->data);
}
static void fcm_envelope_copy (FModifier *fcm, FModifier *src)
{
- FMod_Envelope *gen= (FMod_Envelope *)fcm->data;
- FMod_Envelope *ogen= (FMod_Envelope *)src->data;
+ FMod_Envelope *env= (FMod_Envelope *)fcm->data;
+ FMod_Envelope *oenv= (FMod_Envelope *)src->data;
/* copy envelope data array */
- if (ogen->data)
- gen->data= MEM_dupallocN(ogen->data);
+ 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;
@@ -1412,7 +1431,7 @@
if (env->data == NULL) return;
prevfed= env->data;
fed= prevfed + 1;
- lastfed= prevfed + env->totvert-1;
+ lastfed= prevfed + (env->totvert-1);
/* get min/max values for envelope at evaluation time (relative to mid-value) */
if (prevfed->time >= evaltime) {
@@ -1434,10 +1453,10 @@
diff= fed->time - prevfed->time;
afac= (evaltime - prevfed->time) / diff;
- bfac= (fed->time - evaltime)/(diff);
+ bfac= (fed->time - evaltime) / diff;
- min= afac*prevfed->min + bfac*fed->min;
- max= afac*prevfed->max + bfac*fed->max;
+ min= bfac*prevfed->min + afac*fed->min;
+ max= bfac*prevfed->max + afac*fed->max;
break;
}
@@ -1460,8 +1479,8 @@
"FMod_Envelope", /* struct name */
fcm_envelope_free, /* free data */
fcm_envelope_copy, /* copy data */
- NULL, /* new data */
- NULL /*fcm_envelope_verify*/, /* verify */
+ fcm_envelope_new_data, /* new data */
+ fcm_envelope_verify, /* verify */
fcm_envelope_evaluate /* evaluate */
};
@@ -1831,11 +1850,13 @@
return;
/* free modifier's special data (stored inside fcm->data) */
- if (fmi && fmi->free_data)
- fmi->free_data(fcm);
-
- /* free modifier's data (fcm->data) */
- MEM_freeN(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)
@@ -1917,7 +1938,7 @@
/* sanity checks */
if ELEM(NULL, fcu, fcu->modifiers.first)
- return NULL;
+ return;
/* deactivate all, and set current one active */
for (fm= fcu->modifiers.first; fm; fm= fm->next)
Modified: branches/blender2.5/blender/source/blender/blenloader/intern/readfile.c
===================================================================
--- branches/blender2.5/blender/source/blender/blenloader/intern/readfile.c 2009-03-20 23:19:47 UTC (rev 19344)
+++ branches/blender2.5/blender/source/blender/blenloader/intern/readfile.c 2009-03-21 03:49:22 UTC (rev 19345)
@@ -1728,6 +1728,13 @@
data->coefficients= newdataadr(fd, data->coefficients);
}
break;
+ case FMODIFIER_TYPE_ENVELOPE:
+ {
+ FMod_Envelope *data= (FMod_Envelope *)fcm->data;
+
+ data->data= newdataadr(fd, data->data);
+ }
+ break;
case FMODIFIER_TYPE_PYTHON:
{
FMod_Python *data= (FMod_Python *)fcm->data;
Modified: branches/blender2.5/blender/source/blender/blenloader/intern/writefile.c
===================================================================
--- branches/blender2.5/blender/source/blender/blenloader/intern/writefile.c 2009-03-20 23:19:47 UTC (rev 19344)
+++ branches/blender2.5/blender/source/blender/blenloader/intern/writefile.c 2009-03-21 03:49:22 UTC (rev 19345)
@@ -810,6 +810,15 @@
writedata(wd, DATA, sizeof(float)*(data->arraysize), data->coefficients);
}
break;
+ case FMODIFIER_TYPE_ENVELOPE:
+ {
+ FMod_Envelope *data= (FMod_Envelope *)fcm->data;
+
+ /* write envelope data */
+ if (data->data)
+ writedata(wd, DATA, sizeof(FCM_EnvelopeData)*(data->totvert), data->data);
+ }
+ break;
case FMODIFIER_TYPE_PYTHON:
{
FMod_Python *data = (FMod_Python *)fcm->data;
@@ -822,7 +831,7 @@
}
}
- /* Write the constraint */
+ /* Write the modifier */
writestruct(wd, DATA, "FModifier", 1, fcm);
}
}
Modified: branches/blender2.5/blender/source/blender/editors/space_graph/graph_buttons.c
===================================================================
--- branches/blender2.5/blender/source/blender/editors/space_graph/graph_buttons.c 2009-03-20 23:19:47 UTC (rev 19344)
+++ branches/blender2.5/blender/source/blender/editors/space_graph/graph_buttons.c 2009-03-21 03:49:22 UTC (rev 19345)
@@ -133,7 +133,7 @@
*/
}
-/* -------------- */
+/* ******************* drivers ******************************** */
#define B_IPO_DEPCHANGE 10
@@ -217,7 +217,7 @@
}
}
-/* -------------- */
+/* ******************* f-modifiers ******************************** */
#define B_FMODIFIER_REDRAW 20
@@ -262,7 +262,6 @@
fcurve_set_active_modifier(fcu, fcm);
}
-
/* callback to remove the given modifier */
static void delete_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v)
{
@@ -272,6 +271,8 @@
/* remove the given F-Modifier from the F-Curve */
fcurve_remove_modifier(fcu, fcm);
}
+
+/* --------------- */
/* draw settings for generator modifier */
static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col)
@@ -449,7 +450,9 @@
}
}
-/* draw settings for generator modifier */
+/* --------------- */
+
+/* draw settings for cycles modifier */
static void draw_modifier__cycles(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col)
{
FMod_Cycles *data= (FMod_Cycles *)fcm->data;
@@ -477,6 +480,223 @@
uiBlockEndAlign(block);
}
+/* --------------- */
+
+#define BINARYSEARCH_FRAMEEQ_THRESH 0.0001
+
+/* 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)
+ */
+static int binarysearch_fcm_envelopedata_index (FCM_EnvelopeData array[], float frame, int arraylen, short *exists)
+{
+ int start=0, end=arraylen;
+ int loopbreaker= 0, maxloop= arraylen * 2;
+
+ /* initialise exists-flag first */
+ *exists= 0;
+
+ /* sneaky optimisations (don't go through searching process if...):
+ * - keyframe to be added is to be added out of current bounds
+ * - keyframe to be added would replace one of the existing ones on bounds
+ */
+ if ((arraylen <= 0) || (array == NULL)) {
+ printf("Warning: binarysearch_fcm_envelopedata_index() encountered invalid array \n");
+ return 0;
+ }
+ else {
+ /* check whether to add before/after/on */
+ float framenum;
+
+ /* 'First' Point (when only one point, this case is used) */
+ framenum= array[0].time;
+ if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
+ *exists = 1;
+ return 0;
+ }
+ else if (frame < framenum)
+ return 0;
+
+ /* 'Last' Point */
+ framenum= array[(arraylen-1)].time;
+ if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
+ *exists= 1;
+ return (arraylen - 1);
+ }
+ else if (frame > framenum)
+ return arraylen;
+ }
+
+
+ /* most of the time, this loop is just to find where to put it
+ * - 'loopbreaker' is just here to prevent infinite loops
+ */
+ for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
+ /* compute and get midpoint */
+ int mid = start + ((end - start) / 2); /* we calculate the midpoint this way to avoid int overflows... */
+ float midfra= array[mid].time;
+
+ /* check if exactly equal to midpoint */
+ if (IS_EQT(frame, midfra, BINARYSEARCH_FRAMEEQ_THRESH)) {
+ *exists = 1;
+ return mid;
+ }
+
+ /* repeat in upper/lower half */
+ if (frame > midfra)
+ start= mid + 1;
+ else if (frame < midfra)
+ end= mid - 1;
+ }
+
+ /* print error if loop-limit exceeded */
+ if (loopbreaker == (maxloop-1)) {
+ printf("Error: binarysearch_fcm_envelopedata_index() was taking too long \n");
+
+ // include debug info
+ printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen);
+ }
+
+ /* not found, so return where to place it */
+ return start;
+}
+
+/* callback to add new envelope data point */
+// TODO: should we have a separate file for things like this?
+static void fmod_envelope_addpoint_cb (bContext *C, void *fcm_dv, void *dummy)
+{
+ Scene *scene= CTX_data_scene(C);
+ FMod_Envelope *env= (FMod_Envelope *)fcm_dv;
+ FCM_EnvelopeData *fedn;
+ FCM_EnvelopeData fed;
+
+ /* init template data */
+ fed.min= -1.0f;
+ fed.max= 1.0f;
+ fed.time= (float)scene->r.cfra; // XXX make this int for ease of use?
+ fed.f1= fed.f2= 0;
+
+ /* check that no data exists for the current frame... */
+ if (env->data) {
+ short exists = -1;
+ int i= binarysearch_fcm_envelopedata_index(env->data, (float)(scene->r.cfra), env->totvert, &exists);
+
+ /* binarysearch_...() will set exists by default to 0, so if it is non-zero, that means that the point exists already */
+ if (exists)
+ return;
+
+ /* add new */
+ fedn= MEM_callocN((env->totvert+1)*sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
+
+ /* add the points that should occur before the point to be pasted */
+ if (i > 0)
+ memcpy(fedn, env->data, i*sizeof(FCM_EnvelopeData));
+
+ /* add point to paste at index i */
+ *(fedn + i)= fed;
+
+ /* add the points that occur after the point to be pasted */
+ if (i < env->totvert)
+ memcpy(fedn+i+1, env->data+i, (env->totvert-i)*sizeof(FCM_EnvelopeData));
+
+ /* replace (+ free) old with new */
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list