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. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to