814f0715d11f8015093667978bcc10032020e90d
[blender.git] / source / blender / blenkernel / intern / nla.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Joshua Leung (full recode)
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/nla.c
29  *  \ingroup bke
30  */
31
32
33 #include <stdlib.h>
34 #include <stddef.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <math.h>
38 #include <float.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "BLI_utildefines.h"
43 #include "BLI_path_util.h"
44 #include "BLI_listbase.h"
45 #include "BLI_string.h"
46 #include "BLI_ghash.h"
47
48 #include "DNA_anim_types.h"
49 #include "DNA_scene_types.h"
50 #include "DNA_sound_types.h"
51 #include "DNA_speaker_types.h"
52
53 #include "BKE_action.h"
54 #include "BKE_fcurve.h"
55 #include "BKE_nla.h"
56 #include "BKE_global.h"
57 #include "BKE_library.h"
58
59 #ifdef WITH_AUDASPACE
60 #  include "AUD_C-API.h"
61 #endif
62
63 #include "RNA_access.h"
64 #include "nla_private.h"
65
66
67
68 /* *************************************************** */
69 /* Data Management */
70
71 /* Freeing ------------------------------------------- */
72
73 /* Remove the given NLA strip from the NLA track it occupies, free the strip's data,
74  * and the strip itself. 
75  */
76 void free_nlastrip (ListBase *strips, NlaStrip *strip)
77 {
78         NlaStrip *cs, *csn;
79         
80         /* sanity checks */
81         if (strip == NULL)
82                 return;
83                 
84         /* free child-strips */
85         for (cs= strip->strips.first; cs; cs= csn) {
86                 csn= cs->next;
87                 free_nlastrip(&strip->strips, cs);
88         }
89                 
90         /* remove reference to action */
91         if (strip->act)
92                 id_us_min(&strip->act->id);
93                 
94         /* free remapping info */
95         //if (strip->remap)
96         //      BKE_animremap_free();
97         
98         /* free own F-Curves */
99         free_fcurves(&strip->fcurves);
100         
101         /* free own F-Modifiers */
102         free_fmodifiers(&strip->modifiers);
103         
104         /* free the strip itself */
105         if (strips)
106                 BLI_freelinkN(strips, strip);
107         else
108                 MEM_freeN(strip);
109 }
110
111 /* Remove the given NLA track from the set of NLA tracks, free the track's data,
112  * and the track itself.
113  */
114 void free_nlatrack (ListBase *tracks, NlaTrack *nlt)
115 {
116         NlaStrip *strip, *stripn;
117         
118         /* sanity checks */
119         if (nlt == NULL)
120                 return;
121                 
122         /* free strips */
123         for (strip= nlt->strips.first; strip; strip= stripn) {
124                 stripn= strip->next;
125                 free_nlastrip(&nlt->strips, strip);
126         }
127         
128         /* free NLA track itself now */
129         if (tracks)
130                 BLI_freelinkN(tracks, nlt);
131         else
132                 MEM_freeN(nlt);
133 }
134
135 /* Free the elements of type NLA Tracks provided in the given list, but do not free
136  * the list itself since that is not free-standing
137  */
138 void free_nladata (ListBase *tracks)
139 {
140         NlaTrack *nlt, *nltn;
141         
142         /* sanity checks */
143         if ELEM(NULL, tracks, tracks->first)
144                 return;
145                 
146         /* free tracks one by one */
147         for (nlt= tracks->first; nlt; nlt= nltn) {
148                 nltn= nlt->next;
149                 free_nlatrack(tracks, nlt);
150         }
151         
152         /* clear the list's pointers to be safe */
153         tracks->first= tracks->last= NULL;
154 }
155
156 /* Copying ------------------------------------------- */
157
158 /* Copy NLA strip */
159 NlaStrip *copy_nlastrip (NlaStrip *strip)
160 {
161         NlaStrip *strip_d;
162         NlaStrip *cs, *cs_d;
163         
164         /* sanity check */
165         if (strip == NULL)
166                 return NULL;
167                 
168         /* make a copy */
169         strip_d= MEM_dupallocN(strip);
170         strip_d->next= strip_d->prev= NULL;
171         
172         /* increase user-count of action */
173         if (strip_d->act)
174                 id_us_plus(&strip_d->act->id);
175                 
176         /* copy F-Curves and modifiers */
177         copy_fcurves(&strip_d->fcurves, &strip->fcurves);
178         copy_fmodifiers(&strip_d->modifiers, &strip->modifiers);
179         
180         /* make a copy of all the child-strips, one at a time */
181         strip_d->strips.first= strip_d->strips.last= NULL;
182         
183         for (cs= strip->strips.first; cs; cs= cs->next) {
184                 cs_d= copy_nlastrip(cs);
185                 BLI_addtail(&strip_d->strips, cs_d);
186         }
187         
188         /* return the strip */
189         return strip_d;
190 }
191
192 /* Copy NLA Track */
193 NlaTrack *copy_nlatrack (NlaTrack *nlt)
194 {
195         NlaStrip *strip, *strip_d;
196         NlaTrack *nlt_d;
197         
198         /* sanity check */
199         if (nlt == NULL)
200                 return NULL;
201                 
202         /* make a copy */
203         nlt_d= MEM_dupallocN(nlt);
204         nlt_d->next= nlt_d->prev= NULL;
205         
206         /* make a copy of all the strips, one at a time */
207         nlt_d->strips.first= nlt_d->strips.last= NULL;
208         
209         for (strip= nlt->strips.first; strip; strip= strip->next) {
210                 strip_d= copy_nlastrip(strip);
211                 BLI_addtail(&nlt_d->strips, strip_d);
212         }
213         
214         /* return the copy */
215         return nlt_d;
216 }
217
218 /* Copy all NLA data */
219 void copy_nladata (ListBase *dst, ListBase *src)
220 {
221         NlaTrack *nlt, *nlt_d;
222         
223         /* sanity checks */
224         if ELEM(NULL, dst, src)
225                 return;
226                 
227         /* clear out the destination list first for precautions... */
228         dst->first= dst->last= NULL;
229                 
230         /* copy each NLA-track, one at a time */
231         for (nlt= src->first; nlt; nlt= nlt->next) {
232                 /* make a copy, and add the copy to the destination list */
233                 nlt_d= copy_nlatrack(nlt);
234                 BLI_addtail(dst, nlt_d);
235         }
236 }
237
238 /* Adding ------------------------------------------- */
239
240 /* Add a NLA Track to the given AnimData 
241  *      - prev: NLA-Track to add the new one after
242  */
243 NlaTrack *add_nlatrack (AnimData *adt, NlaTrack *prev)
244 {
245         NlaTrack *nlt;
246         
247         /* sanity checks */
248         if (adt == NULL)
249                 return NULL;
250                 
251         /* allocate new track */
252         nlt= MEM_callocN(sizeof(NlaTrack), "NlaTrack");
253         
254         /* set settings requiring the track to not be part of the stack yet */
255         nlt->flag = NLATRACK_SELECTED;
256         nlt->index= BLI_countlist(&adt->nla_tracks);
257         
258         /* add track to stack, and make it the active one */
259         if (prev)
260                 BLI_insertlinkafter(&adt->nla_tracks, prev, nlt);
261         else
262                 BLI_addtail(&adt->nla_tracks, nlt);
263         BKE_nlatrack_set_active(&adt->nla_tracks, nlt);
264         
265         /* must have unique name, but we need to seed this */
266         strcpy(nlt->name, "NlaTrack");
267         BLI_uniquename(&adt->nla_tracks, nlt, "NlaTrack", '.', offsetof(NlaTrack, name), sizeof(nlt->name));
268         
269         /* return the new track */
270         return nlt;
271 }
272
273 /* Add a NLA Strip referencing the given Action */
274 NlaStrip *add_nlastrip (bAction *act)
275 {
276         NlaStrip *strip;
277         
278         /* sanity checks */
279         if (act == NULL)
280                 return NULL;
281                 
282         /* allocate new strip */
283         strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
284         
285         /* generic settings 
286          *      - selected flag to highlight this to the user
287          *      - auto-blends to ensure that blend in/out values are automatically 
288          *        determined by overlaps of strips
289          *      - (XXX) synchronization of strip-length in accordance with changes to action-length
290          *        is not done though, since this should only really happens in editmode for strips now
291          *        though this decision is still subject to further review...
292          */
293         strip->flag = NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_AUTO_BLENDS;
294         
295         /* assign the action reference */
296         strip->act= act;
297         id_us_plus(&act->id);
298         
299         /* determine initial range 
300          *      - strip length cannot be 0... ever...
301          */
302         calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
303         
304         strip->start = strip->actstart;
305         strip->end = (IS_EQF(strip->actstart, strip->actend)) ?  (strip->actstart + 1.0f): (strip->actend);
306         
307         /* strip should be referenced as-is */
308         strip->scale= 1.0f;
309         strip->repeat = 1.0f;
310         
311         /* return the new strip */
312         return strip;
313 }
314
315 /* Add new NLA-strip to the top of the NLA stack - i.e. into the last track if space, or a new one otherwise */
316 NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act)
317 {
318         NlaStrip *strip;
319         NlaTrack *nlt;
320         
321         /* sanity checks */
322         if ELEM(NULL, adt, act)
323                 return NULL;
324         
325         /* create a new NLA strip */
326         strip= add_nlastrip(act);
327         if (strip == NULL)
328                 return NULL;
329         
330         /* firstly try adding strip to last track, but if that fails, add to a new track */
331         if (BKE_nlatrack_add_strip(adt->nla_tracks.last, strip) == 0) {
332                 /* trying to add to the last track failed (no track or no space), 
333                  * so add a new track to the stack, and add to that...
334                  */
335                 nlt= add_nlatrack(adt, NULL);
336                 BKE_nlatrack_add_strip(nlt, strip);
337         }
338         
339         /* automatically name it too */
340         BKE_nlastrip_validate_name(adt, strip);
341         
342         /* returns the strip added */
343         return strip;
344 }
345
346 /* Add a NLA Strip referencing the given speaker's sound */
347 NlaStrip *add_nla_soundstrip (Scene *scene, Speaker *speaker)
348 {
349         NlaStrip *strip = MEM_callocN(sizeof(NlaStrip), "NlaSoundStrip");
350         
351         /* if speaker has a sound, set the strip length to the length of the sound,
352          * otherwise default to length of 10 frames
353          */
354 #ifdef WITH_AUDASPACE
355         if (speaker->sound) 
356         {
357                 AUD_SoundInfo info = AUD_getInfo(speaker->sound->playback_handle);
358                 
359                 strip->end = (float)ceil((double)info.length * FPS);
360         }
361         else 
362 #endif
363         {
364                 strip->end = 10.0f;
365                 /* quiet compiler warnings */
366                 (void)scene;
367                 (void)speaker;
368         }
369         
370         /* general settings */
371         strip->type = NLASTRIP_TYPE_SOUND;
372         
373         strip->flag = NLASTRIP_FLAG_SELECT;
374         strip->extendmode = NLASTRIP_EXTEND_NOTHING; /* nothing to extend... */
375         
376         /* strip should be referenced as-is */
377         strip->scale= 1.0f;
378         strip->repeat = 1.0f;
379         
380         /* return this strip */
381         return strip;
382 }
383
384 /* *************************************************** */
385 /* NLA Evaluation <-> Editing Stuff */
386
387 /* Strip Mapping ------------------------------------- */
388
389 /* non clipped mapping for strip-time <-> global time (for Action-Clips)
390  *      invert = convert action-strip time to global time 
391  */
392 static float nlastrip_get_frame_actionclip (NlaStrip *strip, float cframe, short mode)
393 {
394         float actlength, scale;
395         // float repeat; // UNUSED
396         
397         /* get number of repeats */
398         if (IS_EQF(strip->repeat, 0.0f)) strip->repeat = 1.0f;
399         // repeat = strip->repeat; // UNUSED
400         
401         /* scaling */
402         if (IS_EQF(strip->scale, 0.0f)) strip->scale= 1.0f;
403         scale = fabsf(strip->scale); /* scale must be positive - we've got a special flag for reversing */
404         
405         /* length of referenced action */
406         actlength = strip->actend - strip->actstart;
407         if (IS_EQF(actlength, 0.0f)) actlength = 1.0f;
408         
409         /* reversed = play strip backwards */
410         if (strip->flag & NLASTRIP_FLAG_REVERSE) {
411                 // FIXME: this won't work right with Graph Editor?
412                 if (mode == NLATIME_CONVERT_MAP) {
413                         return strip->end - scale*(cframe - strip->actstart);
414                 }
415                 else if (mode == NLATIME_CONVERT_UNMAP) {
416                         return (strip->end + (strip->actstart * scale - cframe)) / scale;
417                 }
418                 else /* if (mode == NLATIME_CONVERT_EVAL) */{
419                         if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) {
420                                 /* this case prevents the motion snapping back to the first frame at the end of the strip 
421                                  * by catching the case where repeats is a whole number, which means that the end of the strip
422                                  * could also be interpreted as the end of the start of a repeat
423                                  */
424                                 return strip->actstart;
425                         }
426                         else {
427                                 /* - the 'fmod(..., actlength*scale)' is needed to get the repeats working
428                                  * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat
429                                  */
430                                 return strip->actend - fmodf(cframe - strip->start, actlength*scale) / scale;
431                         }
432                 }
433         }
434         else {
435                 if (mode == NLATIME_CONVERT_MAP) {
436                         return strip->start + scale*(cframe - strip->actstart);
437                 }
438                 else if (mode == NLATIME_CONVERT_UNMAP) {
439                         return strip->actstart + (cframe - strip->start) / scale;
440                 }
441                 else /* if (mode == NLATIME_CONVERT_EVAL) */{
442                         if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) {
443                                 /* this case prevents the motion snapping back to the first frame at the end of the strip 
444                                  * by catching the case where repeats is a whole number, which means that the end of the strip
445                                  * could also be interpreted as the end of the start of a repeat
446                                  */
447                                 return strip->actend;
448                         }
449                         else {
450                                 /* - the 'fmod(..., actlength*scale)' is needed to get the repeats working
451                                  * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat
452                                  */
453                                 return strip->actstart + fmodf(cframe - strip->start, actlength*scale) / scale;
454                         }
455                 }
456         }
457 }
458
459 /* non clipped mapping for strip-time <-> global time (for Transitions)
460  *      invert = convert action-strip time to global time 
461  */
462 static float nlastrip_get_frame_transition (NlaStrip *strip, float cframe, short mode)
463 {
464         float length;
465         
466         /* length of strip */
467         length= strip->end - strip->start;
468         
469         /* reversed = play strip backwards */
470         if (strip->flag & NLASTRIP_FLAG_REVERSE) {
471                 if (mode == NLATIME_CONVERT_MAP)
472                         return strip->end - (length * cframe);
473                 else
474                         return (strip->end - cframe) / length;
475         }
476         else {
477                 if (mode == NLATIME_CONVERT_MAP)
478                         return (length * cframe) + strip->start;
479                 else
480                         return (cframe - strip->start) / length;
481         }
482 }
483
484 /* non clipped mapping for strip-time <-> global time
485  *      mode = eNlaTime_ConvertModes[] -> NLATIME_CONVERT_*
486  *
487  * only secure for 'internal' (i.e. within AnimSys evaluation) operations,
488  * but should not be directly relied on for stuff which interacts with editors
489  */
490 float nlastrip_get_frame (NlaStrip *strip, float cframe, short mode)
491 {
492         switch (strip->type) {
493                 case NLASTRIP_TYPE_META: /* meta - for now, does the same as transition (is really just an empty container) */
494                 case NLASTRIP_TYPE_TRANSITION: /* transition */
495                         return nlastrip_get_frame_transition(strip, cframe, mode);
496                 
497                 case NLASTRIP_TYPE_CLIP: /* action-clip (default) */
498                 default:
499                         return nlastrip_get_frame_actionclip(strip, cframe, mode);
500         }       
501 }
502
503
504 /* Non clipped mapping for strip-time <-> global time
505  *      mode = eNlaTime_ConvertModesp[] -> NLATIME_CONVERT_*
506  *
507  * Public API method - perform this mapping using the given AnimData block
508  * and perform any necessary sanity checks on the value
509  */
510 float BKE_nla_tweakedit_remap (AnimData *adt, float cframe, short mode)
511 {
512         NlaStrip *strip;
513         
514         /* sanity checks 
515          *      - obviously we've got to have some starting data
516          *      - when not in tweakmode, the active Action does not have any scaling applied :)
517          *      - when in tweakmode, if the no-mapping flag is set, do not map
518          */
519         if ((adt == NULL) || (adt->flag & ADT_NLA_EDIT_ON)==0 || (adt->flag & ADT_NLA_EDIT_NOMAP))
520                 return cframe;
521                 
522         /* if the active-strip info has been stored already, access this, otherwise look this up
523          * and store for (very probable) future usage
524          */
525         if (adt->actstrip == NULL) {
526                 NlaTrack *nlt= BKE_nlatrack_find_active(&adt->nla_tracks);
527                 adt->actstrip= BKE_nlastrip_find_active(nlt);
528         }
529         strip= adt->actstrip;
530         
531         /* sanity checks 
532          *      - in rare cases, we may not be able to find this strip for some reason (internal error)
533          *      - for now, if the user has defined a curve to control the time, this correction cannot be performed
534          *        reliably...
535          */
536         if ((strip == NULL) || (strip->flag & NLASTRIP_FLAG_USR_TIME))
537                 return cframe;
538                 
539         /* perform the correction now... */
540         return nlastrip_get_frame(strip, cframe, mode);
541 }
542
543 /* *************************************************** */
544 /* NLA API */
545
546 /* List of Strips ------------------------------------ */
547 /* (these functions are used for NLA-Tracks and also for nested/meta-strips) */
548
549 /* Check if there is any space in the given list to add the given strip */
550 short BKE_nlastrips_has_space (ListBase *strips, float start, float end)
551 {
552         NlaStrip *strip;
553         
554         /* sanity checks */
555         if ((strips == NULL) || IS_EQF(start, end))
556                 return 0;
557         if (start > end) {
558                 puts("BKE_nlastrips_has_space() error... start and end arguments swapped");
559                 SWAP(float, start, end);
560         }
561         
562         /* loop over NLA strips checking for any overlaps with this area... */
563         for (strip= strips->first; strip; strip= strip->next) {
564                 /* if start frame of strip is past the target end-frame, that means that
565                  * we've gone past the window we need to check for, so things are fine
566                  */
567                 if (strip->start >= end)
568                         return 1;
569                 
570                 /* if the end of the strip is greater than either of the boundaries, the range
571                  * must fall within the extents of the strip
572                  */
573                 if ((strip->end > start) || (strip->end > end))
574                         return 0;
575         }
576         
577         /* if we are still here, we haven't encountered any overlapping strips */
578         return 1;
579 }
580
581 /* Rearrange the strips in the track so that they are always in order 
582  * (usually only needed after a strip has been moved) 
583  */
584 void BKE_nlastrips_sort_strips (ListBase *strips)
585 {
586         ListBase tmp = {NULL, NULL};
587         NlaStrip *strip, *sstrip, *stripn;
588         
589         /* sanity checks */
590         if ELEM(NULL, strips, strips->first)
591                 return;
592         
593         /* we simply perform insertion sort on this list, since it is assumed that per track,
594          * there are only likely to be at most 5-10 strips
595          */
596         for (strip= strips->first; strip; strip= stripn) {
597                 short not_added = 1;
598                 
599                 stripn= strip->next;
600                 
601                 /* remove this strip from the list, and add it to the new list, searching from the end of 
602                  * the list, assuming that the lists are in order 
603                  */
604                 BLI_remlink(strips, strip);
605                 
606                 for (sstrip= tmp.last; sstrip; sstrip= sstrip->prev) {
607                         /* check if add after */
608                         if (sstrip->end <= strip->start) {
609                                 BLI_insertlinkafter(&tmp, sstrip, strip);
610                                 not_added= 0;
611                                 break;
612                         }
613                 }
614                 
615                 /* add before first? */
616                 if (not_added)
617                         BLI_addhead(&tmp, strip);
618         }
619         
620         /* reassign the start and end points of the strips */
621         strips->first= tmp.first;
622         strips->last= tmp.last;
623 }
624
625 /* Add the given NLA-Strip to the given list of strips, assuming that it 
626  * isn't currently a member of another list
627  */
628 short BKE_nlastrips_add_strip (ListBase *strips, NlaStrip *strip)
629 {
630         NlaStrip *ns;
631         short not_added = 1;
632         
633         /* sanity checks */
634         if ELEM(NULL, strips, strip)
635                 return 0;
636                 
637         /* check if any space to add */
638         if (BKE_nlastrips_has_space(strips, strip->start, strip->end)==0)
639                 return 0;
640         
641         /* find the right place to add the strip to the nominated track */
642         for (ns= strips->first; ns; ns= ns->next) {
643                 /* if current strip occurs after the new strip, add it before */
644                 if (ns->start >= strip->end) {
645                         BLI_insertlinkbefore(strips, ns, strip);
646                         not_added= 0;
647                         break;
648                 }
649         }
650         if (not_added) {
651                 /* just add to the end of the list of the strips then... */
652                 BLI_addtail(strips, strip);
653         }
654         
655         /* added... */
656         return 1;
657 }
658
659
660 /* Meta-Strips ------------------------------------ */
661
662 /* Convert 'islands' (i.e. continuous string of) selected strips to be
663  * contained within 'Meta-Strips' which act as strips which contain strips.
664  *      temp: are the meta-strips to be created 'temporary' ones used for transforms?
665  */
666 void BKE_nlastrips_make_metas (ListBase *strips, short temp)
667 {
668         NlaStrip *mstrip = NULL;
669         NlaStrip *strip, *stripn;
670         
671         /* sanity checks */
672         if ELEM(NULL, strips, strips->first)
673                 return;
674         
675         /* group all continuous chains of selected strips into meta-strips */
676         for (strip= strips->first; strip; strip= stripn) {
677                 stripn= strip->next;
678                 
679                 if (strip->flag & NLASTRIP_FLAG_SELECT) {
680                         /* if there is an existing meta-strip, add this strip to it, otherwise, create a new one */
681                         if (mstrip == NULL) {
682                                 /* add a new meta-strip, and add it before the current strip that it will replace... */
683                                 mstrip= MEM_callocN(sizeof(NlaStrip), "Meta-NlaStrip");
684                                 mstrip->type = NLASTRIP_TYPE_META;
685                                 BLI_insertlinkbefore(strips, strip, mstrip);
686                                 
687                                 /* set flags */
688                                 mstrip->flag = NLASTRIP_FLAG_SELECT;
689                                 
690                                 /* set temp flag if appropriate (i.e. for transform-type editing) */
691                                 if (temp)
692                                         mstrip->flag |= NLASTRIP_FLAG_TEMP_META;
693                                         
694                                 /* set default repeat/scale values to prevent warnings */
695                                 mstrip->repeat= mstrip->scale= 1.0f;
696                                 
697                                 /* make its start frame be set to the start frame of the current strip */
698                                 mstrip->start= strip->start;
699                         }
700                         
701                         /* remove the selected strips from the track, and add to the meta */
702                         BLI_remlink(strips, strip);
703                         BLI_addtail(&mstrip->strips, strip);
704                         
705                         /* expand the meta's dimensions to include the newly added strip- i.e. its last frame */
706                         mstrip->end= strip->end;
707                 }
708                 else {
709                         /* current strip wasn't selected, so the end of 'island' of selected strips has been reached,
710                          * so stop adding strips to the current meta
711                          */
712                         mstrip= NULL;
713                 }
714         }
715 }
716
717 /* Split a meta-strip into a set of normal strips */
718 void BKE_nlastrips_clear_metastrip (ListBase *strips, NlaStrip *strip)
719 {
720         NlaStrip *cs, *csn;
721         
722         /* sanity check */
723         if ELEM(NULL, strips, strip)
724                 return;
725         
726         /* move each one of the meta-strip's children before the meta-strip
727          * in the list of strips after unlinking them from the meta-strip
728          */
729         for (cs= strip->strips.first; cs; cs= csn) {
730                 csn= cs->next;
731                 BLI_remlink(&strip->strips, cs);
732                 BLI_insertlinkbefore(strips, strip, cs);
733         }
734         
735         /* free the meta-strip now */
736         free_nlastrip(strips, strip);
737 }
738
739 /* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips
740  *      sel: only consider selected meta-strips, otherwise all meta-strips are removed
741  *      onlyTemp: only remove the 'temporary' meta-strips used for transforms
742  */
743 void BKE_nlastrips_clear_metas (ListBase *strips, short onlySel, short onlyTemp)
744 {
745         NlaStrip *strip, *stripn;
746         
747         /* sanity checks */
748         if ELEM(NULL, strips, strips->first)
749                 return;
750         
751         /* remove meta-strips fitting the criteria of the arguments */
752         for (strip= strips->first; strip; strip= stripn) {
753                 stripn= strip->next;
754                 
755                 /* check if strip is a meta-strip */
756                 if (strip->type == NLASTRIP_TYPE_META) {
757                         /* if check if selection and 'temporary-only' considerations are met */
758                         if ((onlySel==0) || (strip->flag & NLASTRIP_FLAG_SELECT)) {
759                                 if ((!onlyTemp) || (strip->flag & NLASTRIP_FLAG_TEMP_META)) {
760                                         BKE_nlastrips_clear_metastrip(strips, strip);
761                                 }
762                         }
763                 }
764         }
765 }
766
767 /* Add the given NLA-Strip to the given Meta-Strip, assuming that the
768  * strip isn't attached to anyy list of strips 
769  */
770 short BKE_nlameta_add_strip (NlaStrip *mstrip, NlaStrip *strip)
771 {
772         /* sanity checks */
773         if ELEM(NULL, mstrip, strip)
774                 return 0;
775                 
776         /* firstly, check if the meta-strip has space for this */
777         if (BKE_nlastrips_has_space(&mstrip->strips, strip->start, strip->end) == 0)
778                 return 0;
779                 
780         /* check if this would need to be added to the ends of the meta,
781          * and subsequently, if the neighboring strips allow us enough room
782          */
783         if (strip->start < mstrip->start) {
784                 /* check if strip to the left (if it exists) ends before the 
785                  * start of the strip we're trying to add 
786                  */
787                 if ((mstrip->prev == NULL) || (mstrip->prev->end <= strip->start)) {
788                         /* add strip to start of meta's list, and expand dimensions */
789                         BLI_addhead(&mstrip->strips, strip);
790                         mstrip->start= strip->start;
791                         
792                         return 1;
793                 }
794                 else /* failed... no room before */
795                         return 0;
796         }
797         else if (strip->end > mstrip->end) {
798                 /* check if strip to the right (if it exists) starts before the 
799                  * end of the strip we're trying to add 
800                  */
801                 if ((mstrip->next == NULL) || (mstrip->next->start >= strip->end)) {
802                         /* add strip to end of meta's list, and expand dimensions */
803                         BLI_addtail(&mstrip->strips, strip);
804                         mstrip->end= strip->end;
805                         
806                         return 1;
807                 }
808                 else /* failed... no room after */
809                         return 0;
810         }
811         else {
812                 /* just try to add to the meta-strip (no dimension changes needed) */
813                 return BKE_nlastrips_add_strip(&mstrip->strips, strip);
814         }
815 }
816
817 /* Adjust the settings of NLA-Strips contained within a Meta-Strip (recursively), 
818  * until the Meta-Strips children all fit within the Meta-Strip's new dimensions
819  */
820 void BKE_nlameta_flush_transforms (NlaStrip *mstrip) 
821 {
822         NlaStrip *strip;
823         float oStart, oEnd, offset;
824         float oLen, nLen;
825         short scaleChanged= 0;
826         
827         /* sanity checks 
828          *      - strip must exist
829          *      - strip must be a meta-strip with some contents
830          */
831         if ELEM(NULL, mstrip, mstrip->strips.first)
832                 return;
833         if (mstrip->type != NLASTRIP_TYPE_META)
834                 return;
835                 
836         /* get the original start/end points, and calculate the start-frame offset
837          *      - these are simply the start/end frames of the child strips, 
838          *        since we assume they weren't transformed yet
839          */
840         oStart= ((NlaStrip *)mstrip->strips.first)->start;
841         oEnd= ((NlaStrip *)mstrip->strips.last)->end;
842         offset= mstrip->start - oStart;
843         
844         /* optimization:
845          * don't flush if nothing changed yet
846          *      TODO: maybe we need a flag to say always flush?
847          */
848         if (IS_EQF(oStart, mstrip->start) && IS_EQF(oEnd, mstrip->end))
849                 return;
850         
851         /* check if scale changed */
852         oLen = oEnd - oStart;
853         nLen = mstrip->end - mstrip->start;
854         if (IS_EQF(nLen, oLen) == 0)
855                 scaleChanged= 1;
856         
857         /* for each child-strip, calculate new start/end points based on this new info */
858         for (strip= mstrip->strips.first; strip; strip= strip->next) {
859                 if (scaleChanged) {
860                         float p1, p2;
861                         
862                         /* compute positions of endpoints relative to old extents of strip */
863                         p1= (strip->start - oStart) / oLen;
864                         p2= (strip->end - oStart) / oLen;
865                         
866                         /* apply new strip endpoints using the proportions, then wait for second pass to flush scale properly */
867                         strip->start= (p1 * nLen) + mstrip->start;
868                         strip->end= (p2 * nLen) + mstrip->start;
869                 }
870                 else {
871                         /* just apply the changes in offset to both ends of the strip */
872                         strip->start += offset;
873                         strip->end += offset;
874                 }
875         }
876                 
877         /* apply a second pass over child strips, to finish up unfinished business */
878         for (strip= mstrip->strips.first; strip; strip= strip->next) {
879                 /* only if scale changed, need to perform RNA updates */
880                 if (scaleChanged) {
881                         PointerRNA ptr;
882                         
883                         /* use RNA updates to compute scale properly */
884                         RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &ptr);
885                         
886                         RNA_float_set(&ptr, "frame_start", strip->start);
887                         RNA_float_set(&ptr, "frame_end", strip->end);
888                 }
889                 
890                 /* finally, make sure the strip's children (if it is a meta-itself), get updated */
891                 BKE_nlameta_flush_transforms(strip);
892         }
893 }
894
895 /* NLA-Tracks ---------------------------------------- */
896
897 /* Find the active NLA-track for the given stack */
898 NlaTrack *BKE_nlatrack_find_active (ListBase *tracks)
899 {
900         NlaTrack *nlt;
901         
902         /* sanity check */
903         if ELEM(NULL, tracks, tracks->first)
904                 return NULL;
905                 
906         /* try to find the first active track */
907         for (nlt= tracks->first; nlt; nlt= nlt->next) {
908                 if (nlt->flag & NLATRACK_ACTIVE)
909                         return nlt;
910         }
911         
912         /* none found */
913         return NULL;
914 }
915
916 /* Toggle the 'solo' setting for the given NLA-track, making sure that it is the only one
917  * that has this status in its AnimData block.
918  */
919 void BKE_nlatrack_solo_toggle (AnimData *adt, NlaTrack *nlt)
920 {
921         NlaTrack *nt;
922         
923         /* sanity check */
924         if ELEM(NULL, adt, adt->nla_tracks.first)
925                 return;
926                 
927         /* firstly, make sure 'solo' flag for all tracks is disabled */
928         for (nt= adt->nla_tracks.first; nt; nt= nt->next) {
929                 if (nt != nlt)
930                         nt->flag &= ~NLATRACK_SOLO;
931         }
932                 
933         /* now, enable 'solo' for the given track if appropriate */
934         if (nlt) {
935                 /* toggle solo status */
936                 nlt->flag ^= NLATRACK_SOLO;
937                 
938                 /* set or clear solo-status on AnimData */
939                 if (nlt->flag & NLATRACK_SOLO)
940                         adt->flag |= ADT_NLA_SOLO_TRACK;
941                 else
942                         adt->flag &= ~ADT_NLA_SOLO_TRACK;
943         }
944         else
945                 adt->flag &= ~ADT_NLA_SOLO_TRACK;
946 }
947
948 /* Make the given NLA-track the active one for the given stack. If no track is provided, 
949  * this function can be used to simply deactivate all the NLA tracks in the given stack too.
950  */
951 void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a)
952 {
953         NlaTrack *nlt;
954         
955         /* sanity check */
956         if ELEM(NULL, tracks, tracks->first)
957                 return;
958         
959         /* deactive all the rest */
960         for (nlt= tracks->first; nlt; nlt= nlt->next) 
961                 nlt->flag &= ~NLATRACK_ACTIVE;
962                 
963         /* set the given one as the active one */
964         if (nlt_a)
965                 nlt_a->flag |= NLATRACK_ACTIVE;
966 }
967
968 /* Check if there is any space in the given track to add a strip of the given length */
969 short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end)
970 {
971         /* sanity checks 
972          *      - track must exist
973          *      - track must be editable
974          *      - bounds cannot be equal (0-length is nasty) 
975          */
976         if ((nlt == NULL) || (nlt->flag & NLATRACK_PROTECTED) || IS_EQF(start, end))
977                 return 0;
978         
979         if (start > end) {
980                 puts("BKE_nlatrack_has_space() error... start and end arguments swapped");
981                 SWAP(float, start, end);
982         }
983         
984         /* check if there's any space left in the track for a strip of the given length */
985         return BKE_nlastrips_has_space(&nlt->strips, start, end);
986 }
987
988 /* Rearrange the strips in the track so that they are always in order 
989  * (usually only needed after a strip has been moved) 
990  */
991 void BKE_nlatrack_sort_strips (NlaTrack *nlt)
992 {
993         /* sanity checks */
994         if ELEM(NULL, nlt, nlt->strips.first)
995                 return;
996         
997         /* sort the strips with a more generic function */
998         BKE_nlastrips_sort_strips(&nlt->strips);
999 }
1000
1001 /* Add the given NLA-Strip to the given NLA-Track, assuming that it 
1002  * isn't currently attached to another one 
1003  */
1004 short BKE_nlatrack_add_strip (NlaTrack *nlt, NlaStrip *strip)
1005 {
1006         /* sanity checks */
1007         if ELEM(NULL, nlt, strip)
1008                 return 0;
1009                 
1010         /* try to add the strip to the track using a more generic function */
1011         return BKE_nlastrips_add_strip(&nlt->strips, strip);
1012 }
1013
1014 /* Get the extents of the given NLA-Track including gaps between strips,
1015  * returning whether this succeeded or not
1016  */
1017 short BKE_nlatrack_get_bounds (NlaTrack *nlt, float bounds[2])
1018 {
1019         NlaStrip *strip;
1020         
1021         /* initialize bounds */
1022         if (bounds)
1023                 bounds[0] = bounds[1] = 0.0f;
1024         else
1025                 return 0;
1026         
1027         /* sanity checks */
1028         if ELEM(NULL, nlt, nlt->strips.first)
1029                 return 0;
1030                 
1031         /* lower bound is first strip's start frame */
1032         strip = nlt->strips.first;
1033         bounds[0] = strip->start;
1034         
1035         /* upper bound is last strip's end frame */
1036         strip = nlt->strips.last;
1037         bounds[1] = strip->end;
1038         
1039         /* done */
1040         return 1;
1041 }
1042
1043 /* NLA Strips -------------------------------------- */
1044
1045 /* Find the active NLA-strip within the given track */
1046 NlaStrip *BKE_nlastrip_find_active (NlaTrack *nlt)
1047 {
1048         NlaStrip *strip;
1049         
1050         /* sanity check */
1051         if ELEM(NULL, nlt, nlt->strips.first)
1052                 return NULL;
1053                 
1054         /* try to find the first active strip */
1055         for (strip= nlt->strips.first; strip; strip= strip->next) {
1056                 if (strip->flag & NLASTRIP_FLAG_ACTIVE)
1057                         return strip;
1058         }
1059         
1060         /* none found */
1061         return NULL;
1062 }
1063
1064 /* Make the given NLA-Strip the active one within the given block */
1065 void BKE_nlastrip_set_active (AnimData *adt, NlaStrip *strip)
1066 {
1067         NlaTrack *nlt;
1068         NlaStrip *nls;
1069         
1070         /* sanity checks */
1071         if (adt == NULL)
1072                 return;
1073         
1074         /* loop over tracks, deactivating*/
1075         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1076                 for (nls= nlt->strips.first; nls; nls= nls->next) {
1077                         if (nls != strip)
1078                                 nls->flag &= ~NLASTRIP_FLAG_ACTIVE;
1079                         else
1080                                 nls->flag |= NLASTRIP_FLAG_ACTIVE;
1081                 }
1082         }
1083 }
1084
1085
1086 /* Does the given NLA-strip fall within the given bounds (times)? */
1087 short BKE_nlastrip_within_bounds (NlaStrip *strip, float min, float max)
1088 {
1089         const float stripLen= (strip) ? strip->end - strip->start : 0.0f;
1090         const float boundsLen= fabsf(max - min);
1091         
1092         /* sanity checks */
1093         if ((strip == NULL) || IS_EQF(stripLen, 0.0f) || IS_EQF(boundsLen, 0.0f))
1094                 return 0;
1095         
1096         /* only ok if at least part of the strip is within the bounding window
1097          *      - first 2 cases cover when the strip length is less than the bounding area
1098          *      - second 2 cases cover when the strip length is greater than the bounding area
1099          */
1100         if ( (stripLen < boundsLen) && 
1101                  !(IN_RANGE(strip->start, min, max) ||
1102                    IN_RANGE(strip->end, min, max)) )
1103         {
1104                 return 0;
1105         }
1106         if ( (stripLen > boundsLen) && 
1107                  !(IN_RANGE(min, strip->start, strip->end) ||
1108                    IN_RANGE(max, strip->start, strip->end)) )
1109         {
1110                 return 0;
1111         }
1112         
1113         /* should be ok! */
1114         return 1;
1115 }
1116
1117 /* Recalculate the start and end frames for the current strip, after changing
1118  * the extents of the action or the mapping (repeats or scale factor) info
1119  */
1120 void BKE_nlastrip_recalculate_bounds (NlaStrip *strip)
1121 {
1122         float actlen, mapping;
1123         
1124         /* sanity checks
1125          *      - must have a strip
1126          *      - can only be done for action clips
1127          */
1128         if ((strip == NULL) || (strip->type != NLASTRIP_TYPE_CLIP))
1129                 return;
1130                 
1131         /* calculate new length factors */
1132         actlen= strip->actend - strip->actstart;
1133         if (IS_EQF(actlen, 0.0f)) actlen= 1.0f;
1134         
1135         mapping= strip->scale * strip->repeat;
1136         
1137         /* adjust endpoint of strip in response to this */
1138         if (IS_EQF(mapping, 0.0f) == 0)
1139                 strip->end = (actlen * mapping) + strip->start;
1140 }
1141
1142 /* Is the given NLA-strip the first one to occur for the given AnimData block */
1143 // TODO: make this an api method if necesary, but need to add prefix first
1144 static short nlastrip_is_first (AnimData *adt, NlaStrip *strip)
1145 {
1146         NlaTrack *nlt;
1147         NlaStrip *ns;
1148         
1149         /* sanity checks */
1150         if ELEM(NULL, adt, strip)
1151                 return 0;
1152                 
1153         /* check if strip has any strips before it */
1154         if (strip->prev)
1155                 return 0;
1156                 
1157         /* check other tracks to see if they have a strip that's earlier */
1158         // TODO: or should we check that the strip's track is also the first?
1159         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1160                 /* only check the first strip, assuming that they're all in order */
1161                 ns= nlt->strips.first;
1162                 if (ns) {
1163                         if (ns->start < strip->start)
1164                                 return 0;
1165                 }
1166         }       
1167         
1168         /* should be first now */
1169         return 1;
1170 }
1171
1172 /* Animated Strips ------------------------------------------- */
1173
1174 /* Check if the given NLA-Track has any strips with own F-Curves */
1175 short BKE_nlatrack_has_animated_strips (NlaTrack *nlt)
1176 {
1177         NlaStrip *strip;
1178         
1179         /* sanity checks */
1180         if ELEM(NULL, nlt, nlt->strips.first)
1181                 return 0;
1182                 
1183         /* check each strip for F-Curves only (don't care about whether the flags are set) */
1184         for (strip= nlt->strips.first; strip; strip= strip->next) {
1185                 if (strip->fcurves.first)
1186                         return 1;
1187         }
1188         
1189         /* none found */
1190         return 0;
1191 }
1192
1193 /* Check if given NLA-Tracks have any strips with own F-Curves */
1194 short BKE_nlatracks_have_animated_strips (ListBase *tracks)
1195 {
1196         NlaTrack *nlt;
1197         
1198         /* sanity checks */
1199         if ELEM(NULL, tracks, tracks->first)
1200                 return 0;
1201                 
1202         /* check each track, stopping on the first hit */
1203         for (nlt= tracks->first; nlt; nlt= nlt->next) {
1204                 if (BKE_nlatrack_has_animated_strips(nlt))
1205                         return 1;
1206         }
1207         
1208         /* none found */
1209         return 0;
1210 }
1211
1212 /* Validate the NLA-Strips 'control' F-Curves based on the flags set*/
1213 void BKE_nlastrip_validate_fcurves (NlaStrip *strip) 
1214 {
1215         FCurve *fcu;
1216         
1217         /* sanity checks */
1218         if (strip == NULL)
1219                 return;
1220         
1221         /* if controlling influence... */
1222         if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
1223                 /* try to get F-Curve */
1224                 fcu= list_find_fcurve(&strip->fcurves, "influence", 0);
1225                 
1226                 /* add one if not found */
1227                 if (fcu == NULL) {
1228                         /* make new F-Curve */
1229                         fcu= MEM_callocN(sizeof(FCurve), "NlaStrip FCurve");
1230                         BLI_addtail(&strip->fcurves, fcu);
1231                         
1232                         /* set default flags */
1233                         fcu->flag = (FCURVE_VISIBLE|FCURVE_SELECTED);
1234                         
1235                         /* store path - make copy, and store that */
1236                         fcu->rna_path= BLI_strdupn("influence", 9);
1237                         
1238                         // TODO: insert a few keyframes to ensure default behavior?
1239                 }
1240         }
1241         
1242         /* if controlling time... */
1243         if (strip->flag & NLASTRIP_FLAG_USR_TIME) {
1244                 /* try to get F-Curve */
1245                 fcu= list_find_fcurve(&strip->fcurves, "strip_time", 0);
1246                 
1247                 /* add one if not found */
1248                 if (fcu == NULL) {
1249                         /* make new F-Curve */
1250                         fcu= MEM_callocN(sizeof(FCurve), "NlaStrip FCurve");
1251                         BLI_addtail(&strip->fcurves, fcu);
1252                         
1253                         /* set default flags */
1254                         fcu->flag = (FCURVE_VISIBLE|FCURVE_SELECTED);
1255                         
1256                         /* store path - make copy, and store that */
1257                         fcu->rna_path= BLI_strdupn("strip_time", 10);
1258                         
1259                         // TODO: insert a few keyframes to ensure default behavior?
1260                 }
1261         }
1262 }
1263
1264 /* Sanity Validation ------------------------------------ */
1265
1266 static int nla_editbone_name_check(void *arg, const char *name)
1267 {
1268         return BLI_ghash_haskey((GHash *)arg, (void *)name);
1269 }
1270
1271 /* Find (and set) a unique name for a strip from the whole AnimData block 
1272  * Uses a similar method to the BLI method, but is implemented differently
1273  * as we need to ensure that the name is unique over several lists of tracks,
1274  * not just a single track.
1275  */
1276 void BKE_nlastrip_validate_name (AnimData *adt, NlaStrip *strip)
1277 {
1278         GHash *gh;
1279         NlaStrip *tstrip;
1280         NlaTrack *nlt;
1281         
1282         /* sanity checks */
1283         if ELEM(NULL, adt, strip)
1284                 return;
1285                 
1286         /* give strip a default name if none already */
1287         if (strip->name[0]==0) {
1288                 switch (strip->type) {
1289                         case NLASTRIP_TYPE_CLIP: /* act-clip */
1290                                 BLI_strncpy(strip->name, (strip->act)?(strip->act->id.name+2):("<No Action>"), sizeof(strip->name));
1291                                 break;
1292                         case NLASTRIP_TYPE_TRANSITION: /* transition */
1293                                 BLI_strncpy(strip->name, "Transition", sizeof(strip->name));
1294                                 break;
1295                         case NLASTRIP_TYPE_META: /* meta */
1296                                 BLI_strncpy(strip->name, "Meta", sizeof(strip->name));
1297                                 break;
1298                         default:
1299                                 BLI_strncpy(strip->name, "NLA Strip", sizeof(strip->name));
1300                                 break;
1301                 }
1302         }
1303         
1304         /* build a hash-table of all the strips in the tracks 
1305          *      - this is easier than iterating over all the tracks+strips hierarchy everytime
1306          *        (and probably faster)
1307          */
1308         gh= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "nlastrip_validate_name gh");
1309         
1310         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1311                 for (tstrip= nlt->strips.first; tstrip; tstrip= tstrip->next) {
1312                         /* don't add the strip of interest */
1313                         if (tstrip == strip) 
1314                                 continue;
1315                         
1316                         /* use the name of the strip as the key, and the strip as the value, since we're mostly interested in the keys */
1317                         BLI_ghash_insert(gh, tstrip->name, tstrip);
1318                 }
1319         }
1320         
1321         /* if the hash-table has a match for this name, try other names... 
1322          *      - in an extreme case, it might not be able to find a name, but then everything else in Blender would fail too :)
1323          */
1324         BLI_uniquename_cb(nla_editbone_name_check, (void *)gh, "NlaStrip", '.', strip->name, sizeof(strip->name));
1325
1326         /* free the hash... */
1327         BLI_ghash_free(gh, NULL, NULL);
1328 }
1329
1330 /* ---- */
1331
1332 /* Get strips which overlap the given one at the start/end of its range 
1333  *      - strip: strip that we're finding overlaps for
1334  *      - track: nla-track that the overlapping strips should be found from
1335  *      - start, end: frames for the offending endpoints
1336  */
1337 static void nlastrip_get_endpoint_overlaps (NlaStrip *strip, NlaTrack *track, float **start, float **end)
1338 {
1339         NlaStrip *nls;
1340         
1341         /* find strips that overlap over the start/end of the given strip,
1342          * but which don't cover the entire length 
1343          */
1344         // TODO: this scheme could get quite slow for doing this on many strips...
1345         for (nls= track->strips.first; nls; nls= nls->next) {
1346                 /* check if strip overlaps (extends over or exactly on) the entire range of the strip we're validating */
1347                 if ((nls->start <= strip->start) && (nls->end >= strip->end)) {
1348                         *start= NULL;
1349                         *end= NULL;
1350                         return;
1351                 }
1352                 
1353                 /* check if strip doesn't even occur anywhere near... */
1354                 if (nls->end < strip->start)
1355                         continue; /* skip checking this strip... not worthy of mention */
1356                 if (nls->start > strip->end)
1357                         return; /* the range we're after has already passed */
1358                         
1359                 /* if this strip is not part of an island of continuous strips, it can be used
1360                  *      - this check needs to be done for each end of the strip we try and use...
1361                  */
1362                 if ((nls->next == NULL) || IS_EQF(nls->next->start, nls->end)==0) {
1363                         if ((nls->end > strip->start) && (nls->end < strip->end))
1364                                 *start= &nls->end;
1365                 }
1366                 if ((nls->prev == NULL) || IS_EQF(nls->prev->end, nls->start)==0) {
1367                         if ((nls->start < strip->end) && (nls->start > strip->start))
1368                                 *end= &nls->start;
1369                 }
1370         }
1371 }
1372
1373 /* Determine auto-blending for the given strip */
1374 static void BKE_nlastrip_validate_autoblends (NlaTrack *nlt, NlaStrip *nls)
1375 {
1376         float *ps=NULL, *pe=NULL;
1377         float *ns=NULL, *ne=NULL;
1378         
1379         /* sanity checks */
1380         if ELEM(NULL, nls, nlt)
1381                 return;
1382         if ((nlt->prev == NULL) && (nlt->next == NULL))
1383                 return;
1384         if ((nls->flag & NLASTRIP_FLAG_AUTO_BLENDS)==0)
1385                 return;
1386         
1387         /* get test ranges */
1388         if (nlt->prev)
1389                 nlastrip_get_endpoint_overlaps(nls, nlt->prev, &ps, &pe);
1390         if (nlt->next)
1391                 nlastrip_get_endpoint_overlaps(nls, nlt->next, &ns, &ne);
1392                 
1393         /* set overlaps for this strip 
1394          *      - don't use the values obtained though if the end in question 
1395          *        is directly followed/preceeded by another strip, forming an 
1396          *        'island' of continuous strips
1397          */
1398         if ( (ps || ns) && ((nls->prev == NULL) || IS_EQF(nls->prev->end, nls->start)==0) )
1399         {
1400                 /* start overlaps - pick the largest overlap */
1401                 if ( ((ps && ns) && (*ps > *ns)) || (ps) )
1402                         nls->blendin= *ps - nls->start;
1403                 else
1404                         nls->blendin= *ns - nls->start;
1405         }
1406         else /* no overlap allowed/needed */
1407                 nls->blendin= 0.0f;
1408                 
1409         if ( (pe || ne) && ((nls->next == NULL) || IS_EQF(nls->next->start, nls->end)==0) )
1410         {
1411                 /* end overlaps - pick the largest overlap */
1412                 if ( ((pe && ne) && (*pe > *ne)) || (pe) )
1413                         nls->blendout= nls->end - *pe;
1414                 else
1415                         nls->blendout= nls->end - *ne;
1416         }
1417         else /* no overlap allowed/needed */
1418                 nls->blendout= 0.0f;
1419 }
1420
1421 /* Ensure that auto-blending and other settings are set correctly */
1422 void BKE_nla_validate_state (AnimData *adt)
1423 {
1424         NlaStrip *strip, *fstrip=NULL;
1425         NlaTrack *nlt;
1426         
1427         /* sanity checks */
1428         if ELEM(NULL, adt, adt->nla_tracks.first)
1429                 return;
1430                 
1431         /* adjust blending values for auto-blending, and also do an initial pass to find the earliest strip */
1432         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1433                 for (strip= nlt->strips.first; strip; strip= strip->next) {
1434                         /* auto-blending first */
1435                         BKE_nlastrip_validate_autoblends(nlt, strip);
1436                         
1437                         /* extend mode - find first strip */
1438                         if ((fstrip == NULL) || (strip->start < fstrip->start))
1439                                 fstrip= strip;
1440                 }
1441         }
1442         
1443         /* second pass over the strips to adjust the extend-mode to fix any problems */
1444         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1445                 for (strip= nlt->strips.first; strip; strip= strip->next) {
1446                         /* apart from 'nothing' option which user has to explicitly choose, we don't really know if 
1447                          * we should be overwriting the extend setting (but assume that's what the user wanted)
1448                          */
1449                         // TODO: 1 solution is to tie this in with auto-blending...
1450                         if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
1451                                 /* 1) First strip must be set to extend hold, otherwise, stuff before acts dodgy
1452                                  * 2) Only overwrite extend mode if *not* changing it will most probably result in 
1453                                  * occlusion problems, which will occur iff
1454                                  *      - blendmode = REPLACE
1455                                  *      - all channels the same (this is fiddly to test, so is currently assumed)
1456                                  *
1457                                  * Should fix problems such as [#29869]
1458                                  */
1459                                 if (strip == fstrip)
1460                                         strip->extendmode= NLASTRIP_EXTEND_HOLD;
1461                                 else if (strip->blendmode == NLASTRIP_MODE_REPLACE)
1462                                         strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD;
1463                         }
1464                 }
1465         }
1466 }
1467
1468 /* Core Tools ------------------------------------------- */
1469
1470 /* For the given AnimData block, add the active action to the NLA
1471  * stack (i.e. 'push-down' action). The UI should only allow this 
1472  * for normal editing only (i.e. not in editmode for some strip's action),
1473  * so no checks for this are performed.
1474  */
1475 // TODO: maybe we should have checks for this too...
1476 void BKE_nla_action_pushdown (AnimData *adt)
1477 {
1478         NlaStrip *strip;
1479         
1480         /* sanity checks */
1481         // TODO: need to report the error for this
1482         if ELEM(NULL, adt, adt->action) 
1483                 return;
1484                 
1485         /* if the action is empty, we also shouldn't try to add to stack, 
1486          * as that will cause us grief down the track
1487          */
1488         // TODO: what about modifiers?
1489         if (action_has_motion(adt->action) == 0) {
1490                 printf("BKE_nla_action_pushdown(): action has no data \n");
1491                 return;
1492         }
1493         
1494         /* add a new NLA strip to the track, which references the active action */
1495         strip= add_nlastrip_to_stack(adt, adt->action);
1496         
1497         /* do other necessary work on strip */  
1498         if (strip) {
1499                 /* clear reference to action now that we've pushed it onto the stack */
1500                 id_us_min(&adt->action->id);
1501                 adt->action= NULL;
1502                 
1503                 /* if the strip is the first one in the track it lives in, check if there
1504                  * are strips in any other tracks that may be before this, and set the extend
1505                  * mode accordingly
1506                  */
1507                 if (nlastrip_is_first(adt, strip) == 0) {
1508                         /* not first, so extend mode can only be NLASTRIP_EXTEND_HOLD_FORWARD not NLASTRIP_EXTEND_HOLD,
1509                          * so that it doesn't override strips in previous tracks
1510                          */
1511                         // FIXME: this needs to be more automated, since user can rearrange strips
1512                         strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD;
1513                 }
1514                 
1515                 /* make strip the active one... */
1516                 BKE_nlastrip_set_active(adt, strip);
1517         }
1518 }
1519
1520
1521 /* Find the active strip + track combo, and set them up as the tweaking track,
1522  * and return if successful or not.
1523  */
1524 short BKE_nla_tweakmode_enter (AnimData *adt)
1525 {
1526         NlaTrack *nlt, *activeTrack=NULL;
1527         NlaStrip *strip, *activeStrip=NULL;
1528         
1529         /* verify that data is valid */
1530         if ELEM(NULL, adt, adt->nla_tracks.first)
1531                 return 0;
1532                 
1533         /* if block is already in tweakmode, just leave, but we should report 
1534          * that this block is in tweakmode (as our returncode)
1535          */
1536         if (adt->flag & ADT_NLA_EDIT_ON)
1537                 return 1;
1538                 
1539         /* go over the tracks, finding the active one, and its active strip
1540          *      - if we cannot find both, then there's nothing to do
1541          */
1542         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1543                 /* check if active */
1544                 if (nlt->flag & NLATRACK_ACTIVE) {
1545                         /* store reference to this active track */
1546                         activeTrack= nlt;
1547                         
1548                         /* now try to find active strip */
1549                         activeStrip= BKE_nlastrip_find_active(nlt);
1550                         break;
1551                 }       
1552         }
1553         
1554         /* There are situations where we may have multiple strips selected and we want to enter tweakmode on all 
1555          * of those at once. Usually in those cases, it will usually just be a single strip per AnimData. 
1556          * In such cases, compromise and take the last selected track and/or last selected strip [#28468] 
1557          */
1558         if (activeTrack == NULL) {
1559                 /* try last selected track for active strip */
1560                 for (nlt = adt->nla_tracks.last; nlt; nlt = nlt->prev) {
1561                         if (nlt->flag & NLATRACK_SELECTED) {
1562                                 /* assume this is the active track */
1563                                 activeTrack= nlt;
1564                                 
1565                                 /* try to find active strip */
1566                                 activeStrip= BKE_nlastrip_find_active(nlt);
1567                                 break;
1568                         }
1569                 }       
1570         }
1571         if ((activeTrack) && (activeStrip == NULL)) {
1572                 /* no active strip in active or last selected track; compromise for first selected (assuming only single)... */
1573                 for (strip = activeTrack->strips.first; strip; strip= strip->next) {
1574                         if (strip->flag & (NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_ACTIVE)) {
1575                                 activeStrip = strip;
1576                                 break;
1577                         }
1578                 }
1579         }
1580         
1581         if ELEM3(NULL, activeTrack, activeStrip, activeStrip->act) {
1582                 if (G.f & G_DEBUG) {
1583                         printf("NLA tweakmode enter - neither active requirement found \n");
1584                         printf("\tactiveTrack = %p, activeStrip = %p \n", (void *)activeTrack, (void *)activeStrip);
1585                 }
1586                 return 0;
1587         }
1588                 
1589         /* go over all the tracks up to the active one, tagging each strip that uses the same 
1590          * action as the active strip, but leaving everything else alone
1591          */
1592         for (nlt= activeTrack->prev; nlt; nlt= nlt->prev) {
1593                 for (strip= nlt->strips.first; strip; strip= strip->next) {
1594                         if (strip->act == activeStrip->act)
1595                                 strip->flag |= NLASTRIP_FLAG_TWEAKUSER;
1596                         else
1597                                 strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
1598                 }
1599         }
1600         
1601         
1602         /* go over all the tracks after AND INCLUDING the active one, tagging them as being disabled 
1603          *      - the active track needs to also be tagged, otherwise, it'll overlap with the tweaks going on
1604          */
1605         for (nlt= activeTrack; nlt; nlt= nlt->next)
1606                 nlt->flag |= NLATRACK_DISABLED;
1607         
1608         /* handle AnimData level changes:
1609          *      - 'real' active action to temp storage (no need to change user-counts)
1610          *      - action of active strip set to be the 'active action', and have its usercount incremented
1611          *      - editing-flag for this AnimData block should also get turned on (for more efficient restoring)
1612          *      - take note of the active strip for mapping-correction of keyframes in the action being edited
1613          */
1614         adt->tmpact= adt->action;
1615         adt->action= activeStrip->act;
1616         adt->actstrip= activeStrip;
1617         id_us_plus(&activeStrip->act->id);
1618         adt->flag |= ADT_NLA_EDIT_ON;
1619         
1620         /* done! */
1621         return 1;
1622 }
1623
1624 /* Exit tweakmode for this AnimData block */
1625 void BKE_nla_tweakmode_exit (AnimData *adt)
1626 {
1627         NlaStrip *strip;
1628         NlaTrack *nlt;
1629         
1630         /* verify that data is valid */
1631         if ELEM(NULL, adt, adt->nla_tracks.first)
1632                 return;
1633                 
1634         /* hopefully the flag is correct - skip if not on */
1635         if ((adt->flag & ADT_NLA_EDIT_ON) == 0)
1636                 return;
1637                 
1638         // TODO: need to sync the user-strip with the new state of the action!
1639                 
1640         /* for all Tracks, clear the 'disabled' flag
1641          * for all Strips, clear the 'tweak-user' flag
1642          */
1643         for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
1644                 nlt->flag &= ~NLATRACK_DISABLED;
1645                 
1646                 for (strip= nlt->strips.first; strip; strip= strip->next) 
1647                         strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
1648         }
1649         
1650         /* handle AnimData level changes:
1651          *      - 'temporary' active action needs its usercount decreased, since we're removing this reference
1652          *      - 'real' active action is restored from storage
1653          *      - storage pointer gets cleared (to avoid having bad notes hanging around)
1654          *      - editing-flag for this AnimData block should also get turned off
1655          *      - clear pointer to active strip
1656          */
1657         if (adt->action) adt->action->id.us--;
1658         adt->action= adt->tmpact;
1659         adt->tmpact= NULL;
1660         adt->actstrip= NULL;
1661         adt->flag &= ~ADT_NLA_EDIT_ON;
1662 }
1663
1664 /* Baking Tools ------------------------------------------- */
1665
1666 static void UNUSED_FUNCTION(BKE_nla_bake) (Scene *scene, ID *UNUSED(id), AnimData *adt, int UNUSED(flag))
1667 {
1668
1669         /* verify that data is valid 
1670          *      1) Scene and AnimData must be provided 
1671          *      2) there must be tracks to merge...
1672          */
1673         if ELEM3(NULL, scene, adt, adt->nla_tracks.first)
1674                 return;
1675         
1676         /* if animdata currently has an action, 'push down' this onto the stack first */
1677         if (adt->action)
1678                 BKE_nla_action_pushdown(adt);
1679         
1680         /* get range of motion to bake, and the channels involved... */
1681         
1682         /* temporarily mute the action, and start keying to it */
1683         
1684         /* start keying... */
1685         
1686         /* unmute the action */
1687 }
1688
1689 /* *************************************************** */