From f26f34704eaad264bd5952174da98865dfeeba7c Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Fri, 13 Jan 2023 17:32:19 +0100 Subject: [PATCH 01/21] add operator with menu entry --- release/datafiles/locale | 2 +- release/scripts/addons | 2 +- release/scripts/addons_contrib | 2 +- release/scripts/startup/bl_ui/space_graph.py | 6 + source/blender/blenkernel/BKE_fcurve.h | 5 +- source/blender/blenkernel/intern/fcurve.c | 40 +++++-- .../editors/space_graph/graph_intern.h | 1 + .../blender/editors/space_graph/graph_ops.c | 1 + .../blender/editors/space_graph/graph_view.c | 105 +++++++++++++++++- source/tools | 2 +- 10 files changed, 152 insertions(+), 14 deletions(-) diff --git a/release/datafiles/locale b/release/datafiles/locale index 7084c4ecd97..4f6dbb69893 160000 --- a/release/datafiles/locale +++ b/release/datafiles/locale @@ -1 +1 @@ -Subproject commit 7084c4ecd97d93459d9d23fd90f81589b09be5df +Subproject commit 4f6dbb69893bd6bdf73467effe77ae46c8e4ee37 diff --git a/release/scripts/addons b/release/scripts/addons index a9d4443c244..bf49eeaa14c 160000 --- a/release/scripts/addons +++ b/release/scripts/addons @@ -1 +1 @@ -Subproject commit a9d4443c244f89399ec4bcc427e05a07950528cc +Subproject commit bf49eeaa14c445d3c53068203fdf91bff568fe64 diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib index bdcfdd47ec3..0f72f6c85c3 160000 --- a/release/scripts/addons_contrib +++ b/release/scripts/addons_contrib @@ -1 +1 @@ -Subproject commit bdcfdd47ec3451822b21d1cff2ea2db751093c9a +Subproject commit 0f72f6c85c3743a9072273acb6a8a34b1cf1064b diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index b2c8822a75d..7f871239710 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -204,6 +204,9 @@ class GRAPH_MT_channel(Menu): def draw(self, context): layout = self.layout + layout.separator() + layout.operator("graph.view_channel") + layout.operator_context = 'INVOKE_REGION_CHANNELS' layout.operator("anim.channels_delete") @@ -452,6 +455,9 @@ class GRAPH_MT_channel_context_menu(Menu): layout.operator("anim.channels_expand") layout.operator("anim.channels_collapse") + layout.separator() + layout.operator("graph.view_channel") + layout.separator() layout.operator_menu_enum("anim.channels_move", "direction", text="Move...") diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index cdade9209b6..f09193568ad 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -374,13 +374,14 @@ bool BKE_fcurve_calc_range( /** * Calculate the extents of F-Curve's data. */ -bool BKE_fcurve_calc_bounds(const struct FCurve *fcu, +bool BKE_fcurve_calc_bounds(struct FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax, bool do_sel_only, - bool include_handles); + bool include_handles, + const float range[2]); /** * Return an array of keyed frames, rounded to `interval`. diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index d2550f9db0d..a1e6737db50 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -605,13 +605,14 @@ static short get_fcurve_end_keyframes(const FCurve *fcu, return found; } -bool BKE_fcurve_calc_bounds(const FCurve *fcu, +bool BKE_fcurve_calc_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax, const bool do_sel_only, - const bool include_handles) + const bool include_handles, + const float range[2]) { float xminv = 999999999.0f, xmaxv = -999999999.0f; float yminv = 999999999.0f, ymaxv = -999999999.0f; @@ -622,12 +623,27 @@ bool BKE_fcurve_calc_bounds(const FCurve *fcu, BezTriple *bezt_first = NULL, *bezt_last = NULL; if (xmin || xmax) { - /* Get endpoint keyframes. */ - foundvert = get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, do_sel_only); + if (range == NULL) { + /* Get endpoint keyframes. */ + foundvert = get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, do_sel_only); + } + else { + /* If a range is passed in find the first and last keyframe within that range. */ + bool replace = false; + int first_index = BKE_fcurve_bezt_binarysearch_index( + fcu->bezt, range[0], fcu->totvert, &replace); + int last_index = BKE_fcurve_bezt_binarysearch_index( + fcu->bezt, range[1], fcu->totvert, &replace); + /* If first and last index are the same, no keyframes were found in the range. */ + if (first_index != last_index) { + bezt_first = &fcu->bezt[clamp_i(first_index, 0, fcu->totvert - 1)]; + bezt_last = &fcu->bezt[clamp_i(last_index - 1, 0, fcu->totvert - 1)]; + } + } if (bezt_first) { BLI_assert(bezt_last != NULL); - + foundvert = true; if (include_handles) { xminv = min_fff(xminv, bezt_first->vec[0][0], bezt_first->vec[1][0]); xmaxv = max_fff(xmaxv, bezt_last->vec[1][0], bezt_last->vec[2][0]); @@ -645,6 +661,9 @@ bool BKE_fcurve_calc_bounds(const FCurve *fcu, int i; for (bezt = fcu->bezt, i = 0; i < fcu->totvert; prevbezt = bezt, bezt++, i++) { + if (range != NULL && (bezt->vec[1][0] < range[0] || bezt->vec[1][0] > range[1])) { + continue; + } if ((do_sel_only == false) || BEZT_ISSEL_ANY(bezt)) { /* Keyframe itself. */ yminv = min_ff(yminv, bezt->vec[1][1]); @@ -669,6 +688,13 @@ bool BKE_fcurve_calc_bounds(const FCurve *fcu, foundvert = true; } } + if (range != NULL) { + /* The end of the range might not have keyframes, but might be an extreme. */ + float start_y = evaluate_fcurve(fcu, range[0]); + float end_y = evaluate_fcurve(fcu, range[1]); + yminv = min_fff(yminv, start_y, end_y); + ymaxv = max_fff(ymaxv, start_y, end_y); + } } } else if (fcu->fpt) { @@ -717,10 +743,10 @@ bool BKE_fcurve_calc_bounds(const FCurve *fcu, } if (xmin) { - *xmin = 0.0f; + *xmin = range != NULL ? range[0] : 0.0f; } if (xmax) { - *xmax = 1.0f; + *xmax = range != NULL ? range[1] : 1.0f; } if (ymin) { diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index a685216db31..ed15e44b1a2 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -101,6 +101,7 @@ void GRAPH_OT_previewrange_set(struct wmOperatorType *ot); void GRAPH_OT_view_all(struct wmOperatorType *ot); void GRAPH_OT_view_selected(struct wmOperatorType *ot); void GRAPH_OT_view_frame(struct wmOperatorType *ot); +void GRAPH_OT_view_channel(struct wmOperatorType *ot); void GRAPH_OT_click_insert(struct wmOperatorType *ot); void GRAPH_OT_keyframe_insert(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index b178a3d3430..d7473c63495 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -423,6 +423,7 @@ void graphedit_operatortypes(void) WM_operatortype_append(GRAPH_OT_view_all); WM_operatortype_append(GRAPH_OT_view_selected); WM_operatortype_append(GRAPH_OT_view_frame); + WM_operatortype_append(GRAPH_OT_view_channel); WM_operatortype_append(GRAPH_OT_ghost_curves_create); WM_operatortype_append(GRAPH_OT_ghost_curves_clear); diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c index f80c7c17c3a..b1e5bbd9ba9 100644 --- a/source/blender/editors/space_graph/graph_view.c +++ b/source/blender/editors/space_graph/graph_view.c @@ -91,7 +91,7 @@ void get_graph_keyframe_extents(bAnimContext *ac, /* Get range. */ if (BKE_fcurve_calc_bounds( - fcu, &txmin, &txmax, &tymin, &tymax, do_sel_only, include_handles)) { + fcu, &txmin, &txmax, &tymin, &tymax, do_sel_only, include_handles, NULL)) { short mapping_flag = ANIM_get_normalization_flags(ac); /* Apply NLA scaling. */ @@ -374,6 +374,109 @@ void GRAPH_OT_view_frame(wmOperatorType *ot) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name View Channel Operator + * \{ */ + +static int graphkeys_view_channel_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + + /* Get editor data. */ + if (ANIM_animdata_get_context(C, &ac) == 0) { + return OPERATOR_CANCELLED; + } + + ListBase anim_data = {NULL, NULL}; + int filter = (ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_FCURVESONLY); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + float range[2]; + const bool use_preview_range = RNA_boolean_get(op->ptr, "use_preview_range"); + if (use_preview_range && ac.scene->r.flag & SCER_PRV_RANGE) { + range[0] = ac.scene->r.psfra; + range[1] = ac.scene->r.pefra; + } + else { + range[0] = -FLT_MAX; + range[1] = FLT_MAX; + } + + rctf bounds = {.xmin = FLT_MAX, .xmax = -FLT_MAX, .ymin = FLT_MAX, .ymax = -FLT_MAX}; + + bAnimListElem *ale; + const bool fcu_selection_only = false; + const bool include_handles = RNA_boolean_get(op->ptr, "include_handles"); + + for (ale = anim_data.first; ale; ale = ale->next) { + if (ale->datatype != ALE_FCURVE) { + continue; + } + FCurve *fcu = (FCurve *)ale->key_data; + rctf fcu_bounds; + BKE_fcurve_calc_bounds(fcu, + &fcu_bounds.xmin, + &fcu_bounds.xmax, + &fcu_bounds.ymin, + &fcu_bounds.ymax, + fcu_selection_only, + include_handles, + range); + + float unitFac, offset; + short mapping_flag = ANIM_get_normalization_flags(&ac); + unitFac = ANIM_unit_mapping_get_factor(ac.scene, ale->id, fcu, mapping_flag, &offset); + fcu_bounds.ymin += offset; + fcu_bounds.ymax += offset; + fcu_bounds.ymin *= unitFac; + fcu_bounds.ymax *= unitFac; + + BLI_rctf_union(&bounds, &fcu_bounds); + } + + BLI_rctf_scale(&bounds, 1.1f); + + /* Take regions into account, that could block the view. + * Marker region is supposed to be larger than the scroll-bar, so prioritize it. */ + float pad_top = UI_TIME_SCRUB_MARGIN_Y; + float pad_bottom = BLI_listbase_is_empty(ED_context_get_markers(C)) ? V2D_SCROLL_HANDLE_HEIGHT : + UI_MARKER_MARGIN_Y; + BLI_rctf_pad_y(&bounds, ac.region->winy, pad_bottom, pad_top); + + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + UI_view2d_smooth_view(C, ac.region, &bounds, smooth_viewtx); + + return OPERATOR_FINISHED; +} + +void GRAPH_OT_view_channel(wmOperatorType *ot) +{ + /* Identifiers */ + ot->name = "Frame Channel"; + ot->idname = "GRAPH_OT_view_channel"; + ot->description = "Reset viewable area to show the selected channels"; + + /* API callbacks */ + ot->exec = graphkeys_view_channel_exec; + /* ot->poll = ED_operator_graphedit_active; */ + + ot->flag = 0; + + ot->prop = RNA_def_boolean(ot->srna, + "include_handles", + true, + "Include Handles", + "Include handles of keyframes when calculating extents"); + + ot->prop = RNA_def_boolean(ot->srna, + "use_preview_range", + true, + "Use Preview Range", + "Ignore frames outside of the preview range"); +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Create Ghost-Curves Operator * diff --git a/source/tools b/source/tools index e1744b9bd82..3582f5326d0 160000 --- a/source/tools +++ b/source/tools @@ -1 +1 @@ -Subproject commit e1744b9bd82527cf7e8af63362b61bd309b5711b +Subproject commit 3582f5326d08ca05c2a19056597e49ec5511d854 -- 2.30.2 From 66d9dd510a1b14b5d65888fdb53ef8406c6a4510 Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Fri, 13 Jan 2023 18:18:58 +0100 Subject: [PATCH 02/21] fix area issues --- .../keyconfig/keymap_data/blender_default.py | 3 +++ release/scripts/startup/bl_ui/space_dopesheet.py | 3 +++ release/scripts/startup/bl_ui/space_graph.py | 9 +++------ source/blender/editors/space_graph/graph_intern.h | 2 +- source/blender/editors/space_graph/graph_ops.c | 2 +- source/blender/editors/space_graph/graph_view.c | 14 +++++++++----- 6 files changed, 20 insertions(+), 13 deletions(-) diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index b02454cfa86..d9500416329 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -3508,6 +3508,9 @@ def km_animation_channels(params): ("anim.channels_ungroup", {"type": 'G', "value": 'PRESS', "ctrl": True, "alt": True}, None), # Menus. *_template_items_context_menu("DOPESHEET_MT_channel_context_menu", params.context_menu_event), + # View + ("graph.view_channels", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "alt": True}, None), + ("graph.view_channels", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None), ]) return keymap diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 99b33840051..b074c30e50e 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -699,6 +699,9 @@ class DOPESHEET_MT_channel_context_menu(Menu): layout.operator("anim.channels_group") layout.operator("anim.channels_ungroup") + layout.separator() + layout.operator("graph.view_channels") + layout.separator() layout.operator("anim.channels_editable_toggle") diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index 7f871239710..179e8db1b2b 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -204,9 +204,6 @@ class GRAPH_MT_channel(Menu): def draw(self, context): layout = self.layout - layout.separator() - layout.operator("graph.view_channel") - layout.operator_context = 'INVOKE_REGION_CHANNELS' layout.operator("anim.channels_delete") @@ -241,6 +238,9 @@ class GRAPH_MT_channel(Menu): layout.separator() layout.operator("anim.channels_fcurves_enable") + layout.separator() + layout.operator("graph.view_channels") + class GRAPH_MT_key(Menu): bl_label = "Key" @@ -455,9 +455,6 @@ class GRAPH_MT_channel_context_menu(Menu): layout.operator("anim.channels_expand") layout.operator("anim.channels_collapse") - layout.separator() - layout.operator("graph.view_channel") - layout.separator() layout.operator_menu_enum("anim.channels_move", "direction", text="Move...") diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index ed15e44b1a2..b0a853c520c 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -101,7 +101,7 @@ void GRAPH_OT_previewrange_set(struct wmOperatorType *ot); void GRAPH_OT_view_all(struct wmOperatorType *ot); void GRAPH_OT_view_selected(struct wmOperatorType *ot); void GRAPH_OT_view_frame(struct wmOperatorType *ot); -void GRAPH_OT_view_channel(struct wmOperatorType *ot); +void GRAPH_OT_view_channels(struct wmOperatorType *ot); void GRAPH_OT_click_insert(struct wmOperatorType *ot); void GRAPH_OT_keyframe_insert(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index d7473c63495..d4e7cee56d3 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -423,7 +423,7 @@ void graphedit_operatortypes(void) WM_operatortype_append(GRAPH_OT_view_all); WM_operatortype_append(GRAPH_OT_view_selected); WM_operatortype_append(GRAPH_OT_view_frame); - WM_operatortype_append(GRAPH_OT_view_channel); + WM_operatortype_append(GRAPH_OT_view_channels); WM_operatortype_append(GRAPH_OT_ghost_curves_create); WM_operatortype_append(GRAPH_OT_ghost_curves_clear); diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c index b1e5bbd9ba9..ead22052d59 100644 --- a/source/blender/editors/space_graph/graph_view.c +++ b/source/blender/editors/space_graph/graph_view.c @@ -444,21 +444,25 @@ static int graphkeys_view_channel_exec(bContext *C, wmOperator *op) BLI_rctf_pad_y(&bounds, ac.region->winy, pad_bottom, pad_top); const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - UI_view2d_smooth_view(C, ac.region, &bounds, smooth_viewtx); + LISTBASE_FOREACH (ARegion *, region, &ac.area->regionbase) { + if (region->regiontype == RGN_TYPE_WINDOW) { + UI_view2d_smooth_view(C, region, &bounds, smooth_viewtx); + } + } return OPERATOR_FINISHED; } -void GRAPH_OT_view_channel(wmOperatorType *ot) +void GRAPH_OT_view_channels(wmOperatorType *ot) { /* Identifiers */ - ot->name = "Frame Channel"; - ot->idname = "GRAPH_OT_view_channel"; + ot->name = "Frame Selected Channels"; + ot->idname = "GRAPH_OT_view_channels"; ot->description = "Reset viewable area to show the selected channels"; /* API callbacks */ ot->exec = graphkeys_view_channel_exec; - /* ot->poll = ED_operator_graphedit_active; */ + ot->poll = ED_operator_graphedit_active; ot->flag = 0; -- 2.30.2 From 84894090a7555fa1cc3ebfd1520204907a554272 Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Fri, 13 Jan 2023 18:20:39 +0100 Subject: [PATCH 03/21] rename --- .../scripts/presets/keyconfig/keymap_data/blender_default.py | 4 ++-- release/scripts/startup/bl_ui/space_dopesheet.py | 2 +- release/scripts/startup/bl_ui/space_graph.py | 2 +- source/blender/editors/space_graph/graph_intern.h | 2 +- source/blender/editors/space_graph/graph_ops.c | 2 +- source/blender/editors/space_graph/graph_view.c | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index d9500416329..8ee2091b1fc 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -3509,8 +3509,8 @@ def km_animation_channels(params): # Menus. *_template_items_context_menu("DOPESHEET_MT_channel_context_menu", params.context_menu_event), # View - ("graph.view_channels", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "alt": True}, None), - ("graph.view_channels", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None), + ("graph.view_selected_channels", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "alt": True}, None), + ("graph.view_selected_channels", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None), ]) return keymap diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index b074c30e50e..716a9fd5481 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -700,7 +700,7 @@ class DOPESHEET_MT_channel_context_menu(Menu): layout.operator("anim.channels_ungroup") layout.separator() - layout.operator("graph.view_channels") + layout.operator("graph.view_selected_channels") layout.separator() layout.operator("anim.channels_editable_toggle") diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index 179e8db1b2b..384a92820ac 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -239,7 +239,7 @@ class GRAPH_MT_channel(Menu): layout.operator("anim.channels_fcurves_enable") layout.separator() - layout.operator("graph.view_channels") + layout.operator("graph.view_selected_channels") class GRAPH_MT_key(Menu): diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index b0a853c520c..64525bdb147 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -101,7 +101,7 @@ void GRAPH_OT_previewrange_set(struct wmOperatorType *ot); void GRAPH_OT_view_all(struct wmOperatorType *ot); void GRAPH_OT_view_selected(struct wmOperatorType *ot); void GRAPH_OT_view_frame(struct wmOperatorType *ot); -void GRAPH_OT_view_channels(struct wmOperatorType *ot); +void GRAPH_OT_view_selected_channels(struct wmOperatorType *ot); void GRAPH_OT_click_insert(struct wmOperatorType *ot); void GRAPH_OT_keyframe_insert(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index d4e7cee56d3..831913cf402 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -423,7 +423,7 @@ void graphedit_operatortypes(void) WM_operatortype_append(GRAPH_OT_view_all); WM_operatortype_append(GRAPH_OT_view_selected); WM_operatortype_append(GRAPH_OT_view_frame); - WM_operatortype_append(GRAPH_OT_view_channels); + WM_operatortype_append(GRAPH_OT_view_selected_channels); WM_operatortype_append(GRAPH_OT_ghost_curves_create); WM_operatortype_append(GRAPH_OT_ghost_curves_clear); diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c index ead22052d59..0914f376198 100644 --- a/source/blender/editors/space_graph/graph_view.c +++ b/source/blender/editors/space_graph/graph_view.c @@ -453,11 +453,11 @@ static int graphkeys_view_channel_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GRAPH_OT_view_channels(wmOperatorType *ot) +void GRAPH_OT_view_selected_channels(wmOperatorType *ot) { /* Identifiers */ ot->name = "Frame Selected Channels"; - ot->idname = "GRAPH_OT_view_channels"; + ot->idname = "GRAPH_OT_view_selected_channels"; ot->description = "Reset viewable area to show the selected channels"; /* API callbacks */ -- 2.30.2 From d820ffe64e502585d55c4357545663eaad1ecb7a Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Fri, 13 Jan 2023 18:22:25 +0100 Subject: [PATCH 04/21] move function --- release/scripts/startup/bl_ui/space_dopesheet.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 716a9fd5481..c71c2d46969 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -689,6 +689,9 @@ class DOPESHEET_MT_channel_context_menu(Menu): # This menu is used from the graph editor too. is_graph_editor = context.area.type == 'GRAPH_EDITOR' + layout.separator() + layout.operator("graph.view_selected_channels") + layout.operator("anim.channels_setting_enable", text="Mute Channels").type = 'MUTE' layout.operator("anim.channels_setting_disable", text="Unmute Channels").type = 'MUTE' layout.separator() @@ -699,9 +702,6 @@ class DOPESHEET_MT_channel_context_menu(Menu): layout.operator("anim.channels_group") layout.operator("anim.channels_ungroup") - layout.separator() - layout.operator("graph.view_selected_channels") - layout.separator() layout.operator("anim.channels_editable_toggle") -- 2.30.2 From 61c7827685d90fa4ff85866a141490229550f5b4 Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Sun, 15 Jan 2023 14:14:55 +0100 Subject: [PATCH 05/21] implement alt mmb operator --- .../keyconfig/keymap_data/blender_default.py | 2 +- .../editors/space_graph/graph_intern.h | 1 + .../blender/editors/space_graph/graph_ops.c | 1 + .../blender/editors/space_graph/graph_view.c | 180 ++++++++++++++---- 4 files changed, 144 insertions(+), 40 deletions(-) diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 8ee2091b1fc..e2de5f3530a 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -3509,7 +3509,7 @@ def km_animation_channels(params): # Menus. *_template_items_context_menu("DOPESHEET_MT_channel_context_menu", params.context_menu_event), # View - ("graph.view_selected_channels", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "alt": True}, None), + ("graph.view_channel_pick", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "alt": True}, None), ("graph.view_selected_channels", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None), ]) diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index 64525bdb147..0c33bbe6bbd 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -102,6 +102,7 @@ void GRAPH_OT_view_all(struct wmOperatorType *ot); void GRAPH_OT_view_selected(struct wmOperatorType *ot); void GRAPH_OT_view_frame(struct wmOperatorType *ot); void GRAPH_OT_view_selected_channels(struct wmOperatorType *ot); +void GRAPH_OT_view_channel_pick(struct wmOperatorType *ot); void GRAPH_OT_click_insert(struct wmOperatorType *ot); void GRAPH_OT_keyframe_insert(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 831913cf402..875d94b7c55 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -424,6 +424,7 @@ void graphedit_operatortypes(void) WM_operatortype_append(GRAPH_OT_view_selected); WM_operatortype_append(GRAPH_OT_view_frame); WM_operatortype_append(GRAPH_OT_view_selected_channels); + WM_operatortype_append(GRAPH_OT_view_channel_pick); WM_operatortype_append(GRAPH_OT_ghost_curves_create); WM_operatortype_append(GRAPH_OT_ghost_curves_clear); diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c index 0914f376198..9d250a871ce 100644 --- a/source/blender/editors/space_graph/graph_view.c +++ b/source/blender/editors/space_graph/graph_view.c @@ -378,6 +378,65 @@ void GRAPH_OT_view_frame(wmOperatorType *ot) /** \name View Channel Operator * \{ */ +static void get_normalized_fcurve_bounds(FCurve *fcu, + bAnimContext *ac, + bAnimListElem *ale, + bool include_handles, + const float range[2], + rctf *r_bounds) +{ + const bool fcu_selection_only = false; + BKE_fcurve_calc_bounds(fcu, + &r_bounds->xmin, + &r_bounds->xmax, + &r_bounds->ymin, + &r_bounds->ymax, + fcu_selection_only, + include_handles, + range); + + float unitFac, offset; + short mapping_flag = ANIM_get_normalization_flags(ac); + unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); + r_bounds->ymin += offset; + r_bounds->ymax += offset; + r_bounds->ymin *= unitFac; + r_bounds->ymax *= unitFac; +} + +static void get_view_range(Scene *scene, const bool use_preview_range, float r_range[2]) +{ + if (use_preview_range && scene->r.flag & SCER_PRV_RANGE) { + r_range[0] = scene->r.psfra; + r_range[1] = scene->r.pefra; + } + else { + r_range[0] = -FLT_MAX; + r_range[1] = FLT_MAX; + } +} + +static void pad_fcurve_bounds(bContext *C, bAnimContext *ac, rctf *bounds) +{ + BLI_rctf_scale(bounds, 1.1f); + + /* Take regions into account, that could block the view. + * Marker region is supposed to be larger than the scroll-bar, so prioritize it. */ + float pad_top = UI_TIME_SCRUB_MARGIN_Y; + float pad_bottom = BLI_listbase_is_empty(ED_context_get_markers(C)) ? V2D_SCROLL_HANDLE_HEIGHT : + UI_MARKER_MARGIN_Y; + BLI_rctf_pad_y(bounds, ac->region->winy, pad_bottom, pad_top); +} + +static void move_graph_view(bContext *C, bAnimContext *ac, rctf *bounds, const int smooth_viewtx) +{ + LISTBASE_FOREACH (ARegion *, region, &ac->area->regionbase) { + if (region->regiontype == RGN_TYPE_WINDOW) { + UI_view2d_smooth_view(C, region, bounds, smooth_viewtx); + } + } +} + static int graphkeys_view_channel_exec(bContext *C, wmOperator *op) { bAnimContext ac; @@ -393,19 +452,12 @@ static int graphkeys_view_channel_exec(bContext *C, wmOperator *op) float range[2]; const bool use_preview_range = RNA_boolean_get(op->ptr, "use_preview_range"); - if (use_preview_range && ac.scene->r.flag & SCER_PRV_RANGE) { - range[0] = ac.scene->r.psfra; - range[1] = ac.scene->r.pefra; - } - else { - range[0] = -FLT_MAX; - range[1] = FLT_MAX; - } + get_view_range(ac.scene, use_preview_range, range); rctf bounds = {.xmin = FLT_MAX, .xmax = -FLT_MAX, .ymin = FLT_MAX, .ymax = -FLT_MAX}; bAnimListElem *ale; - const bool fcu_selection_only = false; + const bool include_handles = RNA_boolean_get(op->ptr, "include_handles"); for (ale = anim_data.first; ale; ale = ale->next) { @@ -414,41 +466,14 @@ static int graphkeys_view_channel_exec(bContext *C, wmOperator *op) } FCurve *fcu = (FCurve *)ale->key_data; rctf fcu_bounds; - BKE_fcurve_calc_bounds(fcu, - &fcu_bounds.xmin, - &fcu_bounds.xmax, - &fcu_bounds.ymin, - &fcu_bounds.ymax, - fcu_selection_only, - include_handles, - range); - - float unitFac, offset; - short mapping_flag = ANIM_get_normalization_flags(&ac); - unitFac = ANIM_unit_mapping_get_factor(ac.scene, ale->id, fcu, mapping_flag, &offset); - fcu_bounds.ymin += offset; - fcu_bounds.ymax += offset; - fcu_bounds.ymin *= unitFac; - fcu_bounds.ymax *= unitFac; - + get_normalized_fcurve_bounds(fcu, &ac, ale, include_handles, range, &fcu_bounds); BLI_rctf_union(&bounds, &fcu_bounds); } - BLI_rctf_scale(&bounds, 1.1f); - - /* Take regions into account, that could block the view. - * Marker region is supposed to be larger than the scroll-bar, so prioritize it. */ - float pad_top = UI_TIME_SCRUB_MARGIN_Y; - float pad_bottom = BLI_listbase_is_empty(ED_context_get_markers(C)) ? V2D_SCROLL_HANDLE_HEIGHT : - UI_MARKER_MARGIN_Y; - BLI_rctf_pad_y(&bounds, ac.region->winy, pad_bottom, pad_top); + pad_fcurve_bounds(C, &ac, &bounds); const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - LISTBASE_FOREACH (ARegion *, region, &ac.area->regionbase) { - if (region->regiontype == RGN_TYPE_WINDOW) { - UI_view2d_smooth_view(C, region, &bounds, smooth_viewtx); - } - } + move_graph_view(C, &ac, &bounds, smooth_viewtx); return OPERATOR_FINISHED; } @@ -479,6 +504,83 @@ void GRAPH_OT_view_selected_channels(wmOperatorType *ot) "Ignore frames outside of the preview range"); } +static int graphkeys_view_channel_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + bAnimContext ac; + + if (ANIM_animdata_get_context(C, &ac) == 0) { + return OPERATOR_CANCELLED; + } + + float x, y; + int channel_index; + ARegion *region = ac.region; + View2D *v2d = ®ion->v2d; + + UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y); + UI_view2d_listview_view_to_cell(ACHANNEL_NAMEWIDTH, + ACHANNEL_STEP(&ac), + 0, + ACHANNEL_FIRST_TOP(&ac), + x, + y, + NULL, + &channel_index); + + ListBase anim_data = {NULL, NULL}; + int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS | + ANIMFILTER_FCURVESONLY); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + bAnimListElem *ale; + ale = BLI_findlink(&anim_data, channel_index); + if (ale->datatype != ALE_FCURVE) { + return OPERATOR_CANCELLED; + } + + float range[2]; + const bool use_preview_range = RNA_boolean_get(op->ptr, "use_preview_range"); + get_view_range(ac.scene, use_preview_range, range); + + rctf fcu_bounds; + const bool include_handles = RNA_boolean_get(op->ptr, "include_handles"); + FCurve *fcu = (FCurve *)ale->key_data; + get_normalized_fcurve_bounds(fcu, &ac, ale, include_handles, range, &fcu_bounds); + + pad_fcurve_bounds(C, &ac, &fcu_bounds); + + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + move_graph_view(C, &ac, &fcu_bounds, smooth_viewtx); + + return OPERATOR_FINISHED; +} + +void GRAPH_OT_view_channel_pick(wmOperatorType *ot) +{ + /* Identifiers */ + ot->name = "Frame Channel Under Cursor"; + ot->idname = "GRAPH_OT_view_channel_pick"; + ot->description = "Reset viewable area to show the channel under the cursor"; + + /* API callbacks */ + ot->invoke = graphkeys_view_channel_pick_invoke; + ot->poll = ED_operator_graphedit_active; + + ot->flag = 0; + + ot->prop = RNA_def_boolean(ot->srna, + "include_handles", + true, + "Include Handles", + "Include handles of keyframes when calculating extents"); + + ot->prop = RNA_def_boolean(ot->srna, + "use_preview_range", + true, + "Use Preview Range", + "Ignore frames outside of the preview range"); +} + /** \} */ /* -------------------------------------------------------------------- */ -- 2.30.2 From 55a2e7fc36a6ba46a3977af53014b56876525d97 Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Sun, 15 Jan 2023 14:34:06 +0100 Subject: [PATCH 06/21] comments --- source/blender/editors/space_graph/graph_view.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c index 9d250a871ce..1de8c70b2bc 100644 --- a/source/blender/editors/space_graph/graph_view.c +++ b/source/blender/editors/space_graph/graph_view.c @@ -430,6 +430,8 @@ static void pad_fcurve_bounds(bContext *C, bAnimContext *ac, rctf *bounds) static void move_graph_view(bContext *C, bAnimContext *ac, rctf *bounds, const int smooth_viewtx) { + /* Iterate through regions because the operator might not have been called from the correct + * region. */ LISTBASE_FOREACH (ARegion *, region, &ac->area->regionbase) { if (region->regiontype == RGN_TYPE_WINDOW) { UI_view2d_smooth_view(C, region, bounds, smooth_viewtx); @@ -447,7 +449,7 @@ static int graphkeys_view_channel_exec(bContext *C, wmOperator *op) } ListBase anim_data = {NULL, NULL}; - int filter = (ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_FCURVESONLY); + const int filter = (ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_FCURVESONLY); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); float range[2]; @@ -457,7 +459,6 @@ static int graphkeys_view_channel_exec(bContext *C, wmOperator *op) rctf bounds = {.xmin = FLT_MAX, .xmax = -FLT_MAX, .ymin = FLT_MAX, .ymax = -FLT_MAX}; bAnimListElem *ale; - const bool include_handles = RNA_boolean_get(op->ptr, "include_handles"); for (ale = anim_data.first; ale; ale = ale->next) { -- 2.30.2 From e1fe67cbc37d90aaa1469ae4e7222b93a25b55f9 Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Sun, 15 Jan 2023 14:38:37 +0100 Subject: [PATCH 07/21] cleanup --- source/blender/blenkernel/intern/fcurve.c | 7 ------- source/blender/editors/space_graph/graph_view.c | 4 ++-- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index a1e6737db50..62ccac78320 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -688,13 +688,6 @@ bool BKE_fcurve_calc_bounds(FCurve *fcu, foundvert = true; } } - if (range != NULL) { - /* The end of the range might not have keyframes, but might be an extreme. */ - float start_y = evaluate_fcurve(fcu, range[0]); - float end_y = evaluate_fcurve(fcu, range[1]); - yminv = min_fff(yminv, start_y, end_y); - ymaxv = max_fff(ymaxv, start_y, end_y); - } } } else if (fcu->fpt) { diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c index 1de8c70b2bc..33bd1aaad57 100644 --- a/source/blender/editors/space_graph/graph_view.c +++ b/source/blender/editors/space_graph/graph_view.c @@ -439,7 +439,7 @@ static void move_graph_view(bContext *C, bAnimContext *ac, rctf *bounds, const i } } -static int graphkeys_view_channel_exec(bContext *C, wmOperator *op) +static int graphkeys_view_selected_channels_exec(bContext *C, wmOperator *op) { bAnimContext ac; @@ -487,7 +487,7 @@ void GRAPH_OT_view_selected_channels(wmOperatorType *ot) ot->description = "Reset viewable area to show the selected channels"; /* API callbacks */ - ot->exec = graphkeys_view_channel_exec; + ot->exec = graphkeys_view_selected_channels_exec; ot->poll = ED_operator_graphedit_active; ot->flag = 0; -- 2.30.2 From aef767b6503333713ce6ea2397a7b2839f2d7966 Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Thu, 19 Jan 2023 10:11:28 +0100 Subject: [PATCH 08/21] fix crash when focusing on group --- release/scripts/addons | 2 +- release/scripts/addons_contrib | 2 +- source/blender/editors/space_graph/graph_view.c | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/release/scripts/addons b/release/scripts/addons index bf49eeaa14c..e6e204ef0ed 160000 --- a/release/scripts/addons +++ b/release/scripts/addons @@ -1 +1 @@ -Subproject commit bf49eeaa14c445d3c53068203fdf91bff568fe64 +Subproject commit e6e204ef0ed78a8381f446e7d0204b84b4d50e16 diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib index 0f72f6c85c3..9d538629bb8 160000 --- a/release/scripts/addons_contrib +++ b/release/scripts/addons_contrib @@ -1 +1 @@ -Subproject commit 0f72f6c85c3743a9072273acb6a8a34b1cf1064b +Subproject commit 9d538629bb8a425991c7d10a49bab1ba0788c18f diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c index 33bd1aaad57..7f2dd7dd64b 100644 --- a/source/blender/editors/space_graph/graph_view.c +++ b/source/blender/editors/space_graph/graph_view.c @@ -450,7 +450,11 @@ static int graphkeys_view_selected_channels_exec(bContext *C, wmOperator *op) ListBase anim_data = {NULL, NULL}; const int filter = (ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_FCURVESONLY); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + size_t anim_data_length = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + if (anim_data_length == 0) { + return OPERATOR_CANCELLED; + } float range[2]; const bool use_preview_range = RNA_boolean_get(op->ptr, "use_preview_range"); @@ -476,6 +480,8 @@ static int graphkeys_view_selected_channels_exec(bContext *C, wmOperator *op) const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); move_graph_view(C, &ac, &bounds, smooth_viewtx); + ANIM_animdata_freelist(&anim_data); + return OPERATOR_FINISHED; } -- 2.30.2 From e89c6ecf543550553603ba02bd38b7deb592f4dc Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Thu, 19 Jan 2023 10:36:35 +0100 Subject: [PATCH 09/21] constness --- source/blender/editors/space_graph/graph_view.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c index 7f2dd7dd64b..b1202df44ff 100644 --- a/source/blender/editors/space_graph/graph_view.c +++ b/source/blender/editors/space_graph/graph_view.c @@ -535,8 +535,8 @@ static int graphkeys_view_channel_pick_invoke(bContext *C, wmOperator *op, const &channel_index); ListBase anim_data = {NULL, NULL}; - int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS | - ANIMFILTER_FCURVESONLY); + const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | + ANIMFILTER_LIST_CHANNELS | ANIMFILTER_FCURVESONLY); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); bAnimListElem *ale; -- 2.30.2 From 97889c683f2ad37c8fa1e3e8fa8cde3d0188e82f Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Thu, 19 Jan 2023 11:23:00 +0100 Subject: [PATCH 10/21] new poll --- source/blender/editors/space_graph/graph_view.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c index b1202df44ff..22da890277e 100644 --- a/source/blender/editors/space_graph/graph_view.c +++ b/source/blender/editors/space_graph/graph_view.c @@ -485,6 +485,11 @@ static int graphkeys_view_selected_channels_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static bool view_channel_poll(bContext *C) +{ + return ED_operator_action_active(C) || ED_operator_graphedit_active(C); +} + void GRAPH_OT_view_selected_channels(wmOperatorType *ot) { /* Identifiers */ @@ -494,7 +499,7 @@ void GRAPH_OT_view_selected_channels(wmOperatorType *ot) /* API callbacks */ ot->exec = graphkeys_view_selected_channels_exec; - ot->poll = ED_operator_graphedit_active; + ot->poll = view_channel_poll; ot->flag = 0; @@ -541,7 +546,7 @@ static int graphkeys_view_channel_pick_invoke(bContext *C, wmOperator *op, const bAnimListElem *ale; ale = BLI_findlink(&anim_data, channel_index); - if (ale->datatype != ALE_FCURVE) { + if (ale == NULL || ale->datatype != ALE_FCURVE) { return OPERATOR_CANCELLED; } @@ -571,7 +576,7 @@ void GRAPH_OT_view_channel_pick(wmOperatorType *ot) /* API callbacks */ ot->invoke = graphkeys_view_channel_pick_invoke; - ot->poll = ED_operator_graphedit_active; + ot->poll = view_channel_poll; ot->flag = 0; -- 2.30.2 From 3b95f60f2b49e55f9452121d470059f1820f03e4 Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Thu, 19 Jan 2023 12:48:23 +0100 Subject: [PATCH 11/21] move operators to anim_channels_edit.c --- .../keyconfig/keymap_data/blender_default.py | 4 +- .../scripts/startup/bl_ui/space_dopesheet.py | 2 +- release/scripts/startup/bl_ui/space_graph.py | 2 +- .../editors/animation/anim_channels_edit.c | 268 ++++++++++++++++++ .../editors/space_graph/graph_intern.h | 2 - .../blender/editors/space_graph/graph_ops.c | 2 - .../blender/editors/space_graph/graph_view.c | 221 --------------- 7 files changed, 272 insertions(+), 229 deletions(-) diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index e010d3ff05b..37141b55fd6 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -3509,8 +3509,8 @@ def km_animation_channels(params): # Menus. *_template_items_context_menu("DOPESHEET_MT_channel_context_menu", params.context_menu_event), # View - ("graph.view_channel_pick", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "alt": True}, None), - ("graph.view_selected_channels", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None), + ("anim.channel_view_pick", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "alt": True}, None), + ("anim.channels_view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None), ]) return keymap diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index c71c2d46969..0498ab836a5 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -690,7 +690,7 @@ class DOPESHEET_MT_channel_context_menu(Menu): is_graph_editor = context.area.type == 'GRAPH_EDITOR' layout.separator() - layout.operator("graph.view_selected_channels") + layout.operator("anim.channels_view_selected") layout.operator("anim.channels_setting_enable", text="Mute Channels").type = 'MUTE' layout.operator("anim.channels_setting_disable", text="Unmute Channels").type = 'MUTE' diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index 384a92820ac..bb06b1b60e5 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -239,7 +239,7 @@ class GRAPH_MT_channel(Menu): layout.operator("anim.channels_fcurves_enable") layout.separator() - layout.operator("graph.view_selected_channels") + layout.operator("anim.channels_view_selected") class GRAPH_MT_key(Menu): diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index aa8b5796645..3df1a15ad3f 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -47,6 +47,7 @@ #include "ED_anim_api.h" #include "ED_armature.h" #include "ED_keyframes_edit.h" /* XXX move the select modes out of there! */ +#include "ED_markers.h" #include "ED_object.h" #include "ED_screen.h" #include "ED_select_utils.h" @@ -3637,6 +3638,270 @@ static void ANIM_OT_channel_select_keys(wmOperatorType *ot) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name View Channel Operator + * \{ */ + +static void get_normalized_fcurve_bounds(FCurve *fcu, + bAnimContext *ac, + bAnimListElem *ale, + bool include_handles, + const float range[2], + rctf *r_bounds) +{ + const bool fcu_selection_only = false; + BKE_fcurve_calc_bounds(fcu, + &r_bounds->xmin, + &r_bounds->xmax, + &r_bounds->ymin, + &r_bounds->ymax, + fcu_selection_only, + include_handles, + range); + + float unitFac, offset; + short mapping_flag = ANIM_get_normalization_flags(ac); + unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); + r_bounds->ymin += offset; + r_bounds->ymax += offset; + r_bounds->ymin *= unitFac; + r_bounds->ymax *= unitFac; +} + +static void get_view_range(Scene *scene, const bool use_preview_range, float r_range[2]) +{ + if (use_preview_range && scene->r.flag & SCER_PRV_RANGE) { + r_range[0] = scene->r.psfra; + r_range[1] = scene->r.pefra; + } + else { + r_range[0] = -FLT_MAX; + r_range[1] = FLT_MAX; + } +} + +/* Take regions into account, that could block the view. + * Marker region is supposed to be larger than the scroll-bar, so prioritize it. */ +static void add_region_padding(bContext *C, bAnimContext *ac, rctf *bounds) +{ + BLI_rctf_scale(bounds, 1.1f); + + float pad_top = UI_TIME_SCRUB_MARGIN_Y; + float pad_bottom = BLI_listbase_is_empty(ED_context_get_markers(C)) ? V2D_SCROLL_HANDLE_HEIGHT : + UI_MARKER_MARGIN_Y; + BLI_rctf_pad_y(bounds, ac->region->winy, pad_bottom, pad_top); +} + +/* Iterates through regions because the operator might not have been called from the correct + * region. */ +static void move_graph_view(bContext *C, bAnimContext *ac, rctf *bounds, const int smooth_viewtx) +{ + LISTBASE_FOREACH (ARegion *, region, &ac->area->regionbase) { + if (region->regiontype == RGN_TYPE_WINDOW) { + UI_view2d_smooth_view(C, region, bounds, smooth_viewtx); + } + } +} + +static int graphkeys_view_selected_channels_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + + /* Get editor data. */ + if (ANIM_animdata_get_context(C, &ac) == 0) { + return OPERATOR_CANCELLED; + } + + ListBase anim_data = {NULL, NULL}; + const int filter = (ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_FCURVESONLY); + size_t anim_data_length = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + if (anim_data_length == 0) { + return OPERATOR_CANCELLED; + } + + float range[2]; + const bool use_preview_range = RNA_boolean_get(op->ptr, "use_preview_range"); + get_view_range(ac.scene, use_preview_range, range); + + rctf bounds = {.xmin = FLT_MAX, .xmax = -FLT_MAX, .ymin = FLT_MAX, .ymax = -FLT_MAX}; + + bAnimListElem *ale; + const bool include_handles = RNA_boolean_get(op->ptr, "include_handles"); + + for (ale = anim_data.first; ale; ale = ale->next) { + if (ale->datatype != ALE_FCURVE) { + continue; + } + FCurve *fcu = (FCurve *)ale->key_data; + rctf fcu_bounds; + get_normalized_fcurve_bounds(fcu, &ac, ale, include_handles, range, &fcu_bounds); + BLI_rctf_union(&bounds, &fcu_bounds); + } + + add_region_padding(C, &ac, &bounds); + + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + move_graph_view(C, &ac, &bounds, smooth_viewtx); + + ANIM_animdata_freelist(&anim_data); + + return OPERATOR_FINISHED; +} + +static bool channel_view_poll(bContext *C) +{ + return ED_operator_action_active(C) || ED_operator_graphedit_active(C); +} + +static void ANIM_OT_channels_view_selected(wmOperatorType *ot) +{ + /* Identifiers */ + ot->name = "Frame Selected Channels"; + ot->idname = "ANIM_OT_channels_view_selected"; + ot->description = "Reset viewable area to show the selected channels"; + + /* API callbacks */ + ot->exec = graphkeys_view_selected_channels_exec; + ot->poll = channel_view_poll; + + ot->flag = 0; + + ot->prop = RNA_def_boolean(ot->srna, + "include_handles", + true, + "Include Handles", + "Include handles of keyframes when calculating extents"); + + ot->prop = RNA_def_boolean(ot->srna, + "use_preview_range", + true, + "Use Preview Range", + "Ignore frames outside of the preview range"); +} + +static void get_gpencil_bounds(bGPDlayer *gpl, const float range[2], rctf *r_bounds) +{ + bool found_start = false; + int start_frame = 0; + int end_frame = 1; + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + if (gpf->framenum < range[0]) { + continue; + } + if (gpf->framenum > range[1]) { + break; + } + if (!found_start) { + start_frame = gpf->framenum; + found_start = true; + } + end_frame = gpf->framenum; + } + r_bounds->xmin = start_frame; + r_bounds->xmax = end_frame; + r_bounds->ymin = 0; + r_bounds->ymax = 1; +} + +static void get_channel_bounds(bAnimContext *ac, + bAnimListElem *ale, + const float range[2], + const bool include_handles, + rctf *r_bounds) +{ + switch (ale->datatype) { + case ALE_GPFRAME: + bGPDlayer *gpl = (bGPDlayer *)ale->data; + get_gpencil_bounds(gpl, range, r_bounds); + break; + case ALE_FCURVE: + FCurve *fcu = (FCurve *)ale->key_data; + get_normalized_fcurve_bounds(fcu, ac, ale, include_handles, range, r_bounds); + break; + } +} + +static int graphkeys_channel_view_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + bAnimContext ac; + + if (ANIM_animdata_get_context(C, &ac) == 0) { + return OPERATOR_CANCELLED; + } + + float x, y; + int channel_index; + ARegion *region = ac.region; + View2D *v2d = ®ion->v2d; + + UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y); + UI_view2d_listview_view_to_cell(ACHANNEL_NAMEWIDTH, + ACHANNEL_STEP(&ac), + 0, + ACHANNEL_FIRST_TOP(&ac), + x, + y, + NULL, + &channel_index); + + ListBase anim_data = {NULL, NULL}; + const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + bAnimListElem *ale; + ale = BLI_findlink(&anim_data, channel_index); + if (ale == NULL) { + ANIM_animdata_freelist(&anim_data); + return OPERATOR_CANCELLED; + } + + float range[2]; + const bool use_preview_range = RNA_boolean_get(op->ptr, "use_preview_range"); + get_view_range(ac.scene, use_preview_range, range); + + rctf bounds; + const bool include_handles = RNA_boolean_get(op->ptr, "include_handles"); + get_channel_bounds(&ac, ale, range, include_handles, &bounds); + + add_region_padding(C, &ac, &bounds); + + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + move_graph_view(C, &ac, &bounds, smooth_viewtx); + + ANIM_animdata_freelist(&anim_data); + + return OPERATOR_FINISHED; +} + +static void ANIM_OT_channel_view_pick(wmOperatorType *ot) +{ + /* Identifiers */ + ot->name = "Frame Channel Under Cursor"; + ot->idname = "ANIM_OT_channel_view_pick"; + ot->description = "Reset viewable area to show the channel under the cursor"; + + /* API callbacks */ + ot->invoke = graphkeys_channel_view_pick_invoke; + ot->poll = channel_view_poll; + + ot->flag = 0; + + ot->prop = RNA_def_boolean(ot->srna, + "include_handles", + true, + "Include Handles", + "Include handles of keyframes when calculating extents"); + + ot->prop = RNA_def_boolean(ot->srna, + "use_preview_range", + true, + "Use Preview Range", + "Ignore frames outside of the preview range"); +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Operator Registration * \{ */ @@ -3656,6 +3921,9 @@ void ED_operatortypes_animchannels(void) WM_operatortype_append(ANIM_OT_channels_setting_disable); WM_operatortype_append(ANIM_OT_channels_setting_toggle); + WM_operatortype_append(ANIM_OT_channel_view_pick); + WM_operatortype_append(ANIM_OT_channels_view_selected); + WM_operatortype_append(ANIM_OT_channels_delete); /* XXX does this need to be a separate operator? */ diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index 0c33bbe6bbd..a685216db31 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -101,8 +101,6 @@ void GRAPH_OT_previewrange_set(struct wmOperatorType *ot); void GRAPH_OT_view_all(struct wmOperatorType *ot); void GRAPH_OT_view_selected(struct wmOperatorType *ot); void GRAPH_OT_view_frame(struct wmOperatorType *ot); -void GRAPH_OT_view_selected_channels(struct wmOperatorType *ot); -void GRAPH_OT_view_channel_pick(struct wmOperatorType *ot); void GRAPH_OT_click_insert(struct wmOperatorType *ot); void GRAPH_OT_keyframe_insert(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 875d94b7c55..b178a3d3430 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -423,8 +423,6 @@ void graphedit_operatortypes(void) WM_operatortype_append(GRAPH_OT_view_all); WM_operatortype_append(GRAPH_OT_view_selected); WM_operatortype_append(GRAPH_OT_view_frame); - WM_operatortype_append(GRAPH_OT_view_selected_channels); - WM_operatortype_append(GRAPH_OT_view_channel_pick); WM_operatortype_append(GRAPH_OT_ghost_curves_create); WM_operatortype_append(GRAPH_OT_ghost_curves_clear); diff --git a/source/blender/editors/space_graph/graph_view.c b/source/blender/editors/space_graph/graph_view.c index 22da890277e..e6cbdd63ae6 100644 --- a/source/blender/editors/space_graph/graph_view.c +++ b/source/blender/editors/space_graph/graph_view.c @@ -374,227 +374,6 @@ void GRAPH_OT_view_frame(wmOperatorType *ot) /** \} */ -/* -------------------------------------------------------------------- */ -/** \name View Channel Operator - * \{ */ - -static void get_normalized_fcurve_bounds(FCurve *fcu, - bAnimContext *ac, - bAnimListElem *ale, - bool include_handles, - const float range[2], - rctf *r_bounds) -{ - const bool fcu_selection_only = false; - BKE_fcurve_calc_bounds(fcu, - &r_bounds->xmin, - &r_bounds->xmax, - &r_bounds->ymin, - &r_bounds->ymax, - fcu_selection_only, - include_handles, - range); - - float unitFac, offset; - short mapping_flag = ANIM_get_normalization_flags(ac); - unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); - r_bounds->ymin += offset; - r_bounds->ymax += offset; - r_bounds->ymin *= unitFac; - r_bounds->ymax *= unitFac; -} - -static void get_view_range(Scene *scene, const bool use_preview_range, float r_range[2]) -{ - if (use_preview_range && scene->r.flag & SCER_PRV_RANGE) { - r_range[0] = scene->r.psfra; - r_range[1] = scene->r.pefra; - } - else { - r_range[0] = -FLT_MAX; - r_range[1] = FLT_MAX; - } -} - -static void pad_fcurve_bounds(bContext *C, bAnimContext *ac, rctf *bounds) -{ - BLI_rctf_scale(bounds, 1.1f); - - /* Take regions into account, that could block the view. - * Marker region is supposed to be larger than the scroll-bar, so prioritize it. */ - float pad_top = UI_TIME_SCRUB_MARGIN_Y; - float pad_bottom = BLI_listbase_is_empty(ED_context_get_markers(C)) ? V2D_SCROLL_HANDLE_HEIGHT : - UI_MARKER_MARGIN_Y; - BLI_rctf_pad_y(bounds, ac->region->winy, pad_bottom, pad_top); -} - -static void move_graph_view(bContext *C, bAnimContext *ac, rctf *bounds, const int smooth_viewtx) -{ - /* Iterate through regions because the operator might not have been called from the correct - * region. */ - LISTBASE_FOREACH (ARegion *, region, &ac->area->regionbase) { - if (region->regiontype == RGN_TYPE_WINDOW) { - UI_view2d_smooth_view(C, region, bounds, smooth_viewtx); - } - } -} - -static int graphkeys_view_selected_channels_exec(bContext *C, wmOperator *op) -{ - bAnimContext ac; - - /* Get editor data. */ - if (ANIM_animdata_get_context(C, &ac) == 0) { - return OPERATOR_CANCELLED; - } - - ListBase anim_data = {NULL, NULL}; - const int filter = (ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_FCURVESONLY); - size_t anim_data_length = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - if (anim_data_length == 0) { - return OPERATOR_CANCELLED; - } - - float range[2]; - const bool use_preview_range = RNA_boolean_get(op->ptr, "use_preview_range"); - get_view_range(ac.scene, use_preview_range, range); - - rctf bounds = {.xmin = FLT_MAX, .xmax = -FLT_MAX, .ymin = FLT_MAX, .ymax = -FLT_MAX}; - - bAnimListElem *ale; - const bool include_handles = RNA_boolean_get(op->ptr, "include_handles"); - - for (ale = anim_data.first; ale; ale = ale->next) { - if (ale->datatype != ALE_FCURVE) { - continue; - } - FCurve *fcu = (FCurve *)ale->key_data; - rctf fcu_bounds; - get_normalized_fcurve_bounds(fcu, &ac, ale, include_handles, range, &fcu_bounds); - BLI_rctf_union(&bounds, &fcu_bounds); - } - - pad_fcurve_bounds(C, &ac, &bounds); - - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - move_graph_view(C, &ac, &bounds, smooth_viewtx); - - ANIM_animdata_freelist(&anim_data); - - return OPERATOR_FINISHED; -} - -static bool view_channel_poll(bContext *C) -{ - return ED_operator_action_active(C) || ED_operator_graphedit_active(C); -} - -void GRAPH_OT_view_selected_channels(wmOperatorType *ot) -{ - /* Identifiers */ - ot->name = "Frame Selected Channels"; - ot->idname = "GRAPH_OT_view_selected_channels"; - ot->description = "Reset viewable area to show the selected channels"; - - /* API callbacks */ - ot->exec = graphkeys_view_selected_channels_exec; - ot->poll = view_channel_poll; - - ot->flag = 0; - - ot->prop = RNA_def_boolean(ot->srna, - "include_handles", - true, - "Include Handles", - "Include handles of keyframes when calculating extents"); - - ot->prop = RNA_def_boolean(ot->srna, - "use_preview_range", - true, - "Use Preview Range", - "Ignore frames outside of the preview range"); -} - -static int graphkeys_view_channel_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - bAnimContext ac; - - if (ANIM_animdata_get_context(C, &ac) == 0) { - return OPERATOR_CANCELLED; - } - - float x, y; - int channel_index; - ARegion *region = ac.region; - View2D *v2d = ®ion->v2d; - - UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y); - UI_view2d_listview_view_to_cell(ACHANNEL_NAMEWIDTH, - ACHANNEL_STEP(&ac), - 0, - ACHANNEL_FIRST_TOP(&ac), - x, - y, - NULL, - &channel_index); - - ListBase anim_data = {NULL, NULL}; - const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | - ANIMFILTER_LIST_CHANNELS | ANIMFILTER_FCURVESONLY); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - bAnimListElem *ale; - ale = BLI_findlink(&anim_data, channel_index); - if (ale == NULL || ale->datatype != ALE_FCURVE) { - return OPERATOR_CANCELLED; - } - - float range[2]; - const bool use_preview_range = RNA_boolean_get(op->ptr, "use_preview_range"); - get_view_range(ac.scene, use_preview_range, range); - - rctf fcu_bounds; - const bool include_handles = RNA_boolean_get(op->ptr, "include_handles"); - FCurve *fcu = (FCurve *)ale->key_data; - get_normalized_fcurve_bounds(fcu, &ac, ale, include_handles, range, &fcu_bounds); - - pad_fcurve_bounds(C, &ac, &fcu_bounds); - - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - move_graph_view(C, &ac, &fcu_bounds, smooth_viewtx); - - return OPERATOR_FINISHED; -} - -void GRAPH_OT_view_channel_pick(wmOperatorType *ot) -{ - /* Identifiers */ - ot->name = "Frame Channel Under Cursor"; - ot->idname = "GRAPH_OT_view_channel_pick"; - ot->description = "Reset viewable area to show the channel under the cursor"; - - /* API callbacks */ - ot->invoke = graphkeys_view_channel_pick_invoke; - ot->poll = view_channel_poll; - - ot->flag = 0; - - ot->prop = RNA_def_boolean(ot->srna, - "include_handles", - true, - "Include Handles", - "Include handles of keyframes when calculating extents"); - - ot->prop = RNA_def_boolean(ot->srna, - "use_preview_range", - true, - "Use Preview Range", - "Ignore frames outside of the preview range"); -} - -/** \} */ - /* -------------------------------------------------------------------- */ /** \name Create Ghost-Curves Operator * -- 2.30.2 From 77c39d9ca44e3dd02f357f200e47282c70c1e798 Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Thu, 19 Jan 2023 12:57:42 +0100 Subject: [PATCH 12/21] make gpencil work in mmb click --- .../editors/animation/anim_channels_edit.c | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 3df1a15ad3f..aadd5bb07a3 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -3804,22 +3804,26 @@ static void get_gpencil_bounds(bGPDlayer *gpl, const float range[2], rctf *r_bou r_bounds->ymax = 1; } -static void get_channel_bounds(bAnimContext *ac, +static bool get_channel_bounds(bAnimContext *ac, bAnimListElem *ale, const float range[2], const bool include_handles, rctf *r_bounds) { + bool found_bounds = false; switch (ale->datatype) { case ALE_GPFRAME: bGPDlayer *gpl = (bGPDlayer *)ale->data; get_gpencil_bounds(gpl, range, r_bounds); + found_bounds = true; break; case ALE_FCURVE: FCurve *fcu = (FCurve *)ale->key_data; get_normalized_fcurve_bounds(fcu, ac, ale, include_handles, range, r_bounds); + found_bounds = true; break; } + return found_bounds; } static int graphkeys_channel_view_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) @@ -3830,26 +3834,13 @@ static int graphkeys_channel_view_pick_invoke(bContext *C, wmOperator *op, const return OPERATOR_CANCELLED; } - float x, y; - int channel_index; - ARegion *region = ac.region; - View2D *v2d = ®ion->v2d; - - UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y); - UI_view2d_listview_view_to_cell(ACHANNEL_NAMEWIDTH, - ACHANNEL_STEP(&ac), - 0, - ACHANNEL_FIRST_TOP(&ac), - x, - y, - NULL, - &channel_index); - ListBase anim_data = {NULL, NULL}; - const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); + const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS | + ANIMFILTER_LIST_CHANNELS); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); bAnimListElem *ale; + const int channel_index = animchannels_channel_get(&ac, event->mval); ale = BLI_findlink(&anim_data, channel_index); if (ale == NULL) { ANIM_animdata_freelist(&anim_data); @@ -3862,7 +3853,12 @@ static int graphkeys_channel_view_pick_invoke(bContext *C, wmOperator *op, const rctf bounds; const bool include_handles = RNA_boolean_get(op->ptr, "include_handles"); - get_channel_bounds(&ac, ale, range, include_handles, &bounds); + const bool found_bounds = get_channel_bounds(&ac, ale, range, include_handles, &bounds); + + if (!found_bounds) { + ANIM_animdata_freelist(&anim_data); + return OPERATOR_CANCELLED; + } add_region_padding(C, &ac, &bounds); -- 2.30.2 From 65d528aa5060bd5af869e5acb506f39e6993273e Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Thu, 19 Jan 2023 13:10:59 +0100 Subject: [PATCH 13/21] view selected for gp --- .../editors/animation/anim_channels_edit.c | 113 ++++++++++-------- 1 file changed, 60 insertions(+), 53 deletions(-) diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index aadd5bb07a3..c3fc121de93 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -3668,6 +3668,52 @@ static void get_normalized_fcurve_bounds(FCurve *fcu, r_bounds->ymax *= unitFac; } +static void get_gpencil_bounds(bGPDlayer *gpl, const float range[2], rctf *r_bounds) +{ + bool found_start = false; + int start_frame = 0; + int end_frame = 1; + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + if (gpf->framenum < range[0]) { + continue; + } + if (gpf->framenum > range[1]) { + break; + } + if (!found_start) { + start_frame = gpf->framenum; + found_start = true; + } + end_frame = gpf->framenum; + } + r_bounds->xmin = start_frame; + r_bounds->xmax = end_frame; + r_bounds->ymin = 0; + r_bounds->ymax = 1; +} + +static bool get_channel_bounds(bAnimContext *ac, + bAnimListElem *ale, + const float range[2], + const bool include_handles, + rctf *r_bounds) +{ + bool found_bounds = false; + switch (ale->datatype) { + case ALE_GPFRAME: + bGPDlayer *gpl = (bGPDlayer *)ale->data; + get_gpencil_bounds(gpl, range, r_bounds); + found_bounds = true; + break; + case ALE_FCURVE: + FCurve *fcu = (FCurve *)ale->key_data; + get_normalized_fcurve_bounds(fcu, ac, ale, include_handles, range, r_bounds); + found_bounds = true; + break; + } + return found_bounds; +} + static void get_view_range(Scene *scene, const bool use_preview_range, float r_range[2]) { if (use_preview_range && scene->r.flag & SCER_PRV_RANGE) { @@ -3713,7 +3759,8 @@ static int graphkeys_view_selected_channels_exec(bContext *C, wmOperator *op) } ListBase anim_data = {NULL, NULL}; - const int filter = (ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_FCURVESONLY); + const int filter = (ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_DATA_VISIBLE | + ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); size_t anim_data_length = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); if (anim_data_length == 0) { @@ -3729,14 +3776,20 @@ static int graphkeys_view_selected_channels_exec(bContext *C, wmOperator *op) bAnimListElem *ale; const bool include_handles = RNA_boolean_get(op->ptr, "include_handles"); + bool valid_bounds = false; for (ale = anim_data.first; ale; ale = ale->next) { - if (ale->datatype != ALE_FCURVE) { - continue; + rctf channel_bounds; + const bool found_bounds = get_channel_bounds( + &ac, ale, range, include_handles, &channel_bounds); + if (found_bounds) { + BLI_rctf_union(&bounds, &channel_bounds); + valid_bounds = true; } - FCurve *fcu = (FCurve *)ale->key_data; - rctf fcu_bounds; - get_normalized_fcurve_bounds(fcu, &ac, ale, include_handles, range, &fcu_bounds); - BLI_rctf_union(&bounds, &fcu_bounds); + } + + if (!valid_bounds) { + ANIM_animdata_freelist(&anim_data); + return OPERATOR_CANCELLED; } add_region_padding(C, &ac, &bounds); @@ -3780,52 +3833,6 @@ static void ANIM_OT_channels_view_selected(wmOperatorType *ot) "Ignore frames outside of the preview range"); } -static void get_gpencil_bounds(bGPDlayer *gpl, const float range[2], rctf *r_bounds) -{ - bool found_start = false; - int start_frame = 0; - int end_frame = 1; - LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - if (gpf->framenum < range[0]) { - continue; - } - if (gpf->framenum > range[1]) { - break; - } - if (!found_start) { - start_frame = gpf->framenum; - found_start = true; - } - end_frame = gpf->framenum; - } - r_bounds->xmin = start_frame; - r_bounds->xmax = end_frame; - r_bounds->ymin = 0; - r_bounds->ymax = 1; -} - -static bool get_channel_bounds(bAnimContext *ac, - bAnimListElem *ale, - const float range[2], - const bool include_handles, - rctf *r_bounds) -{ - bool found_bounds = false; - switch (ale->datatype) { - case ALE_GPFRAME: - bGPDlayer *gpl = (bGPDlayer *)ale->data; - get_gpencil_bounds(gpl, range, r_bounds); - found_bounds = true; - break; - case ALE_FCURVE: - FCurve *fcu = (FCurve *)ale->key_data; - get_normalized_fcurve_bounds(fcu, ac, ale, include_handles, range, r_bounds); - found_bounds = true; - break; - } - return found_bounds; -} - static int graphkeys_channel_view_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; -- 2.30.2 From 9e67d32813d89ae9f266fa55fd2782d39903fed2 Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Thu, 19 Jan 2023 13:19:15 +0100 Subject: [PATCH 14/21] add operator to dope sheet menu --- release/scripts/startup/bl_ui/space_dopesheet.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 0498ab836a5..a47c89af86e 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -474,6 +474,9 @@ class DOPESHEET_MT_channel(Menu): layout.separator() layout.operator("anim.channels_fcurves_enable") + layout.separator() + layout.operator("anim.channels_view_selected") + class DOPESHEET_MT_key(Menu): bl_label = "Key" @@ -601,6 +604,9 @@ class DOPESHEET_MT_gpencil_channel(Menu): layout.separator() layout.operator_menu_enum("anim.channels_move", "direction", text="Move...") + layout.separator() + layout.operator("anim.channels_view_selected") + class DOPESHEET_MT_gpencil_key(Menu): bl_label = "Key" -- 2.30.2 From 7f89cc7d8dd51128531b29c68a874a8c3cf28c4f Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Thu, 16 Feb 2023 12:59:54 +0100 Subject: [PATCH 15/21] extract logic for getting start and end bezt in range --- source/blender/blenkernel/BKE_fcurve.h | 4 +- source/blender/blenkernel/intern/fcurve.c | 74 ++++++++++++----------- 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index eeb3cc098b9..69cf1f1edf6 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -373,8 +373,10 @@ bool BKE_fcurve_calc_range( /** * Calculate the extents of F-Curve's data. + * \param range Only calculate the bounds of the FCurve in the given range. + * Does the full range if NULL. */ -bool BKE_fcurve_calc_bounds(struct FCurve *fcu, +bool BKE_fcurve_calc_bounds(const struct FCurve *fcu, float *xmin, float *xmax, float *ymin, diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 236eb40ee71..8e054d4d35f 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -557,10 +557,11 @@ int BKE_fcurve_bezt_binarysearch_index(const BezTriple array[], /* ...................................... */ /* Helper for calc_fcurve_* functions -> find first and last BezTriple to be used. */ -static short get_fcurve_end_keyframes(const FCurve *fcu, - BezTriple **first, - BezTriple **last, - const bool do_sel_only) +static bool get_fcurve_end_keyframes(const FCurve *fcu, + BezTriple **first, + BezTriple **last, + const bool do_sel_only, + const float range[2]) { bool found = false; @@ -573,11 +574,31 @@ static short get_fcurve_end_keyframes(const FCurve *fcu, return found; } + int first_index = 0; + int last_index = fcu->totvert - 1; + + if (range != NULL) { + /* If a range is passed in find the first and last keyframe within that range. */ + bool replace = false; + first_index = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, range[0], fcu->totvert, &replace); + last_index = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, range[1], fcu->totvert, &replace); + + /* If first and last index are the same, no keyframes were found in the range. */ + if (first_index == last_index) { + return found; + } + + /* The binary search returns an index where a keyframe would be inserted, + so it needs to be clamped to ensure it is in range of the array. */ + first_index = clamp_i(first_index, 0, fcu->totvert - 1); + last_index = clamp_i(last_index - 1, 0, fcu->totvert - 1); + } + /* Only include selected items? */ if (do_sel_only) { /* Find first selected. */ - BezTriple *bezt = fcu->bezt; - for (int i = 0; i < fcu->totvert; bezt++, i++) { + for (int i = first_index; i <= last_index; i++) { + BezTriple *bezt = &fcu->bezt[i]; if (BEZT_ISSEL_ANY(bezt)) { *first = bezt; found = true; @@ -586,8 +607,8 @@ static short get_fcurve_end_keyframes(const FCurve *fcu, } /* Find last selected. */ - bezt = ARRAY_LAST_ITEM(fcu->bezt, BezTriple, fcu->totvert); - for (int i = 0; i < fcu->totvert; bezt--, i++) { + for (int i = last_index; i >= first_index; i--) { + BezTriple *bezt = &fcu->bezt[i]; if (BEZT_ISSEL_ANY(bezt)) { *last = bezt; found = true; @@ -596,16 +617,15 @@ static short get_fcurve_end_keyframes(const FCurve *fcu, } } else { - /* Use the whole array. */ - *first = fcu->bezt; - *last = ARRAY_LAST_ITEM(fcu->bezt, BezTriple, fcu->totvert); + *first = &fcu->bezt[first_index]; + *last = &fcu->bezt[last_index]; found = true; } return found; } -bool BKE_fcurve_calc_bounds(FCurve *fcu, +bool BKE_fcurve_calc_bounds(const FCurve *fcu, float *xmin, float *xmax, float *ymin, @@ -618,29 +638,15 @@ bool BKE_fcurve_calc_bounds(FCurve *fcu, float yminv = 999999999.0f, ymaxv = -999999999.0f; bool foundvert = false; + const bool use_range = range != NULL; + if (fcu->totvert) { if (fcu->bezt) { - BezTriple *bezt_first = NULL, *bezt_last = NULL; if (xmin || xmax) { - if (range == NULL) { - /* Get endpoint keyframes. */ - foundvert = get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, do_sel_only); - } - else { - /* If a range is passed in find the first and last keyframe within that range. */ - bool replace = false; - int first_index = BKE_fcurve_bezt_binarysearch_index( - fcu->bezt, range[0], fcu->totvert, &replace); - int last_index = BKE_fcurve_bezt_binarysearch_index( - fcu->bezt, range[1], fcu->totvert, &replace); + BezTriple *bezt_first = NULL, *bezt_last = NULL; + foundvert = get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, do_sel_only, range); - /* If first and last index are the same, no keyframes were found in the range. */ - if (first_index != last_index) { - bezt_first = &fcu->bezt[clamp_i(first_index, 0, fcu->totvert - 1)]; - bezt_last = &fcu->bezt[clamp_i(last_index - 1, 0, fcu->totvert - 1)]; - } - } if (bezt_first) { BLI_assert(bezt_last != NULL); foundvert = true; @@ -661,7 +667,7 @@ bool BKE_fcurve_calc_bounds(FCurve *fcu, int i; for (bezt = fcu->bezt, i = 0; i < fcu->totvert; prevbezt = bezt, bezt++, i++) { - if (range != NULL && (bezt->vec[1][0] < range[0] || bezt->vec[1][0] > range[1])) { + if (use_range && (bezt->vec[1][0] < range[0] || bezt->vec[1][0] > range[1])) { continue; } if ((do_sel_only == false) || BEZT_ISSEL_ANY(bezt)) { @@ -736,10 +742,10 @@ bool BKE_fcurve_calc_bounds(FCurve *fcu, } if (xmin) { - *xmin = range != NULL ? range[0] : 0.0f; + *xmin = use_range ? range[0] : 0.0f; } if (xmax) { - *xmax = range != NULL ? range[1] : 1.0f; + *xmax = use_range ? range[1] : 1.0f; } if (ymin) { @@ -764,7 +770,7 @@ bool BKE_fcurve_calc_range( BezTriple *bezt_first = NULL, *bezt_last = NULL; /* Get endpoint keyframes. */ - get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, do_sel_only); + get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, do_sel_only, NULL); if (bezt_first) { BLI_assert(bezt_last != NULL); -- 2.30.2 From 406e2c0ac02af7b25a0b30fa82d6a974ab2570d7 Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Thu, 16 Feb 2023 13:17:28 +0100 Subject: [PATCH 16/21] implement sybrens notes --- release/datafiles/locale | 2 +- release/scripts/addons_contrib | 2 +- .../editors/animation/anim_channels_edit.c | 37 ++++++++++--------- source/tools | 2 +- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/release/datafiles/locale b/release/datafiles/locale index 4331c8e76c2..8d04896a130 160000 --- a/release/datafiles/locale +++ b/release/datafiles/locale @@ -1 +1 @@ -Subproject commit 4331c8e76c2f42b9fd903716c333d6cdeaa5cebd +Subproject commit 8d04896a130c12eb440b7b9ac33bf9dc152506b5 diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib index 14ab9273409..8f4599c4fb6 160000 --- a/release/scripts/addons_contrib +++ b/release/scripts/addons_contrib @@ -1 +1 @@ -Subproject commit 14ab9273409ea0231d08ba6e86fdc73d4e459e99 +Subproject commit 8f4599c4fb6ab2386f2498814c203fd676b2ccf2 diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 2a324bceac7..233cc02d318 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -3643,10 +3643,10 @@ static void ANIM_OT_channel_select_keys(wmOperatorType *ot) /** \name View Channel Operator * \{ */ -static void get_normalized_fcurve_bounds(FCurve *fcu, - bAnimContext *ac, - bAnimListElem *ale, - bool include_handles, +static void get_normalized_fcurve_bounds(const FCurve *fcu, + const bAnimContext *ac, + const bAnimListElem *ale, + const bool include_handles, const float range[2], rctf *r_bounds) { @@ -3659,14 +3659,14 @@ static void get_normalized_fcurve_bounds(FCurve *fcu, fcu_selection_only, include_handles, range); + const short mapping_flag = ANIM_get_normalization_flags(ac); - float unitFac, offset; - short mapping_flag = ANIM_get_normalization_flags(ac); - unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset); - r_bounds->ymin += offset; - r_bounds->ymax += offset; - r_bounds->ymin *= unitFac; - r_bounds->ymax *= unitFac; + float offset; + const float unit_fac = ANIM_unit_mapping_get_factor( + ac->scene, ale->id, fcu, mapping_flag, &offset); + + r_bounds->ymin = (r_bounds->ymin + offset) * unit_fac; + r_bounds->ymax = (r_bounds->ymax + offset) * unit_fac; } static void get_gpencil_bounds(bGPDlayer *gpl, const float range[2], rctf *r_bounds) @@ -3727,20 +3727,20 @@ static void get_view_range(Scene *scene, const bool use_preview_range, float r_r } } -/* Take regions into account, that could block the view. - * Marker region is supposed to be larger than the scroll-bar, so prioritize it. */ +/* Pad the given rctf with regions that could block the view. + * For example Markers and Time Scrubbing. */ static void add_region_padding(bContext *C, bAnimContext *ac, rctf *bounds) { BLI_rctf_scale(bounds, 1.1f); - float pad_top = UI_TIME_SCRUB_MARGIN_Y; - float pad_bottom = BLI_listbase_is_empty(ED_context_get_markers(C)) ? V2D_SCROLL_HANDLE_HEIGHT : - UI_MARKER_MARGIN_Y; + const float pad_top = UI_TIME_SCRUB_MARGIN_Y; + const float pad_bottom = BLI_listbase_is_empty(ED_context_get_markers(C)) ? + V2D_SCROLL_HANDLE_HEIGHT : + UI_MARKER_MARGIN_Y; BLI_rctf_pad_y(bounds, ac->region->winy, pad_bottom, pad_top); } -/* Iterates through regions because the operator might not have been called from the correct - * region. */ +/* Find the window region in the bAnimContext area and move it to bounds. */ static void move_graph_view(bContext *C, bAnimContext *ac, rctf *bounds, const int smooth_viewtx) { LISTBASE_FOREACH (ARegion *, region, &ac->area->regionbase) { @@ -3765,6 +3765,7 @@ static int graphkeys_view_selected_channels_exec(bContext *C, wmOperator *op) size_t anim_data_length = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); if (anim_data_length == 0) { + WM_report(RPT_WARNING, "No channels to operate on"); return OPERATOR_CANCELLED; } diff --git a/source/tools b/source/tools index e133fc08cd3..27826b4aed1 160000 --- a/source/tools +++ b/source/tools @@ -1 +1 @@ -Subproject commit e133fc08cd3254bb3d3bd1345028c8486700bca4 +Subproject commit 27826b4aed138b7e3aed882d0eab96740c3a55c7 -- 2.30.2 From de32d0cbc2a8c66ee1f8c4cc7b93d28f3a4af20e Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Thu, 16 Feb 2023 13:22:27 +0100 Subject: [PATCH 17/21] remove const which throws warnings --- source/blender/editors/animation/anim_channels_edit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 233cc02d318..79454387547 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -3643,8 +3643,8 @@ static void ANIM_OT_channel_select_keys(wmOperatorType *ot) /** \name View Channel Operator * \{ */ -static void get_normalized_fcurve_bounds(const FCurve *fcu, - const bAnimContext *ac, +static void get_normalized_fcurve_bounds(FCurve *fcu, + bAnimContext *ac, const bAnimListElem *ale, const bool include_handles, const float range[2], -- 2.30.2 From 3dd62089b183305c8dd57f8f8d582f1581a09c55 Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Thu, 16 Feb 2023 13:25:06 +0100 Subject: [PATCH 18/21] undoing the submodule bump --- release/datafiles/locale | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/datafiles/locale b/release/datafiles/locale index 8d04896a130..4331c8e76c2 160000 --- a/release/datafiles/locale +++ b/release/datafiles/locale @@ -1 +1 @@ -Subproject commit 8d04896a130c12eb440b7b9ac33bf9dc152506b5 +Subproject commit 4331c8e76c2f42b9fd903716c333d6cdeaa5cebd -- 2.30.2 From bc9529a564b2f960a4987d5acd01adbc750a55e5 Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Thu, 16 Feb 2023 13:26:08 +0100 Subject: [PATCH 19/21] undoing the submodule bump --- release/scripts/addons_contrib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib index 8f4599c4fb6..14ab9273409 160000 --- a/release/scripts/addons_contrib +++ b/release/scripts/addons_contrib @@ -1 +1 @@ -Subproject commit 8f4599c4fb6ab2386f2498814c203fd676b2ccf2 +Subproject commit 14ab9273409ea0231d08ba6e86fdc73d4e459e99 -- 2.30.2 From 84ae06342b92dbe4b10a8a98ba2ea1e171bf4292 Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Thu, 16 Feb 2023 13:27:44 +0100 Subject: [PATCH 20/21] undoing the submodule bump --- source/tools | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/tools b/source/tools index 27826b4aed1..e133fc08cd3 160000 --- a/source/tools +++ b/source/tools @@ -1 +1 @@ -Subproject commit 27826b4aed138b7e3aed882d0eab96740c3a55c7 +Subproject commit e133fc08cd3254bb3d3bd1345028c8486700bca4 -- 2.30.2 From 87ece045b1033b0d3258b7468841b78584ab3c1c Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Fri, 17 Feb 2023 17:17:24 +0100 Subject: [PATCH 21/21] fix issue when fcurve bounds height would be 0 --- source/blender/editors/animation/anim_channels_edit.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 79454387547..549c5378bce 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -3661,6 +3661,13 @@ static void get_normalized_fcurve_bounds(FCurve *fcu, range); const short mapping_flag = ANIM_get_normalization_flags(ac); + const float min_height = 0.01f; + const float height = BLI_rctf_size_y(r_bounds); + if (height < min_height) { + r_bounds->ymin -= (min_height - height) / 2; + r_bounds->ymax += (min_height - height) / 2; + } + float offset; const float unit_fac = ANIM_unit_mapping_get_factor( ac->scene, ale->id, fcu, mapping_flag, &offset); -- 2.30.2