From 6ea7cf7be2560a513d0bec9aaa755e1bf7459ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 27 Oct 2026 16:55:43 +0100 Subject: [PATCH] OSD: Round the corners of on-screen notifications Half the radius of a Choice. Covers notices, progress bars, the leaderboard tracker and RetroAchievements popups (not the listed achievements on the achievement screens). Co-Authored-By: Claude Opus 5.5 --- Common/UI/Notice.cpp | 4 ++-- Common/UI/Notice.h | 2 +- UI/OnScreenDisplay.cpp | 20 ++++++++++---------- UI/RetroAchievementScreens.cpp | 6 ++++-- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Common/UI/Notice.cpp b/Common/UI/Notice.cpp index e0b117220f..106d5d1d1a 100644 --- a/Common/UI/Notice.cpp +++ b/Common/UI/Notice.cpp @@ -92,7 +92,7 @@ void MeasureNotice(const UIContext &dc, NoticeLevel level, std::string_view text *height = std::max(heightSum, iconH + m) + padding * 2.0f; } -void RenderNotice(UIContext &dc, Bounds bounds, float height1, NoticeLevel level, std::string_view text, std::string_view details, std::string_view iconName, int align, float alpha, OSDMessageFlags flags, float timeVal, float padding, RoundCorners corners) { +void RenderNotice(UIContext &dc, Bounds bounds, float height1, NoticeLevel level, std::string_view text, std::string_view details, std::string_view iconName, int align, float alpha, OSDMessageFlags flags, float timeVal, float padding, float radius, RoundCorners corners) { UI::Drawable background = UI::Drawable(colorAlpha(GetNoticeBackgroundColor(level), alpha)); dc.SetFontStyle(dc.GetTheme().uiFont); @@ -100,7 +100,7 @@ void RenderNotice(UIContext &dc, Bounds bounds, float height1, NoticeLevel level uint32_t foreGround = whiteAlpha(alpha); if (!(flags & OSDMessageFlags::Transparent)) { - dc.FillRoundRect(background, bounds, dc.GetTheme().choiceRoundRadius, corners); + dc.FillRoundRect(background, bounds, radius, corners); } bounds = bounds.Expand(-padding); diff --git a/Common/UI/Notice.h b/Common/UI/Notice.h index fee57922de..c786d137be 100644 --- a/Common/UI/Notice.h +++ b/Common/UI/Notice.h @@ -59,4 +59,4 @@ uint32_t GetNoticeBackgroundColor(NoticeLevel type); // padding is added around the contents, inside the background. Pass the same to both. void MeasureNotice(const UIContext &dc, NoticeLevel level, std::string_view text, std::string_view details, std::string_view iconName, int align, float maxWidth, float *width, float *height, float *height1, float padding = 0.0f); // Doesn't draw a drop shadow, floating notices draw their own. -void RenderNotice(UIContext &dc, Bounds bounds, float height1, NoticeLevel level, std::string_view text, std::string_view details, std::string_view iconName, int align, float alpha, OSDMessageFlags flags, float timeVal, float padding = 0.0f, RoundCorners corners = RoundCorners::None); +void RenderNotice(UIContext &dc, Bounds bounds, float height1, NoticeLevel level, std::string_view text, std::string_view details, std::string_view iconName, int align, float alpha, OSDMessageFlags flags, float timeVal, float padding = 0.0f, float radius = 0.0f, RoundCorners corners = RoundCorners::All); diff --git a/UI/OnScreenDisplay.cpp b/UI/OnScreenDisplay.cpp index 314cb1dfda..a469e1a13c 100644 --- a/UI/OnScreenDisplay.cpp +++ b/UI/OnScreenDisplay.cpp @@ -49,13 +49,14 @@ static void RenderOSDEntry(UIContext &dc, const OnScreenDisplay::Entry &entry, B if (!(entry.flags & OSDMessageFlags::Transparent)) { dc.DrawRectDropShadow(bounds, 12.0f, 0.7f * alpha); } - RenderNotice(dc, bounds, height1, GetNoticeLevel(entry.type), entry.text, entry.text2, entry.iconName, align, alpha, entry.flags, now - entry.startTime); + RenderNotice(dc, bounds, height1, GetNoticeLevel(entry.type), entry.text, entry.text2, entry.iconName, align, alpha, entry.flags, now - entry.startTime, 0.0f, dc.GetTheme().choiceRoundRadius * 0.5f); } } static void RenderOSDProgressBar(UIContext &dc, const OnScreenDisplay::Entry &entry, Bounds bounds, int align, float alpha) { dc.DrawRectDropShadow(bounds, 12.0f, 0.7f * alpha); + const float radius = dc.GetTheme().choiceRoundRadius * 0.5f; uint32_t backgroundColor = colorAlpha(0x806050, alpha); uint32_t progressBackgroundColor = colorAlpha(0xa08070, alpha); @@ -68,20 +69,19 @@ static void RenderOSDProgressBar(UIContext &dc, const OnScreenDisplay::Entry &en float ratio = (float)(entry.progress - entry.minValue) / (float)entry.maxValue; Bounds boundLeft = bounds; - Bounds boundRight = bounds; - boundLeft.w *= ratio; - boundRight.x += ratio * boundRight.w; - boundRight.w *= (1.0f - ratio); - dc.FillRect(progressBackground, boundLeft); - dc.FillRect(background, boundRight); + // Clip the progress part, so its rounded corners match the background's at any width. + dc.FillRoundRect(background, bounds, radius); + dc.PushScissor(boundLeft); + dc.FillRoundRect(progressBackground, bounds, radius); + dc.PopScissor(); } else { // Indeterminate spinner float alpha = cos(time_now_d() * 5.0) * 0.5f + 0.5f; uint32_t pulse = colorBlend(backgroundColor, progressBackgroundColor, alpha); UI::Drawable background = UI::Drawable(pulse); - dc.FillRect(background, bounds); + dc.FillRoundRect(background, bounds, radius); } dc.SetFontStyle(dc.GetTheme().uiFont); @@ -101,7 +101,7 @@ static void RenderLeaderboardTracker(UIContext &dc, const Bounds &bounds, const uint32_t backgroundColor = colorAlpha(0x806050, alpha); UI::Drawable background = UI::Drawable(backgroundColor); dc.DrawRectDropShadow(bounds, 12.0f, 0.7f * alpha); - dc.FillRect(background, bounds); + dc.FillRoundRect(background, bounds, dc.GetTheme().choiceRoundRadius * 0.5f); dc.SetFontStyle(dc.GetTheme().uiFont); dc.SetFontScale(1.0f, 1.0f); dc.DrawTextShadowRect(text, bounds.Inset(5.0f, 5.0f), colorAlpha(0xFFFFFFFF, alpha), ALIGN_VCENTER | ALIGN_HCENTER); @@ -454,6 +454,6 @@ void NoticeView::GetContentDimensionsBySpec(const UIContext &dc, UI::MeasureSpec void NoticeView::Draw(UIContext &dc) { dc.PushScissor(bounds_); const int align = wrapText_ ? FLAG_WRAP_TEXT : 0; - RenderNotice(dc, bounds_, height1_, level_, text_, detailsText_, iconName_, align, 1.0f, OSDMessageFlags::None, 0.0f, NoticeViewPadding(dc), roundCorners_); + RenderNotice(dc, bounds_, height1_, level_, text_, detailsText_, iconName_, align, 1.0f, OSDMessageFlags::None, 0.0f, NoticeViewPadding(dc), dc.GetTheme().choiceRoundRadius, roundCorners_); dc.PopScissor(); } diff --git a/UI/RetroAchievementScreens.cpp b/UI/RetroAchievementScreens.cpp index 9d66e9e849..f63e345edf 100644 --- a/UI/RetroAchievementScreens.cpp +++ b/UI/RetroAchievementScreens.cpp @@ -596,11 +596,13 @@ void RenderAchievement(UIContext &dc, const rc_client_achievement_t *achievement dc.Begin(); if (style != AchievementRenderStyle::LISTED) { + // On-screen notification. dc.DrawRectDropShadow(bounds, 12.0f, 0.7f * alpha); + dc.FillRoundRect(background, bounds, dc.GetTheme().choiceRoundRadius * 0.5f); + } else { + dc.FillRect(background, bounds); } - dc.FillRect(background, bounds); - dc.Flush(); dc.Begin();