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