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