svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r20855:20928
[blender.git] / source / blender / blenkernel / intern / fcurve.c
1 /* Testing code for new animation system in 2.5 
2  * Copyright 2009, Joshua Leung
3  */
4  
5
6 #include <math.h>
7 #include <stdio.h>
8 #include <stddef.h>
9 #include <string.h>
10 #include <float.h>
11
12 #ifdef HAVE_CONFIG_H
13 #include <config.h>
14 #endif
15
16 #include "MEM_guardedalloc.h"
17
18 #include "DNA_anim_types.h"
19
20 #include "BLI_blenlib.h"
21 #include "BLI_arithb.h"
22 #include "BLI_noise.h"
23
24 #include "BKE_fcurve.h"
25 #include "BKE_curve.h" 
26 #include "BKE_global.h"
27 #include "BKE_idprop.h"
28 #include "BKE_utildefines.h"
29
30 #include "RNA_access.h"
31 #include "RNA_types.h"
32
33 #ifndef DISABLE_PYTHON
34 #include "BPY_extern.h" /* for BPY_pydriver_eval() */
35 #endif
36
37 #define SMALL -1.0e-10
38 #define SELECT 1
39
40 /* ************************** Data-Level Functions ************************* */
41
42 /* ---------------------- Freeing --------------------------- */
43
44 /* Frees the F-Curve itself too, so make sure BLI_remlink is called before calling this... */
45 void free_fcurve (FCurve *fcu) 
46 {
47         if (fcu == NULL) 
48                 return;
49         
50         /* free curve data */
51         if (fcu) {
52                 if (fcu->bezt) MEM_freeN(fcu->bezt);
53                 if (fcu->fpt) MEM_freeN(fcu->fpt);
54         }
55         
56         /* free RNA-path, as this were allocated when getting the path string */
57         if (fcu->rna_path)
58                 MEM_freeN(fcu->rna_path);
59         
60         /* free extra data - i.e. modifiers, and driver */
61         fcurve_free_driver(fcu);
62         fcurve_free_modifiers(fcu);
63         
64         /* free f-curve itself */
65         MEM_freeN(fcu);
66 }
67
68 /* Frees a list of F-Curves */
69 void free_fcurves (ListBase *list)
70 {
71         FCurve *fcu, *fcn;
72         
73         /* sanity check */
74         if (list == NULL)
75                 return;
76                 
77         /* free data - no need to call remlink before freeing each curve, 
78          * as we store reference to next, and freeing only touches the curve
79          * it's given
80          */
81         for (fcu= list->first; fcu; fcu= fcn) {
82                 fcn= fcu->next;
83                 free_fcurve(fcu);
84         }
85         
86         /* clear pointers just in case */
87         list->first= list->last= NULL;
88 }       
89
90 /* ---------------------- Copy --------------------------- */
91
92 /* duplicate an F-Curve */
93 FCurve *copy_fcurve (FCurve *fcu)
94 {
95         FCurve *fcu_d;
96         
97         /* sanity check */
98         if (fcu == NULL)
99                 return NULL;
100                 
101         /* make a copy */
102         fcu_d= MEM_dupallocN(fcu);
103         
104         fcu_d->next= fcu_d->prev= NULL;
105         fcu_d->grp= NULL;
106         
107         /* copy curve data */
108         fcu_d->bezt= MEM_dupallocN(fcu_d->bezt);
109         fcu_d->fpt= MEM_dupallocN(fcu_d->fpt);
110         
111         /* copy rna-path */
112         fcu_d->rna_path= MEM_dupallocN(fcu_d->rna_path);
113         
114         /* copy driver */
115         fcu_d->driver= fcurve_copy_driver(fcu_d->driver);
116         
117         /* copy modifiers */
118         fcurve_copy_modifiers(&fcu_d->modifiers, &fcu->modifiers);
119         
120         /* return new data */
121         return fcu_d;
122 }
123
124 /* duplicate a list of F-Curves */
125 void copy_fcurves (ListBase *dst, ListBase *src)
126 {
127         FCurve *dfcu, *sfcu;
128         
129         /* sanity checks */
130         if ELEM(NULL, dst, src)
131                 return;
132         
133         /* clear destination list first */
134         dst->first= dst->last= NULL;
135         
136         /* copy one-by-one */
137         for (sfcu= src->first; sfcu; sfcu= sfcu->next) {
138                 dfcu= copy_fcurve(sfcu);
139                 BLI_addtail(dst, dfcu);
140         }
141 }
142
143 /* ---------------------- Relink --------------------------- */
144
145 #if 0
146 /* uses id->newid to match pointers with other copied data 
147  *      - called after single-user or other such
148  */
149                         if (icu->driver)
150                                 ID_NEW(icu->driver->ob);
151 #endif
152
153 /* --------------------- Finding -------------------------- */
154
155 /* Find the F-Curve affecting the given RNA-access path + index, in the list of F-Curves provided */
156 FCurve *list_find_fcurve (ListBase *list, const char rna_path[], const int array_index)
157 {
158         FCurve *fcu;
159         
160         /* sanity checks */
161         if ( ELEM(NULL, list, rna_path) || (array_index < 0) )
162                 return NULL;
163         
164         /* check paths of curves, then array indices... */
165         for (fcu= list->first; fcu; fcu= fcu->next) {
166                 /* simple string-compare (this assumes that they have the same root...) */
167                 if (fcu->rna_path && !strcmp(fcu->rna_path, rna_path)) {
168                         /* now check indicies */
169                         if (fcu->array_index == array_index)
170                                 return fcu;
171                 }
172         }
173         
174         /* return */
175         return NULL;
176 }
177
178 short on_keyframe_fcurve(FCurve *fcu, float cfra)
179 {
180         BezTriple *bezt;
181         unsigned i;
182
183         bezt= fcu->bezt;
184         for (i=0; i<fcu->totvert; i++, bezt++) {
185                 if (IS_EQ(bezt->vec[1][0], cfra))
186                         return 1;
187         }
188         
189         return 0;
190 }
191
192 /* Calculate the extents of F-Curve's data */
193 void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax)
194 {
195         float xminv=999999999.0f, xmaxv=-999999999.0f;
196         float yminv=999999999.0f, ymaxv=-999999999.0f;
197         short foundvert=0;
198         unsigned int i;
199         
200         if (fcu->totvert) {
201                 if (fcu->bezt) {
202                         /* frame range can be directly calculated from end verts */
203                         if (xmin || xmax) {
204                                 xminv= MIN2(xminv, fcu->bezt[0].vec[1][0]);
205                                 xmaxv= MAX2(xmaxv, fcu->bezt[fcu->totvert-1].vec[1][0]);
206                         }
207                         
208                         /* only loop over keyframes to find extents for values if needed */
209                         if (ymin || ymax) {
210                                 BezTriple *bezt;
211                                 
212                                 for (bezt=fcu->bezt, i=0; i < fcu->totvert; bezt++, i++) {
213                                         if (bezt->vec[1][1] < yminv)
214                                                 yminv= bezt->vec[1][1];
215                                         if (bezt->vec[1][1] > ymaxv)
216                                                 ymaxv= bezt->vec[1][1];
217                                 }
218                         }
219                 }
220                 else if (fcu->fpt) {
221                         /* frame range can be directly calculated from end verts */
222                         if (xmin || xmax) {
223                                 xminv= MIN2(xminv, fcu->fpt[0].vec[0]);
224                                 xmaxv= MAX2(xmaxv, fcu->fpt[fcu->totvert-1].vec[0]);
225                         }
226                         
227                         /* only loop over keyframes to find extents for values if needed */
228                         if (ymin || ymax) {
229                                 FPoint *fpt;
230                                 
231                                 for (fpt=fcu->fpt, i=0; i < fcu->totvert; fpt++, i++) {
232                                         if (fpt->vec[1] < yminv)
233                                                 yminv= fpt->vec[1];
234                                         if (fpt->vec[1] > ymaxv)
235                                                 ymaxv= fpt->vec[1];
236                                 }
237                         }
238                 }
239                 
240                 foundvert=1;
241         }
242         
243         /* minimum sizes are 1.0f */
244         if (foundvert) {
245                 if (xminv == xmaxv) xmaxv += 1.0f;
246                 if (yminv == ymaxv) ymaxv += 1.0f;
247                 
248                 if (xmin) *xmin= xminv;
249                 if (xmax) *xmax= xmaxv;
250                 
251                 if (ymin) *ymin= yminv;
252                 if (ymax) *ymax= ymaxv;
253         }
254         else {
255                 if (xmin) *xmin= 0.0f;
256                 if (xmax) *xmax= 0.0f;
257                 
258                 if (ymin) *ymin= 1.0f;
259                 if (ymax) *ymax= 1.0f;
260         }
261 }
262
263 /* Calculate the extents of F-Curve's keyframes */
264 void calc_fcurve_range (FCurve *fcu, float *start, float *end)
265 {
266         float min=999999999.0f, max=-999999999.0f;
267         short foundvert=0;
268
269         if (fcu->totvert) {
270                 if (fcu->bezt) {
271                         min= MIN2(min, fcu->bezt[0].vec[1][0]);
272                         max= MAX2(max, fcu->bezt[fcu->totvert-1].vec[1][0]);
273                 }
274                 else if (fcu->fpt) {
275                         min= MIN2(min, fcu->fpt[0].vec[0]);
276                         max= MAX2(max, fcu->fpt[fcu->totvert-1].vec[0]);
277                 }
278                 
279                 foundvert=1;
280         }
281         
282         /* minimum length is 1 frame */
283         if (foundvert) {
284                 if (min == max) max += 1.0f;
285                 *start= min;
286                 *end= max;
287         }
288         else {
289                 *start= 0.0f;
290                 *end= 1.0f;
291         }
292 }
293
294 /* ***************************** Keyframe Column Tools ********************************* */
295
296 /* add a BezTriple to a column */
297 void bezt_add_to_cfra_elem (ListBase *lb, BezTriple *bezt)
298 {
299         CfraElem *ce, *cen;
300         
301         for (ce= lb->first; ce; ce= ce->next) {
302                 /* double key? */
303                 if (ce->cfra == bezt->vec[1][0]) {
304                         if (bezt->f2 & SELECT) ce->sel= bezt->f2;
305                         return;
306                 }
307                 /* should key be inserted before this column? */
308                 else if (ce->cfra > bezt->vec[1][0]) break;
309         }
310         
311         /* create a new column */
312         cen= MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem"); 
313         if (ce) BLI_insertlinkbefore(lb, ce, cen);
314         else BLI_addtail(lb, cen);
315
316         cen->cfra= bezt->vec[1][0];
317         cen->sel= bezt->f2;
318 }
319
320 /* ***************************** Samples Utilities ******************************* */
321 /* Some utilities for working with FPoints (i.e. 'sampled' animation curve data, such as
322  * data imported from BVH/Mocap files), which are specialised for use with high density datasets,
323  * which BezTriples/Keyframe data are ill equipped to do.
324  */
325  
326  
327 /* Basic sampling callback which acts as a wrapper for evaluate_fcurve() 
328  *      'data' arg here is unneeded here...
329  */
330 float fcurve_samplingcb_evalcurve (FCurve *fcu, void *data, float evaltime)
331 {
332         /* assume any interference from drivers on the curve is intended... */
333         return evaluate_fcurve(fcu, evaltime);
334
335
336  
337 /* Main API function for creating a set of sampled curve data, given some callback function 
338  * used to retrieve the values to store.
339  */
340 void fcurve_store_samples (FCurve *fcu, void *data, int start, int end, FcuSampleFunc sample_cb)
341 {
342         FPoint *fpt, *new_fpt;
343         int cfra;
344         
345         /* sanity checks */
346         // TODO: make these tests report errors using reports not printf's
347         if ELEM(NULL, fcu, sample_cb) {
348                 printf("Error: No F-Curve with F-Curve Modifiers to Bake\n");
349                 return;
350         }
351         if (start >= end) {
352                 printf("Error: Frame range for Sampled F-Curve creation is inappropriate \n");
353                 return;
354         }
355         
356         /* set up sample data */
357         fpt= new_fpt= MEM_callocN(sizeof(FPoint)*(end-start+1), "FPoint Samples");
358         
359         /* use the sampling callback at 1-frame intervals from start to end frames */
360         for (cfra= start; cfra <= end; cfra++, fpt++) {
361                 fpt->vec[0]= (float)cfra;
362                 fpt->vec[1]= sample_cb(fcu, data, (float)cfra);
363         }
364         
365         /* free any existing sample/keyframe data on curve  */
366         if (fcu->bezt) MEM_freeN(fcu->bezt);
367         if (fcu->fpt) MEM_freeN(fcu->fpt);
368         
369         /* store the samples */
370         fcu->bezt= NULL;
371         fcu->fpt= new_fpt;
372         fcu->totvert= end - start + 1;
373 }
374
375 /* ***************************** F-Curve Sanity ********************************* */
376 /* The functions here are used in various parts of Blender, usually after some editing
377  * of keyframe data has occurred. They ensure that keyframe data is properly ordered and
378  * that the handles are correctly 
379  */
380
381 /* This function recalculates the handles of an F-Curve 
382  * If the BezTriples have been rearranged, sort them first before using this.
383  */
384 void calchandles_fcurve (FCurve *fcu)
385 {
386         BezTriple *bezt, *prev, *next;
387         int a= fcu->totvert;
388
389         /* Error checking:
390          *      - need at least two points
391          *      - need bezier keys
392          *      - only bezier-interpolation has handles (for now)
393          */
394         if (ELEM(NULL, fcu, fcu->bezt) || (a < 2) /*|| ELEM(fcu->ipo, BEZT_IPO_CONST, BEZT_IPO_LIN)*/) 
395                 return;
396         
397         /* get initial pointers */
398         bezt= fcu->bezt;
399         prev= NULL;
400         next= (bezt + 1);
401         
402         /* loop over all beztriples, adjusting handles */
403         while (a--) {
404                 /* clamp timing of handles to be on either side of beztriple */
405                 if (bezt->vec[0][0] > bezt->vec[1][0]) bezt->vec[0][0]= bezt->vec[1][0];
406                 if (bezt->vec[2][0] < bezt->vec[1][0]) bezt->vec[2][0]= bezt->vec[1][0];
407                 
408                 /* calculate auto-handles */
409                 if (fcu->flag & FCURVE_AUTO_HANDLES) 
410                         calchandleNurb(bezt, prev, next, 2);    /* 2==special autohandle && keep extrema horizontal */
411                 else
412                         calchandleNurb(bezt, prev, next, 1);    /* 1==special autohandle */
413                 
414                 /* for automatic ease in and out */
415                 if ((bezt->h1==HD_AUTO) && (bezt->h2==HD_AUTO)) {
416                         /* only do this on first or last beztriple */
417                         if ((a == 0) || (a == fcu->totvert-1)) {
418                                 /* set both handles to have same horizontal value as keyframe */
419                                 if (fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) {
420                                         bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
421                                 }
422                         }
423                 }
424                 
425                 /* advance pointers for next iteration */
426                 prev= bezt;
427                 if (a == 1) next= NULL;
428                 else next++;
429                 bezt++;
430         }
431 }
432
433 /* Use when F-Curve with handles has changed
434  * It treats all BezTriples with the following rules:
435  *  - PHASE 1: do types have to be altered?
436  *              -> Auto handles: become aligned when selection status is NOT(000 || 111)
437  *              -> Vector handles: become 'nothing' when (one half selected AND other not)
438  *  - PHASE 2: recalculate handles
439 */
440 void testhandles_fcurve (FCurve *fcu)
441 {
442         BezTriple *bezt;
443         unsigned int a;
444
445         /* only beztriples have handles (bpoints don't though) */
446         if ELEM(NULL, fcu, fcu->bezt)
447                 return;
448         
449         /* loop over beztriples */
450         for (a=0, bezt=fcu->bezt; a < fcu->totvert; a++, bezt++) {
451                 short flag= 0;
452                 
453                 /* flag is initialised as selection status
454                  * of beztriple control-points (labelled 0,1,2)
455                  */
456                 if (bezt->f1 & SELECT) flag |= (1<<0); // == 1
457                 if (bezt->f2 & SELECT) flag |= (1<<1); // == 2
458                 if (bezt->f3 & SELECT) flag |= (1<<2); // == 4
459                 
460                 /* one or two handles selected only */
461                 if (ELEM(flag, 0, 7)==0) {
462                         /* auto handles become aligned */
463                         if (bezt->h1==HD_AUTO)
464                                 bezt->h1= HD_ALIGN;
465                         if (bezt->h2==HD_AUTO)
466                                 bezt->h2= HD_ALIGN;
467                         
468                         /* vector handles become 'free' when only one half selected */
469                         if (bezt->h1==HD_VECT) {
470                                 /* only left half (1 or 2 or 1+2) */
471                                 if (flag < 4) 
472                                         bezt->h1= 0;
473                         }
474                         if (bezt->h2==HD_VECT) {
475                                 /* only right half (4 or 2+4) */
476                                 if (flag > 3) 
477                                         bezt->h2= 0;
478                         }
479                 }
480         }
481
482         /* recalculate handles */
483         calchandles_fcurve(fcu);
484 }
485
486 /* This function sorts BezTriples so that they are arranged in chronological order,
487  * as tools working on F-Curves expect that the BezTriples are in order.
488  */
489 void sort_time_fcurve (FCurve *fcu)
490 {
491         short ok= 1;
492         
493         /* keep adjusting order of beztriples until nothing moves (bubble-sort) */
494         while (ok) {
495                 ok= 0;
496                 
497                 /* currently, will only be needed when there are beztriples */
498                 if (fcu->bezt) {
499                         BezTriple *bezt;
500                         unsigned int a;
501                         
502                         /* loop over ALL points to adjust position in array and recalculate handles */
503                         for (a=0, bezt=fcu->bezt; a < fcu->totvert; a++, bezt++) {
504                                 /* check if thee's a next beztriple which we could try to swap with current */
505                                 if (a < (fcu->totvert-1)) {
506                                         /* swap if one is after the other (and indicate that order has changed) */
507                                         if (bezt->vec[1][0] > (bezt+1)->vec[1][0]) {
508                                                 SWAP(BezTriple, *bezt, *(bezt+1));
509                                                 ok= 1;
510                                         }
511                                         
512                                         /* if either one of both of the points exceeds crosses over the keyframe time... */
513                                         if ( (bezt->vec[0][0] > bezt->vec[1][0]) && (bezt->vec[2][0] < bezt->vec[1][0]) ) {
514                                                 /* swap handles if they have switched sides for some reason */
515                                                 SWAP(float, bezt->vec[0][0], bezt->vec[2][0]);
516                                                 SWAP(float, bezt->vec[0][1], bezt->vec[2][1]);
517                                         }
518                                         else {
519                                                 /* clamp handles */
520                                                 if (bezt->vec[0][0] > bezt->vec[1][0]) 
521                                                         bezt->vec[0][0]= bezt->vec[1][0];
522                                                 if (bezt->vec[2][0] < bezt->vec[1][0]) 
523                                                         bezt->vec[2][0]= bezt->vec[1][0];
524                                         }
525                                 }
526                         }
527                 }
528         }
529 }
530
531 /* This function tests if any BezTriples are out of order, thus requiring a sort */
532 short test_time_fcurve (FCurve *fcu)
533 {
534         unsigned int a;
535         
536         /* sanity checks */
537         if (fcu == NULL)
538                 return 0;
539         
540         /* currently, only need to test beztriples */
541         if (fcu->bezt) {
542                 BezTriple *bezt;
543                 
544                 /* loop through all BezTriples, stopping when one exceeds the one after it */
545                 for (a=0, bezt= fcu->bezt; a < (fcu->totvert - 1); a++, bezt++) {
546                         if (bezt->vec[1][0] > (bezt+1)->vec[1][0])
547                                 return 1;
548                 }
549         }
550         else if (fcu->fpt) {
551                 FPoint *fpt;
552                 
553                 /* loop through all FPoints, stopping when one exceeds the one after it */
554                 for (a=0, fpt= fcu->fpt; a < (fcu->totvert - 1); a++, fpt++) {
555                         if (fpt->vec[0] > (fpt+1)->vec[0])
556                                 return 1;
557                 }
558         }
559         
560         /* none need any swapping */
561         return 0;
562 }
563
564 /* ***************************** Drivers ********************************* */
565
566 /* Driver API --------------------------------- */
567
568 /* This frees the driver target itself */
569 void driver_free_target (ChannelDriver *driver, DriverTarget *dtar)
570 {
571         /* sanity checks */
572         if (dtar == NULL)
573                 return;
574                 
575         /* free target vars */
576         if (dtar->rna_path)
577                 MEM_freeN(dtar->rna_path);
578         
579         /* remove the target from the driver */
580         if (driver)
581                 BLI_freelinkN(&driver->targets, dtar);
582         else
583                 MEM_freeN(dtar);
584 }
585
586 /* Add a new driver target variable */
587 DriverTarget *driver_add_new_target (ChannelDriver *driver)
588 {
589         DriverTarget *dtar;
590         
591         /* sanity checks */
592         if (driver == NULL)
593                 return NULL;
594                 
595         /* make a new target */
596         dtar= MEM_callocN(sizeof(DriverTarget), "DriverTarget");
597         BLI_addtail(&driver->targets, dtar);
598         
599         /* give the target a 'unique' name */
600         strcpy(dtar->name, "var");
601         BLI_uniquename(&driver->targets, dtar, "var", '_', offsetof(DriverTarget, name), 64);
602         
603         /* return the target */
604         return dtar;
605 }
606
607 /* This frees the driver itself */
608 void fcurve_free_driver(FCurve *fcu)
609 {
610         ChannelDriver *driver;
611         DriverTarget *dtar, *dtarn;
612         
613         /* sanity checks */
614         if ELEM(NULL, fcu, fcu->driver)
615                 return;
616         driver= fcu->driver;
617         
618         /* free driver targets */
619         for (dtar= driver->targets.first; dtar; dtar= dtarn) {
620                 dtarn= dtar->next;
621                 driver_free_target(driver, dtar);
622         }
623         
624         /* free driver itself, then set F-Curve's point to this to NULL (as the curve may still be used) */
625         MEM_freeN(driver);
626         fcu->driver= NULL;
627 }
628
629 /* This makes a copy of the given driver */
630 ChannelDriver *fcurve_copy_driver (ChannelDriver *driver)
631 {
632         ChannelDriver *ndriver;
633         DriverTarget *dtar;
634         
635         /* sanity checks */
636         if (driver == NULL)
637                 return NULL;
638                 
639         /* copy all data */
640         ndriver= MEM_dupallocN(driver);
641         
642         /* copy targets */
643         ndriver->targets.first= ndriver->targets.last= NULL;
644         BLI_duplicatelist(&ndriver->targets, &driver->targets);
645         
646         for (dtar= ndriver->targets.first; dtar; dtar= dtar->next) {
647                 /* make a copy of target's rna path if available */
648                 if (dtar->rna_path)
649                         dtar->rna_path = MEM_dupallocN(dtar->rna_path);
650         }
651         
652         /* return the new driver */
653         return ndriver;
654 }
655
656 /* Driver Evaluation -------------------------- */
657
658 /* Helper function to obtain a value using RNA from the specified source (for evaluating drivers) */
659 float driver_get_target_value (ChannelDriver *driver, DriverTarget *dtar)
660 {
661         PointerRNA id_ptr, ptr;
662         PropertyRNA *prop;
663         ID *id;
664         char *path;
665         int index;
666         float value= 0.0f;
667         
668         /* sanity check */
669         if ELEM(NULL, driver, dtar)
670                 return 0.0f;
671         
672         /* get RNA-pointer for the ID-block given in target */
673         RNA_id_pointer_create(dtar->id, &id_ptr);
674         id= dtar->id;
675         path= dtar->rna_path;
676         index= dtar->array_index;
677         
678         /* error check for missing pointer... */
679         if (id == NULL) {
680                 printf("Error: driver doesn't have any valid target to use \n");
681                 if (G.f & G_DEBUG) printf("\tpath = %s [%d] \n", path, index);
682                 driver->flag |= DRIVER_FLAG_INVALID;
683                 return 0.0f;
684         }
685         
686         /* get property to read from, and get value as appropriate */
687         if (RNA_path_resolve(&id_ptr, path, &ptr, &prop)) {
688                 switch (RNA_property_type(prop)) {
689                         case PROP_BOOLEAN:
690                                 if (RNA_property_array_length(prop))
691                                         value= (float)RNA_property_boolean_get_index(&ptr, prop, index);
692                                 else
693                                         value= (float)RNA_property_boolean_get(&ptr, prop);
694                                 break;
695                         case PROP_INT:
696                                 if (RNA_property_array_length(prop))
697                                         value= (float)RNA_property_int_get_index(&ptr, prop, index);
698                                 else
699                                         value= (float)RNA_property_int_get(&ptr, prop);
700                                 break;
701                         case PROP_FLOAT:
702                                 if (RNA_property_array_length(prop))
703                                         value= RNA_property_float_get_index(&ptr, prop, index);
704                                 else
705                                         value= RNA_property_float_get(&ptr, prop);
706                                 break;
707                         case PROP_ENUM:
708                                 value= (float)RNA_property_enum_get(&ptr, prop);
709                                 break;
710                         default:
711                                 break;
712                 }
713         }
714         
715         return value;
716 }
717
718 /* Get two PoseChannels from the targets of the given Driver */
719 static void driver_get_target_pchans2 (ChannelDriver *driver, bPoseChannel **pchan1, bPoseChannel **pchan2)
720 {
721         DriverTarget *dtar;
722         short i = 0;
723         
724         /* before doing anything */
725         *pchan1= NULL;
726         *pchan2= NULL;
727         
728         /* only take the first two targets */
729         for (dtar= driver->targets.first; (dtar) && (i < 2); dtar=dtar->next, i++) {
730                 PointerRNA id_ptr, ptr;
731                 PropertyRNA *prop;
732                 
733                 /* get RNA-pointer for the ID-block given in target */
734                 if (dtar->id)
735                         RNA_id_pointer_create(dtar->id, &id_ptr);
736                 else
737                         continue;
738                 
739                 /* resolve path so that we have pointer to the right posechannel */
740                 if (RNA_path_resolve(&id_ptr, dtar->rna_path, &ptr, &prop)) {
741                         /* is pointer valid (i.e. pointing to an actual posechannel */
742                         if ((ptr.type == &RNA_PoseChannel) && (ptr.data)) {
743                                 /* first or second target? */
744                                 if (i)
745                                         *pchan1= ptr.data;
746                                 else
747                                         *pchan2= ptr.data;
748                         }
749                 }
750         }
751 }
752
753 /* Evaluate an Channel-Driver to get a 'time' value to use instead of "evaltime"
754  *      - "evaltime" is the frame at which F-Curve is being evaluated
755  *      - has to return a float value 
756  */
757 static float evaluate_driver (ChannelDriver *driver, float evaltime)
758 {
759         DriverTarget *dtar;
760         
761         /* check if driver can be evaluated */
762         if (driver->flag & DRIVER_FLAG_INVALID)
763                 return 0.0f;
764         
765         // TODO: the flags for individual targets need to be used too for more fine-grained support...
766         switch (driver->type) {
767                 case DRIVER_TYPE_AVERAGE: /* average values of driver targets */
768                 {
769                         /* check how many targets there are first (i.e. just one?) */
770                         if (driver->targets.first == driver->targets.last) {
771                                 /* just one target, so just use that */
772                                 dtar= driver->targets.first;
773                                 return driver_get_target_value(driver, dtar);
774                         }
775                         else {
776                                 /* more than one target, so average the values of the targets */
777                                 int tot = 0;
778                                 float value = 0.0f;
779                                 
780                                 /* loop through targets, adding (hopefully we don't get any overflow!) */
781                                 for (dtar= driver->targets.first; dtar; dtar=dtar->next) {
782                                         value += driver_get_target_value(driver, dtar); 
783                                         tot++;
784                                 }
785                                 
786                                 /* return the average of these */
787                                 return (value / (float)tot);
788                         }
789                 }
790                         break;
791                 
792                 case DRIVER_TYPE_PYTHON: /* expression */
793                 {
794 #ifndef DISABLE_PYTHON
795                         /* check for empty or invalid expression */
796                         if ( (driver->expression[0] == '\0') ||
797                                  (driver->flag & DRIVER_FLAG_INVALID) )
798                         {
799                                 return 0.0f;
800                         }
801                         
802                         /* this evaluates the expression using Python,and returns its result:
803                          *      - on errors it reports, then returns 0.0f
804                          */
805                         return BPY_pydriver_eval(driver);
806 #endif /* DISABLE_PYTHON*/
807                 }
808                         break;
809
810                 
811                 case DRIVER_TYPE_ROTDIFF: /* difference of rotations of 2 bones (should ideally be in same armature) */
812                 {
813                         bPoseChannel *pchan, *pchan2;
814                         float q1[4], q2[4], quat[4], angle;
815                         
816                         /* get pose channels, and check if we've got two */
817                         driver_get_target_pchans2(driver, &pchan, &pchan2);
818                         if (ELEM(NULL, pchan, pchan2)) {
819                                 /* disable this driver, since it doesn't work correctly... */
820                                 driver->flag |= DRIVER_FLAG_INVALID;
821                                 
822                                 /* check what the error was */
823                                 if ((pchan == NULL) && (pchan2 == NULL))
824                                         printf("Driver Evaluation Error: Rotational difference failed - first 2 targets invalid \n");
825                                 else if (pchan == NULL)
826                                         printf("Driver Evaluation Error: Rotational difference failed - first target not valid PoseChannel \n");
827                                 else if (pchan2 == NULL)
828                                         printf("Driver Evaluation Error: Rotational difference failed - second target not valid PoseChannel \n");
829                                         
830                                 /* stop here... */
831                                 return 0.0f;
832                         }                       
833                         
834                         /* use the final posed locations */
835                         Mat4ToQuat(pchan->pose_mat, q1);
836                         Mat4ToQuat(pchan2->pose_mat, q2);
837                         
838                         QuatInv(q1);
839                         QuatMul(quat, q1, q2);
840                         angle = 2.0f * (saacos(quat[0]));
841                         angle= ABS(angle);
842                         
843                         return (angle > M_PI) ? (float)((2.0f * M_PI) - angle) : (float)(angle);
844                 }
845                         break;
846                 
847                 default:
848                 {
849                         /* special 'hack' - just use stored value 
850                          *      This is currently used as the mechanism which allows animated settings to be able
851                          *      to be changed via the UI.
852                          */
853                         return driver->curval;
854                 }
855         }
856         
857         /* return 0.0f, as couldn't find relevant data to use */
858         return 0.0f;
859 }
860
861 /* ***************************** Curve Calculations ********************************* */
862
863 /* The total length of the handles is not allowed to be more
864  * than the horizontal distance between (v1-v4).
865  * This is to prevent curve loops.
866 */
867 void correct_bezpart (float *v1, float *v2, float *v3, float *v4)
868 {
869         float h1[2], h2[2], len1, len2, len, fac;
870         
871         /* calculate handle deltas */
872         h1[0]= v1[0] - v2[0];
873         h1[1]= v1[1] - v2[1];
874         
875         h2[0]= v4[0] - v3[0];
876         h2[1]= v4[1] - v3[1];
877         
878         /* calculate distances: 
879          *      - len   = span of time between keyframes 
880          *      - len1  = length of handle of start key
881          *      - len2  = length of handle of end key
882          */
883         len= v4[0]- v1[0];
884         len1= (float)fabs(h1[0]);
885         len2= (float)fabs(h2[0]);
886         
887         /* if the handles have no length, no need to do any corrections */
888         if ((len1+len2) == 0.0f) 
889                 return;
890                 
891         /* the two handles cross over each other, so force them
892          * apart using the proportion they overlap 
893          */
894         if ((len1+len2) > len) {
895                 fac= len / (len1+len2);
896                 
897                 v2[0]= (v1[0] - fac*h1[0]);
898                 v2[1]= (v1[1] - fac*h1[1]);
899                 
900                 v3[0]= (v4[0] - fac*h2[0]);
901                 v3[1]= (v4[1] - fac*h2[1]);
902         }
903 }
904
905 /* find root ('zero') */
906 int findzero (float x, float q0, float q1, float q2, float q3, float *o)
907 {
908         double c0, c1, c2, c3, a, b, c, p, q, d, t, phi;
909         int nr= 0;
910
911         c0= q0 - x;
912         c1= 3.0 * (q1 - q0);
913         c2= 3.0 * (q0 - 2.0*q1 + q2);
914         c3= q3 - q0 + 3.0 * (q1 - q2);
915         
916         if (c3 != 0.0) {
917                 a= c2/c3;
918                 b= c1/c3;
919                 c= c0/c3;
920                 a= a/3;
921                 
922                 p= b/3 - a*a;
923                 q= (2*a*a*a - a*b + c) / 2;
924                 d= q*q + p*p*p;
925                 
926                 if (d > 0.0) {
927                         t= sqrt(d);
928                         o[0]= (float)(Sqrt3d(-q+t) + Sqrt3d(-q-t) - a);
929                         
930                         if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1;
931                         else return 0;
932                 }
933                 else if (d == 0.0) {
934                         t= Sqrt3d(-q);
935                         o[0]= (float)(2*t - a);
936                         
937                         if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++;
938                         o[nr]= (float)(-t-a);
939                         
940                         if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1;
941                         else return nr;
942                 }
943                 else {
944                         phi= acos(-q / sqrt(-(p*p*p)));
945                         t= sqrt(-p);
946                         p= cos(phi/3);
947                         q= sqrt(3 - 3*p*p);
948                         o[0]= (float)(2*t*p - a);
949                         
950                         if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++;
951                         o[nr]= (float)(-t * (p + q) - a);
952                         
953                         if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) nr++;
954                         o[nr]= (float)(-t * (p - q) - a);
955                         
956                         if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1;
957                         else return nr;
958                 }
959         }
960         else {
961                 a=c2;
962                 b=c1;
963                 c=c0;
964                 
965                 if (a != 0.0) {
966                         // discriminant
967                         p= b*b - 4*a*c;
968                         
969                         if (p > 0) {
970                                 p= sqrt(p);
971                                 o[0]= (float)((-b-p) / (2 * a));
972                                 
973                                 if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++;
974                                 o[nr]= (float)((-b+p)/(2*a));
975                                 
976                                 if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1;
977                                 else return nr;
978                         }
979                         else if (p == 0) {
980                                 o[0]= (float)(-b / (2 * a));
981                                 if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1;
982                                 else return 0;
983                         }
984                 }
985                 else if (b != 0.0) {
986                         o[0]= (float)(-c/b);
987                         
988                         if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1;
989                         else return 0;
990                 }
991                 else if (c == 0.0) {
992                         o[0]= 0.0;
993                         return 1;
994                 }
995                 
996                 return 0;       
997         }
998 }
999
1000 void berekeny (float f1, float f2, float f3, float f4, float *o, int b)
1001 {
1002         float t, c0, c1, c2, c3;
1003         int a;
1004
1005         c0= f1;
1006         c1= 3.0f * (f2 - f1);
1007         c2= 3.0f * (f1 - 2.0f*f2 + f3);
1008         c3= f4 - f1 + 3.0f * (f2 - f3);
1009         
1010         for (a=0; a < b; a++) {
1011                 t= o[a];
1012                 o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3;
1013         }
1014 }
1015
1016 void berekenx (float *f, float *o, int b)
1017 {
1018         float t, c0, c1, c2, c3;
1019         int a;
1020
1021         c0= f[0];
1022         c1= 3.0f * (f[3] - f[0]);
1023         c2= 3.0f * (f[0] - 2.0f*f[3] + f[6]);
1024         c3= f[9] - f[0] + 3.0f * (f[3] - f[6]);
1025         
1026         for (a=0; a < b; a++) {
1027                 t= o[a];
1028                 o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3;
1029         }
1030 }
1031
1032
1033 /* -------------------------- */
1034
1035 /* Calculate F-Curve value for 'evaltime' using BezTriple keyframes */
1036 static float fcurve_eval_keyframes (FCurve *fcu, BezTriple *bezts, float evaltime)
1037 {
1038         BezTriple *bezt, *prevbezt, *lastbezt;
1039         float v1[2], v2[2], v3[2], v4[2], opl[32], dx, fac;
1040         unsigned int a;
1041         int b;
1042         float cvalue = 0.0f;
1043         
1044         /* get pointers */
1045         a= fcu->totvert-1;
1046         prevbezt= bezts;
1047         bezt= prevbezt+1;
1048         lastbezt= prevbezt + a;
1049         
1050         /* evaluation time at or past endpoints? */
1051         if (prevbezt->vec[1][0] >= evaltime) 
1052         {
1053                 /* before or on first keyframe */
1054                 if ( (fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (prevbezt->ipo != BEZT_IPO_CONST) &&
1055                         !(fcu->flag & FCURVE_DISCRETE_VALUES) ) 
1056                 {
1057                         /* linear or bezier interpolation */
1058                         if (prevbezt->ipo==BEZT_IPO_LIN) 
1059                         {
1060                                 /* Use the next center point instead of our own handle for
1061                                  * linear interpolated extrapolate 
1062                                  */
1063                                 if (fcu->totvert == 1) 
1064                                         cvalue= prevbezt->vec[1][1];
1065                                 else 
1066                                 {
1067                                         bezt = prevbezt+1;
1068                                         dx= prevbezt->vec[1][0] - evaltime;
1069                                         fac= bezt->vec[1][0] - prevbezt->vec[1][0];
1070                                         
1071                                         /* prevent division by zero */
1072                                         if (fac) {
1073                                                 fac= (bezt->vec[1][1] - prevbezt->vec[1][1]) / fac;
1074                                                 cvalue= prevbezt->vec[1][1] - (fac * dx);
1075                                         }
1076                                         else 
1077                                                 cvalue= prevbezt->vec[1][1];
1078                                 }
1079                         } 
1080                         else 
1081                         {
1082                                 /* Use the first handle (earlier) of first BezTriple to calculate the
1083                                  * gradient and thus the value of the curve at evaltime
1084                                  */
1085                                 dx= prevbezt->vec[1][0] - evaltime;
1086                                 fac= prevbezt->vec[1][0] - prevbezt->vec[0][0];
1087                                 
1088                                 /* prevent division by zero */
1089                                 if (fac) {
1090                                         fac= (prevbezt->vec[1][1] - prevbezt->vec[0][1]) / fac;
1091                                         cvalue= prevbezt->vec[1][1] - (fac * dx);
1092                                 }
1093                                 else 
1094                                         cvalue= prevbezt->vec[1][1];
1095                         }
1096                 }
1097                 else 
1098                 {
1099                         /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, 
1100                          * so just extend first keyframe's value 
1101                          */
1102                         cvalue= prevbezt->vec[1][1];
1103                 }
1104         }
1105         else if (lastbezt->vec[1][0] <= evaltime) 
1106         {
1107                 /* after or on last keyframe */
1108                 if ( (fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (lastbezt->ipo != BEZT_IPO_CONST) &&
1109                         !(fcu->flag & FCURVE_DISCRETE_VALUES) ) 
1110                 {
1111                         /* linear or bezier interpolation */
1112                         if (lastbezt->ipo==BEZT_IPO_LIN) 
1113                         {
1114                                 /* Use the next center point instead of our own handle for
1115                                  * linear interpolated extrapolate 
1116                                  */
1117                                 if (fcu->totvert == 1) 
1118                                         cvalue= lastbezt->vec[1][1];
1119                                 else 
1120                                 {
1121                                         prevbezt = lastbezt - 1;
1122                                         dx= evaltime - lastbezt->vec[1][0];
1123                                         fac= lastbezt->vec[1][0] - prevbezt->vec[1][0];
1124                                         
1125                                         /* prevent division by zero */
1126                                         if (fac) {
1127                                                 fac= (lastbezt->vec[1][1] - prevbezt->vec[1][1]) / fac;
1128                                                 cvalue= lastbezt->vec[1][1] + (fac * dx);
1129                                         }
1130                                         else 
1131                                                 cvalue= lastbezt->vec[1][1];
1132                                 }
1133                         } 
1134                         else 
1135                         {
1136                                 /* Use the gradient of the second handle (later) of last BezTriple to calculate the
1137                                  * gradient and thus the value of the curve at evaltime
1138                                  */
1139                                 dx= evaltime - lastbezt->vec[1][0];
1140                                 fac= lastbezt->vec[2][0] - lastbezt->vec[1][0];
1141                                 
1142                                 /* prevent division by zero */
1143                                 if (fac) {
1144                                         fac= (lastbezt->vec[2][1] - lastbezt->vec[1][1]) / fac;
1145                                         cvalue= lastbezt->vec[1][1] + (fac * dx);
1146                                 }
1147                                 else 
1148                                         cvalue= lastbezt->vec[1][1];
1149                         }
1150                 }
1151                 else 
1152                 {
1153                         /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, 
1154                          * so just extend last keyframe's value 
1155                          */
1156                         cvalue= lastbezt->vec[1][1];
1157                 }
1158         }
1159         else 
1160         {
1161                 /* evaltime occurs somewhere in the middle of the curve */
1162                 for (a=0; prevbezt && bezt && (a < fcu->totvert-1); a++, prevbezt=bezt, bezt++) 
1163                 {  
1164                         /* evaltime occurs within the interval defined by these two keyframes */
1165                         if ((prevbezt->vec[1][0] <= evaltime) && (bezt->vec[1][0] >= evaltime)) 
1166                         {
1167                                 /* value depends on interpolation mode */
1168                                 if ((prevbezt->ipo == BEZT_IPO_CONST) || (fcu->flag & FCURVE_DISCRETE_VALUES))
1169                                 {
1170                                         /* constant (evaltime not relevant, so no interpolation needed) */
1171                                         cvalue= prevbezt->vec[1][1];
1172                                 }
1173                                 else if (prevbezt->ipo == BEZT_IPO_LIN) 
1174                                 {
1175                                         /* linear - interpolate between values of the two keyframes */
1176                                         fac= bezt->vec[1][0] - prevbezt->vec[1][0];
1177                                         
1178                                         /* prevent division by zero */
1179                                         if (fac) {
1180                                                 fac= (evaltime - prevbezt->vec[1][0]) / fac;
1181                                                 cvalue= prevbezt->vec[1][1] + (fac * (bezt->vec[1][1] - prevbezt->vec[1][1]));
1182                                         }
1183                                         else
1184                                                 cvalue= prevbezt->vec[1][1];
1185                                 }
1186                                 else 
1187                                 {
1188                                         /* bezier interpolation */
1189                                                 /* v1,v2 are the first keyframe and its 2nd handle */
1190                                         v1[0]= prevbezt->vec[1][0];
1191                                         v1[1]= prevbezt->vec[1][1];
1192                                         v2[0]= prevbezt->vec[2][0];
1193                                         v2[1]= prevbezt->vec[2][1];
1194                                                 /* v3,v4 are the last keyframe's 1st handle + the last keyframe */
1195                                         v3[0]= bezt->vec[0][0];
1196                                         v3[1]= bezt->vec[0][1];
1197                                         v4[0]= bezt->vec[1][0];
1198                                         v4[1]= bezt->vec[1][1];
1199                                         
1200                                         /* adjust handles so that they don't overlap (forming a loop) */
1201                                         correct_bezpart(v1, v2, v3, v4);
1202                                         
1203                                         /* try to get a value for this position - if failure, try another set of points */
1204                                         b= findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl);
1205                                         if (b) {
1206                                                 berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1);
1207                                                 cvalue= opl[0];
1208                                                 break;
1209                                         }
1210                                 }
1211                         }
1212                 }
1213         }
1214         
1215         /* return value */
1216         return cvalue;
1217 }
1218
1219 /* Calculate F-Curve value for 'evaltime' using FPoint samples */
1220 static float fcurve_eval_samples (FCurve *fcu, FPoint *fpts, float evaltime)
1221 {
1222         FPoint *prevfpt, *lastfpt, *fpt;
1223         float cvalue= 0.0f;
1224         
1225         /* get pointers */
1226         prevfpt= fpts;
1227         lastfpt= prevfpt + fcu->totvert-1;
1228         
1229         /* evaluation time at or past endpoints? */
1230         if (prevfpt->vec[0] >= evaltime) {
1231                 /* before or on first sample, so just extend value */
1232                 cvalue= prevfpt->vec[1];
1233         }
1234         else if (lastfpt->vec[0] <= evaltime) {
1235                 /* after or on last sample, so just extend value */
1236                 cvalue= lastfpt->vec[1];
1237         }
1238         else {
1239                 /* find the one on the right frame (assume that these are spaced on 1-frame intervals) */
1240                 fpt= prevfpt + (int)(evaltime - prevfpt->vec[0]);
1241                 cvalue= fpt->vec[1];
1242         }
1243         
1244         /* return value */
1245         return cvalue;
1246 }
1247
1248 /* ******************************** F-Curve Modifiers ********************************* */
1249
1250 /* Template --------------------------- */
1251
1252 /* Each modifier defines a set of functions, which will be called at the appropriate
1253  * times. In addition to this, each modifier should have a type-info struct, where
1254  * its functions are attached for use. 
1255  */
1256  
1257 /* Template for type-info data:
1258  *      - make a copy of this when creating new modifiers, and just change the functions
1259  *        pointed to as necessary
1260  *      - although the naming of functions doesn't matter, it would help for code
1261  *        readability, to follow the same naming convention as is presented here
1262  *      - any functions that a constraint doesn't need to define, don't define
1263  *        for such cases, just use NULL 
1264  *      - these should be defined after all the functions have been defined, so that
1265  *        forward-definitions/prototypes don't need to be used!
1266  *      - keep this copy #if-def'd so that future constraints can get based off this
1267  */
1268 #if 0
1269 static FModifierTypeInfo FMI_MODNAME = {
1270         FMODIFIER_TYPE_MODNAME, /* type */
1271         sizeof(FMod_ModName), /* size */
1272         FMI_TYPE_SOME_ACTION, /* action type */
1273         FMI_REQUIRES_SOME_REQUIREMENT, /* requirements */
1274         "Modifier Name", /* name */
1275         "FMod_ModName", /* struct name */
1276         fcm_modname_free, /* free data */
1277         fcm_modname_relink, /* relink data */
1278         fcm_modname_copy, /* copy data */
1279         fcm_modname_new_data, /* new data */
1280         fcm_modname_verify, /* verify */
1281         fcm_modname_time, /* evaluate time */
1282         fcm_modname_evaluate /* evaluate */
1283 };
1284 #endif
1285
1286 /* Generator F-Curve Modifier --------------------------- */
1287
1288 /* Generators available:
1289  *      1) simple polynomial generator:
1290  *              - Exanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n])  
1291  *              - Factorised form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1]))
1292  *      2) simple builin 'functions':
1293  *              of the form (y = C[0] * fn( C[1]*x + C[2] ) + C[3])
1294  *         where fn() can be any one of:
1295  *              sin, cos, tan, ln, sqrt
1296  *      3) expression...
1297  */
1298
1299 static void fcm_generator_free (FModifier *fcm)
1300 {
1301         FMod_Generator *data= (FMod_Generator *)fcm->data;
1302         
1303         /* free polynomial coefficients array */
1304         if (data->coefficients)
1305                 MEM_freeN(data->coefficients);
1306 }
1307
1308 static void fcm_generator_copy (FModifier *fcm, FModifier *src)
1309 {
1310         FMod_Generator *gen= (FMod_Generator *)fcm->data;
1311         FMod_Generator *ogen= (FMod_Generator *)src->data;
1312         
1313         /* copy coefficients array? */
1314         if (ogen->coefficients)
1315                 gen->coefficients= MEM_dupallocN(ogen->coefficients);
1316 }
1317
1318 static void fcm_generator_new_data (void *mdata)
1319 {
1320         FMod_Generator *data= (FMod_Generator *)mdata;
1321         float *cp;
1322         
1323         /* set default generator to be linear 0-1 (gradient = 1, y-offset = 0) */
1324         data->poly_order= 1;
1325         data->arraysize= 2;
1326         cp= data->coefficients= MEM_callocN(sizeof(float)*2, "FMod_Generator_Coefs");
1327         cp[0] = 0; // y-offset 
1328         cp[1] = 1; // gradient
1329 }
1330
1331 static void fcm_generator_verify (FModifier *fcm)
1332 {
1333         FMod_Generator *data= (FMod_Generator *)fcm->data;
1334         
1335         /* requirements depend on mode */
1336         switch (data->mode) {
1337                 case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
1338                 {
1339                         /* arraysize needs to be order+1, so resize if not */
1340                         if (data->arraysize != (data->poly_order+1)) {
1341                                 float *nc;
1342                                 
1343                                 /* make new coefficients array, and copy over as much data as can fit */
1344                                 nc= MEM_callocN(sizeof(float)*(data->poly_order+1), "FMod_Generator_Coefs");
1345                                 
1346                                 if (data->coefficients) {
1347                                         if (data->arraysize > (data->poly_order+1))
1348                                                 memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order+1));
1349                                         else
1350                                                 memcpy(nc, data->coefficients, sizeof(float)*data->arraysize);
1351                                                 
1352                                         /* free the old data */
1353                                         MEM_freeN(data->coefficients);
1354                                 }       
1355                                 
1356                                 /* set the new data */
1357                                 data->coefficients= nc;
1358                                 data->arraysize= data->poly_order+1;
1359                         }
1360                 }
1361                         break;
1362                 
1363                 case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* expanded polynomial expression */
1364                 {
1365                         /* arraysize needs to be 2*order, so resize if not */
1366                         if (data->arraysize != (data->poly_order * 2)) {
1367                                 float *nc;
1368                                 
1369                                 /* make new coefficients array, and copy over as much data as can fit */
1370                                 nc= MEM_callocN(sizeof(float)*(data->poly_order*2), "FMod_Generator_Coefs");
1371                                 
1372                                 if (data->coefficients) {
1373                                         if (data->arraysize > (data->poly_order * 2))
1374                                                 memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order * 2));
1375                                         else
1376                                                 memcpy(nc, data->coefficients, sizeof(float)*data->arraysize);
1377                                                 
1378                                         /* free the old data */
1379                                         MEM_freeN(data->coefficients);
1380                                 }       
1381                                 
1382                                 /* set the new data */
1383                                 data->coefficients= nc;
1384                                 data->arraysize= data->poly_order * 2;
1385                         }
1386                 }
1387                         break;
1388                         
1389                 case FCM_GENERATOR_FUNCTION: /* builtin function */
1390                 {
1391                         /* arraysize needs to be 4*/
1392                         if (data->arraysize != 4) {
1393                                 float *nc;
1394                                 
1395                                 /* free the old data */
1396                                 if (data->coefficients)
1397                                         MEM_freeN(data->coefficients);
1398                                 
1399                                 /* make new coefficients array, and init using default values */
1400                                 nc= data->coefficients= MEM_callocN(sizeof(float)*4, "FMod_Generator_Coefs");
1401                                 data->arraysize= 4;
1402                                 
1403                                 nc[0]= 1.0f;
1404                                 nc[1]= 1.0f;
1405                                 nc[2]= 0.0f;
1406                                 nc[3]= 0.0f;
1407                         }
1408                 }
1409                         break;  
1410         }
1411 }
1412
1413 static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
1414 {
1415         FMod_Generator *data= (FMod_Generator *)fcm->data;
1416         
1417         /* behaviour depends on mode 
1418          * NOTE: the data in its default state is fine too
1419          */
1420         switch (data->mode) {
1421                 case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
1422                 {
1423                         /* we overwrite cvalue with the sum of the polynomial */
1424                         float *powers = MEM_callocN(sizeof(float)*data->arraysize, "Poly Powers");
1425                         float value= 0.0f;
1426                         unsigned int i;
1427                         
1428                         /* for each x^n, precalculate value based on previous one first... this should be 
1429                          * faster that calling pow() for each entry
1430                          */
1431                         for (i=0; i < data->arraysize; i++) {
1432                                 /* first entry is x^0 = 1, otherwise, calculate based on previous */
1433                                 if (i)
1434                                         powers[i]= powers[i-1] * evaltime;
1435                                 else
1436                                         powers[0]= 1;
1437                         }
1438                         
1439                         /* for each coefficient, add to value, which we'll write to *cvalue in one go */
1440                         for (i=0; i < data->arraysize; i++)
1441                                 value += data->coefficients[i] * powers[i];
1442                         
1443                         /* only if something changed, write *cvalue in one go */
1444                         if (data->poly_order) {
1445                                 if (data->flag & FCM_GENERATOR_ADDITIVE)
1446                                         *cvalue += value;
1447                                 else
1448                                         *cvalue= value;
1449                         }
1450                                 
1451                         /* cleanup */
1452                         if (powers) 
1453                                 MEM_freeN(powers);
1454                 }
1455                         break;
1456                         
1457                 case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */
1458                 {
1459                         float value= 1.0f, *cp=NULL;
1460                         unsigned int i;
1461                         
1462                         /* for each coefficient pair, solve for that bracket before accumulating in value by multiplying */
1463                         for (cp=data->coefficients, i=0; (cp) && (i < data->poly_order); cp+=2, i++) 
1464                                 value *= (cp[0]*evaltime + cp[1]);
1465                                 
1466                         /* only if something changed, write *cvalue in one go */
1467                         if (data->poly_order) {
1468                                 if (data->flag & FCM_GENERATOR_ADDITIVE)
1469                                         *cvalue += value;
1470                                 else
1471                                         *cvalue= value;
1472                         }
1473                 }
1474                         break;
1475                         
1476                 case FCM_GENERATOR_FUNCTION: /* builtin function */
1477                 {
1478                         double arg= data->coefficients[1]*evaltime + data->coefficients[2];
1479                         double (*fn)(double v) = NULL;
1480                         
1481                         /* get function pointer to the func to use:
1482                          * WARNING: must perform special argument validation hereto guard against crashes  
1483                          */
1484                         switch (data->func_type)
1485                         {
1486                                 /* simple ones */                       
1487                                 case FCM_GENERATOR_FN_SIN: /* sine wave */
1488                                         fn= sin;
1489                                         break;
1490                                 case FCM_GENERATOR_FN_COS: /* cosine wave */
1491                                         fn= cos;
1492                                         break;
1493                                         
1494                                 /* validation required */
1495                                 case FCM_GENERATOR_FN_TAN: /* tangent wave */
1496                                 {
1497                                         /* check that argument is not on one of the discontinuities (i.e. 90deg, 270 deg, etc) */
1498                                         if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) {
1499                                                 if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
1500                                                         *cvalue = 0.0f; /* no value possible here */
1501                                         }
1502                                         else
1503                                                 fn= tan;
1504                                 }
1505                                         break;
1506                                 case FCM_GENERATOR_FN_LN: /* natural log */
1507                                 {
1508                                         /* check that value is greater than 1? */
1509                                         if (arg > 1.0f) {
1510                                                 fn= log;
1511                                         }
1512                                         else {
1513                                                 if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
1514                                                         *cvalue = 0.0f; /* no value possible here */
1515                                         }
1516                                 }
1517                                         break;
1518                                 case FCM_GENERATOR_FN_SQRT: /* square root */
1519                                 {
1520                                         /* no negative numbers */
1521                                         if (arg > 0.0f) {
1522                                                 fn= sqrt;
1523                                         }
1524                                         else {
1525                                                 if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
1526                                                         *cvalue = 0.0f; /* no value possible here */
1527                                         }
1528                                 }
1529                                         break;
1530                                         
1531                                 default:
1532                                         printf("Invalid Function-Generator for F-Modifier - %d \n", data->func_type);
1533                         }
1534                         
1535                         /* execute function callback to set value if appropriate */
1536                         if (fn) {
1537                                 float value= (float)(data->coefficients[0]*fn(arg) + data->coefficients[3]);
1538                                 
1539                                 if (data->flag & FCM_GENERATOR_ADDITIVE)
1540                                         *cvalue += value;
1541                                 else
1542                                         *cvalue= value;
1543                         }
1544                 }
1545                         break;
1546
1547 #ifndef DISABLE_PYTHON
1548                 case FCM_GENERATOR_EXPRESSION: /* py-expression */
1549                         // TODO...
1550                         break;
1551 #endif /* DISABLE_PYTHON */
1552         }
1553 }
1554
1555 static FModifierTypeInfo FMI_GENERATOR = {
1556         FMODIFIER_TYPE_GENERATOR, /* type */
1557         sizeof(FMod_Generator), /* size */
1558         FMI_TYPE_GENERATE_CURVE, /* action type */
1559         FMI_REQUIRES_NOTHING, /* requirements */
1560         "Generator", /* name */
1561         "FMod_Generator", /* struct name */
1562         fcm_generator_free, /* free data */
1563         fcm_generator_copy, /* copy data */
1564         fcm_generator_new_data, /* new data */
1565         fcm_generator_verify, /* verify */
1566         NULL, /* evaluate time */
1567         fcm_generator_evaluate /* evaluate */
1568 };
1569
1570 /* Envelope F-Curve Modifier --------------------------- */
1571
1572 static void fcm_envelope_free (FModifier *fcm)
1573 {
1574         FMod_Envelope *env= (FMod_Envelope *)fcm->data;
1575         
1576         /* free envelope data array */
1577         if (env->data)
1578                 MEM_freeN(env->data);
1579 }
1580
1581 static void fcm_envelope_copy (FModifier *fcm, FModifier *src)
1582 {
1583         FMod_Envelope *env= (FMod_Envelope *)fcm->data;
1584         FMod_Envelope *oenv= (FMod_Envelope *)src->data;
1585         
1586         /* copy envelope data array */
1587         if (oenv->data)
1588                 env->data= MEM_dupallocN(oenv->data);
1589 }
1590
1591 static void fcm_envelope_new_data (void *mdata)
1592 {
1593         FMod_Envelope *env= (FMod_Envelope *)mdata;
1594         
1595         /* set default min/max ranges */
1596         env->min= -1.0f;
1597         env->max= 1.0f;
1598 }
1599
1600 static void fcm_envelope_verify (FModifier *fcm)
1601 {
1602         FMod_Envelope *env= (FMod_Envelope *)fcm->data;
1603         
1604         /* if the are points, perform bubble-sort on them, as user may have changed the order */
1605         if (env->data) {
1606                 // XXX todo...
1607         }
1608 }
1609
1610 static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
1611 {
1612         FMod_Envelope *env= (FMod_Envelope *)fcm->data;
1613         FCM_EnvelopeData *fed, *prevfed, *lastfed;
1614         float min=0.0f, max=0.0f, fac=0.0f;
1615         int a;
1616         
1617         /* get pointers */
1618         if (env->data == NULL) return;
1619         prevfed= env->data;
1620         fed= prevfed + 1;
1621         lastfed= prevfed + (env->totvert-1);
1622         
1623         /* get min/max values for envelope at evaluation time (relative to mid-value) */
1624         if (prevfed->time >= evaltime) {
1625                 /* before or on first sample, so just extend value */
1626                 min= prevfed->min;
1627                 max= prevfed->max;
1628         }
1629         else if (lastfed->time <= evaltime) {
1630                 /* after or on last sample, so just extend value */
1631                 min= lastfed->min;
1632                 max= lastfed->max;
1633         }
1634         else {
1635                 /* evaltime occurs somewhere between segments */
1636                 // TODO: implement binary search for this to make it faster?
1637                 for (a=0; prevfed && fed && (a < env->totvert-1); a++, prevfed=fed, fed++) {  
1638                         /* evaltime occurs within the interval defined by these two envelope points */
1639                         if ((prevfed->time <= evaltime) && (fed->time >= evaltime)) {
1640                                 float afac, bfac, diff;
1641                                 
1642                                 diff= fed->time - prevfed->time;
1643                                 afac= (evaltime - prevfed->time) / diff;
1644                                 bfac= (fed->time - evaltime) / diff;
1645                                 
1646                                 min= bfac*prevfed->min + afac*fed->min;
1647                                 max= bfac*prevfed->max + afac*fed->max;
1648                                 
1649                                 break;
1650                         }
1651                 }
1652         }
1653         
1654         /* adjust *cvalue 
1655          *      - fac is the ratio of how the current y-value corresponds to the reference range
1656          *      - thus, the new value is found by mapping the old range to the new!
1657          */
1658         fac= (*cvalue - (env->midval + env->min)) / (env->max - env->min);
1659         *cvalue= min + fac*(max - min); 
1660 }
1661
1662 static FModifierTypeInfo FMI_ENVELOPE = {
1663         FMODIFIER_TYPE_ENVELOPE, /* type */
1664         sizeof(FMod_Envelope), /* size */
1665         FMI_TYPE_REPLACE_VALUES, /* action type */
1666         0, /* requirements */
1667         "Envelope", /* name */
1668         "FMod_Envelope", /* struct name */
1669         fcm_envelope_free, /* free data */
1670         fcm_envelope_copy, /* copy data */
1671         fcm_envelope_new_data, /* new data */
1672         fcm_envelope_verify, /* verify */
1673         NULL, /* evaluate time */
1674         fcm_envelope_evaluate /* evaluate */
1675 };
1676
1677 /* Cycles F-Curve Modifier  --------------------------- */
1678
1679 /* This modifier changes evaltime to something that exists within the curve's frame-range, 
1680  * then re-evaluates modifier stack up to this point using the new time. This re-entrant behaviour
1681  * is very likely to be more time-consuming than the original approach... (which was tighly integrated into 
1682  * the calculation code...).
1683  *
1684  * NOTE: this needs to be at the start of the stack to be of use, as it needs to know the extents of the keyframes/sample-data
1685  * Possible TODO - store length of cycle information that can be initialised from the extents of the keyframes/sample-data, and adjusted
1686  *                              as appropriate
1687  */
1688
1689 /* temp data used during evaluation */
1690 typedef struct tFCMED_Cycles {
1691         float cycyofs;          /* y-offset to apply */
1692 } tFCMED_Cycles;
1693  
1694 static void fcm_cycles_new_data (void *mdata)
1695 {
1696         FMod_Cycles *data= (FMod_Cycles *)mdata;
1697         
1698         /* turn on cycles by default */
1699         data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC;
1700 }
1701
1702 static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
1703 {
1704         FMod_Cycles *data= (FMod_Cycles *)fcm->data;
1705         float prevkey[2], lastkey[2], cycyofs=0.0f;
1706         short side=0, mode=0;
1707         int cycles=0;
1708         
1709         /* check if modifier is first in stack, otherwise disable ourself... */
1710         // FIXME...
1711         if (fcm->prev) {
1712                 fcm->flag |= FMODIFIER_FLAG_DISABLED;
1713                 return evaltime;
1714         }
1715         
1716         /* calculate new evaltime due to cyclic interpolation */
1717         if (fcu && fcu->bezt) {
1718                 BezTriple *prevbezt= fcu->bezt;
1719                 BezTriple *lastbezt= prevbezt + fcu->totvert-1;
1720                 
1721                 prevkey[0]= prevbezt->vec[1][0];
1722                 prevkey[1]= prevbezt->vec[1][1];
1723                 
1724                 lastkey[0]= lastbezt->vec[1][0];
1725                 lastkey[1]= lastbezt->vec[1][1];
1726         }
1727         else if (fcu && fcu->fpt) {
1728                 FPoint *prevfpt= fcu->fpt;
1729                 FPoint *lastfpt= prevfpt + fcu->totvert-1;
1730                 
1731                 prevkey[0]= prevfpt->vec[0];
1732                 prevkey[1]= prevfpt->vec[1];
1733                 
1734                 lastkey[0]= lastfpt->vec[0];
1735                 lastkey[1]= lastfpt->vec[1];
1736         }
1737         else
1738                 return evaltime;
1739                 
1740         /* check if modifier will do anything
1741          *      1) if in data range, definitely don't do anything
1742          *      2) if before first frame or after last frame, make sure some cycling is in use
1743          */
1744         if (evaltime < prevkey[0]) {
1745                 if (data->before_mode)  {
1746                         side= -1;
1747                         mode= data->before_mode;
1748                         cycles= data->before_cycles;
1749                 }
1750         }
1751         else if (evaltime > lastkey[0]) {
1752                 if (data->after_mode) {
1753                         side= 1;
1754                         mode= data->after_mode;
1755                         cycles= data->after_cycles;
1756                 }
1757         }
1758         if ELEM(0, side, mode)
1759                 return evaltime;
1760                 
1761         /* find relative place within a cycle */
1762         {
1763                 float cycdx=0, cycdy=0, ofs=0;
1764                 float cycle= 0;
1765                 
1766                 /* ofs is start frame of cycle */
1767                 ofs= prevkey[0];
1768                 
1769                 /* calculate period and amplitude (total height) of a cycle */
1770                 cycdx= lastkey[0] - prevkey[0];
1771                 cycdy= lastkey[1] - prevkey[1];
1772                 
1773                 /* check if cycle is infinitely small, to be point of being impossible to use */
1774                 if (cycdx == 0)
1775                         return evaltime;
1776                         
1777                 /* calculate the 'number' of the cycle */
1778                 cycle= ((float)side * (evaltime - ofs) / cycdx);
1779                 
1780                 /* check that cyclic is still enabled for the specified time */
1781                 if (cycles == 0) {
1782                         /* catch this case so that we don't exit when we have cycles=0
1783                          * as this indicates infinite cycles...
1784                          */
1785                 }
1786                 else if (cycle > (cycles+1)) {
1787                         /* we are too far away from range to evaluate
1788                          * TODO: but we should still hold last value... 
1789                          */
1790                         return evaltime;
1791                 }
1792                 
1793                 /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */
1794                 if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
1795                         cycyofs = (float)floor((evaltime - ofs) / cycdx);
1796                         cycyofs *= cycdy;
1797                 }
1798                 
1799                 /* calculate where in the cycle we are (overwrite evaltime to reflect this) */
1800                 if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle) % 2)) {
1801                         /* when 'mirror' option is used and cycle number is odd, this cycle is played in reverse 
1802                          *      - for 'before' extrapolation, we need to flip in a different way, otherwise values past
1803                          *        then end of the curve get referenced (result of fmod will be negative, and with different phase)
1804                          */
1805                         if (side < 0)
1806                                 evaltime= (float)(prevkey[0] - fmod(evaltime-ofs, cycdx));
1807                         else
1808                                 evaltime= (float)(lastkey[0] - fmod(evaltime-ofs, cycdx));
1809                 }
1810                 else {
1811                         /* the cycle is played normally... */
1812                         evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs);
1813                 }
1814                 if (evaltime < ofs) evaltime += cycdx;
1815         }
1816         
1817         /* store temp data if needed */
1818         if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
1819                 tFCMED_Cycles *edata;
1820                 
1821                 /* for now, this is just a float, but we could get more stuff... */
1822                 fcm->edata= edata= MEM_callocN(sizeof(tFCMED_Cycles), "tFCMED_Cycles");
1823                 edata->cycyofs= cycyofs;
1824         }
1825         
1826         /* return the new frame to evaluate */
1827         return evaltime;
1828 }
1829  
1830 static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
1831 {
1832         tFCMED_Cycles *edata= (tFCMED_Cycles *)fcm->edata;
1833         
1834         /* use temp data */
1835         if (edata) {
1836                 /* add cyclic offset - no need to check for now, otherwise the data wouldn't exist! */
1837                 *cvalue += edata->cycyofs;
1838                 
1839                 /* free temp data */
1840                 MEM_freeN(edata);
1841                 fcm->edata= NULL;
1842         }
1843 }
1844
1845 static FModifierTypeInfo FMI_CYCLES = {
1846         FMODIFIER_TYPE_CYCLES, /* type */
1847         sizeof(FMod_Cycles), /* size */
1848         FMI_TYPE_EXTRAPOLATION, /* action type */
1849         FMI_REQUIRES_ORIGINAL_DATA, /* requirements */
1850         "Cycles", /* name */
1851         "FMod_Cycles", /* struct name */
1852         NULL, /* free data */
1853         NULL, /* copy data */
1854         fcm_cycles_new_data, /* new data */
1855         NULL /*fcm_cycles_verify*/, /* verify */
1856         fcm_cycles_time, /* evaluate time */
1857         fcm_cycles_evaluate /* evaluate */
1858 };
1859
1860 /* Noise F-Curve Modifier  --------------------------- */
1861
1862 static void fcm_noise_new_data (void *mdata)
1863 {
1864         FMod_Noise *data= (FMod_Noise *)mdata;
1865         
1866         /* defaults */
1867         data->size= 1.0f;
1868         data->strength= 1.0f;
1869         data->phase= 1.0f;
1870         data->depth = 0;
1871         data->modification = FCM_NOISE_MODIF_REPLACE;
1872 }
1873  
1874 static void fcm_noise_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
1875 {
1876         FMod_Noise *data= (FMod_Noise *)fcm->data;
1877         float noise;
1878         
1879         noise = BLI_turbulence(data->size, evaltime, data->phase, 0.f, data->depth);
1880         
1881         switch (data->modification) {
1882                 case FCM_NOISE_MODIF_ADD:
1883                         *cvalue= *cvalue + noise * data->strength;
1884                         break;
1885                 case FCM_NOISE_MODIF_SUBTRACT:
1886                         *cvalue= *cvalue - noise * data->strength;
1887                         break;
1888                 case FCM_NOISE_MODIF_MULTIPLY:
1889                         *cvalue= *cvalue * noise * data->strength;
1890                         break;
1891                 case FCM_NOISE_MODIF_REPLACE:
1892                 default:
1893                         *cvalue= *cvalue + (noise - 0.5f) * data->strength;
1894                         break;
1895         }
1896 }
1897
1898 static FModifierTypeInfo FMI_NOISE = {
1899         FMODIFIER_TYPE_NOISE, /* type */
1900         sizeof(FMod_Noise), /* size */
1901         FMI_TYPE_REPLACE_VALUES, /* action type */
1902         0, /* requirements */
1903         "Noise", /* name */
1904         "FMod_Noise", /* struct name */
1905         NULL, /* free data */
1906         NULL, /* copy data */
1907         fcm_noise_new_data, /* new data */
1908         NULL /*fcm_noise_verify*/, /* verify */
1909         NULL, /* evaluate time */
1910         fcm_noise_evaluate /* evaluate */
1911 };
1912
1913 /* Filter F-Curve Modifier --------------------------- */
1914
1915 #if 0 // XXX not yet implemented 
1916 static FModifierTypeInfo FMI_FILTER = {
1917         FMODIFIER_TYPE_FILTER, /* type */
1918         sizeof(FMod_Filter), /* size */
1919         FMI_TYPE_REPLACE_VALUES, /* action type */
1920         0, /* requirements */
1921         "Filter", /* name */
1922         "FMod_Filter", /* struct name */
1923         NULL, /* free data */
1924         NULL, /* copy data */
1925         NULL, /* new data */
1926         NULL /*fcm_filter_verify*/, /* verify */
1927         NULL, /* evlauate time */
1928         fcm_filter_evaluate /* evaluate */
1929 };
1930 #endif // XXX not yet implemented
1931
1932
1933 /* Python F-Curve Modifier --------------------------- */
1934
1935 static void fcm_python_free (FModifier *fcm)
1936 {
1937         FMod_Python *data= (FMod_Python *)fcm->data;
1938         
1939         /* id-properties */
1940         IDP_FreeProperty(data->prop);
1941         MEM_freeN(data->prop);
1942 }
1943
1944 static void fcm_python_new_data (void *mdata) 
1945 {
1946         FMod_Python *data= (FMod_Python *)mdata;
1947         
1948         /* everything should be set correctly by calloc, except for the prop->type constant.*/
1949         data->prop = MEM_callocN(sizeof(IDProperty), "PyFModifierProps");
1950         data->prop->type = IDP_GROUP;
1951 }
1952
1953 static void fcm_python_copy (FModifier *fcm, FModifier *src)
1954 {
1955         FMod_Python *pymod = (FMod_Python *)fcm->data;
1956         FMod_Python *opymod = (FMod_Python *)src->data;
1957         
1958         pymod->prop = IDP_CopyProperty(opymod->prop);
1959 }
1960
1961 static void fcm_python_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
1962 {
1963 #ifndef DISABLE_PYTHON
1964         //FMod_Python *data= (FMod_Python *)fcm->data;
1965         
1966         /* FIXME... need to implement this modifier...
1967          *      It will need it execute a script using the custom properties 
1968          */
1969 #endif /* DISABLE_PYTHON */
1970 }
1971
1972 static FModifierTypeInfo FMI_PYTHON = {
1973         FMODIFIER_TYPE_PYTHON, /* type */
1974         sizeof(FMod_Python), /* size */
1975         FMI_TYPE_GENERATE_CURVE, /* action type */
1976         FMI_REQUIRES_RUNTIME_CHECK, /* requirements */
1977         "Python", /* name */
1978         "FMod_Python", /* struct name */
1979         fcm_python_free, /* free data */
1980         fcm_python_copy, /* copy data */
1981         fcm_python_new_data, /* new data */
1982         NULL /*fcm_python_verify*/, /* verify */
1983         NULL /*fcm_python_time*/, /* evaluate time */
1984         fcm_python_evaluate /* evaluate */
1985 };
1986
1987
1988 /* Limits F-Curve Modifier --------------------------- */
1989
1990 static float fcm_limits_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
1991 {
1992         FMod_Limits *data= (FMod_Limits *)fcm->data;
1993         
1994         /* check for the time limits */
1995         if ((data->flag & FCM_LIMIT_XMIN) && (evaltime < data->rect.xmin))
1996                 return data->rect.xmin;
1997         if ((data->flag & FCM_LIMIT_XMAX) && (evaltime > data->rect.xmax))
1998                 return data->rect.xmax;
1999                 
2000         /* modifier doesn't change time */
2001         return evaltime;
2002 }
2003
2004 static void fcm_limits_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
2005 {
2006         FMod_Limits *data= (FMod_Limits *)fcm->data;
2007         
2008         /* value limits now */
2009         if ((data->flag & FCM_LIMIT_YMIN) && (*cvalue < data->rect.ymin))
2010                 *cvalue= data->rect.ymin;
2011         if ((data->flag & FCM_LIMIT_YMAX) && (*cvalue > data->rect.ymax))
2012                 *cvalue= data->rect.ymax;
2013 }
2014
2015 static FModifierTypeInfo FMI_LIMITS = {
2016         FMODIFIER_TYPE_LIMITS, /* type */
2017         sizeof(FMod_Limits), /* size */
2018         FMI_TYPE_GENERATE_CURVE, /* action type */  /* XXX... err... */   
2019         FMI_REQUIRES_RUNTIME_CHECK, /* requirements */
2020         "Limits", /* name */
2021         "FMod_Limits", /* struct name */
2022         NULL, /* free data */
2023         NULL, /* copy data */
2024         NULL, /* new data */
2025         NULL, /* verify */
2026         fcm_limits_time, /* evaluate time */
2027         fcm_limits_evaluate /* evaluate */
2028 };
2029
2030 /* F-Curve Modifier API --------------------------- */
2031 /* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out
2032  * and operations that involve F-Curve modifier specific code.
2033  */
2034
2035 /* These globals only ever get directly accessed in this file */
2036 static FModifierTypeInfo *fmodifiersTypeInfo[FMODIFIER_NUM_TYPES];
2037 static short FMI_INIT= 1; /* when non-zero, the list needs to be updated */
2038
2039 /* This function only gets called when FMI_INIT is non-zero */
2040 static void fmods_init_typeinfo () 
2041 {
2042         fmodifiersTypeInfo[0]=  NULL;                                   /* 'Null' F-Curve Modifier */
2043         fmodifiersTypeInfo[1]=  &FMI_GENERATOR;                 /* Generator F-Curve Modifier */
2044         fmodifiersTypeInfo[2]=  &FMI_ENVELOPE;                  /* Envelope F-Curve Modifier */
2045         fmodifiersTypeInfo[3]=  &FMI_CYCLES;                    /* Cycles F-Curve Modifier */
2046         fmodifiersTypeInfo[4]=  &FMI_NOISE;                             /* Apply-Noise F-Curve Modifier */
2047         fmodifiersTypeInfo[5]=  NULL/*&FMI_FILTER*/;                    /* Filter F-Curve Modifier */  // XXX unimplemented
2048         fmodifiersTypeInfo[6]=  &FMI_PYTHON;                    /* Custom Python F-Curve Modifier */
2049         fmodifiersTypeInfo[7]=  &FMI_LIMITS;                    /* Limits F-Curve Modifier */
2050 }
2051
2052 /* This function should be used for getting the appropriate type-info when only
2053  * a F-Curve modifier type is known
2054  */
2055 FModifierTypeInfo *get_fmodifier_typeinfo (int type)
2056 {
2057         /* initialise the type-info list? */
2058         if (FMI_INIT) {
2059                 fmods_init_typeinfo();
2060                 FMI_INIT = 0;
2061         }
2062         
2063         /* only return for valid types */
2064         if ( (type >= FMODIFIER_TYPE_NULL) && 
2065                  (type <= FMODIFIER_NUM_TYPES ) ) 
2066         {
2067                 /* there shouldn't be any segfaults here... */
2068                 return fmodifiersTypeInfo[type];
2069         }
2070         else {
2071                 printf("No valid F-Curve Modifier type-info data available. Type = %i \n", type);
2072         }
2073         
2074         return NULL;
2075
2076  
2077 /* This function should always be used to get the appropriate type-info, as it
2078  * has checks which prevent segfaults in some weird cases.
2079  */
2080 FModifierTypeInfo *fmodifier_get_typeinfo (FModifier *fcm)
2081 {
2082         /* only return typeinfo for valid modifiers */
2083         if (fcm)
2084                 return get_fmodifier_typeinfo(fcm->type);
2085         else
2086                 return NULL;
2087 }
2088
2089 /* API --------------------------- */
2090
2091 /* Add a new F-Curve Modifier to the given F-Curve of a certain type */
2092 FModifier *fcurve_add_modifier (FCurve *fcu, int type)
2093 {
2094         FModifierTypeInfo *fmi= get_fmodifier_typeinfo(type);
2095         FModifier *fcm;
2096         
2097         /* sanity checks */
2098         if ELEM(NULL, fcu, fmi)
2099                 return NULL;
2100         
2101         /* special checks for whether modifier can be added */
2102         if ((fcu->modifiers.first) && (type == FMODIFIER_TYPE_CYCLES)) {
2103                 /* cycles modifier must be first in stack, so for now, don't add if it can't be */
2104                 // TODO: perhaps there is some better way, but for now, 
2105                 printf("Error: Cannot add 'Cycles' modifier to F-Curve, as 'Cycles' modifier can only be first in stack. \n");
2106                 return NULL;
2107         }
2108         
2109         /* add modifier itself */
2110         fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier");
2111         fcm->type = type;
2112         fcm->flag = FMODIFIER_FLAG_EXPANDED;
2113         BLI_addtail(&fcu->modifiers, fcm);
2114         
2115         /* add modifier's data */
2116         fcm->data= MEM_callocN(fmi->size, fmi->structName);
2117                 
2118         /* init custom settings if necessary */
2119         if (fmi->new_data)      
2120                 fmi->new_data(fcm->data);
2121                 
2122         /* return modifier for further editing */
2123         return fcm;
2124 }
2125
2126 /* Duplicate all of the F-Curve Modifiers in the Modifier stacks */
2127 void fcurve_copy_modifiers (ListBase *dst, ListBase *src)
2128 {
2129         FModifier *fcm, *srcfcm;
2130         
2131         if ELEM(NULL, dst, src)
2132                 return;
2133         
2134         dst->first= dst->last= NULL;
2135         BLI_duplicatelist(dst, src);
2136         
2137         for (fcm=dst->first, srcfcm=src->first; fcm && srcfcm; srcfcm=srcfcm->next, fcm=fcm->next) {
2138                 FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
2139                 
2140                 /* make a new copy of the F-Modifier's data */
2141                 fcm->data = MEM_dupallocN(fcm->data);
2142                 
2143                 /* only do specific constraints if required */
2144                 if (fmi && fmi->copy_data)
2145                         fmi->copy_data(fcm, srcfcm);
2146         }
2147 }
2148
2149 /* Remove and free the given F-Curve Modifier from the given F-Curve's stack  */
2150 void fcurve_remove_modifier (FCurve *fcu, FModifier *fcm)
2151 {
2152         FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
2153         
2154         /* sanity check */
2155         if (fcm == NULL)
2156                 return;
2157         
2158         /* free modifier's special data (stored inside fcm->data) */
2159         if (fcm->data) {
2160                 if (fmi && fmi->free_data)
2161                         fmi->free_data(fcm);
2162                         
2163                 /* free modifier's data (fcm->data) */
2164                 MEM_freeN(fcm->data);
2165         }
2166         
2167         /* remove modifier from stack */
2168         if (fcu)
2169                 BLI_freelinkN(&fcu->modifiers, fcm);
2170         else {
2171                 // XXX this case can probably be removed some day, as it shouldn't happen...
2172                 printf("fcurve_remove_modifier() - no fcurve \n");
2173                 MEM_freeN(fcm);
2174         }
2175 }
2176
2177 /* Remove all of a given F-Curve's modifiers */
2178 void fcurve_free_modifiers (FCurve *fcu)
2179 {
2180         FModifier *fcm, *fmn;
2181         
2182         /* sanity check */
2183         if (fcu == NULL)
2184                 return;
2185         
2186         /* free each modifier in order - modifier is unlinked from list and freed */
2187         for (fcm= fcu->modifiers.first; fcm; fcm= fmn) {
2188                 fmn= fcm->next;
2189                 fcurve_remove_modifier(fcu, fcm);
2190         }
2191 }
2192
2193 /* Bake modifiers for given F-Curve to curve sample data, in the frame range defined
2194  * by start and end (inclusive).
2195  */
2196 void fcurve_bake_modifiers (FCurve *fcu, int start, int end)
2197 {
2198         ChannelDriver *driver;
2199         
2200         /* sanity checks */
2201         // TODO: make these tests report errors using reports not printf's
2202         if ELEM(NULL, fcu, fcu->modifiers.first) {
2203                 printf("Error: No F-Curve with F-Curve Modifiers to Bake\n");
2204                 return;
2205         }
2206         
2207         /* temporarily, disable driver while we sample, so that they don't influence the outcome */
2208         driver= fcu->driver;
2209         fcu->driver= NULL;
2210         
2211         /* bake the modifiers, by sampling the curve at each frame */
2212         fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve);
2213         
2214         /* free the modifiers now */
2215         fcurve_free_modifiers(fcu);
2216         
2217         /* restore driver */
2218         fcu->driver= driver;
2219 }
2220
2221 /* Find the active F-Curve Modifier */
2222 FModifier *fcurve_find_active_modifier (FCurve *fcu)
2223 {
2224         FModifier *fcm;
2225         
2226         /* sanity checks */
2227         if ELEM(NULL, fcu, fcu->modifiers.first)
2228                 return NULL;
2229         
2230         /* loop over modifiers until 'active' one is found */
2231         for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
2232                 if (fcm->flag & FMODIFIER_FLAG_ACTIVE)
2233                         return fcm;
2234         }
2235         
2236         /* no modifier is active */
2237         return NULL;
2238 }
2239
2240 /* Set the active F-Curve Modifier */
2241 void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm)
2242 {
2243         FModifier *fm;
2244         
2245         /* sanity checks */
2246         if ELEM(NULL, fcu, fcu->modifiers.first)
2247                 return;
2248         
2249         /* deactivate all, and set current one active */
2250         for (fm= fcu->modifiers.first; fm; fm= fm->next)
2251                 fm->flag &= ~FMODIFIER_FLAG_ACTIVE;
2252         
2253         /* make given modifier active */
2254         if (fcm)
2255                 fcm->flag |= FMODIFIER_FLAG_ACTIVE;
2256 }
2257
2258 /* ***************************** F-Curve - Evaluation ********************************* */
2259
2260 /* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime") 
2261  * Note: this is also used for drivers
2262  */
2263 float evaluate_fcurve (FCurve *fcu, float evaltime) 
2264 {
2265         FModifier *fcm;
2266         float cvalue= 0.0f;
2267         float devaltime;
2268         
2269         /* if there is a driver (only if this F-Curve is acting as 'driver'), evaluate it to find value to use as "evaltime" 
2270          * since drivers essentially act as alternative input (i.e. in place of 'time') for F-Curves
2271          *      - this value will also be returned as the value of the 'curve', if there are no keyframes
2272          */
2273         if (fcu->driver) {
2274                 /* evaltime now serves as input for the curve */
2275                 evaltime= cvalue= evaluate_driver(fcu->driver, evaltime);
2276         }
2277         
2278         /* evaluate time modifications imposed by some F-Curve Modifiers
2279          *      - this step acts as an optimisation to prevent the F-Curve stack being evaluated 
2280          *        several times by modifiers requesting the time be modified, as the final result
2281          *        would have required using the modified time
2282          *      - modifiers only ever recieve the unmodified time, as subsequent modifiers should be
2283          *        working on the 'global' result of the modified curve, not some localised segment,
2284          *        so nevaltime gets set to whatever the last time-modifying modifier likes...
2285          *      - we start from the end of the stack, as only the last one matters for now
2286          */
2287         devaltime= evaltime;
2288         
2289         for (fcm= fcu->modifiers.last; fcm; fcm= fcm->prev) {
2290                 FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
2291                 
2292                 /* only evaluate if there's a callback for this */
2293                 // TODO: implement the 'influence' control feature...
2294                 if (fmi && fmi->evaluate_modifier_time) {
2295                         if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
2296                                 devaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime);
2297                         break;
2298                 }
2299         }
2300         
2301         /* evaluate curve-data 
2302          *      - 'devaltime' instead of 'evaltime', as this is the time that the last time-modifying 
2303          *        F-Curve modifier on the stack requested the curve to be evaluated at
2304          */
2305         if (fcu->bezt)
2306                 cvalue= fcurve_eval_keyframes(fcu, fcu->bezt, devaltime);
2307         else if (fcu->fpt)
2308                 cvalue= fcurve_eval_samples(fcu, fcu->fpt, devaltime);
2309         
2310         /* evaluate modifiers */
2311         for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
2312                 FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
2313                 
2314                 /* only evaluate if there's a callback for this */
2315                 // TODO: implement the 'influence' control feature...
2316                 if (fmi && fmi->evaluate_modifier) {
2317                         if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
2318                                 fmi->evaluate_modifier(fcu, fcm, &cvalue, evaltime);
2319                 }
2320         }
2321         
2322         /* if curve can only have integral values, perform truncation (i.e. drop the decimal part)
2323          * here so that the curve can be sampled correctly
2324          */
2325         if (fcu->flag & FCURVE_INT_VALUES)
2326                 cvalue= (float)((int)cvalue);
2327         
2328         /* return evaluated value */
2329         return cvalue;
2330 }
2331
2332 /* Calculate the value of the given F-Curve at the given frame, and set its curval */
2333 // TODO: will this be necessary?
2334 void calculate_fcurve (FCurve *fcu, float ctime)
2335 {
2336         /* calculate and set curval (evaluates driver too) */
2337         fcu->curval= evaluate_fcurve(fcu, ctime);
2338 }
2339