Blender V2.61 - r43446
|
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