diff --git a/Common/UI/Notice.cpp b/Common/UI/Notice.cpp index a5ee6c88eb..e0b117220f 100644 --- a/Common/UI/Notice.cpp +++ b/Common/UI/Notice.cpp @@ -47,7 +47,7 @@ NoticeLevel GetNoticeLevel(OSDType type) { constexpr float m = 4.0f; // Align only matters here for the ASCII-only flag. -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) { +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) { float iconW = 0.0f; float iconH = 0.0f; if (!iconName.empty() && !startsWith(iconName, "I_")) { // Check for atlas image. Bit hacky, but we choose prefixes for icon IDs anyway in a way that this is safe. @@ -64,7 +64,7 @@ void MeasureNotice(const UIContext &dc, NoticeLevel level, std::string_view text } } - float chromeWidth = iconW + m * 2.0f + 12.0f; + float chromeWidth = iconW + m * 2.0f + 12.0f + padding * 2.0f; float availableWidth = maxWidth - chromeWidth; // OK, now that we have figured out how much space we have for the text, we can measure it (with wrapping if needed). @@ -89,10 +89,10 @@ void MeasureNotice(const UIContext &dc, NoticeLevel level, std::string_view text } float heightSum = *height1 + (height2 > 0.0f ? height2 + 8.0f : 0.0f); - *height = std::max(heightSum, iconH + m); + *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) { +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) { UI::Drawable background = UI::Drawable(colorAlpha(GetNoticeBackgroundColor(level), alpha)); dc.SetFontStyle(dc.GetTheme().uiFont); @@ -100,9 +100,9 @@ void RenderNotice(UIContext &dc, Bounds bounds, float height1, NoticeLevel level uint32_t foreGround = whiteAlpha(alpha); if (!(flags & OSDMessageFlags::Transparent)) { - dc.DrawRectDropShadow(bounds, 12.0f, 0.7f * alpha); - dc.FillRect(background, bounds); + dc.FillRoundRect(background, bounds, dc.GetTheme().choiceRoundRadius, corners); } + bounds = bounds.Expand(-padding); float iconW = 0.0f; float iconH = 0.0f; diff --git a/Common/UI/Notice.h b/Common/UI/Notice.h index 5962e77502..fee57922de 100644 --- a/Common/UI/Notice.h +++ b/Common/UI/Notice.h @@ -4,6 +4,7 @@ #include #include +#include "Common/Render/DrawEnum.h" #include "Common/UI/View.h" #include "Common/System/OSD.h" @@ -18,8 +19,7 @@ enum class NoticeLevel { class NoticeView : public UI::InertView { public: - NoticeView(NoticeLevel level, std::string_view text, std::string_view detailsText, UI::LayoutParams *layoutParams = 0) - : InertView(layoutParams), level_(level), text_(text), detailsText_(detailsText) {} + NoticeView(NoticeLevel level, std::string_view text, std::string_view detailsText, UI::LayoutParams *layoutParams = nullptr); void SetIconName(std::string_view name) { iconName_ = name; @@ -56,5 +56,7 @@ private: ImageID GetOSDIcon(NoticeLevel level); NoticeLevel GetNoticeLevel(OSDType type); uint32_t GetNoticeBackgroundColor(NoticeLevel type); -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); -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); +// 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); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 40f037a2dd..7f3a66736a 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -141,6 +141,7 @@ #include "UI/DevScreens.h" #include "UI/DiscordIntegration.h" #include "UI/EmuScreen.h" +#include "UI/FirmwareScreen.h" #include "UI/GameInfoCache.h" #include "UI/GameSettingsScreen.h" #include "UI/GPUDriverTestScreen.h" @@ -900,6 +901,9 @@ void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineO GameSettingsScreen *settings = new GameSettingsScreen(Path()); settings->OpenDeveloperTools(); g_screenManager->push(settings); + } else if (equals(cmdLineOptions.startScreen.value(), "firmware")) { + g_screenManager->switchScreen(new MainScreen()); + g_screenManager->push(new FirmwareScreen(Path())); } else { WARN_LOG(Log::System, "Unknown start screen '%s'", cmdLineOptions.startScreen.value().c_str()); g_screenManager->switchScreen(new LogoScreen(AfterLogoScreen::DEFAULT)); diff --git a/UI/OnScreenDisplay.cpp b/UI/OnScreenDisplay.cpp index c0af73f7a8..314cb1dfda 100644 --- a/UI/OnScreenDisplay.cpp +++ b/UI/OnScreenDisplay.cpp @@ -46,6 +46,9 @@ static void RenderOSDEntry(UIContext &dc, const OnScreenDisplay::Entry &entry, B } return; } else { + 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); } } @@ -424,6 +427,19 @@ ViewLayoutMode OSDOverlayScreen::LayoutMode() const { return ViewLayoutMode::ApplyInsets; } +// Inside the background, enough to keep the contents clear of the rounded corners. +static float NoticeViewPadding(const UIContext &dc) { + return dc.GetTheme().choiceRoundRadius * 0.5f; +} + +NoticeView::NoticeView(NoticeLevel level, std::string_view text, std::string_view detailsText, UI::LayoutParams *layoutParams) + : InertView(layoutParams), level_(level), text_(text), detailsText_(detailsText) { + if (!layoutParams) { + layoutParams_->width = UI::FILL_PARENT; + layoutParams_->height = UI::WRAP_CONTENT; + } +} + void NoticeView::GetContentDimensionsBySpec(const UIContext &dc, UI::MeasureSpec horiz, UI::MeasureSpec vert, float &w, float &h) const { float layoutWidth = layoutParams_->width; if (layoutWidth < 0) { @@ -432,12 +448,12 @@ void NoticeView::GetContentDimensionsBySpec(const UIContext &dc, UI::MeasureSpec } ApplyBoundBySpec(layoutWidth, horiz); const int align = wrapText_ ? FLAG_WRAP_TEXT : 0; - MeasureNotice(dc, level_, text_, detailsText_, iconName_, align, layoutWidth, &w, &h, &height1_); + MeasureNotice(dc, level_, text_, detailsText_, iconName_, align, layoutWidth, &w, &h, &height1_, NoticeViewPadding(dc)); } 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); + RenderNotice(dc, bounds_, height1_, level_, text_, detailsText_, iconName_, align, 1.0f, OSDMessageFlags::None, 0.0f, NoticeViewPadding(dc), roundCorners_); dc.PopScissor(); }