Merge branch 'master' into blender2.8
[blender.git] / source / blender / blenkernel / intern / nla.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Joshua Leung (full recode)
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/nla.c
29  *  \ingroup bke
30  */
31
32
33 #include <stdlib.h>
34 #include <stddef.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <math.h>
38 #include <float.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "BLI_utildefines.h"
43 #include "BLI_listbase.h"
44 #include "BLI_string.h"
45 #include "BLI_string_utils.h"
46 #include "BLI_ghash.h"
47
48 #include "BLT_translation.h"
49
50 #include "DNA_anim_types.h"
51 #include "DNA_scene_types.h"
52 #include "DNA_sound_types.h"
53 #include "DNA_speaker_types.h"
54
55 #include "BKE_action.h"
56 #include "BKE_fcurve.h"
57 #include "BKE_nla.h"
58 #include "BKE_global.h"
59 #include "BKE_library.h"
60
61 #ifdef WITH_AUDASPACE
62 #  include <AUD_Special.h>
63 #endif
64
65 #include "RNA_access.h"
66 #include "nla_private.h"
67
68
69
70 /* *************************************************** */
71 /* Data Management */
72
73 /* Freeing ------------------------------------------- */
74
75 /* Remove the given NLA strip from the NLA track it occupies, free the strip's data,
76  * and the strip itself. 
77  */
78 void BKE_nlastrip_free(ListBase *strips, NlaStrip *strip)
79 {
80         NlaStrip *cs, *csn;
81         
82         /* sanity checks */
83         if (strip == NULL)
84                 return;
85                 
86         /* free child-strips */
87         for (cs = strip->strips.first; cs; cs = csn) {
88                 csn = cs->next;
89                 BKE_nlastrip_free(&strip->strips, cs);
90         }
91                 
92         /* remove reference to action */
93         if (strip->act)
94                 id_us_min(&strip->act->id);
95                 
96         /* free remapping info */
97         //if (strip->remap)
98         //      BKE_animremap_free();
99         
100         /* free own F-Curves */
101         free_fcurves(&strip->fcurves);
102         
103         /* free own F-Modifiers */
104         free_fmodifiers(&strip->modifiers);
105         
106         /* free the strip itself */
107         if (strips)
108                 BLI_freelinkN(strips, strip);
109         else
110                 MEM_freeN(strip);
111 }
112
113 /* Remove the given NLA track from the set of NLA tracks, free the track's data,
114  * and the track itself.
115  */
116 void BKE_nlatrack_free(ListBase *tracks, NlaTrack *nlt)
117 {
118         NlaStrip *strip, *stripn;
119         
120         /* sanity checks */
121         if (nlt == NULL)
122                 return;
123                 
124         /* free strips */
125         for (strip = nlt->strips.first; strip; strip = stripn) {
126                 stripn = strip->next;
127                 BKE_nlastrip_free(&nlt->strips, strip);
128         }
129         
130         /* free NLA track itself now */
131         if (tracks)
132                 BLI_freelinkN(tracks, nlt);
133         else
134                 MEM_freeN(nlt);
135 }
136
137 /* Free the elements of type NLA Tracks provided in the given list, but do not free
138  * the list itself since that is not free-standing
139  */
140 void BKE_nla_tracks_free(ListBase *tracks)
141 {
142         NlaTrack *nlt, *nltn;
143         
144         /* sanity checks */
145         if (ELEM(NULL, tracks, tracks->first))
146                 return;
147                 
148         /* free tracks one by one */
149         for (nlt = tracks->first; nlt; nlt = nltn) {
150                 nltn = nlt->next;
151                 BKE_nlatrack_free(tracks, nlt);
152         }
153         
154         /* clear the list's pointers to be safe */
155         BLI_listbase_clear(tracks);
156 }
157
158 /* Copying ------------------------------------------- */
159
160 /**
161  * Copy NLA strip
162  *
163  * \param use_same_action When true, the existing action is used (instead of being duplicated)
164  */
165 NlaStrip *BKE_nlastrip_copy(NlaStrip *strip, const bool use_same_action)
166 {
167         NlaStrip *strip_d;
168         NlaStrip *cs, *cs_d;
169         
170         /* sanity check */
171         if (strip == NULL)
172                 return NULL;
173                 
174         /* make a copy */
175         strip_d = MEM_dupallocN(strip);
176         strip_d->next = strip_d->prev = NULL;
177         
178         /* handle action */
179         if (strip_d->act) {
180                 if (use_same_action) {
181                         /* increase user-count of action */
182                         id_us_plus(&strip_d->act->id);
183                 }
184                 else {
185                         /* use a copy of the action instead (user count shouldn't have changed yet) */
186                         strip_d->act = BKE_action_copy(G.main, strip_d->act);
187                 }
188         }
189                 
190         /* copy F-Curves and modifiers */
191         copy_fcurves(&strip_d->fcurves, &strip->fcurves);
192         copy_fmodifiers(&strip_d->modifiers, &strip->modifiers);
193         
194         /* make a copy of all the child-strips, one at a time */
195         BLI_listbase_clear(&strip_d->strips);
196         
197         for (cs = strip->strips.first; cs; cs = cs->next) {
198                 cs_d = BKE_nlastrip_copy(cs, use_same_action);
199                 BLI_addtail(&strip_d->strips, cs_d);
200         }
201         
202         /* return the strip */
203         return strip_d;
204 }
205
206 /* Copy NLA Track */
207 NlaTrack *BKE_nlatrack_copy(NlaTrack *nlt, const bool use_same_actions)
208 {
209         NlaStrip *strip, *strip_d;
210         NlaTrack *nlt_d;
211         
212         /* sanity check */
213         if (nlt == NULL)
214                 return NULL;
215                 
216         /* make a copy */
217         nlt_d = MEM_dupallocN(nlt);
218         nlt_d->next = nlt_d->prev = NULL;
219         
220         /* make a copy of all the strips, one at a time */
221         BLI_listbase_clear(&nlt_d->strips);
222         
223         for (strip = nlt->strips.first; strip; strip = strip->next) {
224                 strip_d = BKE_nlastrip_copy(strip, use_same_actions);
225                 BLI_addtail(&nlt_d->strips, strip_d);
226         }
227         
228         /* return the copy */
229         return nlt_d;
230 }
231
232 /* Copy all NLA data */
233 void BKE_nla_tracks_copy(ListBase *dst, ListBase *src)
234 {
235         NlaTrack *nlt, *nlt_d;
236         
237         /* sanity checks */
238         if (ELEM(NULL, dst, src))
239                 return;
240                 
241         /* clear out the destination list first for precautions... */
242         BLI_listbase_clear(dst);
243                 
244         /* copy each NLA-track, one at a time */
245         for (nlt = src->first; nlt; nlt = nlt->next) {
246                 /* make a copy, and add the copy to the destination list */
247                 // XXX: we need to fix this sometime
248                 nlt_d = BKE_nlatrack_copy(nlt, true);
249                 BLI_addtail(dst, nlt_d);
250         }
251 }
252
253 /* Adding ------------------------------------------- */
254
255 /* Add a NLA Track to the given AnimData 
256  *      - prev: NLA-Track to add the new one after
257  */
258 NlaTrack *BKE_nlatrack_add(AnimData *adt, NlaTrack *prev)
259 {
260         NlaTrack *nlt;
261         
262         /* sanity checks */
263         if (adt == NULL)
264                 return NULL;
265                 
266         /* allocate new track */
267         nlt = MEM_callocN(sizeof(NlaTrack), "NlaTrack");
268         
269         /* set settings requiring the track to not be part of the stack yet */
270         nlt->flag = NLATRACK_SELECTED;
271         nlt->index = BLI_listbase_count(&adt->nla_tracks);
272         
273         /* add track to stack, and make it the active one */
274         if (prev)
275                 BLI_insertlinkafter(&adt->nla_tracks, prev, nlt);
276         else
277                 BLI_addtail(&adt->nla_tracks, nlt);
278         BKE_nlatrack_set_active(&adt->nla_tracks, nlt);
279         
280         /* must have unique name, but we need to seed this */
281         strcpy(nlt->name, "NlaTrack");
282         BLI_uniquename(&adt->nla_tracks, nlt, DATA_("NlaTrack"), '.', offsetof(NlaTrack, name), sizeof(nlt->name));
283         
284         /* return the new track */
285         return nlt;
286 }
287
288 /* Create a NLA Strip referencing the given Action */
289 NlaStrip *BKE_nlastrip_new(bAction *act)
290 {
291         NlaStrip *strip;
292         
293         /* sanity checks */
294         if (act == NULL)
295                 return NULL;
296                 
297         /* allocate new strip */
298         strip = MEM_callocN(sizeof(NlaStrip), "NlaStrip");
299         
300         /* generic settings 
301          *      - selected flag to highlight this to the user
302          *      - (XXX) disabled Auto-Blends, as this was often causing some unwanted effects
303          *      - (XXX) synchronization of strip-length in accordance with changes to action-length
304          *        is not done though, since this should only really happens in editmode for strips now
305          *        though this decision is still subject to further review...
306          */
307         strip->flag = NLASTRIP_FLAG_SELECT;
308         
309         /* assign the action reference */
310         strip->act = act;
311         id_us_plus(&act->id);
312         
313         /* determine initial range 
314          *      - strip length cannot be 0... ever...
315          */
316         calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
317         
318         strip->start = strip->actstart;
319         strip->end = (IS_EQF(strip->actstart, strip->actend)) ?  (strip->actstart + 1.0f) : (strip->actend);
320         
321         /* strip should be referenced as-is */
322         strip->scale = 1.0f;
323         strip->repeat = 1.0f;
324         
325         /* return the new strip */
326         return strip;
327 }
328
329 /* Add new NLA-strip to the top of the NLA stack - i.e. into the last track if space, or a new one otherwise */
330 NlaStrip *BKE_nlastack_add_strip(AnimData *adt, bAction *act)
331 {
332         NlaStrip *strip;
333         NlaTrack *nlt;
334         
335         /* sanity checks */
336         if (ELEM(NULL, adt, act))
337                 return NULL;
338         
339         /* create a new NLA strip */
340         strip = BKE_nlastrip_new(act);
341         if (strip == NULL)
342                 return NULL;
343         
344         /* firstly try adding strip to last track, but if that fails, add to a new track */
345         if (BKE_nlatrack_add_strip(adt->nla_tracks.last, strip) == 0) {
346                 /* trying to add to the last track failed (no track or no space), 
347                  * so add a new track to the stack, and add to that...
348                  */
349                 nlt = BKE_nlatrack_add(adt, NULL);
350                 BKE_nlatrack_add_strip(nlt, strip);
351         }
352         
353         /* automatically name it too */
354         BKE_nlastrip_validate_name(adt, strip);
355         
356         /* returns the strip added */
357         return strip;
358 }
359
360 /* Add a NLA Strip referencing the given speaker's sound */
361 NlaStrip *BKE_nla_add_soundstrip(Scene *scene, Speaker *speaker)
362 {
363         NlaStrip *strip = MEM_callocN(sizeof(NlaStrip), "NlaSoundStrip");
364         
365         /* if speaker has a sound, set the strip length to the length of the sound,
366          * otherwise default to length of 10 frames
367          */
368 #ifdef WITH_AUDASPACE
369         if (speaker->sound) {
370                 AUD_SoundInfo info = AUD_getInfo(speaker->sound->playback_handle);
371                 
372                 strip->end = (float)ceil((double)info.length * FPS);
373         }
374         else
375 #endif
376         {
377                 strip->end = 10.0f;
378                 /* quiet compiler warnings */
379                 (void)scene;
380                 (void)speaker;
381         }
382         
383         /* general settings */
384         strip->type = NLASTRIP_TYPE_SOUND;
385         
386         strip->flag = NLASTRIP_FLAG_SELECT;
387         strip->extendmode = NLASTRIP_EXTEND_NOTHING; /* nothing to extend... */
388         
389         /* strip should be referenced as-is */
390         strip->scale = 1.0f;
391         strip->repeat = 1.0f;
392         
393         /* return this strip */
394         return strip;
395 }
396
397 /* *************************************************** */
398 /* NLA Evaluation <-> Editing Stuff */
399
400 /* Strip Mapping ------------------------------------- */
401
402 /* non clipped mapping for strip-time <-> global time (for Action-Clips)
403  *      invert = convert action-strip time to global time 
404  */
405 static float nlastrip_get_frame_actionclip(NlaStrip *strip, float cframe, short mode)
406 {
407         float actlength, scale;
408         // float repeat; // UNUSED
409         
410         /* get number of repeats */
411         if (IS_EQF(strip->repeat, 0.0f)) strip->repeat = 1.0f;
412         // repeat = strip->repeat; // UNUSED
413         
414         /* scaling */
415         if (IS_EQF(strip->scale, 0.0f)) strip->scale = 1.0f;
416         scale = fabsf(strip->scale); /* scale must be positive - we've got a special flag for reversing */
417         
418         /* length of referenced action */
419         actlength = strip->actend - strip->actstart;
420         if (IS_EQF(actlength, 0.0f)) actlength = 1.0f;
421         
422         /* reversed = play strip backwards */
423         if (strip->flag & NLASTRIP_FLAG_REVERSE) {
424                 /* FIXME: this won't work right with Graph Editor? */
425                 if (mode == NLATIME_CONVERT_MAP) {
426                         return strip->end - scale * (cframe - strip->actstart);
427                 }
428                 else if (mode == NLATIME_CONVERT_UNMAP) {
429                         return (strip->end + (strip->actstart * scale - cframe)) / scale;
430                 }
431                 else { /* if (mode == NLATIME_CONVERT_EVAL) */
432                         if (IS_EQF((float)cframe, strip->end) && IS_EQF(strip->repeat, floorf(strip->repeat))) {
433                                 /* this case prevents the motion snapping back to the first frame at the end of the strip 
434                                  * by catching the case where repeats is a whole number, which means that the end of the strip
435                                  * could also be interpreted as the end of the start of a repeat
436                                  */
437                                 return strip->actstart;
438                         }
439                         else {
440                                 /* - the 'fmod(..., actlength * scale)' is needed to get the repeats working
441                                  * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat
442                                  */
443                                 return strip->actend - fmodf(cframe - strip->start, actlength * scale) / scale;
444                         }
445                 }
446         }
447         else {
448                 if (mode == NLATIME_CONVERT_MAP) {
449                         return strip->start + scale * (cframe - strip->actstart);
450                 }
451                 else if (mode == NLATIME_CONVERT_UNMAP) {
452                         return strip->actstart + (cframe - strip->start) / scale;
453                 }
454                 else { /* if (mode == NLATIME_CONVERT_EVAL) */
455                         if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, floorf(strip->repeat))) {
456                                 /* this case prevents the motion snapping back to the first frame at the end of the strip 
457                                  * by catching the case where repeats is a whole number, which means that the end of the strip
458                                  * could also be interpreted as the end of the start of a repeat
459                                  */
460                                 return strip->actend;
461                         }
462                         else {
463                                 /* - the 'fmod(..., actlength * scale)' is needed to get the repeats working
464                                  * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat
465                                  */
466                                 return strip->actstart + fmodf(cframe - strip->start, actlength * scale) / scale;
467                         }
468                 }
469         }
470 }
471
472 /* non clipped mapping for strip-time <-> global time (for Transitions)
473  *      invert = convert action-strip time to global time 
474  */
475 static float nlastrip_get_frame_transition(NlaStrip *strip, float cframe, short mode)
476 {
477         float length;
478         
479         /* length of strip */
480         length = strip->end - strip->start;
481         
482         /* reversed = play strip backwards */
483         if (strip->flag & NLASTRIP_FLAG_REVERSE) {
484                 if (mode == NLATIME_CONVERT_MAP)
485                         return strip->end - (length * cframe);
486                 else
487                         return (strip->end - cframe) / length;
488         }
489         else {
490                 if (mode == NLATIME_CONVERT_MAP)
491                         return (length * cframe) + strip->start;
492                 else
493                         return (cframe - strip->start) / length;
494         }
495 }
496
497 /* non clipped mapping for strip-time <-> global time
498  *  mode = eNlaTime_ConvertModes[] -> NLATIME_CONVERT_*
499  *
500  * only secure for 'internal' (i.e. within AnimSys evaluation) operations,
501  * but should not be directly relied on for stuff which interacts with editors
502  */
503 float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode)
504 {
505         switch (strip->type) {
506                 case NLASTRIP_TYPE_META: /* meta - for now, does the same as transition (is really just an empty container) */
507                 case NLASTRIP_TYPE_TRANSITION: /* transition */
508                         return nlastrip_get_frame_transition(strip, cframe, mode);
509                 
510                 case NLASTRIP_TYPE_CLIP: /* action-clip (default) */
511                 default:
512                         return nlastrip_get_frame_actionclip(strip, cframe, mode);
513         }
514 }
515
516
517 /* Non clipped mapping for strip-time <-> global time
518  *      mode = eNlaTime_ConvertModes -> NLATIME_CONVERT_*
519  *
520  * Public API method - perform this mapping using the given AnimData block
521  * and perform any necessary sanity checks on the value
522  */
523 float BKE_nla_tweakedit_remap(AnimData *adt, float cframe, short mode)
524 {
525         NlaStrip *strip;
526         
527         /* sanity checks 
528          *      - obviously we've got to have some starting data
529          *      - when not in tweakmode, the active Action does not have any scaling applied :)
530          *      - when in tweakmode, if the no-mapping flag is set, do not map
531          */
532         if ((adt == NULL) || (adt->flag & ADT_NLA_EDIT_ON) == 0 || (adt->flag & ADT_NLA_EDIT_NOMAP))
533                 return cframe;
534                 
535         /* if the active-strip info has been stored already, access this, otherwise look this up
536          * and store for (very probable) future usage
537          */
538         if (adt->act_track == NULL) {
539                 if (adt->actstrip)
540                         adt->act_track = BKE_nlatrack_find_tweaked(adt);
541                 else
542                         adt->act_track = BKE_nlatrack_find_active(&adt->nla_tracks);
543         }
544         if (adt->actstrip == NULL) {
545                 adt->actstrip = BKE_nlastrip_find_active(adt->act_track);
546         }
547         strip = adt->actstrip;
548         
549         /* sanity checks 
550          *      - in rare cases, we may not be able to find this strip for some reason (internal error)
551          *      - for now, if the user has defined a curve to control the time, this correction cannot be performed
552          *        reliably...
553          */
554         if ((strip == NULL) || (strip->flag & NLASTRIP_FLAG_USR_TIME))
555                 return cframe;
556                 
557         /* perform the correction now... */
558         return nlastrip_get_frame(strip, cframe, mode);
559 }
560
561 /* *************************************************** */
562 /* NLA API */
563
564 /* List of Strips ------------------------------------ */
565 /* (these functions are used for NLA-Tracks and also for nested/meta-strips) */
566
567 /* Check if there is any space in the given list to add the given strip */
568 bool BKE_nlastrips_has_space(ListBase *strips, float start, float end)
569 {
570         NlaStrip *strip;
571         
572         /* sanity checks */
573         if ((strips == NULL) || IS_EQF(start, end))
574                 return false;
575         if (start > end) {
576                 puts("BKE_nlastrips_has_space() error... start and end arguments swapped");
577                 SWAP(float, start, end);
578         }
579         
580         /* loop over NLA strips checking for any overlaps with this area... */
581         for (strip = strips->first; strip; strip = strip->next) {
582                 /* if start frame of strip is past the target end-frame, that means that
583                  * we've gone past the window we need to check for, so things are fine
584                  */
585                 if (strip->start >= end)
586                         return true;
587                 
588                 /* if the end of the strip is greater than either of the boundaries, the range
589                  * must fall within the extents of the strip
590                  */
591                 if ((strip->end > start) || (strip->end > end))
592                         return false;
593         }
594         
595         /* if we are still here, we haven't encountered any overlapping strips */
596         return true;
597 }
598
599 /* Rearrange the strips in the track so that they are always in order 
600  * (usually only needed after a strip has been moved) 
601  */
602 void BKE_nlastrips_sort_strips(ListBase *strips)
603 {
604         ListBase tmp = {NULL, NULL};
605         NlaStrip *strip, *sstrip, *stripn;
606         
607         /* sanity checks */
608         if (ELEM(NULL, strips, strips->first))
609                 return;
610         
611         /* we simply perform insertion sort on this list, since it is assumed that per track,
612          * there are only likely to be at most 5-10 strips
613          */
614         for (strip = strips->first; strip; strip = stripn) {
615                 short not_added = 1;
616                 
617                 stripn = strip->next;
618                 
619                 /* remove this strip from the list, and add it to the new list, searching from the end of 
620                  * the list, assuming that the lists are in order 
621                  */
622                 BLI_remlink(strips, strip);
623                 
624                 for (sstrip = tmp.last; sstrip; sstrip = sstrip->prev) {
625                         /* check if add after */
626                         if (sstrip->end <= strip->start) {
627                                 BLI_insertlinkafter(&tmp, sstrip, strip);
628                                 not_added = 0;
629                                 break;
630                         }
631                 }
632                 
633                 /* add before first? */
634                 if (not_added)
635                         BLI_addhead(&tmp, strip);
636         }
637         
638         /* reassign the start and end points of the strips */
639         strips->first = tmp.first;
640         strips->last = tmp.last;
641 }
642
643 /* Add the given NLA-Strip to the given list of strips, assuming that it 
644  * isn't currently a member of another list
645  */
646 bool BKE_nlastrips_add_strip(ListBase *strips, NlaStrip *strip)
647 {
648         NlaStrip *ns;
649         bool not_added = true;
650         
651         /* sanity checks */
652         if (ELEM(NULL, strips, strip))
653                 return false;
654                 
655         /* check if any space to add */
656         if (BKE_nlastrips_has_space(strips, strip->start, strip->end) == 0)
657                 return false;
658         
659         /* find the right place to add the strip to the nominated track */
660         for (ns = strips->first; ns; ns = ns->next) {
661                 /* if current strip occurs after the new strip, add it before */
662                 if (ns->start >= strip->end) {
663                         BLI_insertlinkbefore(strips, ns, strip);
664                         not_added = 0;
665                         break;
666                 }
667         }
668         if (not_added) {
669                 /* just add to the end of the list of the strips then... */
670                 BLI_addtail(strips, strip);
671         }
672         
673         /* added... */
674         return true;
675 }
676
677
678 /* Meta-Strips ------------------------------------ */
679
680 /* Convert 'islands' (i.e. continuous string of) selected strips to be
681  * contained within 'Meta-Strips' which act as strips which contain strips.
682  *      temp: are the meta-strips to be created 'temporary' ones used for transforms?
683  */
684 void BKE_nlastrips_make_metas(ListBase *strips, bool is_temp)
685 {
686         NlaStrip *mstrip = NULL;
687         NlaStrip *strip, *stripn;
688         
689         /* sanity checks */
690         if (ELEM(NULL, strips, strips->first))
691                 return;
692         
693         /* group all continuous chains of selected strips into meta-strips */
694         for (strip = strips->first; strip; strip = stripn) {
695                 stripn = strip->next;
696                 
697                 if (strip->flag & NLASTRIP_FLAG_SELECT) {
698                         /* if there is an existing meta-strip, add this strip to it, otherwise, create a new one */
699                         if (mstrip == NULL) {
700                                 /* add a new meta-strip, and add it before the current strip that it will replace... */
701                                 mstrip = MEM_callocN(sizeof(NlaStrip), "Meta-NlaStrip");
702                                 mstrip->type = NLASTRIP_TYPE_META;
703                                 BLI_insertlinkbefore(strips, strip, mstrip);
704                                 
705                                 /* set flags */
706                                 mstrip->flag = NLASTRIP_FLAG_SELECT;
707                                 
708                                 /* set temp flag if appropriate (i.e. for transform-type editing) */
709                                 if (is_temp)
710                                         mstrip->flag |= NLASTRIP_FLAG_TEMP_META;
711                                         
712                                 /* set default repeat/scale values to prevent warnings */
713                                 mstrip->repeat = mstrip->scale = 1.0f;
714                                 
715                                 /* make its start frame be set to the start frame of the current strip */
716                                 mstrip->start = strip->start;
717                         }
718                         
719                         /* remove the selected strips from the track, and add to the meta */
720                         BLI_remlink(strips, strip);
721                         BLI_addtail(&mstrip->strips, strip);
722                         
723                         /* expand the meta's dimensions to include the newly added strip- i.e. its last frame */
724                         mstrip->end = strip->end;
725                 }
726                 else {
727                         /* current strip wasn't selected, so the end of 'island' of selected strips has been reached,
728                          * so stop adding strips to the current meta
729                          */
730                         mstrip = NULL;
731                 }
732         }
733 }
734
735 /* Split a meta-strip into a set of normal strips */
736 void BKE_nlastrips_clear_metastrip(ListBase *strips, NlaStrip *strip)
737 {
738         NlaStrip *cs, *csn;
739         
740         /* sanity check */
741         if (ELEM(NULL, strips, strip))
742                 return;
743         
744         /* move each one of the meta-strip's children before the meta-strip
745          * in the list of strips after unlinking them from the meta-strip
746          */
747         for (cs = strip->strips.first; cs; cs = csn) {
748                 csn = cs->next;
749                 BLI_remlink(&strip->strips, cs);
750                 BLI_insertlinkbefore(strips, strip, cs);
751         }
752         
753         /* free the meta-strip now */
754         BKE_nlastrip_free(strips, strip);
755 }
756
757 /* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips
758  *      sel: only consider selected meta-strips, otherwise all meta-strips are removed
759  *      onlyTemp: only remove the 'temporary' meta-strips used for transforms
760  */
761 void BKE_nlastrips_clear_metas(ListBase *strips, bool only_sel, bool only_temp)
762 {
763         NlaStrip *strip, *stripn;
764         
765         /* sanity checks */
766         if (ELEM(NULL, strips, strips->first))
767                 return;
768         
769         /* remove meta-strips fitting the criteria of the arguments */
770         for (strip = strips->first; strip; strip = stripn) {
771                 stripn = strip->next;
772                 
773                 /* check if strip is a meta-strip */
774                 if (strip->type == NLASTRIP_TYPE_META) {
775                         /* if check if selection and 'temporary-only' considerations are met */
776                         if ((!only_sel) || (strip->flag & NLASTRIP_FLAG_SELECT)) {
777                                 if ((!only_temp) || (strip->flag & NLASTRIP_FLAG_TEMP_META)) {
778                                         BKE_nlastrips_clear_metastrip(strips, strip);
779                                 }
780                         }
781                 }
782         }
783 }
784
785 /* Add the given NLA-Strip to the given Meta-Strip, assuming that the
786  * strip isn't attached to any list of strips
787  */
788 bool BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip)
789 {
790         /* sanity checks */
791         if (ELEM(NULL, mstrip, strip))
792                 return false;
793                 
794         /* firstly, check if the meta-strip has space for this */
795         if (BKE_nlastrips_has_space(&mstrip->strips, strip->start, strip->end) == 0)
796                 return false;
797                 
798         /* check if this would need to be added to the ends of the meta,
799          * and subsequently, if the neighboring strips allow us enough room
800          */
801         if (strip->start < mstrip->start) {
802                 /* check if strip to the left (if it exists) ends before the 
803                  * start of the strip we're trying to add 
804                  */
805                 if ((mstrip->prev == NULL) || (mstrip->prev->end <= strip->start)) {
806                         /* add strip to start of meta's list, and expand dimensions */
807                         BLI_addhead(&mstrip->strips, strip);
808                         mstrip->start = strip->start;
809                         
810                         return true;
811                 }
812                 else /* failed... no room before */
813                         return false;
814         }
815         else if (strip->end > mstrip->end) {
816                 /* check if strip to the right (if it exists) starts before the 
817                  * end of the strip we're trying to add 
818                  */
819                 if ((mstrip->next == NULL) || (mstrip->next->start >= strip->end)) {
820                         /* add strip to end of meta's list, and expand dimensions */
821                         BLI_addtail(&mstrip->strips, strip);
822                         mstrip->end = strip->end;
823                         
824                         return true;
825                 }
826                 else /* failed... no room after */
827                         return false;
828         }
829         else {
830                 /* just try to add to the meta-strip (no dimension changes needed) */
831                 return BKE_nlastrips_add_strip(&mstrip->strips, strip);
832         }
833 }
834
835 /* Adjust the settings of NLA-Strips contained within a Meta-Strip (recursively), 
836  * until the Meta-Strips children all fit within the Meta-Strip's new dimensions
837  */
838 void BKE_nlameta_flush_transforms(NlaStrip *mstrip)
839 {
840         NlaStrip *strip;
841         float oStart, oEnd, offset;
842         float oLen, nLen;
843         short scaleChanged = 0;
844         
845         /* sanity checks 
846          *      - strip must exist
847          *      - strip must be a meta-strip with some contents
848          */
849         if (ELEM(NULL, mstrip, mstrip->strips.first))
850                 return;
851         if (mstrip->type != NLASTRIP_TYPE_META)
852                 return;
853                 
854         /* get the original start/end points, and calculate the start-frame offset
855          *      - these are simply the start/end frames of the child strips, 
856          *        since we assume they weren't transformed yet
857          */
858         oStart = ((NlaStrip *)mstrip->strips.first)->start;
859         oEnd = ((NlaStrip *)mstrip->strips.last)->end;
860         offset = mstrip->start - oStart;
861         
862         /* optimization:
863          * don't flush if nothing changed yet
864          *      TODO: maybe we need a flag to say always flush?
865          */
866         if (IS_EQF(oStart, mstrip->start) && IS_EQF(oEnd, mstrip->end))
867                 return;
868         
869         /* check if scale changed */
870         oLen = oEnd - oStart;
871         nLen = mstrip->end - mstrip->start;
872         if (IS_EQF(nLen, oLen) == 0)
873                 scaleChanged = 1;
874         
875         /* for each child-strip, calculate new start/end points based on this new info */
876         for (strip = mstrip->strips.first; strip; strip = strip->next) {
877                 if (scaleChanged) {
878                         float p1, p2;
879                         
880                         /* compute positions of endpoints relative to old extents of strip */
881                         p1 = (strip->start - oStart) / oLen;
882                         p2 = (strip->end - oStart) / oLen;
883                         
884                         /* apply new strip endpoints using the proportions, then wait for second pass to flush scale properly */
885                         strip->start = (p1 * nLen) + mstrip->start;
886                         strip->end = (p2 * nLen) + mstrip->start;
887                 }
888                 else {
889                         /* just apply the changes in offset to both ends of the strip */
890                         strip->start += offset;
891                         strip->end += offset;
892                 }
893         }
894                 
895         /* apply a second pass over child strips, to finish up unfinished business */
896         for (strip = mstrip->strips.first; strip; strip = strip->next) {
897                 /* only if scale changed, need to perform RNA updates */
898                 if (scaleChanged) {
899                         PointerRNA ptr;
900                         
901                         /* use RNA updates to compute scale properly */
902                         RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &ptr);
903                         
904                         RNA_float_set(&ptr, "frame_start", strip->start);
905                         RNA_float_set(&ptr, "frame_end", strip->end);
906                 }
907                 
908                 /* finally, make sure the strip's children (if it is a meta-itself), get updated */
909                 BKE_nlameta_flush_transforms(strip);
910         }
911 }
912
913 /* NLA-Tracks ---------------------------------------- */
914
915 /* Find the active NLA-track for the given stack */
916 NlaTrack *BKE_nlatrack_find_active(ListBase *tracks)
917 {
918         NlaTrack *nlt;
919         
920         /* sanity check */
921         if (ELEM(NULL, tracks, tracks->first))
922                 return NULL;
923                 
924         /* try to find the first active track */
925         for (nlt = tracks->first; nlt; nlt = nlt->next) {
926                 if (nlt->flag & NLATRACK_ACTIVE)
927                         return nlt;
928         }
929         
930         /* none found */
931         return NULL;
932 }
933
934 /* Get the NLA Track that the active action/action strip comes from,
935  * since this info is not stored in AnimData. It also isn't as simple
936  * as just using the active track, since multiple tracks may have been
937  * entered at the same time.
938  */
939 NlaTrack *BKE_nlatrack_find_tweaked(AnimData *adt)
940 {
941         NlaTrack *nlt;
942         
943         /* sanity check */
944         if (adt == NULL)
945                 return NULL;
946         
947         /* Since the track itself gets disabled, we want the first disabled... */
948         for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
949                 if (nlt->flag & (NLATRACK_ACTIVE | NLATRACK_DISABLED)) {
950                         /* For good measure, make sure that strip actually exists there */
951                         if (BLI_findindex(&nlt->strips, adt->actstrip) != -1) {
952                                 return nlt;
953                         }
954                         else if (G.debug & G_DEBUG) {
955                                 printf("%s: Active strip (%p, %s) not in NLA track found (%p, %s)\n",
956                                        __func__, 
957                                        adt->actstrip, (adt->actstrip) ? adt->actstrip->name : "<None>",
958                                        nlt,           nlt->name);
959                         }
960                 }
961         }
962         
963         /* Not found! */
964         return NULL;
965 }
966
967 /* Toggle the 'solo' setting for the given NLA-track, making sure that it is the only one
968  * that has this status in its AnimData block.
969  */
970 void BKE_nlatrack_solo_toggle(AnimData *adt, NlaTrack *nlt)
971 {
972         NlaTrack *nt;
973         
974         /* sanity check */
975         if (ELEM(NULL, adt, adt->nla_tracks.first))
976                 return;
977                 
978         /* firstly, make sure 'solo' flag for all tracks is disabled */
979         for (nt = adt->nla_tracks.first; nt; nt = nt->next) {
980                 if (nt != nlt)
981                         nt->flag &= ~NLATRACK_SOLO;
982         }
983                 
984         /* now, enable 'solo' for the given track if appropriate */
985         if (nlt) {
986                 /* toggle solo status */
987                 nlt->flag ^= NLATRACK_SOLO;
988                 
989                 /* set or clear solo-status on AnimData */
990                 if (nlt->flag & NLATRACK_SOLO)
991                         adt->flag |= ADT_NLA_SOLO_TRACK;
992                 else
993                         adt->flag &= ~ADT_NLA_SOLO_TRACK;
994         }
995         else
996                 adt->flag &= ~ADT_NLA_SOLO_TRACK;
997 }
998
999 /* Make the given NLA-track the active one for the given stack. If no track is provided, 
1000  * this function can be used to simply deactivate all the NLA tracks in the given stack too.
1001  */
1002 void BKE_nlatrack_set_active(ListBase *tracks, NlaTrack *nlt_a)
1003 {
1004         NlaTrack *nlt;
1005         
1006         /* sanity check */
1007         if (ELEM(NULL, tracks, tracks->first))
1008                 return;
1009         
1010         /* deactive all the rest */
1011         for (nlt = tracks->first; nlt; nlt = nlt->next)
1012                 nlt->flag &= ~NLATRACK_ACTIVE;
1013                 
1014         /* set the given one as the active one */
1015         if (nlt_a)
1016                 nlt_a->flag |= NLATRACK_ACTIVE;
1017 }
1018
1019 /* Check if there is any space in the given track to add a strip of the given length */
1020 bool BKE_nlatrack_has_space(NlaTrack *nlt, float start, float end)
1021 {
1022         /* sanity checks 
1023          *  - track must exist
1024          *  - track must be editable
1025          *  - bounds cannot be equal (0-length is nasty)
1026          */
1027         if ((nlt == NULL) || (nlt->flag & NLATRACK_PROTECTED) || IS_EQF(start, end))
1028                 return false;
1029         
1030         if (start > end) {
1031                 puts("BKE_nlatrack_has_space() error... start and end arguments swapped");
1032                 SWAP(float, start, end);
1033         }
1034         
1035         /* check if there's any space left in the track for a strip of the given length */
1036         return BKE_nlastrips_has_space(&nlt->strips, start, end);
1037 }
1038
1039 /* Rearrange the strips in the track so that they are always in order 
1040  * (usually only needed after a strip has been moved) 
1041  */
1042 void BKE_nlatrack_sort_strips(NlaTrack *nlt)
1043 {
1044         /* sanity checks */
1045         if (ELEM(NULL, nlt, nlt->strips.first))
1046                 return;
1047         
1048         /* sort the strips with a more generic function */
1049         BKE_nlastrips_sort_strips(&nlt->strips);
1050 }
1051
1052 /* Add the given NLA-Strip to the given NLA-Track, assuming that it 
1053  * isn't currently attached to another one 
1054  */
1055 bool BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip)
1056 {
1057         /* sanity checks */
1058         if (ELEM(NULL, nlt, strip))
1059                 return false;
1060                 
1061         /* do not allow adding strips if this track is locked */
1062         if (nlt->flag & NLATRACK_PROTECTED)
1063                 return false;
1064         
1065         /* try to add the strip to the track using a more generic function */
1066         return BKE_nlastrips_add_strip(&nlt->strips, strip);
1067 }
1068
1069 /* Get the extents of the given NLA-Track including gaps between strips,
1070  * returning whether this succeeded or not
1071  */
1072 bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2])
1073 {
1074         NlaStrip *strip;
1075         
1076         /* initialize bounds */
1077         if (bounds)
1078                 bounds[0] = bounds[1] = 0.0f;
1079         else
1080                 return false;
1081         
1082         /* sanity checks */
1083         if (ELEM(NULL, nlt, nlt->strips.first))
1084                 return false;
1085                 
1086         /* lower bound is first strip's start frame */
1087         strip = nlt->strips.first;
1088         bounds[0] = strip->start;
1089         
1090         /* upper bound is last strip's end frame */
1091         strip = nlt->strips.last;
1092         bounds[1] = strip->end;
1093         
1094         /* done */
1095         return true;
1096 }
1097
1098 /* NLA Strips -------------------------------------- */
1099
1100 /* Find the active NLA-strip within the given track */
1101 NlaStrip *BKE_nlastrip_find_active(NlaTrack *nlt)
1102 {
1103         NlaStrip *strip;
1104         
1105         /* sanity check */
1106         if (ELEM(NULL, nlt, nlt->strips.first))
1107                 return NULL;
1108                 
1109         /* try to find the first active strip */
1110         for (strip = nlt->strips.first; strip; strip = strip->next) {
1111                 if (strip->flag & NLASTRIP_FLAG_ACTIVE)
1112                         return strip;
1113         }
1114         
1115         /* none found */
1116         return NULL;
1117 }
1118
1119 /* Make the given NLA-Strip the active one within the given block */
1120 void BKE_nlastrip_set_active(AnimData *adt, NlaStrip *strip)
1121 {
1122         NlaTrack *nlt;
1123         NlaStrip *nls;
1124         
1125         /* sanity checks */
1126         if (adt == NULL)
1127                 return;
1128         
1129         /* loop over tracks, deactivating*/
1130         for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
1131                 for (nls = nlt->strips.first; nls; nls = nls->next) {
1132                         if (nls != strip)
1133                                 nls->flag &= ~NLASTRIP_FLAG_ACTIVE;
1134                         else
1135                                 nls->flag |= NLASTRIP_FLAG_ACTIVE;
1136                 }
1137         }
1138 }
1139
1140
1141 /* Does the given NLA-strip fall within the given bounds (times)? */
1142 bool BKE_nlastrip_within_bounds(NlaStrip *strip, float min, float max)
1143 {
1144         const float stripLen = (strip) ? strip->end - strip->start : 0.0f;
1145         const float boundsLen = fabsf(max - min);
1146         
1147         /* sanity checks */
1148         if ((strip == NULL) || IS_EQF(stripLen, 0.0f) || IS_EQF(boundsLen, 0.0f))
1149                 return false;
1150         
1151         /* only ok if at least part of the strip is within the bounding window
1152          *      - first 2 cases cover when the strip length is less than the bounding area
1153          *      - second 2 cases cover when the strip length is greater than the bounding area
1154          */
1155         if ((stripLen < boundsLen) &&
1156             !(IN_RANGE(strip->start, min, max) ||
1157               IN_RANGE(strip->end, min, max)))
1158         {
1159                 return false;
1160         }
1161         if ((stripLen > boundsLen) &&
1162             !(IN_RANGE(min, strip->start, strip->end) ||
1163               IN_RANGE(max, strip->start, strip->end)) )
1164         {
1165                 return false;
1166         }
1167         
1168         /* should be ok! */
1169         return true;
1170 }
1171
1172
1173 /* Ensure that strip doesn't overlap those around it after resizing by offsetting those which follow */
1174 static void nlastrip_fix_resize_overlaps(NlaStrip *strip)
1175 {
1176         /* next strips - do this first, since we're often just getting longer */
1177         if (strip->next) {
1178                 NlaStrip *nls = strip->next;
1179                 float offset = 0.0f;
1180                 
1181                 if (nls->type == NLASTRIP_TYPE_TRANSITION) {
1182                         /* transition strips should grow/shrink to accomodate the resized strip,
1183                          * but if the strip's bounds now exceed the transition, we're forced to
1184                          * offset everything to maintain the balance
1185                          */
1186                         if (strip->end <= nls->start) {
1187                                 /* grow the transition to fill the void */
1188                                 nls->start = strip->end;
1189                         }
1190                         else if (strip->end < nls->end) {
1191                                 /* shrink the transition to give the strip room */
1192                                 nls->start = strip->end;
1193                         }
1194                         else {
1195                                 /* shrink transition down to 1 frame long (so that it can still be found),
1196                                  * then offset everything else by the remaining defict to give the strip room
1197                                  */
1198                                 nls->start = nls->end - 1.0f;
1199                                 offset     = ceilf(strip->end - nls->start);  /* XXX: review whether preventing fractionals is good here... */
1200                                 
1201                                 /* apply necessary offset to ensure that the strip has enough space */
1202                                 for (; nls; nls = nls->next) {
1203                                         nls->start += offset;
1204                                         nls->end   += offset;
1205                                 }
1206                         }
1207                 }
1208                 else if (strip->end > nls->start) {
1209                         /* NOTE: need to ensure we don't have a fractional frame offset, even if that leaves a gap,
1210                          * otherwise it will be very hard to get rid of later
1211                          */
1212                         offset = ceilf(strip->end - nls->start);
1213                         
1214                         /* apply to times of all strips in this direction */
1215                         for (; nls; nls = nls->next) {
1216                                 nls->start += offset;
1217                                 nls->end   += offset;
1218                         }
1219                 }
1220         }
1221         
1222         /* previous strips - same routine as before */
1223         /* NOTE: when strip bounds are recalculated, this is not considered! */
1224         if (strip->prev) {
1225                 NlaStrip *nls = strip->prev;
1226                 float offset = 0.0f;
1227                 
1228                 if (nls->type == NLASTRIP_TYPE_TRANSITION) {
1229                         /* transition strips should grow/shrink to accomodate the resized strip,
1230                          * but if the strip's bounds now exceed the transition, we're forced to
1231                          * offset everything to maintain the balance
1232                          */
1233                         if (strip->start >= nls->end) {
1234                                 /* grow the transition to fill the void */
1235                                 nls->end = strip->start;
1236                         }
1237                         else if (strip->start > nls->start) {
1238                                 /* shrink the transition to give the strip room */
1239                                 nls->end = strip->start;
1240                         }
1241                         else {
1242                                 /* shrink transition down to 1 frame long (so that it can still be found),
1243                                  * then offset everything else by the remaining defict to give the strip room
1244                                  */
1245                                 nls->end = nls->start + 1.0f;
1246                                 offset   = ceilf(nls->end - strip->start);  /* XXX: review whether preventing fractionals is good here... */
1247                                 
1248                                 /* apply necessary offset to ensure that the strip has enough space */
1249                                 for (; nls; nls = nls->next) {
1250                                         nls->start -= offset;
1251                                         nls->end   -= offset;
1252                                 }
1253                         }
1254                 }
1255                 else if (strip->start < nls->end) {
1256                         /* NOTE: need to ensure we don't have a fractional frame offset, even if that leaves a gap,
1257                          * otherwise it will be very hard to get rid of later
1258                          */
1259                         offset = ceilf(nls->end - strip->start);
1260                         
1261                         /* apply to times of all strips in this direction */
1262                         for (; nls; nls = nls->prev) {
1263                                 nls->start -= offset;
1264                                 nls->end   -= offset;
1265                         }
1266                 }
1267         }
1268 }
1269
1270 /* Recalculate the start and end frames for the current strip, after changing
1271  * the extents of the action or the mapping (repeats or scale factor) info
1272  */
1273 void BKE_nlastrip_recalculate_bounds(NlaStrip *strip)
1274 {
1275         float actlen, mapping;
1276         
1277         /* sanity checks
1278          *      - must have a strip
1279          *      - can only be done for action clips
1280          */
1281         if ((strip == NULL) || (strip->type != NLASTRIP_TYPE_CLIP))
1282                 return;
1283                 
1284         /* calculate new length factors */
1285         actlen = strip->actend - strip->actstart;
1286         if (IS_EQF(actlen, 0.0f)) actlen = 1.0f;
1287         
1288         mapping = strip->scale * strip->repeat;
1289         
1290         /* adjust endpoint of strip in response to this */
1291         if (IS_EQF(mapping, 0.0f) == 0)
1292                 strip->end = (actlen * mapping) + strip->start;
1293         
1294         /* make sure we don't overlap our neighbors */
1295         nlastrip_fix_resize_overlaps(strip);
1296 }
1297
1298 /* Is the given NLA-strip the first one to occur for the given AnimData block */
1299 // TODO: make this an api method if necesary, but need to add prefix first
1300 static bool nlastrip_is_first(AnimData *adt, NlaStrip *strip)
1301 {
1302         NlaTrack *nlt;
1303         NlaStrip *ns;
1304         
1305         /* sanity checks */
1306         if (ELEM(NULL, adt, strip))
1307                 return false;
1308                 
1309         /* check if strip has any strips before it */
1310         if (strip->prev)
1311                 return false;
1312                 
1313         /* check other tracks to see if they have a strip that's earlier */
1314         /* TODO: or should we check that the strip's track is also the first? */
1315         for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
1316                 /* only check the first strip, assuming that they're all in order */
1317                 ns = nlt->strips.first;
1318                 if (ns) {
1319                         if (ns->start < strip->start)
1320                                 return false;
1321                 }
1322         }
1323         
1324         /* should be first now */
1325         return true;
1326 }
1327
1328 /* Animated Strips ------------------------------------------- */
1329
1330 /* Check if the given NLA-Track has any strips with own F-Curves */
1331 bool BKE_nlatrack_has_animated_strips(NlaTrack *nlt)
1332 {
1333         NlaStrip *strip;
1334         
1335         /* sanity checks */
1336         if (ELEM(NULL, nlt, nlt->strips.first))
1337                 return false;
1338                 
1339         /* check each strip for F-Curves only (don't care about whether the flags are set) */
1340         for (strip = nlt->strips.first; strip; strip = strip->next) {
1341                 if (strip->fcurves.first)
1342                         return true;
1343         }
1344         
1345         /* none found */
1346         return false;
1347 }
1348
1349 /* Check if given NLA-Tracks have any strips with own F-Curves */
1350 bool BKE_nlatracks_have_animated_strips(ListBase *tracks)
1351 {
1352         NlaTrack *nlt;
1353         
1354         /* sanity checks */
1355         if (ELEM(NULL, tracks, tracks->first))
1356                 return false;
1357                 
1358         /* check each track, stopping on the first hit */
1359         for (nlt = tracks->first; nlt; nlt = nlt->next) {
1360                 if (BKE_nlatrack_has_animated_strips(nlt))
1361                         return true;
1362         }
1363         
1364         /* none found */
1365         return false;
1366 }
1367
1368 /* Validate the NLA-Strips 'control' F-Curves based on the flags set*/
1369 void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
1370 {
1371         FCurve *fcu;
1372         
1373         /* sanity checks */
1374         if (strip == NULL)
1375                 return;
1376         
1377         /* if controlling influence... */
1378         if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
1379                 /* try to get F-Curve */
1380                 fcu = list_find_fcurve(&strip->fcurves, "influence", 0);
1381                 
1382                 /* add one if not found */
1383                 if (fcu == NULL) {
1384                         /* make new F-Curve */
1385                         fcu = MEM_callocN(sizeof(FCurve), "NlaStrip FCurve");
1386                         BLI_addtail(&strip->fcurves, fcu);
1387                         
1388                         /* set default flags */
1389                         fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
1390                         fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
1391                         
1392                         /* store path - make copy, and store that */
1393                         fcu->rna_path = BLI_strdupn("influence", 9);
1394                         
1395                         /* insert keyframe to ensure current value stays on first refresh */
1396                         fcu->bezt = MEM_callocN(sizeof(BezTriple), "nlastrip influence bezt");
1397                         fcu->totvert = 1;
1398                         
1399                         fcu->bezt->vec[1][0] = strip->start;
1400                         fcu->bezt->vec[1][1] = strip->influence;
1401                 }
1402         }
1403         
1404         /* if controlling time... */
1405         if (strip->flag & NLASTRIP_FLAG_USR_TIME) {
1406                 /* try to get F-Curve */
1407                 fcu = list_find_fcurve(&strip->fcurves, "strip_time", 0);
1408                 
1409                 /* add one if not found */
1410                 if (fcu == NULL) {
1411                         /* make new F-Curve */
1412                         fcu = MEM_callocN(sizeof(FCurve), "NlaStrip FCurve");
1413                         BLI_addtail(&strip->fcurves, fcu);
1414                         
1415                         /* set default flags */
1416                         fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
1417                         fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
1418                         
1419                         /* store path - make copy, and store that */
1420                         fcu->rna_path = BLI_strdupn("strip_time", 10);
1421                         
1422                         /* TODO: insert a few keyframes to ensure default behavior? */
1423                 }
1424         }
1425 }
1426
1427 /* Check if the given RNA pointer + property combo should be handled by
1428  * NLA strip curves or not.
1429  */
1430 bool BKE_nlastrip_has_curves_for_property(const PointerRNA *ptr, const PropertyRNA *prop)
1431 {
1432         /* sanity checks */
1433         if (ELEM(NULL, ptr, prop))
1434                 return false;
1435         
1436         /* 1) Must be NLA strip */
1437         if (ptr->type == &RNA_NlaStrip) {
1438                 /* 2) Must be one of the predefined properties */
1439                 static PropertyRNA *prop_influence = NULL; 
1440                 static PropertyRNA *prop_time = NULL;
1441                 static bool needs_init = true;
1442                 
1443                 /* Init the properties on first use */
1444                 if (needs_init) {
1445                         prop_influence = RNA_struct_type_find_property(&RNA_NlaStrip, "influence");
1446                         prop_time = RNA_struct_type_find_property(&RNA_NlaStrip, "strip_time");
1447                         
1448                         needs_init = false;
1449                 }
1450                 
1451                 /* Check if match */
1452                 if (ELEM(prop, prop_influence, prop_time)) {
1453                         return true;
1454                 }
1455         }
1456         
1457         /* No criteria met */
1458         return false;
1459 }
1460
1461 /* Sanity Validation ------------------------------------ */
1462
1463 static bool nla_editbone_name_check(void *arg, const char *name)
1464 {
1465         return BLI_ghash_haskey((GHash *)arg, (const void *)name);
1466 }
1467
1468 /* Find (and set) a unique name for a strip from the whole AnimData block 
1469  * Uses a similar method to the BLI method, but is implemented differently
1470  * as we need to ensure that the name is unique over several lists of tracks,
1471  * not just a single track.
1472  */
1473 void BKE_nlastrip_validate_name(AnimData *adt, NlaStrip *strip)
1474 {
1475         GHash *gh;
1476         NlaStrip *tstrip;
1477         NlaTrack *nlt;
1478         
1479         /* sanity checks */
1480         if (ELEM(NULL, adt, strip))
1481                 return;
1482                 
1483         /* give strip a default name if none already */
1484         if (strip->name[0] == 0) {
1485                 switch (strip->type) {
1486                         case NLASTRIP_TYPE_CLIP: /* act-clip */
1487                                 BLI_strncpy(strip->name, (strip->act) ? (strip->act->id.name + 2) : ("<No Action>"), sizeof(strip->name));
1488                                 break;
1489                         case NLASTRIP_TYPE_TRANSITION: /* transition */
1490                                 BLI_strncpy(strip->name, "Transition", sizeof(strip->name));
1491                                 break;
1492                         case NLASTRIP_TYPE_META: /* meta */
1493                                 BLI_strncpy(strip->name, "Meta", sizeof(strip->name));
1494                                 break;
1495                         default:
1496                                 BLI_strncpy(strip->name, "NLA Strip", sizeof(strip->name));
1497                                 break;
1498                 }
1499         }
1500         
1501         /* build a hash-table of all the strips in the tracks 
1502          *      - this is easier than iterating over all the tracks+strips hierarchy every time
1503          *        (and probably faster)
1504          */
1505         gh = BLI_ghash_str_new("nlastrip_validate_name gh");
1506         
1507         for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
1508                 for (tstrip = nlt->strips.first; tstrip; tstrip = tstrip->next) {
1509                         /* don't add the strip of interest */
1510                         if (tstrip == strip) 
1511                                 continue;
1512                         
1513                         /* use the name of the strip as the key, and the strip as the value, since we're mostly interested in the keys */
1514                         BLI_ghash_insert(gh, tstrip->name, tstrip);
1515                 }
1516         }
1517         
1518         /* if the hash-table has a match for this name, try other names... 
1519          *      - in an extreme case, it might not be able to find a name, but then everything else in Blender would fail too :)
1520          */
1521         BLI_uniquename_cb(nla_editbone_name_check, (void *)gh, DATA_("NlaStrip"), '.', strip->name, sizeof(strip->name));
1522
1523         /* free the hash... */
1524         BLI_ghash_free(gh, NULL, NULL);
1525 }
1526
1527 /* ---- */
1528
1529 /* Get strips which overlap the given one at the start/end of its range 
1530  *      - strip: strip that we're finding overlaps for
1531  *      - track: nla-track that the overlapping strips should be found from
1532  *      - start, end: frames for the offending endpoints
1533  */
1534 static void nlastrip_get_endpoint_overlaps(NlaStrip *strip, NlaTrack *track, float **start, float **end)
1535 {
1536         NlaStrip *nls;
1537         
1538         /* find strips that overlap over the start/end of the given strip,
1539          * but which don't cover the entire length 
1540          */
1541         /* TODO: this scheme could get quite slow for doing this on many strips... */
1542         for (nls = track->strips.first; nls; nls = nls->next) {
1543                 /* check if strip overlaps (extends over or exactly on) the entire range of the strip we're validating */
1544                 if ((nls->start <= strip->start) && (nls->end >= strip->end)) {
1545                         *start = NULL;
1546                         *end = NULL;
1547                         return;
1548                 }
1549                 
1550                 /* check if strip doesn't even occur anywhere near... */
1551                 if (nls->end < strip->start)
1552                         continue;  /* skip checking this strip... not worthy of mention */
1553                 if (nls->start > strip->end)
1554                         return;  /* the range we're after has already passed */
1555                         
1556                 /* if this strip is not part of an island of continuous strips, it can be used
1557                  *      - this check needs to be done for each end of the strip we try and use...
1558                  */
1559                 if ((nls->next == NULL) || IS_EQF(nls->next->start, nls->end) == 0) {
1560                         if ((nls->end > strip->start) && (nls->end < strip->end))
1561                                 *start = &nls->end;
1562                 }
1563                 if ((nls->prev == NULL) || IS_EQF(nls->prev->end, nls->start) == 0) {
1564                         if ((nls->start < strip->end) && (nls->start > strip->start))
1565                                 *end = &nls->start;
1566                 }
1567         }
1568 }
1569
1570 /* Determine auto-blending for the given strip */
1571 static void BKE_nlastrip_validate_autoblends(NlaTrack *nlt, NlaStrip *nls)
1572 {
1573         float *ps = NULL, *pe = NULL;
1574         float *ns = NULL, *ne = NULL;
1575         
1576         /* sanity checks */
1577         if (ELEM(NULL, nls, nlt))
1578                 return;
1579         if ((nlt->prev == NULL) && (nlt->next == NULL))
1580                 return;
1581         if ((nls->flag & NLASTRIP_FLAG_AUTO_BLENDS) == 0)
1582                 return;
1583         
1584         /* get test ranges */
1585         if (nlt->prev)
1586                 nlastrip_get_endpoint_overlaps(nls, nlt->prev, &ps, &pe);
1587         if (nlt->next)
1588                 nlastrip_get_endpoint_overlaps(nls, nlt->next, &ns, &ne);
1589                 
1590         /* set overlaps for this strip 
1591          *      - don't use the values obtained though if the end in question 
1592          *        is directly followed/preceded by another strip, forming an 
1593          *        'island' of continuous strips
1594          */
1595         if ((ps || ns) && ((nls->prev == NULL) || IS_EQF(nls->prev->end, nls->start) == 0)) {
1596                 /* start overlaps - pick the largest overlap */
1597                 if ( ((ps && ns) && (*ps > *ns)) || (ps) )
1598                         nls->blendin = *ps - nls->start;
1599                 else
1600                         nls->blendin = *ns - nls->start;
1601         }
1602         else /* no overlap allowed/needed */
1603                 nls->blendin = 0.0f;
1604                 
1605         if ((pe || ne) && ((nls->next == NULL) || IS_EQF(nls->next->start, nls->end) == 0)) {
1606                 /* end overlaps - pick the largest overlap */
1607                 if ( ((pe && ne) && (*pe > *ne)) || (pe) )
1608                         nls->blendout = nls->end - *pe;
1609                 else
1610                         nls->blendout = nls->end - *ne;
1611         }
1612         else /* no overlap allowed/needed */
1613                 nls->blendout = 0.0f;
1614 }
1615
1616 /* Ensure that auto-blending and other settings are set correctly */
1617 void BKE_nla_validate_state(AnimData *adt)
1618 {
1619         NlaStrip *strip, *fstrip = NULL;
1620         NlaTrack *nlt;
1621         
1622         /* sanity checks */
1623         if (ELEM(NULL, adt, adt->nla_tracks.first))
1624                 return;
1625                 
1626         /* adjust blending values for auto-blending, and also do an initial pass to find the earliest strip */
1627         for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
1628                 for (strip = nlt->strips.first; strip; strip = strip->next) {
1629                         /* auto-blending first */
1630                         BKE_nlastrip_validate_autoblends(nlt, strip);
1631                         
1632                         /* extend mode - find first strip */
1633                         if ((fstrip == NULL) || (strip->start < fstrip->start))
1634                                 fstrip = strip;
1635                 }
1636         }
1637         
1638         /* second pass over the strips to adjust the extend-mode to fix any problems */
1639         for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
1640                 for (strip = nlt->strips.first; strip; strip = strip->next) {
1641                         /* apart from 'nothing' option which user has to explicitly choose, we don't really know if 
1642                          * we should be overwriting the extend setting (but assume that's what the user wanted)
1643                          */
1644                         /* TODO: 1 solution is to tie this in with auto-blending... */
1645                         if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
1646                                 /* 1) First strip must be set to extend hold, otherwise, stuff before acts dodgy
1647                                  * 2) Only overwrite extend mode if *not* changing it will most probably result in 
1648                                  * occlusion problems, which will occur if...
1649                                  * - blendmode = REPLACE
1650                                  * - all channels the same (this is fiddly to test, so is currently assumed)
1651                                  *
1652                                  * Should fix problems such as [#29869]
1653                                  */
1654                                 if (strip == fstrip)
1655                                         strip->extendmode = NLASTRIP_EXTEND_HOLD;
1656                                 else if (strip->blendmode == NLASTRIP_MODE_REPLACE)
1657                                         strip->extendmode = NLASTRIP_EXTEND_HOLD_FORWARD;
1658                         }
1659                 }
1660         }
1661 }
1662
1663 /* Action Stashing -------------------------------------- */
1664
1665 /* name of stashed tracks - the translation stuff is included here to save extra work */
1666 #define STASH_TRACK_NAME  DATA_("[Action Stash]")
1667
1668 /* Check if an action is "stashed" in the NLA already
1669  *
1670  * The criteria for this are:
1671  *   1) The action in question lives in a "stash" track
1672  *   2) We only check first-level strips. That is, we will not check inside meta strips.
1673  */
1674 bool BKE_nla_action_is_stashed(AnimData *adt, bAction *act)
1675 {
1676         NlaTrack *nlt;
1677         NlaStrip *strip;
1678         
1679         for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
1680                 if (strstr(nlt->name, STASH_TRACK_NAME)) {
1681                         for (strip = nlt->strips.first; strip; strip = strip->next) {
1682                                 if (strip->act == act)
1683                                         return true;
1684                         }
1685                 }
1686         }
1687         
1688         return false;
1689 }
1690
1691 /* "Stash" an action (i.e. store it as a track/layer in the NLA, but non-contributing)
1692  * to retain it in the file for future uses
1693  */
1694 bool BKE_nla_action_stash(AnimData *adt)
1695 {
1696         NlaTrack *prev_track = NULL;
1697         NlaTrack *nlt;
1698         NlaStrip *strip;
1699         
1700         /* sanity check */
1701         if (ELEM(NULL, adt, adt->action)) {
1702                 printf("%s: Invalid argument - %p %p\n", __func__, adt, adt->action);
1703                 return false;
1704         }
1705         
1706         /* do not add if it is already stashed */
1707         if (BKE_nla_action_is_stashed(adt, adt->action))
1708                 return false;
1709         
1710         /* create a new track, and add this immediately above the previous stashing track */
1711         for (prev_track = adt->nla_tracks.last; prev_track; prev_track = prev_track->prev) {
1712                 if (strstr(prev_track->name, STASH_TRACK_NAME)) {
1713                         break;
1714                 }
1715         }
1716         
1717         nlt = BKE_nlatrack_add(adt, prev_track);
1718         BLI_assert(nlt != NULL);
1719         
1720         /* we need to ensure that if there wasn't any previous instance, it must go to tbe bottom of the stack */
1721         if (prev_track == NULL) {
1722                 BLI_remlink(&adt->nla_tracks, nlt);
1723                 BLI_addhead(&adt->nla_tracks, nlt);
1724         }
1725         
1726         BLI_strncpy(nlt->name, STASH_TRACK_NAME, sizeof(nlt->name));
1727         BLI_uniquename(&adt->nla_tracks, nlt, STASH_TRACK_NAME, '.', offsetof(NlaTrack, name), sizeof(nlt->name));
1728         
1729         /* add the action as a strip in this new track
1730          * NOTE: a new user is created here
1731          */
1732         strip = BKE_nlastrip_new(adt->action);
1733         BLI_assert(strip != NULL);
1734         
1735         BKE_nlatrack_add_strip(nlt, strip);
1736         BKE_nlastrip_validate_name(adt, strip);
1737         
1738         /* mark the stash track and strip so that they doesn't disturb the stack animation,
1739          * and are unlikely to draw attention to itself (or be accidentally bumped around)
1740          * 
1741          * NOTE: this must be done *after* adding the strip to the track, or else
1742          *       the strip locking will prevent the strip from getting added
1743          */
1744         nlt->flag = (NLATRACK_MUTED | NLATRACK_PROTECTED);
1745         strip->flag &= ~(NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE);
1746         
1747         /* also mark the strip for auto syncing the length, so that the strips accurately
1748          * reflect the length of the action
1749          * XXX: we could do with some extra flags here to prevent repeats/scaling options from working!
1750          */
1751         strip->flag |= NLASTRIP_FLAG_SYNC_LENGTH;
1752         
1753         /* succeeded */
1754         return true;
1755 }
1756
1757 /* Core Tools ------------------------------------------- */
1758
1759 /* For the given AnimData block, add the active action to the NLA
1760  * stack (i.e. 'push-down' action). The UI should only allow this 
1761  * for normal editing only (i.e. not in editmode for some strip's action),
1762  * so no checks for this are performed.
1763  */
1764 /* TODO: maybe we should have checks for this too... */
1765 void BKE_nla_action_pushdown(AnimData *adt)
1766 {
1767         NlaStrip *strip;
1768         const bool is_first = (adt) && (adt->nla_tracks.first == NULL);
1769         
1770         /* sanity checks */
1771         /* TODO: need to report the error for this */
1772         if (ELEM(NULL, adt, adt->action))
1773                 return;
1774
1775         /* if the action is empty, we also shouldn't try to add to stack,
1776          * as that will cause us grief down the track
1777          */
1778         /* TODO: what about modifiers? */
1779         if (action_has_motion(adt->action) == 0) {
1780                 printf("BKE_nla_action_pushdown(): action has no data\n");
1781                 return;
1782         }
1783         
1784         /* add a new NLA strip to the track, which references the active action */
1785         strip = BKE_nlastack_add_strip(adt, adt->action);
1786         
1787         /* do other necessary work on strip */
1788         if (strip) {
1789                 /* clear reference to action now that we've pushed it onto the stack */
1790                 id_us_min(&adt->action->id);
1791                 adt->action = NULL;
1792                 
1793                 /* copy current "action blending" settings from adt to the strip,
1794                  * as it was keyframed with these settings, so omitting them will
1795                  * change the effect  [T54233]
1796                  *
1797                  * NOTE: We only do this when there are no tracks
1798                  */
1799                 if (is_first == false) {
1800                         strip->blendmode = adt->act_blendmode;
1801                         strip->influence = adt->act_influence;
1802                         strip->extendmode = adt->act_extendmode;
1803                         
1804                         if (adt->act_influence < 1.0f) {
1805                                 /* enable "user-controlled" influence (which will insert a default keyframe)
1806                                  * so that the influence doesn't get lost on the new update
1807                                  *
1808                                  * NOTE: An alternative way would have been to instead hack the influence
1809                                  * to not get always get reset to full strength if NLASTRIP_FLAG_USR_INFLUENCE
1810                                  * is disabled but auto-blending isn't being used. However, that approach
1811                                  * is a bit hacky/hard to discover, and may cause backwards compatability issues,
1812                                  * so it's better to just do it this way.
1813                                  */
1814                                 strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
1815                                 BKE_nlastrip_validate_fcurves(strip);
1816                         }
1817                 }
1818                 
1819                 /* if the strip is the first one in the track it lives in, check if there
1820                  * are strips in any other tracks that may be before this, and set the extend
1821                  * mode accordingly
1822                  */
1823                 if (nlastrip_is_first(adt, strip) == 0) {
1824                         /* not first, so extend mode can only be NLASTRIP_EXTEND_HOLD_FORWARD not NLASTRIP_EXTEND_HOLD,
1825                          * so that it doesn't override strips in previous tracks
1826                          */
1827                         /* FIXME: this needs to be more automated, since user can rearrange strips */
1828                         if (strip->extendmode == NLASTRIP_EXTEND_HOLD)
1829                                 strip->extendmode = NLASTRIP_EXTEND_HOLD_FORWARD;
1830                 }
1831                 
1832                 /* make strip the active one... */
1833                 BKE_nlastrip_set_active(adt, strip);
1834         }
1835 }
1836
1837 /* Find the active strip + track combo, and set them up as the tweaking track,
1838  * and return if successful or not.
1839  */
1840 bool BKE_nla_tweakmode_enter(AnimData *adt)
1841 {
1842         NlaTrack *nlt, *activeTrack = NULL;
1843         NlaStrip *strip, *activeStrip = NULL;
1844         
1845         /* verify that data is valid */
1846         if (ELEM(NULL, adt, adt->nla_tracks.first))
1847                 return false;
1848                 
1849         /* if block is already in tweakmode, just leave, but we should report 
1850          * that this block is in tweakmode (as our returncode)
1851          */
1852         if (adt->flag & ADT_NLA_EDIT_ON)
1853                 return true;
1854                 
1855         /* go over the tracks, finding the active one, and its active strip
1856          *  - if we cannot find both, then there's nothing to do
1857          */
1858         for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
1859                 /* check if active */
1860                 if (nlt->flag & NLATRACK_ACTIVE) {
1861                         /* store reference to this active track */
1862                         activeTrack = nlt;
1863                         
1864                         /* now try to find active strip */
1865                         activeStrip = BKE_nlastrip_find_active(nlt);
1866                         break;
1867                 }
1868         }
1869         
1870         /* There are situations where we may have multiple strips selected and we want to enter tweakmode on all 
1871          * of those at once. Usually in those cases, it will usually just be a single strip per AnimData. 
1872          * In such cases, compromise and take the last selected track and/or last selected strip [#28468] 
1873          */
1874         if (activeTrack == NULL) {
1875                 /* try last selected track for active strip */
1876                 for (nlt = adt->nla_tracks.last; nlt; nlt = nlt->prev) {
1877                         if (nlt->flag & NLATRACK_SELECTED) {
1878                                 /* assume this is the active track */
1879                                 activeTrack = nlt;
1880                                 
1881                                 /* try to find active strip */
1882                                 activeStrip = BKE_nlastrip_find_active(nlt);
1883                                 break;
1884                         }
1885                 }
1886         }
1887         if ((activeTrack) && (activeStrip == NULL)) {
1888                 /* no active strip in active or last selected track; compromise for first selected (assuming only single)... */
1889                 for (strip = activeTrack->strips.first; strip; strip = strip->next) {
1890                         if (strip->flag & (NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE)) {
1891                                 activeStrip = strip;
1892                                 break;
1893                         }
1894                 }
1895         }
1896         
1897         if (ELEM(NULL, activeTrack, activeStrip, activeStrip->act)) {
1898                 if (G.debug & G_DEBUG) {
1899                         printf("NLA tweakmode enter - neither active requirement found\n");
1900                         printf("\tactiveTrack = %p, activeStrip = %p\n", (void *)activeTrack, (void *)activeStrip);
1901                 }
1902                 return false;
1903         }
1904         
1905         /* go over all the tracks up to the active one, tagging each strip that uses the same 
1906          * action as the active strip, but leaving everything else alone
1907          */
1908         for (nlt = activeTrack->prev; nlt; nlt = nlt->prev) {
1909                 for (strip = nlt->strips.first; strip; strip = strip->next) {
1910                         if (strip->act == activeStrip->act)
1911                                 strip->flag |= NLASTRIP_FLAG_TWEAKUSER;
1912                         else
1913                                 strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
1914                 }
1915         }
1916         
1917         /* tag all other strips in active track that uses the same action as the active strip */
1918         for (strip = activeTrack->strips.first; strip; strip = strip->next) {
1919                 if ((strip->act == activeStrip->act) && (strip != activeStrip))
1920                         strip->flag |= NLASTRIP_FLAG_TWEAKUSER;
1921                 else
1922                         strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
1923         }
1924         
1925         /* go over all the tracks after AND INCLUDING the active one, tagging them as being disabled 
1926          *      - the active track needs to also be tagged, otherwise, it'll overlap with the tweaks going on
1927          */
1928         for (nlt = activeTrack; nlt; nlt = nlt->next)
1929                 nlt->flag |= NLATRACK_DISABLED;
1930         
1931         /* handle AnimData level changes:
1932          *      - 'real' active action to temp storage (no need to change user-counts)
1933          *      - action of active strip set to be the 'active action', and have its usercount incremented
1934          *      - editing-flag for this AnimData block should also get turned on (for more efficient restoring)
1935          *      - take note of the active strip for mapping-correction of keyframes in the action being edited
1936          */
1937         adt->tmpact = adt->action;
1938         adt->action = activeStrip->act;
1939         adt->act_track = activeTrack;
1940         adt->actstrip = activeStrip;
1941         id_us_plus(&activeStrip->act->id);
1942         adt->flag |= ADT_NLA_EDIT_ON;
1943         
1944         /* done! */
1945         return true;
1946 }
1947
1948 /* Exit tweakmode for this AnimData block */
1949 void BKE_nla_tweakmode_exit(AnimData *adt)
1950 {
1951         NlaStrip *strip;
1952         NlaTrack *nlt;
1953         
1954         /* verify that data is valid */
1955         if (ELEM(NULL, adt, adt->nla_tracks.first))
1956                 return;
1957                 
1958         /* hopefully the flag is correct - skip if not on */
1959         if ((adt->flag & ADT_NLA_EDIT_ON) == 0)
1960                 return;
1961                 
1962         /* sync the length of the user-strip with the new state of the action
1963          * but only if the user has explicitly asked for this to happen
1964          * (see [#34645] for things to be careful about)
1965          */
1966         if ((adt->actstrip) && (adt->actstrip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) {
1967                 strip = adt->actstrip;
1968                 
1969                 /* must be action-clip only (transitions don't have scale) */
1970                 if ((strip->type == NLASTRIP_TYPE_CLIP) && (strip->act)) {
1971                         /* recalculate the length of the action */
1972                         calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
1973                         
1974                         /* adjust the strip extents in response to this */
1975                         BKE_nlastrip_recalculate_bounds(strip);
1976                 }
1977         }
1978
1979         /* for all Tracks, clear the 'disabled' flag
1980          * for all Strips, clear the 'tweak-user' flag
1981          */
1982         for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
1983                 nlt->flag &= ~NLATRACK_DISABLED;
1984                 
1985                 for (strip = nlt->strips.first; strip; strip = strip->next) {
1986                         /* sync strip extents if this strip uses the same action */
1987                         if ((adt->actstrip) && (adt->actstrip->act == strip->act) && (strip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) {
1988                                 /* recalculate the length of the action */
1989                                 calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
1990                                 
1991                                 /* adjust the strip extents in response to this */
1992                                 BKE_nlastrip_recalculate_bounds(strip);
1993                         }
1994                         
1995                         /* clear tweakuser flag */
1996                         strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
1997                 }
1998         }
1999         
2000         /* handle AnimData level changes:
2001          *      - 'temporary' active action needs its usercount decreased, since we're removing this reference
2002          *      - 'real' active action is restored from storage
2003          *      - storage pointer gets cleared (to avoid having bad notes hanging around)
2004          *      - editing-flag for this AnimData block should also get turned off
2005          *      - clear pointer to active strip
2006          */
2007         if (adt->action)
2008                 id_us_min(&adt->action->id);
2009         adt->action = adt->tmpact;
2010         adt->tmpact = NULL;
2011         adt->act_track = NULL;
2012         adt->actstrip = NULL;
2013         adt->flag &= ~ADT_NLA_EDIT_ON;
2014 }
2015
2016 /* Baking Tools ------------------------------------------- */
2017
2018 static void UNUSED_FUNCTION(BKE_nla_bake) (Scene *scene, ID *UNUSED(id), AnimData *adt, int UNUSED(flag))
2019 {
2020
2021         /* verify that data is valid 
2022          *      1) Scene and AnimData must be provided 
2023          *      2) there must be tracks to merge...
2024          */
2025         if (ELEM(NULL, scene, adt, adt->nla_tracks.first))
2026                 return;
2027         
2028         /* if animdata currently has an action, 'push down' this onto the stack first */
2029         if (adt->action)
2030                 BKE_nla_action_pushdown(adt);
2031         
2032         /* get range of motion to bake, and the channels involved... */
2033         
2034         /* temporarily mute the action, and start keying to it */
2035         
2036         /* start keying... */
2037         
2038         /* unmute the action */
2039 }
2040
2041 /* *************************************************** */