From 3d5a1f7d335105862a9d86d12806bebdb33db12e Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Thu, 13 Jun 2024 00:03:46 -0400 Subject: [PATCH] Refactored Challenge Icons to handle icon updates If an icon is displayed on screen before it downloads, it was displaying a default icon but it would fail to load the actual icon even after it was downloaded. This fixes that. --- Source/Core/Core/AchievementManager.cpp | 29 +++++++++++--- Source/Core/Core/AchievementManager.h | 9 +++-- Source/Core/VideoCommon/OnScreenUI.cpp | 51 ++++++++++++------------- Source/Core/VideoCommon/OnScreenUI.h | 2 +- 4 files changed, 55 insertions(+), 36 deletions(-) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index 6904b3e7a9..ae95cc370e 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -338,7 +338,18 @@ AchievementManager::RichPresence AchievementManager::GetRichPresence() const return m_rich_presence; } -const AchievementManager::NamedBadgeMap& AchievementManager::GetChallengeIcons() const +const bool AchievementManager::AreChallengesUpdated() const +{ + return m_challenges_updated; +} + +void AchievementManager::ResetChallengesUpdated() +{ + m_challenges_updated = false; +} + +const std::unordered_set& +AchievementManager::GetActiveChallenges() const { return m_active_challenges; } @@ -796,15 +807,18 @@ void AchievementManager::HandleAchievementChallengeIndicatorShowEvent( const rc_client_event_t* client_event) { auto& instance = AchievementManager::GetInstance(); - instance.m_active_challenges[client_event->achievement->badge_name] = - &AchievementManager::GetInstance().GetAchievementBadge(client_event->achievement->id, false); + const auto [iter, inserted] = instance.m_active_challenges.insert(client_event->achievement->id); + if (inserted) + instance.m_challenges_updated = true; } void AchievementManager::HandleAchievementChallengeIndicatorHideEvent( const rc_client_event_t* client_event) { - AchievementManager::GetInstance().m_active_challenges.erase( - client_event->achievement->badge_name); + auto& instance = AchievementManager::GetInstance(); + const auto removed = instance.m_active_challenges.erase(client_event->achievement->id); + if (removed > 0) + instance.m_challenges_updated = true; } void AchievementManager::HandleAchievementProgressIndicatorShowEvent( @@ -968,6 +982,11 @@ void AchievementManager::FetchBadge(AchievementManager::Badge* badge, u32 badge_ } m_update_callback(callback_data); + if (badge_type == RC_IMAGE_TYPE_ACHIEVEMENT && + m_active_challenges.contains(*callback_data.achievements.begin())) + { + m_challenges_updated = true; + } }); } diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index f538832ade..94fa2a6025 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -50,7 +51,6 @@ public: static constexpr size_t RP_SIZE = 256; using RichPresence = std::array; using Badge = VideoCommon::CustomTextureData::ArraySlice::Level; - using NamedBadgeMap = std::unordered_map; static constexpr size_t MAX_DISPLAYED_LBOARDS = 4; static constexpr std::string_view DEFAULT_PLAYER_BADGE_FILENAME = "achievements_player.png"; @@ -116,7 +116,9 @@ public: const Badge& GetAchievementBadge(AchievementId id, bool locked) const; const LeaderboardStatus* GetLeaderboardInfo(AchievementId leaderboard_id); RichPresence GetRichPresence() const; - const NamedBadgeMap& GetChallengeIcons() const; + const bool AreChallengesUpdated() const; + void ResetChallengesUpdated(); + const std::unordered_set& GetActiveChallenges() const; std::vector GetActiveLeaderboards() const; void DoState(PointerWrap& p); @@ -203,7 +205,8 @@ private: std::chrono::steady_clock::time_point m_last_rp_time = std::chrono::steady_clock::now(); std::unordered_map m_leaderboard_map; - NamedBadgeMap m_active_challenges; + bool m_challenges_updated = false; + std::unordered_set m_active_challenges; std::vector m_active_leaderboards; Common::WorkQueueThread> m_queue; diff --git a/Source/Core/VideoCommon/OnScreenUI.cpp b/Source/Core/VideoCommon/OnScreenUI.cpp index 1d5a432d8a..d3a3c7397d 100644 --- a/Source/Core/VideoCommon/OnScreenUI.cpp +++ b/Source/Core/VideoCommon/OnScreenUI.cpp @@ -334,11 +334,28 @@ void OnScreenUI::DrawDebugText() void OnScreenUI::DrawChallengesAndLeaderboards() { #ifdef USE_RETRO_ACHIEVEMENTS - std::lock_guard lg{AchievementManager::GetInstance().GetLock()}; - const auto& challenge_icons = AchievementManager::GetInstance().GetChallengeIcons(); - const auto& leaderboard_progress = AchievementManager::GetInstance().GetActiveLeaderboards(); + auto& instance = AchievementManager::GetInstance(); + std::lock_guard lg{instance.GetLock()}; + if (instance.AreChallengesUpdated()) + { + instance.ResetChallengesUpdated(); + const auto& challenges = instance.GetActiveChallenges(); + m_challenge_texture_map.clear(); + for (const auto& name : challenges) + { + const auto& icon = instance.GetAchievementBadge(name, false); + const u32 width = icon.width; + const u32 height = icon.height; + TextureConfig tex_config(width, height, 1, 1, 1, AbstractTextureFormat::RGBA8, 0, + AbstractTextureType::Texture_2DArray); + auto res = m_challenge_texture_map.insert_or_assign(name, g_gfx->CreateTexture(tex_config)); + res.first->second->Load(0, width, height, width, icon.data.data(), + sizeof(u32) * width * height); + } + } + float leaderboard_y = ImGui::GetIO().DisplaySize.y; - if (!challenge_icons.empty()) + if (!m_challenge_texture_map.empty()) { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y), 0, ImVec2(1.0, 1.0)); @@ -349,37 +366,17 @@ void OnScreenUI::DrawChallengesAndLeaderboards() ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing)) { - for (const auto& [name, icon] : challenge_icons) - { - if (m_challenge_texture_map.find(name) != m_challenge_texture_map.end()) - continue; - const u32 width = icon->width; - const u32 height = icon->height; - TextureConfig tex_config(width, height, 1, 1, 1, AbstractTextureFormat::RGBA8, 0, - AbstractTextureType::Texture_2DArray); - auto res = m_challenge_texture_map.insert_or_assign(name, g_gfx->CreateTexture(tex_config)); - res.first->second->Load(0, width, height, width, icon->data.data(), - sizeof(u32) * width * height); - } for (auto& [name, texture] : m_challenge_texture_map) { - auto icon_itr = challenge_icons.find(name); - if (icon_itr == challenge_icons.end()) - { - m_challenge_texture_map.erase(name); - continue; - } - if (texture) - { - ImGui::Image(texture.get(), ImVec2(static_cast(icon_itr->second->width), - static_cast(icon_itr->second->height))); - } + ImGui::Image(texture.get(), ImVec2(static_cast(texture->GetWidth()), + static_cast(texture->GetHeight()))); } leaderboard_y -= ImGui::GetWindowHeight(); } ImGui::End(); } + const auto& leaderboard_progress = instance.GetActiveLeaderboards(); if (!leaderboard_progress.empty()) { ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x, leaderboard_y), 0, diff --git a/Source/Core/VideoCommon/OnScreenUI.h b/Source/Core/VideoCommon/OnScreenUI.h index 76fdcee19a..28749807be 100644 --- a/Source/Core/VideoCommon/OnScreenUI.h +++ b/Source/Core/VideoCommon/OnScreenUI.h @@ -76,7 +76,7 @@ private: float m_backbuffer_scale = 1.0; #ifdef USE_RETRO_ACHIEVEMENTS - std::map, std::less<>> m_challenge_texture_map; + std::map, std::less<>> m_challenge_texture_map; #endif // USE_RETRO_ACHIEVEMENTS bool m_ready = false;