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