From f7ddb1ed8a2a646e3d04d5e2e46929673084149c Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Sat, 25 Dec 2021 20:58:47 +0100 Subject: Breakdown Implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds the breakdown (or tween) functionality to the graph editor. The factor defines the linear interpolation from left key to right key. Reviewed by: Sybren A. Stüvel Differential Revision: https://developer.blender.org/D9375 Ref: D9375 --- source/blender/editors/space_graph/graph_intern.h | 1 + source/blender/editors/space_graph/graph_ops.c | 1 + .../blender/editors/space_graph/graph_slider_ops.c | 123 +++++++++++++++++++++ 3 files changed, 125 insertions(+) (limited to 'source/blender/editors/space_graph') diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index ed52e684eb7..286580b5629 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -127,6 +127,7 @@ void GRAPH_OT_duplicate(struct wmOperatorType *ot); void GRAPH_OT_delete(struct wmOperatorType *ot); void GRAPH_OT_clean(struct wmOperatorType *ot); void GRAPH_OT_blend_to_neighbor(struct wmOperatorType *ot); +void GRAPH_OT_breakdown(struct wmOperatorType *ot); void GRAPH_OT_decimate(struct wmOperatorType *ot); void GRAPH_OT_sample(struct wmOperatorType *ot); void GRAPH_OT_bake(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 724d5351283..fe4cffcb3b8 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -471,6 +471,7 @@ void graphedit_operatortypes(void) WM_operatortype_append(GRAPH_OT_clean); WM_operatortype_append(GRAPH_OT_decimate); WM_operatortype_append(GRAPH_OT_blend_to_neighbor); + WM_operatortype_append(GRAPH_OT_breakdown); WM_operatortype_append(GRAPH_OT_euler_filter); WM_operatortype_append(GRAPH_OT_delete); WM_operatortype_append(GRAPH_OT_duplicate); diff --git a/source/blender/editors/space_graph/graph_slider_ops.c b/source/blender/editors/space_graph/graph_slider_ops.c index a78e65aa3d6..733313dd06b 100644 --- a/source/blender/editors/space_graph/graph_slider_ops.c +++ b/source/blender/editors/space_graph/graph_slider_ops.c @@ -681,3 +681,126 @@ void GRAPH_OT_blend_to_neighbor(wmOperatorType *ot) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Breakdown Operator + * \{ */ + +static void breakdown_graph_keys(bAnimContext *ac, float factor) +{ + ListBase anim_data = {NULL, NULL}; + ANIM_animdata_filter(ac, &anim_data, OPERATOR_DATA_FILTER, ac->data, ac->datatype); + + bAnimListElem *ale; + + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->key_data; + ListBase segments = find_fcurve_segments(fcu); + LISTBASE_FOREACH (FCurveSegment *, segment, &segments) { + breakdown_fcurve_segment(fcu, segment, factor); + } + BLI_freelistN(&segments); + ale->update |= ANIM_UPDATE_DEFAULT; + } + + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); +} + +static void breakdown_draw_status_header(bContext *C, tGraphSliderOp *gso) +{ + char status_str[UI_MAX_DRAW_STR]; + char mode_str[32]; + char slider_string[UI_MAX_DRAW_STR]; + + ED_slider_status_string_get(gso->slider, slider_string, UI_MAX_DRAW_STR); + + strcpy(mode_str, TIP_("Breakdown")); + + if (hasNumInput(&gso->num)) { + char str_ofs[NUM_STR_REP_LEN]; + + outputNumInput(&gso->num, str_ofs, &gso->scene->unit); + + BLI_snprintf(status_str, sizeof(status_str), "%s: %s", mode_str, str_ofs); + } + else { + BLI_snprintf(status_str, sizeof(status_str), "%s: %s", mode_str, slider_string); + } + + ED_workspace_status_text(C, status_str); +} + +static void breakdown_modal_update(bContext *C, wmOperator *op) +{ + tGraphSliderOp *gso = op->customdata; + + breakdown_draw_status_header(C, gso); + + /* Reset keyframe data to the state at invoke. */ + reset_bezts(gso); + breakdown_graph_keys(&gso->ac, ED_slider_factor_get(gso->slider)); + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); +} + +static int breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + const int invoke_result = graph_slider_invoke(C, op, event); + + if (invoke_result == OPERATOR_CANCELLED) { + return invoke_result; + } + + tGraphSliderOp *gso = op->customdata; + gso->modal_update = breakdown_modal_update; + breakdown_draw_status_header(C, gso); + + return invoke_result; +} + +static int breakdown_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + + if (ANIM_animdata_get_context(C, &ac) == 0) { + return OPERATOR_CANCELLED; + } + + const float factor = RNA_float_get(op->ptr, "factor"); + + breakdown_graph_keys(&ac, factor); + + /* Set notifier that keyframes have changed. */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GRAPH_OT_breakdown(wmOperatorType *ot) +{ + /* Identifiers. */ + ot->name = "Breakdown"; + ot->idname = "GRAPH_OT_breakdown"; + ot->description = "Move selected keyframes to an inbetween position relative to adjacent keys"; + + /* API callbacks. */ + ot->invoke = breakdown_invoke; + ot->modal = graph_slider_modal; + ot->exec = breakdown_exec; + ot->poll = graphop_editable_keyframes_poll; + + /* Flags. */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_float_factor(ot->srna, + "factor", + 1.0f / 3.0f, + -FLT_MAX, + FLT_MAX, + "Factor", + "Favor either the left or the right key", + 0.0f, + 1.0f); +} + +/** \} */ -- cgit v1.2.3