NLA SoC: Fixed bug with NLA-Transform
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 <math.h>
34 #include <float.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLI_blenlib.h"
39
40 #include "DNA_anim_types.h"
41 #include "DNA_action_types.h"
42
43 #include "BKE_animsys.h"
44 #include "BKE_action.h"
45 #include "BKE_fcurve.h"
46 #include "BKE_nla.h"
47 #include "BKE_blender.h"
48 #include "BKE_library.h"
49 #include "BKE_object.h"
50 #include "BKE_utildefines.h"
51
52 #include "RNA_access.h"
53 #include "nla_private.h"
54
55
56 #ifdef HAVE_CONFIG_H
57 #include <config.h>
58 #endif
59
60
61 /* *************************************************** */
62 /* Data Management */
63
64 /* Freeing ------------------------------------------- */
65
66 /* Remove the given NLA strip from the NLA track it occupies, free the strip's data,
67  * and the strip itself. 
68  */
69 void free_nlastrip (ListBase *strips, NlaStrip *strip)
70 {
71         NlaStrip *cs, *csn;
72         
73         /* sanity checks */
74         if (strip == NULL)
75                 return;
76                 
77         /* free child-strips */
78         for (cs= strip->strips.first; cs; cs= csn) {
79                 csn= cs->next;
80                 free_nlastrip(&strip->strips, cs);
81         }
82                 
83         /* remove reference to action */
84         if (strip->act)
85                 strip->act->id.us--;
86                 
87         /* free remapping info */
88         //if (strip->remap)
89         //      BKE_animremap_free();
90         
91         /* free own F-Curves */
92         free_fcurves(&strip->fcurves);
93         
94         /* free own F-Modifiers */
95         free_fmodifiers(&strip->modifiers);
96         
97         /* free the strip itself */
98         if (strips)
99                 BLI_freelinkN(strips, strip);
100         else
101                 MEM_freeN(strip);
102 }
103
104 /* Remove the given NLA track from the set of NLA tracks, free the track's data,
105  * and the track itself.
106  */
107 void free_nlatrack (ListBase *tracks, NlaTrack *nlt)
108 {
109         NlaStrip *strip, *stripn;
110         
111         /* sanity checks */
112         if (nlt == NULL)
113                 return;
114                 
115         /* free strips */
116         for (strip= nlt->strips.first; strip; strip= stripn) {
117                 stripn= strip->next;
118                 free_nlastrip(&nlt->strips, strip);
119         }
120         
121         /* free NLA track itself now */
122         if (tracks)
123                 BLI_freelinkN(tracks, nlt);
124         else
125                 MEM_freeN(nlt);
126 }
127
128 /* Free the elements of type NLA Tracks provided in the given list, but do not free
129  * the list itself since that is not free-standing
130  */
131 void free_nladata (ListBase *tracks)
132 {
133         NlaTrack *nlt, *nltn;
134         
135         /* sanity checks */
136         if ELEM(NULL, tracks, tracks->first)
137                 return;
138                 
139         /* free tracks one by one */
140         for (nlt= tracks->first; nlt; nlt= nltn) {
141                 nltn= nlt->next;
142                 free_nlatrack(tracks, nlt);
143         }
144         
145         /* clear the list's pointers to be safe */
146         tracks->first= tracks->last= NULL;
147 }
148
149 /* Copying ------------------------------------------- */
150
151 /* Copy NLA strip */
152 NlaStrip *copy_nlastrip (NlaStrip *strip)
153 {
154         NlaStrip *strip_d;
155         NlaStrip *cs, *cs_d;
156         
157         /* sanity check */
158         if (strip == NULL)
159                 return NULL;
160                 
161         /* make a copy */
162         strip_d= MEM_dupallocN(strip);
163         strip_d->next= strip_d->prev= NULL;
164         
165         /* increase user-count of action */
166         if (strip_d->act)
167                 strip_d->act->id.us++;
168                 
169         /* copy F-Curves and modifiers */
170         copy_fcurves(&strip_d->fcurves, &strip->fcurves);
171         copy_fmodifiers(&strip_d->modifiers, &strip->modifiers);
172         
173         /* make a copy of all the child-strips, one at a time */
174         strip_d->strips.first= strip_d->strips.last= NULL;
175         
176         for (cs= strip->strips.first; cs; cs= cs->next) {
177                 cs_d= copy_nlastrip(cs);
178                 BLI_addtail(&strip_d->strips, cs_d);
179         }
180         
181         /* return the strip */
182         return strip_d;
183 }
184
185 /* Copy NLA Track */
186 NlaTrack *copy_nlatrack (NlaTrack *nlt)
187 {
188         NlaStrip *strip, *strip_d;
189         NlaTrack *nlt_d;
190         
191         /* sanity check */
192         if (nlt == NULL)
193                 return NULL;
194                 
195         /* make a copy */
196         nlt_d= MEM_dupallocN(nlt);
197         nlt_d->next= nlt_d->prev= NULL;
198         
199         /* make a copy of all the strips, one at a time */
200         nlt_d->strips.first= nlt_d->strips.last= NULL;
201         
202         for (strip= nlt->strips.first; strip; strip= strip->next) {
203                 strip_d= copy_nlastrip(strip);
204                 BLI_addtail(&nlt_d->strips, strip_d);
205         }
206         
207         /* return the copy */
208         return nlt_d;
209 }
210
211 /* Copy all NLA data */
212 void copy_nladata (ListBase *dst, ListBase *src)
213 {
214         NlaTrack *nlt, *nlt_d;
215         
216         /* sanity checks */
217         if ELEM(NULL, dst, src)
218                 return;
219                 
220         /* copy each NLA-track, one at a time */
221         for (nlt= src->first; nlt; nlt= nlt->next) {
222                 /* make a copy, and add the copy to the destination list */
223                 nlt_d= copy_nlatrack(nlt);
224                 BLI_addtail(dst, nlt_d);
225         }
226 }
227
228 /* Adding ------------------------------------------- */
229
230 /* Add a NLA Track to the given AnimData 
231  *      - prev: NLA-Track to add the new one after
232  */
233 NlaTrack *add_nlatrack (AnimData *adt, NlaTrack *prev)
234 {
235         NlaTrack *nlt;
236         
237         /* sanity checks */
238         if (adt == NULL)
239                 return NULL;
240                 
241         /* allocate new track */
242         nlt= MEM_callocN(sizeof(NlaTrack), "NlaTrack");
243         
244         /* set settings requiring the track to not be part of the stack yet */
245         nlt->flag = NLATRACK_SELECTED;
246         nlt->index= BLI_countlist(&adt->nla_tracks);
247         
248         /* add track to stack, and make it the active one */
249         if (prev)
250                 BLI_insertlinkafter(&adt->nla_tracks, prev, nlt);
251         else
252                 BLI_addtail(&adt->nla_tracks, nlt);
253         BKE_nlatrack_set_active(&adt->nla_tracks, nlt);
254         
255         /* must have unique name, but we need to seed this */
256         sprintf(nlt->name, "NlaTrack");
257         BLI_uniquename(&adt->nla_tracks, nlt, "NlaTrack", '.', offsetof(NlaTrack, name), 64);
258         
259         /* return the new track */
260         return nlt;
261 }
262
263 /* Add a NLA Strip referencing the given Action */
264 NlaStrip *add_nlastrip (bAction *act)
265 {
266         NlaStrip *strip;
267         
268         /* sanity checks */
269         if (act == NULL)
270                 return NULL;
271                 
272         /* allocate new strip */
273         strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
274         
275         /* generic settings 
276          *      - selected flag to highlight this to the user
277          *      - auto-blends to ensure that blend in/out values are automatically 
278          *        determined by overlaps of strips
279          *      - (XXX) synchronisation of strip-length in accordance with changes to action-length
280          *        is not done though, since this should only really happens in editmode for strips now
281          *        though this decision is still subject to further review...
282          */
283         strip->flag = NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_AUTO_BLENDS;
284         
285         /* assign the action reference */
286         strip->act= act;
287         id_us_plus(&act->id);
288         
289         /* determine initial range 
290          *      - strip length cannot be 0... ever...
291          */
292         calc_action_range(strip->act, &strip->actstart, &strip->actend, 1);
293         
294         strip->start = strip->actstart;
295         strip->end = (IS_EQ(strip->actstart, strip->actend)) ?  (strip->actstart + 1.0f): (strip->actend);
296         
297         /* strip should be referenced as-is */
298         strip->scale= 1.0f;
299         strip->repeat = 1.0f;
300         
301         /* return the new strip */
302         return strip;
303 }
304
305 /* Add new NLA-strip to the top of the NLA stack - i.e. into the last track if space, or a new one otherwise */
306 NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act)
307 {
308         NlaStrip *strip;
309         NlaTrack *nlt;
310         
311         /* sanity checks */
312         if ELEM(NULL, adt, act)
313                 return NULL;
314         
315         /* create a new NLA strip */
316         strip= add_nlastrip(act);
317         if (strip == NULL)
318                 return NULL;
319         
320         /* firstly try adding strip to last track, but if that fails, add to a new track */
321         if (BKE_nlatrack_add_strip(adt->nla_tracks.last, strip) == 0) {
322                 /* trying to add to the last track failed (no track or no space), 
323                  * so add a new track to the stack, and add to that...
324                  */
325                 nlt= add_nlatrack(adt, NULL);
326                 BKE_nlatrack_add_strip(nlt, strip);
327         }
328         
329         /* returns the strip added */
330         return strip;
331 }
332
333 /* *************************************************** */
334 /* NLA Evaluation <-> Editing Stuff */
335
336 /* Strip Mapping ------------------------------------- */
337
338 /* non clipped mapping for strip-time <-> global time (for Action-Clips)
339  *      invert = convert action-strip time to global time 
340  */
341 static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short mode)
342 {
343         float actlength, repeat, scale;
344         
345         /* get number of repeats */
346         if (IS_EQ(strip->repeat, 0.0f)) strip->repeat = 1.0f;
347         repeat = strip->repeat;
348         
349         /* scaling */
350         if (IS_EQ(strip->scale, 0.0f)) strip->scale= 1.0f;
351         scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */
352         
353         /* length of referenced action */
354         actlength = strip->actend - strip->actstart;
355         if (IS_EQ(actlength, 0.0f)) actlength = 1.0f;
356         
357         /* reversed = play strip backwards */
358         if (strip->flag & NLASTRIP_FLAG_REVERSE) {
359                 // FIXME: this won't work right with Graph Editor?
360                 if (mode == NLATIME_CONVERT_MAP) {
361                         return strip->end - scale*(cframe - strip->actstart);
362                 }
363                 else if (mode == NLATIME_CONVERT_UNMAP) {
364                         int repeatsNum = (int)((cframe - strip->start) / (actlength * scale));
365                         
366                         /* this method doesn't clip the values to lie within the action range only 
367                          *      - the '(repeatsNum * actlength * scale)' compensates for the fmod(...)
368                          *      - the fmod(...) works in the same way as for eval 
369                          */
370                         return strip->actend - (repeatsNum * actlength * scale) 
371                                         - (fmod(cframe - strip->start, actlength*scale) / scale);
372                 }
373                 else {
374                         if (IS_EQ(cframe, strip->end) && IS_EQ(strip->repeat, ((int)strip->repeat))) {
375                                 /* this case prevents the motion snapping back to the first frame at the end of the strip 
376                                  * by catching the case where repeats is a whole number, which means that the end of the strip
377                                  * could also be interpreted as the end of the start of a repeat
378                                  */
379                                 return strip->actstart;
380                         }
381                         else {
382                                 /* - the 'fmod(..., actlength*scale)' is needed to get the repeats working
383                                  * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat
384                                  */
385                                 return strip->actend - fmod(cframe - strip->start, actlength*scale) / scale; 
386                         }
387                 }
388         }
389         else {
390                 if (mode == NLATIME_CONVERT_MAP) {
391                         return strip->start + scale*(cframe - strip->actstart);
392                 }
393                 else if (mode == NLATIME_CONVERT_UNMAP) {
394                         int repeatsNum = (int)((cframe - strip->start) / (actlength * scale));
395                         
396                         /* this method doesn't clip the values to lie within the action range only 
397                          *      - the '(repeatsNum * actlength * scale)' compensates for the fmod(...)
398                          *      - the fmod(...) works in the same way as for eval 
399                          */
400                         return strip->actstart + (repeatsNum * actlength * scale) 
401                                         + (fmod(cframe - strip->start, actlength*scale) / scale);
402                 }
403                 else /* if (mode == NLATIME_CONVERT_EVAL) */{
404                         if (IS_EQ(cframe, strip->end) && IS_EQ(strip->repeat, ((int)strip->repeat))) {
405                                 /* this case prevents the motion snapping back to the first frame at the end of the strip 
406                                  * by catching the case where repeats is a whole number, which means that the end of the strip
407                                  * could also be interpreted as the end of the start of a repeat
408                                  */
409                                 return strip->actend;
410                         }
411                         else {
412                                 /* - the 'fmod(..., actlength*scale)' is needed to get the repeats working
413                                  * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat
414                                  */
415                                 return strip->actstart + fmod(cframe - strip->start, actlength*scale) / scale; 
416                         }
417                 }
418         }
419 }
420
421 /* non clipped mapping for strip-time <-> global time (for Transitions)
422  *      invert = convert action-strip time to global time 
423  */
424 static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short mode)
425 {
426         float length;
427         
428         /* length of strip */
429         length= strip->end - strip->start;
430         
431         /* reversed = play strip backwards */
432         if (strip->flag & NLASTRIP_FLAG_REVERSE) {
433                 if (mode == NLATIME_CONVERT_MAP)
434                         return strip->end - (length * cframe);
435                 else
436                         return (strip->end - cframe) / length;
437         }
438         else {
439                 if (mode == NLATIME_CONVERT_MAP)
440                         return (length * cframe) + strip->start;
441                 else
442                         return (cframe - strip->start) / length;
443         }
444 }
445
446 /* non clipped mapping for strip-time <-> global time
447  *      mode = eNlaTime_ConvertModes[] -> NLATIME_CONVERT_*
448  *
449  * only secure for 'internal' (i.e. within AnimSys evaluation) operations,
450  * but should not be directly relied on for stuff which interacts with editors
451  */
452 float nlastrip_get_frame (NlaStrip *strip, float cframe, short mode)
453 {
454         switch (strip->type) {
455                 case NLASTRIP_TYPE_META: /* meta (is just a container for other strips, so shouldn't use the action-clip method) */
456                 case NLASTRIP_TYPE_TRANSITION: /* transition */
457                         return nlastrip_get_frame_transition(strip, cframe, mode);
458                 
459                 case NLASTRIP_TYPE_CLIP: /* action-clip (default) */
460                 default:
461                         return nlastrip_get_frame_actionclip(strip, cframe, mode);
462         }       
463 }
464
465
466 /* Non clipped mapping for strip-time <-> global time
467  *      mode = eNlaTime_ConvertModesp[] -> NLATIME_CONVERT_*
468  *
469  * Public API method - perform this mapping using the given AnimData block
470  * and perform any necessary sanity checks on the value
471  */
472 float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short mode)
473 {
474         NlaStrip *strip;
475         
476         /* sanity checks 
477          *      - obviously we've got to have some starting data
478          *      - when not in tweakmode, the active Action does not have any scaling applied :)
479          *      - when in tweakmode, if the no-mapping flag is set, do not map
480          */
481         if ((adt == NULL) || (adt->flag & ADT_NLA_EDIT_ON)==0 || (adt->flag & ADT_NLA_EDIT_NOMAP))
482                 return cframe;
483                 
484         /* if the active-strip info has been stored already, access this, otherwise look this up
485          * and store for (very probable) future usage
486          */
487         if (adt->actstrip == NULL) {
488                 NlaTrack *nlt= BKE_nlatrack_find_active(&adt->nla_tracks);
489                 adt->actstrip= BKE_nlastrip_find_active(nlt);
490         }
491         strip= adt->actstrip;
492         
493         /* sanity checks 
494          *      - in rare cases, we may not be able to find this strip for some reason (internal error)
495          *      - for now, if the user has defined a curve to control the time, this correction cannot be performed
496          *        reliably...
497          */
498         if ((strip == NULL) || (strip->flag & NLASTRIP_FLAG_USR_TIME))
499                 return cframe;
500                 
501         /* perform the correction now... */
502         return nlastrip_get_frame(strip, cframe, mode);
503 }
504
505 /* *************************************************** */
506 /* Basic Utilities */
507
508 /* List of Strips ------------------------------------ */
509 /* (these functions are used for NLA-Tracks and also for nested/meta-strips) */
510
511 /* Check if there is any space in the given list to add the given strip */
512 short BKE_nlastrips_has_space (ListBase *strips, float start, float end)
513 {
514         NlaStrip *strip;
515         
516         /* sanity checks */
517         if ((strips == NULL) || IS_EQ(start, end))
518                 return 0;
519         if (start > end) {
520                 puts("BKE_nlastrips_has_space() error... start and end arguments swapped");
521                 SWAP(float, start, end);
522         }
523         
524         /* loop over NLA strips checking for any overlaps with this area... */
525         for (strip= strips->first; strip; strip= strip->next) {
526                 /* if start frame of strip is past the target end-frame, that means that
527                  * we've gone past the window we need to check for, so things are fine
528                  */
529                 if (strip->start > end)
530                         return 1;
531                 
532                 /* if the end of the strip is greater than either of the boundaries, the range
533                  * must fall within the extents of the strip
534                  */
535                 if ((strip->end > start) || (strip->end > end))
536                         return 0;
537         }
538         
539         /* if we are still here, we haven't encountered any overlapping strips */
540         return 1;
541 }
542
543 /* Rearrange the strips in the track so that they are always in order 
544  * (usually only needed after a strip has been moved) 
545  */
546 void BKE_nlastrips_sort_strips (ListBase *strips)
547 {
548         ListBase tmp = {NULL, NULL};
549         NlaStrip *strip, *sstrip, *stripn;
550         
551         /* sanity checks */
552         if ELEM(NULL, strips, strips->first)
553                 return;
554         
555         /* we simply perform insertion sort on this list, since it is assumed that per track,
556          * there are only likely to be at most 5-10 strips
557          */
558         for (strip= strips->first; strip; strip= stripn) {
559                 short not_added = 1;
560                 
561                 stripn= strip->next;
562                 
563                 /* remove this strip from the list, and add it to the new list, searching from the end of 
564                  * the list, assuming that the lists are in order 
565                  */
566                 BLI_remlink(strips, strip);
567                 
568                 for (sstrip= tmp.last; sstrip; sstrip= sstrip->prev) {
569                         /* check if add after */
570                         if (sstrip->end <= strip->start) {
571                                 BLI_insertlinkafter(&tmp, sstrip, strip);
572                                 not_added= 0;
573                                 break;
574                         }
575                 }
576                 
577                 /* add before first? */
578                 if (not_added)
579                         BLI_addhead(&tmp, strip);
580         }
581         
582         /* reassign the start and end points of the strips */
583         strips->first= tmp.first;
584         strips->last= tmp.last;
585 }
586
587 /* Add the given NLA-Strip to the given list of strips, assuming that it 
588  * isn't currently a member of another list
589  */
590 short BKE_nlastrips_add_strip (ListBase *strips, NlaStrip *strip)
591 {
592         NlaStrip *ns;
593         short not_added = 1;
594         
595         /* sanity checks */
596         if ELEM(NULL, strips, strip)
597                 return 0;
598                 
599         /* check if any space to add */
600         if (BKE_nlastrips_has_space(strips, strip->start, strip->end)==0)
601                 return 0;
602         
603         /* find the right place to add the strip to the nominated track */
604         for (ns= strips->first; ns; ns= ns->next) {
605                 /* if current strip occurs after the new strip, add it before */
606                 if (ns->start > strip->end) {
607                         BLI_insertlinkbefore(strips, ns, strip);
608                         not_added= 0;
609                         break;
610                 }
611         }
612         if (not_added) {
613                 /* just add to the end of the list of the strips then... */
614                 BLI_addtail(strips, strip);
615         }
616         
617         /* added... */
618         return 1;
619 }
620
621
622 /* Meta-Strips ------------------------------------ */
623
624 /* Convert 'islands' (i.e. continuous string of) selected strips to be
625  * contained within 'Meta-Strips' which act as strips which contain strips.
626  *      temp: are the meta-strips to be created 'temporary' ones used for transforms?
627  */
628 void BKE_nlastrips_make_metas (ListBase *strips, short temp)
629 {
630         NlaStrip *mstrip = NULL;
631         NlaStrip *strip, *stripn;
632         
633         /* sanity checks */
634         if ELEM(NULL, strips, strips->first)
635                 return;
636         
637         /* group all continuous chains of selected strips into meta-strips */
638         for (strip= strips->first; strip; strip= stripn) {
639                 stripn= strip->next;
640                 
641                 if (strip->flag & NLASTRIP_FLAG_SELECT) {
642                         /* if there is an existing meta-strip, add this strip to it, otherwise, create a new one */
643                         if (mstrip == NULL) {
644                                 /* add a new meta-strip, and add it before the current strip that it will replace... */
645                                 mstrip= MEM_callocN(sizeof(NlaStrip), "Meta-NlaStrip");
646                                 mstrip->type = NLASTRIP_TYPE_META;
647                                 BLI_insertlinkbefore(strips, strip, mstrip);
648                                 
649                                 /* set flags */
650                                 mstrip->flag = NLASTRIP_FLAG_SELECT;
651                                 
652                                 /* set temp flag if appropriate (i.e. for transform-type editing) */
653                                 if (temp)
654                                         mstrip->flag |= NLASTRIP_FLAG_TEMP_META;
655                                         
656                                 /* set default repeat/scale values to prevent warnings */
657                                 mstrip->repeat= mstrip->scale= 1.0f;
658                                 
659                                 /* make its start frame be set to the start frame of the current strip */
660                                 mstrip->start= strip->start;
661                         }
662                         
663                         /* remove the selected strips from the track, and add to the meta */
664                         BLI_remlink(strips, strip);
665                         BLI_addtail(&mstrip->strips, strip);
666                         
667                         /* expand the meta's dimensions to include the newly added strip- i.e. its last frame */
668                         mstrip->end= strip->end;
669                 }
670                 else {
671                         /* current strip wasn't selected, so the end of 'island' of selected strips has been reached,
672                          * so stop adding strips to the current meta
673                          */
674                         mstrip= NULL;
675                 }
676         }
677 }
678
679 /* Split a meta-strip into a set of normal strips */
680 void BKE_nlastrips_clear_metastrip (ListBase *strips, NlaStrip *strip)
681 {
682         NlaStrip *cs, *csn;
683         
684         /* sanity check */
685         if ELEM(NULL, strips, strip)
686                 return;
687         
688         /* move each one of the meta-strip's children before the meta-strip
689          * in the list of strips after unlinking them from the meta-strip
690          */
691         for (cs= strip->strips.first; cs; cs= csn) {
692                 csn= cs->next;
693                 BLI_remlink(&strip->strips, cs);
694                 BLI_insertlinkbefore(strips, strip, cs);
695         }
696         
697         /* free the meta-strip now */
698         BLI_freelinkN(strips, strip);
699 }
700
701 /* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips
702  *      sel: only consider selected meta-strips, otherwise all meta-strips are removed
703  *      onlyTemp: only remove the 'temporary' meta-strips used for transforms
704  */
705 void BKE_nlastrips_clear_metas (ListBase *strips, short onlySel, short onlyTemp)
706 {
707         NlaStrip *strip, *stripn;
708         
709         /* sanity checks */
710         if ELEM(NULL, strips, strips->first)
711                 return;
712         
713         /* remove meta-strips fitting the criteria of the arguments */
714         for (strip= strips->first; strip; strip= stripn) {
715                 stripn= strip->next;
716                 
717                 /* check if strip is a meta-strip */
718                 if (strip->type == NLASTRIP_TYPE_META) {
719                         /* if check if selection and 'temporary-only' considerations are met */
720                         if ((onlySel==0) || (strip->flag & NLASTRIP_FLAG_SELECT)) {
721                                 if ((!onlyTemp) || (strip->flag & NLASTRIP_FLAG_TEMP_META)) {
722                                         BKE_nlastrips_clear_metastrip(strips, strip);
723                                 }
724                         }
725                 }
726         }
727 }
728
729 /* Add the given NLA-Strip to the given Meta-Strip, assuming that the
730  * strip isn't attached to anyy list of strips 
731  */
732 short BKE_nlameta_add_strip (NlaStrip *mstrip, NlaStrip *strip)
733 {
734         /* sanity checks */
735         if ELEM(NULL, mstrip, strip)
736                 return 0;
737                 
738         /* firstly, check if the meta-strip has space for this */
739         if (BKE_nlastrips_has_space(&mstrip->strips, strip->start, strip->end) == 0)
740                 return 0;
741                 
742         /* check if this would need to be added to the ends of the meta,
743          * and subsequently, if the neighbouring strips allow us enough room
744          */
745         if (strip->start < mstrip->start) {
746                 /* check if strip to the left (if it exists) ends before the 
747                  * start of the strip we're trying to add 
748                  */
749                 if ((mstrip->prev == NULL) || (mstrip->prev->end <= strip->start)) {
750                         /* add strip to start of meta's list, and expand dimensions */
751                         BLI_addhead(&mstrip->strips, strip);
752                         mstrip->start= strip->start;
753                         
754                         return 1;
755                 }
756                 else /* failed... no room before */
757                         return 0;
758         }
759         else if (strip->end > mstrip->end) {
760                 /* check if strip to the right (if it exists) starts before the 
761                  * end of the strip we're trying to add 
762                  */
763                 if ((mstrip->next == NULL) || (mstrip->next->start >= strip->end)) {
764                         /* add strip to end of meta's list, and expand dimensions */
765                         BLI_addtail(&mstrip->strips, strip);
766                         mstrip->end= strip->end;
767                         
768                         return 1;
769                 }
770                 else /* failed... no room after */
771                         return 0;
772         }
773         else {
774                 /* just try to add to the meta-strip (no dimension changes needed) */
775                 return BKE_nlastrips_add_strip(&mstrip->strips, strip);
776         }
777 }
778
779 /* Adjust the settings of NLA-Strips contained within a Meta-Strip (recursively), 
780  * until the Meta-Strips children all fit within the Meta-Strip's new dimensions
781  */
782 void BKE_nlameta_flush_transforms (NlaStrip *mstrip) 
783 {
784         NlaStrip *strip;
785         float oStart, oEnd, offset;
786         float oLen, nLen;
787         short scaleChanged= 0;
788         
789         /* sanity checks 
790          *      - strip must exist
791          *      - strip must be a meta-strip with some contents
792          */
793         if ELEM(NULL, mstrip, mstrip->strips.first)
794                 return;
795         if (mstrip->type != NLASTRIP_TYPE_META)
796                 return;
797                 
798         /* get the original start/end points, and calculate the start-frame offset
799          *      - these are simply the start/end frames of the child strips, 
800          *        since we assume they weren't transformed yet
801          */
802         oStart= ((NlaStrip *)mstrip->strips.first)->start;
803         oEnd= ((NlaStrip *)mstrip->strips.last)->end;
804         offset= mstrip->start - oStart;
805         
806         /* optimisation:
807          * don't flush if nothing changed yet
808          *      TODO: maybe we need a flag to say always flush?
809          */
810         if (IS_EQ(oStart, mstrip->start) && IS_EQ(oEnd, mstrip->end))
811                 return;
812         
813         /* check if scale changed */
814         oLen = oEnd - oStart;
815         nLen = mstrip->end - mstrip->start;
816         if (IS_EQ(nLen, oLen) == 0)
817                 scaleChanged= 1;
818         
819         /* for each child-strip, calculate new start/end points based on this new info */
820         for (strip= mstrip->strips.first; strip; strip= strip->next) {
821                 if (scaleChanged) {
822                         PointerRNA ptr;
823                         float p1, p2, nStart, nEnd;
824                         
825                         /* compute positions of endpoints relative to old extents of strip */
826                         p1= (strip->start - oStart) / oLen;
827                         p2= (strip->end - oStart) / oLen;
828                         
829                         /* compute the new strip endpoints using the proportions */
830                         nStart= (p1 * nLen) + mstrip->start;
831                         nEnd= (p2 * nLen) + mstrip->start;
832                         
833                         /* firstly, apply the new positions manually, then apply using RNA 
834                          *      - first time is to make sure no truncation errors from one endpoint not being 
835                          *        set yet occur
836                          *      - second time is to make sure scale is computed properly...
837                          */
838                         strip->start= nStart;
839                         strip->end= nEnd;
840                         
841                         RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &ptr);
842                         RNA_float_set(&ptr, "start_frame", nStart);
843                         RNA_float_set(&ptr, "end_frame", nEnd);
844                 }
845                 else {
846                         /* just apply the changes in offset to both ends of the strip */
847                         strip->start += offset;
848                         strip->end += offset;
849                 }
850                 
851                 /* finally, make sure the strip's children (if it is a meta-itself), get updated */
852                 BKE_nlameta_flush_transforms(strip);
853         }
854 }
855
856 /* NLA-Tracks ---------------------------------------- */
857
858 /* Find the active NLA-track for the given stack */
859 NlaTrack *BKE_nlatrack_find_active (ListBase *tracks)
860 {
861         NlaTrack *nlt;
862         
863         /* sanity check */
864         if ELEM(NULL, tracks, tracks->first)
865                 return NULL;
866                 
867         /* try to find the first active track */
868         for (nlt= tracks->first; nlt; nlt= nlt->next) {
869                 if (nlt->flag & NLATRACK_ACTIVE)
870                         return nlt;
871         }
872         
873         /* none found */
874         return NULL;
875 }
876
877 /* Toggle the 'solo' setting for the given NLA-track, making sure that it is the only one
878  * that has this status in its AnimData block.
879  */
880 void BKE_nlatrack_solo_toggle (AnimData *adt, NlaTrack *nlt)
881 {
882         NlaTrack *nt;
883         
884         /* sanity check */
885         if ELEM(NULL, adt, adt->nla_tracks.first)
886                 return;
887                 
888         /* firstly, make sure 'solo' flag for all tracks is disabled */
889         for (nt= adt->nla_tracks.first; nt; nt= nt->next) {
890                 if (nt != nlt)
891                         nt->flag &= ~NLATRACK_SOLO;
892         }
893                 
894         /* now, enable 'solo' for the given track if appropriate */
895         if (nlt) {
896                 /* toggle solo status */
897                 nlt->flag ^= NLATRACK_SOLO;
898                 
899                 /* set or clear solo-status on AnimData */
900                 if (nlt->flag & NLATRACK_SOLO)
901                         adt->flag |= ADT_NLA_SOLO_TRACK;
902                 else
903                         adt->flag &= ~ADT_NLA_SOLO_TRACK;
904         }
905         else
906                 adt->flag &= ~ADT_NLA_SOLO_TRACK;
907 }
908
909 /* Make the given NLA-track the active one for the given stack. If no track is provided, 
910  * this function can be used to simply deactivate all the NLA tracks in the given stack too.
911  */
912 void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a)
913 {
914         NlaTrack *nlt;
915         
916         /* sanity check */
917         if ELEM(NULL, tracks, tracks->first)
918                 return;
919         
920         /* deactive all the rest */
921         for (nlt= tracks->first; nlt; nlt= nlt->next) 
922                 nlt->flag &= ~NLATRACK_ACTIVE;
923                 
924         /* set the given one as the active one */
925         if (nlt_a)
926                 nlt_a->flag |= NLATRACK_ACTIVE;
927 }
928
929
930 /* Check if there is any space in the given track to add a strip of the given length */
931 short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end)
932 {
933         /* sanity checks */
934         if ((nlt == NULL) || IS_EQ(start, end))
935                 return 0;
936         if (start > end) {
937                 puts("BKE_nlatrack_has_space() error... start and end arguments swapped");
938                 SWAP(float, start, end);
939         }
940         
941         /* check if there's any space left in the track for a strip of the given length */
942         return BKE_nlastrips_has_space(&nlt->strips, start, end);
943 }
944
945 /* Rearrange the strips in the track so that they are always in order 
946  * (usually only needed after a strip has been moved) 
947  */
948 void BKE_nlatrack_sort_strips (NlaTrack *nlt)
949 {
950         /* sanity checks */
951         if ELEM(NULL, nlt, nlt->strips.first)
952                 return;
953         
954         /* sort the strips with a more generic function */
955         BKE_nlastrips_sort_strips(&nlt->strips);
956 }
957
958 /* Add the given NLA-Strip to the given NLA-Track, assuming that it 
959  * isn't currently attached to another one 
960  */
961 short BKE_nlatrack_add_strip (NlaTrack *nlt, NlaStrip *strip)
962 {
963         /* sanity checks */
964         if ELEM(NULL, nlt, strip)
965                 return 0;
966                 
967         /* try to add the strip to the track using a more generic function */
968         return BKE_nlastrips_add_strip(&nlt->strips, strip);
969 }
970
971 /* NLA Strips -------------------------------------- */
972
973 /* Find the active NLA-strip within the given track */
974 NlaStrip *BKE_nlastrip_find_active (NlaTrack *nlt)
975 {
976         NlaStrip *strip;
977         
978         /* sanity check */
979         if ELEM(NULL, nlt, nlt->strips.first)
980                 return NULL;
981                 
982         /* try to find the first active strip */
983         for (strip= nlt->strips.first; strip; strip= strip->next) {
984                 if (strip->flag & NLASTRIP_FLAG_ACTIVE)
985                         return strip;
986         }
987         
988         /* none found */
989         return NULL;
990 }
991
992 /* Does the given NLA-strip fall within the given bounds (times)? */
993 short BKE_nlastrip_within_bounds (NlaStrip *strip, float min, float max)
994 {
995         const float stripLen= (strip) ? strip->end - strip->start : 0.0f;
996         const float boundsLen= (float)fabs(max - min);
997         
998         /* sanity checks */
999         if ((strip == NULL) || IS_EQ(stripLen, 0.0f) || IS_EQ(boundsLen, 0.0f))
1000                 return 0;
1001         
1002         /* only ok if at least part of the strip is within the bounding window
1003          *      - first 2 cases cover when the strip length is less than the bounding area
1004          *      - second 2 cases cover when the strip length is greater than the bounding area
1005          */
1006         if ( (stripLen < boundsLen) && 
1007                  !(IN_RANGE(strip->start, min, max) ||
1008                    IN_RANGE(strip->end, min, max)) )
1009         {
1010                 return 0;
1011         }
1012         if ( (stripLen > boundsLen) && 
1013                  !(IN_RANGE(min, strip->start, strip->end) ||
1014                    IN_RANGE(max, strip->start, strip->end)) )
1015         {
1016                 return 0;
1017         }
1018         
1019         /* should be ok! */
1020         return 1;
1021 }
1022
1023 /* Is the given NLA-strip the first one to occur for the given AnimData block */
1024 // TODO: make this an api method if necesary, but need to add prefix first
1025 short nlastrip_is_first (AnimData *adt, NlaStrip *strip)
1026 {
1027         NlaTrack *nlt;
1028         NlaStrip *ns;
1029         
1030         /* sanity checks */
1031         if ELEM(NULL, adt, strip)
1032                 return 0;
1033                 
1034         /* check if strip has any strips before it */
1035         if (strip->prev)
1036                 return 0;
1037                 
1038         /* check other tracks to see if they have a strip that's earlier */
1039         // TODO: or should we check that the strip's track is also the first?
1040         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1041                 /* only check the first strip, assuming that they're all in order */
1042                 ns= nlt->strips.first;
1043                 if (ns) {
1044                         if (ns->start < strip->start)
1045                                 return 0;
1046                 }
1047         }       
1048         
1049         /* should be first now */
1050         return 1;
1051 }
1052  
1053 /* Tools ------------------------------------------- */
1054
1055 /* For the given AnimData block, add the active action to the NLA
1056  * stack (i.e. 'push-down' action). The UI should only allow this 
1057  * for normal editing only (i.e. not in editmode for some strip's action),
1058  * so no checks for this are performed.
1059  */
1060 // TODO: maybe we should have checks for this too...
1061 void BKE_nla_action_pushdown (AnimData *adt)
1062 {
1063         NlaStrip *strip;
1064         
1065         /* sanity checks */
1066         // TODO: need to report the error for this
1067         if ELEM(NULL, adt, adt->action) 
1068                 return;
1069                 
1070         /* if the action is empty, we also shouldn't try to add to stack, 
1071          * as that will cause us grief down the track
1072          */
1073         // TODO: what about modifiers?
1074         if (action_has_motion(adt->action) == 0) {
1075                 printf("BKE_nla_action_pushdown(): action has no data \n");
1076                 return;
1077         }
1078         
1079         /* add a new NLA strip to the track, which references the active action */
1080         strip= add_nlastrip_to_stack(adt, adt->action);
1081         
1082         /* do other necessary work on strip */  
1083         if (strip) {
1084                 /* clear reference to action now that we've pushed it onto the stack */
1085                 adt->action->id.us--;
1086                 adt->action= NULL;
1087                 
1088                 /* if the strip is the first one in the track it lives in, check if there
1089                  * are strips in any other tracks that may be before this, and set the extend
1090                  * mode accordingly
1091                  */
1092                 if (nlastrip_is_first(adt, strip) == 0) {
1093                         /* not first, so extend mode can only be NLASTRIP_EXTEND_HOLD_FORWARD not NLASTRIP_EXTEND_HOLD,
1094                          * so that it doesn't override strips in previous tracks
1095                          */
1096                         // FIXME: this needs to be more automated, since user can rearrange strips
1097                         strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD;
1098                 }
1099         }
1100 }
1101
1102
1103 /* Find the active strip + track combo, and set them up as the tweaking track,
1104  * and return if successful or not.
1105  */
1106 short BKE_nla_tweakmode_enter (AnimData *adt)
1107 {
1108         NlaTrack *nlt, *activeTrack=NULL;
1109         NlaStrip *strip, *activeStrip=NULL;
1110         
1111         /* verify that data is valid */
1112         if ELEM(NULL, adt, adt->nla_tracks.first)
1113                 return 0;
1114                 
1115         /* if block is already in tweakmode, just leave, but we should report 
1116          * that this block is in tweakmode (as our returncode)
1117          */
1118         if (adt->flag & ADT_NLA_EDIT_ON)
1119                 return 1;
1120                 
1121         /* go over the tracks, finding the active one, and its active strip
1122          *      - if we cannot find both, then there's nothing to do
1123          */
1124         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1125                 /* check if active */
1126                 if (nlt->flag & NLATRACK_ACTIVE) {
1127                         /* store reference to this active track */
1128                         activeTrack= nlt;
1129                         
1130                         /* now try to find active strip */
1131                         activeStrip= BKE_nlastrip_find_active(nlt);
1132                         break;
1133                 }       
1134         }
1135         if ELEM3(NULL, activeTrack, activeStrip, activeStrip->act) {
1136                 printf("NLA tweakmode enter - neither active requirement found \n");
1137                 return 0;
1138         }
1139                 
1140         /* go over all the tracks up to the active one, tagging each strip that uses the same 
1141          * action as the active strip, but leaving everything else alone
1142          */
1143         for (nlt= activeTrack->prev; nlt; nlt= nlt->prev) {
1144                 for (strip= nlt->strips.first; strip; strip= strip->next) {
1145                         if (strip->act == activeStrip->act)
1146                                 strip->flag |= NLASTRIP_FLAG_TWEAKUSER;
1147                         else
1148                                 strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
1149                 }
1150         }
1151         
1152         
1153         /* go over all the tracks after AND INCLUDING the active one, tagging them as being disabled 
1154          *      - the active track needs to also be tagged, otherwise, it'll overlap with the tweaks going on
1155          */
1156         for (nlt= activeTrack; nlt; nlt= nlt->next)
1157                 nlt->flag |= NLATRACK_DISABLED;
1158         
1159         /* handle AnimData level changes:
1160          *      - 'real' active action to temp storage (no need to change user-counts)
1161          *      - action of active strip set to be the 'active action', and have its usercount incremented
1162          *      - editing-flag for this AnimData block should also get turned on (for more efficient restoring)
1163          *      - take note of the active strip for mapping-correction of keyframes in the action being edited
1164          */
1165         adt->tmpact= adt->action;
1166         adt->action= activeStrip->act;
1167         adt->actstrip= activeStrip;
1168         id_us_plus(&activeStrip->act->id);
1169         adt->flag |= ADT_NLA_EDIT_ON;
1170         
1171         /* done! */
1172         return 1;
1173 }
1174
1175 /* Exit tweakmode for this AnimData block */
1176 void BKE_nla_tweakmode_exit (AnimData *adt)
1177 {
1178         NlaStrip *strip;
1179         NlaTrack *nlt;
1180         
1181         /* verify that data is valid */
1182         if ELEM(NULL, adt, adt->nla_tracks.first)
1183                 return;
1184                 
1185         /* hopefully the flag is correct - skip if not on */
1186         if ((adt->flag & ADT_NLA_EDIT_ON) == 0)
1187                 return;
1188                 
1189         // TODO: need to sync the user-strip with the new state of the action!
1190                 
1191         /* for all Tracks, clear the 'disabled' flag
1192          * for all Strips, clear the 'tweak-user' flag
1193          */
1194         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1195                 nlt->flag &= ~NLATRACK_DISABLED;
1196                 
1197                 for (strip= nlt->strips.first; strip; strip= strip->next) 
1198                         strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
1199         }
1200         
1201         /* handle AnimData level changes:
1202          *      - 'temporary' active action needs its usercount decreased, since we're removing this reference
1203          *      - 'real' active action is restored from storage
1204          *      - storage pointer gets cleared (to avoid having bad notes hanging around)
1205          *      - editing-flag for this AnimData block should also get turned off
1206          *      - clear pointer to active strip
1207          */
1208         if (adt->action) adt->action->id.us--;
1209         adt->action= adt->tmpact;
1210         adt->tmpact= NULL;
1211         adt->actstrip= NULL;
1212         adt->flag &= ~ADT_NLA_EDIT_ON;
1213 }
1214
1215 /* *************************************************** */