d062a2ab14b48bd6a5f262ef2d3ce1715fc2595c
[blender.git] / source / blender / blenkernel / intern / nla.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Joshua Leung (full recode)
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <stdlib.h>
31 #include <stddef.h>
32 #include <stdio.h>
33 #include <math.h>
34 #include <float.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLI_blenlib.h"
39
40 #include "DNA_anim_types.h"
41 #include "DNA_action_types.h"
42
43 #include "BKE_animsys.h"
44 #include "BKE_action.h"
45 #include "BKE_fcurve.h"
46 #include "BKE_nla.h"
47 #include "BKE_blender.h"
48 #include "BKE_library.h"
49 #include "BKE_object.h"
50 #include "BKE_utildefines.h"
51
52
53 #ifdef HAVE_CONFIG_H
54 #include <config.h>
55 #endif
56
57
58 /* *************************************************** */
59 /* Data Management */
60
61 /* Freeing ------------------------------------------- */
62
63 /* Remove the given NLA strip from the NLA track it occupies, free the strip's data,
64  * and the strip itself. 
65  */
66 // TODO: with things like transitions, should these get freed too? Maybe better as a UI tool
67 void free_nlastrip (ListBase *strips, NlaStrip *strip)
68 {
69         FModifier *fcm, *fmn;
70         
71         /* sanity checks */
72         if (strip == NULL)
73                 return;
74                 
75         /* remove reference to action */
76         if (strip->act)
77                 strip->act->id.us--;
78                 
79         /* free remapping info */
80         //if (strip->remap)
81         //      BKE_animremap_free();
82         
83         /* free own F-Curves */
84         free_fcurves(&strip->fcurves);
85         
86         /* free F-Modifiers */
87         for (fcm= strip->modifiers.first; fcm; fcm= fmn) {
88                 fmn= fcm->next;
89                 
90                 BLI_remlink(&strip->modifiers, fcm);
91                 fcurve_remove_modifier(NULL, fcm);
92         }
93         
94         /* free the strip itself */
95         if (strips)
96                 BLI_freelinkN(strips, strip);
97         else
98                 MEM_freeN(strip);
99 }
100
101 /* Remove the given NLA track from the set of NLA tracks, free the track's data,
102  * and the track itself.
103  */
104 void free_nlatrack (ListBase *tracks, NlaTrack *nlt)
105 {
106         NlaStrip *strip, *stripn;
107         
108         /* sanity checks */
109         if (nlt == NULL)
110                 return;
111                 
112         /* free strips */
113         for (strip= nlt->strips.first; strip; strip= stripn) {
114                 stripn= strip->next;
115                 free_nlastrip(&nlt->strips, strip);
116         }
117         
118         /* free NLA track itself now */
119         if (tracks)
120                 BLI_freelinkN(tracks, nlt);
121         else
122                 MEM_freeN(nlt);
123 }
124
125 /* Free the elements of type NLA Tracks provided in the given list, but do not free
126  * the list itself since that is not free-standing
127  */
128 void free_nladata (ListBase *tracks)
129 {
130         NlaTrack *nlt, *nltn;
131         
132         /* sanity checks */
133         if ELEM(NULL, tracks, tracks->first)
134                 return;
135                 
136         /* free tracks one by one */
137         for (nlt= tracks->first; nlt; nlt= nltn) {
138                 nltn= nlt->next;
139                 free_nlatrack(tracks, nlt);
140         }
141         
142         /* clear the list's pointers to be safe */
143         tracks->first= tracks->last= NULL;
144 }
145
146 /* Copying ------------------------------------------- */
147
148 /* Copy NLA strip */
149 NlaStrip *copy_nlastrip (NlaStrip *strip)
150 {
151         NlaStrip *strip_d;
152         
153         /* sanity check */
154         if (strip == NULL)
155                 return NULL;
156                 
157         /* make a copy */
158         strip_d= MEM_dupallocN(strip);
159         strip_d->next= strip_d->prev= NULL;
160         
161         /* increase user-count of action */
162         if (strip_d->act)
163                 strip_d->act->id.us++;
164                 
165         /* copy F-Curves and modifiers */
166         copy_fcurves(&strip_d->fcurves, &strip->fcurves);
167         fcurve_copy_modifiers(&strip_d->modifiers, &strip->modifiers);
168         
169         /* return the strip */
170         return strip_d;
171 }
172
173 /* Copy NLA Track */
174 NlaTrack *copy_nlatrack (NlaTrack *nlt)
175 {
176         NlaStrip *strip, *strip_d;
177         NlaTrack *nlt_d;
178         
179         /* sanity check */
180         if (nlt == NULL)
181                 return NULL;
182                 
183         /* make a copy */
184         nlt_d= MEM_dupallocN(nlt);
185         nlt_d->next= nlt_d->prev= NULL;
186         
187         /* make a copy of all the strips, one at a time */
188         nlt_d->strips.first= nlt_d->strips.last= NULL;
189         
190         for (strip= nlt->strips.first; strip; strip= strip->next) {
191                 strip_d= copy_nlastrip(strip);
192                 BLI_addtail(&nlt_d->strips, strip_d);
193         }
194         
195         /* return the copy */
196         return nlt_d;
197 }
198
199 /* Copy all NLA data */
200 void copy_nladata (ListBase *dst, ListBase *src)
201 {
202         NlaTrack *nlt, *nlt_d;
203         
204         /* sanity checks */
205         if ELEM(NULL, dst, src)
206                 return;
207                 
208         /* copy each NLA-track, one at a time */
209         for (nlt= src->first; nlt; nlt= nlt->next) {
210                 /* make a copy, and add the copy to the destination list */
211                 nlt_d= copy_nlatrack(nlt);
212                 BLI_addtail(dst, nlt_d);
213         }
214 }
215
216 /* Adding ------------------------------------------- */
217
218 /* Add a NLA Strip referencing the given Action, to the given NLA Track */
219 // TODO: any extra parameters to control how this is done?
220 NlaStrip *add_nlastrip (NlaTrack *nlt, bAction *act)
221 {
222         NlaStrip *strip;
223         
224         /* sanity checks */
225         if ELEM(NULL, nlt, act)
226                 return NULL;
227                 
228         /* allocate new strip */
229         strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
230         BLI_addtail(&nlt->strips, strip);
231         
232         /* generic settings 
233          *      - selected flag to highlight this to the user
234          *      - auto-blends to ensure that blend in/out values are automatically 
235          *        determined by overlaps of strips
236          *      - (XXX) synchronisation of strip-length in accordance with changes to action-length
237          *        is not done though, since this should only really happens in editmode for strips now
238          *        though this decision is still subject to further review...
239          */
240         strip->flag = NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_AUTO_BLENDS;
241         
242         /* assign the action reference */
243         strip->act= act;
244         id_us_plus(&act->id);
245         
246         /* determine initial range 
247          *      - strip length cannot be 0... ever...
248          */
249         calc_action_range(strip->act, &strip->actstart, &strip->actend, 1);
250         
251         strip->start = strip->actstart;
252         strip->end = (IS_EQ(strip->actstart, strip->actend)) ?  (strip->actstart + 1.0f): (strip->actend);
253         
254         /* strip should be referenced as-is */
255         strip->scale= 1.0f;
256         strip->repeat = 1.0f;
257         
258         /* return the new strip */
259         return strip;
260 }
261
262 /* Add a NLA Track to the given AnimData */
263 NlaTrack *add_nlatrack (AnimData *adt)
264 {
265         NlaTrack *nlt;
266         
267         /* sanity checks */
268         if (adt == NULL)
269                 return NULL;
270                 
271         /* allocate new track */
272         nlt= MEM_callocN(sizeof(NlaTrack), "NlaTrack");
273         
274         /* set settings requiring the track to not be part of the stack yet */
275         nlt->flag = NLATRACK_SELECTED;
276         nlt->index= BLI_countlist(&adt->nla_tracks);
277         
278         /* add track to stack, and make it the active one */
279         BLI_addtail(&adt->nla_tracks, nlt);
280         BKE_nlatrack_set_active(&adt->nla_tracks, nlt);
281         
282         /* must have unique name, but we need to seed this */
283         sprintf(nlt->name, "NlaTrack");
284         BLI_uniquename(&adt->nla_tracks, nlt, "NlaTrack", '.', offsetof(NlaTrack, name), 64);
285         
286         /* return the new track */
287         return nlt;
288 }
289
290 /* *************************************************** */
291 /* Basic Utilities */
292
293 /* NLA-Tracks ---------------------------------------- */
294
295 /* Find the active NLA-track for the given stack */
296 NlaTrack *BKE_nlatrack_find_active (ListBase *tracks)
297 {
298         NlaTrack *nlt;
299         
300         /* sanity check */
301         if ELEM(NULL, tracks, tracks->first)
302                 return NULL;
303                 
304         /* try to find the first active track */
305         for (nlt= tracks->first; nlt; nlt= nlt->next) {
306                 if (nlt->flag & NLATRACK_ACTIVE)
307                         return nlt;
308         }
309         
310         /* none found */
311         return NULL;
312 }
313
314 /* Make the given NLA-track the active one for the given stack. If no track is provided, 
315  * this function can be used to simply deactivate all the NLA tracks in the given stack too.
316  */
317 void BKE_nlatrack_set_active (ListBase *tracks, NlaTrack *nlt_a)
318 {
319         NlaTrack *nlt;
320         
321         /* sanity check */
322         if ELEM(NULL, tracks, tracks->first)
323                 return;
324         
325         /* deactive all the rest */
326         for (nlt= tracks->first; nlt; nlt= nlt->next) 
327                 nlt->flag &= ~NLATRACK_ACTIVE;
328                 
329         /* set the given one as the active one */
330         if (nlt_a)
331                 nlt_a->flag |= NLATRACK_ACTIVE;
332 }
333
334 /* Check if there is any space in the last track to add the given strip */
335 short BKE_nlatrack_has_space (NlaTrack *nlt, float start, float end)
336 {
337         NlaStrip *strip;
338         
339         /* sanity checks */
340         if ((nlt == NULL) || IS_EQ(start, end))
341                 return 0;
342         if (start > end) {
343                 puts("BKE_nlatrack_has_space error... start and end arguments swapped");
344                 SWAP(float, start, end);
345         }
346         
347         /* loop over NLA strips checking for any overlaps with this area... */
348         for (strip= nlt->strips.first; strip; strip= strip->next) {
349                 /* if start frame of strip is past the target end-frame, that means that
350                  * we've gone past the window we need to check for, so things are fine
351                  */
352                 if (strip->start > end)
353                         return 1;
354                 
355                 /* if the end of the strip is greater than either of the boundaries, the range
356                  * must fall within the extents of the strip
357                  */
358                 if ((strip->end > start) || (strip->end > end))
359                         return 0;
360         }
361         
362         /* if we are still here, we haven't encountered any overlapping strips */
363         return 1;
364 }
365
366 /* Rearrange the strips in the track so that they are always in order 
367  * (usually only needed after a strip has been moved) 
368  */
369 void BKE_nlatrack_sort_strips (NlaTrack *nlt)
370 {
371         ListBase tmp = {NULL, NULL};
372         NlaStrip *strip, *sstrip;
373         
374         /* sanity checks */
375         if ELEM(NULL, nlt, nlt->strips.first)
376                 return;
377                 
378         /* we simply perform insertion sort on this list, since it is assumed that per track,
379          * there are only likely to be at most 5-10 strips
380          */
381         for (strip= nlt->strips.first; strip; strip= strip->next) {
382                 short not_added = 1;
383                 
384                 /* remove this strip from the list, and add it to the new list, searching from the end of 
385                  * the list, assuming that the lists are in order 
386                  */
387                 BLI_remlink(&nlt->strips, strip);
388                 
389                 for (sstrip= tmp.last; not_added && sstrip; sstrip= sstrip->prev) {
390                         /* check if add after */
391                         if (sstrip->end < strip->start) {
392                                 BLI_insertlinkafter(&tmp, sstrip, strip);
393                                 not_added= 0;
394                                 break;
395                         }
396                 }
397                 
398                 /* add before first? */
399                 if (not_added)
400                         BLI_addhead(&tmp, strip);
401         }
402         
403         /* reassign the start and end points of the strips */
404         nlt->strips.first= tmp.first;
405         nlt->strips.last= tmp.last;
406 }
407  
408 /* Tools ------------------------------------------- */
409
410 /* For the given AnimData block, add the active action to the NLA
411  * stack (i.e. 'push-down' action). The UI should only allow this 
412  * for normal editing only (i.e. not in editmode for some strip's action),
413  * so no checks for this are performed.
414  */
415 // TODO: maybe we should have checks for this too...
416 void BKE_nla_action_pushdown (AnimData *adt)
417 {
418         NlaTrack *nlt;
419         NlaStrip *strip;
420         
421         /* sanity checks */
422         // TODO: need to report the error for this
423         if ELEM(NULL, adt, adt->action) 
424                 return;
425                 
426         /* if the action is empty, we also shouldn't try to add to stack, 
427          * as that will cause us grief down the track
428          */
429         // TODO: what about modifiers?
430         if (action_has_motion(adt->action) == 0)
431                 return;
432                 
433         /* add a new NLA track to house this action 
434          *      - we could investigate trying to fit the action into an appropriately
435          *        sized gap in the existing tracks, however, this may result in unexpected 
436          *        changes in blending behaviour...
437          */
438         nlt= add_nlatrack(adt);
439         if (nlt == NULL)
440                 return;
441         
442         /* add a new NLA strip to the track, which references the active action */
443         strip= add_nlastrip(nlt, adt->action);
444         
445         /* clear reference to action now that we've pushed it onto the stack */
446         if (strip) {
447                 adt->action->id.us--;
448                 adt->action= NULL;
449         }
450         
451         // TODO: set any other flags necessary here...
452 }
453
454 /* *************************************************** */