Merging with trunk up to r38631.
[blender.git] / source / blender / blenkernel / intern / nla.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Joshua Leung (full recode)
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/blenkernel/intern/nla.c
31  *  \ingroup bke
32  */
33
34
35 #include <stdlib.h>
36 #include <stddef.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <math.h>
40 #include <float.h>
41
42 #include "MEM_guardedalloc.h"
43
44 #include "BLI_utildefines.h"
45 #include "BLI_ghash.h"
46
47 #include "DNA_anim_types.h"
48 #include "DNA_scene_types.h"
49
50 #include "BKE_action.h"
51 #include "BKE_fcurve.h"
52 #include "BKE_nla.h"
53 #include "BKE_global.h"
54 #include "BKE_library.h"
55
56
57 #include "RNA_access.h"
58 #include "nla_private.h"
59
60
61
62 /* *************************************************** */
63 /* Data Management */
64
65 /* Freeing ------------------------------------------- */
66
67 /* Remove the given NLA strip from the NLA track it occupies, free the strip's data,
68  * and the strip itself. 
69  */
70 void free_nlastrip (ListBase *strips, NlaStrip *strip)
71 {
72         NlaStrip *cs, *csn;
73         
74         /* sanity checks */
75         if (strip == NULL)
76                 return;
77                 
78         /* free child-strips */
79         for (cs= strip->strips.first; cs; cs= csn) {
80                 csn= cs->next;
81                 free_nlastrip(&strip->strips, cs);
82         }
83                 
84         /* remove reference to action */
85         if (strip->act)
86                 id_us_min(&strip->act->id);
87                 
88         /* free remapping info */
89         //if (strip->remap)
90         //      BKE_animremap_free();
91         
92         /* free own F-Curves */
93         free_fcurves(&strip->fcurves);
94         
95         /* free own F-Modifiers */
96         free_fmodifiers(&strip->modifiers);
97         
98         /* free the strip itself */
99         if (strips)
100                 BLI_freelinkN(strips, strip);
101         else
102                 MEM_freeN(strip);
103 }
104
105 /* Remove the given NLA track from the set of NLA tracks, free the track's data,
106  * and the track itself.
107  */
108 void free_nlatrack (ListBase *tracks, NlaTrack *nlt)
109 {
110         NlaStrip *strip, *stripn;
111         
112         /* sanity checks */
113         if (nlt == NULL)
114                 return;
115                 
116         /* free strips */
117         for (strip= nlt->strips.first; strip; strip= stripn) {
118                 stripn= strip->next;
119                 free_nlastrip(&nlt->strips, strip);
120         }
121         
122         /* free NLA track itself now */
123         if (tracks)
124                 BLI_freelinkN(tracks, nlt);
125         else
126                 MEM_freeN(nlt);
127 }
128
129 /* Free the elements of type NLA Tracks provided in the given list, but do not free
130  * the list itself since that is not free-standing
131  */
132 void free_nladata (ListBase *tracks)
133 {
134         NlaTrack *nlt, *nltn;
135         
136         /* sanity checks */
137         if ELEM(NULL, tracks, tracks->first)
138                 return;
139                 
140         /* free tracks one by one */
141         for (nlt= tracks->first; nlt; nlt= nltn) {
142                 nltn= nlt->next;
143                 free_nlatrack(tracks, nlt);
144         }
145         
146         /* clear the list's pointers to be safe */
147         tracks->first= tracks->last= NULL;
148 }
149
150 /* Copying ------------------------------------------- */
151
152 /* Copy NLA strip */
153 NlaStrip *copy_nlastrip (NlaStrip *strip)
154 {
155         NlaStrip *strip_d;
156         NlaStrip *cs, *cs_d;
157         
158         /* sanity check */
159         if (strip == NULL)
160                 return NULL;
161                 
162         /* make a copy */
163         strip_d= MEM_dupallocN(strip);
164         strip_d->next= strip_d->prev= NULL;
165         
166         /* increase user-count of action */
167         if (strip_d->act)
168                 id_us_plus(&strip_d->act->id);
169                 
170         /* copy F-Curves and modifiers */
171         copy_fcurves(&strip_d->fcurves, &strip->fcurves);
172         copy_fmodifiers(&strip_d->modifiers, &strip->modifiers);
173         
174         /* make a copy of all the child-strips, one at a time */
175         strip_d->strips.first= strip_d->strips.last= NULL;
176         
177         for (cs= strip->strips.first; cs; cs= cs->next) {
178                 cs_d= copy_nlastrip(cs);
179                 BLI_addtail(&strip_d->strips, cs_d);
180         }
181         
182         /* return the strip */
183         return strip_d;
184 }
185
186 /* Copy NLA Track */
187 NlaTrack *copy_nlatrack (NlaTrack *nlt)
188 {
189         NlaStrip *strip, *strip_d;
190         NlaTrack *nlt_d;
191         
192         /* sanity check */
193         if (nlt == NULL)
194                 return NULL;
195                 
196         /* make a copy */
197         nlt_d= MEM_dupallocN(nlt);
198         nlt_d->next= nlt_d->prev= NULL;
199         
200         /* make a copy of all the strips, one at a time */
201         nlt_d->strips.first= nlt_d->strips.last= NULL;
202         
203         for (strip= nlt->strips.first; strip; strip= strip->next) {
204                 strip_d= copy_nlastrip(strip);
205                 BLI_addtail(&nlt_d->strips, strip_d);
206         }
207         
208         /* return the copy */
209         return nlt_d;
210 }
211
212 /* Copy all NLA data */
213 void copy_nladata (ListBase *dst, ListBase *src)
214 {
215         NlaTrack *nlt, *nlt_d;
216         
217         /* sanity checks */
218         if ELEM(NULL, dst, src)
219                 return;
220                 
221         /* clear out the destination list first for precautions... */
222         dst->first= dst->last= NULL;
223                 
224         /* copy each NLA-track, one at a time */
225         for (nlt= src->first; nlt; nlt= nlt->next) {
226                 /* make a copy, and add the copy to the destination list */
227                 nlt_d= copy_nlatrack(nlt);
228                 BLI_addtail(dst, nlt_d);
229         }
230 }
231
232 /* Adding ------------------------------------------- */
233
234 /* Add a NLA Track to the given AnimData 
235  *      - prev: NLA-Track to add the new one after
236  */
237 NlaTrack *add_nlatrack (AnimData *adt, NlaTrack *prev)
238 {
239         NlaTrack *nlt;
240         
241         /* sanity checks */
242         if (adt == NULL)
243                 return NULL;
244                 
245         /* allocate new track */
246         nlt= MEM_callocN(sizeof(NlaTrack), "NlaTrack");
247         
248         /* set settings requiring the track to not be part of the stack yet */
249         nlt->flag = NLATRACK_SELECTED;
250         nlt->index= BLI_countlist(&adt->nla_tracks);
251         
252         /* add track to stack, and make it the active one */
253         if (prev)
254                 BLI_insertlinkafter(&adt->nla_tracks, prev, nlt);
255         else
256                 BLI_addtail(&adt->nla_tracks, nlt);
257         BKE_nlatrack_set_active(&adt->nla_tracks, nlt);
258         
259         /* must have unique name, but we need to seed this */
260         strcpy(nlt->name, "NlaTrack");
261         BLI_uniquename(&adt->nla_tracks, nlt, "NlaTrack", '.', offsetof(NlaTrack, name), sizeof(nlt->name));
262         
263         /* return the new track */
264         return nlt;
265 }
266
267 /* Add a NLA Strip referencing the given Action */
268 NlaStrip *add_nlastrip (bAction *act)
269 {
270         NlaStrip *strip;
271         
272         /* sanity checks */
273         if (act == NULL)
274                 return NULL;
275                 
276         /* allocate new strip */
277         strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
278         
279         /* generic settings 
280          *      - selected flag to highlight this to the user
281          *      - auto-blends to ensure that blend in/out values are automatically 
282          *        determined by overlaps of strips
283          *      - (XXX) synchronisation of strip-length in accordance with changes to action-length
284          *        is not done though, since this should only really happens in editmode for strips now
285          *        though this decision is still subject to further review...
286          */
287         strip->flag = NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_AUTO_BLENDS;
288         
289         /* assign the action reference */
290         strip->act= act;
291         id_us_plus(&act->id);
292         
293         /* determine initial range 
294          *      - strip length cannot be 0... ever...
295          */
296         calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
297         
298         strip->start = strip->actstart;
299         strip->end = (IS_EQF(strip->actstart, strip->actend)) ?  (strip->actstart + 1.0f): (strip->actend);
300         
301         /* strip should be referenced as-is */
302         strip->scale= 1.0f;
303         strip->repeat = 1.0f;
304         
305         /* return the new strip */
306         return strip;
307 }
308
309 /* Add new NLA-strip to the top of the NLA stack - i.e. into the last track if space, or a new one otherwise */
310 NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act)
311 {
312         NlaStrip *strip;
313         NlaTrack *nlt;
314         
315         /* sanity checks */
316         if ELEM(NULL, adt, act)
317                 return NULL;
318         
319         /* create a new NLA strip */
320         strip= add_nlastrip(act);
321         if (strip == NULL)
322                 return NULL;
323         
324         /* firstly try adding strip to last track, but if that fails, add to a new track */
325         if (BKE_nlatrack_add_strip(adt->nla_tracks.last, strip) == 0) {
326                 /* trying to add to the last track failed (no track or no space), 
327                  * so add a new track to the stack, and add to that...
328                  */
329                 nlt= add_nlatrack(adt, NULL);
330                 BKE_nlatrack_add_strip(nlt, strip);
331         }
332         
333         /* automatically name it too */
334         BKE_nlastrip_validate_name(adt, strip);
335         
336         /* returns the strip added */
337         return strip;
338 }
339
340 /* *************************************************** */
341 /* NLA Evaluation <-> Editing Stuff */
342
343 /* Strip Mapping ------------------------------------- */
344
345 /* non clipped mapping for strip-time <-> global time (for Action-Clips)
346  *      invert = convert action-strip time to global time 
347  */
348 static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short mode)
349 {
350         float actlength, scale;
351         // float repeat; // UNUSED
352         
353         /* get number of repeats */
354         if (IS_EQF(strip->repeat, 0.0f)) strip->repeat = 1.0f;
355         // repeat = strip->repeat; // UNUSED
356         
357         /* scaling */
358         if (IS_EQF(strip->scale, 0.0f)) strip->scale= 1.0f;
359         scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */
360         
361         /* length of referenced action */
362         actlength = strip->actend - strip->actstart;
363         if (IS_EQF(actlength, 0.0f)) actlength = 1.0f;
364         
365         /* reversed = play strip backwards */
366         if (strip->flag & NLASTRIP_FLAG_REVERSE) {
367                 // FIXME: this won't work right with Graph Editor?
368                 if (mode == NLATIME_CONVERT_MAP) {
369                         return strip->end - scale*(cframe - strip->actstart);
370                 }
371                 else if (mode == NLATIME_CONVERT_UNMAP) {
372                         return (strip->end + (strip->actstart * scale - cframe)) / scale;
373                 }
374                 else /* if (mode == NLATIME_CONVERT_EVAL) */{
375                         if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) {
376                                 /* this case prevents the motion snapping back to the first frame at the end of the strip 
377                                  * by catching the case where repeats is a whole number, which means that the end of the strip
378                                  * could also be interpreted as the end of the start of a repeat
379                                  */
380                                 return strip->actstart;
381                         }
382                         else {
383                                 /* - the 'fmod(..., actlength*scale)' is needed to get the repeats working
384                                  * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat
385                                  */
386                                 return strip->actend - fmodf(cframe - strip->start, actlength*scale) / scale;
387                         }
388                 }
389         }
390         else {
391                 if (mode == NLATIME_CONVERT_MAP) {
392                         return strip->start + scale*(cframe - strip->actstart);
393                 }
394                 else if (mode == NLATIME_CONVERT_UNMAP) {
395                         return strip->actstart + (cframe - strip->start) / scale;
396                 }
397                 else /* if (mode == NLATIME_CONVERT_EVAL) */{
398                         if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) {
399                                 /* this case prevents the motion snapping back to the first frame at the end of the strip 
400                                  * by catching the case where repeats is a whole number, which means that the end of the strip
401                                  * could also be interpreted as the end of the start of a repeat
402                                  */
403                                 return strip->actend;
404                         }
405                         else {
406                                 /* - the 'fmod(..., actlength*scale)' is needed to get the repeats working
407                                  * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat
408                                  */
409                                 return strip->actstart + fmodf(cframe - strip->start, actlength*scale) / scale;
410                         }
411                 }
412         }
413 }
414
415 /* non clipped mapping for strip-time <-> global time (for Transitions)
416  *      invert = convert action-strip time to global time 
417  */
418 static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short mode)
419 {
420         float length;
421         
422         /* length of strip */
423         length= strip->end - strip->start;
424         
425         /* reversed = play strip backwards */
426         if (strip->flag & NLASTRIP_FLAG_REVERSE) {
427                 if (mode == NLATIME_CONVERT_MAP)
428                         return strip->end - (length * cframe);
429                 else
430                         return (strip->end - cframe) / length;
431         }
432         else {
433                 if (mode == NLATIME_CONVERT_MAP)
434                         return (length * cframe) + strip->start;
435                 else
436                         return (cframe - strip->start) / length;
437         }
438 }
439
440 /* non clipped mapping for strip-time <-> global time
441  *      mode = eNlaTime_ConvertModes[] -> NLATIME_CONVERT_*
442  *
443  * only secure for 'internal' (i.e. within AnimSys evaluation) operations,
444  * but should not be directly relied on for stuff which interacts with editors
445  */
446 float nlastrip_get_frame (NlaStrip *strip, float cframe, short mode)
447 {
448         switch (strip->type) {
449                 case NLASTRIP_TYPE_META: /* meta - for now, does the same as transition (is really just an empty container) */
450                 case NLASTRIP_TYPE_TRANSITION: /* transition */
451                         return nlastrip_get_frame_transition(strip, cframe, mode);
452                 
453                 case NLASTRIP_TYPE_CLIP: /* action-clip (default) */
454                 default:
455                         return nlastrip_get_frame_actionclip(strip, cframe, mode);
456         }       
457 }
458
459
460 /* Non clipped mapping for strip-time <-> global time
461  *      mode = eNlaTime_ConvertModesp[] -> NLATIME_CONVERT_*
462  *
463  * Public API method - perform this mapping using the given AnimData block
464  * and perform any necessary sanity checks on the value
465  */
466 float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short mode)
467 {
468         NlaStrip *strip;
469         
470         /* sanity checks 
471          *      - obviously we've got to have some starting data
472          *      - when not in tweakmode, the active Action does not have any scaling applied :)
473          *      - when in tweakmode, if the no-mapping flag is set, do not map
474          */
475         if ((adt == NULL) || (adt->flag & ADT_NLA_EDIT_ON)==0 || (adt->flag & ADT_NLA_EDIT_NOMAP))
476                 return cframe;
477                 
478         /* if the active-strip info has been stored already, access this, otherwise look this up
479          * and store for (very probable) future usage
480          */
481         if (adt->actstrip == NULL) {
482                 NlaTrack *nlt= BKE_nlatrack_find_active(&adt->nla_tracks);
483                 adt->actstrip= BKE_nlastrip_find_active(nlt);
484         }
485         strip= adt->actstrip;
486         
487         /* sanity checks 
488          *      - in rare cases, we may not be able to find this strip for some reason (internal error)
489          *      - for now, if the user has defined a curve to control the time, this correction cannot be performed
490          *        reliably...
491          */
492         if ((strip == NULL) || (strip->flag & NLASTRIP_FLAG_USR_TIME))
493                 return cframe;
494                 
495         /* perform the correction now... */
496         return nlastrip_get_frame(strip, cframe, mode);
497 }
498
499 /* *************************************************** */
500 /* NLA API */
501
502 /* List of Strips ------------------------------------ */
503 /* (these functions are used for NLA-Tracks and also for nested/meta-strips) */
504
505 /* Check if there is any space in the given list to add the given strip */
506 short BKE_nlastrips_has_space (ListBase *strips, float start, float end)
507 {
508         NlaStrip *strip;
509         
510         /* sanity checks */
511         if ((strips == NULL) || IS_EQF(start, end))
512                 return 0;
513         if (start > end) {
514                 puts("BKE_nlastrips_has_space() error... start and end arguments swapped");
515                 SWAP(float, start, end);
516         }
517         
518         /* loop over NLA strips checking for any overlaps with this area... */
519         for (strip= strips->first; strip; strip= strip->next) {
520                 /* if start frame of strip is past the target end-frame, that means that
521                  * we've gone past the window we need to check for, so things are fine
522                  */
523                 if (strip->start >= end)
524                         return 1;
525                 
526                 /* if the end of the strip is greater than either of the boundaries, the range
527                  * must fall within the extents of the strip
528                  */
529                 if ((strip->end > start) || (strip->end > end))
530                         return 0;
531         }
532         
533         /* if we are still here, we haven't encountered any overlapping strips */
534         return 1;
535 }
536
537 /* Rearrange the strips in the track so that they are always in order 
538  * (usually only needed after a strip has been moved) 
539  */
540 void BKE_nlastrips_sort_strips (ListBase *strips)
541 {
542         ListBase tmp = {NULL, NULL};
543         NlaStrip *strip, *sstrip, *stripn;
544         
545         /* sanity checks */
546         if ELEM(NULL, strips, strips->first)
547                 return;
548         
549         /* we simply perform insertion sort on this list, since it is assumed that per track,
550          * there are only likely to be at most 5-10 strips
551          */
552         for (strip= strips->first; strip; strip= stripn) {
553                 short not_added = 1;
554                 
555                 stripn= strip->next;
556                 
557                 /* remove this strip from the list, and add it to the new list, searching from the end of 
558                  * the list, assuming that the lists are in order 
559                  */
560                 BLI_remlink(strips, strip);
561                 
562                 for (sstrip= tmp.last; sstrip; sstrip= sstrip->prev) {
563                         /* check if add after */
564                         if (sstrip->end <= strip->start) {
565                                 BLI_insertlinkafter(&tmp, sstrip, strip);
566                                 not_added= 0;
567                                 break;
568                         }
569                 }
570                 
571                 /* add before first? */
572                 if (not_added)
573                         BLI_addhead(&tmp, strip);
574         }
575         
576         /* reassign the start and end points of the strips */
577         strips->first= tmp.first;
578         strips->last= tmp.last;
579 }
580
581 /* Add the given NLA-Strip to the given list of strips, assuming that it 
582  * isn't currently a member of another list
583  */
584 short BKE_nlastrips_add_strip (ListBase *strips, NlaStrip *strip)
585 {
586         NlaStrip *ns;
587         short not_added = 1;
588         
589         /* sanity checks */
590         if ELEM(NULL, strips, strip)
591                 return 0;
592                 
593         /* check if any space to add */
594         if (BKE_nlastrips_has_space(strips, strip->start, strip->end)==0)
595                 return 0;
596         
597         /* find the right place to add the strip to the nominated track */
598         for (ns= strips->first; ns; ns= ns->next) {
599                 /* if current strip occurs after the new strip, add it before */
600                 if (ns->start >= strip->end) {
601                         BLI_insertlinkbefore(strips, ns, strip);
602                         not_added= 0;
603                         break;
604                 }
605         }
606         if (not_added) {
607                 /* just add to the end of the list of the strips then... */
608                 BLI_addtail(strips, strip);
609         }
610         
611         /* added... */
612         return 1;
613 }
614
615
616 /* Meta-Strips ------------------------------------ */
617
618 /* Convert 'islands' (i.e. continuous string of) selected strips to be
619  * contained within 'Meta-Strips' which act as strips which contain strips.
620  *      temp: are the meta-strips to be created 'temporary' ones used for transforms?
621  */
622 void BKE_nlastrips_make_metas (ListBase *strips, short temp)
623 {
624         NlaStrip *mstrip = NULL;
625         NlaStrip *strip, *stripn;
626         
627         /* sanity checks */
628         if ELEM(NULL, strips, strips->first)
629                 return;
630         
631         /* group all continuous chains of selected strips into meta-strips */
632         for (strip= strips->first; strip; strip= stripn) {
633                 stripn= strip->next;
634                 
635                 if (strip->flag & NLASTRIP_FLAG_SELECT) {
636                         /* if there is an existing meta-strip, add this strip to it, otherwise, create a new one */
637                         if (mstrip == NULL) {
638                                 /* add a new meta-strip, and add it before the current strip that it will replace... */
639                                 mstrip= MEM_callocN(sizeof(NlaStrip), "Meta-NlaStrip");
640                                 mstrip->type = NLASTRIP_TYPE_META;
641                                 BLI_insertlinkbefore(strips, strip, mstrip);
642                                 
643                                 /* set flags */
644                                 mstrip->flag = NLASTRIP_FLAG_SELECT;
645                                 
646                                 /* set temp flag if appropriate (i.e. for transform-type editing) */
647                                 if (temp)
648                                         mstrip->flag |= NLASTRIP_FLAG_TEMP_META;
649                                         
650                                 /* set default repeat/scale values to prevent warnings */
651                                 mstrip->repeat= mstrip->scale= 1.0f;
652                                 
653                                 /* make its start frame be set to the start frame of the current strip */
654                                 mstrip->start= strip->start;
655                         }
656                         
657                         /* remove the selected strips from the track, and add to the meta */
658                         BLI_remlink(strips, strip);
659                         BLI_addtail(&mstrip->strips, strip);
660                         
661                         /* expand the meta's dimensions to include the newly added strip- i.e. its last frame */
662                         mstrip->end= strip->end;
663                 }
664                 else {
665                         /* current strip wasn't selected, so the end of 'island' of selected strips has been reached,
666                          * so stop adding strips to the current meta
667                          */
668                         mstrip= NULL;
669                 }
670         }
671 }
672
673 /* Split a meta-strip into a set of normal strips */
674 void BKE_nlastrips_clear_metastrip (ListBase *strips, NlaStrip *strip)
675 {
676         NlaStrip *cs, *csn;
677         
678         /* sanity check */
679         if ELEM(NULL, strips, strip)
680                 return;
681         
682         /* move each one of the meta-strip's children before the meta-strip
683          * in the list of strips after unlinking them from the meta-strip
684          */
685         for (cs= strip->strips.first; cs; cs= csn) {
686                 csn= cs->next;
687                 BLI_remlink(&strip->strips, cs);
688                 BLI_insertlinkbefore(strips, strip, cs);
689         }
690         
691         /* free the meta-strip now */
692         free_nlastrip(strips, strip);
693 }
694
695 /* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips
696  *      sel: only consider selected meta-strips, otherwise all meta-strips are removed
697  *      onlyTemp: only remove the 'temporary' meta-strips used for transforms
698  */
699 void BKE_nlastrips_clear_metas (ListBase *strips, short onlySel, short onlyTemp)
700 {
701         NlaStrip *strip, *stripn;
702         
703         /* sanity checks */
704         if ELEM(NULL, strips, strips->first)
705                 return;
706         
707         /* remove meta-strips fitting the criteria of the arguments */
708         for (strip= strips->first; strip; strip= stripn) {
709                 stripn= strip->next;
710                 
711                 /* check if strip is a meta-strip */
712                 if (strip->type == NLASTRIP_TYPE_META) {
713                         /* if check if selection and 'temporary-only' considerations are met */
714                         if ((onlySel==0) || (strip->flag & NLASTRIP_FLAG_SELECT)) {
715                                 if ((!onlyTemp) || (strip->flag & NLASTRIP_FLAG_TEMP_META)) {
716                                         BKE_nlastrips_clear_metastrip(strips, strip);
717                                 }
718                         }
719                 }
720         }
721 }
722
723 /* Add the given NLA-Strip to the given Meta-Strip, assuming that the
724  * strip isn't attached to anyy list of strips 
725  */
726 short BKE_nlameta_add_strip (NlaStrip *mstrip, NlaStrip *strip)
727 {
728         /* sanity checks */
729         if ELEM(NULL, mstrip, strip)
730                 return 0;
731                 
732         /* firstly, check if the meta-strip has space for this */
733         if (BKE_nlastrips_has_space(&mstrip->strips, strip->start, strip->end) == 0)
734                 return 0;
735                 
736         /* check if this would need to be added to the ends of the meta,
737          * and subsequently, if the neighbouring strips allow us enough room
738          */
739         if (strip->start < mstrip->start) {
740                 /* check if strip to the left (if it exists) ends before the 
741                  * start of the strip we're trying to add 
742                  */
743                 if ((mstrip->prev == NULL) || (mstrip->prev->end <= strip->start)) {
744                         /* add strip to start of meta's list, and expand dimensions */
745                         BLI_addhead(&mstrip->strips, strip);
746                         mstrip->start= strip->start;
747                         
748                         return 1;
749                 }
750                 else /* failed... no room before */
751                         return 0;
752         }
753         else if (strip->end > mstrip->end) {
754                 /* check if strip to the right (if it exists) starts before the 
755                  * end of the strip we're trying to add 
756                  */
757                 if ((mstrip->next == NULL) || (mstrip->next->start >= strip->end)) {
758                         /* add strip to end of meta's list, and expand dimensions */
759                         BLI_addtail(&mstrip->strips, strip);
760                         mstrip->end= strip->end;
761                         
762                         return 1;
763                 }
764                 else /* failed... no room after */
765                         return 0;
766         }
767         else {
768                 /* just try to add to the meta-strip (no dimension changes needed) */
769                 return BKE_nlastrips_add_strip(&mstrip->strips, strip);
770         }
771 }
772
773 /* Adjust the settings of NLA-Strips contained within a Meta-Strip (recursively), 
774  * until the Meta-Strips children all fit within the Meta-Strip's new dimensions
775  */
776 void BKE_nlameta_flush_transforms (NlaStrip *mstrip) 
777 {
778         NlaStrip *strip;
779         float oStart, oEnd, offset;
780         float oLen, nLen;
781         short scaleChanged= 0;
782         
783         /* sanity checks 
784          *      - strip must exist
785          *      - strip must be a meta-strip with some contents
786          */
787         if ELEM(NULL, mstrip, mstrip->strips.first)
788                 return;
789         if (mstrip->type != NLASTRIP_TYPE_META)
790                 return;
791                 
792         /* get the original start/end points, and calculate the start-frame offset
793          *      - these are simply the start/end frames of the child strips, 
794          *        since we assume they weren't transformed yet
795          */
796         oStart= ((NlaStrip *)mstrip->strips.first)->start;
797         oEnd= ((NlaStrip *)mstrip->strips.last)->end;
798         offset= mstrip->start - oStart;
799         
800         /* optimisation:
801          * don't flush if nothing changed yet
802          *      TODO: maybe we need a flag to say always flush?
803          */
804         if (IS_EQF(oStart, mstrip->start) && IS_EQF(oEnd, mstrip->end))
805                 return;
806         
807         /* check if scale changed */
808         oLen = oEnd - oStart;
809         nLen = mstrip->end - mstrip->start;
810         if (IS_EQF(nLen, oLen) == 0)
811                 scaleChanged= 1;
812         
813         /* for each child-strip, calculate new start/end points based on this new info */
814         for (strip= mstrip->strips.first; strip; strip= strip->next) {
815                 if (scaleChanged) {
816                         PointerRNA ptr;
817                         float p1, p2, nStart, nEnd;
818                         
819                         /* compute positions of endpoints relative to old extents of strip */
820                         p1= (strip->start - oStart) / oLen;
821                         p2= (strip->end - oStart) / oLen;
822                         
823                         /* compute the new strip endpoints using the proportions */
824                         nStart= (p1 * nLen) + mstrip->start;
825                         nEnd= (p2 * nLen) + mstrip->start;
826                         
827                         /* firstly, apply the new positions manually, then apply using RNA 
828                          *      - first time is to make sure no truncation errors from one endpoint not being 
829                          *        set yet occur
830                          *      - second time is to make sure scale is computed properly...
831                          */
832                         strip->start= nStart;
833                         strip->end= nEnd;
834                         
835                         RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &ptr);
836                         RNA_float_set(&ptr, "frame_start", nStart);
837                         RNA_float_set(&ptr, "frame_end", nEnd);
838                 }
839                 else {
840                         /* just apply the changes in offset to both ends of the strip */
841                         strip->start += offset;
842                         strip->end += offset;
843                 }
844                 
845                 /* finally, make sure the strip's children (if it is a meta-itself), get updated */
846                 BKE_nlameta_flush_transforms(strip);
847         }
848 }
849
850 /* NLA-Tracks ---------------------------------------- */
851
852 /* Find the active NLA-track for the given stack */
853 NlaTrack *BKE_nlatrack_find_active (ListBase *tracks)
854 {
855         NlaTrack *nlt;
856         
857         /* sanity check */
858         if ELEM(NULL, tracks, tracks->first)
859                 return NULL;
860                 
861         /* try to find the first active track */
862         for (nlt= tracks->first; nlt; nlt= nlt->next) {
863                 if (nlt->flag & NLATRACK_ACTIVE)
864                         return nlt;
865         }
866         
867         /* none found */
868         return NULL;
869 }
870
871 /* Toggle the 'solo' setting for the given NLA-track, making sure that it is the only one
872  * that has this status in its AnimData block.
873  */
874 void BKE_nlatrack_solo_toggle (AnimData *adt, NlaTrack *nlt)
875 {
876         NlaTrack *nt;
877         
878         /* sanity check */
879         if ELEM(NULL, adt, adt->nla_tracks.first)
880                 return;
881                 
882         /* firstly, make sure 'solo' flag for all tracks is disabled */
883         for (nt= adt->nla_tracks.first; nt; nt= nt->next) {
884                 if (nt != nlt)
885                         nt->flag &= ~NLATRACK_SOLO;
886         }
887                 
888         /* now, enable 'solo' for the given track if appropriate */
889         if (nlt) {
890                 /* toggle solo status */
891                 nlt->flag ^= NLATRACK_SOLO;
892                 
893                 /* set or clear solo-status on AnimData */
894                 if (nlt->flag & NLATRACK_SOLO)
895                         adt->flag |= ADT_NLA_SOLO_TRACK;
896                 else
897                         adt->flag &= ~ADT_NLA_SOLO_TRACK;
898         }
899         else
900                 adt->flag &= ~ADT_NLA_SOLO_TRACK;
901 }
902
903 /* Make the given NLA-track the active one for the given stack. If no track is provided, 
904  * this function can be used to simply deactivate all the NLA tracks in the given stack too.
905  */
906 void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a)
907 {
908         NlaTrack *nlt;
909         
910         /* sanity check */
911         if ELEM(NULL, tracks, tracks->first)
912                 return;
913         
914         /* deactive all the rest */
915         for (nlt= tracks->first; nlt; nlt= nlt->next) 
916                 nlt->flag &= ~NLATRACK_ACTIVE;
917                 
918         /* set the given one as the active one */
919         if (nlt_a)
920                 nlt_a->flag |= NLATRACK_ACTIVE;
921 }
922
923 /* Check if there is any space in the given track to add a strip of the given length */
924 short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end)
925 {
926         /* sanity checks 
927          *      - track must exist
928          *      - track must be editable
929          *      - bounds cannot be equal (0-length is nasty) 
930          */
931         if ((nlt == NULL) || (nlt->flag & NLATRACK_PROTECTED) || IS_EQF(start, end))
932                 return 0;
933         
934         if (start > end) {
935                 puts("BKE_nlatrack_has_space() error... start and end arguments swapped");
936                 SWAP(float, start, end);
937         }
938         
939         /* check if there's any space left in the track for a strip of the given length */
940         return BKE_nlastrips_has_space(&nlt->strips, start, end);
941 }
942
943 /* Rearrange the strips in the track so that they are always in order 
944  * (usually only needed after a strip has been moved) 
945  */
946 void BKE_nlatrack_sort_strips (NlaTrack *nlt)
947 {
948         /* sanity checks */
949         if ELEM(NULL, nlt, nlt->strips.first)
950                 return;
951         
952         /* sort the strips with a more generic function */
953         BKE_nlastrips_sort_strips(&nlt->strips);
954 }
955
956 /* Add the given NLA-Strip to the given NLA-Track, assuming that it 
957  * isn't currently attached to another one 
958  */
959 short BKE_nlatrack_add_strip (NlaTrack *nlt, NlaStrip *strip)
960 {
961         /* sanity checks */
962         if ELEM(NULL, nlt, strip)
963                 return 0;
964                 
965         /* try to add the strip to the track using a more generic function */
966         return BKE_nlastrips_add_strip(&nlt->strips, strip);
967 }
968
969 /* Get the extents of the given NLA-Track including gaps between strips,
970  * returning whether this succeeded or not
971  */
972 short BKE_nlatrack_get_bounds (NlaTrack *nlt, float bounds[2])
973 {
974         NlaStrip *strip;
975         
976         /* initialise bounds */
977         if (bounds)
978                 bounds[0] = bounds[1] = 0.0f;
979         else
980                 return 0;
981         
982         /* sanity checks */
983         if ELEM(NULL, nlt, nlt->strips.first)
984                 return 0;
985                 
986         /* lower bound is first strip's start frame */
987         strip = nlt->strips.first;
988         bounds[0] = strip->start;
989         
990         /* upper bound is last strip's end frame */
991         strip = nlt->strips.last;
992         bounds[1] = strip->end;
993         
994         /* done */
995         return 1;
996 }
997
998 /* NLA Strips -------------------------------------- */
999
1000 /* Find the active NLA-strip within the given track */
1001 NlaStrip *BKE_nlastrip_find_active (NlaTrack *nlt)
1002 {
1003         NlaStrip *strip;
1004         
1005         /* sanity check */
1006         if ELEM(NULL, nlt, nlt->strips.first)
1007                 return NULL;
1008                 
1009         /* try to find the first active strip */
1010         for (strip= nlt->strips.first; strip; strip= strip->next) {
1011                 if (strip->flag & NLASTRIP_FLAG_ACTIVE)
1012                         return strip;
1013         }
1014         
1015         /* none found */
1016         return NULL;
1017 }
1018
1019 /* Make the given NLA-Strip the active one within the given block */
1020 void BKE_nlastrip_set_active (AnimData *adt, NlaStrip *strip)
1021 {
1022         NlaTrack *nlt;
1023         NlaStrip *nls;
1024         
1025         /* sanity checks */
1026         if (adt == NULL)
1027                 return;
1028         
1029         /* loop over tracks, deactivating*/
1030         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1031                 for (nls= nlt->strips.first; nls; nls= nls->next)  {
1032                         if (nls != strip)
1033                                 nls->flag &= ~NLASTRIP_FLAG_ACTIVE;
1034                         else
1035                                 nls->flag |= NLASTRIP_FLAG_ACTIVE;
1036                 }
1037         }
1038 }
1039
1040
1041 /* Does the given NLA-strip fall within the given bounds (times)? */
1042 short BKE_nlastrip_within_bounds (NlaStrip *strip, float min, float max)
1043 {
1044         const float stripLen= (strip) ? strip->end - strip->start : 0.0f;
1045         const float boundsLen= (float)fabs(max - min);
1046         
1047         /* sanity checks */
1048         if ((strip == NULL) || IS_EQF(stripLen, 0.0f) || IS_EQF(boundsLen, 0.0f))
1049                 return 0;
1050         
1051         /* only ok if at least part of the strip is within the bounding window
1052          *      - first 2 cases cover when the strip length is less than the bounding area
1053          *      - second 2 cases cover when the strip length is greater than the bounding area
1054          */
1055         if ( (stripLen < boundsLen) && 
1056                  !(IN_RANGE(strip->start, min, max) ||
1057                    IN_RANGE(strip->end, min, max)) )
1058         {
1059                 return 0;
1060         }
1061         if ( (stripLen > boundsLen) && 
1062                  !(IN_RANGE(min, strip->start, strip->end) ||
1063                    IN_RANGE(max, strip->start, strip->end)) )
1064         {
1065                 return 0;
1066         }
1067         
1068         /* should be ok! */
1069         return 1;
1070 }
1071
1072 /* Recalculate the start and end frames for the current strip, after changing
1073  * the extents of the action or the mapping (repeats or scale factor) info
1074  */
1075 void BKE_nlastrip_recalculate_bounds (NlaStrip *strip)
1076 {
1077         float actlen, mapping;
1078         
1079         /* sanity checks
1080          *      - must have a strip
1081          *      - can only be done for action clips
1082          */
1083         if ((strip == NULL) || (strip->type != NLASTRIP_TYPE_CLIP))
1084                 return;
1085                 
1086         /* calculate new length factors */
1087         actlen= strip->actend - strip->actstart;
1088         if (IS_EQF(actlen, 0.0f)) actlen= 1.0f;
1089         
1090         mapping= strip->scale * strip->repeat;
1091         
1092         /* adjust endpoint of strip in response to this */
1093         if (IS_EQF(mapping, 0.0f) == 0)
1094                 strip->end = (actlen * mapping) + strip->start;
1095 }
1096
1097 /* Is the given NLA-strip the first one to occur for the given AnimData block */
1098 // TODO: make this an api method if necesary, but need to add prefix first
1099 static short nlastrip_is_first (AnimData *adt, NlaStrip *strip)
1100 {
1101         NlaTrack *nlt;
1102         NlaStrip *ns;
1103         
1104         /* sanity checks */
1105         if ELEM(NULL, adt, strip)
1106                 return 0;
1107                 
1108         /* check if strip has any strips before it */
1109         if (strip->prev)
1110                 return 0;
1111                 
1112         /* check other tracks to see if they have a strip that's earlier */
1113         // TODO: or should we check that the strip's track is also the first?
1114         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1115                 /* only check the first strip, assuming that they're all in order */
1116                 ns= nlt->strips.first;
1117                 if (ns) {
1118                         if (ns->start < strip->start)
1119                                 return 0;
1120                 }
1121         }       
1122         
1123         /* should be first now */
1124         return 1;
1125 }
1126
1127 /* Animated Strips ------------------------------------------- */
1128
1129 /* Check if the given NLA-Track has any strips with own F-Curves */
1130 short BKE_nlatrack_has_animated_strips (NlaTrack *nlt)
1131 {
1132         NlaStrip *strip;
1133         
1134         /* sanity checks */
1135         if ELEM(NULL, nlt, nlt->strips.first)
1136                 return 0;
1137                 
1138         /* check each strip for F-Curves only (don't care about whether the flags are set) */
1139         for (strip= nlt->strips.first; strip; strip= strip->next) {
1140                 if (strip->fcurves.first)
1141                         return 1;
1142         }
1143         
1144         /* none found */
1145         return 0;
1146 }
1147
1148 /* Check if given NLA-Tracks have any strips with own F-Curves */
1149 short BKE_nlatracks_have_animated_strips (ListBase *tracks)
1150 {
1151         NlaTrack *nlt;
1152         
1153         /* sanity checks */
1154         if ELEM(NULL, tracks, tracks->first)
1155                 return 0;
1156                 
1157         /* check each track, stopping on the first hit */
1158         for (nlt= tracks->first; nlt; nlt= nlt->next) {
1159                 if (BKE_nlatrack_has_animated_strips(nlt))
1160                         return 1;
1161         }
1162         
1163         /* none found */
1164         return 0;
1165 }
1166
1167 /* Validate the NLA-Strips 'control' F-Curves based on the flags set*/
1168 void BKE_nlastrip_validate_fcurves (NlaStrip *strip) 
1169 {
1170         FCurve *fcu;
1171         
1172         /* sanity checks */
1173         if (strip == NULL)
1174                 return;
1175         
1176         /* if controlling influence... */
1177         if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
1178                 /* try to get F-Curve */
1179                 fcu= list_find_fcurve(&strip->fcurves, "influence", 0);
1180                 
1181                 /* add one if not found */
1182                 if (fcu == NULL) {
1183                         /* make new F-Curve */
1184                         fcu= MEM_callocN(sizeof(FCurve), "NlaStrip FCurve");
1185                         BLI_addtail(&strip->fcurves, fcu);
1186                         
1187                         /* set default flags */
1188                         fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
1189                         
1190                         /* store path - make copy, and store that */
1191                         fcu->rna_path= BLI_strdupn("influence", 9);
1192                         
1193                         // TODO: insert a few keyframes to ensure default behaviour?
1194                 }
1195         }
1196         
1197         /* if controlling time... */
1198         if (strip->flag & NLASTRIP_FLAG_USR_TIME) {
1199                 /* try to get F-Curve */
1200                 fcu= list_find_fcurve(&strip->fcurves, "strip_time", 0);
1201                 
1202                 /* add one if not found */
1203                 if (fcu == NULL) {
1204                         /* make new F-Curve */
1205                         fcu= MEM_callocN(sizeof(FCurve), "NlaStrip FCurve");
1206                         BLI_addtail(&strip->fcurves, fcu);
1207                         
1208                         /* set default flags */
1209                         fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
1210                         
1211                         /* store path - make copy, and store that */
1212                         fcu->rna_path= BLI_strdupn("strip_time", 10);
1213                         
1214                         // TODO: insert a few keyframes to ensure default behaviour?
1215                 }
1216         }
1217 }
1218
1219 /* Sanity Validation ------------------------------------ */
1220
1221 static int nla_editbone_name_check(void *arg, const char *name)
1222 {
1223         return BLI_ghash_haskey((GHash *)arg, (void *)name);
1224 }
1225
1226 /* Find (and set) a unique name for a strip from the whole AnimData block 
1227  * Uses a similar method to the BLI method, but is implemented differently
1228  * as we need to ensure that the name is unique over several lists of tracks,
1229  * not just a single track.
1230  */
1231 void BKE_nlastrip_validate_name (AnimData *adt, NlaStrip *strip)
1232 {
1233         GHash *gh;
1234         NlaStrip *tstrip;
1235         NlaTrack *nlt;
1236         
1237         /* sanity checks */
1238         if ELEM(NULL, adt, strip)
1239                 return;
1240                 
1241         /* give strip a default name if none already */
1242         if (strip->name[0]==0) {
1243                 switch (strip->type) {
1244                         case NLASTRIP_TYPE_CLIP: /* act-clip */
1245                                 sprintf(strip->name, "%s", (strip->act)?(strip->act->id.name+2):("<No Action>"));
1246                                 break;
1247                         case NLASTRIP_TYPE_TRANSITION: /* transition */
1248                                 sprintf(strip->name, "Transition");
1249                                 break;
1250                         case NLASTRIP_TYPE_META: /* meta */
1251                                 sprintf(strip->name, "Meta");
1252                                 break;
1253                         default:
1254                                 sprintf(strip->name, "NLA Strip");
1255                                 break;
1256                 }
1257         }
1258         
1259         /* build a hash-table of all the strips in the tracks 
1260          *      - this is easier than iterating over all the tracks+strips hierarchy everytime
1261          *        (and probably faster)
1262          */
1263         gh= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "nlastrip_validate_name gh");
1264         
1265         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1266                 for (tstrip= nlt->strips.first; tstrip; tstrip= tstrip->next) {
1267                         /* don't add the strip of interest */
1268                         if (tstrip == strip) 
1269                                 continue;
1270                         
1271                         /* use the name of the strip as the key, and the strip as the value, since we're mostly interested in the keys */
1272                         BLI_ghash_insert(gh, tstrip->name, tstrip);
1273                 }
1274         }
1275         
1276         /* if the hash-table has a match for this name, try other names... 
1277          *      - in an extreme case, it might not be able to find a name, but then everything else in Blender would fail too :)
1278          */
1279         BLI_uniquename_cb(nla_editbone_name_check, (void *)gh, "NlaStrip", '.', strip->name, sizeof(strip->name));
1280
1281         /* free the hash... */
1282         BLI_ghash_free(gh, NULL, NULL);
1283 }
1284
1285 /* ---- */
1286
1287 /* Get strips which overlap the given one at the start/end of its range 
1288  *      - strip: strip that we're finding overlaps for
1289  *      - track: nla-track that the overlapping strips should be found from
1290  *      - start, end: frames for the offending endpoints
1291  */
1292 static void nlastrip_get_endpoint_overlaps (NlaStrip *strip, NlaTrack *track, float **start, float **end)
1293 {
1294         NlaStrip *nls;
1295         
1296         /* find strips that overlap over the start/end of the given strip,
1297          * but which don't cover the entire length 
1298          */
1299         // TODO: this scheme could get quite slow for doing this on many strips...
1300         for (nls= track->strips.first; nls; nls= nls->next) {
1301                 /* check if strip overlaps (extends over or exactly on) the entire range of the strip we're validating */
1302                 if ((nls->start <= strip->start) && (nls->end >= strip->end)) {
1303                         *start= NULL;
1304                         *end= NULL;
1305                         return;
1306                 }
1307                 
1308                 /* check if strip doesn't even occur anywhere near... */
1309                 if (nls->end < strip->start)
1310                         continue; /* skip checking this strip... not worthy of mention */
1311                 if (nls->start > strip->end)
1312                         return; /* the range we're after has already passed */
1313                         
1314                 /* if this strip is not part of an island of continuous strips, it can be used
1315                  *      - this check needs to be done for each end of the strip we try and use...
1316                  */
1317                 if ((nls->next == NULL) || IS_EQF(nls->next->start, nls->end)==0) {
1318                         if ((nls->end > strip->start) && (nls->end < strip->end))
1319                                 *start= &nls->end;
1320                 }
1321                 if ((nls->prev == NULL) || IS_EQF(nls->prev->end, nls->start)==0) {
1322                         if ((nls->start < strip->end) && (nls->start > strip->start))
1323                                 *end= &nls->start;
1324                 }
1325         }
1326 }
1327
1328 /* Determine auto-blending for the given strip */
1329 static void BKE_nlastrip_validate_autoblends (NlaTrack *nlt, NlaStrip *nls)
1330 {
1331         float *ps=NULL, *pe=NULL;
1332         float *ns=NULL, *ne=NULL;
1333         
1334         /* sanity checks */
1335         if ELEM(NULL, nls, nlt)
1336                 return;
1337         if ((nlt->prev == NULL) && (nlt->next == NULL))
1338                 return;
1339         if ((nls->flag & NLASTRIP_FLAG_AUTO_BLENDS)==0)
1340                 return;
1341         
1342         /* get test ranges */
1343         if (nlt->prev)
1344                 nlastrip_get_endpoint_overlaps(nls, nlt->prev, &ps, &pe);
1345         if (nlt->next)
1346                 nlastrip_get_endpoint_overlaps(nls, nlt->next, &ns, &ne);
1347                 
1348         /* set overlaps for this strip 
1349          *      - don't use the values obtained though if the end in question 
1350          *        is directly followed/preceeded by another strip, forming an 
1351          *        'island' of continuous strips
1352          */
1353         if ( (ps || ns) && ((nls->prev == NULL) || IS_EQF(nls->prev->end, nls->start)==0) )
1354         {
1355                 /* start overlaps - pick the largest overlap */
1356                 if ( ((ps && ns) && (*ps > *ns)) || (ps) )
1357                         nls->blendin= *ps - nls->start;
1358                 else
1359                         nls->blendin= *ns - nls->start;
1360         }
1361         else /* no overlap allowed/needed */
1362                 nls->blendin= 0.0f;
1363                 
1364         if ( (pe || ne) && ((nls->next == NULL) || IS_EQF(nls->next->start, nls->end)==0) )
1365         {
1366                 /* end overlaps - pick the largest overlap */
1367                 if ( ((pe && ne) && (*pe > *ne)) || (pe) )
1368                         nls->blendout= nls->end - *pe;
1369                 else
1370                         nls->blendout= nls->end - *ne;
1371         }
1372         else /* no overlap allowed/needed */
1373                 nls->blendout= 0.0f;
1374 }
1375
1376 /* Ensure that auto-blending and other settings are set correctly */
1377 void BKE_nla_validate_state (AnimData *adt)
1378 {
1379         NlaStrip *strip, *fstrip=NULL;
1380         NlaTrack *nlt;
1381         
1382         /* sanity checks */
1383         if ELEM(NULL, adt, adt->nla_tracks.first)
1384                 return;
1385                 
1386         /* adjust blending values for auto-blending, and also do an initial pass to find the earliest strip */
1387         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1388                 for (strip= nlt->strips.first; strip; strip= strip->next) {
1389                         /* auto-blending first */
1390                         BKE_nlastrip_validate_autoblends(nlt, strip);
1391                         
1392                         /* extend mode - find first strip */
1393                         if ((fstrip == NULL) || (strip->start < fstrip->start))
1394                                 fstrip= strip;
1395                 }
1396         }
1397         
1398         /* second pass over the strips to adjust the extend-mode to fix any problems */
1399         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1400                 for (strip= nlt->strips.first; strip; strip= strip->next) {
1401                         /* apart from 'nothing' option which user has to explicitly choose, we don't really know if 
1402                          * we should be overwriting the extend setting (but assume that's what the user wanted)
1403                          */
1404                         // TODO: 1 solution is to tie this in with auto-blending...
1405                         if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
1406                                 if (strip == fstrip)
1407                                         strip->extendmode= NLASTRIP_EXTEND_HOLD;
1408                                 else
1409                                         strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD;
1410                         }
1411                 }
1412         }
1413 }
1414
1415 /* Core Tools ------------------------------------------- */
1416
1417 /* For the given AnimData block, add the active action to the NLA
1418  * stack (i.e. 'push-down' action). The UI should only allow this 
1419  * for normal editing only (i.e. not in editmode for some strip's action),
1420  * so no checks for this are performed.
1421  */
1422 // TODO: maybe we should have checks for this too...
1423 void BKE_nla_action_pushdown (AnimData *adt)
1424 {
1425         NlaStrip *strip;
1426         
1427         /* sanity checks */
1428         // TODO: need to report the error for this
1429         if ELEM(NULL, adt, adt->action) 
1430                 return;
1431                 
1432         /* if the action is empty, we also shouldn't try to add to stack, 
1433          * as that will cause us grief down the track
1434          */
1435         // TODO: what about modifiers?
1436         if (action_has_motion(adt->action) == 0) {
1437                 printf("BKE_nla_action_pushdown(): action has no data \n");
1438                 return;
1439         }
1440         
1441         /* add a new NLA strip to the track, which references the active action */
1442         strip= add_nlastrip_to_stack(adt, adt->action);
1443         
1444         /* do other necessary work on strip */  
1445         if (strip) {
1446                 /* clear reference to action now that we've pushed it onto the stack */
1447                 id_us_min(&adt->action->id);
1448                 adt->action= NULL;
1449                 
1450                 /* if the strip is the first one in the track it lives in, check if there
1451                  * are strips in any other tracks that may be before this, and set the extend
1452                  * mode accordingly
1453                  */
1454                 if (nlastrip_is_first(adt, strip) == 0) {
1455                         /* not first, so extend mode can only be NLASTRIP_EXTEND_HOLD_FORWARD not NLASTRIP_EXTEND_HOLD,
1456                          * so that it doesn't override strips in previous tracks
1457                          */
1458                         // FIXME: this needs to be more automated, since user can rearrange strips
1459                         strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD;
1460                 }
1461                 
1462                 /* make strip the active one... */
1463                 BKE_nlastrip_set_active(adt, strip);
1464         }
1465 }
1466
1467
1468 /* Find the active strip + track combo, and set them up as the tweaking track,
1469  * and return if successful or not.
1470  */
1471 short BKE_nla_tweakmode_enter (AnimData *adt)
1472 {
1473         NlaTrack *nlt, *activeTrack=NULL;
1474         NlaStrip *strip, *activeStrip=NULL;
1475         
1476         /* verify that data is valid */
1477         if ELEM(NULL, adt, adt->nla_tracks.first)
1478                 return 0;
1479                 
1480         /* if block is already in tweakmode, just leave, but we should report 
1481          * that this block is in tweakmode (as our returncode)
1482          */
1483         if (adt->flag & ADT_NLA_EDIT_ON)
1484                 return 1;
1485                 
1486         /* go over the tracks, finding the active one, and its active strip
1487          *      - if we cannot find both, then there's nothing to do
1488          */
1489         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1490                 /* check if active */
1491                 if (nlt->flag & NLATRACK_ACTIVE) {
1492                         /* store reference to this active track */
1493                         activeTrack= nlt;
1494                         
1495                         /* now try to find active strip */
1496                         activeStrip= BKE_nlastrip_find_active(nlt);
1497                         break;
1498                 }       
1499         }
1500         if ELEM3(NULL, activeTrack, activeStrip, activeStrip->act) {
1501                 if (G.f & G_DEBUG) {
1502                         printf("NLA tweakmode enter - neither active requirement found \n");
1503                         printf("\tactiveTrack = %p, activeStrip = %p \n", (void *)activeTrack, (void *)activeStrip);
1504                 }
1505                 return 0;
1506         }
1507                 
1508         /* go over all the tracks up to the active one, tagging each strip that uses the same 
1509          * action as the active strip, but leaving everything else alone
1510          */
1511         for (nlt= activeTrack->prev; nlt; nlt= nlt->prev) {
1512                 for (strip= nlt->strips.first; strip; strip= strip->next) {
1513                         if (strip->act == activeStrip->act)
1514                                 strip->flag |= NLASTRIP_FLAG_TWEAKUSER;
1515                         else
1516                                 strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
1517                 }
1518         }
1519         
1520         
1521         /* go over all the tracks after AND INCLUDING the active one, tagging them as being disabled 
1522          *      - the active track needs to also be tagged, otherwise, it'll overlap with the tweaks going on
1523          */
1524         for (nlt= activeTrack; nlt; nlt= nlt->next)
1525                 nlt->flag |= NLATRACK_DISABLED;
1526         
1527         /* handle AnimData level changes:
1528          *      - 'real' active action to temp storage (no need to change user-counts)
1529          *      - action of active strip set to be the 'active action', and have its usercount incremented
1530          *      - editing-flag for this AnimData block should also get turned on (for more efficient restoring)
1531          *      - take note of the active strip for mapping-correction of keyframes in the action being edited
1532          */
1533         adt->tmpact= adt->action;
1534         adt->action= activeStrip->act;
1535         adt->actstrip= activeStrip;
1536         id_us_plus(&activeStrip->act->id);
1537         adt->flag |= ADT_NLA_EDIT_ON;
1538         
1539         /* done! */
1540         return 1;
1541 }
1542
1543 /* Exit tweakmode for this AnimData block */
1544 void BKE_nla_tweakmode_exit (AnimData *adt)
1545 {
1546         NlaStrip *strip;
1547         NlaTrack *nlt;
1548         
1549         /* verify that data is valid */
1550         if ELEM(NULL, adt, adt->nla_tracks.first)
1551                 return;
1552                 
1553         /* hopefully the flag is correct - skip if not on */
1554         if ((adt->flag & ADT_NLA_EDIT_ON) == 0)
1555                 return;
1556                 
1557         // TODO: need to sync the user-strip with the new state of the action!
1558                 
1559         /* for all Tracks, clear the 'disabled' flag
1560          * for all Strips, clear the 'tweak-user' flag
1561          */
1562         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1563                 nlt->flag &= ~NLATRACK_DISABLED;
1564                 
1565                 for (strip= nlt->strips.first; strip; strip= strip->next) 
1566                         strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
1567         }
1568         
1569         /* handle AnimData level changes:
1570          *      - 'temporary' active action needs its usercount decreased, since we're removing this reference
1571          *      - 'real' active action is restored from storage
1572          *      - storage pointer gets cleared (to avoid having bad notes hanging around)
1573          *      - editing-flag for this AnimData block should also get turned off
1574          *      - clear pointer to active strip
1575          */
1576         if (adt->action) adt->action->id.us--;
1577         adt->action= adt->tmpact;
1578         adt->tmpact= NULL;
1579         adt->actstrip= NULL;
1580         adt->flag &= ~ADT_NLA_EDIT_ON;
1581 }
1582
1583 /* Baking Tools ------------------------------------------- */
1584
1585 static void BKE_nla_bake (Scene *scene, ID *UNUSED(id), AnimData *adt, int UNUSED(flag))
1586 {
1587
1588         /* verify that data is valid 
1589          *      1) Scene and AnimData must be provided 
1590          *      2) there must be tracks to merge...
1591          */
1592         if ELEM3(NULL, scene, adt, adt->nla_tracks.first)
1593                 return;
1594         
1595         /* if animdata currently has an action, 'push down' this onto the stack first */
1596         if (adt->action)
1597                 BKE_nla_action_pushdown(adt);
1598         
1599         /* get range of motion to bake, and the channels involved... */
1600         
1601         /* temporarily mute the action, and start keying to it */
1602         
1603         /* start keying... */
1604         
1605         /* unmute the action */
1606 }
1607
1608 /* *************************************************** */