Merged changes in the trunk up to revision 35203.
[blender.git] / source / blender / blenkernel / intern / anim_sys.c
index e03799ff938d333f8c772e51ae4faefac170f116..2268a1535bd77092f87ac5f08eae87f11408f504 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
 
 #include "BLI_blenlib.h"
 #include "BLI_dynstr.h"
+#include "BLI_utildefines.h"
 
 #include "DNA_anim_types.h"
+#include "DNA_material_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
 
 #include "BKE_animsys.h"
 #include "BKE_action.h"
@@ -47,6 +50,7 @@
 #include "BKE_nla.h"
 #include "BKE_global.h"
 #include "BKE_main.h"
+#include "BKE_library.h"
 #include "BKE_utildefines.h"
 
 #include "RNA_access.h"
@@ -70,11 +74,12 @@ short id_type_can_have_animdata (ID *id)
        switch (GS(id->name)) {
                        /* has AnimData */
                case ID_OB:
-               case ID_ME: case ID_MB: case ID_CU: case ID_AR:
+               case ID_ME: case ID_MB: case ID_CU: case ID_AR: case ID_LT:
                case ID_KE:
                case ID_PA:
                case ID_MA: case ID_TE: case ID_NT:
                case ID_LA: case ID_CA: case ID_WO:
+               case ID_LS:
                case ID_SCE:
                {
                        return 1;
@@ -175,7 +180,7 @@ void BKE_free_animdata (ID *id)
 /* Freeing -------------------------------------------- */
 
 /* Make a copy of the given AnimData - to be used when copying datablocks */
-AnimData *BKE_copy_animdata (AnimData *adt)
+AnimData *BKE_copy_animdata (AnimData *adt, const short do_action)
 {
        AnimData *dadt;
        
@@ -185,9 +190,15 @@ AnimData *BKE_copy_animdata (AnimData *adt)
        dadt= MEM_dupallocN(adt);
        
        /* make a copy of action - at worst, user has to delete copies... */
-       dadt->action= copy_action(adt->action);
-       dadt->tmpact= copy_action(adt->tmpact);
-       
+       if(do_action) {
+               dadt->action= copy_action(adt->action);
+               dadt->tmpact= copy_action(adt->tmpact);
+       }
+       else {
+               id_us_plus((ID *)dadt->action);
+               id_us_plus((ID *)dadt->tmpact);
+       }
+
        /* duplicate NLA data */
        copy_nladata(&dadt->nla_tracks, &adt->nla_tracks);
        
@@ -201,7 +212,7 @@ AnimData *BKE_copy_animdata (AnimData *adt)
        return dadt;
 }
 
-int BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from)
+int BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from, const short do_action)
 {
        AnimData *adt;
 
@@ -213,13 +224,26 @@ int BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from)
        adt = BKE_animdata_from_id(id_from);
        if (adt) {
                IdAdtTemplate *iat = (IdAdtTemplate *)id_to;
-               iat->adt= BKE_copy_animdata(adt);
+               iat->adt= BKE_copy_animdata(adt, do_action);
        }
 
        return 1;
 }
 
-
+void BKE_copy_animdata_id_action(struct ID *id)
+{
+       AnimData *adt= BKE_animdata_from_id(id);
+       if(adt) {
+               if(adt->action) {
+                       ((ID *)adt->action)->us--;
+                       adt->action= copy_action(adt->action);
+               }
+               if(adt->tmpact) {
+                       ((ID *)adt->tmpact)->us--;
+                       adt->tmpact= copy_action(adt->tmpact);
+               }
+       }
+}
 
 /* Make Local -------------------------------------------- */
 
@@ -254,6 +278,176 @@ void BKE_animdata_make_local(AnimData *adt)
                make_local_strips(&nlt->strips);
 }
 
+/* Sub-ID Regrouping ------------------------------------------- */
+
+/* helper heuristic for determining if a path is compatible with the basepath 
+ * < path: (str) full RNA-path from some data (usually an F-Curve) to compare
+ * < basepath: (str) shorter path fragment to look for
+ * > returns (bool) whether there is a match
+ */
+static short animpath_matches_basepath (const char path[], const char basepath[])
+{
+       /* we need start of path to be basepath */
+       return (path && basepath) && (strstr(path, basepath) == path);
+}
+
+/* Move F-Curves in src action to dst action, setting up all the necessary groups 
+ * for this to happen, but only if the F-Curves being moved have the appropriate 
+ * "base path". 
+ *     - This is used when data moves from one datablock to another, causing the
+ *       F-Curves to need to be moved over too
+ */
+void action_move_fcurves_by_basepath (bAction *srcAct, bAction *dstAct, const char basepath[])
+{
+       FCurve *fcu, *fcn=NULL;
+       
+       /* sanity checks */
+       if ELEM3(NULL, srcAct, dstAct, basepath) {
+               if (G.f & G_DEBUG) {
+                       printf("ERROR: action_partition_fcurves_by_basepath(%p, %p, %p) has insufficient info to work with\n",
+                                       srcAct, dstAct, basepath);
+               }
+               return;
+       }
+               
+       /* clear 'temp' flags on all groups in src, as we'll be needing them later 
+        * to identify groups that we've managed to empty out here
+        */
+       action_groups_clear_tempflags(srcAct);
+       
+       /* iterate over all src F-Curves, moving over the ones that need to be moved */
+       for (fcu = srcAct->curves.first; fcu; fcu = fcn) {
+               /* store next pointer in case we move stuff */
+               fcn = fcu->next;
+               
+               /* should F-Curve be moved over?
+                *      - we only need the start of the path to match basepath
+                */
+               if (animpath_matches_basepath(fcu->rna_path, basepath)) {                       
+                       bActionGroup *agrp = NULL;
+                       
+                       /* if grouped... */
+                       if (fcu->grp) {
+                               /* make sure there will be a matching group on the other side for the migrants */
+                               agrp = action_groups_find_named(dstAct, fcu->grp->name);
+                               
+                               if (agrp == NULL) {
+                                       /* add a new one with a similar name (usually will be the same though) */
+                                       agrp = action_groups_add_new(dstAct, fcu->grp->name);
+                               }
+                               
+                               /* old groups should be tagged with 'temp' flags so they can be removed later
+                                * if we remove everything from them
+                                */
+                               fcu->grp->flag |= AGRP_TEMP;
+                       }
+                       
+                       /* perform the migration now */
+                       action_groups_remove_channel(srcAct, fcu);
+                       
+                       if (agrp)
+                               action_groups_add_channel(dstAct, agrp, fcu);
+                       else
+                               BLI_addtail(&dstAct->curves, fcu);
+               }
+       }
+       
+       /* cleanup groups (if present) */
+       if (srcAct->groups.first) {
+               bActionGroup *agrp, *grp=NULL;
+               
+               for (agrp = srcAct->groups.first; agrp; agrp = grp) {
+                       grp = agrp->next;
+                       
+                       /* only tagged groups need to be considered - clearing these tags or removing them */
+                       if (agrp->flag & AGRP_TEMP) {
+                               /* if group is empty and tagged, then we can remove as this operation
+                                * moved out all the channels that were formerly here
+                                */
+                               if (agrp->channels.first == NULL)
+                                       BLI_freelinkN(&srcAct->groups, agrp);
+                               else
+                                       agrp->flag &= ~AGRP_TEMP;
+                       }
+               }
+       }
+}
+
+/* Transfer the animation data from srcID to dstID where the srcID
+ * animation data is based off "basepath", creating new AnimData and
+ * associated data as necessary
+ */
+void BKE_animdata_separate_by_basepath (ID *srcID, ID *dstID, ListBase *basepaths)
+{
+       AnimData *srcAdt=NULL, *dstAdt=NULL;
+       LinkData *ld;
+       
+       /* sanity checks */
+       if ELEM(NULL, srcID, dstID) {
+               if (G.f & G_DEBUG)
+                       printf("ERROR: no source or destination ID to separate AnimData with\n");
+               return;
+       }
+       
+       /* get animdata from src, and create for destination (if needed) */
+       srcAdt = BKE_animdata_from_id(srcID);
+       dstAdt = BKE_id_add_animdata(dstID);
+       
+       if ELEM(NULL, srcAdt, dstAdt) {
+               if (G.f & G_DEBUG)
+                       printf("ERROR: no AnimData for this pair of ID's\n");
+               return;
+       }
+       
+       /* active action */
+       if (srcAdt->action) {
+               /* set up an action if necessary, and name it in a similar way so that it can be easily found again */
+               if (dstAdt->action == NULL) {
+                       dstAdt->action = add_empty_action(srcAdt->action->id.name+2);
+               }
+               else if (dstAdt->action == srcAdt->action) {
+                       printf("Argh! Source and Destination share animation! ('%s' and '%s' both use '%s') Making new empty action\n",
+                               srcID->name, dstID->name, srcAdt->action->id.name);
+                       
+                       // TODO: review this...
+                       id_us_min(&dstAdt->action->id);
+                       dstAdt->action = add_empty_action(dstAdt->action->id.name+2);
+               }
+                       
+               /* loop over base paths, trying to fix for each one... */
+               for (ld = basepaths->first; ld; ld = ld->next) {
+                       const char *basepath = (const char *)ld->data;
+                       action_move_fcurves_by_basepath(srcAdt->action, dstAdt->action, basepath);
+               }
+       }
+       
+       /* drivers */
+       if (srcAdt->drivers.first) {
+               FCurve *fcu, *fcn=NULL;
+               
+               /* check each driver against all the base paths to see if any should go */
+               for (fcu = srcAdt->drivers.first; fcu; fcu = fcn) {
+                       fcn = fcu->next;
+                       
+                       /* try each basepath in turn, but stop on the first one which works */
+                       for (ld = basepaths->first; ld; ld = ld->next) {
+                               const char *basepath = (const char *)ld->data;
+                               
+                               if (animpath_matches_basepath(fcu->rna_path, basepath)) {
+                                       /* just need to change lists */
+                                       BLI_remlink(&srcAdt->drivers, fcu);
+                                       BLI_addtail(&dstAdt->drivers, fcu);
+                                       
+                                       // TODO: add depsgraph flushing calls?
+                                       
+                                       /* can stop now, as moved already */
+                                       break;
+                               }
+                       }
+               }
+       }
+}
+
 /* Path Validation -------------------------------------------- */
 
 /* Check if a given RNA Path is valid, by tracing it from the given ID, and seeing if we can resolve it */
@@ -272,7 +466,7 @@ static short check_rna_path_is_valid (ID *owner_id, char *path)
 /* Check if some given RNA Path needs fixing - free the given path and set a new one as appropriate 
  * NOTE: we assume that oldName and newName have [" "] padding around them
  */
-static char *rna_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, char *oldpath, int verify_paths)
+static char *rna_path_rename_fix (ID *owner_id, const char *prefix, char *oldName, char *newName, char *oldpath, int verify_paths)
 {
        char *prefixPtr= strstr(oldpath, prefix);
        char *oldNamePtr= strstr(oldpath, oldName);
@@ -330,7 +524,7 @@ static char *rna_path_rename_fix (ID *owner_id, char *prefix, char *oldName, cha
 }
 
 /* Check RNA-Paths for a list of F-Curves */
-static void fcurves_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, ListBase *curves, int verify_paths)
+static void fcurves_path_rename_fix (ID *owner_id, const char *prefix, char *oldName, char *newName, ListBase *curves, int verify_paths)
 {
        FCurve *fcu;
        
@@ -343,7 +537,7 @@ static void fcurves_path_rename_fix (ID *owner_id, char *prefix, char *oldName,
 }
 
 /* Check RNA-Paths for a list of Drivers */
-static void drivers_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, char *oldKey, char *newKey, ListBase *curves, int verify_paths)
+static void drivers_path_rename_fix (ID *owner_id, const char *prefix, char *oldName, char *newName, char *oldKey, char *newKey, ListBase *curves, int verify_paths)
 {
        FCurve *fcu;
        
@@ -383,7 +577,7 @@ static void drivers_path_rename_fix (ID *owner_id, char *prefix, char *oldName,
 }
 
 /* Fix all RNA-Paths for Actions linked to NLA Strips */
-static void nlastrips_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, ListBase *strips, int verify_paths)
+static void nlastrips_path_rename_fix (ID *owner_id, const char *prefix, char *oldName, char *newName, ListBase *strips, int verify_paths)
 {
        NlaStrip *strip;
        
@@ -403,7 +597,7 @@ static void nlastrips_path_rename_fix (ID *owner_id, char *prefix, char *oldName
  * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
  *             i.e. pose.bones["Bone"]
  */
-void BKE_animdata_fix_paths_rename (ID *owner_id, AnimData *adt, char *prefix, char *oldName, char *newName, int oldSubscript, int newSubscript, int verify_paths)
+void BKE_animdata_fix_paths_rename (ID *owner_id, AnimData *adt, const char *prefix, char *oldName, char *newName, int oldSubscript, int newSubscript, int verify_paths)
 {
        NlaTrack *nlt;
        char *oldN, *newN;
@@ -443,45 +637,77 @@ void BKE_animdata_fix_paths_rename (ID *owner_id, AnimData *adt, char *prefix, c
 /* Whole Database Ops -------------------------------------------- */
 
 /* apply the given callback function on all data in main database */
-void BKE_animdata_main_cb (Main *main, ID_AnimData_Edit_Callback func, void *user_data)
+void BKE_animdata_main_cb (Main *mainptr, ID_AnimData_Edit_Callback func, void *user_data)
 {
        ID *id;
 
+       /* standard data version */
 #define ANIMDATA_IDS_CB(first) \
        for (id= first; id; id= id->next) { \
                AnimData *adt= BKE_animdata_from_id(id); \
                if (adt) func(id, adt, user_data); \
        }
 
-       ANIMDATA_IDS_CB(main->nodetree.first);  /* nodes */
-       ANIMDATA_IDS_CB(main->tex.first);               /* textures */
-       ANIMDATA_IDS_CB(main->lamp.first);              /* lamps */
-       ANIMDATA_IDS_CB(main->mat.first);               /* materials */
-       ANIMDATA_IDS_CB(main->camera.first);    /* cameras */
-       ANIMDATA_IDS_CB(main->key.first);               /* shapekeys */
-       ANIMDATA_IDS_CB(main->mball.first);             /* metaballs */
-       ANIMDATA_IDS_CB(main->curve.first);             /* curves */
-       ANIMDATA_IDS_CB(main->armature.first);  /* armatures */
-       ANIMDATA_IDS_CB(main->mesh.first);              /* meshes */
-       ANIMDATA_IDS_CB(main->particle.first);  /* particles */
-       ANIMDATA_IDS_CB(main->object.first);    /* objects */
-       ANIMDATA_IDS_CB(main->world.first);             /* worlds */
+       /* "embedded" nodetree cases (i.e. scene/material/texture->nodetree) */
+#define ANIMDATA_NODETREE_IDS_CB(first, NtId_Type) \
+       for (id= first; id; id= id->next) { \
+               AnimData *adt= BKE_animdata_from_id(id); \
+               NtId_Type *ntp= (NtId_Type *)id; \
+               if (ntp->nodetree) { \
+                       AnimData *adt2= BKE_animdata_from_id((ID *)ntp); \
+                       if (adt2) func(id, adt2, user_data); \
+               } \
+               if (adt) func(id, adt, user_data); \
+       }
 
-       /* scenes */
-       for (id= main->scene.first; id; id= id->next) {
-               AnimData *adt= BKE_animdata_from_id(id);
-               Scene *scene= (Scene *)id;
+       /* nodes */
+       ANIMDATA_IDS_CB(mainptr->nodetree.first);
                
-               /* do compositing nodes first (since these aren't included in main tree) */
-               if (scene->nodetree) {
-                       AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree);
-                       if (adt2) func(id, adt2, user_data);
-               }
+       /* textures */
+       ANIMDATA_NODETREE_IDS_CB(mainptr->tex.first, Tex);
                
-               /* now fix scene animation data as per normal */
-               if (adt) func((ID *)id, adt, user_data);
+       /* lamps */
+       ANIMDATA_IDS_CB(mainptr->lamp.first);
+       
+       /* materials */
+       ANIMDATA_NODETREE_IDS_CB(mainptr->mat.first, Material);
+       
+       /* cameras */
+       ANIMDATA_IDS_CB(mainptr->camera.first);
+       
+       /* shapekeys */
+       ANIMDATA_IDS_CB(mainptr->key.first);
+       
+       /* metaballs */
+       ANIMDATA_IDS_CB(mainptr->mball.first);
+       
+       /* curves */
+       ANIMDATA_IDS_CB(mainptr->curve.first);
+       
+       /* armatures */
+       ANIMDATA_IDS_CB(mainptr->armature.first);
+       
+       /* lattices */
+       ANIMDATA_IDS_CB(mainptr->latt.first);
+       
+       /* meshes */
+       ANIMDATA_IDS_CB(mainptr->mesh.first);
+       
+       /* particles */
+       ANIMDATA_IDS_CB(mainptr->particle.first);
+       
+       /* objects */
+       ANIMDATA_IDS_CB(mainptr->object.first);
+       
+       /* worlds */
+       ANIMDATA_IDS_CB(mainptr->world.first);
+       
+       /* scenes */
+       ANIMDATA_NODETREE_IDS_CB(mainptr->scene.first, Scene);
+       
+       /* line styles */
+       ANIMDATA_IDS_CB(mainptr->linestyle.first);
        }
-}
 
 /* Fix all RNA-Paths throughout the database (directly access the Global.main version)
  * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
@@ -503,17 +729,29 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa
                BKE_animdata_fix_paths_rename(id, adt, prefix, oldName, newName, 0, 0, 1);\
        }
        
+       /* another version of this macro for nodetrees */
+#define RENAMEFIX_ANIM_NODETREE_IDS(first, NtId_Type) \
+       for (id= first; id; id= id->next) { \
+               AnimData *adt= BKE_animdata_from_id(id); \
+               NtId_Type *ntp= (NtId_Type *)id; \
+               if (ntp->nodetree) { \
+                       AnimData *adt2= BKE_animdata_from_id((ID *)ntp); \
+                       BKE_animdata_fix_paths_rename((ID *)ntp, adt2, prefix, oldName, newName, 0, 0, 1);\
+               } \
+               BKE_animdata_fix_paths_rename(id, adt, prefix, oldName, newName, 0, 0, 1);\
+       }
+       
        /* nodes */
        RENAMEFIX_ANIM_IDS(mainptr->nodetree.first);
        
        /* textures */
-       RENAMEFIX_ANIM_IDS(mainptr->tex.first);
+       RENAMEFIX_ANIM_NODETREE_IDS(mainptr->tex.first, Tex);
        
        /* lamps */
        RENAMEFIX_ANIM_IDS(mainptr->lamp.first);
        
        /* materials */
-       RENAMEFIX_ANIM_IDS(mainptr->mat.first);
+       RENAMEFIX_ANIM_NODETREE_IDS(mainptr->mat.first, Material);
        
        /* cameras */
        RENAMEFIX_ANIM_IDS(mainptr->camera.first);
@@ -530,8 +768,11 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa
        /* armatures */
        RENAMEFIX_ANIM_IDS(mainptr->armature.first);
        
+       /* lattices */
+       RENAMEFIX_ANIM_IDS(mainptr->latt.first);
+       
        /* meshes */
-       // TODO...
+       RENAMEFIX_ANIM_IDS(mainptr->mesh.first);
        
        /* particles */
        RENAMEFIX_ANIM_IDS(mainptr->particle.first);
@@ -542,22 +783,13 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa
        /* worlds */
        RENAMEFIX_ANIM_IDS(mainptr->world.first);
        
+       /* linestyles */
+       RENAMEFIX_ANIM_IDS(mainptr->linestyle.first);
+       
        /* scenes */
-       for (id= mainptr->scene.first; id; id= id->next) {
-               AnimData *adt= BKE_animdata_from_id(id);
-               Scene *scene= (Scene *)id;
-               
-               /* do compositing nodes first (since these aren't included in main tree) */
-               if (scene->nodetree) {
-                       AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree);
-                       BKE_animdata_fix_paths_rename((ID *)scene->nodetree, adt2, prefix, oldName, newName, 0, 0, 1);
+       RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene);
                }
                
-               /* now fix scene animation data as per normal */
-               BKE_animdata_fix_paths_rename((ID *)id, adt, prefix, oldName, newName, 0, 0, 1);
-       }
-}
-
 /* *********************************** */ 
 /* KeyingSet API */
 
@@ -584,7 +816,7 @@ KS_Path *BKE_keyingset_find_path (KeyingSet *ks, ID *id, const char group_name[]
                        eq_id= 0;
                
                /* path */
-               if ((ksp->rna_path==0) || strcmp(rna_path, ksp->rna_path))
+               if ((ksp->rna_path==NULL) || strcmp(rna_path, ksp->rna_path))
                        eq_path= 0;
                        
                /* index - need to compare whole-array setting too... */
@@ -614,12 +846,9 @@ KeyingSet *BKE_keyingset_add (ListBase *list, const char name[], short flag, sho
        
        /* allocate new KeyingSet */
        ks= MEM_callocN(sizeof(KeyingSet), "KeyingSet");
-       
-       if (name)
-               strncpy(ks->name, name, sizeof(ks->name));
-       else
-               strcpy(ks->name, "KeyingSet");
-       
+
+       BLI_strncpy(ks->name, name ? name : "KeyingSet", sizeof(ks->name));
+
        ks->flag= flag;
        ks->keyingflag= keyingflag;
        
@@ -665,9 +894,9 @@ KS_Path *BKE_keyingset_add_path (KeyingSet *ks, ID *id, const char group_name[],
        /* just store absolute info */
        ksp->id= id;
        if (group_name)
-               BLI_snprintf(ksp->group, 64, group_name);
+               BLI_strncpy(ksp->group, group_name, sizeof(ksp->group));
        else
-               strcpy(ksp->group, "");
+               ksp->group[0]= '\0';
        
        /* store additional info for relative paths (just in case user makes the set relative) */
        if (id)
@@ -695,10 +924,11 @@ void BKE_keyingset_free_path (KeyingSet *ks, KS_Path *ksp)
        /* sanity check */
        if ELEM(NULL, ks, ksp)
                return;
-       
+
        /* free RNA-path info */
-       MEM_freeN(ksp->rna_path);
-       
+       if(ksp->rna_path)
+               MEM_freeN(ksp->rna_path);
+
        /* free path itself */
        BLI_freelinkN(&ks->paths, ksp);
 }
@@ -1591,9 +1821,6 @@ void nladata_flush_channels (ListBase *channels)
  */
 static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime)
 {
-       ListBase dummy_trackslist = {NULL, NULL};
-       NlaStrip dummy_strip;
-       
        NlaTrack *nlt;
        short track_index=0;
        short has_strips = 0;
@@ -1636,7 +1863,9 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime)
                /* if there are strips, evaluate action as per NLA rules */
                if ((has_strips) || (adt->actstrip)) {
                        /* make dummy NLA strip, and add that to the stack */
-                       memset(&dummy_strip, 0, sizeof(NlaStrip));
+                       NlaStrip dummy_strip= {NULL};
+                       ListBase dummy_trackslist;
+                       
                        dummy_trackslist.first= dummy_trackslist.last= &dummy_strip;
                        
                        if ((nlt) && !(adt->flag & ADT_NLA_EDIT_NOMAP)) {
@@ -1693,11 +1922,13 @@ static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime)
 /* Clear all overides */
 
 /* Add or get existing Override for given setting */
+#if 0
 AnimOverride *BKE_animsys_validate_override (PointerRNA *UNUSED(ptr), char *UNUSED(path), int UNUSED(array_index))
 {
        // FIXME: need to define how to get overrides
        return NULL;
 } 
+#endif
 
 /* -------------------- */
 
@@ -1821,7 +2052,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
        if (G.f & G_DEBUG)
                printf("Evaluate all animation - %f \n", ctime);
        
-       /* macro for less typing 
+       /* macros for less typing 
         *      - only evaluate animation data for id if it has users (and not just fake ones)
         *      - whether animdata exists is checked for by the evaluation function, though taking 
         *        this outside of the function may make things slightly faster?
@@ -1833,6 +2064,24 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
                        BKE_animsys_evaluate_animdata(id, adt, ctime, aflag); \
                } \
        }
+       /* another macro for the "embedded" nodetree cases 
+        *      - this is like EVAL_ANIM_IDS, but this handles the case "embedded nodetrees" 
+        *        (i.e. scene/material/texture->nodetree) which we need a special exception
+        *        for, otherwise they'd get skipped
+        *      - ntp = "node tree parent" = datablock where node tree stuff resides
+        */
+#define EVAL_ANIM_NODETREE_IDS(first, NtId_Type, aflag) \
+       for (id= first; id; id= id->next) { \
+               if (ID_REAL_USERS(id) > 0) { \
+                       AnimData *adt= BKE_animdata_from_id(id); \
+                       NtId_Type *ntp= (NtId_Type *)id; \
+                       if (ntp->nodetree) { \
+                               AnimData *adt2= BKE_animdata_from_id((ID *)ntp->nodetree); \
+                               BKE_animsys_evaluate_animdata((ID *)ntp->nodetree, adt2, ctime, ADT_RECALC_ANIM); \
+                       } \
+                       BKE_animsys_evaluate_animdata(id, adt, ctime, aflag); \
+               } \
+       }
        
        /* optimisation: 
         * when there are no actions, don't go over database and loop over heaps of datablocks, 
@@ -1853,19 +2102,18 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
        EVAL_ANIM_IDS(main->nodetree.first, ADT_RECALC_ANIM);
        
        /* textures */
-       EVAL_ANIM_IDS(main->tex.first, ADT_RECALC_ANIM);
+       EVAL_ANIM_NODETREE_IDS(main->tex.first, Tex, ADT_RECALC_ANIM);
        
        /* lamps */
        EVAL_ANIM_IDS(main->lamp.first, ADT_RECALC_ANIM);
        
        /* materials */
-       EVAL_ANIM_IDS(main->mat.first, ADT_RECALC_ANIM);
+       EVAL_ANIM_NODETREE_IDS(main->mat.first, Material, ADT_RECALC_ANIM);
        
        /* cameras */
        EVAL_ANIM_IDS(main->camera.first, ADT_RECALC_ANIM);
        
        /* shapekeys */
-               // TODO: we probably need the same hack as for curves (ctime-hack)
        EVAL_ANIM_IDS(main->key.first, ADT_RECALC_ANIM);
        
        /* metaballs */
@@ -1877,12 +2125,18 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
        /* armatures */
        EVAL_ANIM_IDS(main->armature.first, ADT_RECALC_ANIM);
        
+       /* lattices */
+       EVAL_ANIM_IDS(main->latt.first, ADT_RECALC_ANIM);
+       
        /* meshes */
        EVAL_ANIM_IDS(main->mesh.first, ADT_RECALC_ANIM);
        
        /* particles */
        EVAL_ANIM_IDS(main->particle.first, ADT_RECALC_ANIM);
        
+       /* linestyles */
+       EVAL_ANIM_IDS(main->linestyle.first, ADT_RECALC_ANIM);
+       
        /* objects */
                /* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets 
                 * this tagged by Depsgraph on framechange. This optimisation means that objects
@@ -1894,19 +2148,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
        EVAL_ANIM_IDS(main->world.first, ADT_RECALC_ANIM);
        
        /* scenes */
-       for (id= main->scene.first; id; id= id->next) {
-               AnimData *adt= BKE_animdata_from_id(id);
-               Scene *scene= (Scene *)id;
-               
-               /* do compositing nodes first (since these aren't included in main tree) */
-               if (scene->nodetree) {
-                       AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree);
-                       BKE_animsys_evaluate_animdata((ID *)scene->nodetree, adt2, ctime, ADT_RECALC_ANIM);
-               }
-               
-               /* now execute scene animation data as per normal */
-               BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM);
-       }
+       EVAL_ANIM_NODETREE_IDS(main->scene.first, Scene, ADT_RECALC_ANIM);
 }
 
 /* ***************************************** */