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