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