Merge pull request #12778 from LillyJadeKatrin/retroachievements-default-badges-v2

RetroAchievements - Default Badges
This commit is contained in:
Admiral H. Curtiss 2024-05-23 21:38:30 +02:00 committed by GitHub
commit f991610052
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 161 additions and 174 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

View File

@ -13,6 +13,8 @@
#include <rcheevos/include/rc_api_info.h>
#include <rcheevos/include/rc_hash.h>
#include "Common/CommonPaths.h"
#include "Common/FileUtil.h"
#include "Common/Image.h"
#include "Common/Logging/Log.h"
#include "Common/ScopeGuard.h"
@ -23,11 +25,10 @@
#include "Core/System.h"
#include "DiscIO/Blob.h"
#include "UICommon/DiscordPresence.h"
#include "VideoCommon/Assets/CustomTextureData.h"
#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/VideoEvents.h"
static std::unique_ptr<OSD::Icon> DecodeBadgeToOSDIcon(const AchievementManager::Badge& badge);
AchievementManager& AchievementManager::GetInstance()
{
static AchievementManager s_instance;
@ -36,6 +37,7 @@ AchievementManager& AchievementManager::GetInstance()
void AchievementManager::Init()
{
LoadDefaultBadges();
if (!m_client && Config::Get(Config::RA_ENABLED))
{
m_client = rc_client_create(MemoryPeeker, Request);
@ -278,7 +280,7 @@ u32 AchievementManager::GetPlayerScore() const
return user->score;
}
const AchievementManager::BadgeStatus& AchievementManager::GetPlayerBadge() const
const AchievementManager::Badge& AchievementManager::GetPlayerBadge() const
{
return m_player_badge;
}
@ -298,17 +300,19 @@ rc_api_fetch_game_data_response_t* AchievementManager::GetGameData()
return &m_game_data;
}
const AchievementManager::BadgeStatus& AchievementManager::GetGameBadge() const
const AchievementManager::Badge& AchievementManager::GetGameBadge() const
{
return m_game_badge;
}
const AchievementManager::BadgeStatus& AchievementManager::GetAchievementBadge(AchievementId id,
bool locked) const
const AchievementManager::Badge& AchievementManager::GetAchievementBadge(AchievementId id,
bool locked) const
{
auto& badge_list = locked ? m_locked_badges : m_locked_badges;
auto& badge_list = locked ? m_locked_badges : m_unlocked_badges;
auto itr = badge_list.find(id);
return (itr == badge_list.end()) ? m_default_badge : itr->second;
return (itr != badge_list.end() && itr->second.data.size() > 0) ?
itr->second :
(locked ? m_default_locked_badge : m_default_unlocked_badge);
}
const AchievementManager::LeaderboardStatus*
@ -330,7 +334,7 @@ AchievementManager::RichPresence AchievementManager::GetRichPresence() const
return m_rich_presence;
}
const AchievementManager::NamedIconMap& AchievementManager::GetChallengeIcons() const
const AchievementManager::NamedBadgeMap& AchievementManager::GetChallengeIcons() const
{
return m_active_challenges;
}
@ -393,7 +397,9 @@ void AchievementManager::CloseGame()
{
m_active_challenges.clear();
m_active_leaderboards.clear();
m_game_badge.name.clear();
m_game_badge.width = 0;
m_game_badge.height = 0;
m_game_badge.data.clear();
m_unlocked_badges.clear();
m_locked_badges.clear();
m_leaderboard_map.clear();
@ -415,7 +421,9 @@ void AchievementManager::Logout()
{
std::lock_guard lg{m_lock};
CloseGame();
m_player_badge.name.clear();
m_player_badge.width = 0;
m_player_badge.height = 0;
m_player_badge.data.clear();
Config::SetBaseOrCurrent(Config::RA_API_TOKEN, "");
}
@ -500,6 +508,55 @@ void AchievementManager::FilereaderClose(void* file_handle)
delete static_cast<FilereaderState*>(file_handle);
}
void AchievementManager::LoadDefaultBadges()
{
std::lock_guard lg{m_lock};
std::string directory = File::GetSysDirectory() + DIR_SEP + RESOURCES_DIR + DIR_SEP;
if (m_default_player_badge.data.empty())
{
if (!LoadPNGTexture(&m_default_player_badge,
fmt::format("{}{}", directory, DEFAULT_PLAYER_BADGE_FILENAME)))
{
ERROR_LOG_FMT(ACHIEVEMENTS, "Default player badge '{}' failed to load",
DEFAULT_PLAYER_BADGE_FILENAME);
}
}
m_player_badge = m_default_player_badge;
if (m_default_game_badge.data.empty())
{
if (!LoadPNGTexture(&m_default_game_badge,
fmt::format("{}{}", directory, DEFAULT_GAME_BADGE_FILENAME)))
{
ERROR_LOG_FMT(ACHIEVEMENTS, "Default game badge '{}' failed to load",
DEFAULT_GAME_BADGE_FILENAME);
}
}
m_game_badge = m_default_game_badge;
if (m_default_unlocked_badge.data.empty())
{
if (!LoadPNGTexture(&m_default_unlocked_badge,
fmt::format("{}{}", directory, DEFAULT_UNLOCKED_BADGE_FILENAME)))
{
ERROR_LOG_FMT(ACHIEVEMENTS, "Default unlocked achievement badge '{}' failed to load",
DEFAULT_UNLOCKED_BADGE_FILENAME);
}
}
if (m_default_locked_badge.data.empty())
{
if (!LoadPNGTexture(&m_default_locked_badge,
fmt::format("{}{}", directory, DEFAULT_LOCKED_BADGE_FILENAME)))
{
ERROR_LOG_FMT(ACHIEVEMENTS, "Default locked achievement badge '{}' failed to load",
DEFAULT_LOCKED_BADGE_FILENAME);
}
}
}
void AchievementManager::LoginCallback(int result, const char* error_message, rc_client_t* client,
void* userdata)
{
@ -637,11 +694,8 @@ void AchievementManager::DisplayWelcomeMessage()
m_display_welcome_message = false;
const u32 color =
rc_client_get_hardcore_enabled(m_client) ? OSD::Color::YELLOW : OSD::Color::CYAN;
if (Config::Get(Config::RA_BADGES_ENABLED) && !m_game_badge.name.empty())
{
OSD::AddMessage("", OSD::Duration::VERY_LONG, OSD::Color::GREEN,
DecodeBadgeToOSDIcon(m_game_badge.badge));
}
OSD::AddMessage("", OSD::Duration::VERY_LONG, OSD::Color::GREEN, &m_game_badge);
auto info = rc_client_get_game_info(m_client);
if (!info)
{
@ -671,17 +725,13 @@ void AchievementManager::DisplayWelcomeMessage()
void AchievementManager::HandleAchievementTriggeredEvent(const rc_client_event_t* client_event)
{
const auto& instance = AchievementManager::GetInstance();
OSD::AddMessage(fmt::format("Unlocked: {} ({})", client_event->achievement->title,
client_event->achievement->points),
OSD::Duration::VERY_LONG,
(rc_client_get_hardcore_enabled(AchievementManager::GetInstance().m_client)) ?
OSD::Color::YELLOW :
OSD::Color::CYAN,
(Config::Get(Config::RA_BADGES_ENABLED)) ?
DecodeBadgeToOSDIcon(AchievementManager::GetInstance()
.m_unlocked_badges[client_event->achievement->id]
.badge) :
nullptr);
(rc_client_get_hardcore_enabled(instance.m_client)) ? OSD::Color::YELLOW :
OSD::Color::CYAN,
&instance.GetAchievementBadge(client_event->achievement->id, false));
}
void AchievementManager::HandleLeaderboardStartedEvent(const rc_client_event_t* client_event)
@ -738,16 +788,9 @@ void AchievementManager::HandleLeaderboardTrackerHideEvent(const rc_client_event
void AchievementManager::HandleAchievementChallengeIndicatorShowEvent(
const rc_client_event_t* client_event)
{
if (Config::Get(Config::RA_BADGES_ENABLED))
{
auto& unlocked_badges = AchievementManager::GetInstance().m_unlocked_badges;
if (const auto unlocked_iter = unlocked_badges.find(client_event->achievement->id);
unlocked_iter != unlocked_badges.end())
{
AchievementManager::GetInstance().m_active_challenges[client_event->achievement->badge_name] =
DecodeBadgeToOSDIcon(unlocked_iter->second.badge);
}
}
auto& instance = AchievementManager::GetInstance();
instance.m_active_challenges[client_event->achievement->badge_name] =
&AchievementManager::GetInstance().GetAchievementBadge(client_event->achievement->id, false);
}
void AchievementManager::HandleAchievementChallengeIndicatorHideEvent(
@ -760,14 +803,11 @@ void AchievementManager::HandleAchievementChallengeIndicatorHideEvent(
void AchievementManager::HandleAchievementProgressIndicatorShowEvent(
const rc_client_event_t* client_event)
{
const auto& instance = AchievementManager::GetInstance();
OSD::AddMessage(fmt::format("{} {}", client_event->achievement->title,
client_event->achievement->measured_progress),
OSD::Duration::SHORT, OSD::Color::GREEN,
(Config::Get(Config::RA_BADGES_ENABLED)) ?
DecodeBadgeToOSDIcon(AchievementManager::GetInstance()
.m_unlocked_badges[client_event->achievement->id]
.badge) :
nullptr);
&instance.GetAchievementBadge(client_event->achievement->id, false));
}
void AchievementManager::HandleGameCompletedEvent(const rc_client_event_t* client_event,
@ -784,9 +824,7 @@ void AchievementManager::HandleGameCompletedEvent(const rc_client_event_t* clien
OSD::AddMessage(fmt::format("Congratulations! {} has {} {}", user_info->display_name,
hardcore ? "mastered" : "completed", game_info->title),
OSD::Duration::VERY_LONG, hardcore ? OSD::Color::YELLOW : OSD::Color::CYAN,
(Config::Get(Config::RA_BADGES_ENABLED)) ?
DecodeBadgeToOSDIcon(AchievementManager::GetInstance().m_game_badge.badge) :
nullptr);
&AchievementManager::GetInstance().m_game_badge);
}
void AchievementManager::HandleResetEvent(const rc_client_event_t* client_event)
@ -801,20 +839,6 @@ void AchievementManager::HandleServerErrorEvent(const rc_client_event_t* client_
client_event->server_error->api, client_event->server_error->error_message);
}
static std::unique_ptr<OSD::Icon> DecodeBadgeToOSDIcon(const AchievementManager::Badge& badge)
{
if (badge.empty())
return nullptr;
auto icon = std::make_unique<OSD::Icon>();
if (!Common::LoadPNG(badge, &icon->rgba_data, &icon->width, &icon->height))
{
ERROR_LOG_FMT(ACHIEVEMENTS, "Error decoding badge.");
return nullptr;
}
return icon;
}
void AchievementManager::Request(const rc_api_request_t* request,
rc_client_server_callback_t callback, void* callback_data,
rc_client_t* client)
@ -876,11 +900,11 @@ u32 AchievementManager::MemoryPeeker(u32 address, u8* buffer, u32 num_bytes, rc_
return num_bytes;
}
void AchievementManager::FetchBadge(AchievementManager::BadgeStatus* badge, u32 badge_type,
void AchievementManager::FetchBadge(AchievementManager::Badge* badge, u32 badge_type,
const AchievementManager::BadgeNameFunction function,
const UpdatedItems callback_data)
{
if (!m_client || !HasAPIToken() || !Config::Get(Config::RA_BADGES_ENABLED))
if (!m_client || !HasAPIToken())
{
m_update_callback(callback_data);
if (m_display_welcome_message && badge_type == RC_IMAGE_TYPE_GAME)
@ -923,7 +947,6 @@ void AchievementManager::FetchBadge(AchievementManager::BadgeStatus* badge, u32
}
rc_api_destroy_request(&api_request);
fetched_badge = std::move(*http_response);
INFO_LOG_FMT(ACHIEVEMENTS, "Successfully downloaded badge id {}.", name_to_fetch);
std::lock_guard lg{m_lock};
@ -932,8 +955,12 @@ void AchievementManager::FetchBadge(AchievementManager::BadgeStatus* badge, u32
INFO_LOG_FMT(ACHIEVEMENTS, "Requested outdated badge id {}.", name_to_fetch);
return;
}
badge->badge = std::move(fetched_badge);
badge->name = std::move(name_to_fetch);
if (!LoadPNGTexture(badge, *http_response))
{
ERROR_LOG_FMT(ACHIEVEMENTS, "Default game badge '{}' failed to load",
DEFAULT_GAME_BADGE_FILENAME);
}
m_update_callback(callback_data);
});

View File

@ -22,6 +22,7 @@
#include "Common/HttpRequest.h"
#include "Common/WorkQueueThread.h"
#include "DiscIO/Volume.h"
#include "VideoCommon/Assets/CustomTextureData.h"
namespace Core
{
@ -29,11 +30,6 @@ class CPUThreadGuard;
class System;
} // namespace Core
namespace OSD
{
struct Icon;
}
class AchievementManager
{
public:
@ -47,16 +43,14 @@ public:
using LeaderboardRank = u32;
static constexpr size_t RP_SIZE = 256;
using RichPresence = std::array<char, RP_SIZE>;
using Badge = std::vector<u8>;
using NamedIconMap = std::map<std::string, std::unique_ptr<OSD::Icon>, std::less<>>;
using Badge = VideoCommon::CustomTextureData::ArraySlice::Level;
using NamedBadgeMap = std::unordered_map<std::string, const Badge*>;
static constexpr size_t MAX_DISPLAYED_LBOARDS = 4;
struct BadgeStatus
{
std::string name = "";
Badge badge{};
};
static constexpr std::string_view DEFAULT_PLAYER_BADGE_FILENAME = "achievements_player.png";
static constexpr std::string_view DEFAULT_GAME_BADGE_FILENAME = "achievements_game.png";
static constexpr std::string_view DEFAULT_LOCKED_BADGE_FILENAME = "achievements_locked.png";
static constexpr std::string_view DEFAULT_UNLOCKED_BADGE_FILENAME = "achievements_unlocked.png";
static constexpr std::string_view GRAY = "transparent";
static constexpr std::string_view GOLD = "#FFD700";
static constexpr std::string_view BLUE = "#0B71C1";
@ -108,15 +102,15 @@ public:
void SetSpectatorMode();
std::string_view GetPlayerDisplayName() const;
u32 GetPlayerScore() const;
const BadgeStatus& GetPlayerBadge() const;
const Badge& GetPlayerBadge() const;
std::string_view GetGameDisplayName() const;
rc_client_t* GetClient();
rc_api_fetch_game_data_response_t* GetGameData();
const BadgeStatus& GetGameBadge() const;
const BadgeStatus& GetAchievementBadge(AchievementId id, bool locked) const;
const Badge& GetGameBadge() const;
const Badge& GetAchievementBadge(AchievementId id, bool locked) const;
const LeaderboardStatus* GetLeaderboardInfo(AchievementId leaderboard_id);
RichPresence GetRichPresence() const;
const NamedIconMap& GetChallengeIcons() const;
const NamedBadgeMap& GetChallengeIcons() const;
std::vector<std::string> GetActiveLeaderboards() const;
void DoState(PointerWrap& p);
@ -134,8 +128,6 @@ private:
std::unique_ptr<DiscIO::Volume> volume;
};
const BadgeStatus m_default_badge;
static void* FilereaderOpenByFilepath(const char* path_utf8);
static void* FilereaderOpenByVolume(const char* path_utf8);
static void FilereaderSeek(void* file_handle, int64_t offset, int origin);
@ -143,6 +135,7 @@ private:
static size_t FilereaderRead(void* file_handle, void* buffer, size_t requested_bytes);
static void FilereaderClose(void* file_handle);
void LoadDefaultBadges();
static void LoginCallback(int result, const char* error_message, rc_client_t* client,
void* userdata);
@ -177,7 +170,7 @@ private:
static void Request(const rc_api_request_t* request, rc_client_server_callback_t callback,
void* callback_data, 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(Badge* badge, u32 badge_type, const BadgeNameFunction function,
const UpdatedItems callback_data);
static void EventHandler(const rc_client_event_t* event, rc_client_t* client);
@ -187,20 +180,24 @@ private:
bool m_is_runtime_initialized = false;
UpdateCallback m_update_callback = [](const UpdatedItems&) {};
std::unique_ptr<DiscIO::Volume> m_loading_volume;
BadgeStatus m_player_badge;
Badge m_default_player_badge;
Badge m_default_game_badge;
Badge m_default_unlocked_badge;
Badge m_default_locked_badge;
Badge m_player_badge;
Hash m_game_hash{};
u32 m_game_id = 0;
rc_api_fetch_game_data_response_t m_game_data{};
bool m_is_game_loaded = false;
BadgeStatus m_game_badge;
Badge m_game_badge;
bool m_display_welcome_message = false;
std::unordered_map<AchievementId, BadgeStatus> m_unlocked_badges;
std::unordered_map<AchievementId, BadgeStatus> m_locked_badges;
std::unordered_map<AchievementId, Badge> m_unlocked_badges;
std::unordered_map<AchievementId, Badge> m_locked_badges;
RichPresence m_rich_presence;
std::chrono::steady_clock::time_point m_last_rp_time = std::chrono::steady_clock::now();
std::unordered_map<AchievementId, LeaderboardStatus> m_leaderboard_map;
NamedIconMap m_active_challenges;
NamedBadgeMap m_active_challenges;
std::vector<rc_client_leaderboard_tracker_t> m_active_leaderboards;
Common::WorkQueueThread<std::function<void()>> m_queue;

View File

@ -26,7 +26,6 @@ const Info<bool> RA_DISCORD_PRESENCE_ENABLED{
{System::Achievements, "Achievements", "DiscordPresenceEnabled"}, false};
const Info<bool> RA_PROGRESS_ENABLED{{System::Achievements, "Achievements", "ProgressEnabled"},
false};
const Info<bool> RA_BADGES_ENABLED{{System::Achievements, "Achievements", "BadgesEnabled"}, false};
} // namespace Config
#endif // USE_RETRO_ACHIEVEMENTS

View File

@ -20,7 +20,6 @@ extern const Info<bool> RA_ENCORE_ENABLED;
extern const Info<bool> RA_SPECTATOR_ENABLED;
extern const Info<bool> RA_DISCORD_PRESENCE_ENABLED;
extern const Info<bool> RA_PROGRESS_ENABLED;
extern const Info<bool> RA_BADGES_ENABLED;
} // namespace Config
#endif // USE_RETRO_ACHIEVEMENTS

View File

@ -61,22 +61,11 @@ void AchievementBox::UpdateData()
color = AchievementManager::GOLD;
else if (m_achievement->unlocked & RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE)
color = AchievementManager::BLUE;
if (Config::Get(Config::RA_BADGES_ENABLED) && badge.name != "")
{
QImage i_badge{};
if (i_badge.loadFromData(&badge.badge.front(), static_cast<int>(badge.badge.size())))
{
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)));
}
}
else
{
m_badge->setText({});
}
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)
{

View File

@ -68,24 +68,20 @@ void AchievementHeaderWidget::UpdateData()
QString user_name = QtUtils::FromStdString(instance.GetPlayerDisplayName());
QString game_name = QtUtils::FromStdString(instance.GetGameDisplayName());
AchievementManager::BadgeStatus player_badge = instance.GetPlayerBadge();
AchievementManager::BadgeStatus game_badge = instance.GetGameBadge();
const AchievementManager::Badge& player_badge = instance.GetPlayerBadge();
const AchievementManager::Badge& game_badge = instance.GetGameBadge();
m_user_icon->setVisible(false);
m_user_icon->clear();
m_user_icon->setText({});
if (Config::Get(Config::RA_BADGES_ENABLED) && !player_badge.name.empty())
{
QImage i_user_icon{};
if (i_user_icon.loadFromData(&player_badge.badge.front(), (int)player_badge.badge.size()))
{
m_user_icon->setPixmap(QPixmap::fromImage(i_user_icon)
.scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
m_user_icon->adjustSize();
m_user_icon->setStyleSheet(QStringLiteral("border: 4px solid transparent"));
m_user_icon->setVisible(true);
}
}
QImage i_user_icon(&player_badge.data.front(), player_badge.width, player_badge.height,
QImage::Format_RGBA8888);
m_user_icon->setPixmap(QPixmap::fromImage(i_user_icon)
.scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
m_user_icon->adjustSize();
m_user_icon->setStyleSheet(QStringLiteral("border: 4px solid transparent"));
m_user_icon->setVisible(true);
m_game_icon->setVisible(false);
m_game_icon->clear();
m_game_icon->setText({});
@ -94,26 +90,19 @@ void AchievementHeaderWidget::UpdateData()
{
rc_client_user_game_summary_t game_summary;
rc_client_get_user_game_summary(instance.GetClient(), &game_summary);
if (Config::Get(Config::RA_BADGES_ENABLED) && !game_badge.name.empty())
QImage i_game_icon(&game_badge.data.front(), game_badge.width, game_badge.height,
QImage::Format_RGBA8888);
m_game_icon->setPixmap(QPixmap::fromImage(i_game_icon)
.scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
m_game_icon->adjustSize();
std::string_view color = AchievementManager::GRAY;
if (game_summary.num_core_achievements == game_summary.num_unlocked_achievements)
{
QImage i_game_icon{};
if (i_game_icon.loadFromData(&game_badge.badge.front(), (int)game_badge.badge.size()))
{
m_game_icon->setPixmap(QPixmap::fromImage(i_game_icon)
.scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
m_game_icon->adjustSize();
std::string_view color = AchievementManager::GRAY;
if (game_summary.num_core_achievements == game_summary.num_unlocked_achievements)
{
color =
instance.IsHardcoreModeActive() ? AchievementManager::GOLD : AchievementManager::BLUE;
}
m_game_icon->setStyleSheet(
QStringLiteral("border: 4px solid %1").arg(QtUtils::FromStdString(color)));
m_game_icon->setVisible(true);
}
color = instance.IsHardcoreModeActive() ? AchievementManager::GOLD : AchievementManager::BLUE;
}
m_game_icon->setStyleSheet(
QStringLiteral("border: 4px solid %1").arg(QtUtils::FromStdString(color)));
m_game_icon->setVisible(true);
m_name->setText(tr("%1 is playing %2").arg(user_name).arg(game_name));
m_points->setText(tr("%1 has unlocked %2/%3 achievements worth %4/%5 points")

View File

@ -105,11 +105,6 @@ void AchievementSettingsWidget::CreateLayout()
tr("Enable progress notifications on achievements.<br><br>Displays a brief popup message "
"whenever the player makes progress on an achievement that tracks an accumulated value, "
"such as 60 out of 120 stars."));
m_common_badges_enabled_input = new ToolTipCheckBox(tr("Enable Achievement Badges"));
m_common_badges_enabled_input->SetDescription(
tr("Enable achievement badges.<br><br>Displays icons for the player, game, and achievements. "
"Simple visual option, but will require a small amount of extra memory and time to "
"download the images."));
m_common_layout->addWidget(m_common_integration_enabled_input);
m_common_layout->addWidget(m_common_username_label);
@ -129,7 +124,6 @@ void AchievementSettingsWidget::CreateLayout()
m_common_layout->addWidget(m_common_discord_presence_enabled_input);
#endif // USE_DISCORD_PRESENCE
m_common_layout->addWidget(m_common_progress_enabled_input);
m_common_layout->addWidget(m_common_badges_enabled_input);
m_common_layout->setAlignment(Qt::AlignTop);
setLayout(m_common_layout);
@ -153,8 +147,6 @@ void AchievementSettingsWidget::ConnectWidgets()
&AchievementSettingsWidget::ToggleDiscordPresence);
connect(m_common_progress_enabled_input, &QCheckBox::toggled, this,
&AchievementSettingsWidget::ToggleProgress);
connect(m_common_badges_enabled_input, &QCheckBox::toggled, this,
&AchievementSettingsWidget::ToggleBadges);
}
void AchievementSettingsWidget::OnControllerInterfaceConfigure()
@ -214,9 +206,6 @@ void AchievementSettingsWidget::LoadSettings()
SignalBlocking(m_common_progress_enabled_input)
->setChecked(Config::Get(Config::RA_PROGRESS_ENABLED));
SignalBlocking(m_common_progress_enabled_input)->setEnabled(enabled);
SignalBlocking(m_common_badges_enabled_input)->setChecked(Config::Get(Config::RA_BADGES_ENABLED));
SignalBlocking(m_common_badges_enabled_input)->setEnabled(enabled);
}
void AchievementSettingsWidget::SaveSettings()
@ -235,7 +224,6 @@ void AchievementSettingsWidget::SaveSettings()
m_common_discord_presence_enabled_input->isChecked());
Config::SetBaseOrCurrent(Config::RA_PROGRESS_ENABLED,
m_common_progress_enabled_input->isChecked());
Config::SetBaseOrCurrent(Config::RA_BADGES_ENABLED, m_common_badges_enabled_input->isChecked());
Config::Save();
}
@ -308,11 +296,4 @@ void AchievementSettingsWidget::ToggleProgress()
SaveSettings();
}
void AchievementSettingsWidget::ToggleBadges()
{
SaveSettings();
AchievementManager::GetInstance().FetchPlayerBadge();
AchievementManager::GetInstance().FetchGameBadges();
}
#endif // USE_RETRO_ACHIEVEMENTS

View File

@ -38,7 +38,6 @@ private:
void ToggleSpectator();
void ToggleDiscordPresence();
void ToggleProgress();
void ToggleBadges();
QGroupBox* m_common_box;
QVBoxLayout* m_common_layout;
@ -56,7 +55,6 @@ private:
ToolTipCheckBox* m_common_spectator_enabled_input;
ToolTipCheckBox* m_common_discord_presence_enabled_input;
ToolTipCheckBox* m_common_progress_enabled_input;
ToolTipCheckBox* m_common_badges_enabled_input;
};
#endif // USE_RETRO_ACHIEVEMENTS

View File

@ -574,6 +574,14 @@ bool LoadPNGTexture(CustomTextureData::ArraySlice::Level* level, const std::stri
std::vector<u8> buffer(file.GetSize());
file.ReadBytes(buffer.data(), file.GetSize());
return LoadPNGTexture(level, buffer);
}
bool LoadPNGTexture(CustomTextureData::ArraySlice::Level* level, const std::vector<u8>& buffer)
{
if (!level) [[unlikely]]
return false;
if (!Common::LoadPNG(buffer, &level->data, &level->width, &level->height))
return false;

View File

@ -33,4 +33,5 @@ bool LoadDDSTexture(CustomTextureData* texture, const std::string& filename);
bool LoadDDSTexture(CustomTextureData::ArraySlice::Level* level, const std::string& filename,
u32 mip_level);
bool LoadPNGTexture(CustomTextureData::ArraySlice::Level* level, const std::string& filename);
bool LoadPNGTexture(CustomTextureData::ArraySlice::Level* level, const std::vector<u8>& buffer);
} // namespace VideoCommon

View File

@ -20,6 +20,7 @@
#include "VideoCommon/AbstractGfx.h"
#include "VideoCommon/AbstractTexture.h"
#include "VideoCommon/Assets/CustomTextureData.h"
#include "VideoCommon/TextureConfig.h"
namespace OSD
@ -36,8 +37,9 @@ static std::atomic<int> s_obscured_pixels_top = 0;
struct Message
{
Message() = default;
Message(std::string text_, u32 duration_, u32 color_, std::unique_ptr<Icon> icon_ = nullptr)
: text(std::move(text_)), duration(duration_), color(color_), icon(std::move(icon_))
Message(std::string text_, u32 duration_, u32 color_,
const VideoCommon::CustomTextureData::ArraySlice::Level* icon_ = nullptr)
: text(std::move(text_)), duration(duration_), color(color_), icon(icon_)
{
timer.Start();
}
@ -48,7 +50,7 @@ struct Message
bool ever_drawn = false;
bool should_discard = false;
u32 color = 0;
std::unique_ptr<Icon> icon;
const VideoCommon::CustomTextureData::ArraySlice::Level* icon;
std::unique_ptr<AbstractTexture> texture;
};
static std::multimap<MessageType, Message> s_messages;
@ -95,13 +97,13 @@ static float DrawMessage(int index, Message& msg, const ImVec2& position, int ti
msg.texture = g_gfx->CreateTexture(tex_config);
if (msg.texture)
{
msg.texture->Load(0, width, height, width, msg.icon->rgba_data.data(),
msg.texture->Load(0, width, height, width, msg.icon->data.data(),
sizeof(u32) * width * height);
}
else
{
// don't try again next time
msg.icon.reset();
msg.icon = nullptr;
}
}
@ -127,7 +129,7 @@ static float DrawMessage(int index, Message& msg, const ImVec2& position, int ti
}
void AddTypedMessage(MessageType type, std::string message, u32 ms, u32 argb,
std::unique_ptr<Icon> icon)
const VideoCommon::CustomTextureData::ArraySlice::Level* icon)
{
std::lock_guard lock{s_messages_mutex};
@ -141,7 +143,8 @@ void AddTypedMessage(MessageType type, std::string message, u32 ms, u32 argb,
s_messages.emplace(type, Message(std::move(message), ms, argb, std::move(icon)));
}
void AddMessage(std::string message, u32 ms, u32 argb, std::unique_ptr<Icon> icon)
void AddMessage(std::string message, u32 ms, u32 argb,
const VideoCommon::CustomTextureData::ArraySlice::Level* icon)
{
std::lock_guard lock{s_messages_mutex};
s_messages.emplace(MessageType::Typeless, Message(std::move(message), ms, argb, std::move(icon)));

View File

@ -10,6 +10,8 @@
#include "Common/CommonTypes.h"
#include "VideoCommon/Assets/CustomTextureData.h"
namespace OSD
{
enum class MessageType
@ -37,18 +39,12 @@ constexpr u32 NORMAL = 5000;
constexpr u32 VERY_LONG = 10000;
}; // namespace Duration
struct Icon
{
std::vector<u8> rgba_data;
u32 width = 0;
u32 height = 0;
}; // struct Icon
// On-screen message display (colored yellow by default)
void AddMessage(std::string message, u32 ms = Duration::SHORT, u32 argb = Color::YELLOW,
std::unique_ptr<Icon> icon = nullptr);
const VideoCommon::CustomTextureData::ArraySlice::Level* icon = nullptr);
void AddTypedMessage(MessageType type, std::string message, u32 ms = Duration::SHORT,
u32 argb = Color::YELLOW, std::unique_ptr<Icon> icon = nullptr);
u32 argb = Color::YELLOW,
const VideoCommon::CustomTextureData::ArraySlice::Level* icon = nullptr);
// Draw the current messages on the screen. Only call once per frame.
void DrawMessages();

View File

@ -358,7 +358,7 @@ void OnScreenUI::DrawChallengesAndLeaderboards()
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->rgba_data.data(),
res.first->second->Load(0, width, height, width, icon->data.data(),
sizeof(u32) * width * height);
}
for (auto& [name, texture] : m_challenge_texture_map)