From 6ac9b974eac6800ce3e300ce2d19fcf1448aed98 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Thu, 31 Jul 2025 21:36:07 +0200 Subject: [PATCH] Fix #98089: Improved Alignment of Playhead and Keyframes This PR improves alignment between playhead and keyframe indicators, especially noticeable at small UI scale sizes where we are currently always out by one pixel. This is because keyframe icons are all odd widths while the playhead line is an even width. This PR mostly makes that line an odd width, with other small adjustments. Pull Request: https://projects.blender.org/blender/blender/pulls/142904 --- .../editors/animation/time_scrub_ui.cc | 29 ++++++++++--------- .../editors/interface/interface_icons.cc | 4 +-- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/source/blender/editors/animation/time_scrub_ui.cc b/source/blender/editors/animation/time_scrub_ui.cc index 48b1aebeee5..609db656bc0 100644 --- a/source/blender/editors/animation/time_scrub_ui.cc +++ b/source/blender/editors/animation/time_scrub_ui.cc @@ -90,7 +90,6 @@ static void draw_current_frame(const Scene *scene, float text_width = UI_fontstyle_string_width(fstyle, frame_str); float box_width = std::max(text_width + 8 * UI_SCALE_FAC, 24 * UI_SCALE_FAC); float box_padding = 3 * UI_SCALE_FAC; - const int line_outline = max_ii(1, round_fl_to_int(1 * UI_SCALE_FAC)); float bg_color[4]; UI_GetThemeColorShade4fv(TH_CFRAME, -5, bg_color); @@ -103,20 +102,24 @@ static void draw_current_frame(const Scene *scene, GPU_blend(GPU_BLEND_ALPHA); immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + /* There are two usages of "1.0f" below that are not scaled. This is + * used to force an odd width (but still pixel-aligned) to better + * line up with the odd widths of the keyframe icons. #98089. */ + /* Outline. */ immUniformThemeColorShadeAlpha(TH_BACK, -25, -100); immRectf(pos, - subframe_x - (line_outline + U.pixelsize), - scrub_region_rect->ymax - box_padding, - subframe_x + (line_outline + U.pixelsize), + floor(subframe_x - U.pixelsize - U.pixelsize), + scrub_region_rect->ymax - box_padding - U.pixelsize, + floor(subframe_x + U.pixelsize + 1.0f + U.pixelsize), 0.0f); /* Line. */ immUniformThemeColor(TH_CFRAME); immRectf(pos, - subframe_x - U.pixelsize, - scrub_region_rect->ymax - box_padding, - subframe_x + U.pixelsize, + floor(subframe_x - U.pixelsize), + scrub_region_rect->ymax - box_padding - U.pixelsize, + floor(subframe_x + U.pixelsize + 1.0f), 0.0f); immUnbindProgram(); GPU_blend(GPU_BLEND_NONE); @@ -128,20 +131,20 @@ static void draw_current_frame(const Scene *scene, UI_GetThemeColorShade4fv(TH_CFRAME, 5, outline_color); rctf rect{}; - rect.xmin = frame_x - box_width / 2 + U.pixelsize / 2; - rect.xmax = frame_x + box_width / 2 + U.pixelsize / 2; - rect.ymin = scrub_region_rect->ymin + box_padding; - rect.ymax = scrub_region_rect->ymax - box_padding; + rect.xmin = floor(frame_x - (box_width / 2.0f) + U.pixelsize + 1.0f); + rect.xmax = ceil(frame_x + (box_width / 2.0f)); + rect.ymin = floor(scrub_region_rect->ymin + box_padding); + rect.ymax = ceil(scrub_region_rect->ymax - box_padding); UI_draw_roundbox_4fv_ex( &rect, bg_color, nullptr, 1.0f, outline_color, U.pixelsize, 4 * UI_SCALE_FAC); uchar text_color[4]; UI_GetThemeColor4ubv(TH_HEADER_TEXT_HI, text_color); - const int y = BLI_rcti_cent_y(scrub_region_rect) - int(fstyle->points * UI_SCALE_FAC * 0.35f); + const int y = BLI_rcti_cent_y(scrub_region_rect) - int(fstyle->points * UI_SCALE_FAC * 0.38f); UI_fontstyle_draw_simple( - +fstyle, frame_x - text_width / 2 + U.pixelsize / 2, y, frame_str, text_color); + fstyle, ceil(frame_x - (text_width / 2.0f) + 1.0f), y, frame_str, text_color); } void ED_time_scrub_draw_current_frame(const ARegion *region, diff --git a/source/blender/editors/interface/interface_icons.cc b/source/blender/editors/interface/interface_icons.cc index d7f0cb14789..c1f2c2834ce 100644 --- a/source/blender/editors/interface/interface_icons.cc +++ b/source/blender/editors/interface/interface_icons.cc @@ -270,8 +270,8 @@ static void vicon_keytype_draw_wrapper(const float x, /* The "x" and "y" given are the bottom-left coordinates of the icon, * while the #draw_keyframe_shape() function needs the midpoint for the keyframe. */ - const float xco = x + (w / 2.0f) + 0.5f; - const float yco = y + (h / 2.0f) + 0.5f; + const float xco = x + (w / 2.0f); + const float yco = y + (h / 2.0f); GPUVertFormat *format = immVertexFormat(); KeyframeShaderBindings sh_bindings;