Refactor Leaderboard widget to allow partial updates
Similarly to the Progress widget (though without the separate object for each box, because each Leaderboard unit is just three text fields stacked vertically), AchievementLeaderboardWidget.UpdateData will now accept three options: destroy all and rebuild, update all, or update a set of rows. As part of this, AchievementManager::GetLeaderboardsInfo has been refactored to GetLeaderboardInfo to return a single leaderboard for the ID passed in.
This commit is contained in:
parent
d2069e888d
commit
c57be0efca
|
@ -358,10 +358,12 @@ AchievementManager::GetAchievementProgress(AchievementId achievement_id, u32* va
|
||||||
return ResponseType::SUCCESS;
|
return ResponseType::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::unordered_map<AchievementManager::AchievementId, AchievementManager::LeaderboardStatus>&
|
const AchievementManager::LeaderboardStatus*
|
||||||
AchievementManager::GetLeaderboardsInfo() const
|
AchievementManager::GetLeaderboardInfo(AchievementManager::AchievementId leaderboard_id) const
|
||||||
{
|
{
|
||||||
return m_leaderboard_map;
|
if (m_leaderboard_map.count(leaderboard_id) < 1)
|
||||||
|
return nullptr;
|
||||||
|
return &m_leaderboard_map.at(leaderboard_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
AchievementManager::RichPresence AchievementManager::GetRichPresence() const
|
AchievementManager::RichPresence AchievementManager::GetRichPresence() const
|
||||||
|
|
|
@ -143,7 +143,7 @@ public:
|
||||||
const UnlockStatus* GetUnlockStatus(AchievementId achievement_id) const;
|
const UnlockStatus* GetUnlockStatus(AchievementId achievement_id) const;
|
||||||
AchievementManager::ResponseType GetAchievementProgress(AchievementId achievement_id, u32* value,
|
AchievementManager::ResponseType GetAchievementProgress(AchievementId achievement_id, u32* value,
|
||||||
u32* target);
|
u32* target);
|
||||||
const std::unordered_map<AchievementId, LeaderboardStatus>& GetLeaderboardsInfo() const;
|
const LeaderboardStatus* GetLeaderboardInfo(AchievementId leaderboard_id) const;
|
||||||
RichPresence GetRichPresence() const;
|
RichPresence GetRichPresence() const;
|
||||||
bool IsDisabled() const { return m_disabled; };
|
bool IsDisabled() const { return m_disabled; };
|
||||||
void SetDisabled(bool disabled);
|
void SetDisabled(bool disabled);
|
||||||
|
|
|
@ -24,10 +24,7 @@ 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);
|
||||||
std::lock_guard lg{AchievementManager::GetInstance().GetLock()};
|
|
||||||
UpdateData();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_common_box->setLayout(m_common_layout);
|
m_common_box->setLayout(m_common_layout);
|
||||||
|
|
||||||
|
@ -38,19 +35,27 @@ AchievementLeaderboardWidget::AchievementLeaderboardWidget(QWidget* parent) : QW
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementLeaderboardWidget::UpdateData()
|
void AchievementLeaderboardWidget::UpdateData(bool clean_all)
|
||||||
{
|
{
|
||||||
|
if (clean_all)
|
||||||
|
{
|
||||||
ClearLayoutRecursively(m_common_layout);
|
ClearLayoutRecursively(m_common_layout);
|
||||||
|
|
||||||
if (!AchievementManager::GetInstance().IsGameLoaded())
|
auto& instance = AchievementManager::GetInstance();
|
||||||
|
if (!instance.IsGameLoaded())
|
||||||
return;
|
return;
|
||||||
const auto& leaderboards = AchievementManager::GetInstance().GetLeaderboardsInfo();
|
|
||||||
int row = 0;
|
rc_api_fetch_game_data_response_t* game_data;
|
||||||
for (const auto& board_row : leaderboards)
|
|
||||||
{
|
{
|
||||||
const AchievementManager::LeaderboardStatus& board = board_row.second;
|
std::lock_guard lg{AchievementManager::GetInstance().GetLock()};
|
||||||
QLabel* a_title = new QLabel(QString::fromStdString(board.name));
|
game_data = instance.GetGameData();
|
||||||
QLabel* a_description = new QLabel(QString::fromStdString(board.description));
|
}
|
||||||
|
for (u32 row = 0; row < game_data->num_leaderboards; row += 2)
|
||||||
|
{
|
||||||
|
const auto* leaderboard = game_data->leaderboards + (row / 2);
|
||||||
|
m_leaderboard_order[leaderboard->id] = row;
|
||||||
|
QLabel* a_title = new QLabel(QString::fromUtf8(leaderboard->title));
|
||||||
|
QLabel* a_description = new QLabel(QString::fromUtf8(leaderboard->description));
|
||||||
QVBoxLayout* a_col_left = new QVBoxLayout();
|
QVBoxLayout* a_col_left = new QVBoxLayout();
|
||||||
a_col_left->addWidget(a_title);
|
a_col_left->addWidget(a_title);
|
||||||
a_col_left->addWidget(a_description);
|
a_col_left->addWidget(a_description);
|
||||||
|
@ -61,6 +66,54 @@ void AchievementLeaderboardWidget::UpdateData()
|
||||||
m_common_layout->addWidget(a_divider, row - 1, 0);
|
m_common_layout->addWidget(a_divider, row - 1, 0);
|
||||||
}
|
}
|
||||||
m_common_layout->addLayout(a_col_left, row, 0);
|
m_common_layout->addLayout(a_col_left, row, 0);
|
||||||
|
for (size_t ix = 0; ix < 4; ix++)
|
||||||
|
{
|
||||||
|
QVBoxLayout* a_col = new QVBoxLayout();
|
||||||
|
for (size_t jx = 0; jx < 3; jx++)
|
||||||
|
a_col->addWidget(new QLabel(QStringLiteral("---")));
|
||||||
|
if (row > 0)
|
||||||
|
{
|
||||||
|
QFrame* a_divider = new QFrame();
|
||||||
|
a_divider->setFrameShape(QFrame::HLine);
|
||||||
|
m_common_layout->addWidget(a_divider, row - 1, static_cast<int>(ix) + 1);
|
||||||
|
}
|
||||||
|
m_common_layout->addLayout(a_col, row, static_cast<int>(ix) + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto row : m_leaderboard_order)
|
||||||
|
{
|
||||||
|
UpdateRow(row.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AchievementLeaderboardWidget::UpdateData(
|
||||||
|
const std::set<AchievementManager::AchievementId>& update_ids)
|
||||||
|
{
|
||||||
|
for (auto row : m_leaderboard_order)
|
||||||
|
{
|
||||||
|
if (update_ids.contains(row.first))
|
||||||
|
{
|
||||||
|
UpdateRow(row.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AchievementLeaderboardWidget::UpdateRow(AchievementManager::AchievementId leaderboard_id)
|
||||||
|
{
|
||||||
|
const auto leaderboard_itr = m_leaderboard_order.find(leaderboard_id);
|
||||||
|
if (leaderboard_itr == m_leaderboard_order.end())
|
||||||
|
return;
|
||||||
|
const int row = leaderboard_itr->second;
|
||||||
|
|
||||||
|
const AchievementManager::LeaderboardStatus* board;
|
||||||
|
{
|
||||||
|
std::lock_guard lg{AchievementManager::GetInstance().GetLock()};
|
||||||
|
board = AchievementManager::GetInstance().GetLeaderboardInfo(leaderboard_id);
|
||||||
|
}
|
||||||
|
if (!board)
|
||||||
|
return;
|
||||||
|
|
||||||
// Each leaderboard entry is displayed with four values. These are *generally* intended to be,
|
// Each leaderboard entry is displayed with four values. These are *generally* intended to be,
|
||||||
// in order, the first place entry, the entry one above the player, the player's entry, and
|
// in order, the first place entry, the entry one above the player, the player's entry, and
|
||||||
// the entry one below the player.
|
// the entry one below the player.
|
||||||
|
@ -72,43 +125,31 @@ void AchievementLeaderboardWidget::UpdateData()
|
||||||
// * If the player is last place, the player will be in the fourth slot, and the second and
|
// * If the player is last place, the player will be in the fourth slot, and the second and
|
||||||
// third slots will be the two players above them. The first slot will always be first place.
|
// third slots will be the two players above them. The first slot will always be first place.
|
||||||
std::array<u32, 4> to_display{1, 2, 3, 4};
|
std::array<u32, 4> to_display{1, 2, 3, 4};
|
||||||
if (board.player_index > to_display.size() - 1)
|
if (board->player_index > to_display.size() - 1)
|
||||||
{
|
{
|
||||||
// If the rank one below than the player is found, offset = 1.
|
// If the rank one below than the player is found, offset = 1.
|
||||||
u32 offset = static_cast<u32>(board.entries.count(board.player_index + 1));
|
u32 offset = static_cast<u32>(board->entries.count(board->player_index + 1));
|
||||||
// Example: player is 10th place but not last
|
// Example: player is 10th place but not last
|
||||||
// to_display = {1, 10-3+1+1, 10-3+1+2, 10-3+1+3} = {1, 9, 10, 11}
|
// to_display = {1, 10-3+1+1, 10-3+1+2, 10-3+1+3} = {1, 9, 10, 11}
|
||||||
// Example: player is 15th place and is last
|
// Example: player is 15th place and is last
|
||||||
// to_display = {1, 15-3+0+1, 15-3+0+2, 15-3+0+3} = {1, 13, 14, 15}
|
// to_display = {1, 15-3+0+1, 15-3+0+2, 15-3+0+3} = {1, 13, 14, 15}
|
||||||
for (size_t i = 1; i < to_display.size(); ++i)
|
for (size_t ix = 1; ix < to_display.size(); ++ix)
|
||||||
to_display[i] = board.player_index - 3 + offset + static_cast<u32>(i);
|
to_display[ix] = board->player_index - 3 + offset + static_cast<u32>(ix);
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < to_display.size(); ++i)
|
for (size_t ix = 0; ix < to_display.size(); ++ix)
|
||||||
{
|
{
|
||||||
u32 index = to_display[i];
|
const auto it = board->entries.find(to_display[ix]);
|
||||||
QLabel* a_rank = new QLabel(QStringLiteral("---"));
|
if (it != board->entries.end())
|
||||||
QLabel* a_username = new QLabel(QStringLiteral("---"));
|
|
||||||
QLabel* a_score = new QLabel(QStringLiteral("---"));
|
|
||||||
const auto it = board.entries.find(index);
|
|
||||||
if (it != board.entries.end())
|
|
||||||
{
|
{
|
||||||
a_rank->setText(tr("Rank %1").arg(it->second.rank));
|
|
||||||
a_username->setText(QString::fromStdString(it->second.username));
|
|
||||||
a_score->setText(QString::fromUtf8(it->second.score.data()));
|
|
||||||
}
|
|
||||||
QVBoxLayout* a_col = new QVBoxLayout();
|
QVBoxLayout* a_col = new QVBoxLayout();
|
||||||
a_col->addWidget(a_rank);
|
a_col->addWidget(new QLabel(tr("Rank %1").arg(it->second.rank)));
|
||||||
a_col->addWidget(a_username);
|
a_col->addWidget(new QLabel(QString::fromStdString(it->second.username)));
|
||||||
a_col->addWidget(a_score);
|
a_col->addWidget(new QLabel(QString::fromUtf8(it->second.score.data())));
|
||||||
if (row > 0)
|
auto old_item = m_common_layout->itemAtPosition(row, static_cast<int>(ix) + 1);
|
||||||
{
|
m_common_layout->removeItem(old_item);
|
||||||
QFrame* a_divider = new QFrame();
|
ClearLayoutRecursively(static_cast<QLayout*>(old_item));
|
||||||
a_divider->setFrameShape(QFrame::HLine);
|
m_common_layout->addLayout(a_col, row, static_cast<int>(ix) + 1);
|
||||||
m_common_layout->addWidget(a_divider, row - 1, static_cast<int>(i) + 1);
|
|
||||||
}
|
}
|
||||||
m_common_layout->addLayout(a_col, row, static_cast<int>(i) + 1);
|
|
||||||
}
|
|
||||||
row += 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#ifdef USE_RETRO_ACHIEVEMENTS
|
#ifdef USE_RETRO_ACHIEVEMENTS
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include "Core/AchievementManager.h"
|
||||||
|
|
||||||
class QGroupBox;
|
class QGroupBox;
|
||||||
class QGridLayout;
|
class QGridLayout;
|
||||||
|
|
||||||
|
@ -14,11 +16,14 @@ class AchievementLeaderboardWidget final : public QWidget
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit AchievementLeaderboardWidget(QWidget* parent);
|
explicit AchievementLeaderboardWidget(QWidget* parent);
|
||||||
void UpdateData();
|
void UpdateData(bool clean_all);
|
||||||
|
void UpdateData(const std::set<AchievementManager::AchievementId>& update_ids);
|
||||||
|
void UpdateRow(AchievementManager::AchievementId leaderboard_id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QGroupBox* m_common_box;
|
QGroupBox* m_common_box;
|
||||||
QGridLayout* m_common_layout;
|
QGridLayout* m_common_layout;
|
||||||
|
std::map<AchievementManager::AchievementId, int> m_leaderboard_order;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // USE_RETRO_ACHIEVEMENTS
|
#endif // USE_RETRO_ACHIEVEMENTS
|
||||||
|
|
|
@ -83,7 +83,7 @@ void AchievementsWindow::UpdateData()
|
||||||
m_settings_widget->UpdateData();
|
m_settings_widget->UpdateData();
|
||||||
m_progress_widget->UpdateData(true);
|
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();
|
m_leaderboard_widget->UpdateData(true);
|
||||||
m_tab_widget->setTabVisible(2, is_game_loaded);
|
m_tab_widget->setTabVisible(2, is_game_loaded);
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
|
|
Loading…
Reference in New Issue