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