diff options
-rw-r--r-- | release/scripts/startup/bl_ui/space_dopesheet.py | 32 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_nla.py | 17 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_action.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/action.c | 18 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/nla.c | 9 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_draw.c | 68 | ||||
-rw-r--r-- | source/blender/editors/include/ED_anim_api.h | 7 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_data.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_draw.c | 55 | ||||
-rw-r--r-- | source/blender/editors/space_action/space_action.c | 9 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_draw.c | 9 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_edit.c | 13 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_action_types.h | 6 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_action.c | 104 |
14 files changed, 341 insertions, 12 deletions
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 9b8f1cfeb0d..6e5eba7b734 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -539,6 +539,37 @@ class DOPESHEET_MT_key_transform(Menu): layout.operator("transform.transform", text="Scale").mode = 'TIME_SCALE' +class DopesheetActionPanelBase: + bl_region_type = 'UI' + bl_label = "Action" + + @classmethod + def draw_generic_panel(cls, context, layout, action): + layout.label(text=action.name, icon='ACTION') + + layout.prop(action, "use_frame_range") + + col = layout.column() + col.active = action.use_frame_range + + row = col.row(align=True) + row.prop(action, "frame_start", text="Start") + row.prop(action, "frame_end", text="End") + + +class DOPESHEET_PT_action(DopesheetActionPanelBase, Panel): + bl_space_type = 'DOPESHEET_EDITOR' + bl_category = "Item" + + @classmethod + def poll(cls, context): + return bool(context.selected_visible_actions) + + def draw(self, context): + action = context.selected_visible_actions[0] + self.draw_generic_panel(context, self.layout, action) + + ####################################### # Grease Pencil Editing @@ -792,6 +823,7 @@ classes = ( DOPESHEET_MT_snap_pie, DOPESHEET_MT_view_pie, DOPESHEET_PT_filters, + DOPESHEET_PT_action, DOPESHEET_PT_gpencil_mode, DOPESHEET_PT_gpencil_layer_masks, DOPESHEET_PT_gpencil_layer_transform, diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py index 9507d8296a9..62c02799a9f 100644 --- a/release/scripts/startup/bl_ui/space_nla.py +++ b/release/scripts/startup/bl_ui/space_nla.py @@ -22,6 +22,7 @@ from bpy.types import Header, Menu, Panel from bpy.app.translations import contexts as i18n_contexts from bl_ui.space_dopesheet import ( DopesheetFilterPopoverBase, + DopesheetActionPanelBase, dopesheet_filter, ) @@ -66,6 +67,21 @@ class NLA_PT_filters(DopesheetFilterPopoverBase, Panel): DopesheetFilterPopoverBase.draw_standard_filters(context, layout) +class NLA_PT_action(DopesheetActionPanelBase, Panel): + bl_space_type = 'NLA_EDITOR' + bl_category = "Strip" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + strip = context.active_nla_strip + return strip and strip.type == 'CLIP' and strip.action + + def draw(self, context): + action = context.active_nla_strip.action + self.draw_generic_panel(context, self.layout, action) + + class NLA_MT_editor_menus(Menu): bl_idname = "NLA_MT_editor_menus" bl_label = "" @@ -316,6 +332,7 @@ classes = ( NLA_MT_context_menu, NLA_MT_channel_context_menu, NLA_PT_filters, + NLA_PT_action, ) if __name__ == "__main__": # only for live edit. diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 763e540fdd9..6d457ed32f0 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -91,6 +91,10 @@ short action_get_item_transforms(struct bAction *act, /* Some kind of bounding box operation on the action */ void calc_action_range(const struct bAction *act, float *start, float *end, short incl_modifiers); +/* Retrieve the intended playback frame range, using the manually set range if available, + * or falling back to scanning F-Curves for their first & last frames otherwise. */ +void BKE_action_get_frame_range(const struct bAction *act, float *r_start, float *r_end); + /* Does action have any motion data at all? */ bool action_has_motion(const struct bAction *act); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 27873f19977..47db5183e76 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1573,6 +1573,24 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_ } } +/* Retrieve the intended playback frame range, using the manually set range if available, + * or falling back to scanning F-Curves for their first & last frames otherwise. */ +void BKE_action_get_frame_range(const struct bAction *act, float *r_start, float *r_end) +{ + if (act && (act->flag & ACT_FRAME_RANGE)) { + *r_start = act->frame_start; + *r_end = act->frame_end; + } + else { + calc_action_range(act, r_start, r_end, false); + } + + /* Ensure that action is at least 1 frame long (for NLA strips to have a valid length). */ + if (*r_start >= *r_end) { + *r_end = *r_start + 1.0f; + } +} + /* Return flags indicating which transforms the given object/posechannel has * - if 'curves' is provided, a list of links to these curves are also returned */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 124db07298d..0666c1dfc53 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -390,6 +390,11 @@ NlaStrip *BKE_nlastrip_new(bAction *act) */ strip->flag = NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_SYNC_LENGTH; + /* Disable sync for actions with a manual frame range, since it only syncs to range anyway. */ + if (act->flag & ACT_FRAME_RANGE) { + strip->flag &= ~NLASTRIP_FLAG_SYNC_LENGTH; + } + /* assign the action reference */ strip->act = act; id_us_plus(&act->id); @@ -397,7 +402,7 @@ NlaStrip *BKE_nlastrip_new(bAction *act) /* determine initial range * - strip length cannot be 0... ever... */ - calc_action_range(strip->act, &strip->actstart, &strip->actend, 0); + BKE_action_get_frame_range(strip->act, &strip->actstart, &strip->actend); strip->start = strip->actstart; strip->end = (IS_EQF(strip->actstart, strip->actend)) ? (strip->actstart + 1.0f) : @@ -1444,7 +1449,7 @@ void BKE_nlastrip_recalculate_bounds_sync_action(NlaStrip *strip) prev_actstart = strip->actstart; - calc_action_range(strip->act, &strip->actstart, &strip->actend, 0); + BKE_action_get_frame_range(strip->act, &strip->actstart, &strip->actend); /* Set start such that key's do not visually move, to preserve the overall animation result. */ strip->start += (strip->actstart - prev_actstart) * strip->scale; diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 993d10cf303..f5a5609aa2e 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -168,6 +168,74 @@ void ANIM_draw_framerange(Scene *scene, View2D *v2d) immUnbindProgram(); } +/** + * Draw manually set intended playback frame range guides for the action in the background. + * Allows specifying a subset of the Y range of the view. + */ +void ANIM_draw_action_framerange( + AnimData *adt, bAction *action, View2D *v2d, float ymin, float ymax) +{ + if ((action->flag & ACT_FRAME_RANGE) == 0) { + return; + } + + /* Compute the dimensions. */ + CLAMP_MIN(ymin, v2d->cur.ymin); + CLAMP_MAX(ymax, v2d->cur.ymax); + + if (ymin > ymax) { + return; + } + + const float sfra = BKE_nla_tweakedit_remap(adt, action->frame_start, NLATIME_CONVERT_MAP); + const float efra = BKE_nla_tweakedit_remap(adt, action->frame_end, NLATIME_CONVERT_MAP); + + /* Diagonal stripe filled area outside of the frame range. */ + GPU_blend(GPU_BLEND_ALPHA); + + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES); + + float color[4]; + UI_GetThemeColorShadeAlpha4fv(TH_BACK, -40, -50, color); + + immUniform4f("color1", color[0], color[1], color[2], color[3]); + immUniform4f("color2", 0.0f, 0.0f, 0.0f, 0.0f); + immUniform1i("size1", 2 * U.dpi_fac); + immUniform1i("size2", 4 * U.dpi_fac); + + if (sfra < efra) { + immRectf(pos, v2d->cur.xmin, ymin, sfra, ymax); + immRectf(pos, efra, ymin, v2d->cur.xmax, ymax); + } + else { + immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax, ymax); + } + + immUnbindProgram(); + + GPU_blend(GPU_BLEND_NONE); + + /* Thin lines where the actual frames are. */ + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColorShade(TH_BACK, -60); + + GPU_line_width(1.0f); + + immBegin(GPU_PRIM_LINES, 4); + + immVertex2f(pos, sfra, ymin); + immVertex2f(pos, sfra, ymax); + + immVertex2f(pos, efra, ymin); + immVertex2f(pos, efra, ymax); + + immEnd(); + immUnbindProgram(); +} + /* *************************************************** */ /* NLA-MAPPING UTILITIES (required for drawing and also editing keyframes). */ diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 5d5d9140a24..cab4c18211d 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -676,6 +676,10 @@ void ANIM_draw_previewrange(const struct bContext *C, struct View2D *v2d, int en /* main call to draw normal frame range indicators */ void ANIM_draw_framerange(struct Scene *scene, struct View2D *v2d); +/* Draw manually set intended playback frame range indicators for the action. */ +void ANIM_draw_action_framerange( + struct AnimData *adt, struct bAction *action, struct View2D *v2d, float ymin, float ymax); + /* ************************************************* */ /* F-MODIFIER TOOLS */ @@ -864,7 +868,8 @@ void ED_operatormacros_action(void); /* XXX: Should we be doing these here, or at all? */ /* Action Editor - Action Management */ -struct AnimData *ED_actedit_animdata_from_context(struct bContext *C, struct ID **r_adt_id_owner); +struct AnimData *ED_actedit_animdata_from_context(const struct bContext *C, + struct ID **r_adt_id_owner); void ED_animedit_unlink_action(struct bContext *C, struct ID *id, struct AnimData *adt, diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index 9ff46d96207..57f9138ec3a 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -71,7 +71,7 @@ /* ACTION CREATION */ /* Helper function to find the active AnimData block from the Action Editor context */ -AnimData *ED_actedit_animdata_from_context(bContext *C, ID **r_adt_id_owner) +AnimData *ED_actedit_animdata_from_context(const bContext *C, ID **r_adt_id_owner) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); Object *ob = CTX_data_active_object(C); diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index 6f1a90e56a5..bc13b7f2b1b 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -131,6 +131,54 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region) /* extra padding for lengths (to go under scrollers) */ #define EXTRA_SCROLL_PAD 100.0f +/* Draw manually set intended playback frame ranges for actions. */ +static void draw_channel_action_ranges(bAnimContext *ac, ListBase *anim_data, View2D *v2d) +{ + /* Variables for coalescing the Y region of one action. */ + bAction *cur_action = NULL; + AnimData *cur_adt = NULL; + float cur_ymax; + + /* Walk through channels, grouping contiguous spans referencing the same action. */ + float ymax = ACHANNEL_FIRST_TOP(ac) + ACHANNEL_SKIP / 2; + float ystep = ACHANNEL_STEP(ac); + float ymin = ymax - ystep; + + for (bAnimListElem *ale = anim_data->first; ale; ale = ale->next, ymax = ymin, ymin -= ystep) { + bAction *action = NULL; + AnimData *adt = NULL; + + /* check if visible */ + if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) || + IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) { + /* check if anything to show for this channel */ + if (ale->datatype != ALE_NONE) { + action = ANIM_channel_action_get(ale); + + if (action) { + adt = ale->adt; + } + } + } + + /* Extend the current region, or flush and restart. */ + if (action != cur_action || adt != cur_adt) { + if (cur_action) { + ANIM_draw_action_framerange(cur_adt, cur_action, v2d, ymax, cur_ymax); + } + + cur_action = action; + cur_adt = adt; + cur_ymax = ymax; + } + } + + /* Flush the last region. */ + if (cur_action) { + ANIM_draw_action_framerange(cur_adt, cur_action, v2d, ymax, cur_ymax); + } +} + /* draw keyframes in each channel */ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region) { @@ -166,6 +214,13 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region int height = ACHANNEL_TOT_HEIGHT(ac, items); v2d->tot.ymin = -height; + /* Draw the manual frame ranges for actions in the background of the dopesheet. + * The action editor has already drawn the range for its action so it's not needed. */ + if (ac->datatype == ANIMCONT_DOPESHEET) { + draw_channel_action_ranges(ac, &anim_data, v2d); + } + + /* Draw the background strips. */ GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 738eeb21e2e..ebb28f3a208 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -25,6 +25,7 @@ #include <string.h> #include "DNA_action_types.h" +#include "DNA_anim_types.h" #include "DNA_collection_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -35,6 +36,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_nla.h" #include "BKE_screen.h" #include "RNA_access.h" @@ -204,6 +206,13 @@ static void action_main_region_draw(const bContext *C, ARegion *region) /* start and end frame */ ANIM_draw_framerange(scene, v2d); + /* Draw the manually set intended playback frame range highlight in the Action editor. */ + if (ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY) && saction->action) { + AnimData *adt = ED_actedit_animdata_from_context(C, NULL); + + ANIM_draw_action_framerange(adt, saction->action, v2d, -FLT_MAX, FLT_MAX); + } + /* data */ if (ANIM_animdata_get_context(C, &ac)) { draw_channel_strips(&ac, saction, region); diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index bf2d20cf4c9..4f335a0d13a 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -111,11 +111,11 @@ static void nla_action_draw_keyframes( /* draw a darkened region behind the strips * - get and reset the background color, this time without the alpha to stand out better - * (amplified alpha is used instead) + * (amplified alpha is used instead, but clamped to avoid 100% opacity) */ float color[4]; nla_action_get_color(adt, act, color); - color[3] *= 2.5f; + color[3] = min_ff(0.7f, color[3] * 2.5f); GPUVertFormat *format = immVertexFormat(); uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); @@ -786,6 +786,11 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *region) case ANIMTYPE_NLAACTION: { AnimData *adt = ale->adt; + /* Draw the manually set intended playback frame range highlight. */ + if (ale->data) { + ANIM_draw_action_framerange(adt, ale->data, v2d, ymin, ymax); + } + uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 62f8906d136..9f42e6378ca 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -2193,8 +2193,19 @@ static int nlaedit_apply_scale_exec(bContext *C, wmOperator *UNUSED(op)) * and recalculate the extents of the action now that it has been scaled * but leave everything else alone */ + const float start = nlastrip_get_frame(strip, strip->actstart, NLATIME_CONVERT_MAP); + const float end = nlastrip_get_frame(strip, strip->actend, NLATIME_CONVERT_MAP); + + if (strip->act->flag & ACT_FRAME_RANGE) { + strip->act->frame_start = nlastrip_get_frame( + strip, strip->act->frame_start, NLATIME_CONVERT_MAP); + strip->act->frame_end = nlastrip_get_frame( + strip, strip->act->frame_end, NLATIME_CONVERT_MAP); + } + strip->scale = 1.0f; - calc_action_range(strip->act, &strip->actstart, &strip->actend, 0); + strip->actstart = start; + strip->actend = end; ale->update |= ANIM_UPDATE_DEPS; } diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index e899e6bd3ec..9d1de4c0c36 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -682,6 +682,10 @@ typedef struct bAction { int idroot; char _pad[4]; + /** Start and end of the manually set intended playback frame range. Used by UI and + * some editing tools, but doesn't directly affect animation evaluation in any way. */ + float frame_start, frame_end; + PreviewImage *preview; } bAction; @@ -695,6 +699,8 @@ typedef enum eAction_Flags { ACT_MUTED = (1 << 9), /* ACT_PROTECTED = (1 << 10), */ /* UNUSED */ /* ACT_DISABLED = (1 << 11), */ /* UNUSED */ + /** The action has a manually set intended playback frame range. */ + ACT_FRAME_RANGE = (1 << 12), } eAction_Flags; /* ************************************************ */ diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 2aa09a30c75..db2c415c918 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -246,12 +246,60 @@ static void rna_Action_active_pose_marker_index_range( *max = max_ii(0, BLI_listbase_count(&act->markers) - 1); } -static void rna_Action_frame_range_get(PointerRNA *ptr, float *values) +static void rna_Action_frame_range_get(PointerRNA *ptr, float *r_values) +{ + BKE_action_get_frame_range((bAction *)ptr->owner_id, &r_values[0], &r_values[1]); +} + +static void rna_Action_frame_range_set(PointerRNA *ptr, const float *values) +{ + bAction *data = (bAction *)ptr->owner_id; + + data->flag |= ACT_FRAME_RANGE; + data->frame_start = values[0]; + data->frame_end = values[1]; + CLAMP_MIN(data->frame_end, data->frame_start); +} + +static void rna_Action_curve_frame_range_get(PointerRNA *ptr, float *values) { /* don't include modifiers because they too easily can have very large * ranges: MINAFRAMEF to MAXFRAMEF. */ calc_action_range((bAction *)ptr->owner_id, values, values + 1, false); } +static void rna_Action_use_frame_range_set(PointerRNA *ptr, bool value) +{ + bAction *data = (bAction *)ptr->owner_id; + + if (value) { + /* If the frame range is blank, initialize it by scanning F-Curves. */ + if ((data->frame_start == data->frame_end) && (data->frame_start == 0)) { + calc_action_range(data, &data->frame_start, &data->frame_end, false); + } + + data->flag |= ACT_FRAME_RANGE; + } + else { + data->flag &= ~ACT_FRAME_RANGE; + } +} + +static void rna_Action_start_frame_set(PointerRNA *ptr, float value) +{ + bAction *data = (bAction *)ptr->owner_id; + + data->frame_start = value; + CLAMP_MIN(data->frame_end, data->frame_start); +} + +static void rna_Action_end_frame_set(PointerRNA *ptr, float value) +{ + bAction *data = (bAction *)ptr->owner_id; + + data->frame_end = value; + CLAMP_MAX(data->frame_start, data->frame_end); +} + /* Used to check if an action (value pointer) * is suitable to be assigned to the ID-block that is ptr. */ bool rna_Action_id_poll(PointerRNA *ptr, PointerRNA value) @@ -834,17 +882,63 @@ static void rna_def_action(BlenderRNA *brna) rna_def_action_pose_markers(brna, prop); /* properties */ + prop = RNA_def_property(srna, "use_frame_range", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_FRAME_RANGE); + RNA_def_property_boolean_funcs(prop, NULL, "rna_Action_use_frame_range_set"); + RNA_def_property_ui_text( + prop, + "Manual Frame Range", + "Manually specify the intended playback frame range for the action " + "(this range is used by some tools, but does not affect animation evaluation)"); + RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + + prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_TIME); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_float_sdna(prop, NULL, "frame_start"); + RNA_def_property_float_funcs(prop, NULL, "rna_Action_start_frame_set", NULL); + RNA_def_property_ui_range(prop, MINFRAME, MAXFRAME, 100, 0); + RNA_def_property_ui_text( + prop, "Start Frame", "The start frame of the manually set intended playback range"); + RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + + prop = RNA_def_property(srna, "frame_end", PROP_FLOAT, PROP_TIME); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_float_sdna(prop, NULL, "frame_end"); + RNA_def_property_float_funcs(prop, NULL, "rna_Action_end_frame_set", NULL); + RNA_def_property_ui_range(prop, MINFRAME, MAXFRAME, 100, 0); + RNA_def_property_ui_text( + prop, "End Frame", "The end frame of the manually set intended playback range"); + RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + + prop = RNA_def_float_vector( + srna, + "frame_range", + 2, + NULL, + 0, + 0, + "Frame Range", + "The intended playback frame range of this action, using the manually set range " + "if available, or the combined frame range of all F-Curves within this action " + "if not (assigning sets the manual frame range)", + 0, + 0); + RNA_def_property_float_funcs( + prop, "rna_Action_frame_range_get", "rna_Action_frame_range_set", NULL); + RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + prop = RNA_def_float_vector(srna, - "frame_range", + "curve_frame_range", 2, NULL, 0, 0, - "Frame Range", - "The final frame range of all F-Curves within this action", + "Curve Frame Range", + "The combined frame range of all F-Curves within this action", 0, 0); - RNA_def_property_float_funcs(prop, "rna_Action_frame_range_get", NULL, NULL); + RNA_def_property_float_funcs(prop, "rna_Action_curve_frame_range_get", NULL, NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* special "type" limiter - should not really be edited in general, |