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