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