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