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