Blender V2.61 - r43446

fcurve.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Joshua Leung (full recode)
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00034 #include <math.h>
00035 #include <stdio.h>
00036 #include <stddef.h>
00037 #include <string.h>
00038 #include <float.h>
00039 
00040 #include "MEM_guardedalloc.h"
00041 
00042 #include "DNA_anim_types.h"
00043 #include "DNA_constraint_types.h"
00044 #include "DNA_object_types.h"
00045 
00046 #include "BLI_blenlib.h"
00047 #include "BLI_math.h"
00048 #include "BLI_utildefines.h"
00049 
00050 #include "BKE_fcurve.h"
00051 #include "BKE_animsys.h"
00052 #include "BKE_action.h"
00053 #include "BKE_armature.h"
00054 #include "BKE_constraint.h"
00055 #include "BKE_curve.h" 
00056 #include "BKE_global.h"
00057 #include "BKE_object.h"
00058 #include "BKE_utildefines.h"
00059 
00060 #include "RNA_access.h"
00061 
00062 #ifdef WITH_PYTHON
00063 #include "BPY_extern.h" 
00064 #endif
00065 
00066 #define SMALL -1.0e-10
00067 #define SELECT 1
00068 
00069 /* ************************** Data-Level Functions ************************* */
00070 
00071 /* ---------------------- Freeing --------------------------- */
00072 
00073 /* Frees the F-Curve itself too, so make sure BLI_remlink is called before calling this... */
00074 void free_fcurve (FCurve *fcu) 
00075 {
00076     if (fcu == NULL) 
00077         return;
00078     
00079     /* free curve data */
00080     if (fcu) {
00081         if (fcu->bezt) MEM_freeN(fcu->bezt);
00082         if (fcu->fpt) MEM_freeN(fcu->fpt);
00083     }
00084     
00085     /* free RNA-path, as this were allocated when getting the path string */
00086     if (fcu->rna_path)
00087         MEM_freeN(fcu->rna_path);
00088     
00089     /* free extra data - i.e. modifiers, and driver */
00090     fcurve_free_driver(fcu);
00091     free_fmodifiers(&fcu->modifiers);
00092     
00093     /* free f-curve itself */
00094     MEM_freeN(fcu);
00095 }
00096 
00097 /* Frees a list of F-Curves */
00098 void free_fcurves (ListBase *list)
00099 {
00100     FCurve *fcu, *fcn;
00101     
00102     /* sanity check */
00103     if (list == NULL)
00104         return;
00105         
00106     /* free data - no need to call remlink before freeing each curve, 
00107      * as we store reference to next, and freeing only touches the curve
00108      * it's given
00109      */
00110     for (fcu= list->first; fcu; fcu= fcn) {
00111         fcn= fcu->next;
00112         free_fcurve(fcu);
00113     }
00114     
00115     /* clear pointers just in case */
00116     list->first= list->last= NULL;
00117 }   
00118 
00119 /* ---------------------- Copy --------------------------- */
00120 
00121 /* duplicate an F-Curve */
00122 FCurve *copy_fcurve (FCurve *fcu)
00123 {
00124     FCurve *fcu_d;
00125     
00126     /* sanity check */
00127     if (fcu == NULL)
00128         return NULL;
00129         
00130     /* make a copy */
00131     fcu_d= MEM_dupallocN(fcu);
00132     
00133     fcu_d->next= fcu_d->prev= NULL;
00134     fcu_d->grp= NULL;
00135     
00136     /* copy curve data */
00137     fcu_d->bezt= MEM_dupallocN(fcu_d->bezt);
00138     fcu_d->fpt= MEM_dupallocN(fcu_d->fpt);
00139     
00140     /* copy rna-path */
00141     fcu_d->rna_path= MEM_dupallocN(fcu_d->rna_path);
00142     
00143     /* copy driver */
00144     fcu_d->driver= fcurve_copy_driver(fcu_d->driver);
00145     
00146     /* copy modifiers */
00147     copy_fmodifiers(&fcu_d->modifiers, &fcu->modifiers);
00148     
00149     /* return new data */
00150     return fcu_d;
00151 }
00152 
00153 /* duplicate a list of F-Curves */
00154 void copy_fcurves (ListBase *dst, ListBase *src)
00155 {
00156     FCurve *dfcu, *sfcu;
00157     
00158     /* sanity checks */
00159     if ELEM(NULL, dst, src)
00160         return;
00161     
00162     /* clear destination list first */
00163     dst->first= dst->last= NULL;
00164     
00165     /* copy one-by-one */
00166     for (sfcu= src->first; sfcu; sfcu= sfcu->next) {
00167         dfcu= copy_fcurve(sfcu);
00168         BLI_addtail(dst, dfcu);
00169     }
00170 }
00171 
00172 /* ----------------- Finding F-Curves -------------------------- */
00173 
00174 /* high level function to get an fcurve from C without having the rna */
00175 FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *prop_name, int index, char *driven)
00176 {
00177     /* anim vars */
00178     AnimData *adt= BKE_animdata_from_id(id);
00179     FCurve *fcu= NULL;
00180 
00181     /* rna vars */
00182     PointerRNA ptr;
00183     PropertyRNA *prop;
00184     char *path;
00185 
00186     if(driven)
00187         *driven = FALSE;
00188     
00189     /* only use the current action ??? */
00190     if (ELEM(NULL, adt, adt->action))
00191         return NULL;
00192     
00193     RNA_pointer_create(id, type, data, &ptr);
00194     prop = RNA_struct_find_property(&ptr, prop_name);
00195     
00196     if (prop) {
00197         path= RNA_path_from_ID_to_property(&ptr, prop);
00198             
00199         if (path) {
00200             /* animation takes priority over drivers */
00201             if ((adt->action) && (adt->action->curves.first))
00202                 fcu= list_find_fcurve(&adt->action->curves, path, index);
00203             
00204             /* if not animated, check if driven */
00205             if ((fcu == NULL) && (adt->drivers.first)) {
00206                 fcu= list_find_fcurve(&adt->drivers, path, index);
00207                 if(fcu && driven)
00208                     *driven = TRUE;
00209                 fcu = NULL;
00210             }
00211             
00212             MEM_freeN(path);
00213         }
00214     }
00215 
00216     return fcu;
00217 }
00218 
00219 
00220 /* Find the F-Curve affecting the given RNA-access path + index, in the list of F-Curves provided */
00221 FCurve *list_find_fcurve (ListBase *list, const char rna_path[], const int array_index)
00222 {
00223     FCurve *fcu;
00224     
00225     /* sanity checks */
00226     if ( ELEM(NULL, list, rna_path) || (array_index < 0) )
00227         return NULL;
00228     
00229     /* check paths of curves, then array indices... */
00230     for (fcu= list->first; fcu; fcu= fcu->next) {
00231         /* simple string-compare (this assumes that they have the same root...) */
00232         if (fcu->rna_path && !strcmp(fcu->rna_path, rna_path)) {
00233             /* now check indices */
00234             if (fcu->array_index == array_index)
00235                 return fcu;
00236         }
00237     }
00238     
00239     /* return */
00240     return NULL;
00241 }
00242 
00243 /* quick way to loop over all fcurves of a given 'path' */
00244 FCurve *iter_step_fcurve (FCurve *fcu_iter, const char rna_path[])
00245 {
00246     FCurve *fcu;
00247     
00248     /* sanity checks */
00249     if (ELEM(NULL, fcu_iter, rna_path))
00250         return NULL;
00251 
00252     /* check paths of curves, then array indices... */
00253     for (fcu= fcu_iter; fcu; fcu= fcu->next) {
00254         /* simple string-compare (this assumes that they have the same root...) */
00255         if (fcu->rna_path && !strcmp(fcu->rna_path, rna_path)) {
00256             return fcu;
00257         }
00258     }
00259 
00260     /* return */
00261     return NULL;
00262 }
00263 
00264 /* Get list of LinkData's containing pointers to the F-Curves which control the types of data indicated 
00265  * Lists...
00266  *  - dst: list of LinkData's matching the criteria returned. 
00267  *    List must be freed after use, and is assumed to be empty when passed.
00268  *  - src: list of F-Curves to search through
00269  * Filters...
00270  *  - dataPrefix: i.e. 'pose.bones[' or 'nodes['
00271  *  - dataName: name of entity within "" immediately following the prefix
00272  */
00273 int list_find_data_fcurves (ListBase *dst, ListBase *src, const char *dataPrefix, const char *dataName)
00274 {
00275     FCurve *fcu;
00276     int matches = 0;
00277     
00278     /* sanity checks */
00279     if (ELEM4(NULL, dst, src, dataPrefix, dataName))
00280         return 0;
00281     else if ((dataPrefix[0] == 0) || (dataName[0] == 0))
00282         return 0;
00283     
00284     /* search each F-Curve one by one */
00285     for (fcu= src->first; fcu; fcu= fcu->next) {
00286         /* check if quoted string matches the path */
00287         if ((fcu->rna_path) && strstr(fcu->rna_path, dataPrefix)) {
00288             char *quotedName= BLI_getQuotedStr(fcu->rna_path, dataPrefix);
00289             
00290             if (quotedName) {
00291                 /* check if the quoted name matches the required name */
00292                 if (strcmp(quotedName, dataName) == 0) {
00293                     LinkData *ld= MEM_callocN(sizeof(LinkData), "list_find_data_fcurves");
00294                     
00295                     ld->data= fcu;
00296                     BLI_addtail(dst, ld);
00297                     
00298                     matches++;
00299                 }
00300                 
00301                 /* always free the quoted string, since it needs freeing */
00302                 MEM_freeN(quotedName);
00303             }
00304         }
00305     }
00306     
00307     /* return the number of matches */
00308     return matches;
00309 }
00310 
00311 FCurve *rna_get_fcurve (PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction **action, int *driven)
00312 {
00313     FCurve *fcu= NULL;
00314     
00315     *driven= 0;
00316     
00317     /* there must be some RNA-pointer + property combon */
00318     if (prop && ptr->id.data && RNA_property_animateable(ptr, prop)) {
00319         AnimData *adt= BKE_animdata_from_id(ptr->id.data);
00320         char *path;
00321         
00322         if (adt) {
00323             if ((adt->action && adt->action->curves.first) || (adt->drivers.first)) {
00324                 /* XXX this function call can become a performance bottleneck */
00325                 path= RNA_path_from_ID_to_property(ptr, prop);
00326                 
00327                 if (path) {
00328                     /* animation takes priority over drivers */
00329                     if (adt->action && adt->action->curves.first)
00330                         fcu= list_find_fcurve(&adt->action->curves, path, rnaindex);
00331                     
00332                     /* if not animated, check if driven */
00333                     if (!fcu && (adt->drivers.first)) {
00334                         fcu= list_find_fcurve(&adt->drivers, path, rnaindex);
00335                         
00336                         if (fcu)
00337                             *driven= 1;
00338                     }
00339                     
00340                     if (fcu && action)
00341                         *action= adt->action;
00342                     
00343                     MEM_freeN(path);
00344                 }
00345             }
00346         }
00347     }
00348     
00349     return fcu;
00350 }
00351 
00352 /* ----------------- Finding Keyframes/Extents -------------------------- */
00353 
00354 /* threshold for binary-searching keyframes - threshold here should be good enough for now, but should become userpref */
00355 #define BEZT_BINARYSEARCH_THRESH    0.01f /* was 0.00001, but giving errors */
00356 
00357 /* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_fcurve)
00358  * Returns the index to insert at (data already at that index will be offset if replace is 0)
00359  */
00360 int binarysearch_bezt_index (BezTriple array[], float frame, int arraylen, short *replace)
00361 {
00362     int start=0, end=arraylen;
00363     int loopbreaker= 0, maxloop= arraylen * 2;
00364     
00365     /* initialise replace-flag first */
00366     *replace= 0;
00367     
00368     /* sneaky optimisations (don't go through searching process if...):
00369      *  - keyframe to be added is to be added out of current bounds
00370      *  - keyframe to be added would replace one of the existing ones on bounds
00371      */
00372     if ((arraylen <= 0) || (array == NULL)) {
00373         printf("Warning: binarysearch_bezt_index() encountered invalid array \n");
00374         return 0;
00375     }
00376     else {
00377         /* check whether to add before/after/on */
00378         float framenum;
00379         
00380         /* 'First' Keyframe (when only one keyframe, this case is used) */
00381         framenum= array[0].vec[1][0];
00382         if (IS_EQT(frame, framenum, BEZT_BINARYSEARCH_THRESH)) {
00383             *replace = 1;
00384             return 0;
00385         }
00386         else if (frame < framenum)
00387             return 0;
00388             
00389         /* 'Last' Keyframe */
00390         framenum= array[(arraylen-1)].vec[1][0];
00391         if (IS_EQT(frame, framenum, BEZT_BINARYSEARCH_THRESH)) {
00392             *replace= 1;
00393             return (arraylen - 1);
00394         }
00395         else if (frame > framenum)
00396             return arraylen;
00397     }
00398     
00399     
00400     /* most of the time, this loop is just to find where to put it
00401      * 'loopbreaker' is just here to prevent infinite loops 
00402      */
00403     for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
00404         /* compute and get midpoint */
00405         int mid = start + ((end - start) / 2);  /* we calculate the midpoint this way to avoid int overflows... */
00406         float midfra= array[mid].vec[1][0];
00407         
00408         /* check if exactly equal to midpoint */
00409         if (IS_EQT(frame, midfra, BEZT_BINARYSEARCH_THRESH)) {
00410             *replace = 1;
00411             return mid;
00412         }
00413         
00414         /* repeat in upper/lower half */
00415         if (frame > midfra)
00416             start= mid + 1;
00417         else if (frame < midfra)
00418             end= mid - 1;
00419     }
00420     
00421     /* print error if loop-limit exceeded */
00422     if (loopbreaker == (maxloop-1)) {
00423         printf("Error: binarysearch_bezt_index() was taking too long \n");
00424         
00425         // include debug info 
00426         printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen);
00427     }
00428     
00429     /* not found, so return where to place it */
00430     return start;
00431 }
00432 
00433 /* ...................................... */
00434 
00435 /* helper for calc_fcurve_* functions -> find first and last BezTriple to be used */
00436 static void get_fcurve_end_keyframes (FCurve *fcu, BezTriple **first, BezTriple **last,
00437                                       const short do_sel_only)
00438 {
00439     /* init outputs */
00440     *first = NULL;
00441     *last = NULL;
00442     
00443     /* sanity checks */
00444     if (fcu->bezt == NULL)
00445         return;
00446     
00447     /* only include selected items? */
00448     if (do_sel_only) {
00449         BezTriple *bezt;
00450         unsigned int i;
00451         
00452         /* find first selected */
00453         bezt = fcu->bezt;
00454         for (i=0; i < fcu->totvert; bezt++, i++) {
00455             if (BEZSELECTED(bezt)) {
00456                 *first= bezt;
00457                 break;
00458             }
00459         }
00460         
00461         /* find last selected */
00462         bezt = ARRAY_LAST_ITEM(fcu->bezt, BezTriple, sizeof(BezTriple), fcu->totvert);
00463         for (i=0; i < fcu->totvert; bezt--, i++) {
00464             if (BEZSELECTED(bezt)) {
00465                 *last= bezt;
00466                 break;
00467             }
00468         }
00469     }
00470     else {
00471         /* just full array */
00472         *first = fcu->bezt;
00473         *last = ARRAY_LAST_ITEM(fcu->bezt, BezTriple, sizeof(BezTriple), fcu->totvert);
00474     }
00475 }
00476 
00477 
00478 /* Calculate the extents of F-Curve's data */
00479 void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax,
00480                          const short do_sel_only)
00481 {
00482     float xminv=999999999.0f, xmaxv=-999999999.0f;
00483     float yminv=999999999.0f, ymaxv=-999999999.0f;
00484     short foundvert= FALSE;
00485     unsigned int i;
00486     
00487     if (fcu->totvert) {
00488         if (fcu->bezt) {
00489             BezTriple *bezt_first= NULL, *bezt_last= NULL;
00490             
00491             if (xmin || xmax) {
00492                 /* get endpoint keyframes */
00493                 get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, do_sel_only);
00494                 
00495                 if (bezt_first) {
00496                     BLI_assert(bezt_last != NULL);
00497                     
00498                     xminv= MIN2(xminv, bezt_first->vec[1][0]);
00499                     xmaxv= MAX2(xmaxv, bezt_last->vec[1][0]);
00500                 }
00501             }
00502             
00503             /* only loop over keyframes to find extents for values if needed */
00504             if (ymin || ymax) { 
00505                 BezTriple *bezt;
00506                 
00507                 for (bezt=fcu->bezt, i=0; i < fcu->totvert; bezt++, i++) {
00508                     if ((do_sel_only == 0) || BEZSELECTED(bezt)) {
00509                         if (bezt->vec[1][1] < yminv)
00510                             yminv= bezt->vec[1][1];
00511                         if (bezt->vec[1][1] > ymaxv)
00512                             ymaxv= bezt->vec[1][1];
00513                         foundvert= TRUE;
00514                     }
00515                 }
00516             }
00517         }
00518         else if (fcu->fpt) {
00519             /* frame range can be directly calculated from end verts */
00520             if (xmin || xmax) {
00521                 xminv= MIN2(xminv, fcu->fpt[0].vec[0]);
00522                 xmaxv= MAX2(xmaxv, fcu->fpt[fcu->totvert-1].vec[0]);
00523             }
00524             
00525             /* only loop over keyframes to find extents for values if needed */
00526             if (ymin || ymax) {
00527                 FPoint *fpt;
00528                 
00529                 for (fpt=fcu->fpt, i=0; i < fcu->totvert; fpt++, i++) {
00530                     if (fpt->vec[1] < yminv)
00531                         yminv= fpt->vec[1];
00532                     if (fpt->vec[1] > ymaxv)
00533                         ymaxv= fpt->vec[1];
00534 
00535                     foundvert= TRUE;
00536                 }
00537             }
00538         }
00539     }
00540     
00541     if (foundvert) {
00542         if (xmin) *xmin= xminv;
00543         if (xmax) *xmax= xmaxv;
00544         
00545         if (ymin) *ymin= yminv;
00546         if (ymax) *ymax= ymaxv;
00547     }
00548     else {
00549         if (G.f & G_DEBUG)
00550             printf("F-Curve calc bounds didn't find anything, so assuming minimum bounds of 1.0\n");
00551             
00552         if (xmin) *xmin= 0.0f;
00553         if (xmax) *xmax= 1.0f;
00554         
00555         if (ymin) *ymin= 0.0f;
00556         if (ymax) *ymax= 1.0f;
00557     }
00558 }
00559 
00560 /* Calculate the extents of F-Curve's keyframes */
00561 void calc_fcurve_range (FCurve *fcu, float *start, float *end,
00562                         const short do_sel_only, const short do_min_length)
00563 {
00564     float min=999999999.0f, max=-999999999.0f;
00565     short foundvert= FALSE;
00566 
00567     if (fcu->totvert) {
00568         if (fcu->bezt) {
00569             BezTriple *bezt_first= NULL, *bezt_last= NULL;
00570             
00571             /* get endpoint keyframes */
00572             get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, do_sel_only);
00573 
00574             if (bezt_first) {
00575                 BLI_assert(bezt_last != NULL);
00576 
00577                 min= MIN2(min, bezt_first->vec[1][0]);
00578                 max= MAX2(max, bezt_last->vec[1][0]);
00579 
00580                 foundvert= TRUE;
00581             }
00582         }
00583         else if (fcu->fpt) {
00584             min= MIN2(min, fcu->fpt[0].vec[0]);
00585             max= MAX2(max, fcu->fpt[fcu->totvert-1].vec[0]);
00586 
00587             foundvert= TRUE;
00588         }
00589         
00590     }
00591     
00592     if (foundvert == FALSE) {
00593         min= max= 0.0f;
00594     }
00595 
00596     if (do_min_length) {
00597         /* minimum length is 1 frame */
00598         if (min == max) {
00599             max += 1.0f;
00600         }
00601     }
00602 
00603     *start= min;
00604     *end= max;
00605 }
00606 
00607 /* ----------------- Status Checks -------------------------- */
00608 
00609 /* Are keyframes on F-Curve of any use? 
00610  * Usability of keyframes refers to whether they should be displayed,
00611  * and also whether they will have any influence on the final result.
00612  */
00613 short fcurve_are_keyframes_usable (FCurve *fcu)
00614 {
00615     /* F-Curve must exist */
00616     if (fcu == NULL)
00617         return 0;
00618         
00619     /* F-Curve must not have samples - samples are mutually exclusive of keyframes */
00620     if (fcu->fpt)
00621         return 0;
00622     
00623     /* if it has modifiers, none of these should "drastically" alter the curve */
00624     if (fcu->modifiers.first) {
00625         FModifier *fcm;
00626         
00627         /* check modifiers from last to first, as last will be more influential */
00628         // TODO: optionally, only check modifier if it is the active one...
00629         for (fcm = fcu->modifiers.last; fcm; fcm = fcm->prev) {
00630             /* ignore if muted/disabled */
00631             if (fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED))
00632                 continue;
00633                 
00634             /* type checks */
00635             switch (fcm->type) {
00636                 /* clearly harmless - do nothing */
00637                 case FMODIFIER_TYPE_CYCLES:
00638                 case FMODIFIER_TYPE_STEPPED:
00639                 case FMODIFIER_TYPE_NOISE:
00640                     break;
00641                     
00642                 /* sometimes harmful - depending on whether they're "additive" or not */
00643                 case FMODIFIER_TYPE_GENERATOR:
00644                 {
00645                     FMod_Generator *data = (FMod_Generator *)fcm->data;
00646                     
00647                     if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
00648                         return 0;
00649                 }
00650                     break;
00651                 case FMODIFIER_TYPE_FN_GENERATOR:
00652                 {
00653                     FMod_FunctionGenerator *data = (FMod_FunctionGenerator *)fcm->data;
00654                     
00655                     if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
00656                         return 0;
00657                 }
00658                     break;
00659                     
00660                 /* always harmful - cannot allow */
00661                 default:
00662                     return 0;
00663             }
00664         }
00665     }
00666     
00667     /* keyframes are usable */
00668     return 1;
00669 }
00670 
00671 /* Can keyframes be added to F-Curve? 
00672  * Keyframes can only be added if they are already visible
00673  */
00674 short fcurve_is_keyframable (FCurve *fcu)
00675 {
00676     /* F-Curve's keyframes must be "usable" (i.e. visible + have an effect on final result) */
00677     if (fcurve_are_keyframes_usable(fcu) == 0)
00678         return 0;
00679         
00680     /* F-Curve must currently be editable too */
00681     if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) )
00682         return 0;
00683     
00684     /* F-Curve is keyframable */
00685     return 1;
00686 }
00687 
00688 /* ***************************** Keyframe Column Tools ********************************* */
00689 
00690 /* add a BezTriple to a column */
00691 void bezt_add_to_cfra_elem (ListBase *lb, BezTriple *bezt)
00692 {
00693     CfraElem *ce, *cen;
00694     
00695     for (ce= lb->first; ce; ce= ce->next) {
00696         /* double key? */
00697         if (ce->cfra == bezt->vec[1][0]) {
00698             if (bezt->f2 & SELECT) ce->sel= bezt->f2;
00699             return;
00700         }
00701         /* should key be inserted before this column? */
00702         else if (ce->cfra > bezt->vec[1][0]) break;
00703     }
00704     
00705     /* create a new column */
00706     cen= MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem"); 
00707     if (ce) BLI_insertlinkbefore(lb, ce, cen);
00708     else BLI_addtail(lb, cen);
00709 
00710     cen->cfra= bezt->vec[1][0];
00711     cen->sel= bezt->f2;
00712 }
00713 
00714 /* ***************************** Samples Utilities ******************************* */
00715 /* Some utilities for working with FPoints (i.e. 'sampled' animation curve data, such as
00716  * data imported from BVH/Mocap files), which are specialized for use with high density datasets,
00717  * which BezTriples/Keyframe data are ill equipped to do.
00718  */
00719  
00720  
00721 /* Basic sampling callback which acts as a wrapper for evaluate_fcurve() 
00722  *  'data' arg here is unneeded here...
00723  */
00724 float fcurve_samplingcb_evalcurve (FCurve *fcu, void *UNUSED(data), float evaltime)
00725 {
00726     /* assume any interference from drivers on the curve is intended... */
00727     return evaluate_fcurve(fcu, evaltime);
00728 } 
00729 
00730  
00731 /* Main API function for creating a set of sampled curve data, given some callback function 
00732  * used to retrieve the values to store.
00733  */
00734 void fcurve_store_samples (FCurve *fcu, void *data, int start, int end, FcuSampleFunc sample_cb)
00735 {
00736     FPoint *fpt, *new_fpt;
00737     int cfra;
00738     
00739     /* sanity checks */
00740     // TODO: make these tests report errors using reports not printf's
00741     if ELEM(NULL, fcu, sample_cb) {
00742         printf("Error: No F-Curve with F-Curve Modifiers to Bake\n");
00743         return;
00744     }
00745     if (start >= end) {
00746         printf("Error: Frame range for Sampled F-Curve creation is inappropriate \n");
00747         return;
00748     }
00749     
00750     /* set up sample data */
00751     fpt= new_fpt= MEM_callocN(sizeof(FPoint)*(end-start+1), "FPoint Samples");
00752     
00753     /* use the sampling callback at 1-frame intervals from start to end frames */
00754     for (cfra= start; cfra <= end; cfra++, fpt++) {
00755         fpt->vec[0]= (float)cfra;
00756         fpt->vec[1]= sample_cb(fcu, data, (float)cfra);
00757     }
00758     
00759     /* free any existing sample/keyframe data on curve  */
00760     if (fcu->bezt) MEM_freeN(fcu->bezt);
00761     if (fcu->fpt) MEM_freeN(fcu->fpt);
00762     
00763     /* store the samples */
00764     fcu->bezt= NULL;
00765     fcu->fpt= new_fpt;
00766     fcu->totvert= end - start + 1;
00767 }
00768 
00769 /* ***************************** F-Curve Sanity ********************************* */
00770 /* The functions here are used in various parts of Blender, usually after some editing
00771  * of keyframe data has occurred. They ensure that keyframe data is properly ordered and
00772  * that the handles are correctly 
00773  */
00774 
00775 /* This function recalculates the handles of an F-Curve 
00776  * If the BezTriples have been rearranged, sort them first before using this.
00777  */
00778 void calchandles_fcurve (FCurve *fcu)
00779 {
00780     BezTriple *bezt, *prev, *next;
00781     int a= fcu->totvert;
00782 
00783     /* Error checking:
00784      *  - need at least two points
00785      *  - need bezier keys
00786      *  - only bezier-interpolation has handles (for now)
00787      */
00788     if (ELEM(NULL, fcu, fcu->bezt) || (a < 2) /*|| ELEM(fcu->ipo, BEZT_IPO_CONST, BEZT_IPO_LIN)*/) 
00789         return;
00790     
00791     /* get initial pointers */
00792     bezt= fcu->bezt;
00793     prev= NULL;
00794     next= (bezt + 1);
00795     
00796     /* loop over all beztriples, adjusting handles */
00797     while (a--) {
00798         /* clamp timing of handles to be on either side of beztriple */
00799         if (bezt->vec[0][0] > bezt->vec[1][0]) bezt->vec[0][0]= bezt->vec[1][0];
00800         if (bezt->vec[2][0] < bezt->vec[1][0]) bezt->vec[2][0]= bezt->vec[1][0];
00801         
00802         /* calculate auto-handles */
00803         calchandleNurb(bezt, prev, next, 1);    /* 1==special autohandle */
00804         
00805         /* for automatic ease in and out */
00806         if (ELEM(bezt->h1,HD_AUTO,HD_AUTO_ANIM) && ELEM(bezt->h2,HD_AUTO,HD_AUTO_ANIM)) {
00807             /* only do this on first or last beztriple */
00808             if ((a == 0) || (a == fcu->totvert-1)) {
00809                 /* set both handles to have same horizontal value as keyframe */
00810                 if (fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) {
00811                     bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
00812                 }
00813             }
00814         }
00815         
00816         /* advance pointers for next iteration */
00817         prev= bezt;
00818         if (a == 1) next= NULL;
00819         else next++;
00820         bezt++;
00821     }
00822 }
00823 
00824 /* Use when F-Curve with handles has changed
00825  * It treats all BezTriples with the following rules:
00826  *  - PHASE 1: do types have to be altered?
00827  *      -> Auto handles: become aligned when selection status is NOT(000 || 111)
00828  *      -> Vector handles: become 'nothing' when (one half selected AND other not)
00829  *  - PHASE 2: recalculate handles
00830 */
00831 void testhandles_fcurve (FCurve *fcu, const short use_handle)
00832 {
00833     BezTriple *bezt;
00834     unsigned int a;
00835 
00836     /* only beztriples have handles (bpoints don't though) */
00837     if ELEM(NULL, fcu, fcu->bezt)
00838         return;
00839     
00840     /* loop over beztriples */
00841     for (a=0, bezt=fcu->bezt; a < fcu->totvert; a++, bezt++) {
00842         short flag= 0;
00843         
00844         /* flag is initialised as selection status
00845          * of beztriple control-points (labelled 0,1,2)
00846          */
00847         if (bezt->f2 & SELECT) flag |= (1<<1); // == 2
00848         if(use_handle == FALSE) {
00849             if(flag & 2) {
00850                 flag |= (1<<0) | (1<<2);
00851             }
00852         }
00853         else {
00854             if (bezt->f1 & SELECT) flag |= (1<<0); // == 1
00855             if (bezt->f3 & SELECT) flag |= (1<<2); // == 4
00856         }
00857         
00858         /* one or two handles selected only */
00859         if (ELEM(flag, 0, 7)==0) {
00860             /* auto handles become aligned */
00861             if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM))
00862                 bezt->h1= HD_ALIGN;
00863             if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM))
00864                 bezt->h2= HD_ALIGN;
00865             
00866             /* vector handles become 'free' when only one half selected */
00867             if (bezt->h1==HD_VECT) {
00868                 /* only left half (1 or 2 or 1+2) */
00869                 if (flag < 4) 
00870                     bezt->h1= 0;
00871             }
00872             if (bezt->h2==HD_VECT) {
00873                 /* only right half (4 or 2+4) */
00874                 if (flag > 3) 
00875                     bezt->h2= 0;
00876             }
00877         }
00878     }
00879 
00880     /* recalculate handles */
00881     calchandles_fcurve(fcu);
00882 }
00883 
00884 /* This function sorts BezTriples so that they are arranged in chronological order,
00885  * as tools working on F-Curves expect that the BezTriples are in order.
00886  */
00887 void sort_time_fcurve (FCurve *fcu)
00888 {
00889     short ok= 1;
00890     
00891     /* keep adjusting order of beztriples until nothing moves (bubble-sort) */
00892     while (ok) {
00893         ok= 0;
00894         
00895         /* currently, will only be needed when there are beztriples */
00896         if (fcu->bezt) {
00897             BezTriple *bezt;
00898             unsigned int a;
00899             
00900             /* loop over ALL points to adjust position in array and recalculate handles */
00901             for (a=0, bezt=fcu->bezt; a < fcu->totvert; a++, bezt++) {
00902                 /* check if thee's a next beztriple which we could try to swap with current */
00903                 if (a < (fcu->totvert-1)) {
00904                     /* swap if one is after the other (and indicate that order has changed) */
00905                     if (bezt->vec[1][0] > (bezt+1)->vec[1][0]) {
00906                         SWAP(BezTriple, *bezt, *(bezt+1));
00907                         ok= 1;
00908                     }
00909                     
00910                     /* if either one of both of the points exceeds crosses over the keyframe time... */
00911                     if ( (bezt->vec[0][0] > bezt->vec[1][0]) && (bezt->vec[2][0] < bezt->vec[1][0]) ) {
00912                         /* swap handles if they have switched sides for some reason */
00913                         SWAP(float, bezt->vec[0][0], bezt->vec[2][0]);
00914                         SWAP(float, bezt->vec[0][1], bezt->vec[2][1]);
00915                     }
00916                     else {
00917                         /* clamp handles */
00918                         if (bezt->vec[0][0] > bezt->vec[1][0]) 
00919                             bezt->vec[0][0]= bezt->vec[1][0];
00920                         if (bezt->vec[2][0] < bezt->vec[1][0]) 
00921                             bezt->vec[2][0]= bezt->vec[1][0];
00922                     }
00923                 }
00924             }
00925         }
00926     }
00927 }
00928 
00929 /* This function tests if any BezTriples are out of order, thus requiring a sort */
00930 short test_time_fcurve (FCurve *fcu)
00931 {
00932     unsigned int a;
00933     
00934     /* sanity checks */
00935     if (fcu == NULL)
00936         return 0;
00937     
00938     /* currently, only need to test beztriples */
00939     if (fcu->bezt) {
00940         BezTriple *bezt;
00941         
00942         /* loop through all BezTriples, stopping when one exceeds the one after it */
00943         for (a=0, bezt= fcu->bezt; a < (fcu->totvert - 1); a++, bezt++) {
00944             if (bezt->vec[1][0] > (bezt+1)->vec[1][0])
00945                 return 1;
00946         }
00947     }
00948     else if (fcu->fpt) {
00949         FPoint *fpt;
00950         
00951         /* loop through all FPoints, stopping when one exceeds the one after it */
00952         for (a=0, fpt= fcu->fpt; a < (fcu->totvert - 1); a++, fpt++) {
00953             if (fpt->vec[0] > (fpt+1)->vec[0])
00954                 return 1;
00955         }
00956     }
00957     
00958     /* none need any swapping */
00959     return 0;
00960 }
00961 
00962 /* ***************************** Drivers ********************************* */
00963 
00964 /* Driver Variables --------------------------- */
00965 
00966 /* TypeInfo for Driver Variables (dvti) */
00967 typedef struct DriverVarTypeInfo {
00968     /* evaluation callback */
00969     float (*get_value)(ChannelDriver *driver, DriverVar *dvar);
00970     
00971     /* allocation of target slots */
00972     int num_targets;                        /* number of target slots required */
00973     const char *target_names[MAX_DRIVER_TARGETS];   /* UI names that should be given to the slots */
00974     int target_flags[MAX_DRIVER_TARGETS];   /* flags defining the requirements for each slot */
00975 } DriverVarTypeInfo;
00976 
00977 /* Macro to begin definitions */
00978 #define BEGIN_DVAR_TYPEDEF(type) \
00979     {
00980     
00981 /* Macro to end definitions */
00982 #define END_DVAR_TYPEDEF \
00983     }
00984 
00985 /* ......... */
00986 
00987 static ID *dtar_id_ensure_proxy_from(ID *id)
00988 {
00989     if (id && GS(id->name)==ID_OB && ((Object *)id)->proxy_from)
00990         return (ID *)(((Object *)id)->proxy_from);
00991     return id;
00992 }
00993 
00994 /* Helper function to obtain a value using RNA from the specified source (for evaluating drivers) */
00995 static float dtar_get_prop_val (ChannelDriver *driver, DriverTarget *dtar)
00996 {
00997     PointerRNA id_ptr, ptr;
00998     PropertyRNA *prop;
00999     ID *id;
01000     int index;
01001     float value= 0.0f;
01002     
01003     /* sanity check */
01004     if ELEM(NULL, driver, dtar)
01005         return 0.0f;
01006     
01007     id= dtar_id_ensure_proxy_from(dtar->id);
01008     
01009     /* error check for missing pointer... */
01010     // TODO: tag the specific target too as having issues
01011     if (id == NULL) {
01012         printf("Error: driver has an invalid target to use \n");
01013         if (G.f & G_DEBUG) printf("\tpath = %s\n", dtar->rna_path);
01014         driver->flag |= DRIVER_FLAG_INVALID;
01015         return 0.0f;
01016     }
01017     
01018     /* get RNA-pointer for the ID-block given in target */
01019     RNA_id_pointer_create(id, &id_ptr);
01020     
01021     /* get property to read from, and get value as appropriate */
01022     if (RNA_path_resolve_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) {
01023         if(RNA_property_array_check(prop)) {
01024             /* array */
01025             if (index < RNA_property_array_length(&ptr, prop)) {    
01026                 switch (RNA_property_type(prop)) {
01027                 case PROP_BOOLEAN:
01028                     value= (float)RNA_property_boolean_get_index(&ptr, prop, index);
01029                     break;
01030                 case PROP_INT:
01031                     value= (float)RNA_property_int_get_index(&ptr, prop, index);
01032                     break;
01033                 case PROP_FLOAT:
01034                     value= RNA_property_float_get_index(&ptr, prop, index);
01035                     break;
01036                 default:
01037                     break;
01038                 }
01039             }
01040         }
01041         else {
01042             /* not an array */
01043             switch (RNA_property_type(prop)) {
01044             case PROP_BOOLEAN:
01045                 value= (float)RNA_property_boolean_get(&ptr, prop);
01046                 break;
01047             case PROP_INT:
01048                 value= (float)RNA_property_int_get(&ptr, prop);
01049                 break;
01050             case PROP_FLOAT:
01051                 value= RNA_property_float_get(&ptr, prop);
01052                 break;
01053             case PROP_ENUM:
01054                 value= (float)RNA_property_enum_get(&ptr, prop);
01055                 break;
01056             default:
01057                 break;
01058             }
01059         }
01060 
01061     }
01062     else {
01063         if (G.f & G_DEBUG)
01064             printf("Driver Evaluation Error: cannot resolve target for %s -> %s \n", id->name, dtar->rna_path);
01065         
01066         driver->flag |= DRIVER_FLAG_INVALID;
01067         return 0.0f;
01068     }
01069     
01070     return value;
01071 }
01072 
01073 /* Helper function to obtain a pointer to a Pose Channel (for evaluating drivers) */
01074 static bPoseChannel *dtar_get_pchan_ptr (ChannelDriver *driver, DriverTarget *dtar)
01075 {
01076     ID *id;
01077     /* sanity check */
01078     if ELEM(NULL, driver, dtar)
01079         return NULL;
01080 
01081     id= dtar_id_ensure_proxy_from(dtar->id);
01082 
01083     /* check if the ID here is a valid object */
01084     if (id && GS(id->name)) {
01085         Object *ob= (Object *)id;
01086         
01087         /* get pose, and subsequently, posechannel */
01088         return get_pose_channel(ob->pose, dtar->pchan_name);
01089     }
01090     else {
01091         /* cannot find a posechannel this way */
01092         return NULL;
01093     }
01094 }
01095 
01096 /* ......... */
01097 
01098 /* evaluate 'single prop' driver variable */
01099 static float dvar_eval_singleProp (ChannelDriver *driver, DriverVar *dvar)
01100 {
01101     /* just evaluate the first target slot */
01102     return dtar_get_prop_val(driver, &dvar->targets[0]);
01103 }
01104 
01105 /* evaluate 'rotation difference' driver variable */
01106 static float dvar_eval_rotDiff (ChannelDriver *driver, DriverVar *dvar)
01107 {
01108     bPoseChannel *pchan, *pchan2;
01109     float q1[4], q2[4], quat[4], angle;
01110     
01111     /* get pose channels, and check if we've got two */
01112     pchan= dtar_get_pchan_ptr(driver, &dvar->targets[0]);
01113     pchan2= dtar_get_pchan_ptr(driver, &dvar->targets[1]);
01114     
01115     if (ELEM(NULL, pchan, pchan2)) {
01116         /* disable this driver, since it doesn't work correctly... */
01117         driver->flag |= DRIVER_FLAG_INVALID;
01118         
01119         /* check what the error was */
01120         if ((pchan == NULL) && (pchan2 == NULL))
01121             printf("Driver Evaluation Error: Rotational difference failed - first 2 targets invalid \n");
01122         else if (pchan == NULL)
01123             printf("Driver Evaluation Error: Rotational difference failed - first target not valid PoseChannel \n");
01124         else if (pchan2 == NULL)
01125             printf("Driver Evaluation Error: Rotational difference failed - second target not valid PoseChannel \n");
01126             
01127         /* stop here... */
01128         return 0.0f;
01129     }           
01130     
01131     /* use the final posed locations */
01132     mat4_to_quat(q1, pchan->pose_mat);
01133     mat4_to_quat(q2, pchan2->pose_mat);
01134     
01135     invert_qt(q1);
01136     mul_qt_qtqt(quat, q1, q2);
01137     angle = 2.0f * (saacos(quat[0]));
01138     angle= ABS(angle);
01139     
01140     return (angle > (float)M_PI) ? (float)((2.0f * (float)M_PI) - angle) : (float)(angle);
01141 }
01142 
01143 /* evaluate 'location difference' driver variable */
01144 // TODO: this needs to take into account space conversions...
01145 static float dvar_eval_locDiff (ChannelDriver *driver, DriverVar *dvar)
01146 {
01147     float loc1[3] = {0.0f,0.0f,0.0f};
01148     float loc2[3] = {0.0f,0.0f,0.0f};
01149     
01150     /* get two location values */
01151     // NOTE: for now, these are all just worldspace
01152     DRIVER_TARGETS_USED_LOOPER(dvar)
01153     {
01154         /* get pointer to loc values to store in */
01155         Object *ob= (Object *)dtar_id_ensure_proxy_from(dtar->id);
01156         bPoseChannel *pchan;
01157         float tmp_loc[3];
01158         
01159         /* check if this target has valid data */
01160         if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) {
01161             /* invalid target, so will not have enough targets */
01162             driver->flag |= DRIVER_FLAG_INVALID;
01163             return 0.0f;
01164         }
01165         
01166         /* try to get posechannel */
01167         pchan= get_pose_channel(ob->pose, dtar->pchan_name);
01168         
01169         /* check if object or bone */
01170         if (pchan) {
01171             /* bone */
01172             if (dtar->flag & DTAR_FLAG_LOCALSPACE) {
01173                 if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
01174                     float mat[4][4];
01175                     
01176                     /* extract transform just like how the constraints do it! */
01177                     copy_m4_m4(mat, pchan->pose_mat);
01178                     constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
01179                     
01180                     /* ... and from that, we get our transform */
01181                     copy_v3_v3(tmp_loc, mat[3]);
01182                 }
01183                 else {
01184                     /* transform space (use transform values directly) */
01185                     copy_v3_v3(tmp_loc, pchan->loc);
01186                 }
01187             }
01188             else {
01189                 /* convert to worldspace */
01190                 copy_v3_v3(tmp_loc, pchan->pose_head);
01191                 mul_m4_v3(ob->obmat, tmp_loc);
01192             }
01193         }
01194         else {
01195             /* object */
01196             if (dtar->flag & DTAR_FLAG_LOCALSPACE) {
01197                 if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
01198                     // XXX: this should practically be the same as transform space...
01199                     float mat[4][4];
01200                     
01201                     /* extract transform just like how the constraints do it! */
01202                     copy_m4_m4(mat, ob->obmat);
01203                     constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
01204                     
01205                     /* ... and from that, we get our transform */
01206                     copy_v3_v3(tmp_loc, mat[3]);
01207                 }
01208                 else {
01209                     /* transform space (use transform values directly) */
01210                     copy_v3_v3(tmp_loc, ob->loc);
01211                 }
01212             }
01213             else {
01214                 /* worldspace */
01215                 copy_v3_v3(tmp_loc, ob->obmat[3]);
01216             }
01217         }
01218         
01219         /* copy the location to the right place */
01220         if (tarIndex) {
01221             copy_v3_v3(loc2, tmp_loc);
01222         }
01223         else {
01224             copy_v3_v3(loc1, tmp_loc);
01225         }
01226     }
01227     DRIVER_TARGETS_LOOPER_END
01228     
01229     
01230     /* if we're still here, there should now be two targets to use,
01231      * so just take the length of the vector between these points 
01232      */
01233     return len_v3v3(loc1, loc2);
01234 }
01235 
01236 /* evaluate 'transform channel' driver variable */
01237 static float dvar_eval_transChan (ChannelDriver *driver, DriverVar *dvar)
01238 {
01239     DriverTarget *dtar= &dvar->targets[0];
01240     Object *ob= (Object *)dtar_id_ensure_proxy_from(dtar->id);
01241     bPoseChannel *pchan;
01242     float mat[4][4];
01243     float oldEul[3] = {0.0f,0.0f,0.0f};
01244     short useEulers=0, rotOrder=ROT_MODE_EUL;
01245     
01246     /* check if this target has valid data */
01247     if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) {
01248         /* invalid target, so will not have enough targets */
01249         driver->flag |= DRIVER_FLAG_INVALID;
01250         return 0.0f;
01251     }
01252     
01253     /* try to get posechannel */
01254     pchan= get_pose_channel(ob->pose, dtar->pchan_name);
01255     
01256     /* check if object or bone, and get transform matrix accordingly 
01257      *  - "useEulers" code is used to prevent the problems associated with non-uniqueness
01258      *    of euler decomposition from matrices [#20870]
01259      *  - localspace is for [#21384], where parent results are not wanted
01260      *    but local-consts is for all the common "corrective-shapes-for-limbs" situations
01261      */
01262     if (pchan) {
01263         /* bone */
01264         if (pchan->rotmode > 0) {
01265             copy_v3_v3(oldEul, pchan->eul);
01266             rotOrder= pchan->rotmode;
01267             useEulers = 1;
01268         }
01269         
01270         if (dtar->flag & DTAR_FLAG_LOCALSPACE) {
01271             if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
01272                 /* just like how the constraints do it! */
01273                 copy_m4_m4(mat, pchan->pose_mat);
01274                 constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
01275             }
01276             else {
01277                 /* specially calculate local matrix, since chan_mat is not valid 
01278                  * since it stores delta transform of pose_mat so that deforms work
01279                  * so it cannot be used here for "transform" space
01280                  */
01281                 pchan_to_mat4(pchan, mat);
01282             }
01283         }
01284         else {
01285             /* worldspace matrix */
01286             mult_m4_m4m4(mat, ob->obmat, pchan->pose_mat);
01287         }
01288     }
01289     else {
01290         /* object */
01291         if (ob->rotmode > 0) {
01292             copy_v3_v3(oldEul, ob->rot);
01293             rotOrder= ob->rotmode;
01294             useEulers = 1;
01295         }
01296         
01297         if (dtar->flag & DTAR_FLAG_LOCALSPACE) {
01298             if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
01299                 /* just like how the constraints do it! */
01300                 copy_m4_m4(mat, ob->obmat);
01301                 constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
01302             }
01303             else {
01304                 /* transforms to matrix */
01305                 object_to_mat4(ob, mat);
01306             }
01307         }
01308         else {
01309             /* worldspace matrix - just the good-old one */
01310             copy_m4_m4(mat, ob->obmat);
01311         }
01312     }
01313     
01314     /* check which transform */
01315     if (dtar->transChan >= MAX_DTAR_TRANSCHAN_TYPES) {
01316         /* not valid channel */
01317         return 0.0f;
01318     }
01319     else if (dtar->transChan >= DTAR_TRANSCHAN_SCALEX) {
01320         /* extract scale, and choose the right axis */
01321         float scale[3];
01322         
01323         mat4_to_size(scale, mat);
01324         return scale[dtar->transChan - DTAR_TRANSCHAN_SCALEX];
01325     }
01326     else if (dtar->transChan >= DTAR_TRANSCHAN_ROTX) {
01327         /* extract rotation as eulers (if needed) 
01328          *  - definitely if rotation order isn't eulers already
01329          *  - if eulers, then we have 2 options:
01330          *      a) decompose transform matrix as required, then try to make eulers from
01331          *         there compatible with original values
01332          *      b) [NOT USED] directly use the original values (no decomposition) 
01333          *          - only an option for "transform space", if quality is really bad with a)
01334          */
01335         float eul[3];
01336         
01337         mat4_to_eulO(eul, rotOrder, mat);
01338         
01339         if (useEulers) {
01340             compatible_eul(eul, oldEul);
01341         }
01342         
01343         return eul[dtar->transChan - DTAR_TRANSCHAN_ROTX];
01344     }
01345     else {
01346         /* extract location and choose right axis */
01347         return mat[3][dtar->transChan];
01348     }
01349 }
01350 
01351 /* ......... */
01352 
01353 /* Table of Driver Varaiable Type Info Data */
01354 static DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = {
01355     BEGIN_DVAR_TYPEDEF(DVAR_TYPE_SINGLE_PROP)
01356         dvar_eval_singleProp, /* eval callback */
01357         1, /* number of targets used */
01358         {"Property"}, /* UI names for targets */
01359         {0} /* flags */
01360     END_DVAR_TYPEDEF,
01361     
01362     BEGIN_DVAR_TYPEDEF(DVAR_TYPE_ROT_DIFF)
01363         dvar_eval_rotDiff, /* eval callback */
01364         2, /* number of targets used */
01365         {"Bone 1", "Bone 2"}, /* UI names for targets */
01366         {DTAR_FLAG_STRUCT_REF|DTAR_FLAG_ID_OB_ONLY, DTAR_FLAG_STRUCT_REF|DTAR_FLAG_ID_OB_ONLY} /* flags */
01367     END_DVAR_TYPEDEF,
01368     
01369     BEGIN_DVAR_TYPEDEF(DVAR_TYPE_LOC_DIFF)
01370         dvar_eval_locDiff, /* eval callback */
01371         2, /* number of targets used */
01372         {"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */
01373         {DTAR_FLAG_STRUCT_REF|DTAR_FLAG_ID_OB_ONLY, DTAR_FLAG_STRUCT_REF|DTAR_FLAG_ID_OB_ONLY} /* flags */
01374     END_DVAR_TYPEDEF,
01375     
01376     BEGIN_DVAR_TYPEDEF(DVAR_TYPE_TRANSFORM_CHAN)
01377         dvar_eval_transChan, /* eval callback */
01378         1, /* number of targets used */
01379         {"Object/Bone"}, /* UI names for targets */
01380         {DTAR_FLAG_STRUCT_REF|DTAR_FLAG_ID_OB_ONLY} /* flags */
01381     END_DVAR_TYPEDEF,
01382 };
01383 
01384 /* Get driver variable typeinfo */
01385 static DriverVarTypeInfo *get_dvar_typeinfo (int type)
01386 {
01387     /* check if valid type */
01388     if ((type >= 0) && (type < MAX_DVAR_TYPES))
01389         return &dvar_types[type];
01390     else
01391         return NULL;
01392 }
01393 
01394 /* Driver API --------------------------------- */
01395 
01396 /* This frees the driver variable itself */
01397 void driver_free_variable (ChannelDriver *driver, DriverVar *dvar)
01398 {
01399     /* sanity checks */
01400     if (dvar == NULL)
01401         return;
01402         
01403     /* free target vars 
01404      *  - need to go over all of them, not just up to the ones that are used
01405      *    currently, since there may be some lingering RNA paths from 
01406      *    previous users needing freeing
01407      */
01408     DRIVER_TARGETS_LOOPER(dvar) 
01409     {
01410         /* free RNA path if applicable */
01411         if (dtar->rna_path)
01412             MEM_freeN(dtar->rna_path);
01413     }
01414     DRIVER_TARGETS_LOOPER_END
01415     
01416     /* remove the variable from the driver */
01417     BLI_freelinkN(&driver->variables, dvar);
01418 
01419 #ifdef WITH_PYTHON
01420     /* since driver variables are cached, the expression needs re-compiling too */
01421     if(driver->type==DRIVER_TYPE_PYTHON)
01422         driver->flag |= DRIVER_FLAG_RENAMEVAR;
01423 #endif
01424 }
01425 
01426 /* Change the type of driver variable */
01427 void driver_change_variable_type (DriverVar *dvar, int type)
01428 {
01429     DriverVarTypeInfo *dvti= get_dvar_typeinfo(type);
01430     
01431     /* sanity check */
01432     if (ELEM(NULL, dvar, dvti))
01433         return;
01434         
01435     /* set the new settings */
01436     dvar->type= type;
01437     dvar->num_targets= dvti->num_targets;
01438     
01439     /* make changes to the targets based on the defines for these types 
01440      * NOTE: only need to make sure the ones we're using here are valid...
01441      */
01442     DRIVER_TARGETS_USED_LOOPER(dvar)
01443     {
01444         int flags = dvti->target_flags[tarIndex];
01445         
01446         /* store the flags */
01447         dtar->flag = flags;
01448         
01449         /* object ID types only, or idtype not yet initialised*/
01450         if ((flags & DTAR_FLAG_ID_OB_ONLY) || (dtar->idtype == 0))
01451             dtar->idtype= ID_OB;
01452     }
01453     DRIVER_TARGETS_LOOPER_END
01454 }
01455 
01456 /* Add a new driver variable */
01457 DriverVar *driver_add_new_variable (ChannelDriver *driver)
01458 {
01459     DriverVar *dvar;
01460     
01461     /* sanity checks */
01462     if (driver == NULL)
01463         return NULL;
01464         
01465     /* make a new variable */
01466     dvar= MEM_callocN(sizeof(DriverVar), "DriverVar");
01467     BLI_addtail(&driver->variables, dvar);
01468     
01469     /* give the variable a 'unique' name */
01470     strcpy(dvar->name, "var");
01471     BLI_uniquename(&driver->variables, dvar, "var", '_', offsetof(DriverVar, name), sizeof(dvar->name));
01472     
01473     /* set the default type to 'single prop' */
01474     driver_change_variable_type(dvar, DVAR_TYPE_SINGLE_PROP);
01475     
01476 #ifdef WITH_PYTHON
01477     /* since driver variables are cached, the expression needs re-compiling too */
01478     if (driver->type==DRIVER_TYPE_PYTHON)
01479         driver->flag |= DRIVER_FLAG_RENAMEVAR;
01480 #endif
01481 
01482     /* return the target */
01483     return dvar;
01484 }
01485 
01486 /* This frees the driver itself */
01487 void fcurve_free_driver(FCurve *fcu)
01488 {
01489     ChannelDriver *driver;
01490     DriverVar *dvar, *dvarn;
01491     
01492     /* sanity checks */
01493     if ELEM(NULL, fcu, fcu->driver)
01494         return;
01495     driver= fcu->driver;
01496     
01497     /* free driver targets */
01498     for (dvar= driver->variables.first; dvar; dvar= dvarn) {
01499         dvarn= dvar->next;
01500         driver_free_variable(driver, dvar);
01501     }
01502 
01503 #ifdef WITH_PYTHON
01504     /* free compiled driver expression */
01505     if (driver->expr_comp)
01506         BPY_DECREF(driver->expr_comp);
01507 #endif
01508 
01509     /* free driver itself, then set F-Curve's point to this to NULL (as the curve may still be used) */
01510     MEM_freeN(driver);
01511     fcu->driver= NULL;
01512 }
01513 
01514 /* This makes a copy of the given driver */
01515 ChannelDriver *fcurve_copy_driver (ChannelDriver *driver)
01516 {
01517     ChannelDriver *ndriver;
01518     DriverVar *dvar;
01519     
01520     /* sanity checks */
01521     if (driver == NULL)
01522         return NULL;
01523         
01524     /* copy all data */
01525     ndriver= MEM_dupallocN(driver);
01526     ndriver->expr_comp= NULL;
01527     
01528     /* copy variables */
01529     ndriver->variables.first= ndriver->variables.last= NULL;
01530     BLI_duplicatelist(&ndriver->variables, &driver->variables);
01531     
01532     for (dvar= ndriver->variables.first; dvar; dvar= dvar->next) {  
01533         /* need to go over all targets so that we don't leave any dangling paths */
01534         DRIVER_TARGETS_LOOPER(dvar) 
01535         {   
01536             /* make a copy of target's rna path if available */
01537             if (dtar->rna_path)
01538                 dtar->rna_path = MEM_dupallocN(dtar->rna_path);
01539         }
01540         DRIVER_TARGETS_LOOPER_END
01541     }
01542     
01543     /* return the new driver */
01544     return ndriver;
01545 }
01546 
01547 /* Driver Evaluation -------------------------- */
01548 
01549 /* Evaluate a Driver Variable to get a value that contributes to the final */
01550 float driver_get_variable_value (ChannelDriver *driver, DriverVar *dvar)
01551 {
01552     DriverVarTypeInfo *dvti;
01553 
01554     /* sanity check */
01555     if (ELEM(NULL, driver, dvar))
01556         return 0.0f;
01557     
01558     /* call the relevant callbacks to get the variable value 
01559      * using the variable type info, storing the obtained value
01560      * in dvar->curval so that drivers can be debugged
01561      */
01562     dvti= get_dvar_typeinfo(dvar->type);
01563     
01564     if (dvti && dvti->get_value)
01565         dvar->curval= dvti->get_value(driver, dvar);
01566     else
01567         dvar->curval= 0.0f;
01568     
01569     return dvar->curval;
01570 }
01571 
01572 /* Evaluate an Channel-Driver to get a 'time' value to use instead of "evaltime"
01573  *  - "evaltime" is the frame at which F-Curve is being evaluated
01574  *  - has to return a float value 
01575  */
01576 static float evaluate_driver (ChannelDriver *driver, const float evaltime)
01577 {
01578     DriverVar *dvar;
01579     
01580     /* check if driver can be evaluated */
01581     if (driver->flag & DRIVER_FLAG_INVALID)
01582         return 0.0f;
01583     
01584     switch (driver->type) {
01585         case DRIVER_TYPE_AVERAGE: /* average values of driver targets */
01586         case DRIVER_TYPE_SUM: /* sum values of driver targets */
01587         {
01588             /* check how many variables there are first (i.e. just one?) */
01589             if (driver->variables.first == driver->variables.last) {
01590                 /* just one target, so just use that */
01591                 dvar= driver->variables.first;
01592                 driver->curval= driver_get_variable_value(driver, dvar);
01593             }
01594             else {
01595                 /* more than one target, so average the values of the targets */
01596                 float value = 0.0f;
01597                 int tot = 0;
01598                 
01599                 /* loop through targets, adding (hopefully we don't get any overflow!) */
01600                 for (dvar= driver->variables.first; dvar; dvar=dvar->next) {
01601                     value += driver_get_variable_value(driver, dvar);
01602                     tot++;
01603                 }
01604                 
01605                 /* perform operations on the total if appropriate */
01606                 if (driver->type == DRIVER_TYPE_AVERAGE)
01607                     driver->curval= (value / (float)tot);
01608                 else
01609                     driver->curval= value;
01610             }
01611         }
01612             break;
01613             
01614         case DRIVER_TYPE_MIN: /* smallest value */
01615         case DRIVER_TYPE_MAX: /* largest value */
01616         {
01617             float value = 0.0f;
01618             
01619             /* loop through the variables, getting the values and comparing them to existing ones */
01620             for (dvar= driver->variables.first; dvar; dvar= dvar->next) {
01621                 /* get value */
01622                 float tmp_val= driver_get_variable_value(driver, dvar);
01623                 
01624                 /* store this value if appropriate */
01625                 if (dvar->prev) {
01626                     /* check if greater/smaller than the baseline */
01627                     if (driver->type == DRIVER_TYPE_MAX) {
01628                         /* max? */
01629                         if (tmp_val > value) 
01630                             value= tmp_val;
01631                     }
01632                     else {
01633                         /* min? */
01634                         if (tmp_val < value) 
01635                             value= tmp_val;
01636                     }
01637                 }
01638                 else {
01639                     /* first item - make this the baseline for comparisons */
01640                     value= tmp_val;
01641                 }
01642             }
01643             
01644             /* store value in driver */
01645             driver->curval= value;
01646         }
01647             break;
01648             
01649         case DRIVER_TYPE_PYTHON: /* expression */
01650         {
01651 #ifdef WITH_PYTHON
01652             /* check for empty or invalid expression */
01653             if ( (driver->expression[0] == '\0') ||
01654                  (driver->flag & DRIVER_FLAG_INVALID) )
01655             {
01656                 driver->curval= 0.0f;
01657             }
01658             else
01659             {
01660                 /* this evaluates the expression using Python,and returns its result:
01661                  *  - on errors it reports, then returns 0.0f
01662                  */
01663                 driver->curval= BPY_driver_exec(driver, evaltime);
01664             }
01665 #else /* WITH_PYTHON*/
01666         (void)evaltime;
01667 #endif /* WITH_PYTHON*/
01668         }
01669             break;
01670         
01671         default:
01672         {
01673             /* special 'hack' - just use stored value 
01674              *  This is currently used as the mechanism which allows animated settings to be able
01675              *  to be changed via the UI.
01676              */
01677         }
01678     }
01679     
01680     /* return value for driver */
01681     return driver->curval;
01682 }
01683 
01684 /* ***************************** Curve Calculations ********************************* */
01685 
01686 /* The total length of the handles is not allowed to be more
01687  * than the horizontal distance between (v1-v4).
01688  * This is to prevent curve loops.
01689 */
01690 void correct_bezpart (float *v1, float *v2, float *v3, float *v4)
01691 {
01692     float h1[2], h2[2], len1, len2, len, fac;
01693     
01694     /* calculate handle deltas */
01695     h1[0]= v1[0] - v2[0];
01696     h1[1]= v1[1] - v2[1];
01697     
01698     h2[0]= v4[0] - v3[0];
01699     h2[1]= v4[1] - v3[1];
01700     
01701     /* calculate distances: 
01702      *  - len   = span of time between keyframes 
01703      *  - len1  = length of handle of start key
01704      *  - len2  = length of handle of end key
01705      */
01706     len= v4[0]- v1[0];
01707     len1= fabsf(h1[0]);
01708     len2= fabsf(h2[0]);
01709     
01710     /* if the handles have no length, no need to do any corrections */
01711     if ((len1+len2) == 0.0f) 
01712         return;
01713         
01714     /* the two handles cross over each other, so force them
01715      * apart using the proportion they overlap 
01716      */
01717     if ((len1+len2) > len) {
01718         fac= len / (len1+len2);
01719         
01720         v2[0]= (v1[0] - fac*h1[0]);
01721         v2[1]= (v1[1] - fac*h1[1]);
01722         
01723         v3[0]= (v4[0] - fac*h2[0]);
01724         v3[1]= (v4[1] - fac*h2[1]);
01725     }
01726 }
01727 
01728 /* find root ('zero') */
01729 static int findzero (float x, float q0, float q1, float q2, float q3, float *o)
01730 {
01731     double c0, c1, c2, c3, a, b, c, p, q, d, t, phi;
01732     int nr= 0;
01733 
01734     c0= q0 - x;
01735     c1= 3.0f * (q1 - q0);
01736     c2= 3.0f * (q0 - 2.0f*q1 + q2);
01737     c3= q3 - q0 + 3.0f * (q1 - q2);
01738     
01739     if (c3 != 0.0) {
01740         a= c2/c3;
01741         b= c1/c3;
01742         c= c0/c3;
01743         a= a/3;
01744         
01745         p= b/3 - a*a;
01746         q= (2*a*a*a - a*b + c) / 2;
01747         d= q*q + p*p*p;
01748         
01749         if (d > 0.0) {
01750             t= sqrt(d);
01751             o[0]= (float)(sqrt3d(-q+t) + sqrt3d(-q-t) - a);
01752             
01753             if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) return 1;
01754             else return 0;
01755         }
01756         else if (d == 0.0) {
01757             t= sqrt3d(-q);
01758             o[0]= (float)(2*t - a);
01759             
01760             if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) nr++;
01761             o[nr]= (float)(-t-a);
01762             
01763             if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) return nr+1;
01764             else return nr;
01765         }
01766         else {
01767             phi= acos(-q / sqrt(-(p*p*p)));
01768             t= sqrt(-p);
01769             p= cos(phi/3);
01770             q= sqrt(3 - 3*p*p);
01771             o[0]= (float)(2*t*p - a);
01772             
01773             if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) nr++;
01774             o[nr]= (float)(-t * (p + q) - a);
01775             
01776             if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) nr++;
01777             o[nr]= (float)(-t * (p - q) - a);
01778             
01779             if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) return nr+1;
01780             else return nr;
01781         }
01782     }
01783     else {
01784         a=c2;
01785         b=c1;
01786         c=c0;
01787         
01788         if (a != 0.0) {
01789             // discriminant
01790             p= b*b - 4*a*c;
01791             
01792             if (p > 0) {
01793                 p= sqrt(p);
01794                 o[0]= (float)((-b-p) / (2 * a));
01795                 
01796                 if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) nr++;
01797                 o[nr]= (float)((-b+p)/(2*a));
01798                 
01799                 if ((o[nr] >= (float)SMALL) && (o[nr] <= 1.000001f)) return nr+1;
01800                 else return nr;
01801             }
01802             else if (p == 0) {
01803                 o[0]= (float)(-b / (2 * a));
01804                 if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) return 1;
01805                 else return 0;
01806             }
01807         }
01808         else if (b != 0.0) {
01809             o[0]= (float)(-c/b);
01810             
01811             if ((o[0] >= (float)SMALL) && (o[0] <= 1.000001f)) return 1;
01812             else return 0;
01813         }
01814         else if (c == 0.0) {
01815             o[0]= 0.0;
01816             return 1;
01817         }
01818         
01819         return 0;   
01820     }
01821 }
01822 
01823 static void berekeny (float f1, float f2, float f3, float f4, float *o, int b)
01824 {
01825     float t, c0, c1, c2, c3;
01826     int a;
01827 
01828     c0= f1;
01829     c1= 3.0f * (f2 - f1);
01830     c2= 3.0f * (f1 - 2.0f*f2 + f3);
01831     c3= f4 - f1 + 3.0f * (f2 - f3);
01832     
01833     for (a=0; a < b; a++) {
01834         t= o[a];
01835         o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3;
01836     }
01837 }
01838 
01839 #if 0
01840 static void berekenx (float *f, float *o, int b)
01841 {
01842     float t, c0, c1, c2, c3;
01843     int a;
01844 
01845     c0= f[0];
01846     c1= 3.0f * (f[3] - f[0]);
01847     c2= 3.0f * (f[0] - 2.0f*f[3] + f[6]);
01848     c3= f[9] - f[0] + 3.0f * (f[3] - f[6]);
01849     
01850     for (a=0; a < b; a++) {
01851         t= o[a];
01852         o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3;
01853     }
01854 }
01855 #endif
01856 
01857 
01858 /* -------------------------- */
01859 
01860 /* Calculate F-Curve value for 'evaltime' using BezTriple keyframes */
01861 static float fcurve_eval_keyframes (FCurve *fcu, BezTriple *bezts, float evaltime)
01862 {
01863     BezTriple *bezt, *prevbezt, *lastbezt;
01864     float v1[2], v2[2], v3[2], v4[2], opl[32], dx, fac;
01865     unsigned int a;
01866     int b;
01867     float cvalue = 0.0f;
01868     
01869     /* get pointers */
01870     a= fcu->totvert-1;
01871     prevbezt= bezts;
01872     bezt= prevbezt+1;
01873     lastbezt= prevbezt + a;
01874     
01875     /* evaluation time at or past endpoints? */
01876     if (prevbezt->vec[1][0] >= evaltime) 
01877     {
01878         /* before or on first keyframe */
01879         if ( (fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (prevbezt->ipo != BEZT_IPO_CONST) &&
01880             !(fcu->flag & FCURVE_DISCRETE_VALUES) ) 
01881         {
01882             /* linear or bezier interpolation */
01883             if (prevbezt->ipo==BEZT_IPO_LIN) 
01884             {
01885                 /* Use the next center point instead of our own handle for
01886                  * linear interpolated extrapolate 
01887                  */
01888                 if (fcu->totvert == 1) 
01889                     cvalue= prevbezt->vec[1][1];
01890                 else 
01891                 {
01892                     bezt = prevbezt+1;
01893                     dx= prevbezt->vec[1][0] - evaltime;
01894                     fac= bezt->vec[1][0] - prevbezt->vec[1][0];
01895                     
01896                     /* prevent division by zero */
01897                     if (fac) {
01898                         fac= (bezt->vec[1][1] - prevbezt->vec[1][1]) / fac;
01899                         cvalue= prevbezt->vec[1][1] - (fac * dx);
01900                     }
01901                     else 
01902                         cvalue= prevbezt->vec[1][1];
01903                 }
01904             } 
01905             else 
01906             {
01907                 /* Use the first handle (earlier) of first BezTriple to calculate the
01908                  * gradient and thus the value of the curve at evaltime
01909                  */
01910                 dx= prevbezt->vec[1][0] - evaltime;
01911                 fac= prevbezt->vec[1][0] - prevbezt->vec[0][0];
01912                 
01913                 /* prevent division by zero */
01914                 if (fac) {
01915                     fac= (prevbezt->vec[1][1] - prevbezt->vec[0][1]) / fac;
01916                     cvalue= prevbezt->vec[1][1] - (fac * dx);
01917                 }
01918                 else 
01919                     cvalue= prevbezt->vec[1][1];
01920             }
01921         }
01922         else 
01923         {
01924             /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, 
01925              * so just extend first keyframe's value 
01926              */
01927             cvalue= prevbezt->vec[1][1];
01928         }
01929     }
01930     else if (lastbezt->vec[1][0] <= evaltime) 
01931     {
01932         /* after or on last keyframe */
01933         if ( (fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (lastbezt->ipo != BEZT_IPO_CONST) &&
01934             !(fcu->flag & FCURVE_DISCRETE_VALUES) ) 
01935         {
01936             /* linear or bezier interpolation */
01937             if (lastbezt->ipo==BEZT_IPO_LIN) 
01938             {
01939                 /* Use the next center point instead of our own handle for
01940                  * linear interpolated extrapolate 
01941                  */
01942                 if (fcu->totvert == 1) 
01943                     cvalue= lastbezt->vec[1][1];
01944                 else 
01945                 {
01946                     prevbezt = lastbezt - 1;
01947                     dx= evaltime - lastbezt->vec[1][0];
01948                     fac= lastbezt->vec[1][0] - prevbezt->vec[1][0];
01949                     
01950                     /* prevent division by zero */
01951                     if (fac) {
01952                         fac= (lastbezt->vec[1][1] - prevbezt->vec[1][1]) / fac;
01953                         cvalue= lastbezt->vec[1][1] + (fac * dx);
01954                     }
01955                     else 
01956                         cvalue= lastbezt->vec[1][1];
01957                 }
01958             } 
01959             else 
01960             {
01961                 /* Use the gradient of the second handle (later) of last BezTriple to calculate the
01962                  * gradient and thus the value of the curve at evaltime
01963                  */
01964                 dx= evaltime - lastbezt->vec[1][0];
01965                 fac= lastbezt->vec[2][0] - lastbezt->vec[1][0];
01966                 
01967                 /* prevent division by zero */
01968                 if (fac) {
01969                     fac= (lastbezt->vec[2][1] - lastbezt->vec[1][1]) / fac;
01970                     cvalue= lastbezt->vec[1][1] + (fac * dx);
01971                 }
01972                 else 
01973                     cvalue= lastbezt->vec[1][1];
01974             }
01975         }
01976         else 
01977         {
01978             /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, 
01979              * so just extend last keyframe's value 
01980              */
01981             cvalue= lastbezt->vec[1][1];
01982         }
01983     }
01984     else 
01985     {
01986         /* evaltime occurs somewhere in the middle of the curve */
01987         for (a=0; prevbezt && bezt && (a < fcu->totvert-1); a++, prevbezt=bezt, bezt++) 
01988         {
01989             /* use if the key is directly on the frame, rare cases this is needed else we get 0.0 instead. */
01990             if(fabs(bezt->vec[1][0] - evaltime) < SMALL_NUMBER) {
01991                 cvalue= bezt->vec[1][1];
01992             }
01993             /* evaltime occurs within the interval defined by these two keyframes */
01994             else if ((prevbezt->vec[1][0] <= evaltime) && (bezt->vec[1][0] >= evaltime))
01995             {
01996                 /* value depends on interpolation mode */
01997                 if ((prevbezt->ipo == BEZT_IPO_CONST) || (fcu->flag & FCURVE_DISCRETE_VALUES))
01998                 {
01999                     /* constant (evaltime not relevant, so no interpolation needed) */
02000                     cvalue= prevbezt->vec[1][1];
02001                 }
02002                 else if (prevbezt->ipo == BEZT_IPO_LIN) 
02003                 {
02004                     /* linear - interpolate between values of the two keyframes */
02005                     fac= bezt->vec[1][0] - prevbezt->vec[1][0];
02006                     
02007                     /* prevent division by zero */
02008                     if (fac) {
02009                         fac= (evaltime - prevbezt->vec[1][0]) / fac;
02010                         cvalue= prevbezt->vec[1][1] + (fac * (bezt->vec[1][1] - prevbezt->vec[1][1]));
02011                     }
02012                     else
02013                         cvalue= prevbezt->vec[1][1];
02014                 }
02015                 else 
02016                 {
02017                     /* bezier interpolation */
02018                         /* v1,v2 are the first keyframe and its 2nd handle */
02019                     v1[0]= prevbezt->vec[1][0];
02020                     v1[1]= prevbezt->vec[1][1];
02021                     v2[0]= prevbezt->vec[2][0];
02022                     v2[1]= prevbezt->vec[2][1];
02023                         /* v3,v4 are the last keyframe's 1st handle + the last keyframe */
02024                     v3[0]= bezt->vec[0][0];
02025                     v3[1]= bezt->vec[0][1];
02026                     v4[0]= bezt->vec[1][0];
02027                     v4[1]= bezt->vec[1][1];
02028                     
02029                     /* adjust handles so that they don't overlap (forming a loop) */
02030                     correct_bezpart(v1, v2, v3, v4);
02031                     
02032                     /* try to get a value for this position - if failure, try another set of points */
02033                     b= findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl);
02034                     if (b) {
02035                         berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1);
02036                         cvalue= opl[0];
02037                         break;
02038                     }
02039                 }
02040             }
02041         }
02042     }
02043     
02044     /* return value */
02045     return cvalue;
02046 }
02047 
02048 /* Calculate F-Curve value for 'evaltime' using FPoint samples */
02049 static float fcurve_eval_samples (FCurve *fcu, FPoint *fpts, float evaltime)
02050 {
02051     FPoint *prevfpt, *lastfpt, *fpt;
02052     float cvalue= 0.0f;
02053     
02054     /* get pointers */
02055     prevfpt= fpts;
02056     lastfpt= prevfpt + fcu->totvert-1;
02057     
02058     /* evaluation time at or past endpoints? */
02059     if (prevfpt->vec[0] >= evaltime) {
02060         /* before or on first sample, so just extend value */
02061         cvalue= prevfpt->vec[1];
02062     }
02063     else if (lastfpt->vec[0] <= evaltime) {
02064         /* after or on last sample, so just extend value */
02065         cvalue= lastfpt->vec[1];
02066     }
02067     else {
02068         float t= (float)abs(evaltime - (int)evaltime);
02069         
02070         /* find the one on the right frame (assume that these are spaced on 1-frame intervals) */
02071         fpt= prevfpt + (int)(evaltime - prevfpt->vec[0]);
02072         
02073         /* if not exactly on the frame, perform linear interpolation with the next one */
02074         if (t != 0.0f) 
02075             cvalue= interpf(fpt->vec[1], (fpt+1)->vec[1], t);
02076         else
02077             cvalue= fpt->vec[1];
02078     }
02079     
02080     /* return value */
02081     return cvalue;
02082 }
02083 
02084 /* ***************************** F-Curve - Evaluation ********************************* */
02085 
02086 /* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime") 
02087  * Note: this is also used for drivers
02088  */
02089 float evaluate_fcurve (FCurve *fcu, float evaltime)
02090 {
02091     float cvalue= 0.0f;
02092     float devaltime;
02093     
02094     /* if there is a driver (only if this F-Curve is acting as 'driver'), evaluate it to find value to use as "evaltime" 
02095      * since drivers essentially act as alternative input (i.e. in place of 'time') for F-Curves
02096      *  - this value will also be returned as the value of the 'curve', if there are no keyframes
02097      */
02098     if (fcu->driver) {
02099         /* evaltime now serves as input for the curve */
02100         evaltime= cvalue= evaluate_driver(fcu->driver, evaltime);
02101     }
02102     
02103     /* evaluate modifiers which modify time to evaluate the base curve at */
02104     devaltime= evaluate_time_fmodifiers(&fcu->modifiers, fcu, cvalue, evaltime);
02105     
02106     /* evaluate curve-data 
02107      *  - 'devaltime' instead of 'evaltime', as this is the time that the last time-modifying 
02108      *    F-Curve modifier on the stack requested the curve to be evaluated at
02109      */
02110     if (fcu->bezt)
02111         cvalue= fcurve_eval_keyframes(fcu, fcu->bezt, devaltime);
02112     else if (fcu->fpt)
02113         cvalue= fcurve_eval_samples(fcu, fcu->fpt, devaltime);
02114     
02115     /* evaluate modifiers */
02116     evaluate_value_fmodifiers(&fcu->modifiers, fcu, &cvalue, evaltime);
02117     
02118     /* if curve can only have integral values, perform truncation (i.e. drop the decimal part)
02119      * here so that the curve can be sampled correctly
02120      */
02121     if (fcu->flag & FCURVE_INT_VALUES)
02122         cvalue= floorf(cvalue + 0.5f);
02123     
02124     /* return evaluated value */
02125     return cvalue;
02126 }
02127 
02128 /* Calculate the value of the given F-Curve at the given frame, and set its curval */
02129 void calculate_fcurve (FCurve *fcu, float ctime)
02130 {
02131     /* only calculate + set curval (overriding the existing value) if curve has 
02132      * any data which warrants this...
02133      */
02134     if ( (fcu->totvert) || (fcu->driver && !(fcu->driver->flag & DRIVER_FLAG_INVALID)) ||
02135          list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) )
02136     {
02137         /* calculate and set curval (evaluates driver too if necessary) */
02138         fcu->curval= evaluate_fcurve(fcu, ctime);
02139     }
02140 }
02141