From ac38eba721a5c0d8c9cf47c0222b38212acb9ae6 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 24 Jan 2010 06:28:53 +0000 Subject: NLA Editor: Sync Action Extents with Referenced Range This operator can be accessed from the "Action Clip" panel, and is used to include keyframes that have been added to a strip already in the NLA. Although this is not a recommended workflow, having this ability is useful at times. --- source/blender/blenkernel/BKE_nla.h | 1 + source/blender/blenkernel/intern/nla.c | 25 +++++++ source/blender/editors/space_logic/logic_buttons.c | 3 +- source/blender/editors/space_nla/nla_buttons.c | 1 + source/blender/editors/space_nla/nla_edit.c | 79 ++++++++++++++++++++++ source/blender/editors/space_nla/nla_intern.h | 2 + source/blender/editors/space_nla/nla_ops.c | 2 + source/blender/makesrna/intern/rna_nla.c | 50 +++----------- 8 files changed, 121 insertions(+), 42 deletions(-) diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 989043c1d67..780f871ebd8 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -83,6 +83,7 @@ struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt); void BKE_nlastrip_set_active(struct AnimData *adt, struct NlaStrip *strip); short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max); +void BKE_nlastrip_recalculate_bounds(struct NlaStrip *strip); void BKE_nlastrip_validate_name(struct AnimData *adt, struct NlaStrip *strip); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index c9008e91646..2af9159f70f 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1035,6 +1035,31 @@ short BKE_nlastrip_within_bounds (NlaStrip *strip, float min, float max) return 1; } +/* Recalculate the start and end frames for the current strip, after changing + * the extents of the action or the mapping (repeats or scale factor) info + */ +void BKE_nlastrip_recalculate_bounds (NlaStrip *strip) +{ + float actlen, mapping; + + /* sanity checks + * - must have a strip + * - can only be done for action clips + */ + if ((strip == NULL) || (strip->type != NLASTRIP_TYPE_CLIP)) + return; + + /* calculate new length factors */ + actlen= strip->actend - strip->actstart; + if (IS_EQ(actlen, 0.0f)) actlen= 1.0f; + + mapping= strip->scale * strip->repeat; + + /* adjust endpoint of strip in response to this */ + if (IS_EQ(mapping, 0.0f) == 0) + strip->end = (actlen * mapping) + strip->start; +} + /* Is the given NLA-strip the first one to occur for the given AnimData block */ // TODO: make this an api method if necesary, but need to add prefix first static short nlastrip_is_first (AnimData *adt, NlaStrip *strip) diff --git a/source/blender/editors/space_logic/logic_buttons.c b/source/blender/editors/space_logic/logic_buttons.c index 9ee170b90d8..cf3fb889118 100644 --- a/source/blender/editors/space_logic/logic_buttons.c +++ b/source/blender/editors/space_logic/logic_buttons.c @@ -231,4 +231,5 @@ void LOGIC_OT_links_cut(wmOperatorType *ot) RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath); /* internal */ RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX); -} \ No newline at end of file +} + diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index df791297967..cd926218757 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -363,6 +363,7 @@ static void nla_panel_actclip(const bContext *C, Panel *pa) uiItemL(column, "Action Extents:", 0); uiItemR(column, "Start Frame", 0, &strip_ptr, "action_start_frame", 0); uiItemR(column, "End Frame", 0, &strip_ptr, "action_end_frame", 0); + uiItemO(column, NULL, 0, "NLA_OT_action_sync_length"); /* action usage */ column= uiLayoutColumn(layout, 1); diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index a54627ec0d8..7e2aa6b5709 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -1181,6 +1181,85 @@ void NLA_OT_move_down (wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } +/* ******************** Sync Action Length Operator ***************************** */ +/* Recalculate the extents of the action ranges used for the selected strips */ + +static int nlaedit_sync_actlen_exec (bContext *C, wmOperator *op) +{ + bAnimContext ac; + + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + short active_only= RNA_boolean_get(op->ptr, "active"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* get a list of the editable tracks being shown in the NLA */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); + if (active_only) filter |= ANIMFILTER_ACTIVE; + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* for each NLA-Track, apply scale of all selected strips */ + for (ale= anim_data.first; ale; ale= ale->next) { + NlaTrack *nlt= (NlaTrack *)ale->data; + NlaStrip *strip; + + for (strip= nlt->strips.first; strip; strip= strip->next) { + /* strip selection/active status check */ + if (active_only) { + if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) + continue; + } + else { + if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0) + continue; + } + + /* must be action-clip only (transitions don't have scale) */ + if (strip->type == NLASTRIP_TYPE_CLIP) { + if (strip->act == NULL) + continue; + + /* recalculate the length of the action */ + calc_action_range(strip->act, &strip->actstart, &strip->actend, 0); + + /* adjust the strip extents in response to this */ + BKE_nlastrip_recalculate_bounds(strip); + } + } + } + + /* free temp data */ + BLI_freelistN(&anim_data); + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLA_OT_action_sync_length (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Sync Action Length"; + ot->idname= "NLA_OT_action_sync_length"; + ot->description= "Sychronise the length of the referenced Action with the lengths used in the strip."; + + /* api callbacks */ + ot->exec= nlaedit_sync_actlen_exec; + ot->poll= ED_operator_nla_active; // XXX: is this satisfactory... probably requires a check for active strip... + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + ot->prop= RNA_def_boolean(ot->srna, "active", 1, "Active Strip Only", "Only sync the active length for the active strip."); +} + /* ******************** Apply Scale Operator ***************************** */ /* Reset the scaling of the selected strips to 1.0f */ diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index ca50452b442..3b73f783c41 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -103,6 +103,8 @@ void NLA_OT_mute_toggle(wmOperatorType *ot); void NLA_OT_move_up(wmOperatorType *ot); void NLA_OT_move_down(wmOperatorType *ot); +void NLA_OT_action_sync_length(wmOperatorType *ot); + void NLA_OT_apply_scale(wmOperatorType *ot); void NLA_OT_clear_scale(wmOperatorType *ot); diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index bec3a003b1e..32408abcdeb 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -157,6 +157,8 @@ void nla_operatortypes(void) WM_operatortype_append(NLA_OT_move_up); WM_operatortype_append(NLA_OT_move_down); + WM_operatortype_append(NLA_OT_action_sync_length); + WM_operatortype_append(NLA_OT_apply_scale); WM_operatortype_append(NLA_OT_clear_scale); diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index f182e930a67..7de0f4e8f6b 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -164,43 +164,25 @@ static void rna_NlaStrip_end_frame_set(PointerRNA *ptr, float value) static void rna_NlaStrip_scale_set(PointerRNA *ptr, float value) { NlaStrip *data= (NlaStrip*)ptr->data; - float actlen, mapping; /* set scale value */ CLAMP(value, 0.0001f, 1000.0f); /* NOTE: these need to be synced with the values in the property definition in rna_def_nlastrip() */ data->scale= value; - /* calculate existing factors */ - actlen= data->actend - data->actstart; - if (IS_EQ(actlen, 0.0f)) actlen= 1.0f; - mapping= data->scale * data->repeat; - - /* adjust endpoint of strip in response to this */ - if (IS_EQ(mapping, 0.0f) == 0) - data->end = (actlen * mapping) + data->start; - else - printf("NlaStrip Set Scale Error (in RNA): Scale = %0.4f, Repeat = %0.4f \n", data->scale, data->repeat); + /* adjust the strip extents in response to this */ + BKE_nlastrip_recalculate_bounds(data); } static void rna_NlaStrip_repeat_set(PointerRNA *ptr, float value) { NlaStrip *data= (NlaStrip*)ptr->data; - float actlen, mapping; /* set repeat value */ CLAMP(value, 0.01f, 1000.0f); /* NOTE: these need to be synced with the values in the property definition in rna_def_nlastrip() */ data->repeat= value; - /* calculate existing factors */ - actlen= data->actend - data->actstart; - if (IS_EQ(actlen, 0.0f)) actlen= 1.0f; - mapping= data->scale * data->repeat; - - /* adjust endpoint of strip in response to this */ - if (IS_EQ(mapping, 0.0f) == 0) - data->end = (actlen * mapping) + data->start; - else - printf("NlaStrip Set Repeat Error (in RNA): Scale = %0.4f, Repeat = %0.4f \n", data->scale, data->repeat); + /* adjust the strip extents in response to this */ + BKE_nlastrip_recalculate_bounds(data); } static void rna_NlaStrip_blend_in_set(PointerRNA *ptr, float value) @@ -234,40 +216,26 @@ static void rna_NlaStrip_blend_out_set(PointerRNA *ptr, float value) static void rna_NlaStrip_action_start_frame_set(PointerRNA *ptr, float value) { NlaStrip *data= (NlaStrip*)ptr->data; - float actlen, mapping; /* prevent start frame from occurring after end of action */ CLAMP(value, MINAFRAME, data->actend); data->actstart= value; - /* calculate new length factors */ - actlen= data->actend - data->actstart; - if (IS_EQ(actlen, 0.0f)) actlen= 1.0f; - mapping= data->scale * data->repeat; - - /* adjust endpoint of strip in response to this */ - // FIXME: should we be moving the start backwards instead? - if (IS_EQ(mapping, 0.0f) == 0) - data->end = (actlen * mapping) + data->start; + /* adjust the strip extents in response to this */ + // TODO: should the strip be moved backwards instead as a special case? + BKE_nlastrip_recalculate_bounds(data); } static void rna_NlaStrip_action_end_frame_set(PointerRNA *ptr, float value) { NlaStrip *data= (NlaStrip*)ptr->data; - float actlen, mapping; /* prevent end frame from starting before start of action */ CLAMP(value, data->actstart, MAXFRAME); data->actend= value; - /* calculate new length factors */ - actlen= data->actend - data->actstart; - if (IS_EQ(actlen, 0.0f)) actlen= 1.0f; - mapping= data->scale * data->repeat; - - /* adjust endpoint of strip in response to this */ - if (IS_EQ(mapping, 0.0f) == 0) - data->end = (actlen * mapping) + data->start; + /* adjust the strip extents in response to this */ + BKE_nlastrip_recalculate_bounds(data); } static void rna_NlaStrip_animated_influence_set(PointerRNA *ptr, int value) -- cgit v1.2.3