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