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