From 87a4daed611112968c41c5313e9ffdd8d1577453 Mon Sep 17 00:00:00 2001 From: "Kevin C. Burke" Date: Tue, 25 Jan 2022 11:40:46 +0100 Subject: Animation: Equalize Handle Operator The Equalize Handles operator allows users to make selected handle lengths uniform: either respecting their original angle from the key control point or by flattening their angle (removing the overshoot sometimes produced by certain handle types). Design: T94172 Reviewed by: sybren Differential Revision: https://developer.blender.org/D13702 --- source/blender/editors/space_graph/graph_edit.c | 97 +++++++++++++++++++++++ source/blender/editors/space_graph/graph_intern.h | 10 +++ source/blender/editors/space_graph/graph_ops.c | 1 + 3 files changed, 108 insertions(+) (limited to 'source/blender/editors/space_graph') diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 2afee277847..9675901ead3 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -2352,6 +2352,103 @@ void GRAPH_OT_snap(wmOperatorType *ot) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Equalize Handles Operator + * \{ */ + +/* Defines for equalize handles tool. */ +static const EnumPropertyItem prop_graphkeys_equalize_handles_sides[] = { + {GRAPHKEYS_EQUALIZE_LEFT, "LEFT", 0, "Left", "Equalize selected keyframes' left handles"}, + {GRAPHKEYS_EQUALIZE_RIGHT, "RIGHT", 0, "Right", "Equalize selected keyframes' right handles"}, + {GRAPHKEYS_EQUALIZE_BOTH, "BOTH", 0, "Both", "Equalize both of a keyframe's handles"}, + {0, NULL, 0, NULL, NULL}, +}; + +/* ------------------- */ + +/* Equalize selected keyframes' bezier handles. */ +static void equalize_graph_keys(bAnimContext *ac, int mode, float handle_length, bool flatten) +{ + /* Filter data. */ + const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | + ANIMFILTER_NODUPLIS); + ListBase anim_data = {NULL, NULL}; + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* Equalize keyframes. */ + LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) { + ANIM_fcurve_equalize_keyframes_loop(ale->key_data, mode, handle_length, flatten); + ale->update |= ANIM_UPDATE_DEFAULT; + } + + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); +} + +static int graphkeys_equalize_handles_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + + /* Get editor data. */ + if (ANIM_animdata_get_context(C, &ac) == 0) { + return OPERATOR_CANCELLED; + } + + /* Get equalize mode. */ + int mode = RNA_enum_get(op->ptr, "side"); + float handle_length = RNA_float_get(op->ptr, "handle_length"); + bool flatten = RNA_boolean_get(op->ptr, "flatten"); + + /* Equalize graph keyframes. */ + equalize_graph_keys(&ac, mode, handle_length, flatten); + + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GRAPH_OT_equalize_handles(wmOperatorType *ot) +{ + /* Identifiers */ + ot->name = "Equalize Handles"; + ot->idname = "GRAPH_OT_equalize_handles"; + ot->description = + "Ensure selected keyframes' handles have equal length, optionally making them horizontal"; + + /* API callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = graphkeys_equalize_handles_exec; + ot->poll = graphop_editable_keyframes_poll; + + /* Flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* Properties */ + ot->prop = RNA_def_enum(ot->srna, + "side", + prop_graphkeys_equalize_handles_sides, + 0, + "Side", + "Side of the keyframes' bezier handles to affect"); + RNA_def_float(ot->srna, + "handle_length", + 5.0f, + 0.1f, + FLT_MAX, + "Handle Length", + "Length to make selected keyframes' bezier handles", + 1.0f, + 50.0f); + RNA_def_boolean( + ot->srna, + "flatten", + false, + "Flatten", + "Make the values of the selected keyframes' handles the same as their respective keyframes"); +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Mirror Keyframes Operator * \{ */ diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index 243a4ee4b95..a59fb63dd22 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -144,6 +144,7 @@ void GRAPH_OT_easing_type(struct wmOperatorType *ot); void GRAPH_OT_frame_jump(struct wmOperatorType *ot); void GRAPH_OT_snap_cursor_value(struct wmOperatorType *ot); void GRAPH_OT_snap(struct wmOperatorType *ot); +void GRAPH_OT_equalize_handles(struct wmOperatorType *ot); void GRAPH_OT_mirror(struct wmOperatorType *ot); /* defines for snap keyframes @@ -158,6 +159,15 @@ enum eGraphKeys_Snap_Mode { GRAPHKEYS_SNAP_VALUE, }; +/* Defines for equalize keyframe handles. + * NOTE: Keep in sync with eEditKeyframes_Equalize (in ED_keyframes_edit.h). + */ +enum eGraphKeys_Equalize_Mode { + GRAPHKEYS_EQUALIZE_LEFT = 1, + GRAPHKEYS_EQUALIZE_RIGHT, + GRAPHKEYS_EQUALIZE_BOTH, +}; + /* defines for mirror keyframes * NOTE: keep in sync with eEditKeyframes_Mirror (in ED_keyframes_edit.h) */ diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index fe4cffcb3b8..7606dcc60cf 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -456,6 +456,7 @@ void graphedit_operatortypes(void) /* editing */ WM_operatortype_append(GRAPH_OT_snap); + WM_operatortype_append(GRAPH_OT_equalize_handles); WM_operatortype_append(GRAPH_OT_mirror); WM_operatortype_append(GRAPH_OT_frame_jump); WM_operatortype_append(GRAPH_OT_snap_cursor_value); -- cgit v1.2.3