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.
This commit is contained in:
Joshua Leung 2010-01-24 06:28:53 +00:00
parent 351d239ac7
commit ac38eba721
8 changed files with 121 additions and 42 deletions

@ -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);

@ -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)

@ -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);
}
}

@ -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);

@ -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 */

@ -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);

@ -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);

@ -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)