Refactor AchievementsWindow::UpdateData to take a partial update parameter
UpdateData in AchievementsWindow now only updates the components being requested, massively improving the window's performance. The parameter is UpdatedItems in AchievementManager, which tracks which portions of the system have been updated for every update callback.
This commit is contained in:
parent
fa2210f80d
commit
4214c301ef
|
@ -61,9 +61,9 @@ void AchievementManager::SetUpdateCallback(UpdateCallback callback)
|
||||||
m_update_callback = std::move(callback);
|
m_update_callback = std::move(callback);
|
||||||
|
|
||||||
if (!m_update_callback)
|
if (!m_update_callback)
|
||||||
m_update_callback = [] {};
|
m_update_callback = [](UpdatedItems) {};
|
||||||
|
|
||||||
m_update_callback();
|
m_update_callback(UpdatedItems{.all = true});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementManager::Login(const std::string& password)
|
void AchievementManager::Login(const std::string& password)
|
||||||
|
@ -147,22 +147,26 @@ bool AchievementManager::IsGameLoaded() const
|
||||||
|
|
||||||
void AchievementManager::FetchPlayerBadge()
|
void AchievementManager::FetchPlayerBadge()
|
||||||
{
|
{
|
||||||
FetchBadge(&m_player_badge, RC_IMAGE_TYPE_USER, [](const AchievementManager& manager) {
|
FetchBadge(&m_player_badge, RC_IMAGE_TYPE_USER,
|
||||||
|
[](const AchievementManager& manager) {
|
||||||
auto* user_info = rc_client_get_user_info(manager.m_client);
|
auto* user_info = rc_client_get_user_info(manager.m_client);
|
||||||
if (!user_info)
|
if (!user_info)
|
||||||
return std::string("");
|
return std::string("");
|
||||||
return std::string(user_info->display_name);
|
return std::string(user_info->display_name);
|
||||||
});
|
},
|
||||||
|
{.player_icon = true});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementManager::FetchGameBadges()
|
void AchievementManager::FetchGameBadges()
|
||||||
{
|
{
|
||||||
FetchBadge(&m_game_badge, RC_IMAGE_TYPE_GAME, [](const AchievementManager& manager) {
|
FetchBadge(&m_game_badge, RC_IMAGE_TYPE_GAME,
|
||||||
|
[](const AchievementManager& manager) {
|
||||||
auto* game_info = rc_client_get_game_info(manager.m_client);
|
auto* game_info = rc_client_get_game_info(manager.m_client);
|
||||||
if (!game_info)
|
if (!game_info)
|
||||||
return std::string("");
|
return std::string("");
|
||||||
return std::string(game_info->badge_name);
|
return std::string(game_info->badge_name);
|
||||||
});
|
},
|
||||||
|
{.game_icon = true});
|
||||||
|
|
||||||
if (!rc_client_has_achievements(m_client))
|
if (!rc_client_has_achievements(m_client))
|
||||||
return;
|
return;
|
||||||
|
@ -188,7 +192,8 @@ void AchievementManager::FetchGameBadges()
|
||||||
return std::string("");
|
return std::string("");
|
||||||
return std::string(
|
return std::string(
|
||||||
rc_client_get_achievement_info(manager.m_client, achievement_id)->badge_name);
|
rc_client_get_achievement_info(manager.m_client, achievement_id)->badge_name);
|
||||||
});
|
},
|
||||||
|
{.achievements = {achievement_id}});
|
||||||
FetchBadge(
|
FetchBadge(
|
||||||
&m_locked_badges[achievement_id], RC_IMAGE_TYPE_ACHIEVEMENT_LOCKED,
|
&m_locked_badges[achievement_id], RC_IMAGE_TYPE_ACHIEVEMENT_LOCKED,
|
||||||
[achievement_id](const AchievementManager& manager) {
|
[achievement_id](const AchievementManager& manager) {
|
||||||
|
@ -196,7 +201,8 @@ void AchievementManager::FetchGameBadges()
|
||||||
return std::string("");
|
return std::string("");
|
||||||
return std::string(
|
return std::string(
|
||||||
rc_client_get_achievement_info(manager.m_client, achievement_id)->badge_name);
|
rc_client_get_achievement_info(manager.m_client, achievement_id)->badge_name);
|
||||||
});
|
},
|
||||||
|
{.achievements = {achievement_id}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rc_client_destroy_achievement_list(achievement_list);
|
rc_client_destroy_achievement_list(achievement_list);
|
||||||
|
@ -226,7 +232,7 @@ void AchievementManager::DoFrame()
|
||||||
GenerateRichPresence(Core::CPUThreadGuard{*m_system});
|
GenerateRichPresence(Core::CPUThreadGuard{*m_system});
|
||||||
m_queue.EmplaceItem([this] { PingRichPresence(m_rich_presence); });
|
m_queue.EmplaceItem([this] { PingRichPresence(m_rich_presence); });
|
||||||
m_last_ping_time = current_time;
|
m_last_ping_time = current_time;
|
||||||
m_update_callback();
|
m_update_callback(UpdatedItems{.rich_presence = true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,13 +400,13 @@ void AchievementManager::SetDisabled(bool disable)
|
||||||
INFO_LOG_FMT(ACHIEVEMENTS, "Achievement Manager has been disabled.");
|
INFO_LOG_FMT(ACHIEVEMENTS, "Achievement Manager has been disabled.");
|
||||||
OSD::AddMessage("Please close all games to re-enable achievements.", OSD::Duration::VERY_LONG,
|
OSD::AddMessage("Please close all games to re-enable achievements.", OSD::Duration::VERY_LONG,
|
||||||
OSD::Color::RED);
|
OSD::Color::RED);
|
||||||
m_update_callback();
|
m_update_callback(UpdatedItems{.all = true});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (previously_disabled && !disable)
|
if (previously_disabled && !disable)
|
||||||
{
|
{
|
||||||
INFO_LOG_FMT(ACHIEVEMENTS, "Achievement Manager has been re-enabled.");
|
INFO_LOG_FMT(ACHIEVEMENTS, "Achievement Manager has been re-enabled.");
|
||||||
m_update_callback();
|
m_update_callback(UpdatedItems{.all = true});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -481,7 +487,7 @@ void AchievementManager::CloseGame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_update_callback();
|
m_update_callback(UpdatedItems{.all = true});
|
||||||
INFO_LOG_FMT(ACHIEVEMENTS, "Game closed.");
|
INFO_LOG_FMT(ACHIEVEMENTS, "Game closed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,7 +501,7 @@ void AchievementManager::Logout()
|
||||||
Config::SetBaseOrCurrent(Config::RA_API_TOKEN, "");
|
Config::SetBaseOrCurrent(Config::RA_API_TOKEN, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_update_callback();
|
m_update_callback(UpdatedItems{.all = true});
|
||||||
INFO_LOG_FMT(ACHIEVEMENTS, "Logged out from server.");
|
INFO_LOG_FMT(ACHIEVEMENTS, "Logged out from server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -655,7 +661,7 @@ void AchievementManager::LeaderboardEntriesCallback(int result, const char* erro
|
||||||
memcpy(map_entry.score.data(), response_entry.display, FORMAT_SIZE);
|
memcpy(map_entry.score.data(), response_entry.display, FORMAT_SIZE);
|
||||||
map_entry.rank = response_entry.rank;
|
map_entry.rank = response_entry.rank;
|
||||||
}
|
}
|
||||||
AchievementManager::GetInstance().m_update_callback();
|
AchievementManager::GetInstance().m_update_callback({.leaderboards = {leaderboard_id}});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementManager::GenerateRichPresence(const Core::CPUThreadGuard& guard)
|
void AchievementManager::GenerateRichPresence(const Core::CPUThreadGuard& guard)
|
||||||
|
@ -701,6 +707,7 @@ void AchievementManager::LoadGameCallback(int result, const char* error_message,
|
||||||
|
|
||||||
AchievementManager::GetInstance().FetchGameBadges();
|
AchievementManager::GetInstance().FetchGameBadges();
|
||||||
AchievementManager::GetInstance().m_system = &Core::System::GetInstance();
|
AchievementManager::GetInstance().m_system = &Core::System::GetInstance();
|
||||||
|
AchievementManager::GetInstance().m_update_callback({.all = true});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementManager::DisplayWelcomeMessage()
|
void AchievementManager::DisplayWelcomeMessage()
|
||||||
|
@ -987,15 +994,17 @@ u32 AchievementManager::MemoryPeeker(u32 address, u8* buffer, u32 num_bytes, rc_
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementManager::FetchBadge(AchievementManager::BadgeStatus* badge, u32 badge_type,
|
void AchievementManager::FetchBadge(AchievementManager::BadgeStatus* badge, u32 badge_type,
|
||||||
const AchievementManager::BadgeNameFunction function)
|
const AchievementManager::BadgeNameFunction function,
|
||||||
|
const UpdatedItems callback_data)
|
||||||
{
|
{
|
||||||
if (!m_client || !HasAPIToken() || !Config::Get(Config::RA_BADGES_ENABLED))
|
if (!m_client || !HasAPIToken() || !Config::Get(Config::RA_BADGES_ENABLED))
|
||||||
{
|
{
|
||||||
m_update_callback();
|
m_update_callback(callback_data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_image_queue.EmplaceItem([this, badge, badge_type, function = std::move(function)] {
|
m_image_queue.EmplaceItem([this, badge, badge_type, function = std::move(function),
|
||||||
|
callback_data = std::move(callback_data)] {
|
||||||
std::string name_to_fetch;
|
std::string name_to_fetch;
|
||||||
{
|
{
|
||||||
std::lock_guard lg{m_lock};
|
std::lock_guard lg{m_lock};
|
||||||
|
@ -1019,7 +1028,7 @@ void AchievementManager::FetchBadge(AchievementManager::BadgeStatus* badge, u32
|
||||||
WARN_LOG_FMT(ACHIEVEMENTS, "RetroAchievements connection failed on image request.\n URL: {}",
|
WARN_LOG_FMT(ACHIEVEMENTS, "RetroAchievements connection failed on image request.\n URL: {}",
|
||||||
api_request.url);
|
api_request.url);
|
||||||
rc_api_destroy_request(&api_request);
|
rc_api_destroy_request(&api_request);
|
||||||
m_update_callback();
|
m_update_callback(callback_data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1036,7 +1045,7 @@ void AchievementManager::FetchBadge(AchievementManager::BadgeStatus* badge, u32
|
||||||
badge->badge = std::move(fetched_badge);
|
badge->badge = std::move(fetched_badge);
|
||||||
badge->name = std::move(name_to_fetch);
|
badge->name = std::move(name_to_fetch);
|
||||||
|
|
||||||
m_update_callback();
|
m_update_callback(callback_data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,6 @@ public:
|
||||||
UNKNOWN_FAILURE
|
UNKNOWN_FAILURE
|
||||||
};
|
};
|
||||||
using ResponseCallback = std::function<void(ResponseType)>;
|
using ResponseCallback = std::function<void(ResponseType)>;
|
||||||
using UpdateCallback = std::function<void()>;
|
|
||||||
using BadgeNameFunction = std::function<std::string(const AchievementManager&)>;
|
using BadgeNameFunction = std::function<std::string(const AchievementManager&)>;
|
||||||
|
|
||||||
struct PointSpread
|
struct PointSpread
|
||||||
|
@ -116,6 +115,19 @@ public:
|
||||||
std::unordered_map<u32, LeaderboardEntry> entries;
|
std::unordered_map<u32, LeaderboardEntry> entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UpdatedItems
|
||||||
|
{
|
||||||
|
bool all = false;
|
||||||
|
bool player_icon = false;
|
||||||
|
bool game_icon = false;
|
||||||
|
bool all_achievements = false;
|
||||||
|
std::set<AchievementId> achievements{};
|
||||||
|
bool all_leaderboards = false;
|
||||||
|
std::set<AchievementId> leaderboards{};
|
||||||
|
bool rich_presence = false;
|
||||||
|
};
|
||||||
|
using UpdateCallback = std::function<void(const UpdatedItems&)>;
|
||||||
|
|
||||||
static AchievementManager& GetInstance();
|
static AchievementManager& GetInstance();
|
||||||
void Init();
|
void Init();
|
||||||
void SetUpdateCallback(UpdateCallback callback);
|
void SetUpdateCallback(UpdateCallback callback);
|
||||||
|
@ -213,14 +225,15 @@ private:
|
||||||
static void RequestV2(const rc_api_request_t* request, rc_client_server_callback_t callback,
|
static void RequestV2(const rc_api_request_t* request, rc_client_server_callback_t callback,
|
||||||
void* callback_data, rc_client_t* client);
|
void* callback_data, rc_client_t* client);
|
||||||
static u32 MemoryPeeker(u32 address, u8* buffer, u32 num_bytes, rc_client_t* client);
|
static u32 MemoryPeeker(u32 address, u8* buffer, u32 num_bytes, rc_client_t* client);
|
||||||
void FetchBadge(BadgeStatus* badge, u32 badge_type, const BadgeNameFunction function);
|
void FetchBadge(BadgeStatus* badge, u32 badge_type, const BadgeNameFunction function,
|
||||||
|
const UpdatedItems callback_data);
|
||||||
static void EventHandler(const rc_client_event_t* event, rc_client_t* client);
|
static void EventHandler(const rc_client_event_t* event, rc_client_t* client);
|
||||||
|
|
||||||
rc_runtime_t m_runtime{};
|
rc_runtime_t m_runtime{};
|
||||||
rc_client_t* m_client{};
|
rc_client_t* m_client{};
|
||||||
Core::System* m_system{};
|
Core::System* m_system{};
|
||||||
bool m_is_runtime_initialized = false;
|
bool m_is_runtime_initialized = false;
|
||||||
UpdateCallback m_update_callback = [] {};
|
UpdateCallback m_update_callback = [](const UpdatedItems&) {};
|
||||||
std::unique_ptr<DiscIO::Volume> m_loading_volume;
|
std::unique_ptr<DiscIO::Volume> m_loading_volume;
|
||||||
bool m_disabled = false;
|
bool m_disabled = false;
|
||||||
BadgeStatus m_player_badge;
|
BadgeStatus m_player_badge;
|
||||||
|
|
|
@ -62,13 +62,11 @@ AchievementHeaderWidget::AchievementHeaderWidget(QWidget* parent) : QWidget(pare
|
||||||
m_total->setContentsMargins(0, 0, 0, 0);
|
m_total->setContentsMargins(0, 0, 0, 0);
|
||||||
m_total->setAlignment(Qt::AlignTop);
|
m_total->setAlignment(Qt::AlignTop);
|
||||||
setLayout(m_total);
|
setLayout(m_total);
|
||||||
|
|
||||||
std::lock_guard lg{AchievementManager::GetInstance().GetLock()};
|
|
||||||
UpdateData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementHeaderWidget::UpdateData()
|
void AchievementHeaderWidget::UpdateData()
|
||||||
{
|
{
|
||||||
|
std::lock_guard lg{AchievementManager::GetInstance().GetLock()};
|
||||||
auto& instance = AchievementManager::GetInstance();
|
auto& instance = AchievementManager::GetInstance();
|
||||||
if (!instance.HasAPIToken())
|
if (!instance.HasAPIToken())
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,8 +24,6 @@ AchievementLeaderboardWidget::AchievementLeaderboardWidget(QWidget* parent) : QW
|
||||||
m_common_box = new QGroupBox();
|
m_common_box = new QGroupBox();
|
||||||
m_common_layout = new QGridLayout();
|
m_common_layout = new QGridLayout();
|
||||||
|
|
||||||
UpdateData(true);
|
|
||||||
|
|
||||||
m_common_box->setLayout(m_common_layout);
|
m_common_box->setLayout(m_common_layout);
|
||||||
|
|
||||||
auto* layout = new QVBoxLayout;
|
auto* layout = new QVBoxLayout;
|
||||||
|
|
|
@ -27,8 +27,6 @@ AchievementProgressWidget::AchievementProgressWidget(QWidget* parent) : QWidget(
|
||||||
m_common_box = new QGroupBox();
|
m_common_box = new QGroupBox();
|
||||||
m_common_layout = new QVBoxLayout();
|
m_common_layout = new QVBoxLayout();
|
||||||
|
|
||||||
UpdateData(true);
|
|
||||||
|
|
||||||
m_common_box->setLayout(m_common_layout);
|
m_common_box->setLayout(m_common_layout);
|
||||||
|
|
||||||
auto* layout = new QVBoxLayout;
|
auto* layout = new QVBoxLayout;
|
||||||
|
|
|
@ -28,11 +28,13 @@ AchievementsWindow::AchievementsWindow(QWidget* parent) : QDialog(parent)
|
||||||
CreateMainLayout();
|
CreateMainLayout();
|
||||||
ConnectWidgets();
|
ConnectWidgets();
|
||||||
AchievementManager::GetInstance().SetUpdateCallback(
|
AchievementManager::GetInstance().SetUpdateCallback(
|
||||||
[this] { QueueOnObject(this, &AchievementsWindow::UpdateData); });
|
[this](AchievementManager::UpdatedItems updated_items) {
|
||||||
|
QueueOnObject(this, [this, updated_items = std::move(updated_items)] {
|
||||||
|
AchievementsWindow::UpdateData(std::move(updated_items));
|
||||||
|
});
|
||||||
|
});
|
||||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
||||||
&AchievementsWindow::UpdateData);
|
[this] { AchievementsWindow::UpdateData({.all = true}); });
|
||||||
|
|
||||||
UpdateData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementsWindow::showEvent(QShowEvent* event)
|
void AchievementsWindow::showEvent(QShowEvent* event)
|
||||||
|
@ -71,19 +73,38 @@ void AchievementsWindow::ConnectWidgets()
|
||||||
connect(m_button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
connect(m_button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementsWindow::UpdateData()
|
void AchievementsWindow::UpdateData(AchievementManager::UpdatedItems updated_items)
|
||||||
{
|
{
|
||||||
|
m_settings_widget->UpdateData();
|
||||||
|
if (updated_items.all)
|
||||||
|
{
|
||||||
|
m_header_widget->UpdateData();
|
||||||
|
m_progress_widget->UpdateData(true);
|
||||||
|
m_leaderboard_widget->UpdateData(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (updated_items.player_icon || updated_items.game_icon || updated_items.rich_presence ||
|
||||||
|
updated_items.all_achievements || updated_items.achievements.size() > 0)
|
||||||
|
{
|
||||||
|
m_header_widget->UpdateData();
|
||||||
|
}
|
||||||
|
if (updated_items.all_achievements)
|
||||||
|
m_progress_widget->UpdateData(false);
|
||||||
|
else if (updated_items.achievements.size() > 0)
|
||||||
|
m_progress_widget->UpdateData(updated_items.achievements);
|
||||||
|
if (updated_items.all_leaderboards)
|
||||||
|
m_leaderboard_widget->UpdateData(false);
|
||||||
|
else if (updated_items.leaderboards.size() > 0)
|
||||||
|
m_leaderboard_widget->UpdateData(updated_items.leaderboards);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto& instance = AchievementManager::GetInstance();
|
auto& instance = AchievementManager::GetInstance();
|
||||||
std::lock_guard lg{instance.GetLock()};
|
std::lock_guard lg{instance.GetLock()};
|
||||||
const bool is_game_loaded = instance.IsGameLoaded();
|
const bool is_game_loaded = instance.IsGameLoaded();
|
||||||
|
|
||||||
m_header_widget->UpdateData();
|
|
||||||
m_header_widget->setVisible(instance.HasAPIToken());
|
m_header_widget->setVisible(instance.HasAPIToken());
|
||||||
m_settings_widget->UpdateData();
|
|
||||||
m_progress_widget->UpdateData(true);
|
|
||||||
m_tab_widget->setTabVisible(1, is_game_loaded);
|
m_tab_widget->setTabVisible(1, is_game_loaded);
|
||||||
m_leaderboard_widget->UpdateData(true);
|
|
||||||
m_tab_widget->setTabVisible(2, is_game_loaded);
|
m_tab_widget->setTabVisible(2, is_game_loaded);
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#ifdef USE_RETRO_ACHIEVEMENTS
|
#ifdef USE_RETRO_ACHIEVEMENTS
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
|
||||||
|
#include "Core/AchievementManager.h"
|
||||||
|
|
||||||
class AchievementHeaderWidget;
|
class AchievementHeaderWidget;
|
||||||
class AchievementLeaderboardWidget;
|
class AchievementLeaderboardWidget;
|
||||||
class AchievementSettingsWidget;
|
class AchievementSettingsWidget;
|
||||||
|
@ -19,7 +21,7 @@ class AchievementsWindow : public QDialog
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit AchievementsWindow(QWidget* parent);
|
explicit AchievementsWindow(QWidget* parent);
|
||||||
void UpdateData();
|
void UpdateData(AchievementManager::UpdatedItems updated_items);
|
||||||
void ForceSettingsTab();
|
void ForceSettingsTab();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -2005,6 +2005,7 @@ void MainWindow::ShowAchievementsWindow()
|
||||||
m_achievements_window->show();
|
m_achievements_window->show();
|
||||||
m_achievements_window->raise();
|
m_achievements_window->raise();
|
||||||
m_achievements_window->activateWindow();
|
m_achievements_window->activateWindow();
|
||||||
|
m_achievements_window->UpdateData(AchievementManager::UpdatedItems{.all = true});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::ShowAchievementSettings()
|
void MainWindow::ShowAchievementSettings()
|
||||||
|
|
Loading…
Reference in New Issue