diff --git a/Common/System/OSD.h b/Common/System/OSD.h index 20819da5d4..53253c9fec 100644 --- a/Common/System/OSD.h +++ b/Common/System/OSD.h @@ -53,6 +53,10 @@ 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_; } + struct Entry { OSDType type; std::string text; @@ -84,6 +88,8 @@ private: std::vector sideEntries_; std::vector bars_; std::mutex mutex_; + + bool showSidebar_ = true; }; extern OnScreenDisplay g_OSD; diff --git a/Core/RetroAchievements.cpp b/Core/RetroAchievements.cpp index 0d3a8aeed3..e6142fa931 100644 --- a/Core/RetroAchievements.cpp +++ b/Core/RetroAchievements.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +83,7 @@ const std::string g_iconCachePrefix = "badge:"; Path s_game_path; std::string s_game_hash; +std::set g_activeChallenges; bool g_isIdentifying = false; // rc_client implementation @@ -285,12 +287,14 @@ static void event_handler_callback(const rc_client_event_t *event, rc_client_t * case RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW: NOTICE_LOG(ACHIEVEMENTS, "Challenge indicator show: %s", event->achievement->title); g_OSD.ShowChallengeIndicator(event->achievement->id, true); + g_activeChallenges.insert(event->achievement->id); // A challenge achievement has become active. The handler should show a small version of the achievement icon // to indicate the challenge is active. break; case RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE: NOTICE_LOG(ACHIEVEMENTS, "Challenge indicator hide: %s", event->achievement->title); g_OSD.ShowChallengeIndicator(event->achievement->id, false); + g_activeChallenges.erase(event->achievement->id); // The handler should hide the small version of the achievement icon that was shown by the corresponding RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW event. break; case RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_SHOW: @@ -395,6 +399,7 @@ void Logout() { g_Config.sAchievementsUserName.clear(); NativeSaveSecret(RA_TOKEN_SECRET_NAME, ""); g_Config.Save("Achievements logout"); + g_activeChallenges.clear(); } void UpdateSettings() { @@ -411,6 +416,7 @@ void UpdateSettings() { } bool Shutdown() { + g_activeChallenges.clear(); rc_client_destroy(g_rcClient); g_rcClient = nullptr; return true; @@ -419,6 +425,7 @@ bool Shutdown() { void ResetRuntime() { INFO_LOG(ACHIEVEMENTS, "Resetting rcheevos state..."); rc_client_reset(g_rcClient); + g_activeChallenges.clear(); } void FrameUpdate() { @@ -635,4 +642,8 @@ void ChangeUMD(const Path &path) { g_isIdentifying = true; } +std::set GetActiveChallengeIDs() { + return g_activeChallenges; +} + } // namespace Achievements diff --git a/Core/RetroAchievements.h b/Core/RetroAchievements.h index 10e219dfe7..b92e296048 100644 --- a/Core/RetroAchievements.h +++ b/Core/RetroAchievements.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "Common/StringUtils.h" @@ -105,4 +106,6 @@ Statistics GetStatistics(); std::string GetGameAchievementSummary(); +std::set GetActiveChallengeIDs(); + } // namespace Achievements diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index efb114cda5..faac87a4ac 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -197,6 +197,7 @@ 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) { diff --git a/UI/OnScreenDisplay.cpp b/UI/OnScreenDisplay.cpp index 2d6f3bac65..2c1a0b30ee 100644 --- a/UI/OnScreenDisplay.cpp +++ b/UI/OnScreenDisplay.cpp @@ -226,61 +226,63 @@ void OnScreenMessagesView::Draw(UIContext &dc) { const float fadeoutCoef = 1.0f / OnScreenDisplay::FadeoutTime(); - // 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(); - for (auto &entry : sideEntries) { - float tw, th; + if (g_OSD.ShowSidebar()) { + // 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(); + for (auto &entry : sideEntries) { + float tw, th; - const rc_client_achievement_t *achievement = nullptr; - AchievementRenderStyle style; + const rc_client_achievement_t *achievement = nullptr; + AchievementRenderStyle style; - switch (entry.type) { - case OSDType::ACHIEVEMENT_PROGRESS: - { - achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID); - if (!achievement) + switch (entry.type) { + case OSDType::ACHIEVEMENT_PROGRESS: + { + achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID); + if (!achievement) + continue; + style = AchievementRenderStyle::PROGRESS_INDICATOR; + MeasureAchievement(dc, achievement, style, &tw, &th); + break; + } + case OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR: + { + achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID); + if (!achievement) + continue; + style = AchievementRenderStyle::CHALLENGE_INDICATOR; + MeasureAchievement(dc, achievement, style, &tw, &th); + break; + } + case OSDType::LEADERBOARD_TRACKER: + { + MeasureLeaderboardTracker(dc, entry.text, &tw, &th); + break; + } + default: continue; - style = AchievementRenderStyle::PROGRESS_INDICATOR; - MeasureAchievement(dc, achievement, style, &tw, &th); - break; - } - case OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR: - { - achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID); - if (!achievement) + } + Bounds b(10.0f, y, tw, th); + float alpha = Clamp((float)(entry.endTime - now) * fadeoutCoef, 0.0f, 1.0f); + // OK, render the thing. + + switch (entry.type) { + case OSDType::ACHIEVEMENT_PROGRESS: + case OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR: + { + RenderAchievement(dc, achievement, style, b, alpha, entry.startTime, now); + break; + } + case OSDType::LEADERBOARD_TRACKER: + RenderLeaderboardTracker(dc, b, entry.text, alpha); + break; + default: continue; - style = AchievementRenderStyle::CHALLENGE_INDICATOR; - MeasureAchievement(dc, achievement, style, &tw, &th); - break; - } - case OSDType::LEADERBOARD_TRACKER: - { - MeasureLeaderboardTracker(dc, entry.text, &tw, &th); - break; - } - default: - continue; - } - Bounds b(10.0f, y, tw, th); - float alpha = Clamp((float)(entry.endTime - now) * fadeoutCoef, 0.0f, 1.0f); - // OK, render the thing. + } - switch (entry.type) { - case OSDType::ACHIEVEMENT_PROGRESS: - case OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR: - { - RenderAchievement(dc, achievement, style, b, alpha, entry.startTime, now); - break; + y += (b.h + 4.0f) * alpha; // including alpha here gets us smooth animations. } - case OSDType::LEADERBOARD_TRACKER: - RenderLeaderboardTracker(dc, b, entry.text, alpha); - break; - default: - continue; - } - - y += (b.h + 4.0f) * alpha; // including alpha here gets us smooth animations. } // Get height diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index f92242b133..cdef636c32 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -261,8 +261,14 @@ void GamePauseScreen::update() { SetVRAppMode(VRAppMode::VR_MENU_MODE); } +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) { @@ -326,6 +332,18 @@ void GamePauseScreen::CreateViews() { if (!Achievements::ChallengeModeActive()) { CreateSavestateControls(leftColumnItems, vertical); + } else { + // Let's show the active challenges. + std::set ids = Achievements::GetActiveChallengeIDs(); + if (!ids.empty()) { + leftColumnItems->Add(new ItemHeader(ac->T("Active Challenges"))); + for (auto id : ids) { + const rc_client_achievement_t *achievement = rc_client_get_achievement_info(Achievements::GetClient(), id); + if (!achievement) + continue; + leftColumnItems->Add(new AchievementView(achievement)); + } + } } ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(vertical ? 200 : 300, FILL_PARENT, actionMenuMargins)); diff --git a/UI/PauseScreen.h b/UI/PauseScreen.h index 830e7d0581..b81d80a559 100644 --- a/UI/PauseScreen.h +++ b/UI/PauseScreen.h @@ -32,7 +32,7 @@ enum class PauseScreenMode { class GamePauseScreen : public UIDialogScreenWithGameBackground { public: - GamePauseScreen(const Path &filename) : UIDialogScreenWithGameBackground(filename), gamePath_(filename) {} + GamePauseScreen(const Path &filename); ~GamePauseScreen(); void dialogFinished(const Screen *dialog, DialogResult dr) override; @@ -65,6 +65,5 @@ private: // hack bool finishNextFrame_ = false; - Path gamePath_; PauseScreenMode mode_ = PauseScreenMode::MAIN; }; diff --git a/UI/RetroAchievementScreens.cpp b/UI/RetroAchievementScreens.cpp index dea09feac4..9474e19086 100644 --- a/UI/RetroAchievementScreens.cpp +++ b/UI/RetroAchievementScreens.cpp @@ -595,4 +595,3 @@ void LeaderboardEntryView::Draw(UIContext &dc) { void LeaderboardEntryView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { MeasureLeaderboardEntry(dc, entry_, &w, &h); } -