From d5920744f4429423e89a56112ede8a8ea87ccbbb Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Fri, 3 Dec 2021 22:24:41 +0000 Subject: Create generic modal functions from GRAPH_OT_decimate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch extracts the modal functions from GRAPH_OT_decimate and makes them generic so they can be reused by future operators Reviewed by: Sybren A. Stüvel Differential Revision: https://developer.blender.org/D9326 Ref: D9326 --- .../blender/editors/space_graph/graph_slider_ops.c | 263 +++++++++++---------- 1 file changed, 141 insertions(+), 122 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_graph/graph_slider_ops.c b/source/blender/editors/space_graph/graph_slider_ops.c index 4e62ab2df2d..8cd2f5277d7 100644 --- a/source/blender/editors/space_graph/graph_slider_ops.c +++ b/source/blender/editors/space_graph/graph_slider_ops.c @@ -82,6 +82,9 @@ typedef struct tGraphSliderOp { struct tSlider *slider; + /* Each operator has a specific update function. */ + void (*modal_update)(struct bContext *, struct wmOperator *); + NumInput num; } tGraphSliderOp; @@ -177,37 +180,10 @@ static void reset_bezts(tGraphSliderOp *gso) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Decimate Keyframes Operator +/** \name Common Modal Functions * \{ */ -typedef enum tDecimModes { - DECIM_RATIO = 1, - DECIM_ERROR, -} tDecimModes; - -static void decimate_graph_keys(bAnimContext *ac, float remove_ratio, float error_sq_max) -{ - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - - /* Filter data. */ - ANIM_animdata_filter(ac, &anim_data, OPERATOR_DATA_FILTER, ac->data, ac->datatype); - - /* Loop through filtered data and clean curves. */ - for (ale = anim_data.first; ale; ale = ale->next) { - if (!decimate_fcurve(ale, remove_ratio, error_sq_max)) { - /* The selection contains unsupported keyframe types! */ - WM_report(RPT_WARNING, "Decimate: Skipping non linear/bezier keyframes!"); - } - - ale->update |= ANIM_UPDATE_DEFAULT; - } - - ANIM_animdata_update(ac, &anim_data); - ANIM_animdata_freelist(&anim_data); -} - -static void decimate_exit(bContext *C, wmOperator *op) +static void graph_slider_exit(bContext *C, wmOperator *op) { tGraphSliderOp *gso = op->customdata; wmWindow *win = CTX_wm_window(C); @@ -235,36 +211,84 @@ static void decimate_exit(bContext *C, wmOperator *op) WM_cursor_modal_restore(win); ED_area_status_text(area, NULL); - /* Cleanup. */ + /* cleanup */ op->customdata = NULL; } -/* Draw a percentage indicator in workspace footer. */ -static void decimate_draw_status(bContext *C, tGraphSliderOp *gso) +static int graph_slider_modal(bContext *C, wmOperator *op, const wmEvent *event) { - char status_str[UI_MAX_DRAW_STR]; - char mode_str[32]; - char slider_string[UI_MAX_DRAW_STR]; + tGraphSliderOp *gso = op->customdata; - ED_slider_status_string_get(gso->slider, slider_string, UI_MAX_DRAW_STR); + const bool has_numinput = hasNumInput(&gso->num); - strcpy(mode_str, TIP_("Decimate Keyframes")); + ED_slider_modal(gso->slider, event); - if (hasNumInput(&gso->num)) { - char str_ofs[NUM_STR_REP_LEN]; + switch (event->type) { + /* Confirm */ + case LEFTMOUSE: + case EVT_RETKEY: + case EVT_PADENTER: { + if (event->val == KM_PRESS) { + graph_slider_exit(C, op); - outputNumInput(&gso->num, str_ofs, &gso->scene->unit); + return OPERATOR_FINISHED; + } + break; + } - 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); + /* Cancel */ + case EVT_ESCKEY: + case RIGHTMOUSE: { + if (event->val == KM_PRESS) { + reset_bezts(gso); + + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + + graph_slider_exit(C, op); + + return OPERATOR_CANCELLED; + } + break; + } + + /* When the mouse is moved, the percentage and the keyframes update. */ + case MOUSEMOVE: { + if (has_numinput == false) { + /* Do the update as specified by the operator. */ + gso->modal_update(C, op); + } + break; + } + default: { + if ((event->val == KM_PRESS) && handleNumInput(C, &gso->num, event)) { + float value; + float percentage = RNA_property_float_get(op->ptr, gso->percentage_prop); + + /* Grab percentage from numeric input, and store this new value for redo + * NOTE: users see ints, while internally we use a 0-1 float. + */ + value = percentage * 100.0f; + applyNumInput(&gso->num, &value); + + percentage = value / 100.0f; + ED_slider_factor_set(gso->slider, percentage); + RNA_property_float_set(op->ptr, gso->percentage_prop, percentage); + + gso->modal_update(C, op); + break; + } + + /* Unhandled event - maybe it was some view manip? */ + /* Allow to pass through. */ + return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; + } } - ED_workspace_status_text(C, status_str); + return OPERATOR_RUNNING_MODAL; } -static int graphkeys_decimate_invoke(bContext *C, wmOperator *op, const wmEvent *event) +/* Allocate tGraphSliderOp and assign to op->customdata. */ +static int graph_slider_invoke(bContext *C, wmOperator *op, const wmEvent *event) { tGraphSliderOp *gso; @@ -275,7 +299,7 @@ static int graphkeys_decimate_invoke(bContext *C, wmOperator *op, const wmEvent /* Get editor data. */ if (ANIM_animdata_get_context(C, &gso->ac) == 0) { - decimate_exit(C, op); + graph_slider_exit(C, op); return OPERATOR_CANCELLED; } @@ -289,14 +313,11 @@ static int graphkeys_decimate_invoke(bContext *C, wmOperator *op, const wmEvent gso->slider = ED_slider_create(C); ED_slider_init(gso->slider, event); - ED_slider_allow_overshoot_set(gso->slider, false); - - decimate_draw_status(C, gso); if (gso->bezt_arr_list.first == NULL) { WM_report(RPT_WARNING, - "Fcurve Decimate: Can't decimate baked channels. Unbake them and try again."); - decimate_exit(C, op); + "Fcurve Slider: Can't work on baked channels. Unbake them and try again."); + graph_slider_exit(C, op); return OPERATOR_CANCELLED; } @@ -304,6 +325,64 @@ static int graphkeys_decimate_invoke(bContext *C, wmOperator *op, const wmEvent return OPERATOR_RUNNING_MODAL; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Decimate Keyframes Operator + * \{ */ + +typedef enum tDecimModes { + DECIM_RATIO = 1, + DECIM_ERROR, +} tDecimModes; + +static void decimate_graph_keys(bAnimContext *ac, float remove_ratio, float error_sq_max) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + + /* Filter data. */ + ANIM_animdata_filter(ac, &anim_data, OPERATOR_DATA_FILTER, ac->data, ac->datatype); + + /* Loop through filtered data and clean curves. */ + for (ale = anim_data.first; ale; ale = ale->next) { + if (!decimate_fcurve(ale, remove_ratio, error_sq_max)) { + /* The selection contains unsupported keyframe types! */ + WM_report(RPT_WARNING, "Decimate: Skipping non linear/bezier keyframes!"); + } + + ale->update |= ANIM_UPDATE_DEFAULT; + } + + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); +} + +/* Draw a percentage indicator in workspace footer. */ +static void decimate_draw_status(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_("Decimate Keyframes")); + + 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 graphkeys_decimate_modal_update(bContext *C, wmOperator *op) { /* Perform decimate updates - in response to some user action @@ -324,79 +403,19 @@ static void graphkeys_decimate_modal_update(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } -static int graphkeys_decimate_modal(bContext *C, wmOperator *op, const wmEvent *event) +static int graphkeys_decimate_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - /* This assumes that we are in "DECIM_RATIO" mode. This is because the error margin is very hard - * and finicky to control with this modal mouse grab method. Therefore, it is expected that the - * error margin mode is not adjusted by the modal operator but instead tweaked via the redo - * panel. */ - tGraphSliderOp *gso = op->customdata; + const int invoke_result = graph_slider_invoke(C, op, event); - const bool has_numinput = hasNumInput(&gso->num); - - ED_slider_modal(gso->slider, event); - - switch (event->type) { - case LEFTMOUSE: /* Confirm */ - case EVT_RETKEY: - case EVT_PADENTER: { - if (event->val == KM_PRESS) { - decimate_exit(C, op); - - return OPERATOR_FINISHED; - } - break; - } - - case EVT_ESCKEY: /* Cancel */ - case RIGHTMOUSE: { - if (event->val == KM_PRESS) { - reset_bezts(gso); - - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - - decimate_exit(C, op); - - return OPERATOR_CANCELLED; - } - break; - } - - /* Percentage Change... */ - case MOUSEMOVE: /* Calculate new position. */ - { - if (has_numinput == false) { - /* Update pose to reflect the new values. */ - graphkeys_decimate_modal_update(C, op); - } - break; - } - default: { - if ((event->val == KM_PRESS) && handleNumInput(C, &gso->num, event)) { - float value; - float percentage = RNA_property_float_get(op->ptr, gso->percentage_prop); - - /* Grab percentage from numeric input, and store this new value for redo - * NOTE: users see ints, while internally we use a 0-1 float. - */ - value = percentage * 100.0f; - applyNumInput(&gso->num, &value); - - percentage = value / 100.0f; - RNA_property_float_set(op->ptr, gso->percentage_prop, percentage); - - /* Update decimate output to reflect the new values. */ - graphkeys_decimate_modal_update(C, op); - break; - } - - /* Unhandled event - maybe it was some view manipulation? */ - /* Allow to pass through. */ - return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; - } + if (invoke_result == OPERATOR_CANCELLED) { + return OPERATOR_CANCELLED; } - return OPERATOR_RUNNING_MODAL; + tGraphSliderOp *gso = op->customdata; + gso->modal_update = graphkeys_decimate_modal_update; + ED_slider_allow_overshoot_set(gso->slider, false); + + return invoke_result; } static int graphkeys_decimate_exec(bContext *C, wmOperator *op) @@ -500,7 +519,7 @@ void GRAPH_OT_decimate(wmOperatorType *ot) ot->poll_property = graphkeys_decimate_poll_property; ot->get_description = graphkeys_decimate_desc; ot->invoke = graphkeys_decimate_invoke; - ot->modal = graphkeys_decimate_modal; + ot->modal = graph_slider_modal; ot->exec = graphkeys_decimate_exec; ot->poll = graphop_editable_keyframes_poll; -- cgit v1.2.3