diff options
author | Christoph Lendenfeld <chris.lend@gmx.at> | 2021-12-25 22:58:47 +0300 |
---|---|---|
committer | Christoph Lendenfeld <chris.lend@gmx.at> | 2021-12-25 22:58:47 +0300 |
commit | f7ddb1ed8a2a646e3d04d5e2e46929673084149c (patch) | |
tree | d84ae6df91d7935a61c3737605820382dd8d9929 /source/blender | |
parent | fbd01624e3feb10add9d04672a3db0f52817423a (diff) |
Breakdown Implementation
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
Diffstat (limited to 'source/blender')
5 files changed, 140 insertions, 0 deletions
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 3c2e66d9367..8aac1e9b779 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -400,6 +400,18 @@ void blend_to_neighbor_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const /* ---------------- */ +void breakdown_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor) +{ + BezTriple left_bezt = fcurve_segment_start_get(fcu, segment->start_index); + BezTriple right_bezt = fcurve_segment_end_get(fcu, segment->start_index + segment->length); + + for (int i = segment->start_index; i < segment->start_index + segment->length; i++) { + fcu->bezt[i].vec[1][1] = interpf(right_bezt.vec[1][1], left_bezt.vec[1][1], factor); + } +} + +/* ---------------- */ + /* Check if the keyframe interpolation type is supported */ static bool prepare_for_decimate(FCurve *fcu, int i) { diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h index 084da038604..c54fb93e495 100644 --- a/source/blender/editors/include/ED_keyframes_edit.h +++ b/source/blender/editors/include/ED_keyframes_edit.h @@ -392,6 +392,9 @@ void clean_fcurve(struct bAnimContext *ac, void blend_to_neighbor_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, const float factor); +void breakdown_fcurve_segment(struct FCurve *fcu, + struct FCurveSegment *segment, + const float factor); bool decimate_fcurve(struct bAnimListElem *ale, float remove_ratio, float error_sq_max); /** * Use a weighted moving-means method to reduce intensity of fluctuations. 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); +} + +/** \} */ |