NLA-SoC: Merge from 2.5 branch 19863:20113
[blender-staging.git] / source / blender / blenkernel / intern / anim_sys.c
1 /* Testing code for new animation system in 2.5 
2  * Copyright 2009, Joshua Leung
3  */
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <stddef.h>
8 #include <float.h>
9
10 #include "MEM_guardedalloc.h"
11
12 #include "BLI_blenlib.h"
13 #include "BLI_arithb.h"
14 #include "BLI_dynstr.h"
15
16 #include "BKE_animsys.h"
17 #include "BKE_action.h"
18 #include "BKE_fcurve.h"
19 #include "BKE_global.h"
20 #include "BKE_main.h"
21 #include "BKE_utildefines.h"
22
23 #include "RNA_access.h"
24 #include "RNA_types.h"
25
26 #include "DNA_anim_types.h"
27
28 /* ***************************************** */
29 /* AnimData API */
30
31 /* Getter/Setter -------------------------------------------- */
32
33 /* Internal utility to check if ID can have AnimData */
34 static short id_has_animdata (ID *id)
35 {
36         /* sanity check */
37         if (id == NULL)
38                 return 0;
39                 
40         /* Only some ID-blocks have this info for now */
41         // TODO: finish adding this for the other blocktypes
42         switch (GS(id->name)) {
43                         /* has AnimData */
44                 case ID_OB:
45                 case ID_CU:
46                 case ID_KE:
47                 case ID_MA: case ID_TE: case ID_NT:
48                 case ID_LA: case ID_CA: case ID_WO:
49                 case ID_SCE:
50                 {
51                         return 1;
52                 }
53                 
54                         /* no AnimData */
55                 default:
56                         return 0;
57         }
58 }
59
60
61 /* Get AnimData from the given ID-block. In order for this to work, we assume that 
62  * the AnimData pointer is stored immediately after the given ID-block in the struct,
63  * as per IdAdtTemplate.
64  */
65 AnimData *BKE_animdata_from_id (ID *id)
66 {
67         /* only some ID-blocks have this info for now, so we cast the 
68          * types that do to be of type IdAdtTemplate, and extract the
69          * AnimData that way
70          */
71         if (id_has_animdata(id)) {
72                 IdAdtTemplate *iat= (IdAdtTemplate *)id;
73                 return iat->adt;
74         }
75         else
76                 return NULL;
77 }
78
79 /* Add AnimData to the given ID-block. In order for this to work, we assume that 
80  * the AnimData pointer is stored immediately after the given ID-block in the struct,
81  * as per IdAdtTemplate. Also note that 
82  */
83 AnimData *BKE_id_add_animdata (ID *id)
84 {
85         /* Only some ID-blocks have this info for now, so we cast the 
86          * types that do to be of type IdAdtTemplate, and add the AnimData
87          * to it using the template
88          */
89         if (id_has_animdata(id)) {
90                 IdAdtTemplate *iat= (IdAdtTemplate *)id;
91                 
92                 /* check if there's already AnimData, in which case, don't add */
93                 if (iat->adt == NULL)
94                         iat->adt= MEM_callocN(sizeof(AnimData), "AnimData");
95                 
96                 return iat->adt;
97         }
98         else 
99                 return NULL;
100 }
101
102 /* Freeing -------------------------------------------- */
103
104 /* Free AnimData used by the nominated ID-block, and clear ID-block's AnimData pointer */
105 void BKE_free_animdata (ID *id)
106 {
107         /* Only some ID-blocks have this info for now, so we cast the 
108          * types that do to be of type IdAdtTemplate
109          */
110         if (id_has_animdata(id)) {
111                 IdAdtTemplate *iat= (IdAdtTemplate *)id;
112                 AnimData *adt= iat->adt;
113                 
114                 /* check if there's any AnimData to start with */
115                 if (adt) {
116                         /* unlink action (don't free, as it's in its own list) */
117                         if (adt->action)
118                                 adt->action->id.us--;
119                                 
120                         /* free drivers - stored as a list of F-Curves */
121                         free_fcurves(&adt->drivers);
122                         
123                         /* free overrides */
124                         // TODO...
125                         
126                         /* free animdata now */
127                         MEM_freeN(adt);
128                         iat->adt= NULL;
129                 }
130         }
131 }
132
133 /* Freeing -------------------------------------------- */
134
135 /* Make a copy of the given AnimData - to be used when copying datablocks */
136 AnimData *BKE_copy_animdata (AnimData *adt)
137 {
138         AnimData *dadt;
139         
140         /* sanity check before duplicating struct */
141         if (adt == NULL)
142                 return NULL;
143         dadt= MEM_dupallocN(adt);
144         
145         /* make a copy of action - at worst, user has to delete copies... */
146         // XXX review this... it might not be optimal behaviour yet...
147         //id_us_plus((ID *)dadt->action);
148         dadt->action= copy_action(adt->action);
149         
150         /* duplicate NLA data */
151         // XXX todo...
152         
153         /* duplicate drivers (F-Curves) */
154         copy_fcurves(&dadt->drivers, &adt->drivers);
155         
156         /* don't copy overrides */
157         dadt->overrides.first= dadt->overrides.last= NULL;
158         
159         /* return */
160         return dadt;
161 }
162
163 /* *********************************** */ 
164 /* KeyingSet API */
165
166 /* NOTES:
167  * It is very likely that there will be two copies of the api - one for internal use,
168  * and one 'operator' based wrapper of the internal API, which should allow for access
169  * from Python/scripts so that riggers can automate the creation of KeyingSets for their rigs.
170  */
171
172 /* Finding Tools --------------------------- */
173
174 /* Find the first path that matches the given criteria */
175 // TODO: do we want some method to perform partial matches too?
176 KS_Path *BKE_keyingset_find_destination (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, int group_mode)
177 {
178         KS_Path *ksp;
179         
180         /* sanity checks */
181         if ELEM(NULL, ks, rna_path)
182                 return NULL;
183         
184         /* ID is optional for relative KeyingSets, but is necessary for absolute KeyingSets */
185         if (id == NULL) {
186                 if (ks->flag & KEYINGSET_ABSOLUTE)
187                         return NULL;
188         }
189         
190         /* loop over paths in the current KeyingSet, finding the first one where all settings match 
191          * (i.e. the first one where none of the checks fail and equal 0)
192          */
193         for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
194                 short eq_id=1, eq_path=1, eq_index=1, eq_group=1;
195                 
196                 /* id */
197                 if ((ks->flag & KEYINGSET_ABSOLUTE) && (id != ksp->id))
198                         eq_id= 0;
199                 
200                 /* path */
201                 if ((ksp->rna_path==0) || strcmp(rna_path, ksp->rna_path))
202                         eq_path= 0;
203                         
204                 /* index */
205                 if (ksp->array_index != array_index)
206                         eq_index= 0;
207                         
208                 /* group */
209                 if (group_name) {
210                         // FIXME: these checks need to be coded... for now, it's not too important though
211                 }
212                         
213                 /* if all aspects are ok, return */
214                 if (eq_id && eq_path && eq_index && eq_group)
215                         return ksp;
216         }
217         
218         /* none found */
219         return NULL;
220 }
221  
222 /* Defining Tools --------------------------- */
223
224 /* Used to create a new 'custom' KeyingSet for the user, that will be automatically added to the stack */
225 KeyingSet *BKE_keyingset_add (ListBase *list, const char name[], short flag, short keyingflag)
226 {
227         KeyingSet *ks;
228         
229         /* allocate new KeyingSet */
230         ks= MEM_callocN(sizeof(KeyingSet), "KeyingSet");
231         
232         if (name)
233                 BLI_snprintf(ks->name, 64, name);
234         else
235                 strcpy(ks->name, "Keying Set");
236         
237         ks->flag= flag;
238         ks->keyingflag= keyingflag;
239         
240         /* add KeyingSet to list */
241         BLI_addtail(list, ks);
242         
243         /* make sure KeyingSet has a unique name (this helps with identification) */
244         BLI_uniquename(list, ks, "Keying Set", ' ', offsetof(KeyingSet, name), 64);
245         
246         /* return new KeyingSet for further editing */
247         return ks;
248 }
249
250 /* Add a destination to a KeyingSet. Nothing is returned for now...
251  * Checks are performed to ensure that destination is appropriate for the KeyingSet in question
252  */
253 void BKE_keyingset_add_destination (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, short flag, short groupmode)
254 {
255         KS_Path *ksp;
256         
257         /* sanity checks */
258         if ELEM(NULL, ks, rna_path)
259                 return;
260         
261         /* ID is optional for relative KeyingSets, but is necessary for absolute KeyingSets */
262         if (id == NULL) {
263                 if (ks->flag & KEYINGSET_ABSOLUTE)
264                         return;
265         }
266         
267         /* don't add if there is already a matching KS_Path in the KeyingSet */
268         if (BKE_keyingset_find_destination(ks, id, group_name, rna_path, array_index, groupmode))
269                 return;
270         
271         /* allocate a new KeyingSet Path */
272         ksp= MEM_callocN(sizeof(KS_Path), "KeyingSet Path");
273         
274         /* just store absolute info */
275         if (ks->flag & KEYINGSET_ABSOLUTE) {
276                 ksp->id= id;
277                 if (group_name)
278                         BLI_snprintf(ksp->group, 64, group_name);
279                 else
280                         strcpy(ksp->group, "");
281         }
282         
283         /* store additional info for relative paths (just in case user makes the set relative) */
284         if (id)
285                 ksp->idtype= GS(id->name);
286         
287         /* just copy path info */
288         // XXX no checks are performed for templates yet
289         // should array index be checked too?
290         ksp->rna_path= BLI_strdupn(rna_path, strlen(rna_path));
291         ksp->array_index= array_index;
292         
293         /* store flags */
294         ksp->flag= flag;
295         ksp->groupmode= groupmode;
296         
297         /* add KeyingSet path to KeyingSet */
298         BLI_addtail(&ks->paths, ksp);
299 }       
300
301
302 /* Freeing Tools --------------------------- */
303
304 /* Free data for KeyingSet but not set itself */
305 void BKE_keyingset_free (KeyingSet *ks)
306 {
307         KS_Path *ksp, *kspn;
308         
309         /* sanity check */
310         if (ks == NULL)
311                 return;
312         
313         /* free each path as we go to avoid looping twice */
314         for (ksp= ks->paths.first; ksp; ksp= kspn) {
315                 kspn= ksp->next;
316                 
317                 /* free RNA-path info */
318                 MEM_freeN(ksp->rna_path);
319                 
320                 /* free path itself */
321                 BLI_freelinkN(&ks->paths, ksp);
322         }
323 }
324
325 /* Free all the KeyingSets in the given list */
326 void BKE_keyingsets_free (ListBase *list)
327 {
328         KeyingSet *ks, *ksn;
329         
330         /* sanity check */
331         if (list == NULL)
332                 return;
333         
334         /* loop over KeyingSets freeing them 
335          *      - BKE_keyingset_free() doesn't free the set itself, but it frees its sub-data
336          */
337         for (ks= list->first; ks; ks= ksn) {
338                 ksn= ks->next;
339                 BKE_keyingset_free(ks);
340                 BLI_freelinkN(list, ks);
341         }
342 }
343
344 /* ***************************************** */
345 /* Evaluation Data-Setting Backend */
346
347 /* Retrieve string to act as RNA-path, adjusted using mapping-table if provided 
348  * It returns whether the string needs to be freed (i.e. if it was a temp remapped one)
349  * // 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
350  *
351  *      - remap: remapping table to use
352  *      - path: original path string (as stored in F-Curve data)
353  *      - dst: destination string to write data to
354  */
355 short animsys_remap_path (AnimMapper *remap, char *path, char **dst)
356 {
357         /* is there a valid remapping table to use? */
358         if (remap) {
359                 /* find a matching entry... to use to remap */
360                 // ...TODO...
361         }
362         
363         /* nothing suitable found, so just set dst to look at path (i.e. no alloc/free needed) */
364         *dst= path;
365         return 0;
366 }
367
368
369 /* Write the given value to a setting using RNA, and return success */
370 static short animsys_write_rna_setting (PointerRNA *ptr, char *path, int array_index, float value)
371 {
372         PropertyRNA *prop;
373         PointerRNA new_ptr;
374         
375         /* get property to write to */
376         if (RNA_path_resolve(ptr, path, &new_ptr, &prop)) 
377         {
378                 /* set value - only for animatable numerical values */
379                 if (RNA_property_animateable(&new_ptr, prop)) 
380                 {
381                         switch (RNA_property_type(prop)) 
382                         {
383                                 case PROP_BOOLEAN:
384                                         if (RNA_property_array_length(prop))
385                                                 RNA_property_boolean_set_index(&new_ptr, prop, array_index, (int)value);
386                                         else
387                                                 RNA_property_boolean_set(&new_ptr, prop, (int)value);
388                                         break;
389                                 case PROP_INT:
390                                         if (RNA_property_array_length(prop))
391                                                 RNA_property_int_set_index(&new_ptr, prop, array_index, (int)value);
392                                         else
393                                                 RNA_property_int_set(&new_ptr, prop, (int)value);
394                                         break;
395                                 case PROP_FLOAT:
396                                         if (RNA_property_array_length(prop))
397                                                 RNA_property_float_set_index(&new_ptr, prop, array_index, value);
398                                         else
399                                                 RNA_property_float_set(&new_ptr, prop, value);
400                                         break;
401                                 case PROP_ENUM:
402                                         RNA_property_enum_set(&new_ptr, prop, (int)value);
403                                         break;
404                                 default:
405                                         /* nothing can be done here... so it is unsuccessful? */
406                                         return 0;
407                         }
408                 }
409                 
410                 /* successful */
411                 return 1;
412         }
413         else {
414                 /* failed to get path */
415                 // XXX don't tag as failed yet though, as there are some legit situations (Action Constraint) 
416                 // where some channels will not exist, but shouldn't lock up Action
417                 if (G.f & G_DEBUG) {
418                         printf("Animato: Invalid path. ID = '%s',  '%s [%d]' \n", 
419                                 (ptr && ptr->id.data) ? (((ID *)ptr->id.data)->name+2) : "<No ID>", 
420                                 path, array_index);
421                 }
422                 return 0;
423         }
424 }
425
426 /* Simple replacement based data-setting of the FCurve using RNA */
427 static short animsys_execute_fcurve (PointerRNA *ptr, AnimMapper *remap, FCurve *fcu)
428 {
429         char *path = NULL;
430         short free_path=0;
431         short ok= 0;
432         
433         /* get path, remapped as appropriate to work in its new environment */
434         free_path= animsys_remap_path(remap, fcu->rna_path, &path);
435         
436         /* write value to setting */
437         if (path)
438                 ok= animsys_write_rna_setting(ptr, path, fcu->array_index, fcu->curval);
439         
440         /* free temp path-info */
441         if (free_path)
442                 MEM_freeN(path);
443                 
444         /* return whether we were successful */
445         return ok;
446 }
447
448 /* Evaluate all the F-Curves in the given list 
449  * This performs a set of standard checks. If extra checks are required, separate code should be used
450  */
451 static void animsys_evaluate_fcurves (PointerRNA *ptr, ListBase *list, AnimMapper *remap, float ctime)
452 {
453         FCurve *fcu;
454         
455         /* calculate then execute each curve */
456         for (fcu= list->first; fcu; fcu= fcu->next) 
457         {
458                 /* check if this curve should be skipped */
459                 if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) 
460                 {
461                         calculate_fcurve(fcu, ctime);
462                         animsys_execute_fcurve(ptr, remap, fcu); 
463                 }
464         }
465 }
466
467 /* ***************************************** */
468 /* Driver Evaluation */
469
470 /* Evaluate Drivers */
471 static void animsys_evaluate_drivers (PointerRNA *ptr, AnimData *adt, float ctime)
472 {
473         FCurve *fcu;
474         
475         /* drivers are stored as F-Curves, but we cannot use the standard code, as we need to check if
476          * the depsgraph requested that this driver be evaluated...
477          */
478         for (fcu= adt->drivers.first; fcu; fcu= fcu->next) 
479         {
480                 ChannelDriver *driver= fcu->driver;
481                 short ok= 0;
482                 
483                 /* check if this driver's curve should be skipped */
484                 // FIXME: maybe we shouldn't check for muted, though that would make things more confusing, as there's already too many ways to disable?
485                 if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) 
486                 {
487                         /* check if driver itself is tagged for recalculation */
488                         if ((driver) && !(driver->flag & DRIVER_FLAG_INVALID)/*&& (driver->flag & DRIVER_FLAG_RECALC)*/) {      // XXX driver recalc flag is not set yet by depsgraph!
489                                 /* evaluate this using values set already in other places */
490                                 // 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
491                                 calculate_fcurve(fcu, ctime);
492                                 ok= animsys_execute_fcurve(ptr, NULL, fcu);
493                                 
494                                 /* clear recalc flag */
495                                 driver->flag &= ~DRIVER_FLAG_RECALC;
496                                 
497                                 /* set error-flag if evaluation failed */
498                                 if (ok == 0)
499                                         driver->flag |= DRIVER_FLAG_INVALID; 
500                         }
501                 }
502         }
503 }
504
505 /* ***************************************** */
506 /* Actions Evaluation */
507
508 /* Evaluate Action Group */
509 void animsys_evaluate_action_group (PointerRNA *ptr, bAction *act, bActionGroup *agrp, AnimMapper *remap, float ctime)
510 {
511         FCurve *fcu;
512         
513         /* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */
514         if ELEM(NULL, act, agrp) return;
515         if ((remap) && (remap->target != act)) remap= NULL;
516         
517         /* calculate then execute each curve */
518         for (fcu= agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu= fcu->next) 
519         {
520                 /* check if this curve should be skipped */
521                 if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) 
522                 {
523                         calculate_fcurve(fcu, ctime);
524                         animsys_execute_fcurve(ptr, remap, fcu); 
525                 }
526         }
527 }
528
529 /* Evaluate Action (F-Curve Bag) */
530 void animsys_evaluate_action (PointerRNA *ptr, bAction *act, AnimMapper *remap, float ctime)
531 {
532         /* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */
533         if (act == NULL) return;
534         if ((remap) && (remap->target != act)) remap= NULL;
535         
536         /* calculate then execute each curve */
537         animsys_evaluate_fcurves(ptr, &act->curves, remap, ctime);
538 }
539
540 /* ***************************************** */
541 /* NLA System - Evaluation */
542
543 /* used for list of strips to accumulate at current time */
544 typedef struct NlaEvalStrip {
545         struct NlaEvalStrip *next, *prev;
546         
547         NlaTrack *track;                        /* track that this strip belongs to */
548         NlaStrip *strip;                        /* strip that's being used */
549         
550         short track_index;                      /* the index of the track within the list */
551         short strip_mode;                       /* which end of the strip are we looking at */
552 } NlaEvalStrip;
553
554 /* NlaEvalStrip->strip_mode */
555 enum {
556         NES_TIME_BEFORE = -1,
557         NES_TIME_WITHIN,
558         NES_TIME_AFTER,
559 } eNlaEvalStrip_StripMode;
560
561
562 /* temp channel for accumulating data from NLA (avoids needing to clear all values first) */
563 // TODO: maybe this will be used as the 'cache' stuff needed for editable values too?
564 typedef struct NlaEvalChannel {
565         struct NlaEvalChannel *next, *prev;
566         
567         PointerRNA *ptr;                /* pointer to struct containing property to use */
568         PropertyRNA *prop;              /* RNA-property type to use (should be in the struct given) */
569         int index;                              /* array index (where applicable) */
570         
571         float value;                    /* value of this channel */
572 } NlaEvalChannel;
573
574
575 /* ---------------------- */
576
577 /* non clipped mapping for strip-time <-> global time 
578  *      invert = convert action-strip time to global time 
579  */
580 static float nlastrip_get_frame (NlaStrip *strip, float cframe, short invert)
581 {
582         float length, actlength, repeat, scale;
583         
584         /* get number of repeats */
585         if (strip->repeat == 0.0f) strip->repeat = 1.0f;
586         repeat = strip->repeat;
587         
588         /* scaling */
589         if (strip->scale == 0.0f) strip->scale= 1.0f;
590         scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */
591         
592         /* length of referenced action */
593         actlength = strip->actend-strip->actstart;
594         if (actlength == 0.0f) actlength = 1.0f;
595         
596         /* length of strip */
597         length = repeat * scale * actlength;
598         
599         /* reversed = play strip backwards */
600         if (strip->flag & NLASTRIP_FLAG_REVERSE) {
601                 // FIXME: verify these 
602                 /* invert = convert action-strip time to global time */
603                 if (invert)
604                         return length*(strip->actend - cframe)/(repeat*actlength) + strip->start;
605                 else
606                         return strip->actend - repeat*actlength*(cframe - strip->start)/length;
607         }
608         else {
609                 /* invert = convert action-strip time to global time */
610                 if (invert)
611                         return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start;
612                 else
613                         return repeat*actlength*(cframe - strip->start)/length + strip->actstart;
614         }
615 }
616
617 /* calculate influence of strip based for given frame based on blendin/out values */
618 static float nlastrip_get_influence (NlaStrip *strip, float cframe)
619 {
620         /* sanity checks - normalise the blendin/out values? */
621         strip->blendin= (float)fabs(strip->blendin);
622         strip->blendout= (float)fabs(strip->blendout);
623         
624         /* result depends on where frame is in respect to blendin/out values */
625         // TODO: are the fabs() tests needed here?
626         if (IS_EQ(strip->blendin, 0)==0 && (cframe <= (strip->start + strip->blendin))) {
627                 /* there is some blend-in */
628                 return (float)fabs(cframe - strip->start) / (strip->blendin);
629         }
630         else if (IS_EQ(strip->blendout, 0)==0 && (cframe >= (strip->end - strip->blendout))) {
631                 /* there is some blend-out */
632                 return (float)fabs(strip->end - cframe) / (strip->blendout);
633         }
634         else {
635                 /* in the middle of the strip, we should be full strength */
636                 return 1.0f;
637         }
638 }
639
640 /* evaluate the evaluation time and influence for the strip, storing the results in the strip */
641 void nlastrip_evaluate_controls (NlaStrip *strip, float cframe)
642 {
643         /* firstly, analytically generate values for influence and time (if applicable) */
644         if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0)
645                 strip->strip_time= nlastrip_get_frame(strip, cframe, 1); /* last arg '1' means current time to 'strip'/action time */
646         if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0)
647                 strip->influence= nlastrip_get_influence(strip, cframe);
648         
649         /* now strip's evaluate F-Curves for these settings (if applicable) */
650         if (strip->fcurves.first) {
651 #if 0
652                 PointerRNA strip_ptr;
653                 FCurve *fcu;
654                 
655                 /* create RNA-pointer needed to set values */
656                 RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
657                 
658                 /* execute these settings as per normal */
659                 animsys_evaluate_fcurves(&actstrip_ptr, &strip->fcurves, NULL, ctime);
660 #endif
661         }
662 }
663
664
665 /* gets the strip active at the current time for a track for evaluation purposes */
666 static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime)
667 {
668         NlaStrip *strip, *estrip=NULL;
669         NlaEvalStrip *nes;
670         short side= 0;
671         
672         /* skip if track is muted */
673         if (nlt->flag & NLATRACK_MUTED) 
674                 return;
675         
676         /* loop over strips, checking if they fall within the range */
677         for (strip= nlt->strips.first; strip; strip= strip->next) {
678                 /* check if current time occurs within this strip  */
679                 if (IN_RANGE(ctime, strip->start, strip->end)) {
680                         /* this strip is active, so try to use it */
681                         estrip= strip;
682                         side= NES_TIME_WITHIN;
683                         break;
684                 }
685                 
686                 /* if time occurred before current strip... */
687                 if (ctime < strip->start) {
688                         if (strip == nlt->strips.first) {
689                                 /* before first strip - only try to use it if it extends backwards in time too */
690                                 if (strip->extendmode == NLASTRIP_EXTEND_HOLD)
691                                         estrip= strip;
692                                         
693                                 /* side is 'before' regardless of whether there's a useful strip */
694                                 side= NES_TIME_BEFORE;
695                         }
696                         else {
697                                 /* before next strip - previous strip has ended, but next hasn't begun, 
698                                  * so blending mode depends on whether strip is being held or not...
699                                  *      - only occurs when no transition strip added, otherwise the transition would have
700                                  *        been picked up above...
701                                  */
702                                 strip= strip->prev;
703                                 
704                                 if (strip->extendmode != NLASTRIP_EXTEND_NOTHING)
705                                         estrip= strip;
706                                 side= NES_TIME_AFTER;
707                         }
708                         break;
709                 }
710                 
711                 /* if time occurred after current strip... */
712                 if (ctime > strip->end) {
713                         /* only if this is the last strip should we do anything, and only if that is being held */
714                         if (strip == nlt->strips.last) {
715                                 if (strip->extendmode != NLASTRIP_EXTEND_NOTHING)
716                                         estrip= strip;
717                                         
718                                 side= NES_TIME_AFTER;
719                                 break;
720                         }
721                         
722                         /* otherwise, skip... as the 'before' case will catch it more elegantly! */
723                 }
724         }
725         
726         /* check if a valid strip was found
727          *      - must not be muted (i.e. will have contribution
728          */
729         if ((estrip == NULL) || (estrip->flag & NLASTRIP_FLAG_MUTED)) 
730                 return;
731         
732         /* evaluate strip's evaluation controls  
733          *      - skip if no influence (i.e. same effect as muting the strip)
734          *      - negative influence is not supported yet... how would that be defined?
735          */
736         // TODO: this sounds a bit hacky having a few isolated F-Curves stuck on some data it operates on...
737         nlastrip_evaluate_controls(estrip, ctime);
738         if (estrip->influence <= 0.0f)
739                 return;
740                 
741         /* check if strip has valid data to evaluate */
742         switch (estrip->type) {
743                 case NLASTRIP_TYPE_CLIP: 
744                         /* clip must have some action to evaluate */
745                         if (estrip->act == NULL)
746                                 return;
747                         break;
748                 case NLASTRIP_TYPE_TRANSITION:
749                         /* there must be strips to transition from and to (i.e. prev and next required) */
750                         // TODO: what happens about cross-track transitions? 
751                         if (ELEM(NULL, estrip->prev, estrip->next))
752                                 return;
753                         break;
754         }
755         
756         /* add to list of strips we need to evaluate */
757         nes= MEM_callocN(sizeof(NlaEvalStrip), "NlaEvalStrip");
758         
759         nes->track= nlt;
760         nes->strip= estrip;
761         nes->strip_mode= side;
762         nes->track_index= index;
763         
764         BLI_addtail(list, nes);
765 }
766
767 /* ---------------------- */
768
769 /* evaluates the given evaluation strip */
770 // FIXME: will we need the evaluation cache table set up to blend stuff in?
771 // TODO: only evaluate here, but flush in one go using the accumulated channels at end...
772 static void nlastrip_ctime_evaluate (ListBase *channels, NlaEvalStrip *nes, float ctime)
773 {
774         // 1. (in old code) was to extract 'IPO-channels' from actions
775         // 2. blend between the 'accumulated' data, and the new data
776 }
777
778 /* write the accumulated settings to */
779 static void nladata_flush_channels (PointerRNA *ptr, ListBase *channels)
780 {
781         
782 }
783
784 /* ---------------------- */
785
786 /* NLA Evaluation function (mostly for use through do_animdata) 
787  *      - All channels that will be affected are not cleared anymore. Instead, we just evaluate into 
788  *              some temp channels, where values can be accumulated in one go.
789  */
790 static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime)
791 {
792         NlaTrack *nlt;
793         short track_index=0;
794         
795         ListBase estrips= {NULL, NULL};
796         ListBase echannels= {NULL, NULL};
797         NlaEvalStrip *nes;
798         
799         /* 1. get the stack of strips to evaluate at current time (influence calculated here) */
800         for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++) 
801                 nlatrack_ctime_get_strip(&estrips, nlt, track_index, ctime);
802         
803         /* only continue if there are strips to evaluate */
804         if (estrips.first == NULL)
805                 return;
806         
807         
808         /* 2. for each strip, evaluate then accumulate on top of existing channels, but don't set values yet */
809         for (nes= estrips.first; nes; nes= nes->next) 
810                 nlastrip_ctime_evaluate(&echannels, nes, ctime);
811         
812         /* 3. flush effects of accumulating channels in NLA to the actual data they affect */
813         nladata_flush_channels(ptr, &echannels);
814         
815         /* 4. free temporary evaluation data */
816         BLI_freelistN(&estrips);
817         BLI_freelistN(&echannels);
818 }
819
820 /* ***************************************** */ 
821 /* Overrides System - Public API */
822
823 /* Clear all overides */
824
825 /* Add or get existing Override for given setting */
826 AnimOverride *BKE_animsys_validate_override (PointerRNA *ptr, char *path, int array_index)
827 {
828         // FIXME: need to define how to get overrides
829         return NULL;
830
831
832 /* -------------------- */
833
834 /* Evaluate Overrides */
835 static void animsys_evaluate_overrides (PointerRNA *ptr, AnimData *adt, float ctime)
836 {
837         AnimOverride *aor;
838         
839         /* for each override, simply execute... */
840         for (aor= adt->overrides.first; aor; aor= aor->next)
841                 animsys_write_rna_setting(ptr, aor->rna_path, aor->array_index, aor->value);
842 }
843
844 /* ***************************************** */
845 /* Evaluation System - Public API */
846
847 /* Overview of how this system works:
848  *      1) Depsgraph sorts data as necessary, so that data is in an order that means 
849  *              that all dependences are resolved before dependants.
850  *      2) All normal animation is evaluated, so that drivers have some basis values to
851  *              work with
852  *              a.      NLA stacks are done first, as the Active Actions act as 'tweaking' tracks
853  *                      which modify the effects of the NLA-stacks
854  *              b.      Active Action is evaluated as per normal, on top of the results of the NLA tracks
855  *
856  * --------------< often in a separate phase... >------------------ 
857  *
858  *      3) Drivers/expressions are evaluated on top of this, in an order where dependences are
859  *              resolved nicely. 
860  *         Note: it may be necessary to have some tools to handle the cases where some higher-level
861  *              drivers are added and cause some problematic dependencies that didn't exist in the local levels...
862  *
863  * --------------< always executed >------------------ 
864  *
865  * Maintainance of editability of settings (XXX):
866  *      In order to ensure that settings that are animated can still be manipulated in the UI without requiring
867  *      that keyframes are added to prevent these values from being overwritten, we use 'overrides'. 
868  *
869  * Unresolved things:
870  *      - Handling of multi-user settings (i.e. time-offset, group-instancing) -> big cache grids or nodal system? but stored where?
871  *      - Multiple-block dependencies (i.e. drivers for settings are in both local and higher levels) -> split into separate lists?  
872  */
873
874 /* Evaluation loop for evaluation animation data 
875  *
876  * This assumes that the animation-data provided belongs to the ID block in question,
877  * and that the flags for which parts of the anim-data settings need to be recalculated 
878  * have been set already by the depsgraph. Now, we use the recalc 
879  */
880 void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short recalc)
881 {
882         PointerRNA id_ptr;
883         
884         /* sanity checks */
885         if ELEM(NULL, id, adt)
886                 return;
887         
888         /* get pointer to ID-block for RNA to use */
889         RNA_id_pointer_create(id, &id_ptr);
890         
891         /* recalculate keyframe data:
892          *      - NLA before Active Action, as Active Action behaves as 'tweaking track'
893          *        that overrides 'rough' work in NLA
894          */
895         if ((recalc & ADT_RECALC_ANIM) || (adt->recalc & ADT_RECALC_ANIM))
896         {
897                 /* evaluate NLA data */
898                 if ((adt->nla_tracks.first) && !(adt->flag & ADT_NLA_EVAL_OFF))
899                 {
900                         animsys_evaluate_nla(&id_ptr, adt, ctime);
901                 }
902                 
903                 /* evaluate Action data */
904                 // FIXME: what if the solo track was not tweaking one, then nla-solo should be checked too?
905                 if (adt->action) 
906                         animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime);
907                 
908                 /* reset tag */
909                 adt->recalc &= ~ADT_RECALC_ANIM;
910         }
911         
912         /* recalculate drivers 
913          *      - Drivers need to be evaluated afterwards, as they can either override 
914          *        or be layered on top of existing animation data.
915          *      - Drivers should be in the appropriate order to be evaluated without problems...
916          */
917         if ((recalc & ADT_RECALC_DRIVERS) /*&& (adt->recalc & ADT_RECALC_DRIVERS)*/) // XXX for now, don't check yet, as depsgraph hasn't been updated
918         {
919                 animsys_evaluate_drivers(&id_ptr, adt, ctime);
920         }
921         
922         /* always execute 'overrides' 
923          *      - Overrides allow editing, by overwriting the value(s) set from animation-data, with the
924          *        value last set by the user (and not keyframed yet). 
925          *      - Overrides are cleared upon frame change and/or keyframing
926          *      - It is best that we execute this everytime, so that no errors are likely to occur.
927          */
928         animsys_evaluate_overrides(&id_ptr, adt, ctime);
929         
930         /* clear recalc flag now */
931         adt->recalc= 0;
932 }
933
934 /* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only
935  *
936  * This will evaluate only the animation info available in the animation data-blocks
937  * encountered. In order to enforce the system by which some settings controlled by a
938  * 'local' (i.e. belonging in the nearest ID-block that setting is related to, not a
939  * standard 'root') block are overridden by a larger 'user'
940  */
941 // TODO: we currently go over entire 'main' database...
942 void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
943 {
944         ID *id;
945         
946         if (G.f & G_DEBUG)
947                 printf("Evaluate all animation - %f \n", ctime);
948
949         /* macro for less typing */
950 #define EVAL_ANIM_IDS(first, flag) \
951         for (id= first; id; id= id->next) { \
952                 AnimData *adt= BKE_animdata_from_id(id); \
953                 BKE_animsys_evaluate_animdata(id, adt, ctime, flag); \
954         }
955         
956         /* nodes */
957         // TODO...
958         
959         /* textures */
960         EVAL_ANIM_IDS(main->tex.first, ADT_RECALC_ANIM);
961         
962         /* lamps */
963         EVAL_ANIM_IDS(main->lamp.first, ADT_RECALC_ANIM);
964         
965         /* materials */
966         EVAL_ANIM_IDS(main->mat.first, ADT_RECALC_ANIM);
967         
968         /* cameras */
969         EVAL_ANIM_IDS(main->camera.first, ADT_RECALC_ANIM);
970         
971         /* shapekeys */
972         EVAL_ANIM_IDS(main->key.first, ADT_RECALC_ANIM);
973         
974         /* curves */
975         // TODO...
976         
977         /* meshes */
978         // TODO...
979         
980         /* objects */
981                 /* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets 
982                  * this tagged by Depsgraph on framechange 
983                  */
984         EVAL_ANIM_IDS(main->object.first, /*ADT_RECALC_ANIM*/0); 
985         
986         /* worlds */
987         EVAL_ANIM_IDS(main->world.first, ADT_RECALC_ANIM);
988         
989         /* scenes */
990         EVAL_ANIM_IDS(main->scene.first, ADT_RECALC_ANIM);
991 }
992
993 /* ***************************************** */