Blender V2.61 - r43446

anim_sys.c

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