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