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 00033 #include <stdio.h> 00034 #include <string.h> 00035 #include <stddef.h> 00036 #include <float.h> 00037 #include <math.h> 00038 00039 #include "MEM_guardedalloc.h" 00040 00041 #include "BLI_blenlib.h" 00042 #include "BLI_dynstr.h" 00043 #include "BLI_utildefines.h" 00044 00045 #include "DNA_anim_types.h" 00046 #include "DNA_lamp_types.h" 00047 #include "DNA_material_types.h" 00048 #include "DNA_scene_types.h" 00049 #include "DNA_texture_types.h" 00050 #include "DNA_world_types.h" 00051 00052 #include "BKE_animsys.h" 00053 #include "BKE_action.h" 00054 #include "BKE_depsgraph.h" 00055 #include "BKE_fcurve.h" 00056 #include "BKE_nla.h" 00057 #include "BKE_global.h" 00058 #include "BKE_main.h" 00059 #include "BKE_library.h" 00060 #include "BKE_report.h" 00061 #include "BKE_utildefines.h" 00062 00063 #include "RNA_access.h" 00064 00065 #include "nla_private.h" 00066 00067 /* ***************************************** */ 00068 /* AnimData API */ 00069 00070 /* Getter/Setter -------------------------------------------- */ 00071 00072 /* Check if ID can have AnimData */ 00073 short id_type_can_have_animdata (ID *id) 00074 { 00075 /* sanity check */ 00076 if (id == NULL) 00077 return 0; 00078 00079 /* Only some ID-blocks have this info for now */ 00080 // TODO: finish adding this for the other blocktypes 00081 switch (GS(id->name)) { 00082 /* has AnimData */ 00083 case ID_OB: 00084 case ID_ME: case ID_MB: case ID_CU: case ID_AR: case ID_LT: 00085 case ID_KE: 00086 case ID_PA: 00087 case ID_MA: case ID_TE: case ID_NT: 00088 case ID_LA: case ID_CA: case ID_WO: 00089 case ID_SPK: 00090 case ID_SCE: 00091 { 00092 return 1; 00093 } 00094 00095 /* no AnimData */ 00096 default: 00097 return 0; 00098 } 00099 } 00100 00101 00102 /* Get AnimData from the given ID-block. In order for this to work, we assume that 00103 * the AnimData pointer is stored immediately after the given ID-block in the struct, 00104 * as per IdAdtTemplate. 00105 */ 00106 AnimData *BKE_animdata_from_id (ID *id) 00107 { 00108 /* only some ID-blocks have this info for now, so we cast the 00109 * types that do to be of type IdAdtTemplate, and extract the 00110 * AnimData that way 00111 */ 00112 if (id_type_can_have_animdata(id)) { 00113 IdAdtTemplate *iat= (IdAdtTemplate *)id; 00114 return iat->adt; 00115 } 00116 else 00117 return NULL; 00118 } 00119 00120 /* Add AnimData to the given ID-block. In order for this to work, we assume that 00121 * the AnimData pointer is stored immediately after the given ID-block in the struct, 00122 * as per IdAdtTemplate. Also note that 00123 */ 00124 AnimData *BKE_id_add_animdata (ID *id) 00125 { 00126 /* Only some ID-blocks have this info for now, so we cast the 00127 * types that do to be of type IdAdtTemplate, and add the AnimData 00128 * to it using the template 00129 */ 00130 if (id_type_can_have_animdata(id)) { 00131 IdAdtTemplate *iat= (IdAdtTemplate *)id; 00132 00133 /* check if there's already AnimData, in which case, don't add */ 00134 if (iat->adt == NULL) { 00135 AnimData *adt; 00136 00137 /* add animdata */ 00138 adt= iat->adt= MEM_callocN(sizeof(AnimData), "AnimData"); 00139 00140 /* set default settings */ 00141 adt->act_influence= 1.0f; 00142 } 00143 00144 return iat->adt; 00145 } 00146 else 00147 return NULL; 00148 } 00149 00150 /* Action Setter --------------------------------------- */ 00151 00152 /* Called when user tries to change the active action of an AnimData block (via RNA, Outliner, etc.) */ 00153 short BKE_animdata_set_action (ReportList *reports, ID *id, bAction *act) 00154 { 00155 AnimData *adt = BKE_animdata_from_id(id); 00156 short ok = 0; 00157 00158 /* animdata validity check */ 00159 if (adt == NULL) { 00160 BKE_report(reports, RPT_WARNING, "No AnimData to set action on"); 00161 return ok; 00162 } 00163 00164 /* active action is only editable when it is not a tweaking strip 00165 * see rna_AnimData_action_editable() in rna_animation.c 00166 */ 00167 if ((adt->flag & ADT_NLA_EDIT_ON) || (adt->actstrip) || (adt->tmpact)) { 00168 /* cannot remove, otherwise things turn to custard */ 00169 BKE_report(reports, RPT_ERROR, "Cannot change action, as it is still being edited in NLA"); 00170 return ok; 00171 } 00172 00173 /* manage usercount for current action */ 00174 if (adt->action) 00175 id_us_min((ID*)adt->action); 00176 00177 /* assume that AnimData's action can in fact be edited... */ 00178 if (act) { 00179 /* action must have same type as owner */ 00180 if (ELEM(act->idroot, 0, GS(id->name))) { 00181 /* can set */ 00182 adt->action = act; 00183 id_us_plus((ID*)adt->action); 00184 ok = 1; 00185 } 00186 else { 00187 /* cannot set */ 00188 BKE_reportf(reports, RPT_ERROR, 00189 "Couldn't set Action '%s' onto ID '%s', as it doesn't have suitably rooted paths for this purpose", 00190 act->id.name+2, id->name); 00191 //ok = 0; 00192 } 00193 } 00194 else { 00195 /* just clearing the action... */ 00196 adt->action = NULL; 00197 ok = 1; 00198 } 00199 00200 return ok; 00201 } 00202 00203 /* Freeing -------------------------------------------- */ 00204 00205 /* Free AnimData used by the nominated ID-block, and clear ID-block's AnimData pointer */ 00206 void BKE_free_animdata (ID *id) 00207 { 00208 /* Only some ID-blocks have this info for now, so we cast the 00209 * types that do to be of type IdAdtTemplate 00210 */ 00211 if (id_type_can_have_animdata(id)) { 00212 IdAdtTemplate *iat= (IdAdtTemplate *)id; 00213 AnimData *adt= iat->adt; 00214 00215 /* check if there's any AnimData to start with */ 00216 if (adt) { 00217 /* unlink action (don't free, as it's in its own list) */ 00218 if (adt->action) 00219 adt->action->id.us--; 00220 /* same goes for the temporarily displaced action */ 00221 if (adt->tmpact) 00222 adt->tmpact->id.us--; 00223 00224 /* free nla data */ 00225 free_nladata(&adt->nla_tracks); 00226 00227 /* free drivers - stored as a list of F-Curves */ 00228 free_fcurves(&adt->drivers); 00229 00230 /* free overrides */ 00231 // TODO... 00232 00233 /* free animdata now */ 00234 MEM_freeN(adt); 00235 iat->adt= NULL; 00236 } 00237 } 00238 } 00239 00240 /* Freeing -------------------------------------------- */ 00241 00242 /* Make a copy of the given AnimData - to be used when copying datablocks */ 00243 AnimData *BKE_copy_animdata (AnimData *adt, const short do_action) 00244 { 00245 AnimData *dadt; 00246 00247 /* sanity check before duplicating struct */ 00248 if (adt == NULL) 00249 return NULL; 00250 dadt= MEM_dupallocN(adt); 00251 00252 /* make a copy of action - at worst, user has to delete copies... */ 00253 if (do_action) { 00254 dadt->action= copy_action(adt->action); 00255 dadt->tmpact= copy_action(adt->tmpact); 00256 } 00257 else { 00258 id_us_plus((ID *)dadt->action); 00259 id_us_plus((ID *)dadt->tmpact); 00260 } 00261 00262 /* duplicate NLA data */ 00263 copy_nladata(&dadt->nla_tracks, &adt->nla_tracks); 00264 00265 /* duplicate drivers (F-Curves) */ 00266 copy_fcurves(&dadt->drivers, &adt->drivers); 00267 00268 /* don't copy overrides */ 00269 dadt->overrides.first= dadt->overrides.last= NULL; 00270 00271 /* return */ 00272 return dadt; 00273 } 00274 00275 int BKE_copy_animdata_id (ID *id_to, ID *id_from, const short do_action) 00276 { 00277 AnimData *adt; 00278 00279 if ((id_to && id_from) && (GS(id_to->name) != GS(id_from->name))) 00280 return 0; 00281 00282 BKE_free_animdata(id_to); 00283 00284 adt = BKE_animdata_from_id(id_from); 00285 if (adt) { 00286 IdAdtTemplate *iat = (IdAdtTemplate *)id_to; 00287 iat->adt= BKE_copy_animdata(adt, do_action); 00288 } 00289 00290 return 1; 00291 } 00292 00293 void BKE_copy_animdata_id_action(ID *id) 00294 { 00295 AnimData *adt= BKE_animdata_from_id(id); 00296 if (adt) { 00297 if (adt->action) { 00298 id_us_min((ID *)adt->action); 00299 adt->action= copy_action(adt->action); 00300 } 00301 if (adt->tmpact) { 00302 id_us_min((ID *)adt->tmpact); 00303 adt->tmpact= copy_action(adt->tmpact); 00304 } 00305 } 00306 } 00307 00308 /* Make Local -------------------------------------------- */ 00309 00310 static void make_local_strips(ListBase *strips) 00311 { 00312 NlaStrip *strip; 00313 00314 for (strip=strips->first; strip; strip=strip->next) { 00315 if (strip->act) make_local_action(strip->act); 00316 if (strip->remap && strip->remap->target) make_local_action(strip->remap->target); 00317 00318 make_local_strips(&strip->strips); 00319 } 00320 } 00321 00322 /* Use local copy instead of linked copy of various ID-blocks */ 00323 void BKE_animdata_make_local(AnimData *adt) 00324 { 00325 NlaTrack *nlt; 00326 00327 /* Actions - Active and Temp */ 00328 if (adt->action) make_local_action(adt->action); 00329 if (adt->tmpact) make_local_action(adt->tmpact); 00330 /* Remaps */ 00331 if (adt->remap && adt->remap->target) make_local_action(adt->remap->target); 00332 00333 /* Drivers */ 00334 // TODO: need to remap the ID-targets too? 00335 00336 /* NLA Data */ 00337 for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next) 00338 make_local_strips(&nlt->strips); 00339 } 00340 00341 00342 /* When duplicating data (i.e. objects), drivers referring to the original data will 00343 * get updated to point to the duplicated data (if drivers belong to the new data) 00344 */ 00345 void BKE_relink_animdata (AnimData *adt) 00346 { 00347 /* sanity check */ 00348 if (adt == NULL) 00349 return; 00350 00351 /* drivers */ 00352 if (adt->drivers.first) { 00353 FCurve *fcu; 00354 00355 /* check each driver against all the base paths to see if any should go */ 00356 for (fcu= adt->drivers.first; fcu; fcu=fcu->next) { 00357 ChannelDriver *driver= fcu->driver; 00358 DriverVar *dvar; 00359 00360 /* driver variables */ 00361 for (dvar= driver->variables.first; dvar; dvar=dvar->next) { 00362 /* only change the used targets, since the others will need fixing manually anyway */ 00363 DRIVER_TARGETS_USED_LOOPER(dvar) 00364 { 00365 if (dtar->id && dtar->id->newid) { 00366 dtar->id= dtar->id->newid; 00367 } 00368 } 00369 DRIVER_TARGETS_LOOPER_END 00370 } 00371 } 00372 } 00373 } 00374 00375 /* Sub-ID Regrouping ------------------------------------------- */ 00376 00377 /* helper heuristic for determining if a path is compatible with the basepath 00378 * < path: (str) full RNA-path from some data (usually an F-Curve) to compare 00379 * < basepath: (str) shorter path fragment to look for 00380 * > returns (bool) whether there is a match 00381 */ 00382 static short animpath_matches_basepath (const char path[], const char basepath[]) 00383 { 00384 /* we need start of path to be basepath */ 00385 return (path && basepath) && (strstr(path, basepath) == path); 00386 } 00387 00388 /* Move F-Curves in src action to dst action, setting up all the necessary groups 00389 * for this to happen, but only if the F-Curves being moved have the appropriate 00390 * "base path". 00391 * - This is used when data moves from one datablock to another, causing the 00392 * F-Curves to need to be moved over too 00393 */ 00394 void action_move_fcurves_by_basepath (bAction *srcAct, bAction *dstAct, const char basepath[]) 00395 { 00396 FCurve *fcu, *fcn=NULL; 00397 00398 /* sanity checks */ 00399 if ELEM3(NULL, srcAct, dstAct, basepath) { 00400 if (G.f & G_DEBUG) { 00401 printf("ERROR: action_partition_fcurves_by_basepath(%p, %p, %p) has insufficient info to work with\n", 00402 (void *)srcAct, (void *)dstAct, (void *)basepath); 00403 } 00404 return; 00405 } 00406 00407 /* clear 'temp' flags on all groups in src, as we'll be needing them later 00408 * to identify groups that we've managed to empty out here 00409 */ 00410 action_groups_clear_tempflags(srcAct); 00411 00412 /* iterate over all src F-Curves, moving over the ones that need to be moved */ 00413 for (fcu = srcAct->curves.first; fcu; fcu = fcn) { 00414 /* store next pointer in case we move stuff */ 00415 fcn = fcu->next; 00416 00417 /* should F-Curve be moved over? 00418 * - we only need the start of the path to match basepath 00419 */ 00420 if (animpath_matches_basepath(fcu->rna_path, basepath)) { 00421 bActionGroup *agrp = NULL; 00422 00423 /* if grouped... */ 00424 if (fcu->grp) { 00425 /* make sure there will be a matching group on the other side for the migrants */ 00426 agrp = action_groups_find_named(dstAct, fcu->grp->name); 00427 00428 if (agrp == NULL) { 00429 /* add a new one with a similar name (usually will be the same though) */ 00430 agrp = action_groups_add_new(dstAct, fcu->grp->name); 00431 } 00432 00433 /* old groups should be tagged with 'temp' flags so they can be removed later 00434 * if we remove everything from them 00435 */ 00436 fcu->grp->flag |= AGRP_TEMP; 00437 } 00438 00439 /* perform the migration now */ 00440 action_groups_remove_channel(srcAct, fcu); 00441 00442 if (agrp) 00443 action_groups_add_channel(dstAct, agrp, fcu); 00444 else 00445 BLI_addtail(&dstAct->curves, fcu); 00446 } 00447 } 00448 00449 /* cleanup groups (if present) */ 00450 if (srcAct->groups.first) { 00451 bActionGroup *agrp, *grp=NULL; 00452 00453 for (agrp = srcAct->groups.first; agrp; agrp = grp) { 00454 grp = agrp->next; 00455 00456 /* only tagged groups need to be considered - clearing these tags or removing them */ 00457 if (agrp->flag & AGRP_TEMP) { 00458 /* if group is empty and tagged, then we can remove as this operation 00459 * moved out all the channels that were formerly here 00460 */ 00461 if (agrp->channels.first == NULL) 00462 BLI_freelinkN(&srcAct->groups, agrp); 00463 else 00464 agrp->flag &= ~AGRP_TEMP; 00465 } 00466 } 00467 } 00468 } 00469 00470 /* Transfer the animation data from srcID to dstID where the srcID 00471 * animation data is based off "basepath", creating new AnimData and 00472 * associated data as necessary 00473 */ 00474 void BKE_animdata_separate_by_basepath (ID *srcID, ID *dstID, ListBase *basepaths) 00475 { 00476 AnimData *srcAdt=NULL, *dstAdt=NULL; 00477 LinkData *ld; 00478 00479 /* sanity checks */ 00480 if ELEM(NULL, srcID, dstID) { 00481 if (G.f & G_DEBUG) 00482 printf("ERROR: no source or destination ID to separate AnimData with\n"); 00483 return; 00484 } 00485 00486 /* get animdata from src, and create for destination (if needed) */ 00487 srcAdt = BKE_animdata_from_id(srcID); 00488 dstAdt = BKE_id_add_animdata(dstID); 00489 00490 if ELEM(NULL, srcAdt, dstAdt) { 00491 if (G.f & G_DEBUG) 00492 printf("ERROR: no AnimData for this pair of ID's\n"); 00493 return; 00494 } 00495 00496 /* active action */ 00497 if (srcAdt->action) { 00498 /* set up an action if necessary, and name it in a similar way so that it can be easily found again */ 00499 if (dstAdt->action == NULL) { 00500 dstAdt->action = add_empty_action(srcAdt->action->id.name+2); 00501 } 00502 else if (dstAdt->action == srcAdt->action) { 00503 printf("Argh! Source and Destination share animation! ('%s' and '%s' both use '%s') Making new empty action\n", 00504 srcID->name, dstID->name, srcAdt->action->id.name); 00505 00506 // TODO: review this... 00507 id_us_min(&dstAdt->action->id); 00508 dstAdt->action = add_empty_action(dstAdt->action->id.name+2); 00509 } 00510 00511 /* loop over base paths, trying to fix for each one... */ 00512 for (ld = basepaths->first; ld; ld = ld->next) { 00513 const char *basepath = (const char *)ld->data; 00514 action_move_fcurves_by_basepath(srcAdt->action, dstAdt->action, basepath); 00515 } 00516 } 00517 00518 /* drivers */ 00519 if (srcAdt->drivers.first) { 00520 FCurve *fcu, *fcn=NULL; 00521 00522 /* check each driver against all the base paths to see if any should go */ 00523 for (fcu = srcAdt->drivers.first; fcu; fcu = fcn) { 00524 fcn = fcu->next; 00525 00526 /* try each basepath in turn, but stop on the first one which works */ 00527 for (ld = basepaths->first; ld; ld = ld->next) { 00528 const char *basepath = (const char *)ld->data; 00529 00530 if (animpath_matches_basepath(fcu->rna_path, basepath)) { 00531 /* just need to change lists */ 00532 BLI_remlink(&srcAdt->drivers, fcu); 00533 BLI_addtail(&dstAdt->drivers, fcu); 00534 00535 // TODO: add depsgraph flushing calls? 00536 00537 /* can stop now, as moved already */ 00538 break; 00539 } 00540 } 00541 } 00542 } 00543 } 00544 00545 /* Path Validation -------------------------------------------- */ 00546 00547 /* Check if a given RNA Path is valid, by tracing it from the given ID, and seeing if we can resolve it */ 00548 static short check_rna_path_is_valid (ID *owner_id, const char *path) 00549 { 00550 PointerRNA id_ptr, ptr; 00551 PropertyRNA *prop=NULL; 00552 00553 /* make initial RNA pointer to start resolving from */ 00554 RNA_id_pointer_create(owner_id, &id_ptr); 00555 00556 /* try to resolve */ 00557 return RNA_path_resolve(&id_ptr, path, &ptr, &prop); 00558 } 00559 00560 /* Check if some given RNA Path needs fixing - free the given path and set a new one as appropriate 00561 * NOTE: we assume that oldName and newName have [" "] padding around them 00562 */ 00563 static char *rna_path_rename_fix (ID *owner_id, const char *prefix, const char *oldName, const char *newName, char *oldpath, int verify_paths) 00564 { 00565 char *prefixPtr= strstr(oldpath, prefix); 00566 char *oldNamePtr= strstr(oldpath, oldName); 00567 int prefixLen= strlen(prefix); 00568 int oldNameLen= strlen(oldName); 00569 00570 /* only start fixing the path if the prefix and oldName feature in the path, 00571 * and prefix occurs immediately before oldName 00572 */ 00573 if ( (prefixPtr && oldNamePtr) && (prefixPtr+prefixLen == oldNamePtr) ) { 00574 /* if we haven't aren't able to resolve the path now, try again after fixing it */ 00575 if (!verify_paths || check_rna_path_is_valid(owner_id, oldpath) == 0) { 00576 DynStr *ds= BLI_dynstr_new(); 00577 char *postfixPtr= oldNamePtr+oldNameLen; 00578 char *newPath = NULL; 00579 char oldChar; 00580 00581 /* add the part of the string that goes up to the start of the prefix */ 00582 if (prefixPtr > oldpath) { 00583 oldChar= prefixPtr[0]; 00584 prefixPtr[0]= 0; 00585 BLI_dynstr_append(ds, oldpath); 00586 prefixPtr[0]= oldChar; 00587 } 00588 00589 /* add the prefix */ 00590 BLI_dynstr_append(ds, prefix); 00591 00592 /* add the new name (complete with brackets) */ 00593 BLI_dynstr_append(ds, newName); 00594 00595 /* add the postfix */ 00596 BLI_dynstr_append(ds, postfixPtr); 00597 00598 /* create new path, and cleanup old data */ 00599 newPath= BLI_dynstr_get_cstring(ds); 00600 BLI_dynstr_free(ds); 00601 00602 /* check if the new path will solve our problems */ 00603 // TODO: will need to check whether this step really helps in practice 00604 if (!verify_paths || check_rna_path_is_valid(owner_id, newPath)) { 00605 /* free the old path, and return the new one, since we've solved the issues */ 00606 MEM_freeN(oldpath); 00607 return newPath; 00608 } 00609 else { 00610 /* still couldn't resolve the path... so, might as well just leave it alone */ 00611 MEM_freeN(newPath); 00612 } 00613 } 00614 } 00615 00616 /* the old path doesn't need to be changed */ 00617 return oldpath; 00618 } 00619 00620 /* Check RNA-Paths for a list of F-Curves */ 00621 static void fcurves_path_rename_fix (ID *owner_id, const char *prefix, char *oldName, char *newName, ListBase *curves, int verify_paths) 00622 { 00623 FCurve *fcu; 00624 00625 /* we need to check every curve... */ 00626 for (fcu= curves->first; fcu; fcu= fcu->next) { 00627 /* firstly, handle the F-Curve's own path */ 00628 if (fcu->rna_path) 00629 fcu->rna_path= rna_path_rename_fix(owner_id, prefix, oldName, newName, fcu->rna_path, verify_paths); 00630 } 00631 } 00632 00633 /* Check RNA-Paths for a list of Drivers */ 00634 static void drivers_path_rename_fix (ID *owner_id, const char *prefix, const char *oldName, const char *newName, const char *oldKey, const char *newKey, ListBase *curves, int verify_paths) 00635 { 00636 FCurve *fcu; 00637 00638 /* we need to check every curve - drivers are F-Curves too! */ 00639 for (fcu= curves->first; fcu; fcu= fcu->next) { 00640 /* firstly, handle the F-Curve's own path */ 00641 if (fcu->rna_path) 00642 fcu->rna_path= rna_path_rename_fix(owner_id, prefix, oldKey, newKey, fcu->rna_path, verify_paths); 00643 00644 /* driver? */ 00645 if (fcu->driver) { 00646 ChannelDriver *driver= fcu->driver; 00647 DriverVar *dvar; 00648 00649 /* driver variables */ 00650 for (dvar= driver->variables.first; dvar; dvar=dvar->next) { 00651 /* only change the used targets, since the others will need fixing manually anyway */ 00652 DRIVER_TARGETS_USED_LOOPER(dvar) 00653 { 00654 /* rename RNA path */ 00655 if (dtar->rna_path && dtar->id) 00656 dtar->rna_path= rna_path_rename_fix(dtar->id, prefix, oldKey, newKey, dtar->rna_path, verify_paths); 00657 00658 /* also fix the bone-name (if applicable) */ 00659 if (strstr(prefix, "bones")) { 00660 if ( ((dtar->id) && (GS(dtar->id->name) == ID_OB)) && 00661 (dtar->pchan_name[0]) && (strcmp(oldName, dtar->pchan_name)==0) ) 00662 { 00663 BLI_strncpy(dtar->pchan_name, newName, sizeof(dtar->pchan_name)); 00664 } 00665 } 00666 } 00667 DRIVER_TARGETS_LOOPER_END 00668 } 00669 } 00670 } 00671 } 00672 00673 /* Fix all RNA-Paths for Actions linked to NLA Strips */ 00674 static void nlastrips_path_rename_fix (ID *owner_id, const char *prefix, char *oldName, char *newName, ListBase *strips, int verify_paths) 00675 { 00676 NlaStrip *strip; 00677 00678 /* recursively check strips, fixing only actions... */ 00679 for (strip= strips->first; strip; strip= strip->next) { 00680 /* fix strip's action */ 00681 if (strip->act) 00682 fcurves_path_rename_fix(owner_id, prefix, oldName, newName, &strip->act->curves, verify_paths); 00683 /* ignore own F-Curves, since those are local... */ 00684 00685 /* check sub-strips (if metas) */ 00686 nlastrips_path_rename_fix(owner_id, prefix, oldName, newName, &strip->strips, verify_paths); 00687 } 00688 } 00689 00690 /* Fix all RNA-Paths in the AnimData block used by the given ID block 00691 * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]> 00692 * i.e. pose.bones["Bone"] 00693 */ 00694 void BKE_animdata_fix_paths_rename (ID *owner_id, AnimData *adt, const char *prefix, const char *oldName, const char *newName, int oldSubscript, int newSubscript, int verify_paths) 00695 { 00696 NlaTrack *nlt; 00697 char *oldN, *newN; 00698 00699 /* if no AnimData, no need to proceed */ 00700 if (ELEM(NULL, owner_id, adt)) 00701 return; 00702 00703 if ((oldName != NULL) && (newName != NULL)) { 00704 /* pad the names with [" "] so that only exact matches are made */ 00705 oldN= BLI_sprintfN("[\"%s\"]", oldName); 00706 newN= BLI_sprintfN("[\"%s\"]", newName); 00707 } 00708 else { 00709 oldN= BLI_sprintfN("[%d]", oldSubscript); 00710 newN= BLI_sprintfN("[%d]", newSubscript); 00711 } 00712 00713 /* Active action and temp action */ 00714 if (adt->action) 00715 fcurves_path_rename_fix(owner_id, prefix, oldN, newN, &adt->action->curves, verify_paths); 00716 if (adt->tmpact) 00717 fcurves_path_rename_fix(owner_id, prefix, oldN, newN, &adt->tmpact->curves, verify_paths); 00718 00719 /* Drivers - Drivers are really F-Curves */ 00720 drivers_path_rename_fix(owner_id, prefix, oldName, newName, oldN, newN, &adt->drivers, verify_paths); 00721 00722 /* NLA Data - Animation Data for Strips */ 00723 for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) 00724 nlastrips_path_rename_fix(owner_id, prefix, oldN, newN, &nlt->strips, verify_paths); 00725 00726 /* free the temp names */ 00727 MEM_freeN(oldN); 00728 MEM_freeN(newN); 00729 } 00730 00731 /* Whole Database Ops -------------------------------------------- */ 00732 00733 /* apply the given callback function on all data in main database */ 00734 void BKE_animdata_main_cb (Main *mainptr, ID_AnimData_Edit_Callback func, void *user_data) 00735 { 00736 ID *id; 00737 00738 /* standard data version */ 00739 #define ANIMDATA_IDS_CB(first) \ 00740 for (id= first; id; id= id->next) { \ 00741 AnimData *adt= BKE_animdata_from_id(id); \ 00742 if (adt) func(id, adt, user_data); \ 00743 } 00744 00745 /* "embedded" nodetree cases (i.e. scene/material/texture->nodetree) */ 00746 #define ANIMDATA_NODETREE_IDS_CB(first, NtId_Type) \ 00747 for (id= first; id; id= id->next) { \ 00748 AnimData *adt= BKE_animdata_from_id(id); \ 00749 NtId_Type *ntp= (NtId_Type *)id; \ 00750 if (ntp->nodetree) { \ 00751 AnimData *adt2= BKE_animdata_from_id((ID *)ntp); \ 00752 if (adt2) func(id, adt2, user_data); \ 00753 } \ 00754 if (adt) func(id, adt, user_data); \ 00755 } 00756 00757 /* nodes */ 00758 ANIMDATA_IDS_CB(mainptr->nodetree.first); 00759 00760 /* textures */ 00761 ANIMDATA_NODETREE_IDS_CB(mainptr->tex.first, Tex); 00762 00763 /* lamps */ 00764 ANIMDATA_IDS_CB(mainptr->lamp.first); 00765 00766 /* materials */ 00767 ANIMDATA_NODETREE_IDS_CB(mainptr->mat.first, Material); 00768 00769 /* cameras */ 00770 ANIMDATA_IDS_CB(mainptr->camera.first); 00771 00772 /* shapekeys */ 00773 ANIMDATA_IDS_CB(mainptr->key.first); 00774 00775 /* metaballs */ 00776 ANIMDATA_IDS_CB(mainptr->mball.first); 00777 00778 /* curves */ 00779 ANIMDATA_IDS_CB(mainptr->curve.first); 00780 00781 /* armatures */ 00782 ANIMDATA_IDS_CB(mainptr->armature.first); 00783 00784 /* lattices */ 00785 ANIMDATA_IDS_CB(mainptr->latt.first); 00786 00787 /* meshes */ 00788 ANIMDATA_IDS_CB(mainptr->mesh.first); 00789 00790 /* particles */ 00791 ANIMDATA_IDS_CB(mainptr->particle.first); 00792 00793 /* speakers */ 00794 ANIMDATA_IDS_CB(mainptr->speaker.first); 00795 00796 /* objects */ 00797 ANIMDATA_IDS_CB(mainptr->object.first); 00798 00799 /* worlds */ 00800 ANIMDATA_IDS_CB(mainptr->world.first); 00801 00802 /* scenes */ 00803 ANIMDATA_NODETREE_IDS_CB(mainptr->scene.first, Scene); 00804 } 00805 00806 /* Fix all RNA-Paths throughout the database (directly access the Global.main version) 00807 * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]> 00808 * i.e. pose.bones["Bone"] 00809 */ 00810 /* TODO: use BKE_animdata_main_cb for looping over all data */ 00811 void BKE_all_animdata_fix_paths_rename (const char *prefix, const char *oldName, const char *newName) 00812 { 00813 Main *mainptr= G.main; 00814 ID *id; 00815 00816 /* macro for less typing 00817 * - whether animdata exists is checked for by the main renaming callback, though taking 00818 * this outside of the function may make things slightly faster? 00819 */ 00820 #define RENAMEFIX_ANIM_IDS(first) \ 00821 for (id= first; id; id= id->next) { \ 00822 AnimData *adt= BKE_animdata_from_id(id); \ 00823 BKE_animdata_fix_paths_rename(id, adt, prefix, oldName, newName, 0, 0, 1);\ 00824 } 00825 00826 /* another version of this macro for nodetrees */ 00827 #define RENAMEFIX_ANIM_NODETREE_IDS(first, NtId_Type) \ 00828 for (id= first; id; id= id->next) { \ 00829 AnimData *adt= BKE_animdata_from_id(id); \ 00830 NtId_Type *ntp= (NtId_Type *)id; \ 00831 if (ntp->nodetree) { \ 00832 AnimData *adt2= BKE_animdata_from_id((ID *)ntp); \ 00833 BKE_animdata_fix_paths_rename((ID *)ntp, adt2, prefix, oldName, newName, 0, 0, 1);\ 00834 } \ 00835 BKE_animdata_fix_paths_rename(id, adt, prefix, oldName, newName, 0, 0, 1);\ 00836 } 00837 00838 /* nodes */ 00839 RENAMEFIX_ANIM_IDS(mainptr->nodetree.first); 00840 00841 /* textures */ 00842 RENAMEFIX_ANIM_NODETREE_IDS(mainptr->tex.first, Tex); 00843 00844 /* lamps */ 00845 RENAMEFIX_ANIM_IDS(mainptr->lamp.first); 00846 00847 /* materials */ 00848 RENAMEFIX_ANIM_NODETREE_IDS(mainptr->mat.first, Material); 00849 00850 /* cameras */ 00851 RENAMEFIX_ANIM_IDS(mainptr->camera.first); 00852 00853 /* shapekeys */ 00854 RENAMEFIX_ANIM_IDS(mainptr->key.first); 00855 00856 /* metaballs */ 00857 RENAMEFIX_ANIM_IDS(mainptr->mball.first); 00858 00859 /* curves */ 00860 RENAMEFIX_ANIM_IDS(mainptr->curve.first); 00861 00862 /* armatures */ 00863 RENAMEFIX_ANIM_IDS(mainptr->armature.first); 00864 00865 /* lattices */ 00866 RENAMEFIX_ANIM_IDS(mainptr->latt.first); 00867 00868 /* meshes */ 00869 RENAMEFIX_ANIM_IDS(mainptr->mesh.first); 00870 00871 /* particles */ 00872 RENAMEFIX_ANIM_IDS(mainptr->particle.first); 00873 00874 /* speakers */ 00875 RENAMEFIX_ANIM_IDS(mainptr->speaker.first); 00876 00877 /* objects */ 00878 RENAMEFIX_ANIM_IDS(mainptr->object.first); 00879 00880 /* worlds */ 00881 RENAMEFIX_ANIM_IDS(mainptr->world.first); 00882 00883 /* scenes */ 00884 RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene); 00885 } 00886 00887 /* *********************************** */ 00888 /* KeyingSet API */ 00889 00890 /* Finding Tools --------------------------- */ 00891 00892 /* Find the first path that matches the given criteria */ 00893 // TODO: do we want some method to perform partial matches too? 00894 KS_Path *BKE_keyingset_find_path (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, int UNUSED(group_mode)) 00895 { 00896 KS_Path *ksp; 00897 00898 /* sanity checks */ 00899 if ELEM3(NULL, ks, rna_path, id) 00900 return NULL; 00901 00902 /* loop over paths in the current KeyingSet, finding the first one where all settings match 00903 * (i.e. the first one where none of the checks fail and equal 0) 00904 */ 00905 for (ksp= ks->paths.first; ksp; ksp= ksp->next) { 00906 short eq_id=1, eq_path=1, eq_index=1, eq_group=1; 00907 00908 /* id */ 00909 if (id != ksp->id) 00910 eq_id= 0; 00911 00912 /* path */ 00913 if ((ksp->rna_path==NULL) || strcmp(rna_path, ksp->rna_path)) 00914 eq_path= 0; 00915 00916 /* index - need to compare whole-array setting too... */ 00917 if (ksp->array_index != array_index) 00918 eq_index= 0; 00919 00920 /* group */ 00921 if (group_name) { 00922 // FIXME: these checks need to be coded... for now, it's not too important though 00923 } 00924 00925 /* if all aspects are ok, return */ 00926 if (eq_id && eq_path && eq_index && eq_group) 00927 return ksp; 00928 } 00929 00930 /* none found */ 00931 return NULL; 00932 } 00933 00934 /* Defining Tools --------------------------- */ 00935 00936 /* Used to create a new 'custom' KeyingSet for the user, that will be automatically added to the stack */ 00937 KeyingSet *BKE_keyingset_add (ListBase *list, const char name[], short flag, short keyingflag) 00938 { 00939 KeyingSet *ks; 00940 00941 /* allocate new KeyingSet */ 00942 ks= MEM_callocN(sizeof(KeyingSet), "KeyingSet"); 00943 00944 BLI_strncpy(ks->name, name ? name : "KeyingSet", sizeof(ks->name)); 00945 00946 ks->flag= flag; 00947 ks->keyingflag= keyingflag; 00948 00949 /* add KeyingSet to list */ 00950 BLI_addtail(list, ks); 00951 00952 /* make sure KeyingSet has a unique name (this helps with identification) */ 00953 BLI_uniquename(list, ks, "KeyingSet", '.', offsetof(KeyingSet, name), sizeof(ks->name)); 00954 00955 /* return new KeyingSet for further editing */ 00956 return ks; 00957 } 00958 00959 /* Add a path to a KeyingSet. Nothing is returned for now... 00960 * Checks are performed to ensure that destination is appropriate for the KeyingSet in question 00961 */ 00962 KS_Path *BKE_keyingset_add_path (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, short flag, short groupmode) 00963 { 00964 KS_Path *ksp; 00965 00966 /* sanity checks */ 00967 if ELEM(NULL, ks, rna_path) { 00968 printf("ERROR: no Keying Set and/or RNA Path to add path with \n"); 00969 return NULL; 00970 } 00971 00972 /* ID is required for all types of KeyingSets */ 00973 if (id == NULL) { 00974 printf("ERROR: No ID provided for Keying Set Path. \n"); 00975 return NULL; 00976 } 00977 00978 /* don't add if there is already a matching KS_Path in the KeyingSet */ 00979 if (BKE_keyingset_find_path(ks, id, group_name, rna_path, array_index, groupmode)) { 00980 if (G.f & G_DEBUG) 00981 printf("ERROR: destination already exists in Keying Set \n"); 00982 return NULL; 00983 } 00984 00985 /* allocate a new KeyingSet Path */ 00986 ksp= MEM_callocN(sizeof(KS_Path), "KeyingSet Path"); 00987 00988 /* just store absolute info */ 00989 ksp->id= id; 00990 if (group_name) 00991 BLI_strncpy(ksp->group, group_name, sizeof(ksp->group)); 00992 else 00993 ksp->group[0]= '\0'; 00994 00995 /* store additional info for relative paths (just in case user makes the set relative) */ 00996 if (id) 00997 ksp->idtype= GS(id->name); 00998 00999 /* just copy path info */ 01000 // TODO: should array index be checked too? 01001 ksp->rna_path= BLI_strdupn(rna_path, strlen(rna_path)); 01002 ksp->array_index= array_index; 01003 01004 /* store flags */ 01005 ksp->flag= flag; 01006 ksp->groupmode= groupmode; 01007 01008 /* add KeyingSet path to KeyingSet */ 01009 BLI_addtail(&ks->paths, ksp); 01010 01011 /* return this path */ 01012 return ksp; 01013 } 01014 01015 /* Free the given Keying Set path */ 01016 void BKE_keyingset_free_path (KeyingSet *ks, KS_Path *ksp) 01017 { 01018 /* sanity check */ 01019 if ELEM(NULL, ks, ksp) 01020 return; 01021 01022 /* free RNA-path info */ 01023 if(ksp->rna_path) 01024 MEM_freeN(ksp->rna_path); 01025 01026 /* free path itself */ 01027 BLI_freelinkN(&ks->paths, ksp); 01028 } 01029 01030 /* Copy all KeyingSets in the given list */ 01031 void BKE_keyingsets_copy (ListBase *newlist, ListBase *list) 01032 { 01033 KeyingSet *ksn; 01034 KS_Path *kspn; 01035 01036 BLI_duplicatelist(newlist, list); 01037 01038 for (ksn=newlist->first; ksn; ksn=ksn->next) { 01039 BLI_duplicatelist(&ksn->paths, &ksn->paths); 01040 01041 for (kspn=ksn->paths.first; kspn; kspn=kspn->next) 01042 kspn->rna_path= MEM_dupallocN(kspn->rna_path); 01043 } 01044 } 01045 01046 /* Freeing Tools --------------------------- */ 01047 01048 /* Free data for KeyingSet but not set itself */ 01049 void BKE_keyingset_free (KeyingSet *ks) 01050 { 01051 KS_Path *ksp, *kspn; 01052 01053 /* sanity check */ 01054 if (ks == NULL) 01055 return; 01056 01057 /* free each path as we go to avoid looping twice */ 01058 for (ksp= ks->paths.first; ksp; ksp= kspn) { 01059 kspn= ksp->next; 01060 BKE_keyingset_free_path(ks, ksp); 01061 } 01062 } 01063 01064 /* Free all the KeyingSets in the given list */ 01065 void BKE_keyingsets_free (ListBase *list) 01066 { 01067 KeyingSet *ks, *ksn; 01068 01069 /* sanity check */ 01070 if (list == NULL) 01071 return; 01072 01073 /* loop over KeyingSets freeing them 01074 * - BKE_keyingset_free() doesn't free the set itself, but it frees its sub-data 01075 */ 01076 for (ks= list->first; ks; ks= ksn) { 01077 ksn= ks->next; 01078 BKE_keyingset_free(ks); 01079 BLI_freelinkN(list, ks); 01080 } 01081 } 01082 01083 /* ***************************************** */ 01084 /* Evaluation Data-Setting Backend */ 01085 01086 /* Retrieve string to act as RNA-path, adjusted using mapping-table if provided 01087 * It returns whether the string needs to be freed (i.e. if it was a temp remapped one) 01088 * // FIXME: maybe it would be faster if we didn't have to alloc/free strings like this all the time, but for now it's safer 01089 * 01090 * - remap: remapping table to use 01091 * - path: original path string (as stored in F-Curve data) 01092 * - dst: destination string to write data to 01093 */ 01094 static short animsys_remap_path (AnimMapper *UNUSED(remap), char *path, char **dst) 01095 { 01096 /* is there a valid remapping table to use? */ 01097 //if (remap) { 01098 /* find a matching entry... to use to remap */ 01099 // ...TODO... 01100 //} 01101 01102 /* nothing suitable found, so just set dst to look at path (i.e. no alloc/free needed) */ 01103 *dst= path; 01104 return 0; 01105 } 01106 01107 01108 /* less then 1.0 evaluates to false, use epsilon to avoid float error */ 01109 #define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > ((1.0f-FLT_EPSILON))) 01110 01111 /* Write the given value to a setting using RNA, and return success */ 01112 static short animsys_write_rna_setting (PointerRNA *ptr, char *path, int array_index, float value) 01113 { 01114 PropertyRNA *prop; 01115 PointerRNA new_ptr; 01116 01117 //printf("%p %s %i %f\n", ptr, path, array_index, value); 01118 01119 /* get property to write to */ 01120 if (RNA_path_resolve(ptr, path, &new_ptr, &prop)) 01121 { 01122 /* set value - only for animatable numerical values */ 01123 if (RNA_property_animateable(&new_ptr, prop)) 01124 { 01125 int array_len= RNA_property_array_length(&new_ptr, prop); 01126 01127 if (array_len && array_index >= array_len) 01128 { 01129 if (G.f & G_DEBUG) { 01130 printf("Animato: Invalid array index. ID = '%s', '%s[%d]', array length is %d \n", 01131 (ptr && ptr->id.data) ? (((ID *)ptr->id.data)->name+2) : "<No ID>", 01132 path, array_index, array_len-1); 01133 } 01134 01135 return 0; 01136 } 01137 01138 switch (RNA_property_type(prop)) 01139 { 01140 case PROP_BOOLEAN: 01141 if (array_len) 01142 RNA_property_boolean_set_index(&new_ptr, prop, array_index, ANIMSYS_FLOAT_AS_BOOL(value)); 01143 else 01144 RNA_property_boolean_set(&new_ptr, prop, ANIMSYS_FLOAT_AS_BOOL(value)); 01145 break; 01146 case PROP_INT: 01147 if (array_len) 01148 RNA_property_int_set_index(&new_ptr, prop, array_index, (int)value); 01149 else 01150 RNA_property_int_set(&new_ptr, prop, (int)value); 01151 break; 01152 case PROP_FLOAT: 01153 if (array_len) 01154 RNA_property_float_set_index(&new_ptr, prop, array_index, value); 01155 else 01156 RNA_property_float_set(&new_ptr, prop, value); 01157 break; 01158 case PROP_ENUM: 01159 RNA_property_enum_set(&new_ptr, prop, (int)value); 01160 break; 01161 default: 01162 /* nothing can be done here... so it is unsuccessful? */ 01163 return 0; 01164 } 01165 01166 /* RNA property update disabled for now - [#28525] [#28690] [#28774] [#28777] */ 01167 #if 0 01168 /* buffer property update for later flushing */ 01169 if (RNA_property_update_check(prop)) { 01170 short skip_updates_hack = 0; 01171 01172 /* optimisation hacks: skip property updates for those properties 01173 * for we know that which the updates in RNA were really just for 01174 * flushing property editing via UI/Py 01175 */ 01176 if (new_ptr.type == &RNA_PoseBone) { 01177 /* bone transforms - update pose (i.e. tag depsgraph) */ 01178 skip_updates_hack = 1; 01179 } 01180 01181 if (skip_updates_hack == 0) 01182 RNA_property_update_cache_add(&new_ptr, prop); 01183 } 01184 #endif 01185 01186 /* as long as we don't do property update, we still tag datablock 01187 as having been updated. this flag does not cause any updates to 01188 be run, it's for e.g. render engines to synchronize data */ 01189 if(new_ptr.id.data) { 01190 ID *id= new_ptr.id.data; 01191 id->flag |= LIB_ID_RECALC; 01192 DAG_id_type_tag(G.main, GS(id->name)); 01193 } 01194 } 01195 01196 /* successful */ 01197 return 1; 01198 } 01199 else { 01200 /* failed to get path */ 01201 // XXX don't tag as failed yet though, as there are some legit situations (Action Constraint) 01202 // where some channels will not exist, but shouldn't lock up Action 01203 if (G.f & G_DEBUG) { 01204 printf("Animato: Invalid path. ID = '%s', '%s[%d]' \n", 01205 (ptr && ptr->id.data) ? (((ID *)ptr->id.data)->name+2) : "<No ID>", 01206 path, array_index); 01207 } 01208 return 0; 01209 } 01210 } 01211 01212 /* Simple replacement based data-setting of the FCurve using RNA */ 01213 static short animsys_execute_fcurve (PointerRNA *ptr, AnimMapper *remap, FCurve *fcu) 01214 { 01215 char *path = NULL; 01216 short free_path=0; 01217 short ok= 0; 01218 01219 /* get path, remapped as appropriate to work in its new environment */ 01220 free_path= animsys_remap_path(remap, fcu->rna_path, &path); 01221 01222 /* write value to setting */ 01223 if (path) 01224 ok= animsys_write_rna_setting(ptr, path, fcu->array_index, fcu->curval); 01225 01226 /* free temp path-info */ 01227 if (free_path) 01228 MEM_freeN(path); 01229 01230 /* return whether we were successful */ 01231 return ok; 01232 } 01233 01234 /* Evaluate all the F-Curves in the given list 01235 * This performs a set of standard checks. If extra checks are required, separate code should be used 01236 */ 01237 static void animsys_evaluate_fcurves (PointerRNA *ptr, ListBase *list, AnimMapper *remap, float ctime) 01238 { 01239 FCurve *fcu; 01240 01241 /* calculate then execute each curve */ 01242 for (fcu= list->first; fcu; fcu= fcu->next) 01243 { 01244 /* check if this F-Curve doesn't belong to a muted group */ 01245 if ((fcu->grp == NULL) || (fcu->grp->flag & AGRP_MUTED)==0) { 01246 /* check if this curve should be skipped */ 01247 if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) 01248 { 01249 calculate_fcurve(fcu, ctime); 01250 animsys_execute_fcurve(ptr, remap, fcu); 01251 } 01252 } 01253 } 01254 } 01255 01256 /* ***************************************** */ 01257 /* Driver Evaluation */ 01258 01259 /* Evaluate Drivers */ 01260 static void animsys_evaluate_drivers (PointerRNA *ptr, AnimData *adt, float ctime) 01261 { 01262 FCurve *fcu; 01263 01264 /* drivers are stored as F-Curves, but we cannot use the standard code, as we need to check if 01265 * the depsgraph requested that this driver be evaluated... 01266 */ 01267 for (fcu= adt->drivers.first; fcu; fcu= fcu->next) 01268 { 01269 ChannelDriver *driver= fcu->driver; 01270 short ok= 0; 01271 01272 /* check if this driver's curve should be skipped */ 01273 if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) 01274 { 01275 /* check if driver itself is tagged for recalculation */ 01276 if ((driver) && !(driver->flag & DRIVER_FLAG_INVALID)/*&& (driver->flag & DRIVER_FLAG_RECALC)*/) { // XXX driver recalc flag is not set yet by depsgraph! 01277 /* evaluate this using values set already in other places */ 01278 // NOTE: for 'layering' option later on, we should check if we should remove old value before adding new to only be done when drivers only changed 01279 calculate_fcurve(fcu, ctime); 01280 ok= animsys_execute_fcurve(ptr, NULL, fcu); 01281 01282 /* clear recalc flag */ 01283 driver->flag &= ~DRIVER_FLAG_RECALC; 01284 01285 /* set error-flag if evaluation failed */ 01286 if (ok == 0) 01287 driver->flag |= DRIVER_FLAG_INVALID; 01288 } 01289 } 01290 } 01291 } 01292 01293 /* ***************************************** */ 01294 /* Actions Evaluation */ 01295 01296 /* strictly not necessary for actual "evaluation", but it is a useful safety check 01297 * to reduce the amount of times that users end up having to "revive" wrongly-assigned 01298 * actions 01299 */ 01300 static void action_idcode_patch_check (ID *id, bAction *act) 01301 { 01302 int idcode = 0; 01303 01304 /* just in case */ 01305 if (ELEM(NULL, id, act)) 01306 return; 01307 else 01308 idcode = GS(id->name); 01309 01310 /* the actual checks... hopefully not too much of a performance hit in the long run... */ 01311 if (act->idroot == 0) { 01312 /* use the current root if not set already (i.e. newly created actions and actions from 2.50-2.57 builds) 01313 * - this has problems if there are 2 users, and the first one encountered is the invalid one 01314 * in which case, the user will need to manually fix this (?) 01315 */ 01316 act->idroot = idcode; 01317 } 01318 else if (act->idroot != idcode) { 01319 /* only report this error if debug mode is enabled (to save performance everywhere else) */ 01320 if (G.f & G_DEBUG) { 01321 printf("AnimSys Safety Check Failed: Action '%s' is not meant to be used from ID-Blocks of type %d such as '%s'\n", 01322 act->id.name+2, idcode, id->name); 01323 } 01324 } 01325 } 01326 01327 /* ----------------------------------------- */ 01328 01329 /* Evaluate Action Group */ 01330 void animsys_evaluate_action_group (PointerRNA *ptr, bAction *act, bActionGroup *agrp, AnimMapper *remap, float ctime) 01331 { 01332 FCurve *fcu; 01333 01334 /* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */ 01335 if ELEM(NULL, act, agrp) return; 01336 if ((remap) && (remap->target != act)) remap= NULL; 01337 01338 action_idcode_patch_check(ptr->id.data, act); 01339 01340 /* if group is muted, don't evaluated any of the F-Curve */ 01341 if (agrp->flag & AGRP_MUTED) 01342 return; 01343 01344 /* calculate then execute each curve */ 01345 for (fcu= agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu= fcu->next) 01346 { 01347 /* check if this curve should be skipped */ 01348 if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) 01349 { 01350 calculate_fcurve(fcu, ctime); 01351 animsys_execute_fcurve(ptr, remap, fcu); 01352 } 01353 } 01354 } 01355 01356 /* Evaluate Action (F-Curve Bag) */ 01357 void animsys_evaluate_action (PointerRNA *ptr, bAction *act, AnimMapper *remap, float ctime) 01358 { 01359 /* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */ 01360 if (act == NULL) return; 01361 if ((remap) && (remap->target != act)) remap= NULL; 01362 01363 action_idcode_patch_check(ptr->id.data, act); 01364 01365 /* calculate then execute each curve */ 01366 animsys_evaluate_fcurves(ptr, &act->curves, remap, ctime); 01367 } 01368 01369 /* ***************************************** */ 01370 /* NLA System - Evaluation */ 01371 01372 /* calculate influence of strip based for given frame based on blendin/out values */ 01373 static float nlastrip_get_influence (NlaStrip *strip, float cframe) 01374 { 01375 /* sanity checks - normalise the blendin/out values? */ 01376 strip->blendin= fabsf(strip->blendin); 01377 strip->blendout= fabsf(strip->blendout); 01378 01379 /* result depends on where frame is in respect to blendin/out values */ 01380 if (IS_EQ(strip->blendin, 0)==0 && (cframe <= (strip->start + strip->blendin))) { 01381 /* there is some blend-in */ 01382 return fabsf(cframe - strip->start) / (strip->blendin); 01383 } 01384 else if (IS_EQ(strip->blendout, 0)==0 && (cframe >= (strip->end - strip->blendout))) { 01385 /* there is some blend-out */ 01386 return fabsf(strip->end - cframe) / (strip->blendout); 01387 } 01388 else { 01389 /* in the middle of the strip, we should be full strength */ 01390 return 1.0f; 01391 } 01392 } 01393 01394 /* evaluate the evaluation time and influence for the strip, storing the results in the strip */ 01395 static void nlastrip_evaluate_controls (NlaStrip *strip, float ctime) 01396 { 01397 /* firstly, analytically generate values for influence and time (if applicable) */ 01398 if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) 01399 strip->strip_time= nlastrip_get_frame(strip, ctime, NLATIME_CONVERT_EVAL); 01400 if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0) 01401 strip->influence= nlastrip_get_influence(strip, ctime); 01402 01403 /* now strip's evaluate F-Curves for these settings (if applicable) */ 01404 if (strip->fcurves.first) { 01405 PointerRNA strip_ptr; 01406 01407 /* create RNA-pointer needed to set values */ 01408 RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); 01409 01410 /* execute these settings as per normal */ 01411 animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, NULL, ctime); 01412 } 01413 01414 /* if user can control the evaluation time (using F-Curves), consider the option which allows this time to be clamped 01415 * to lie within extents of the action-clip, so that a steady changing rate of progress through several cycles of the clip 01416 * can be achieved easily 01417 */ 01418 // NOTE: if we add any more of these special cases, we better group them up nicely... 01419 if ((strip->flag & NLASTRIP_FLAG_USR_TIME) && (strip->flag & NLASTRIP_FLAG_USR_TIME_CYCLIC)) 01420 strip->strip_time= fmod(strip->strip_time - strip->actstart, strip->actend - strip->actstart); 01421 } 01422 01423 /* gets the strip active at the current time for a list of strips for evaluation purposes */ 01424 NlaEvalStrip *nlastrips_ctime_get_strip (ListBase *list, ListBase *strips, short index, float ctime) 01425 { 01426 NlaStrip *strip, *estrip=NULL; 01427 NlaEvalStrip *nes; 01428 short side= 0; 01429 01430 /* loop over strips, checking if they fall within the range */ 01431 for (strip= strips->first; strip; strip= strip->next) { 01432 /* check if current time occurs within this strip */ 01433 if (IN_RANGE_INCL(ctime, strip->start, strip->end)) { 01434 /* this strip is active, so try to use it */ 01435 estrip= strip; 01436 side= NES_TIME_WITHIN; 01437 break; 01438 } 01439 01440 /* if time occurred before current strip... */ 01441 if (ctime < strip->start) { 01442 if (strip == strips->first) { 01443 /* before first strip - only try to use it if it extends backwards in time too */ 01444 if (strip->extendmode == NLASTRIP_EXTEND_HOLD) 01445 estrip= strip; 01446 01447 /* side is 'before' regardless of whether there's a useful strip */ 01448 side= NES_TIME_BEFORE; 01449 } 01450 else { 01451 /* before next strip - previous strip has ended, but next hasn't begun, 01452 * so blending mode depends on whether strip is being held or not... 01453 * - only occurs when no transition strip added, otherwise the transition would have 01454 * been picked up above... 01455 */ 01456 strip= strip->prev; 01457 01458 if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) 01459 estrip= strip; 01460 side= NES_TIME_AFTER; 01461 } 01462 break; 01463 } 01464 01465 /* if time occurred after current strip... */ 01466 if (ctime > strip->end) { 01467 /* only if this is the last strip should we do anything, and only if that is being held */ 01468 if (strip == strips->last) { 01469 if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) 01470 estrip= strip; 01471 01472 side= NES_TIME_AFTER; 01473 break; 01474 } 01475 01476 /* otherwise, skip... as the 'before' case will catch it more elegantly! */ 01477 } 01478 } 01479 01480 /* check if a valid strip was found 01481 * - must not be muted (i.e. will have contribution 01482 */ 01483 if ((estrip == NULL) || (estrip->flag & NLASTRIP_FLAG_MUTED)) 01484 return NULL; 01485 01486 /* if ctime was not within the boundaries of the strip, clamp! */ 01487 switch (side) { 01488 case NES_TIME_BEFORE: /* extend first frame only */ 01489 ctime= estrip->start; 01490 break; 01491 case NES_TIME_AFTER: /* extend last frame only */ 01492 ctime= estrip->end; 01493 break; 01494 } 01495 01496 /* evaluate strip's evaluation controls 01497 * - skip if no influence (i.e. same effect as muting the strip) 01498 * - negative influence is not supported yet... how would that be defined? 01499 */ 01500 // TODO: this sounds a bit hacky having a few isolated F-Curves stuck on some data it operates on... 01501 nlastrip_evaluate_controls(estrip, ctime); 01502 if (estrip->influence <= 0.0f) 01503 return NULL; 01504 01505 /* check if strip has valid data to evaluate, 01506 * and/or perform any additional type-specific actions 01507 */ 01508 switch (estrip->type) { 01509 case NLASTRIP_TYPE_CLIP: 01510 /* clip must have some action to evaluate */ 01511 if (estrip->act == NULL) 01512 return NULL; 01513 break; 01514 case NLASTRIP_TYPE_TRANSITION: 01515 /* there must be strips to transition from and to (i.e. prev and next required) */ 01516 if (ELEM(NULL, estrip->prev, estrip->next)) 01517 return NULL; 01518 01519 /* evaluate controls for the relevant extents of the bordering strips... */ 01520 nlastrip_evaluate_controls(estrip->prev, estrip->start); 01521 nlastrip_evaluate_controls(estrip->next, estrip->end); 01522 break; 01523 } 01524 01525 /* add to list of strips we need to evaluate */ 01526 nes= MEM_callocN(sizeof(NlaEvalStrip), "NlaEvalStrip"); 01527 01528 nes->strip= estrip; 01529 nes->strip_mode= side; 01530 nes->track_index= index; 01531 nes->strip_time= estrip->strip_time; 01532 01533 if (list) 01534 BLI_addtail(list, nes); 01535 01536 return nes; 01537 } 01538 01539 /* ---------------------- */ 01540 01541 /* find an NlaEvalChannel that matches the given criteria 01542 * - ptr and prop are the RNA data to find a match for 01543 */ 01544 static NlaEvalChannel *nlaevalchan_find_match (ListBase *channels, PointerRNA *ptr, PropertyRNA *prop, int array_index) 01545 { 01546 NlaEvalChannel *nec; 01547 01548 /* sanity check */ 01549 if (channels == NULL) 01550 return NULL; 01551 01552 /* loop through existing channels, checking for a channel which affects the same property */ 01553 for (nec= channels->first; nec; nec= nec->next) { 01554 /* - comparing the PointerRNA's is done by comparing the pointers 01555 * to the actual struct the property resides in, since that all the 01556 * other data stored in PointerRNA cannot allow us to definitively 01557 * identify the data 01558 */ 01559 if ((nec->ptr.data == ptr->data) && (nec->prop == prop) && (nec->index == array_index)) 01560 return nec; 01561 } 01562 01563 /* not found */ 01564 return NULL; 01565 } 01566 01567 /* verify that an appropriate NlaEvalChannel for this F-Curve exists */ 01568 static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes, FCurve *fcu, short *newChan) 01569 { 01570 NlaEvalChannel *nec; 01571 NlaStrip *strip= nes->strip; 01572 PropertyRNA *prop; 01573 PointerRNA new_ptr; 01574 char *path = NULL; 01575 /* short free_path=0; */ 01576 01577 /* sanity checks */ 01578 if (channels == NULL) 01579 return NULL; 01580 01581 /* get RNA pointer+property info from F-Curve for more convenient handling */ 01582 /* get path, remapped as appropriate to work in its new environment */ 01583 /* free_path= */ /* UNUSED */ animsys_remap_path(strip->remap, fcu->rna_path, &path); 01584 01585 /* a valid property must be available, and it must be animateable */ 01586 if (RNA_path_resolve(ptr, path, &new_ptr, &prop) == 0) { 01587 if (G.f & G_DEBUG) printf("NLA Strip Eval: Cannot resolve path \n"); 01588 return NULL; 01589 } 01590 /* only ok if animateable */ 01591 else if (RNA_property_animateable(&new_ptr, prop) == 0) { 01592 if (G.f & G_DEBUG) printf("NLA Strip Eval: Property not animateable \n"); 01593 return NULL; 01594 } 01595 01596 /* try to find a match */ 01597 nec= nlaevalchan_find_match(channels, &new_ptr, prop, fcu->array_index); 01598 01599 /* allocate a new struct for this if none found */ 01600 if (nec == NULL) { 01601 nec= MEM_callocN(sizeof(NlaEvalChannel), "NlaEvalChannel"); 01602 *newChan= 1; 01603 BLI_addtail(channels, nec); 01604 01605 nec->ptr= new_ptr; 01606 nec->prop= prop; 01607 nec->index= fcu->array_index; 01608 } 01609 else 01610 *newChan= 0; 01611 01612 /* we can now return */ 01613 return nec; 01614 } 01615 01616 /* accumulate (i.e. blend) the given value on to the channel it affects */ 01617 static void nlaevalchan_accumulate (NlaEvalChannel *nec, NlaEvalStrip *nes, short newChan, float value) 01618 { 01619 NlaStrip *strip= nes->strip; 01620 short blendmode= strip->blendmode; 01621 float inf= strip->influence; 01622 01623 /* if channel is new, just store value regardless of blending factors, etc. */ 01624 if (newChan) { 01625 nec->value= value; 01626 return; 01627 } 01628 01629 /* if this is being performed as part of transition evaluation, incorporate 01630 * an additional weighting factor for the influence 01631 */ 01632 if (nes->strip_mode == NES_TIME_TRANSITION_END) 01633 inf *= nes->strip_time; 01634 01635 /* premultiply the value by the weighting factor */ 01636 if (IS_EQ(inf, 0)) return; 01637 value *= inf; 01638 01639 /* perform blending */ 01640 switch (blendmode) { 01641 case NLASTRIP_MODE_ADD: 01642 /* simply add the scaled value on to the stack */ 01643 nec->value += value; 01644 break; 01645 01646 case NLASTRIP_MODE_SUBTRACT: 01647 /* simply subtract the scaled value from the stack */ 01648 nec->value -= value; 01649 break; 01650 01651 case NLASTRIP_MODE_MULTIPLY: 01652 /* multiply the scaled value with the stack */ 01653 nec->value *= value; 01654 break; 01655 01656 case NLASTRIP_MODE_REPLACE: 01657 default: // TODO: do we really want to blend by default? it seems more uses might prefer add... 01658 /* do linear interpolation 01659 * - the influence of the accumulated data (elsewhere, that is called dstweight) 01660 * is 1 - influence, since the strip's influence is srcweight 01661 */ 01662 nec->value= nec->value * (1.0f - inf) + value; 01663 break; 01664 } 01665 } 01666 01667 /* accumulate the results of a temporary buffer with the results of the full-buffer */ 01668 static void nlaevalchan_buffers_accumulate (ListBase *channels, ListBase *tmp_buffer, NlaEvalStrip *nes) 01669 { 01670 NlaEvalChannel *nec, *necn, *necd; 01671 01672 /* optimise - abort if no channels */ 01673 if (tmp_buffer->first == NULL) 01674 return; 01675 01676 /* accumulate results in tmp_channels buffer to the accumulation buffer */ 01677 for (nec= tmp_buffer->first; nec; nec= necn) { 01678 /* get pointer to next channel in case we remove the current channel from the temp-buffer */ 01679 necn= nec->next; 01680 01681 /* try to find an existing matching channel for this setting in the accumulation buffer */ 01682 necd= nlaevalchan_find_match(channels, &nec->ptr, nec->prop, nec->index); 01683 01684 /* if there was a matching channel already in the buffer, accumulate to it, 01685 * otherwise, add the current channel to the buffer for efficiency 01686 */ 01687 if (necd) 01688 nlaevalchan_accumulate(necd, nes, 0, nec->value); 01689 else { 01690 BLI_remlink(tmp_buffer, nec); 01691 BLI_addtail(channels, nec); 01692 } 01693 } 01694 01695 /* free temp-channels that haven't been assimilated into the buffer */ 01696 BLI_freelistN(tmp_buffer); 01697 } 01698 01699 /* ---------------------- */ 01700 /* F-Modifier stack joining/separation utilities - should we generalise these for BLI_listbase.h interface? */ 01701 01702 /* Temporarily join two lists of modifiers together, storing the result in a third list */ 01703 static void nlaeval_fmodifiers_join_stacks (ListBase *result, ListBase *list1, ListBase *list2) 01704 { 01705 FModifier *fcm1, *fcm2; 01706 01707 /* if list1 is invalid... */ 01708 if ELEM(NULL, list1, list1->first) { 01709 if (list2 && list2->first) { 01710 result->first= list2->first; 01711 result->last= list2->last; 01712 } 01713 } 01714 /* if list 2 is invalid... */ 01715 else if ELEM(NULL, list2, list2->first) { 01716 result->first= list1->first; 01717 result->last= list1->last; 01718 } 01719 else { 01720 /* list1 should be added first, and list2 second, with the endpoints of these being the endpoints for result 01721 * - the original lists must be left unchanged though, as we need that fact for restoring 01722 */ 01723 result->first= list1->first; 01724 result->last= list2->last; 01725 01726 fcm1= list1->last; 01727 fcm2= list2->first; 01728 01729 fcm1->next= fcm2; 01730 fcm2->prev= fcm1; 01731 } 01732 } 01733 01734 /* Split two temporary lists of modifiers */ 01735 static void nlaeval_fmodifiers_split_stacks (ListBase *list1, ListBase *list2) 01736 { 01737 FModifier *fcm1, *fcm2; 01738 01739 /* if list1/2 is invalid... just skip */ 01740 if ELEM(NULL, list1, list2) 01741 return; 01742 if ELEM(NULL, list1->first, list2->first) 01743 return; 01744 01745 /* get endpoints */ 01746 fcm1= list1->last; 01747 fcm2= list2->first; 01748 01749 /* clear their links */ 01750 fcm1->next= NULL; 01751 fcm2->prev= NULL; 01752 } 01753 01754 /* ---------------------- */ 01755 01756 /* evaluate action-clip strip */ 01757 static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) 01758 { 01759 ListBase tmp_modifiers = {NULL, NULL}; 01760 NlaStrip *strip= nes->strip; 01761 FCurve *fcu; 01762 float evaltime; 01763 01764 /* sanity checks for action */ 01765 if (strip == NULL) 01766 return; 01767 01768 if (strip->act == NULL) { 01769 printf("NLA-Strip Eval Error: Strip '%s' has no Action\n", strip->name); 01770 return; 01771 } 01772 01773 action_idcode_patch_check(ptr->id.data, strip->act); 01774 01775 /* join this strip's modifiers to the parent's modifiers (own modifiers first) */ 01776 nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers); 01777 01778 /* evaluate strip's modifiers which modify time to evaluate the base curves at */ 01779 evaltime= evaluate_time_fmodifiers(&tmp_modifiers, NULL, 0.0f, strip->strip_time); 01780 01781 /* evaluate all the F-Curves in the action, saving the relevant pointers to data that will need to be used */ 01782 for (fcu= strip->act->curves.first; fcu; fcu= fcu->next) { 01783 NlaEvalChannel *nec; 01784 float value = 0.0f; 01785 short newChan = -1; 01786 01787 /* check if this curve should be skipped */ 01788 if (fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) 01789 continue; 01790 if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) 01791 continue; 01792 01793 /* evaluate the F-Curve's value for the time given in the strip 01794 * NOTE: we use the modified time here, since strip's F-Curve Modifiers are applied on top of this 01795 */ 01796 value= evaluate_fcurve(fcu, evaltime); 01797 01798 /* apply strip's F-Curve Modifiers on this value 01799 * NOTE: we apply the strip's original evaluation time not the modified one (as per standard F-Curve eval) 01800 */ 01801 evaluate_value_fmodifiers(&tmp_modifiers, fcu, &value, strip->strip_time); 01802 01803 01804 /* get an NLA evaluation channel to work with, and accumulate the evaluated value with the value(s) 01805 * stored in this channel if it has been used already 01806 */ 01807 nec= nlaevalchan_verify(ptr, channels, nes, fcu, &newChan); 01808 if (nec) 01809 nlaevalchan_accumulate(nec, nes, newChan, value); 01810 } 01811 01812 /* unlink this strip's modifiers from the parent's modifiers again */ 01813 nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers); 01814 } 01815 01816 /* evaluate transition strip */ 01817 static void nlastrip_evaluate_transition (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) 01818 { 01819 ListBase tmp_channels = {NULL, NULL}; 01820 ListBase tmp_modifiers = {NULL, NULL}; 01821 NlaEvalStrip tmp_nes; 01822 NlaStrip *s1, *s2; 01823 01824 /* join this strip's modifiers to the parent's modifiers (own modifiers first) */ 01825 nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &nes->strip->modifiers, modifiers); 01826 01827 /* get the two strips to operate on 01828 * - we use the endpoints of the strips directly flanking our strip 01829 * using these as the endpoints of the transition (destination and source) 01830 * - these should have already been determined to be valid... 01831 * - if this strip is being played in reverse, we need to swap these endpoints 01832 * otherwise they will be interpolated wrong 01833 */ 01834 if (nes->strip->flag & NLASTRIP_FLAG_REVERSE) { 01835 s1= nes->strip->next; 01836 s2= nes->strip->prev; 01837 } 01838 else { 01839 s1= nes->strip->prev; 01840 s2= nes->strip->next; 01841 } 01842 01843 /* prepare template for 'evaluation strip' 01844 * - based on the transition strip's evaluation strip data 01845 * - strip_mode is NES_TIME_TRANSITION_* based on which endpoint 01846 * - strip_time is the 'normalised' (i.e. in-strip) time for evaluation, 01847 * which doubles up as an additional weighting factor for the strip influences 01848 * which allows us to appear to be 'interpolating' between the two extremes 01849 */ 01850 tmp_nes= *nes; 01851 01852 /* evaluate these strips into a temp-buffer (tmp_channels) */ 01853 // FIXME: modifier evalation here needs some work... 01854 /* first strip */ 01855 tmp_nes.strip_mode= NES_TIME_TRANSITION_START; 01856 tmp_nes.strip= s1; 01857 nlastrip_evaluate(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes); 01858 01859 /* second strip */ 01860 tmp_nes.strip_mode= NES_TIME_TRANSITION_END; 01861 tmp_nes.strip= s2; 01862 nlastrip_evaluate(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes); 01863 01864 01865 /* assumulate temp-buffer and full-buffer, using the 'real' strip */ 01866 nlaevalchan_buffers_accumulate(channels, &tmp_channels, nes); 01867 01868 /* unlink this strip's modifiers from the parent's modifiers again */ 01869 nlaeval_fmodifiers_split_stacks(&nes->strip->modifiers, modifiers); 01870 } 01871 01872 /* evaluate meta-strip */ 01873 static void nlastrip_evaluate_meta (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) 01874 { 01875 ListBase tmp_channels = {NULL, NULL}; 01876 ListBase tmp_modifiers = {NULL, NULL}; 01877 NlaStrip *strip= nes->strip; 01878 NlaEvalStrip *tmp_nes; 01879 float evaltime; 01880 01881 /* meta-strip was calculated normally to have some time to be evaluated at 01882 * and here we 'look inside' the meta strip, treating it as a decorated window to 01883 * it's child strips, which get evaluated as if they were some tracks on a strip 01884 * (but with some extra modifiers to apply). 01885 * 01886 * NOTE: keep this in sync with animsys_evaluate_nla() 01887 */ 01888 01889 /* join this strip's modifiers to the parent's modifiers (own modifiers first) */ 01890 nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers); 01891 01892 /* find the child-strip to evaluate */ 01893 evaltime= (nes->strip_time * (strip->end - strip->start)) + strip->start; 01894 tmp_nes= nlastrips_ctime_get_strip(NULL, &strip->strips, -1, evaltime); 01895 if (tmp_nes == NULL) 01896 return; 01897 01898 /* evaluate child-strip into tmp_channels buffer before accumulating 01899 * in the accumulation buffer 01900 */ 01901 nlastrip_evaluate(ptr, &tmp_channels, &tmp_modifiers, tmp_nes); 01902 01903 /* assumulate temp-buffer and full-buffer, using the 'real' strip */ 01904 nlaevalchan_buffers_accumulate(channels, &tmp_channels, nes); 01905 01906 /* free temp eval-strip */ 01907 MEM_freeN(tmp_nes); 01908 01909 /* unlink this strip's modifiers from the parent's modifiers again */ 01910 nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers); 01911 } 01912 01913 /* evaluates the given evaluation strip */ 01914 void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) 01915 { 01916 NlaStrip *strip= nes->strip; 01917 01918 /* to prevent potential infinite recursion problems (i.e. transition strip, beside meta strip containing a transition 01919 * several levels deep inside it), we tag the current strip as being evaluated, and clear this when we leave 01920 */ 01921 // TODO: be careful with this flag, since some edit tools may be running and have set this while animplayback was running 01922 if (strip->flag & NLASTRIP_FLAG_EDIT_TOUCHED) 01923 return; 01924 strip->flag |= NLASTRIP_FLAG_EDIT_TOUCHED; 01925 01926 /* actions to take depend on the type of strip */ 01927 switch (strip->type) { 01928 case NLASTRIP_TYPE_CLIP: /* action-clip */ 01929 nlastrip_evaluate_actionclip(ptr, channels, modifiers, nes); 01930 break; 01931 case NLASTRIP_TYPE_TRANSITION: /* transition */ 01932 nlastrip_evaluate_transition(ptr, channels, modifiers, nes); 01933 break; 01934 case NLASTRIP_TYPE_META: /* meta */ 01935 nlastrip_evaluate_meta(ptr, channels, modifiers, nes); 01936 break; 01937 01938 default: /* do nothing */ 01939 break; 01940 } 01941 01942 /* clear temp recursion safe-check */ 01943 strip->flag &= ~NLASTRIP_FLAG_EDIT_TOUCHED; 01944 } 01945 01946 /* write the accumulated settings to */ 01947 void nladata_flush_channels (ListBase *channels) 01948 { 01949 NlaEvalChannel *nec; 01950 01951 /* sanity checks */ 01952 if (channels == NULL) 01953 return; 01954 01955 /* for each channel with accumulated values, write its value on the property it affects */ 01956 for (nec= channels->first; nec; nec= nec->next) { 01957 PointerRNA *ptr= &nec->ptr; 01958 PropertyRNA *prop= nec->prop; 01959 int array_index= nec->index; 01960 float value= nec->value; 01961 01962 /* write values - see animsys_write_rna_setting() to sync the code */ 01963 switch (RNA_property_type(prop)) 01964 { 01965 case PROP_BOOLEAN: 01966 if (RNA_property_array_length(ptr, prop)) 01967 RNA_property_boolean_set_index(ptr, prop, array_index, ANIMSYS_FLOAT_AS_BOOL(value)); 01968 else 01969 RNA_property_boolean_set(ptr, prop, ANIMSYS_FLOAT_AS_BOOL(value)); 01970 break; 01971 case PROP_INT: 01972 if (RNA_property_array_length(ptr, prop)) 01973 RNA_property_int_set_index(ptr, prop, array_index, (int)value); 01974 else 01975 RNA_property_int_set(ptr, prop, (int)value); 01976 break; 01977 case PROP_FLOAT: 01978 if (RNA_property_array_length(ptr, prop)) 01979 RNA_property_float_set_index(ptr, prop, array_index, value); 01980 else 01981 RNA_property_float_set(ptr, prop, value); 01982 break; 01983 case PROP_ENUM: 01984 RNA_property_enum_set(ptr, prop, (int)value); 01985 break; 01986 default: 01987 // can't do anything with other types of property.... 01988 break; 01989 } 01990 } 01991 } 01992 01993 /* ---------------------- */ 01994 01995 /* NLA Evaluation function - values are calculated and stored in temporary "NlaEvalChannels" 01996 * ! This is exported so that keyframing code can use this for make use of it for anim layers support 01997 * > echannels: (list<NlaEvalChannels>) evaluation channels with calculated values 01998 */ 01999 static void animsys_evaluate_nla (ListBase *echannels, PointerRNA *ptr, AnimData *adt, float ctime) 02000 { 02001 NlaTrack *nlt; 02002 short track_index=0; 02003 short has_strips = 0; 02004 02005 ListBase estrips= {NULL, NULL}; 02006 NlaEvalStrip *nes; 02007 02008 /* 1. get the stack of strips to evaluate at current time (influence calculated here) */ 02009 for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++) { 02010 /* stop here if tweaking is on and this strip is the tweaking track (it will be the first one that's 'disabled')... */ 02011 if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED)) 02012 break; 02013 02014 /* skip if we're only considering a track tagged 'solo' */ 02015 if ((adt->flag & ADT_NLA_SOLO_TRACK) && (nlt->flag & NLATRACK_SOLO)==0) 02016 continue; 02017 /* skip if track is muted */ 02018 if (nlt->flag & NLATRACK_MUTED) 02019 continue; 02020 02021 /* if this track has strips (but maybe they won't be suitable), set has_strips 02022 * - used for mainly for still allowing normal action evaluation... 02023 */ 02024 if (nlt->strips.first) 02025 has_strips= 1; 02026 02027 /* otherwise, get strip to evaluate for this channel */ 02028 nes= nlastrips_ctime_get_strip(&estrips, &nlt->strips, track_index, ctime); 02029 if (nes) nes->track= nlt; 02030 } 02031 02032 /* add 'active' Action (may be tweaking track) as last strip to evaluate in NLA stack 02033 * - only do this if we're not exclusively evaluating the 'solo' NLA-track 02034 */ 02035 if ((adt->action) && !(adt->flag & ADT_NLA_SOLO_TRACK)) { 02036 /* if there are strips, evaluate action as per NLA rules */ 02037 if ((has_strips) || (adt->actstrip)) { 02038 /* make dummy NLA strip, and add that to the stack */ 02039 NlaStrip dummy_strip= {NULL}; 02040 ListBase dummy_trackslist; 02041 02042 dummy_trackslist.first= dummy_trackslist.last= &dummy_strip; 02043 02044 if ((nlt) && !(adt->flag & ADT_NLA_EDIT_NOMAP)) { 02045 /* edit active action in-place according to its active strip, so copy the data */ 02046 memcpy(&dummy_strip, adt->actstrip, sizeof(NlaStrip)); 02047 dummy_strip.next = dummy_strip.prev = NULL; 02048 } 02049 else { 02050 /* set settings of dummy NLA strip from AnimData settings */ 02051 dummy_strip.act= adt->action; 02052 dummy_strip.remap= adt->remap; 02053 02054 /* action range is calculated taking F-Modifiers into account (which making new strips doesn't do due to the troublesome nature of that) */ 02055 calc_action_range(dummy_strip.act, &dummy_strip.actstart, &dummy_strip.actend, 1); 02056 dummy_strip.start = dummy_strip.actstart; 02057 dummy_strip.end = (IS_EQF(dummy_strip.actstart, dummy_strip.actend)) ? (dummy_strip.actstart + 1.0f): (dummy_strip.actend); 02058 02059 dummy_strip.blendmode= adt->act_blendmode; 02060 dummy_strip.extendmode= adt->act_extendmode; 02061 dummy_strip.influence= adt->act_influence; 02062 } 02063 02064 /* add this to our list of evaluation strips */ 02065 nlastrips_ctime_get_strip(&estrips, &dummy_trackslist, -1, ctime); 02066 } 02067 else { 02068 /* special case - evaluate as if there isn't any NLA data */ 02069 // TODO: this is really just a stop-gap measure... 02070 animsys_evaluate_action(ptr, adt->action, adt->remap, ctime); 02071 return; 02072 } 02073 } 02074 02075 /* only continue if there are strips to evaluate */ 02076 if (estrips.first == NULL) 02077 return; 02078 02079 02080 /* 2. for each strip, evaluate then accumulate on top of existing channels, but don't set values yet */ 02081 for (nes= estrips.first; nes; nes= nes->next) 02082 nlastrip_evaluate(ptr, echannels, NULL, nes); 02083 02084 /* 3. free temporary evaluation data that's not used elsewhere */ 02085 BLI_freelistN(&estrips); 02086 } 02087 02088 /* NLA Evaluation function (mostly for use through do_animdata) 02089 * - All channels that will be affected are not cleared anymore. Instead, we just evaluate into 02090 * some temp channels, where values can be accumulated in one go. 02091 */ 02092 static void animsys_calculate_nla (PointerRNA *ptr, AnimData *adt, float ctime) 02093 { 02094 ListBase echannels= {NULL, NULL}; 02095 02096 // TODO: need to zero out all channels used, otherwise we have problems with threadsafety 02097 // and also when the user jumps between different times instead of moving sequentially... 02098 02099 /* evaluate the NLA stack, obtaining a set of values to flush */ 02100 animsys_evaluate_nla(&echannels, ptr, adt, ctime); 02101 02102 /* flush effects of accumulating channels in NLA to the actual data they affect */ 02103 nladata_flush_channels(&echannels); 02104 02105 /* free temp data */ 02106 BLI_freelistN(&echannels); 02107 } 02108 02109 /* ***************************************** */ 02110 /* Overrides System - Public API */ 02111 02112 /* Clear all overides */ 02113 02114 /* Add or get existing Override for given setting */ 02115 #if 0 02116 AnimOverride *BKE_animsys_validate_override (PointerRNA *UNUSED(ptr), char *UNUSED(path), int UNUSED(array_index)) 02117 { 02118 // FIXME: need to define how to get overrides 02119 return NULL; 02120 } 02121 #endif 02122 02123 /* -------------------- */ 02124 02125 /* Evaluate Overrides */ 02126 static void animsys_evaluate_overrides (PointerRNA *ptr, AnimData *adt) 02127 { 02128 AnimOverride *aor; 02129 02130 /* for each override, simply execute... */ 02131 for (aor= adt->overrides.first; aor; aor= aor->next) 02132 animsys_write_rna_setting(ptr, aor->rna_path, aor->array_index, aor->value); 02133 } 02134 02135 /* ***************************************** */ 02136 /* Evaluation System - Public API */ 02137 02138 /* Overview of how this system works: 02139 * 1) Depsgraph sorts data as necessary, so that data is in an order that means 02140 * that all dependences are resolved before dependants. 02141 * 2) All normal animation is evaluated, so that drivers have some basis values to 02142 * work with 02143 * a. NLA stacks are done first, as the Active Actions act as 'tweaking' tracks 02144 * which modify the effects of the NLA-stacks 02145 * b. Active Action is evaluated as per normal, on top of the results of the NLA tracks 02146 * 02147 * --------------< often in a separate phase... >------------------ 02148 * 02149 * 3) Drivers/expressions are evaluated on top of this, in an order where dependences are 02150 * resolved nicely. 02151 * Note: it may be necessary to have some tools to handle the cases where some higher-level 02152 * drivers are added and cause some problematic dependencies that didn't exist in the local levels... 02153 * 02154 * --------------< always executed >------------------ 02155 * 02156 * Maintainance of editability of settings (XXX): 02157 * In order to ensure that settings that are animated can still be manipulated in the UI without requiring 02158 * that keyframes are added to prevent these values from being overwritten, we use 'overrides'. 02159 * 02160 * Unresolved things: 02161 * - Handling of multi-user settings (i.e. time-offset, group-instancing) -> big cache grids or nodal system? but stored where? 02162 * - Multiple-block dependencies (i.e. drivers for settings are in both local and higher levels) -> split into separate lists? 02163 * 02164 * Current Status: 02165 * - Currently (as of September 2009), overrides we haven't needed to (fully) implement overrides. 02166 * However, the code fo this is relatively harmless, so is left in the code for now. 02167 */ 02168 02169 /* Evaluation loop for evaluation animation data 02170 * 02171 * This assumes that the animation-data provided belongs to the ID block in question, 02172 * and that the flags for which parts of the anim-data settings need to be recalculated 02173 * have been set already by the depsgraph. Now, we use the recalc 02174 */ 02175 void BKE_animsys_evaluate_animdata (Scene *scene, ID *id, AnimData *adt, float ctime, short recalc) 02176 { 02177 PointerRNA id_ptr; 02178 02179 /* sanity checks */ 02180 if ELEM(NULL, id, adt) 02181 return; 02182 02183 /* get pointer to ID-block for RNA to use */ 02184 RNA_id_pointer_create(id, &id_ptr); 02185 02186 /* recalculate keyframe data: 02187 * - NLA before Active Action, as Active Action behaves as 'tweaking track' 02188 * that overrides 'rough' work in NLA 02189 */ 02190 // TODO: need to double check that this all works correctly 02191 if ((recalc & ADT_RECALC_ANIM) || (adt->recalc & ADT_RECALC_ANIM)) 02192 { 02193 /* evaluate NLA data */ 02194 if ((adt->nla_tracks.first) && !(adt->flag & ADT_NLA_EVAL_OFF)) 02195 { 02196 /* evaluate NLA-stack 02197 * - active action is evaluated as part of the NLA stack as the last item 02198 */ 02199 animsys_calculate_nla(&id_ptr, adt, ctime); 02200 } 02201 /* evaluate Active Action only */ 02202 else if (adt->action) 02203 animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime); 02204 02205 /* reset tag */ 02206 adt->recalc &= ~ADT_RECALC_ANIM; 02207 } 02208 02209 /* recalculate drivers 02210 * - Drivers need to be evaluated afterwards, as they can either override 02211 * or be layered on top of existing animation data. 02212 * - Drivers should be in the appropriate order to be evaluated without problems... 02213 */ 02214 if ((recalc & ADT_RECALC_DRIVERS) /*&& (adt->recalc & ADT_RECALC_DRIVERS)*/) // XXX for now, don't check yet, as depsgraph hasn't been updated 02215 { 02216 animsys_evaluate_drivers(&id_ptr, adt, ctime); 02217 } 02218 02219 /* always execute 'overrides' 02220 * - Overrides allow editing, by overwriting the value(s) set from animation-data, with the 02221 * value last set by the user (and not keyframed yet). 02222 * - Overrides are cleared upon frame change and/or keyframing 02223 * - It is best that we execute this everytime, so that no errors are likely to occur. 02224 */ 02225 animsys_evaluate_overrides(&id_ptr, adt); 02226 02227 /* execute and clear all cached property update functions */ 02228 if (scene) 02229 { 02230 Main *bmain = G.main; // xxx - to get passed in! 02231 RNA_property_update_cache_flush(bmain, scene); 02232 RNA_property_update_cache_free(); 02233 } 02234 02235 /* clear recalc flag now */ 02236 adt->recalc= 0; 02237 } 02238 02239 /* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only 02240 * 02241 * This will evaluate only the animation info available in the animation data-blocks 02242 * encountered. In order to enforce the system by which some settings controlled by a 02243 * 'local' (i.e. belonging in the nearest ID-block that setting is related to, not a 02244 * standard 'root') block are overridden by a larger 'user' 02245 */ 02246 void BKE_animsys_evaluate_all_animation (Main *main, Scene *scene, float ctime) 02247 { 02248 ID *id; 02249 02250 if (G.f & G_DEBUG) 02251 printf("Evaluate all animation - %f \n", ctime); 02252 02253 /* macros for less typing 02254 * - only evaluate animation data for id if it has users (and not just fake ones) 02255 * - whether animdata exists is checked for by the evaluation function, though taking 02256 * this outside of the function may make things slightly faster? 02257 */ 02258 #define EVAL_ANIM_IDS(first, aflag) \ 02259 for (id= first; id; id= id->next) { \ 02260 if (ID_REAL_USERS(id) > 0) { \ 02261 AnimData *adt= BKE_animdata_from_id(id); \ 02262 BKE_animsys_evaluate_animdata(scene, id, adt, ctime, aflag); \ 02263 } \ 02264 } 02265 /* another macro for the "embedded" nodetree cases 02266 * - this is like EVAL_ANIM_IDS, but this handles the case "embedded nodetrees" 02267 * (i.e. scene/material/texture->nodetree) which we need a special exception 02268 * for, otherwise they'd get skipped 02269 * - ntp = "node tree parent" = datablock where node tree stuff resides 02270 */ 02271 #define EVAL_ANIM_NODETREE_IDS(first, NtId_Type, aflag) \ 02272 for (id= first; id; id= id->next) { \ 02273 if (ID_REAL_USERS(id) > 0) { \ 02274 AnimData *adt= BKE_animdata_from_id(id); \ 02275 NtId_Type *ntp= (NtId_Type *)id; \ 02276 if (ntp->nodetree) { \ 02277 AnimData *adt2= BKE_animdata_from_id((ID *)ntp->nodetree); \ 02278 BKE_animsys_evaluate_animdata(scene, (ID *)ntp->nodetree, adt2, ctime, ADT_RECALC_ANIM); \ 02279 } \ 02280 BKE_animsys_evaluate_animdata(scene, id, adt, ctime, aflag); \ 02281 } \ 02282 } 02283 02284 /* optimisation: 02285 * when there are no actions, don't go over database and loop over heaps of datablocks, 02286 * which should ultimately be empty, since it is not possible for now to have any animation 02287 * without some actions, and drivers wouldn't get affected by any state changes 02288 * 02289 * however, if there are some curves, we will need to make sure that their 'ctime' property gets 02290 * set correctly, so this optimisation must be skipped in that case... 02291 */ 02292 if ((main->action.first == NULL) && (main->curve.first == NULL)) { 02293 if (G.f & G_DEBUG) 02294 printf("\tNo Actions, so no animation needs to be evaluated...\n"); 02295 02296 return; 02297 } 02298 02299 /* nodes */ 02300 EVAL_ANIM_IDS(main->nodetree.first, ADT_RECALC_ANIM); 02301 02302 /* textures */ 02303 EVAL_ANIM_NODETREE_IDS(main->tex.first, Tex, ADT_RECALC_ANIM); 02304 02305 /* lamps */ 02306 EVAL_ANIM_NODETREE_IDS(main->lamp.first, Lamp, ADT_RECALC_ANIM); 02307 02308 /* materials */ 02309 EVAL_ANIM_NODETREE_IDS(main->mat.first, Material, ADT_RECALC_ANIM); 02310 02311 /* cameras */ 02312 EVAL_ANIM_IDS(main->camera.first, ADT_RECALC_ANIM); 02313 02314 /* shapekeys */ 02315 EVAL_ANIM_IDS(main->key.first, ADT_RECALC_ANIM); 02316 02317 /* metaballs */ 02318 EVAL_ANIM_IDS(main->mball.first, ADT_RECALC_ANIM); 02319 02320 /* curves */ 02321 EVAL_ANIM_IDS(main->curve.first, ADT_RECALC_ANIM); 02322 02323 /* armatures */ 02324 EVAL_ANIM_IDS(main->armature.first, ADT_RECALC_ANIM); 02325 02326 /* lattices */ 02327 EVAL_ANIM_IDS(main->latt.first, ADT_RECALC_ANIM); 02328 02329 /* meshes */ 02330 EVAL_ANIM_IDS(main->mesh.first, ADT_RECALC_ANIM); 02331 02332 /* particles */ 02333 EVAL_ANIM_IDS(main->particle.first, ADT_RECALC_ANIM); 02334 02335 /* speakers */ 02336 EVAL_ANIM_IDS(main->speaker.first, ADT_RECALC_ANIM); 02337 02338 /* objects */ 02339 /* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets 02340 * this tagged by Depsgraph on framechange. This optimisation means that objects 02341 * linked from other (not-visible) scenes will not need their data calculated. 02342 */ 02343 EVAL_ANIM_IDS(main->object.first, 0); 02344 02345 /* worlds */ 02346 EVAL_ANIM_NODETREE_IDS(main->world.first, World, ADT_RECALC_ANIM); 02347 02348 /* scenes */ 02349 EVAL_ANIM_NODETREE_IDS(main->scene.first, Scene, ADT_RECALC_ANIM); 02350 } 02351 02352 /* ***************************************** */