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