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