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