Merge pull request #12877 from LillyJadeKatrin/retroachievements-auto-update

Update Achievement List when Rich Presence Updates
This commit is contained in:
Admiral H. Curtiss 2024-06-27 20:30:01 +02:00 committed by GitHub
commit 233ea58446
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 81 additions and 46 deletions

View File

@ -65,32 +65,48 @@ AchievementBox::AchievementBox(QWidget* parent, rc_client_achievement_t* achieve
}
void AchievementBox::UpdateData()
{
{
std::lock_guard lg{AchievementManager::GetInstance().GetLock()};
// rc_client guarantees m_achievement will be valid as long as the game is loaded
if (!AchievementManager::GetInstance().IsGameLoaded())
return;
const auto& badge = AchievementManager::GetInstance().GetAchievementBadge(
m_achievement->id, m_achievement->state != RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED);
std::string_view color = AchievementManager::GRAY;
if (m_achievement->unlocked & RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE)
color = AchievementManager::GOLD;
else if (m_achievement->unlocked & RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE)
color = AchievementManager::BLUE;
QImage i_badge(&badge.data.front(), badge.width, badge.height, QImage::Format_RGBA8888);
m_badge->setPixmap(
QPixmap::fromImage(i_badge).scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
m_badge->adjustSize();
m_badge->setStyleSheet(
QStringLiteral("border: 4px solid %1").arg(QtUtils::FromStdString(color)));
if (m_achievement->state == RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED)
{
m_status->setText(
tr("Unlocked at %1")
.arg(QDateTime::fromSecsSinceEpoch(m_achievement->unlock_time).toString()));
}
else
{
m_status->setText(tr("Locked"));
}
}
UpdateProgress();
}
void AchievementBox::UpdateProgress()
{
std::lock_guard lg{AchievementManager::GetInstance().GetLock()};
const auto& badge = AchievementManager::GetInstance().GetAchievementBadge(
m_achievement->id, m_achievement->state != RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED);
std::string_view color = AchievementManager::GRAY;
if (m_achievement->unlocked & RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE)
color = AchievementManager::GOLD;
else if (m_achievement->unlocked & RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE)
color = AchievementManager::BLUE;
QImage i_badge(&badge.data.front(), badge.width, badge.height, QImage::Format_RGBA8888);
m_badge->setPixmap(
QPixmap::fromImage(i_badge).scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
m_badge->adjustSize();
m_badge->setStyleSheet(QStringLiteral("border: 4px solid %1").arg(QtUtils::FromStdString(color)));
if (m_achievement->state == RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED)
{
m_status->setText(
tr("Unlocked at %1")
.arg(QDateTime::fromSecsSinceEpoch(m_achievement->unlock_time).toString()));
}
else
{
m_status->setText(tr("Locked"));
}
// rc_client guarantees m_achievement will be valid as long as the game is loaded
if (!AchievementManager::GetInstance().IsGameLoaded())
return;
if (m_achievement->measured_percent > 0.000)
{

View File

@ -20,6 +20,7 @@ class AchievementBox final : public QGroupBox
public:
explicit AchievementBox(QWidget* parent, rc_client_achievement_t* achievement);
void UpdateData();
void UpdateProgress();
private:
QLabel* m_badge;

View File

@ -42,33 +42,51 @@ void AchievementProgressWidget::UpdateData(bool clean_all)
{
m_achievement_boxes.clear();
ClearLayoutRecursively(m_common_layout);
auto& instance = AchievementManager::GetInstance();
if (!instance.IsGameLoaded())
return;
auto* client = instance.GetClient();
auto* achievement_list = rc_client_create_achievement_list(
client, RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL,
RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_PROGRESS);
for (u32 ix = 0; ix < achievement_list->num_buckets; ix++)
{
m_common_layout->addWidget(new QLabel(tr(achievement_list->buckets[ix].label)));
for (u32 jx = 0; jx < achievement_list->buckets[ix].num_achievements; jx++)
{
auto* achievement = achievement_list->buckets[ix].achievements[jx];
m_achievement_boxes[achievement->id] = std::make_shared<AchievementBox>(this, achievement);
m_common_layout->addWidget(m_achievement_boxes[achievement->id].get());
}
}
rc_client_destroy_achievement_list(achievement_list);
}
else
{
for (auto box : m_achievement_boxes)
while (auto* item = m_common_layout->takeAt(0))
{
box.second->UpdateData();
auto* widget = item->widget();
m_common_layout->removeWidget(widget);
if (std::strcmp(widget->metaObject()->className(), "QLabel") == 0)
{
widget->deleteLater();
delete item;
}
}
}
auto& instance = AchievementManager::GetInstance();
if (!instance.IsGameLoaded())
return;
auto* client = instance.GetClient();
auto* achievement_list =
rc_client_create_achievement_list(client, RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL,
RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_PROGRESS);
if (!achievement_list)
return;
for (u32 ix = 0; ix < achievement_list->num_buckets; ix++)
{
m_common_layout->addWidget(new QLabel(tr(achievement_list->buckets[ix].label)));
for (u32 jx = 0; jx < achievement_list->buckets[ix].num_achievements; jx++)
{
auto* achievement = achievement_list->buckets[ix].achievements[jx];
auto box_itr = m_achievement_boxes.lower_bound(achievement->id);
if (box_itr != m_achievement_boxes.end() && box_itr->first == achievement->id)
{
box_itr->second->UpdateProgress();
m_common_layout->addWidget(box_itr->second.get());
}
else
{
const auto new_box_itr = m_achievement_boxes.try_emplace(
box_itr, achievement->id, std::make_shared<AchievementBox>(this, achievement));
m_common_layout->addWidget(new_box_itr->second.get());
}
}
}
rc_client_destroy_achievement_list(achievement_list);
}
void AchievementProgressWidget::UpdateData(

View File

@ -91,7 +91,7 @@ void AchievementsWindow::UpdateData(AchievementManager::UpdatedItems updated_ite
{
m_header_widget->UpdateData();
}
if (updated_items.all_achievements)
if (updated_items.all_achievements || updated_items.rich_presence)
m_progress_widget->UpdateData(false);
else if (updated_items.achievements.size() > 0)
m_progress_widget->UpdateData(updated_items.achievements);