use bool for rna funcs.
[blender.git] / source / blender / makesrna / intern / rna_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  * Contributor(s): Blender Foundation (2009), Joshua Leung
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/makesrna/intern/rna_nla.c
24  *  \ingroup RNA
25  */
26
27 #include <stdlib.h>
28
29 #include "DNA_anim_types.h"
30 #include "DNA_action_types.h"
31 #include "DNA_scene_types.h"
32
33 #include "BLI_utildefines.h"
34
35 #include "MEM_guardedalloc.h"
36
37 #include "RNA_access.h"
38 #include "RNA_define.h"
39
40 #include "rna_internal.h"
41
42 #include "WM_api.h"
43 #include "WM_types.h"
44
45 #ifdef RNA_RUNTIME
46
47 #include <stdio.h>
48 #include <math.h>
49
50 /* needed for some of the validation stuff... */
51 #include "BKE_animsys.h"
52 #include "BKE_nla.h"
53
54 #include "ED_anim_api.h"
55
56 /* temp constant defined for these funcs only... */
57 #define NLASTRIP_MIN_LEN_THRESH     0.1f
58
59 static void rna_NlaStrip_name_set(PointerRNA *ptr, const char *value)
60 {
61         NlaStrip *data = (NlaStrip *)ptr->data;
62         
63         /* copy the name first */
64         BLI_strncpy_utf8(data->name, value, sizeof(data->name));
65         
66         /* validate if there's enough info to do so */
67         if (ptr->id.data) {
68                 AnimData *adt = BKE_animdata_from_id(ptr->id.data);
69                 BKE_nlastrip_validate_name(adt, data);
70         }
71 }
72
73 static char *rna_NlaStrip_path(PointerRNA *ptr)
74 {
75         NlaStrip *strip = (NlaStrip *)ptr->data;
76         AnimData *adt = BKE_animdata_from_id(ptr->id.data);
77         
78         /* if we're attached to AnimData, try to resolve path back to AnimData */
79         if (adt) {
80                 NlaTrack *nlt;
81                 NlaStrip *nls;
82                 
83                 for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
84                         for (nls = nlt->strips.first; nls; nls = nls->next) {
85                                 if (nls == strip) {
86                                         /* XXX but if we animate like this, the control will never work... */
87                                         return BLI_sprintfN("animation_data.nla_tracks[\"%s\"].strips[\"%s\"]", nlt->name, strip->name);
88                                 }
89                         }
90                 }
91         }
92         
93         /* no path */
94         return "";
95 }
96
97 static void rna_NlaStrip_transform_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
98 {
99         NlaStrip *strip = (NlaStrip *)ptr->data;
100
101         BKE_nlameta_flush_transforms(strip);
102 }
103
104 static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value)
105 {
106         NlaStrip *data = (NlaStrip *)ptr->data;
107         
108         /* clamp value to lie within valid limits
109          *      - cannot start past the end of the strip + some flexibility threshold
110          *      - cannot start before the previous strip (if present) ends
111          *              -> but if it was a transition, we could go up to the start of the strip + some flexibility threshold
112          *              as long as we re-adjust the transition afterwards
113          *      - minimum frame is -MAXFRAME so that we don't get clipping on frame 0
114          */
115         if (data->prev) {
116                 if (data->prev->type == NLASTRIP_TYPE_TRANSITION) {
117                         CLAMP(value, data->prev->start + NLASTRIP_MIN_LEN_THRESH, data->end - NLASTRIP_MIN_LEN_THRESH);
118                         
119                         /* re-adjust the transition to stick to the endpoints of the action-clips */
120                         data->prev->end = value;
121                 }
122                 else {
123                         CLAMP(value, data->prev->end, data->end - NLASTRIP_MIN_LEN_THRESH);
124                 }
125         }
126         else {
127                 CLAMP(value, MINAFRAME, data->end);
128         }
129         data->start = value;
130 }
131
132 static void rna_NlaStrip_end_frame_set(PointerRNA *ptr, float value)
133 {
134         NlaStrip *data = (NlaStrip *)ptr->data;
135         
136         /* clamp value to lie within valid limits
137          *      - must not have zero or negative length strip, so cannot start before the first frame
138          *        + some minimum-strip-length threshold
139          *      - cannot end later than the start of the next strip (if present)
140          *              -> but if it was a transition, we could go up to the start of the end - some flexibility threshold
141          *              as long as we re-adjust the transition afterwards
142          */
143         if (data->next) {
144                 if (data->next->type == NLASTRIP_TYPE_TRANSITION) {
145                         CLAMP(value, data->start + NLASTRIP_MIN_LEN_THRESH, data->next->end - NLASTRIP_MIN_LEN_THRESH);
146                         
147                         /* readjust the transition to stick to the endpoints of the action-clips */
148                         data->next->start = value;
149                 }
150                 else {
151                         CLAMP(value, data->start + NLASTRIP_MIN_LEN_THRESH, data->next->start);
152                 }
153         }
154         else {
155                 CLAMP(value, data->start + NLASTRIP_MIN_LEN_THRESH, MAXFRAME);
156         }
157         data->end = value;
158         
159         
160         /* calculate the lengths the strip and its action (if applicable) */
161         if (data->type == NLASTRIP_TYPE_CLIP) {
162                 float len, actlen;
163                 
164                 len = data->end - data->start;
165                 actlen = data->actend - data->actstart;
166                 if (IS_EQF(actlen, 0.0f)) actlen = 1.0f;
167                 
168                 /* now, adjust the 'scale' setting to reflect this (so that this change can be valid) */
169                 data->scale = len / ((actlen) * data->repeat);
170         }
171 }
172
173 static void rna_NlaStrip_scale_set(PointerRNA *ptr, float value)
174 {
175         NlaStrip *data = (NlaStrip *)ptr->data;
176         
177         /* set scale value */
178         /* NOTE: these need to be synced with the values in the property definition in rna_def_nlastrip() */
179         CLAMP(value, 0.0001f, 1000.0f);
180         data->scale = value;
181         
182         /* adjust the strip extents in response to this */
183         BKE_nlastrip_recalculate_bounds(data);
184 }
185
186 static void rna_NlaStrip_repeat_set(PointerRNA *ptr, float value)
187 {
188         NlaStrip *data = (NlaStrip *)ptr->data;
189         
190         /* set repeat value */
191         /* NOTE: these need to be synced with the values in the property definition in rna_def_nlastrip() */
192         CLAMP(value, 0.01f, 1000.0f);
193         data->repeat = value;
194         
195         /* adjust the strip extents in response to this */
196         BKE_nlastrip_recalculate_bounds(data);
197 }
198
199 static void rna_NlaStrip_blend_in_set(PointerRNA *ptr, float value)
200 {
201         NlaStrip *data = (NlaStrip *)ptr->data;
202         float len;
203         
204         /* blend-in is limited to the length of the strip, and also cannot overlap with blendout */
205         len = (data->end - data->start) - data->blendout;
206         CLAMP(value, 0, len);
207         
208         data->blendin = value;
209 }
210
211 static void rna_NlaStrip_blend_out_set(PointerRNA *ptr, float value)
212 {
213         NlaStrip *data = (NlaStrip *)ptr->data;
214         float len;
215         
216         /* blend-out is limited to the length of the strip */
217         len = (data->end - data->start);
218         CLAMP(value, 0, len);
219         
220         /* it also cannot overlap with blendin */
221         if ((len - value) < data->blendin)
222                 value = len - data->blendin;
223         
224         data->blendout = value;
225 }
226
227 static int rna_NlaStrip_action_editable(PointerRNA *ptr)
228 {
229         NlaStrip *strip = (NlaStrip *)ptr->data;
230         
231         /* strip actions shouldn't be editable if NLA tweakmode is on */
232         if (ptr->id.data) {
233                 AnimData *adt = BKE_animdata_from_id(ptr->id.data);
234                 
235                 if (adt) {
236                         /* active action is only editable when it is not a tweaking strip */
237                         if ((adt->flag & ADT_NLA_EDIT_ON) || (adt->actstrip) || (adt->tmpact))
238                                 return 0;
239                 }
240         }
241         
242         /* check for clues that strip probably shouldn't be used... */
243         if (strip->flag & NLASTRIP_FLAG_TWEAKUSER)
244                 return 0;
245                 
246         /* should be ok, though we may still miss some cases */
247         return 1;
248 }
249
250 static void rna_NlaStrip_action_start_frame_set(PointerRNA *ptr, float value)
251 {
252         NlaStrip *data = (NlaStrip *)ptr->data;
253         
254         /* prevent start frame from occurring after end of action */
255         CLAMP(value, MINAFRAME, data->actend);
256         data->actstart = value;
257         
258         /* adjust the strip extents in response to this */
259         /* TODO: should the strip be moved backwards instead as a special case? */
260         BKE_nlastrip_recalculate_bounds(data);
261 }
262
263 static void rna_NlaStrip_action_end_frame_set(PointerRNA *ptr, float value)
264 {
265         NlaStrip *data = (NlaStrip *)ptr->data;
266         
267         /* prevent end frame from starting before start of action */
268         CLAMP(value, data->actstart, MAXFRAME);
269         data->actend = value;
270         
271         /* adjust the strip extents in response to this */
272         BKE_nlastrip_recalculate_bounds(data);
273 }
274
275 static void rna_NlaStrip_animated_influence_set(PointerRNA *ptr, int value)
276 {
277         NlaStrip *data = (NlaStrip *)ptr->data;
278         
279         if (value) {
280                 /* set the flag, then make sure a curve for this exists */
281                 data->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
282                 BKE_nlastrip_validate_fcurves(data);
283         }
284         else
285                 data->flag &= ~NLASTRIP_FLAG_USR_INFLUENCE;
286 }
287
288 static void rna_NlaStrip_animated_time_set(PointerRNA *ptr, int value)
289 {
290         NlaStrip *data = (NlaStrip *)ptr->data;
291         
292         if (value) {
293                 /* set the flag, then make sure a curve for this exists */
294                 data->flag |= NLASTRIP_FLAG_USR_TIME;
295                 BKE_nlastrip_validate_fcurves(data);
296         }
297         else
298                 data->flag &= ~NLASTRIP_FLAG_USR_TIME;
299 }
300
301 static NlaStrip *rna_NlaStrip_new(NlaTrack *track, bContext *C, ReportList *reports, const char *UNUSED(name),
302                                   int start, bAction *action)
303 {
304         NlaStrip *strip = add_nlastrip(action);
305         
306         if (strip == NULL) {
307                 BKE_report(reports, RPT_ERROR, "Unable to create new strip");
308                 return NULL;
309         }
310         
311         strip->end += (start - strip->start);
312         strip->start = start;
313         
314         if (BKE_nlastrips_add_strip(&track->strips, strip) == 0) {
315                 BKE_report(reports, RPT_ERROR,
316                            "Unable to add strip (the track does not have any space to accommodate this new strip)");
317                 free_nlastrip(NULL, strip);
318                 return NULL;
319         }
320         
321         /* create dummy AnimData block so that BKE_nlastrip_validate_name()
322          * can be used to ensure a valid name, as we don't have one here...
323          *  - only the nla_tracks list is needed there, which we aim to reverse engineer here...
324          */
325         {
326                 AnimData adt = {NULL};
327                 NlaTrack *nlt, *nlt_p;
328                 
329                 /* 'first' NLA track is found by going back up chain of given track's parents until we fall off */
330                 nlt_p = track; nlt = track;
331                 while ((nlt = nlt->prev) != NULL)
332                         nlt_p = nlt;
333                 adt.nla_tracks.first = nlt_p;
334                 
335                 /* do the same thing to find the last track */
336                 nlt_p = track; nlt = track;
337                 while ((nlt = nlt->next) != NULL)
338                         nlt_p = nlt;
339                 adt.nla_tracks.last = nlt_p;
340                 
341                 /* now we can just auto-name as usual */
342                 BKE_nlastrip_validate_name(&adt, strip);
343         }
344         
345         WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL);
346         
347         return strip;
348 }
349
350 static void rna_NlaStrip_remove(NlaTrack *track, bContext *C, ReportList *reports, PointerRNA *strip_ptr)
351 {
352         NlaStrip *strip = strip_ptr->data;
353         if (BLI_findindex(&track->strips, strip) == -1) {
354                 BKE_reportf(reports, RPT_ERROR, "NLA strip '%s' not found in track '%s'", strip->name, track->name);
355                 return;
356         }
357
358         free_nlastrip(&track->strips, strip);
359         RNA_POINTER_INVALIDATE(strip_ptr);
360
361         WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL);
362 }
363
364 /* Set the 'solo' setting for the given NLA-track, making sure that it is the only one
365  * that has this status in its AnimData block.
366  */
367 static void rna_NlaTrack_solo_set(PointerRNA *ptr, int value)
368 {
369         NlaTrack *data = (NlaTrack *)ptr->data;
370         AnimData *adt = BKE_animdata_from_id(ptr->id.data);
371         NlaTrack *nt;
372
373         if (data == NULL) {
374                 return;
375         }
376         
377         /* firstly, make sure 'solo' flag for all tracks is disabled */
378         for (nt = data; nt; nt = nt->next) {
379                 nt->flag &= ~NLATRACK_SOLO;
380         }
381         for (nt = data; nt; nt = nt->prev) {
382                 nt->flag &= ~NLATRACK_SOLO;
383         }
384                 
385         /* now, enable 'solo' for the given track if appropriate */
386         if (value) {
387                 /* set solo status */
388                 data->flag |= NLATRACK_SOLO;
389                 
390                 /* set solo-status on AnimData */
391                 adt->flag |= ADT_NLA_SOLO_TRACK;
392         }
393         else {
394                 /* solo status was already cleared on track */
395
396                 /* clear solo-status on AnimData */
397                 adt->flag &= ~ADT_NLA_SOLO_TRACK;
398         }
399 }
400
401 #else
402
403 /* enum defines exported for rna_animation.c */
404 EnumPropertyItem nla_mode_blend_items[] = {
405         {NLASTRIP_MODE_REPLACE, "REPLACE", 0, "Replace",
406                                 "Result strip replaces the accumulated results by amount specified by influence"},
407         {NLASTRIP_MODE_ADD, "ADD", 0, "Add", "Weighted result of strip is added to the accumulated results"},
408         {NLASTRIP_MODE_SUBTRACT, "SUBTRACT", 0, "Subtract",
409                                  "Weighted result of strip is removed from the accumulated results"},
410         {NLASTRIP_MODE_MULTIPLY, "MULITPLY", 0, "Multiply",
411                                  "Weighted result of strip is multiplied with the accumulated results"},
412         {0, NULL, 0, NULL, NULL}};
413 EnumPropertyItem nla_mode_extend_items[] = {
414         {NLASTRIP_EXTEND_NOTHING, "NOTHING", 0, "Nothing", "Strip has no influence past its extents"},
415         {NLASTRIP_EXTEND_HOLD, "HOLD", 0, "Hold",
416                                "Hold the first frame if no previous strips in track, and always hold last frame"},
417         {NLASTRIP_EXTEND_HOLD_FORWARD, "HOLD_FORWARD", 0, "Hold Forward", "Only hold last frame"},
418         {0, NULL, 0, NULL, NULL}
419 };
420
421 static void rna_def_nlastrip(BlenderRNA *brna)
422 {
423         StructRNA *srna;
424         PropertyRNA *prop;
425         
426         /* enum defs */
427         static EnumPropertyItem prop_type_items[] = {
428                 {NLASTRIP_TYPE_CLIP, "CLIP", 0, "Action Clip", "NLA Strip references some Action"},
429                 {NLASTRIP_TYPE_TRANSITION, "TRANSITION", 0, "Transition", "NLA Strip 'transitions' between adjacent strips"},
430                 {NLASTRIP_TYPE_META, "META", 0, "Meta", "NLA Strip acts as a container for adjacent strips"},
431                 {NLASTRIP_TYPE_SOUND, "SOUND", 0, "Sound Clip", "NLA Strip representing a sound event for speakers"},
432                 {0, NULL, 0, NULL, NULL}
433         };
434         
435         /* struct definition */
436         srna = RNA_def_struct(brna, "NlaStrip", NULL);
437         RNA_def_struct_ui_text(srna, "NLA Strip", "A container referencing an existing Action");
438         RNA_def_struct_path_func(srna, "rna_NlaStrip_path");
439         RNA_def_struct_ui_icon(srna, ICON_NLA); /* XXX */
440         
441         /* name property */
442         prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
443         RNA_def_property_ui_text(prop, "Name", "");
444         RNA_def_property_string_funcs(prop, NULL, NULL, "rna_NlaStrip_name_set");
445         RNA_def_struct_name_property(srna, prop);
446         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
447         
448         /* Enums */
449         prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
450         RNA_def_property_enum_sdna(prop, NULL, "type");
451         RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* XXX for now, not editable, since this is dangerous */
452         RNA_def_property_enum_items(prop, prop_type_items);
453         RNA_def_property_ui_text(prop, "Type", "Type of NLA Strip");
454         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
455         
456         prop = RNA_def_property(srna, "extrapolation", PROP_ENUM, PROP_NONE);
457         RNA_def_property_enum_sdna(prop, NULL, "extendmode");
458         RNA_def_property_enum_items(prop, nla_mode_extend_items);
459         RNA_def_property_ui_text(prop, "Extrapolation", "Action to take for gaps past the strip extents");
460         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
461         
462         prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE);
463         RNA_def_property_enum_sdna(prop, NULL, "blendmode");
464         RNA_def_property_enum_items(prop, nla_mode_blend_items);
465         RNA_def_property_ui_text(prop, "Blending", "Method used for combining strip's result with accumulated result");
466         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
467         
468         /* Strip extents */
469         prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_TIME);
470         RNA_def_property_float_sdna(prop, NULL, "start");
471         RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_start_frame_set", NULL);
472         RNA_def_property_ui_text(prop, "Start Frame", "");
473         RNA_def_property_update(prop, 0, "rna_NlaStrip_transform_update");
474         
475         prop = RNA_def_property(srna, "frame_end", PROP_FLOAT, PROP_TIME);
476         RNA_def_property_float_sdna(prop, NULL, "end");
477         RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_end_frame_set", NULL);
478         RNA_def_property_ui_text(prop, "End Frame", "");
479         RNA_def_property_update(prop, 0, "rna_NlaStrip_transform_update");
480         
481         /* Blending */
482         prop = RNA_def_property(srna, "blend_in", PROP_FLOAT, PROP_NONE);
483         RNA_def_property_float_sdna(prop, NULL, "blendin");
484         RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_blend_in_set", NULL);
485         RNA_def_property_ui_text(prop, "Blend In", "Number of frames at start of strip to fade in influence");
486         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
487         
488         prop = RNA_def_property(srna, "blend_out", PROP_FLOAT, PROP_NONE);
489         RNA_def_property_float_sdna(prop, NULL, "blendout");
490         RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_blend_out_set", NULL);
491         RNA_def_property_ui_text(prop, "Blend Out", "");
492         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
493         
494         prop = RNA_def_property(srna, "use_auto_blend", PROP_BOOLEAN, PROP_NONE);
495         RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_AUTO_BLENDS);
496         RNA_def_property_ui_text(prop, "Auto Blend In/Out",
497                                  "Number of frames for Blending In/Out is automatically determined from "
498                                  "overlapping strips");
499         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
500         
501         /* Action */
502         prop = RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE);
503         RNA_def_property_pointer_sdna(prop, NULL, "act");
504         RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Action_id_poll");
505         RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
506         RNA_def_property_editable_func(prop, "rna_NlaStrip_action_editable");
507         RNA_def_property_ui_text(prop, "Action", "Action referenced by this strip");
508         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
509         
510         /* Action extents */
511         prop = RNA_def_property(srna, "action_frame_start", PROP_FLOAT, PROP_TIME);
512         RNA_def_property_float_sdna(prop, NULL, "actstart");
513         RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_action_start_frame_set", NULL);
514         RNA_def_property_ui_text(prop, "Action Start Frame", "");
515         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
516         
517         prop = RNA_def_property(srna, "action_frame_end", PROP_FLOAT, PROP_TIME);
518         RNA_def_property_float_sdna(prop, NULL, "actend");
519         RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_action_end_frame_set", NULL);
520         RNA_def_property_ui_text(prop, "Action End Frame", "");
521         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
522         
523         /* Action Reuse */
524         prop = RNA_def_property(srna, "repeat", PROP_FLOAT, PROP_NONE);
525         RNA_def_property_float_sdna(prop, NULL, "repeat");
526         RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_repeat_set", NULL);
527         /* these limits have currently be chosen arbitrarily, but could be extended
528          * (minimum should still be > 0 though) if needed... */
529         RNA_def_property_range(prop, 0.1f, 1000.0f);
530         RNA_def_property_ui_text(prop, "Repeat", "Number of times to repeat the action range");
531         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
532         
533         prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE);
534         RNA_def_property_float_sdna(prop, NULL, "scale");
535         RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_scale_set", NULL);
536         /* these limits can be extended, but beyond this, we can get some crazy+annoying bugs
537          * due to numeric errors */
538         RNA_def_property_range(prop, 0.0001f, 1000.0f);
539         RNA_def_property_ui_text(prop, "Scale", "Scaling factor for action");
540         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
541         
542         /* Strip's F-Curves */
543         prop = RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE);
544         RNA_def_property_struct_type(prop, "FCurve");
545         RNA_def_property_ui_text(prop, "F-Curves", "F-Curves for controlling the strip's influence and timing");
546         
547         /* Strip's F-Modifiers */
548         prop = RNA_def_property(srna, "modifiers", PROP_COLLECTION, PROP_NONE);
549         RNA_def_property_struct_type(prop, "FModifier");
550         RNA_def_property_ui_text(prop, "Modifiers", "Modifiers affecting all the F-Curves in the referenced Action");
551         
552         /* Strip's Sub-Strips (for Meta-Strips) */
553         prop = RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE);
554         RNA_def_property_struct_type(prop, "NlaStrip");
555         RNA_def_property_ui_text(prop, "NLA Strips",
556                                  "NLA Strips that this strip acts as a container for (if it is of type Meta)");
557         
558         /* Settings - Values necessary for evaluation */
559         prop = RNA_def_property(srna, "influence", PROP_FLOAT, PROP_NONE);
560         RNA_def_property_range(prop, 0.0f, 1.0f);
561         RNA_def_property_ui_text(prop, "Influence", "Amount the strip contributes to the current result");
562         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
563         
564         prop = RNA_def_property(srna, "strip_time", PROP_FLOAT, PROP_TIME);
565         RNA_def_property_ui_text(prop, "Strip Time", "Frame of referenced Action to evaluate");
566         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
567         
568         /* TODO: should the animated_influence/time settings be animatable themselves? */
569         prop = RNA_def_property(srna, "use_animated_influence", PROP_BOOLEAN, PROP_NONE);
570         RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_INFLUENCE);
571         RNA_def_property_boolean_funcs(prop, NULL, "rna_NlaStrip_animated_influence_set");
572         RNA_def_property_ui_text(prop, "Animated Influence",
573                                  "Influence setting is controlled by an F-Curve rather than automatically determined");
574         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
575         
576         prop = RNA_def_property(srna, "use_animated_time", PROP_BOOLEAN, PROP_NONE);
577         RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_TIME);
578         RNA_def_property_boolean_funcs(prop, NULL, "rna_NlaStrip_animated_time_set");
579         RNA_def_property_ui_text(prop, "Animated Strip Time",
580                                  "Strip time is controlled by an F-Curve rather than automatically determined");
581         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
582         
583         prop = RNA_def_property(srna, "use_animated_time_cyclic", PROP_BOOLEAN, PROP_NONE);
584         RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_TIME_CYCLIC);
585         RNA_def_property_ui_text(prop, "Cyclic Strip Time", "Cycle the animated time within the action start & end");
586         RNA_def_property_update(prop, 0, "rna_NlaStrip_transform_update"); /* is there a better update flag? */
587         
588         /* settings */
589         prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
590         /* can be made editable by hooking it up to the necessary NLA API methods */
591         RNA_def_property_clear_flag(prop, PROP_EDITABLE);
592         RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_ACTIVE);
593         RNA_def_property_ui_text(prop, "Active", "NLA Strip is active");
594         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
595         
596         prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
597         RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_SELECT);
598         RNA_def_property_ui_text(prop, "Select", "NLA Strip is selected");
599         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
600         
601         prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
602         RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_MUTED);
603         RNA_def_property_ui_text(prop, "Muted", "NLA Strip is not evaluated");
604         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
605         
606         prop = RNA_def_property(srna, "use_reverse", PROP_BOOLEAN, PROP_NONE);
607         RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_REVERSE);
608         RNA_def_property_ui_text(prop, "Reversed",
609                                  "NLA Strip is played back in reverse order (only when timing is "
610                                  "automatically determined)");
611         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
612         
613         /* TODO:  */
614         /* - sync length */
615 }
616
617 static void rna_api_nlatrack_strips(BlenderRNA *brna, PropertyRNA *cprop)
618 {
619         StructRNA *srna;
620         PropertyRNA *parm;
621         FunctionRNA *func;
622
623         RNA_def_property_srna(cprop, "NlaStrips");
624         srna = RNA_def_struct(brna, "NlaStrips", NULL);
625         RNA_def_struct_sdna(srna, "NlaTrack");
626         RNA_def_struct_ui_text(srna, "Nla Strips", "Collection of Nla Strips");
627
628         func = RNA_def_function(srna, "new", "rna_NlaStrip_new");
629         RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
630         RNA_def_function_ui_description(func, "Add a new Action-Clip strip to the track");
631         parm = RNA_def_string(func, "name", "NlaStrip", 0, "", "Name for the NLA Strips");
632         RNA_def_property_flag(parm, PROP_REQUIRED);
633         parm = RNA_def_int(func, "start", 0, INT_MIN, INT_MAX, "Start Frame",
634                            "Start frame for this strip", INT_MIN, INT_MAX);
635         RNA_def_property_flag(parm, PROP_REQUIRED);
636         parm = RNA_def_pointer(func, "action", "Action", "", "Action to assign to this strip");
637         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
638         /* return type */
639         parm = RNA_def_pointer(func, "strip", "NlaStrip", "", "New NLA Strip");
640         RNA_def_function_return(func, parm);
641
642         func = RNA_def_function(srna, "remove", "rna_NlaStrip_remove");
643         RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
644         RNA_def_function_ui_description(func, "Remove a NLA Strip");
645         parm = RNA_def_pointer(func, "strip", "NlaStrip", "", "NLA Strip to remove");
646         RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
647         RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
648 }
649
650 static void rna_def_nlatrack(BlenderRNA *brna)
651 {
652         StructRNA *srna;
653         PropertyRNA *prop;
654         
655         srna = RNA_def_struct(brna, "NlaTrack", NULL);
656         RNA_def_struct_ui_text(srna, "NLA Track", "A animation layer containing Actions referenced as NLA strips");
657         RNA_def_struct_ui_icon(srna, ICON_NLA);
658         
659         /* strips collection */
660         prop = RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE);
661         RNA_def_property_struct_type(prop, "NlaStrip");
662         RNA_def_property_ui_text(prop, "NLA Strips", "NLA Strips on this NLA-track");
663
664         rna_api_nlatrack_strips(brna, prop);
665
666         /* name property */
667         prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
668         RNA_def_property_ui_text(prop, "Name", "");
669         RNA_def_struct_name_property(srna, prop);
670         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
671         
672         /* settings */
673         prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
674         /* can be made editable by hooking it up to the necessary NLA API methods */
675         RNA_def_property_clear_flag(prop, PROP_EDITABLE);
676         RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_ACTIVE);
677         RNA_def_property_ui_text(prop, "Active", "NLA Track is active");
678         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
679         
680         prop = RNA_def_property(srna, "is_solo", PROP_BOOLEAN, PROP_NONE);
681         /* can be made editable by hooking it up to the necessary NLA API methods */
682         RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_SOLO);
683         RNA_def_property_ui_text(prop, "Solo",
684                                  "NLA Track is evaluated itself (i.e. active Action and all other NLA Tracks in the "
685                                  "same AnimData block are disabled)");
686         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
687         RNA_def_property_boolean_funcs(prop, NULL, "rna_NlaTrack_solo_set");
688
689         prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
690         RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_SELECTED);
691         RNA_def_property_ui_text(prop, "Select", "NLA Track is selected");
692         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
693         
694         prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
695         RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_MUTED);
696         RNA_def_property_ui_text(prop, "Muted", "NLA Track is not evaluated");
697         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
698
699         prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE);
700         RNA_def_property_boolean_sdna(prop, NULL, "flag", NLATRACK_PROTECTED);
701         RNA_def_property_ui_text(prop, "Locked", "NLA Track is locked");
702         RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
703 }
704
705 /* --------- */
706
707 void RNA_def_nla(BlenderRNA *brna)
708 {
709         rna_def_nlatrack(brna);
710         rna_def_nlastrip(brna);
711 }
712
713
714 #endif