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