diff --git a/Common/Math/math_util.h b/Common/Math/math_util.h index b76e1f3937..a821be5fe4 100644 --- a/Common/Math/math_util.h +++ b/Common/Math/math_util.h @@ -67,6 +67,13 @@ inline T clamp_value(T val, T floor, T cap) { return val; } +// Very common operation, familiar from shaders. +inline float saturatef(float x) { + if (x > 1.0f) return 1.0f; + else if (x < 0.0f) return 0.0f; + else return x; +} + #define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define ROUND_DOWN(x, a) ((x) & ~((a) - 1)) diff --git a/Common/System/OSD.cpp b/Common/System/OSD.cpp index c58c801f7c..efa729d83c 100644 --- a/Common/System/OSD.cpp +++ b/Common/System/OSD.cpp @@ -3,6 +3,7 @@ #include "Common/System/OSD.h" #include "Common/TimeUtil.h" #include "Common/Log.h" +#include "Common/Math/math_util.h" OnScreenDisplay g_OSD; @@ -50,6 +51,17 @@ std::vector OnScreenDisplay::ProgressBars() { return bars_; // makes a copy. } +void OnScreenDisplay::NudgeSidebar() { + sideBarShowTime_ = time_now_d(); +} + +float OnScreenDisplay::SidebarAlpha() const { + double timeSinceNudge = time_now_d() - sideBarShowTime_; + + // Fade out in 1/4 second, 0.1s after the last nudge. + return saturatef(1.0f - ((float)timeSinceNudge - 0.1f) * 4.0f); +} + void OnScreenDisplay::Show(OSDType type, const std::string &text, const std::string &text2, const std::string &icon, float duration_s, const char *id) { // Automatic duration based on type. if (duration_s <= 0.0f) { diff --git a/Common/System/OSD.h b/Common/System/OSD.h index 7cba61df46..928e1d44d6 100644 --- a/Common/System/OSD.h +++ b/Common/System/OSD.h @@ -53,9 +53,9 @@ public: void SetProgressBar(std::string id, std::string &&message, int minValue, int maxValue, int progress); void RemoveProgressBar(std::string id); - // Show stuff on the side or now, like the challenge indicators etc. - void SetShowSidebar(bool show) { showSidebar_ = show; } - bool ShowSidebar() const { return showSidebar_; } + // Call every frame to keep the sidebar visible. Otherwise it'll fade out. + void NudgeSidebar(); + float SidebarAlpha() const; // Fades out everything related to achievements. Should be used on game shutdown. void ClearAchievementStuff(); @@ -92,7 +92,7 @@ private: std::vector bars_; std::mutex mutex_; - bool showSidebar_ = true; + double sideBarShowTime_ = 0.0; }; extern OnScreenDisplay g_OSD; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index e01fa44f55..64b78d541a 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -197,7 +197,6 @@ EmuScreen::EmuScreen(const Path &filename) // Usually, we don't want focus movement enabled on this screen, so disable on start. // Only if you open chat or dev tools do we want it to start working. UI::EnableFocusMovement(false); - g_OSD.SetShowSidebar(true); } bool EmuScreen::bootAllowStorage(const Path &filename) { @@ -1480,6 +1479,8 @@ void EmuScreen::render() { if (!thin3d) return; // shouldn't really happen but I've seen a suspicious stack trace.. + g_OSD.NudgeSidebar(); + if (invalid_) { // Loading, or after shutdown? if (loadingTextView_->GetVisibility() == UI::V_VISIBLE) diff --git a/UI/OnScreenDisplay.cpp b/UI/OnScreenDisplay.cpp index 1ac129ffac..ea371814e0 100644 --- a/UI/OnScreenDisplay.cpp +++ b/UI/OnScreenDisplay.cpp @@ -230,7 +230,9 @@ void OnScreenMessagesView::Draw(UIContext &dc) { const float fadeoutCoef = 1.0f / OnScreenDisplay::FadeoutTime(); - if (g_OSD.ShowSidebar()) { + float sidebarAlpha = g_OSD.SidebarAlpha(); + + if (sidebarAlpha > 0.0f) { // Draw side entries. Top entries should apply on top of them if there's a collision, so drawing // these first makes sense. const std::vector sideEntries = g_OSD.SideEntries(); @@ -268,6 +270,7 @@ void OnScreenMessagesView::Draw(UIContext &dc) { continue; } Bounds b(10.0f, y, tw, th); + // We don't multiply in sidebarAlpha here because it shouldn't drive the below animation. float alpha = Clamp((float)(entry.endTime - now) * fadeoutCoef, 0.0f, 1.0f); // OK, render the thing. @@ -275,11 +278,11 @@ void OnScreenMessagesView::Draw(UIContext &dc) { case OSDType::ACHIEVEMENT_PROGRESS: case OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR: { - RenderAchievement(dc, achievement, style, b, alpha, entry.startTime, now); + RenderAchievement(dc, achievement, style, b, alpha * sidebarAlpha, entry.startTime, now); break; } case OSDType::LEADERBOARD_TRACKER: - RenderLeaderboardTracker(dc, b, entry.text, alpha); + RenderLeaderboardTracker(dc, b, entry.text, alpha * sidebarAlpha); break; default: continue; diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index cdef636c32..9414463aa4 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -263,12 +263,10 @@ void GamePauseScreen::update() { GamePauseScreen::GamePauseScreen(const Path &filename) : UIDialogScreenWithGameBackground(filename) { - g_OSD.SetShowSidebar(false); } GamePauseScreen::~GamePauseScreen() { __DisplaySetWasPaused(); - g_OSD.SetShowSidebar(true); } void GamePauseScreen::CreateSavestateControls(UI::LinearLayout *leftColumnItems, bool vertical) {