[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