4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): Joshua Leung (full recode)
27 * ***** END GPL LICENSE BLOCK *****
30 /** \file blender/blenkernel/intern/nla.c
42 #include "MEM_guardedalloc.h"
44 #include "BLI_utildefines.h"
45 #include "BLI_ghash.h"
47 #include "DNA_anim_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_sound_types.h"
50 #include "DNA_speaker_types.h"
52 #include "BKE_action.h"
53 #include "BKE_fcurve.h"
55 #include "BKE_global.h"
56 #include "BKE_library.h"
59 # include "AUD_C-API.h"
62 #include "RNA_access.h"
63 #include "nla_private.h"
67 /* *************************************************** */
70 /* Freeing ------------------------------------------- */
72 /* Remove the given NLA strip from the NLA track it occupies, free the strip's data,
73 * and the strip itself.
75 void free_nlastrip (ListBase *strips, NlaStrip *strip)
83 /* free child-strips */
84 for (cs= strip->strips.first; cs; cs= csn) {
86 free_nlastrip(&strip->strips, cs);
89 /* remove reference to action */
91 id_us_min(&strip->act->id);
93 /* free remapping info */
95 // BKE_animremap_free();
97 /* free own F-Curves */
98 free_fcurves(&strip->fcurves);
100 /* free own F-Modifiers */
101 free_fmodifiers(&strip->modifiers);
103 /* free the strip itself */
105 BLI_freelinkN(strips, strip);
110 /* Remove the given NLA track from the set of NLA tracks, free the track's data,
111 * and the track itself.
113 void free_nlatrack (ListBase *tracks, NlaTrack *nlt)
115 NlaStrip *strip, *stripn;
122 for (strip= nlt->strips.first; strip; strip= stripn) {
124 free_nlastrip(&nlt->strips, strip);
127 /* free NLA track itself now */
129 BLI_freelinkN(tracks, nlt);
134 /* Free the elements of type NLA Tracks provided in the given list, but do not free
135 * the list itself since that is not free-standing
137 void free_nladata (ListBase *tracks)
139 NlaTrack *nlt, *nltn;
142 if ELEM(NULL, tracks, tracks->first)
145 /* free tracks one by one */
146 for (nlt= tracks->first; nlt; nlt= nltn) {
148 free_nlatrack(tracks, nlt);
151 /* clear the list's pointers to be safe */
152 tracks->first= tracks->last= NULL;
155 /* Copying ------------------------------------------- */
158 NlaStrip *copy_nlastrip (NlaStrip *strip)
168 strip_d= MEM_dupallocN(strip);
169 strip_d->next= strip_d->prev= NULL;
171 /* increase user-count of action */
173 id_us_plus(&strip_d->act->id);
175 /* copy F-Curves and modifiers */
176 copy_fcurves(&strip_d->fcurves, &strip->fcurves);
177 copy_fmodifiers(&strip_d->modifiers, &strip->modifiers);
179 /* make a copy of all the child-strips, one at a time */
180 strip_d->strips.first= strip_d->strips.last= NULL;
182 for (cs= strip->strips.first; cs; cs= cs->next) {
183 cs_d= copy_nlastrip(cs);
184 BLI_addtail(&strip_d->strips, cs_d);
187 /* return the strip */
192 NlaTrack *copy_nlatrack (NlaTrack *nlt)
194 NlaStrip *strip, *strip_d;
202 nlt_d= MEM_dupallocN(nlt);
203 nlt_d->next= nlt_d->prev= NULL;
205 /* make a copy of all the strips, one at a time */
206 nlt_d->strips.first= nlt_d->strips.last= NULL;
208 for (strip= nlt->strips.first; strip; strip= strip->next) {
209 strip_d= copy_nlastrip(strip);
210 BLI_addtail(&nlt_d->strips, strip_d);
213 /* return the copy */
217 /* Copy all NLA data */
218 void copy_nladata (ListBase *dst, ListBase *src)
220 NlaTrack *nlt, *nlt_d;
223 if ELEM(NULL, dst, src)
226 /* clear out the destination list first for precautions... */
227 dst->first= dst->last= NULL;
229 /* copy each NLA-track, one at a time */
230 for (nlt= src->first; nlt; nlt= nlt->next) {
231 /* make a copy, and add the copy to the destination list */
232 nlt_d= copy_nlatrack(nlt);
233 BLI_addtail(dst, nlt_d);
237 /* Adding ------------------------------------------- */
239 /* Add a NLA Track to the given AnimData
240 * - prev: NLA-Track to add the new one after
242 NlaTrack *add_nlatrack (AnimData *adt, NlaTrack *prev)
250 /* allocate new track */
251 nlt= MEM_callocN(sizeof(NlaTrack), "NlaTrack");
253 /* set settings requiring the track to not be part of the stack yet */
254 nlt->flag = NLATRACK_SELECTED;
255 nlt->index= BLI_countlist(&adt->nla_tracks);
257 /* add track to stack, and make it the active one */
259 BLI_insertlinkafter(&adt->nla_tracks, prev, nlt);
261 BLI_addtail(&adt->nla_tracks, nlt);
262 BKE_nlatrack_set_active(&adt->nla_tracks, nlt);
264 /* must have unique name, but we need to seed this */
265 strcpy(nlt->name, "NlaTrack");
266 BLI_uniquename(&adt->nla_tracks, nlt, "NlaTrack", '.', offsetof(NlaTrack, name), sizeof(nlt->name));
268 /* return the new track */
272 /* Add a NLA Strip referencing the given Action */
273 NlaStrip *add_nlastrip (bAction *act)
281 /* allocate new strip */
282 strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
285 * - selected flag to highlight this to the user
286 * - auto-blends to ensure that blend in/out values are automatically
287 * determined by overlaps of strips
288 * - (XXX) synchronisation of strip-length in accordance with changes to action-length
289 * is not done though, since this should only really happens in editmode for strips now
290 * though this decision is still subject to further review...
292 strip->flag = NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_AUTO_BLENDS;
294 /* assign the action reference */
296 id_us_plus(&act->id);
298 /* determine initial range
299 * - strip length cannot be 0... ever...
301 calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
303 strip->start = strip->actstart;
304 strip->end = (IS_EQF(strip->actstart, strip->actend)) ? (strip->actstart + 1.0f): (strip->actend);
306 /* strip should be referenced as-is */
308 strip->repeat = 1.0f;
310 /* return the new strip */
314 /* Add new NLA-strip to the top of the NLA stack - i.e. into the last track if space, or a new one otherwise */
315 NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act)
321 if ELEM(NULL, adt, act)
324 /* create a new NLA strip */
325 strip= add_nlastrip(act);
329 /* firstly try adding strip to last track, but if that fails, add to a new track */
330 if (BKE_nlatrack_add_strip(adt->nla_tracks.last, strip) == 0) {
331 /* trying to add to the last track failed (no track or no space),
332 * so add a new track to the stack, and add to that...
334 nlt= add_nlatrack(adt, NULL);
335 BKE_nlatrack_add_strip(nlt, strip);
338 /* automatically name it too */
339 BKE_nlastrip_validate_name(adt, strip);
341 /* returns the strip added */
345 /* Add a NLA Strip referencing the given speaker's sound */
346 NlaStrip *add_nla_soundstrip (Scene *scene, Speaker *speaker)
348 NlaStrip *strip = MEM_callocN(sizeof(NlaStrip), "NlaSoundStrip");
350 /* if speaker has a sound, set the strip length to the length of the sound,
351 * otherwise default to length of 10 frames
353 #ifdef WITH_AUDASPACE
356 AUD_SoundInfo info = AUD_getInfo(speaker->sound->playback_handle);
358 strip->end = ceil(info.length * FPS);
366 /* general settings */
367 strip->type = NLASTRIP_TYPE_SOUND;
369 strip->flag = NLASTRIP_FLAG_SELECT;
370 strip->extendmode = NLASTRIP_EXTEND_NOTHING; /* nothing to extend... */
372 /* strip should be referenced as-is */
374 strip->repeat = 1.0f;
376 /* return this strip */
380 /* *************************************************** */
381 /* NLA Evaluation <-> Editing Stuff */
383 /* Strip Mapping ------------------------------------- */
385 /* non clipped mapping for strip-time <-> global time (for Action-Clips)
386 * invert = convert action-strip time to global time
388 static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short mode)
390 float actlength, scale;
391 // float repeat; // UNUSED
393 /* get number of repeats */
394 if (IS_EQF(strip->repeat, 0.0f)) strip->repeat = 1.0f;
395 // repeat = strip->repeat; // UNUSED
398 if (IS_EQF(strip->scale, 0.0f)) strip->scale= 1.0f;
399 scale = (float)fabs(strip->scale); /* scale must be positive - we've got a special flag for reversing */
401 /* length of referenced action */
402 actlength = strip->actend - strip->actstart;
403 if (IS_EQF(actlength, 0.0f)) actlength = 1.0f;
405 /* reversed = play strip backwards */
406 if (strip->flag & NLASTRIP_FLAG_REVERSE) {
407 // FIXME: this won't work right with Graph Editor?
408 if (mode == NLATIME_CONVERT_MAP) {
409 return strip->end - scale*(cframe - strip->actstart);
411 else if (mode == NLATIME_CONVERT_UNMAP) {
412 return (strip->end + (strip->actstart * scale - cframe)) / scale;
414 else /* if (mode == NLATIME_CONVERT_EVAL) */{
415 if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) {
416 /* this case prevents the motion snapping back to the first frame at the end of the strip
417 * by catching the case where repeats is a whole number, which means that the end of the strip
418 * could also be interpreted as the end of the start of a repeat
420 return strip->actstart;
423 /* - the 'fmod(..., actlength*scale)' is needed to get the repeats working
424 * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat
426 return strip->actend - fmodf(cframe - strip->start, actlength*scale) / scale;
431 if (mode == NLATIME_CONVERT_MAP) {
432 return strip->start + scale*(cframe - strip->actstart);
434 else if (mode == NLATIME_CONVERT_UNMAP) {
435 return strip->actstart + (cframe - strip->start) / scale;
437 else /* if (mode == NLATIME_CONVERT_EVAL) */{
438 if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) {
439 /* this case prevents the motion snapping back to the first frame at the end of the strip
440 * by catching the case where repeats is a whole number, which means that the end of the strip
441 * could also be interpreted as the end of the start of a repeat
443 return strip->actend;
446 /* - the 'fmod(..., actlength*scale)' is needed to get the repeats working
447 * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat
449 return strip->actstart + fmodf(cframe - strip->start, actlength*scale) / scale;
455 /* non clipped mapping for strip-time <-> global time (for Transitions)
456 * invert = convert action-strip time to global time
458 static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short mode)
462 /* length of strip */
463 length= strip->end - strip->start;
465 /* reversed = play strip backwards */
466 if (strip->flag & NLASTRIP_FLAG_REVERSE) {
467 if (mode == NLATIME_CONVERT_MAP)
468 return strip->end - (length * cframe);
470 return (strip->end - cframe) / length;
473 if (mode == NLATIME_CONVERT_MAP)
474 return (length * cframe) + strip->start;
476 return (cframe - strip->start) / length;
480 /* non clipped mapping for strip-time <-> global time
481 * mode = eNlaTime_ConvertModes[] -> NLATIME_CONVERT_*
483 * only secure for 'internal' (i.e. within AnimSys evaluation) operations,
484 * but should not be directly relied on for stuff which interacts with editors
486 float nlastrip_get_frame (NlaStrip *strip, float cframe, short mode)
488 switch (strip->type) {
489 case NLASTRIP_TYPE_META: /* meta - for now, does the same as transition (is really just an empty container) */
490 case NLASTRIP_TYPE_TRANSITION: /* transition */
491 return nlastrip_get_frame_transition(strip, cframe, mode);
493 case NLASTRIP_TYPE_CLIP: /* action-clip (default) */
495 return nlastrip_get_frame_actionclip(strip, cframe, mode);
500 /* Non clipped mapping for strip-time <-> global time
501 * mode = eNlaTime_ConvertModesp[] -> NLATIME_CONVERT_*
503 * Public API method - perform this mapping using the given AnimData block
504 * and perform any necessary sanity checks on the value
506 float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short mode)
511 * - obviously we've got to have some starting data
512 * - when not in tweakmode, the active Action does not have any scaling applied :)
513 * - when in tweakmode, if the no-mapping flag is set, do not map
515 if ((adt == NULL) || (adt->flag & ADT_NLA_EDIT_ON)==0 || (adt->flag & ADT_NLA_EDIT_NOMAP))
518 /* if the active-strip info has been stored already, access this, otherwise look this up
519 * and store for (very probable) future usage
521 if (adt->actstrip == NULL) {
522 NlaTrack *nlt= BKE_nlatrack_find_active(&adt->nla_tracks);
523 adt->actstrip= BKE_nlastrip_find_active(nlt);
525 strip= adt->actstrip;
528 * - in rare cases, we may not be able to find this strip for some reason (internal error)
529 * - for now, if the user has defined a curve to control the time, this correction cannot be performed
532 if ((strip == NULL) || (strip->flag & NLASTRIP_FLAG_USR_TIME))
535 /* perform the correction now... */
536 return nlastrip_get_frame(strip, cframe, mode);
539 /* *************************************************** */
542 /* List of Strips ------------------------------------ */
543 /* (these functions are used for NLA-Tracks and also for nested/meta-strips) */
545 /* Check if there is any space in the given list to add the given strip */
546 short BKE_nlastrips_has_space (ListBase *strips, float start, float end)
551 if ((strips == NULL) || IS_EQF(start, end))
554 puts("BKE_nlastrips_has_space() error... start and end arguments swapped");
555 SWAP(float, start, end);
558 /* loop over NLA strips checking for any overlaps with this area... */
559 for (strip= strips->first; strip; strip= strip->next) {
560 /* if start frame of strip is past the target end-frame, that means that
561 * we've gone past the window we need to check for, so things are fine
563 if (strip->start >= end)
566 /* if the end of the strip is greater than either of the boundaries, the range
567 * must fall within the extents of the strip
569 if ((strip->end > start) || (strip->end > end))
573 /* if we are still here, we haven't encountered any overlapping strips */
577 /* Rearrange the strips in the track so that they are always in order
578 * (usually only needed after a strip has been moved)
580 void BKE_nlastrips_sort_strips (ListBase *strips)
582 ListBase tmp = {NULL, NULL};
583 NlaStrip *strip, *sstrip, *stripn;
586 if ELEM(NULL, strips, strips->first)
589 /* we simply perform insertion sort on this list, since it is assumed that per track,
590 * there are only likely to be at most 5-10 strips
592 for (strip= strips->first; strip; strip= stripn) {
597 /* remove this strip from the list, and add it to the new list, searching from the end of
598 * the list, assuming that the lists are in order
600 BLI_remlink(strips, strip);
602 for (sstrip= tmp.last; sstrip; sstrip= sstrip->prev) {
603 /* check if add after */
604 if (sstrip->end <= strip->start) {
605 BLI_insertlinkafter(&tmp, sstrip, strip);
611 /* add before first? */
613 BLI_addhead(&tmp, strip);
616 /* reassign the start and end points of the strips */
617 strips->first= tmp.first;
618 strips->last= tmp.last;
621 /* Add the given NLA-Strip to the given list of strips, assuming that it
622 * isn't currently a member of another list
624 short BKE_nlastrips_add_strip (ListBase *strips, NlaStrip *strip)
630 if ELEM(NULL, strips, strip)
633 /* check if any space to add */
634 if (BKE_nlastrips_has_space(strips, strip->start, strip->end)==0)
637 /* find the right place to add the strip to the nominated track */
638 for (ns= strips->first; ns; ns= ns->next) {
639 /* if current strip occurs after the new strip, add it before */
640 if (ns->start >= strip->end) {
641 BLI_insertlinkbefore(strips, ns, strip);
647 /* just add to the end of the list of the strips then... */
648 BLI_addtail(strips, strip);
656 /* Meta-Strips ------------------------------------ */
658 /* Convert 'islands' (i.e. continuous string of) selected strips to be
659 * contained within 'Meta-Strips' which act as strips which contain strips.
660 * temp: are the meta-strips to be created 'temporary' ones used for transforms?
662 void BKE_nlastrips_make_metas (ListBase *strips, short temp)
664 NlaStrip *mstrip = NULL;
665 NlaStrip *strip, *stripn;
668 if ELEM(NULL, strips, strips->first)
671 /* group all continuous chains of selected strips into meta-strips */
672 for (strip= strips->first; strip; strip= stripn) {
675 if (strip->flag & NLASTRIP_FLAG_SELECT) {
676 /* if there is an existing meta-strip, add this strip to it, otherwise, create a new one */
677 if (mstrip == NULL) {
678 /* add a new meta-strip, and add it before the current strip that it will replace... */
679 mstrip= MEM_callocN(sizeof(NlaStrip), "Meta-NlaStrip");
680 mstrip->type = NLASTRIP_TYPE_META;
681 BLI_insertlinkbefore(strips, strip, mstrip);
684 mstrip->flag = NLASTRIP_FLAG_SELECT;
686 /* set temp flag if appropriate (i.e. for transform-type editing) */
688 mstrip->flag |= NLASTRIP_FLAG_TEMP_META;
690 /* set default repeat/scale values to prevent warnings */
691 mstrip->repeat= mstrip->scale= 1.0f;
693 /* make its start frame be set to the start frame of the current strip */
694 mstrip->start= strip->start;
697 /* remove the selected strips from the track, and add to the meta */
698 BLI_remlink(strips, strip);
699 BLI_addtail(&mstrip->strips, strip);
701 /* expand the meta's dimensions to include the newly added strip- i.e. its last frame */
702 mstrip->end= strip->end;
705 /* current strip wasn't selected, so the end of 'island' of selected strips has been reached,
706 * so stop adding strips to the current meta
713 /* Split a meta-strip into a set of normal strips */
714 void BKE_nlastrips_clear_metastrip (ListBase *strips, NlaStrip *strip)
719 if ELEM(NULL, strips, strip)
722 /* move each one of the meta-strip's children before the meta-strip
723 * in the list of strips after unlinking them from the meta-strip
725 for (cs= strip->strips.first; cs; cs= csn) {
727 BLI_remlink(&strip->strips, cs);
728 BLI_insertlinkbefore(strips, strip, cs);
731 /* free the meta-strip now */
732 free_nlastrip(strips, strip);
735 /* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips
736 * sel: only consider selected meta-strips, otherwise all meta-strips are removed
737 * onlyTemp: only remove the 'temporary' meta-strips used for transforms
739 void BKE_nlastrips_clear_metas (ListBase *strips, short onlySel, short onlyTemp)
741 NlaStrip *strip, *stripn;
744 if ELEM(NULL, strips, strips->first)
747 /* remove meta-strips fitting the criteria of the arguments */
748 for (strip= strips->first; strip; strip= stripn) {
751 /* check if strip is a meta-strip */
752 if (strip->type == NLASTRIP_TYPE_META) {
753 /* if check if selection and 'temporary-only' considerations are met */
754 if ((onlySel==0) || (strip->flag & NLASTRIP_FLAG_SELECT)) {
755 if ((!onlyTemp) || (strip->flag & NLASTRIP_FLAG_TEMP_META)) {
756 BKE_nlastrips_clear_metastrip(strips, strip);
763 /* Add the given NLA-Strip to the given Meta-Strip, assuming that the
764 * strip isn't attached to anyy list of strips
766 short BKE_nlameta_add_strip (NlaStrip *mstrip, NlaStrip *strip)
769 if ELEM(NULL, mstrip, strip)
772 /* firstly, check if the meta-strip has space for this */
773 if (BKE_nlastrips_has_space(&mstrip->strips, strip->start, strip->end) == 0)
776 /* check if this would need to be added to the ends of the meta,
777 * and subsequently, if the neighbouring strips allow us enough room
779 if (strip->start < mstrip->start) {
780 /* check if strip to the left (if it exists) ends before the
781 * start of the strip we're trying to add
783 if ((mstrip->prev == NULL) || (mstrip->prev->end <= strip->start)) {
784 /* add strip to start of meta's list, and expand dimensions */
785 BLI_addhead(&mstrip->strips, strip);
786 mstrip->start= strip->start;
790 else /* failed... no room before */
793 else if (strip->end > mstrip->end) {
794 /* check if strip to the right (if it exists) starts before the
795 * end of the strip we're trying to add
797 if ((mstrip->next == NULL) || (mstrip->next->start >= strip->end)) {
798 /* add strip to end of meta's list, and expand dimensions */
799 BLI_addtail(&mstrip->strips, strip);
800 mstrip->end= strip->end;
804 else /* failed... no room after */
808 /* just try to add to the meta-strip (no dimension changes needed) */
809 return BKE_nlastrips_add_strip(&mstrip->strips, strip);
813 /* Adjust the settings of NLA-Strips contained within a Meta-Strip (recursively),
814 * until the Meta-Strips children all fit within the Meta-Strip's new dimensions
816 void BKE_nlameta_flush_transforms (NlaStrip *mstrip)
819 float oStart, oEnd, offset;
821 short scaleChanged= 0;
825 * - strip must be a meta-strip with some contents
827 if ELEM(NULL, mstrip, mstrip->strips.first)
829 if (mstrip->type != NLASTRIP_TYPE_META)
832 /* get the original start/end points, and calculate the start-frame offset
833 * - these are simply the start/end frames of the child strips,
834 * since we assume they weren't transformed yet
836 oStart= ((NlaStrip *)mstrip->strips.first)->start;
837 oEnd= ((NlaStrip *)mstrip->strips.last)->end;
838 offset= mstrip->start - oStart;
841 * don't flush if nothing changed yet
842 * TODO: maybe we need a flag to say always flush?
844 if (IS_EQF(oStart, mstrip->start) && IS_EQF(oEnd, mstrip->end))
847 /* check if scale changed */
848 oLen = oEnd - oStart;
849 nLen = mstrip->end - mstrip->start;
850 if (IS_EQF(nLen, oLen) == 0)
853 /* for each child-strip, calculate new start/end points based on this new info */
854 for (strip= mstrip->strips.first; strip; strip= strip->next) {
857 float p1, p2, nStart, nEnd;
859 /* compute positions of endpoints relative to old extents of strip */
860 p1= (strip->start - oStart) / oLen;
861 p2= (strip->end - oStart) / oLen;
863 /* compute the new strip endpoints using the proportions */
864 nStart= (p1 * nLen) + mstrip->start;
865 nEnd= (p2 * nLen) + mstrip->start;
867 /* firstly, apply the new positions manually, then apply using RNA
868 * - first time is to make sure no truncation errors from one endpoint not being
870 * - second time is to make sure scale is computed properly...
872 strip->start= nStart;
875 RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &ptr);
876 RNA_float_set(&ptr, "frame_start", nStart);
877 RNA_float_set(&ptr, "frame_end", nEnd);
880 /* just apply the changes in offset to both ends of the strip */
881 strip->start += offset;
882 strip->end += offset;
885 /* finally, make sure the strip's children (if it is a meta-itself), get updated */
886 BKE_nlameta_flush_transforms(strip);
890 /* NLA-Tracks ---------------------------------------- */
892 /* Find the active NLA-track for the given stack */
893 NlaTrack *BKE_nlatrack_find_active (ListBase *tracks)
898 if ELEM(NULL, tracks, tracks->first)
901 /* try to find the first active track */
902 for (nlt= tracks->first; nlt; nlt= nlt->next) {
903 if (nlt->flag & NLATRACK_ACTIVE)
911 /* Toggle the 'solo' setting for the given NLA-track, making sure that it is the only one
912 * that has this status in its AnimData block.
914 void BKE_nlatrack_solo_toggle (AnimData *adt, NlaTrack *nlt)
919 if ELEM(NULL, adt, adt->nla_tracks.first)
922 /* firstly, make sure 'solo' flag for all tracks is disabled */
923 for (nt= adt->nla_tracks.first; nt; nt= nt->next) {
925 nt->flag &= ~NLATRACK_SOLO;
928 /* now, enable 'solo' for the given track if appropriate */
930 /* toggle solo status */
931 nlt->flag ^= NLATRACK_SOLO;
933 /* set or clear solo-status on AnimData */
934 if (nlt->flag & NLATRACK_SOLO)
935 adt->flag |= ADT_NLA_SOLO_TRACK;
937 adt->flag &= ~ADT_NLA_SOLO_TRACK;
940 adt->flag &= ~ADT_NLA_SOLO_TRACK;
943 /* Make the given NLA-track the active one for the given stack. If no track is provided,
944 * this function can be used to simply deactivate all the NLA tracks in the given stack too.
946 void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a)
951 if ELEM(NULL, tracks, tracks->first)
954 /* deactive all the rest */
955 for (nlt= tracks->first; nlt; nlt= nlt->next)
956 nlt->flag &= ~NLATRACK_ACTIVE;
958 /* set the given one as the active one */
960 nlt_a->flag |= NLATRACK_ACTIVE;
963 /* Check if there is any space in the given track to add a strip of the given length */
964 short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end)
968 * - track must be editable
969 * - bounds cannot be equal (0-length is nasty)
971 if ((nlt == NULL) || (nlt->flag & NLATRACK_PROTECTED) || IS_EQF(start, end))
975 puts("BKE_nlatrack_has_space() error... start and end arguments swapped");
976 SWAP(float, start, end);
979 /* check if there's any space left in the track for a strip of the given length */
980 return BKE_nlastrips_has_space(&nlt->strips, start, end);
983 /* Rearrange the strips in the track so that they are always in order
984 * (usually only needed after a strip has been moved)
986 void BKE_nlatrack_sort_strips (NlaTrack *nlt)
989 if ELEM(NULL, nlt, nlt->strips.first)
992 /* sort the strips with a more generic function */
993 BKE_nlastrips_sort_strips(&nlt->strips);
996 /* Add the given NLA-Strip to the given NLA-Track, assuming that it
997 * isn't currently attached to another one
999 short BKE_nlatrack_add_strip (NlaTrack *nlt, NlaStrip *strip)
1002 if ELEM(NULL, nlt, strip)
1005 /* try to add the strip to the track using a more generic function */
1006 return BKE_nlastrips_add_strip(&nlt->strips, strip);
1009 /* Get the extents of the given NLA-Track including gaps between strips,
1010 * returning whether this succeeded or not
1012 short BKE_nlatrack_get_bounds (NlaTrack *nlt, float bounds[2])
1016 /* initialise bounds */
1018 bounds[0] = bounds[1] = 0.0f;
1023 if ELEM(NULL, nlt, nlt->strips.first)
1026 /* lower bound is first strip's start frame */
1027 strip = nlt->strips.first;
1028 bounds[0] = strip->start;
1030 /* upper bound is last strip's end frame */
1031 strip = nlt->strips.last;
1032 bounds[1] = strip->end;
1038 /* NLA Strips -------------------------------------- */
1040 /* Find the active NLA-strip within the given track */
1041 NlaStrip *BKE_nlastrip_find_active (NlaTrack *nlt)
1046 if ELEM(NULL, nlt, nlt->strips.first)
1049 /* try to find the first active strip */
1050 for (strip= nlt->strips.first; strip; strip= strip->next) {
1051 if (strip->flag & NLASTRIP_FLAG_ACTIVE)
1059 /* Make the given NLA-Strip the active one within the given block */
1060 void BKE_nlastrip_set_active (AnimData *adt, NlaStrip *strip)
1069 /* loop over tracks, deactivating*/
1070 for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1071 for (nls= nlt->strips.first; nls; nls= nls->next) {
1073 nls->flag &= ~NLASTRIP_FLAG_ACTIVE;
1075 nls->flag |= NLASTRIP_FLAG_ACTIVE;
1081 /* Does the given NLA-strip fall within the given bounds (times)? */
1082 short BKE_nlastrip_within_bounds (NlaStrip *strip, float min, float max)
1084 const float stripLen= (strip) ? strip->end - strip->start : 0.0f;
1085 const float boundsLen= (float)fabs(max - min);
1088 if ((strip == NULL) || IS_EQF(stripLen, 0.0f) || IS_EQF(boundsLen, 0.0f))
1091 /* only ok if at least part of the strip is within the bounding window
1092 * - first 2 cases cover when the strip length is less than the bounding area
1093 * - second 2 cases cover when the strip length is greater than the bounding area
1095 if ( (stripLen < boundsLen) &&
1096 !(IN_RANGE(strip->start, min, max) ||
1097 IN_RANGE(strip->end, min, max)) )
1101 if ( (stripLen > boundsLen) &&
1102 !(IN_RANGE(min, strip->start, strip->end) ||
1103 IN_RANGE(max, strip->start, strip->end)) )
1112 /* Recalculate the start and end frames for the current strip, after changing
1113 * the extents of the action or the mapping (repeats or scale factor) info
1115 void BKE_nlastrip_recalculate_bounds (NlaStrip *strip)
1117 float actlen, mapping;
1120 * - must have a strip
1121 * - can only be done for action clips
1123 if ((strip == NULL) || (strip->type != NLASTRIP_TYPE_CLIP))
1126 /* calculate new length factors */
1127 actlen= strip->actend - strip->actstart;
1128 if (IS_EQF(actlen, 0.0f)) actlen= 1.0f;
1130 mapping= strip->scale * strip->repeat;
1132 /* adjust endpoint of strip in response to this */
1133 if (IS_EQF(mapping, 0.0f) == 0)
1134 strip->end = (actlen * mapping) + strip->start;
1137 /* Is the given NLA-strip the first one to occur for the given AnimData block */
1138 // TODO: make this an api method if necesary, but need to add prefix first
1139 static short nlastrip_is_first (AnimData *adt, NlaStrip *strip)
1145 if ELEM(NULL, adt, strip)
1148 /* check if strip has any strips before it */
1152 /* check other tracks to see if they have a strip that's earlier */
1153 // TODO: or should we check that the strip's track is also the first?
1154 for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1155 /* only check the first strip, assuming that they're all in order */
1156 ns= nlt->strips.first;
1158 if (ns->start < strip->start)
1163 /* should be first now */
1167 /* Animated Strips ------------------------------------------- */
1169 /* Check if the given NLA-Track has any strips with own F-Curves */
1170 short BKE_nlatrack_has_animated_strips (NlaTrack *nlt)
1175 if ELEM(NULL, nlt, nlt->strips.first)
1178 /* check each strip for F-Curves only (don't care about whether the flags are set) */
1179 for (strip= nlt->strips.first; strip; strip= strip->next) {
1180 if (strip->fcurves.first)
1188 /* Check if given NLA-Tracks have any strips with own F-Curves */
1189 short BKE_nlatracks_have_animated_strips (ListBase *tracks)
1194 if ELEM(NULL, tracks, tracks->first)
1197 /* check each track, stopping on the first hit */
1198 for (nlt= tracks->first; nlt; nlt= nlt->next) {
1199 if (BKE_nlatrack_has_animated_strips(nlt))
1207 /* Validate the NLA-Strips 'control' F-Curves based on the flags set*/
1208 void BKE_nlastrip_validate_fcurves (NlaStrip *strip)
1216 /* if controlling influence... */
1217 if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
1218 /* try to get F-Curve */
1219 fcu= list_find_fcurve(&strip->fcurves, "influence", 0);
1221 /* add one if not found */
1223 /* make new F-Curve */
1224 fcu= MEM_callocN(sizeof(FCurve), "NlaStrip FCurve");
1225 BLI_addtail(&strip->fcurves, fcu);
1227 /* set default flags */
1228 fcu->flag = (FCURVE_VISIBLE|FCURVE_SELECTED);
1230 /* store path - make copy, and store that */
1231 fcu->rna_path= BLI_strdupn("influence", 9);
1233 // TODO: insert a few keyframes to ensure default behaviour?
1237 /* if controlling time... */
1238 if (strip->flag & NLASTRIP_FLAG_USR_TIME) {
1239 /* try to get F-Curve */
1240 fcu= list_find_fcurve(&strip->fcurves, "strip_time", 0);
1242 /* add one if not found */
1244 /* make new F-Curve */
1245 fcu= MEM_callocN(sizeof(FCurve), "NlaStrip FCurve");
1246 BLI_addtail(&strip->fcurves, fcu);
1248 /* set default flags */
1249 fcu->flag = (FCURVE_VISIBLE|FCURVE_SELECTED);
1251 /* store path - make copy, and store that */
1252 fcu->rna_path= BLI_strdupn("strip_time", 10);
1254 // TODO: insert a few keyframes to ensure default behaviour?
1259 /* Sanity Validation ------------------------------------ */
1261 static int nla_editbone_name_check(void *arg, const char *name)
1263 return BLI_ghash_haskey((GHash *)arg, (void *)name);
1266 /* Find (and set) a unique name for a strip from the whole AnimData block
1267 * Uses a similar method to the BLI method, but is implemented differently
1268 * as we need to ensure that the name is unique over several lists of tracks,
1269 * not just a single track.
1271 void BKE_nlastrip_validate_name (AnimData *adt, NlaStrip *strip)
1278 if ELEM(NULL, adt, strip)
1281 /* give strip a default name if none already */
1282 if (strip->name[0]==0) {
1283 switch (strip->type) {
1284 case NLASTRIP_TYPE_CLIP: /* act-clip */
1285 sprintf(strip->name, "%s", (strip->act)?(strip->act->id.name+2):("<No Action>"));
1287 case NLASTRIP_TYPE_TRANSITION: /* transition */
1288 sprintf(strip->name, "Transition");
1290 case NLASTRIP_TYPE_META: /* meta */
1291 sprintf(strip->name, "Meta");
1294 sprintf(strip->name, "NLA Strip");
1299 /* build a hash-table of all the strips in the tracks
1300 * - this is easier than iterating over all the tracks+strips hierarchy everytime
1301 * (and probably faster)
1303 gh= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "nlastrip_validate_name gh");
1305 for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1306 for (tstrip= nlt->strips.first; tstrip; tstrip= tstrip->next) {
1307 /* don't add the strip of interest */
1308 if (tstrip == strip)
1311 /* use the name of the strip as the key, and the strip as the value, since we're mostly interested in the keys */
1312 BLI_ghash_insert(gh, tstrip->name, tstrip);
1316 /* if the hash-table has a match for this name, try other names...
1317 * - in an extreme case, it might not be able to find a name, but then everything else in Blender would fail too :)
1319 BLI_uniquename_cb(nla_editbone_name_check, (void *)gh, "NlaStrip", '.', strip->name, sizeof(strip->name));
1321 /* free the hash... */
1322 BLI_ghash_free(gh, NULL, NULL);
1327 /* Get strips which overlap the given one at the start/end of its range
1328 * - strip: strip that we're finding overlaps for
1329 * - track: nla-track that the overlapping strips should be found from
1330 * - start, end: frames for the offending endpoints
1332 static void nlastrip_get_endpoint_overlaps (NlaStrip *strip, NlaTrack *track, float **start, float **end)
1336 /* find strips that overlap over the start/end of the given strip,
1337 * but which don't cover the entire length
1339 // TODO: this scheme could get quite slow for doing this on many strips...
1340 for (nls= track->strips.first; nls; nls= nls->next) {
1341 /* check if strip overlaps (extends over or exactly on) the entire range of the strip we're validating */
1342 if ((nls->start <= strip->start) && (nls->end >= strip->end)) {
1348 /* check if strip doesn't even occur anywhere near... */
1349 if (nls->end < strip->start)
1350 continue; /* skip checking this strip... not worthy of mention */
1351 if (nls->start > strip->end)
1352 return; /* the range we're after has already passed */
1354 /* if this strip is not part of an island of continuous strips, it can be used
1355 * - this check needs to be done for each end of the strip we try and use...
1357 if ((nls->next == NULL) || IS_EQF(nls->next->start, nls->end)==0) {
1358 if ((nls->end > strip->start) && (nls->end < strip->end))
1361 if ((nls->prev == NULL) || IS_EQF(nls->prev->end, nls->start)==0) {
1362 if ((nls->start < strip->end) && (nls->start > strip->start))
1368 /* Determine auto-blending for the given strip */
1369 static void BKE_nlastrip_validate_autoblends (NlaTrack *nlt, NlaStrip *nls)
1371 float *ps=NULL, *pe=NULL;
1372 float *ns=NULL, *ne=NULL;
1375 if ELEM(NULL, nls, nlt)
1377 if ((nlt->prev == NULL) && (nlt->next == NULL))
1379 if ((nls->flag & NLASTRIP_FLAG_AUTO_BLENDS)==0)
1382 /* get test ranges */
1384 nlastrip_get_endpoint_overlaps(nls, nlt->prev, &ps, &pe);
1386 nlastrip_get_endpoint_overlaps(nls, nlt->next, &ns, &ne);
1388 /* set overlaps for this strip
1389 * - don't use the values obtained though if the end in question
1390 * is directly followed/preceeded by another strip, forming an
1391 * 'island' of continuous strips
1393 if ( (ps || ns) && ((nls->prev == NULL) || IS_EQF(nls->prev->end, nls->start)==0) )
1395 /* start overlaps - pick the largest overlap */
1396 if ( ((ps && ns) && (*ps > *ns)) || (ps) )
1397 nls->blendin= *ps - nls->start;
1399 nls->blendin= *ns - nls->start;
1401 else /* no overlap allowed/needed */
1404 if ( (pe || ne) && ((nls->next == NULL) || IS_EQF(nls->next->start, nls->end)==0) )
1406 /* end overlaps - pick the largest overlap */
1407 if ( ((pe && ne) && (*pe > *ne)) || (pe) )
1408 nls->blendout= nls->end - *pe;
1410 nls->blendout= nls->end - *ne;
1412 else /* no overlap allowed/needed */
1413 nls->blendout= 0.0f;
1416 /* Ensure that auto-blending and other settings are set correctly */
1417 void BKE_nla_validate_state (AnimData *adt)
1419 NlaStrip *strip, *fstrip=NULL;
1423 if ELEM(NULL, adt, adt->nla_tracks.first)
1426 /* adjust blending values for auto-blending, and also do an initial pass to find the earliest strip */
1427 for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1428 for (strip= nlt->strips.first; strip; strip= strip->next) {
1429 /* auto-blending first */
1430 BKE_nlastrip_validate_autoblends(nlt, strip);
1432 /* extend mode - find first strip */
1433 if ((fstrip == NULL) || (strip->start < fstrip->start))
1438 /* second pass over the strips to adjust the extend-mode to fix any problems */
1439 for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1440 for (strip= nlt->strips.first; strip; strip= strip->next) {
1441 /* apart from 'nothing' option which user has to explicitly choose, we don't really know if
1442 * we should be overwriting the extend setting (but assume that's what the user wanted)
1444 // TODO: 1 solution is to tie this in with auto-blending...
1445 if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
1446 if (strip == fstrip)
1447 strip->extendmode= NLASTRIP_EXTEND_HOLD;
1449 strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD;
1455 /* Core Tools ------------------------------------------- */
1457 /* For the given AnimData block, add the active action to the NLA
1458 * stack (i.e. 'push-down' action). The UI should only allow this
1459 * for normal editing only (i.e. not in editmode for some strip's action),
1460 * so no checks for this are performed.
1462 // TODO: maybe we should have checks for this too...
1463 void BKE_nla_action_pushdown (AnimData *adt)
1468 // TODO: need to report the error for this
1469 if ELEM(NULL, adt, adt->action)
1472 /* if the action is empty, we also shouldn't try to add to stack,
1473 * as that will cause us grief down the track
1475 // TODO: what about modifiers?
1476 if (action_has_motion(adt->action) == 0) {
1477 printf("BKE_nla_action_pushdown(): action has no data \n");
1481 /* add a new NLA strip to the track, which references the active action */
1482 strip= add_nlastrip_to_stack(adt, adt->action);
1484 /* do other necessary work on strip */
1486 /* clear reference to action now that we've pushed it onto the stack */
1487 id_us_min(&adt->action->id);
1490 /* if the strip is the first one in the track it lives in, check if there
1491 * are strips in any other tracks that may be before this, and set the extend
1494 if (nlastrip_is_first(adt, strip) == 0) {
1495 /* not first, so extend mode can only be NLASTRIP_EXTEND_HOLD_FORWARD not NLASTRIP_EXTEND_HOLD,
1496 * so that it doesn't override strips in previous tracks
1498 // FIXME: this needs to be more automated, since user can rearrange strips
1499 strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD;
1502 /* make strip the active one... */
1503 BKE_nlastrip_set_active(adt, strip);
1508 /* Find the active strip + track combo, and set them up as the tweaking track,
1509 * and return if successful or not.
1511 short BKE_nla_tweakmode_enter (AnimData *adt)
1513 NlaTrack *nlt, *activeTrack=NULL;
1514 NlaStrip *strip, *activeStrip=NULL;
1516 /* verify that data is valid */
1517 if ELEM(NULL, adt, adt->nla_tracks.first)
1520 /* if block is already in tweakmode, just leave, but we should report
1521 * that this block is in tweakmode (as our returncode)
1523 if (adt->flag & ADT_NLA_EDIT_ON)
1526 /* go over the tracks, finding the active one, and its active strip
1527 * - if we cannot find both, then there's nothing to do
1529 for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1530 /* check if active */
1531 if (nlt->flag & NLATRACK_ACTIVE) {
1532 /* store reference to this active track */
1535 /* now try to find active strip */
1536 activeStrip= BKE_nlastrip_find_active(nlt);
1540 if ELEM3(NULL, activeTrack, activeStrip, activeStrip->act) {
1541 if (G.f & G_DEBUG) {
1542 printf("NLA tweakmode enter - neither active requirement found \n");
1543 printf("\tactiveTrack = %p, activeStrip = %p \n", (void *)activeTrack, (void *)activeStrip);
1548 /* go over all the tracks up to the active one, tagging each strip that uses the same
1549 * action as the active strip, but leaving everything else alone
1551 for (nlt= activeTrack->prev; nlt; nlt= nlt->prev) {
1552 for (strip= nlt->strips.first; strip; strip= strip->next) {
1553 if (strip->act == activeStrip->act)
1554 strip->flag |= NLASTRIP_FLAG_TWEAKUSER;
1556 strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
1561 /* go over all the tracks after AND INCLUDING the active one, tagging them as being disabled
1562 * - the active track needs to also be tagged, otherwise, it'll overlap with the tweaks going on
1564 for (nlt= activeTrack; nlt; nlt= nlt->next)
1565 nlt->flag |= NLATRACK_DISABLED;
1567 /* handle AnimData level changes:
1568 * - 'real' active action to temp storage (no need to change user-counts)
1569 * - action of active strip set to be the 'active action', and have its usercount incremented
1570 * - editing-flag for this AnimData block should also get turned on (for more efficient restoring)
1571 * - take note of the active strip for mapping-correction of keyframes in the action being edited
1573 adt->tmpact= adt->action;
1574 adt->action= activeStrip->act;
1575 adt->actstrip= activeStrip;
1576 id_us_plus(&activeStrip->act->id);
1577 adt->flag |= ADT_NLA_EDIT_ON;
1583 /* Exit tweakmode for this AnimData block */
1584 void BKE_nla_tweakmode_exit (AnimData *adt)
1589 /* verify that data is valid */
1590 if ELEM(NULL, adt, adt->nla_tracks.first)
1593 /* hopefully the flag is correct - skip if not on */
1594 if ((adt->flag & ADT_NLA_EDIT_ON) == 0)
1597 // TODO: need to sync the user-strip with the new state of the action!
1599 /* for all Tracks, clear the 'disabled' flag
1600 * for all Strips, clear the 'tweak-user' flag
1602 for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1603 nlt->flag &= ~NLATRACK_DISABLED;
1605 for (strip= nlt->strips.first; strip; strip= strip->next)
1606 strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
1609 /* handle AnimData level changes:
1610 * - 'temporary' active action needs its usercount decreased, since we're removing this reference
1611 * - 'real' active action is restored from storage
1612 * - storage pointer gets cleared (to avoid having bad notes hanging around)
1613 * - editing-flag for this AnimData block should also get turned off
1614 * - clear pointer to active strip
1616 if (adt->action) adt->action->id.us--;
1617 adt->action= adt->tmpact;
1619 adt->actstrip= NULL;
1620 adt->flag &= ~ADT_NLA_EDIT_ON;
1623 /* Baking Tools ------------------------------------------- */
1625 static void BKE_nla_bake (Scene *scene, ID *UNUSED(id), AnimData *adt, int UNUSED(flag))
1628 /* verify that data is valid
1629 * 1) Scene and AnimData must be provided
1630 * 2) there must be tracks to merge...
1632 if ELEM3(NULL, scene, adt, adt->nla_tracks.first)
1635 /* if animdata currently has an action, 'push down' this onto the stack first */
1637 BKE_nla_action_pushdown(adt);
1639 /* get range of motion to bake, and the channels involved... */
1641 /* temporarily mute the action, and start keying to it */
1643 /* start keying... */
1645 /* unmute the action */
1648 /* *************************************************** */