mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-24 23:11:14 +01:00
Merge pull request #12778 from LillyJadeKatrin/retroachievements-default-badges-v2
RetroAchievements - Default Badges
This commit is contained in:
commit
f991610052
BIN
Data/Sys/Resources/achievements_game.png
Normal file
BIN
Data/Sys/Resources/achievements_game.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 460 B |
BIN
Data/Sys/Resources/achievements_locked.png
Normal file
BIN
Data/Sys/Resources/achievements_locked.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 235 B |
BIN
Data/Sys/Resources/achievements_player.png
Normal file
BIN
Data/Sys/Resources/achievements_player.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 335 B |
BIN
Data/Sys/Resources/achievements_unlocked.png
Normal file
BIN
Data/Sys/Resources/achievements_unlocked.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 235 B |
@ -13,6 +13,8 @@
|
|||||||
#include <rcheevos/include/rc_api_info.h>
|
#include <rcheevos/include/rc_api_info.h>
|
||||||
#include <rcheevos/include/rc_hash.h>
|
#include <rcheevos/include/rc_hash.h>
|
||||||
|
|
||||||
|
#include "Common/CommonPaths.h"
|
||||||
|
#include "Common/FileUtil.h"
|
||||||
#include "Common/Image.h"
|
#include "Common/Image.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/ScopeGuard.h"
|
#include "Common/ScopeGuard.h"
|
||||||
@ -23,11 +25,10 @@
|
|||||||
#include "Core/System.h"
|
#include "Core/System.h"
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
#include "UICommon/DiscordPresence.h"
|
#include "UICommon/DiscordPresence.h"
|
||||||
|
#include "VideoCommon/Assets/CustomTextureData.h"
|
||||||
#include "VideoCommon/OnScreenDisplay.h"
|
#include "VideoCommon/OnScreenDisplay.h"
|
||||||
#include "VideoCommon/VideoEvents.h"
|
#include "VideoCommon/VideoEvents.h"
|
||||||
|
|
||||||
static std::unique_ptr<OSD::Icon> DecodeBadgeToOSDIcon(const AchievementManager::Badge& badge);
|
|
||||||
|
|
||||||
AchievementManager& AchievementManager::GetInstance()
|
AchievementManager& AchievementManager::GetInstance()
|
||||||
{
|
{
|
||||||
static AchievementManager s_instance;
|
static AchievementManager s_instance;
|
||||||
@ -36,6 +37,7 @@ AchievementManager& AchievementManager::GetInstance()
|
|||||||
|
|
||||||
void AchievementManager::Init()
|
void AchievementManager::Init()
|
||||||
{
|
{
|
||||||
|
LoadDefaultBadges();
|
||||||
if (!m_client && Config::Get(Config::RA_ENABLED))
|
if (!m_client && Config::Get(Config::RA_ENABLED))
|
||||||
{
|
{
|
||||||
m_client = rc_client_create(MemoryPeeker, Request);
|
m_client = rc_client_create(MemoryPeeker, Request);
|
||||||
@ -278,7 +280,7 @@ u32 AchievementManager::GetPlayerScore() const
|
|||||||
return user->score;
|
return user->score;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AchievementManager::BadgeStatus& AchievementManager::GetPlayerBadge() const
|
const AchievementManager::Badge& AchievementManager::GetPlayerBadge() const
|
||||||
{
|
{
|
||||||
return m_player_badge;
|
return m_player_badge;
|
||||||
}
|
}
|
||||||
@ -298,17 +300,19 @@ rc_api_fetch_game_data_response_t* AchievementManager::GetGameData()
|
|||||||
return &m_game_data;
|
return &m_game_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AchievementManager::BadgeStatus& AchievementManager::GetGameBadge() const
|
const AchievementManager::Badge& AchievementManager::GetGameBadge() const
|
||||||
{
|
{
|
||||||
return m_game_badge;
|
return m_game_badge;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AchievementManager::BadgeStatus& AchievementManager::GetAchievementBadge(AchievementId id,
|
const AchievementManager::Badge& AchievementManager::GetAchievementBadge(AchievementId id,
|
||||||
bool locked) const
|
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);
|
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*
|
const AchievementManager::LeaderboardStatus*
|
||||||
@ -330,7 +334,7 @@ AchievementManager::RichPresence AchievementManager::GetRichPresence() const
|
|||||||
return m_rich_presence;
|
return m_rich_presence;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AchievementManager::NamedIconMap& AchievementManager::GetChallengeIcons() const
|
const AchievementManager::NamedBadgeMap& AchievementManager::GetChallengeIcons() const
|
||||||
{
|
{
|
||||||
return m_active_challenges;
|
return m_active_challenges;
|
||||||
}
|
}
|
||||||
@ -393,7 +397,9 @@ void AchievementManager::CloseGame()
|
|||||||
{
|
{
|
||||||
m_active_challenges.clear();
|
m_active_challenges.clear();
|
||||||
m_active_leaderboards.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_unlocked_badges.clear();
|
||||||
m_locked_badges.clear();
|
m_locked_badges.clear();
|
||||||
m_leaderboard_map.clear();
|
m_leaderboard_map.clear();
|
||||||
@ -415,7 +421,9 @@ void AchievementManager::Logout()
|
|||||||
{
|
{
|
||||||
std::lock_guard lg{m_lock};
|
std::lock_guard lg{m_lock};
|
||||||
CloseGame();
|
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, "");
|
Config::SetBaseOrCurrent(Config::RA_API_TOKEN, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,6 +508,55 @@ void AchievementManager::FilereaderClose(void* file_handle)
|
|||||||
delete static_cast<FilereaderState*>(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 AchievementManager::LoginCallback(int result, const char* error_message, rc_client_t* client,
|
||||||
void* userdata)
|
void* userdata)
|
||||||
{
|
{
|
||||||
@ -637,11 +694,8 @@ void AchievementManager::DisplayWelcomeMessage()
|
|||||||
m_display_welcome_message = false;
|
m_display_welcome_message = false;
|
||||||
const u32 color =
|
const u32 color =
|
||||||
rc_client_get_hardcore_enabled(m_client) ? OSD::Color::YELLOW : OSD::Color::CYAN;
|
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, &m_game_badge);
|
||||||
OSD::AddMessage("", OSD::Duration::VERY_LONG, OSD::Color::GREEN,
|
|
||||||
DecodeBadgeToOSDIcon(m_game_badge.badge));
|
|
||||||
}
|
|
||||||
auto info = rc_client_get_game_info(m_client);
|
auto info = rc_client_get_game_info(m_client);
|
||||||
if (!info)
|
if (!info)
|
||||||
{
|
{
|
||||||
@ -671,17 +725,13 @@ void AchievementManager::DisplayWelcomeMessage()
|
|||||||
|
|
||||||
void AchievementManager::HandleAchievementTriggeredEvent(const rc_client_event_t* client_event)
|
void AchievementManager::HandleAchievementTriggeredEvent(const rc_client_event_t* client_event)
|
||||||
{
|
{
|
||||||
|
const auto& instance = AchievementManager::GetInstance();
|
||||||
OSD::AddMessage(fmt::format("Unlocked: {} ({})", client_event->achievement->title,
|
OSD::AddMessage(fmt::format("Unlocked: {} ({})", client_event->achievement->title,
|
||||||
client_event->achievement->points),
|
client_event->achievement->points),
|
||||||
OSD::Duration::VERY_LONG,
|
OSD::Duration::VERY_LONG,
|
||||||
(rc_client_get_hardcore_enabled(AchievementManager::GetInstance().m_client)) ?
|
(rc_client_get_hardcore_enabled(instance.m_client)) ? OSD::Color::YELLOW :
|
||||||
OSD::Color::YELLOW :
|
OSD::Color::CYAN,
|
||||||
OSD::Color::CYAN,
|
&instance.GetAchievementBadge(client_event->achievement->id, false));
|
||||||
(Config::Get(Config::RA_BADGES_ENABLED)) ?
|
|
||||||
DecodeBadgeToOSDIcon(AchievementManager::GetInstance()
|
|
||||||
.m_unlocked_badges[client_event->achievement->id]
|
|
||||||
.badge) :
|
|
||||||
nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementManager::HandleLeaderboardStartedEvent(const rc_client_event_t* client_event)
|
void AchievementManager::HandleLeaderboardStartedEvent(const rc_client_event_t* client_event)
|
||||||
@ -738,16 +788,9 @@ void AchievementManager::HandleLeaderboardTrackerHideEvent(const rc_client_event
|
|||||||
void AchievementManager::HandleAchievementChallengeIndicatorShowEvent(
|
void AchievementManager::HandleAchievementChallengeIndicatorShowEvent(
|
||||||
const rc_client_event_t* client_event)
|
const rc_client_event_t* client_event)
|
||||||
{
|
{
|
||||||
if (Config::Get(Config::RA_BADGES_ENABLED))
|
auto& instance = AchievementManager::GetInstance();
|
||||||
{
|
instance.m_active_challenges[client_event->achievement->badge_name] =
|
||||||
auto& unlocked_badges = AchievementManager::GetInstance().m_unlocked_badges;
|
&AchievementManager::GetInstance().GetAchievementBadge(client_event->achievement->id, false);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementManager::HandleAchievementChallengeIndicatorHideEvent(
|
void AchievementManager::HandleAchievementChallengeIndicatorHideEvent(
|
||||||
@ -760,14 +803,11 @@ void AchievementManager::HandleAchievementChallengeIndicatorHideEvent(
|
|||||||
void AchievementManager::HandleAchievementProgressIndicatorShowEvent(
|
void AchievementManager::HandleAchievementProgressIndicatorShowEvent(
|
||||||
const rc_client_event_t* client_event)
|
const rc_client_event_t* client_event)
|
||||||
{
|
{
|
||||||
|
const auto& instance = AchievementManager::GetInstance();
|
||||||
OSD::AddMessage(fmt::format("{} {}", client_event->achievement->title,
|
OSD::AddMessage(fmt::format("{} {}", client_event->achievement->title,
|
||||||
client_event->achievement->measured_progress),
|
client_event->achievement->measured_progress),
|
||||||
OSD::Duration::SHORT, OSD::Color::GREEN,
|
OSD::Duration::SHORT, OSD::Color::GREEN,
|
||||||
(Config::Get(Config::RA_BADGES_ENABLED)) ?
|
&instance.GetAchievementBadge(client_event->achievement->id, false));
|
||||||
DecodeBadgeToOSDIcon(AchievementManager::GetInstance()
|
|
||||||
.m_unlocked_badges[client_event->achievement->id]
|
|
||||||
.badge) :
|
|
||||||
nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementManager::HandleGameCompletedEvent(const rc_client_event_t* client_event,
|
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,
|
OSD::AddMessage(fmt::format("Congratulations! {} has {} {}", user_info->display_name,
|
||||||
hardcore ? "mastered" : "completed", game_info->title),
|
hardcore ? "mastered" : "completed", game_info->title),
|
||||||
OSD::Duration::VERY_LONG, hardcore ? OSD::Color::YELLOW : OSD::Color::CYAN,
|
OSD::Duration::VERY_LONG, hardcore ? OSD::Color::YELLOW : OSD::Color::CYAN,
|
||||||
(Config::Get(Config::RA_BADGES_ENABLED)) ?
|
&AchievementManager::GetInstance().m_game_badge);
|
||||||
DecodeBadgeToOSDIcon(AchievementManager::GetInstance().m_game_badge.badge) :
|
|
||||||
nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementManager::HandleResetEvent(const rc_client_event_t* client_event)
|
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);
|
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,
|
void AchievementManager::Request(const rc_api_request_t* request,
|
||||||
rc_client_server_callback_t callback, void* callback_data,
|
rc_client_server_callback_t callback, void* callback_data,
|
||||||
rc_client_t* client)
|
rc_client_t* client)
|
||||||
@ -876,11 +900,11 @@ u32 AchievementManager::MemoryPeeker(u32 address, u8* buffer, u32 num_bytes, rc_
|
|||||||
return num_bytes;
|
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 AchievementManager::BadgeNameFunction function,
|
||||||
const UpdatedItems callback_data)
|
const UpdatedItems callback_data)
|
||||||
{
|
{
|
||||||
if (!m_client || !HasAPIToken() || !Config::Get(Config::RA_BADGES_ENABLED))
|
if (!m_client || !HasAPIToken())
|
||||||
{
|
{
|
||||||
m_update_callback(callback_data);
|
m_update_callback(callback_data);
|
||||||
if (m_display_welcome_message && badge_type == RC_IMAGE_TYPE_GAME)
|
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);
|
rc_api_destroy_request(&api_request);
|
||||||
fetched_badge = std::move(*http_response);
|
|
||||||
|
|
||||||
INFO_LOG_FMT(ACHIEVEMENTS, "Successfully downloaded badge id {}.", name_to_fetch);
|
INFO_LOG_FMT(ACHIEVEMENTS, "Successfully downloaded badge id {}.", name_to_fetch);
|
||||||
std::lock_guard lg{m_lock};
|
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);
|
INFO_LOG_FMT(ACHIEVEMENTS, "Requested outdated badge id {}.", name_to_fetch);
|
||||||
return;
|
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);
|
m_update_callback(callback_data);
|
||||||
});
|
});
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "Common/HttpRequest.h"
|
#include "Common/HttpRequest.h"
|
||||||
#include "Common/WorkQueueThread.h"
|
#include "Common/WorkQueueThread.h"
|
||||||
#include "DiscIO/Volume.h"
|
#include "DiscIO/Volume.h"
|
||||||
|
#include "VideoCommon/Assets/CustomTextureData.h"
|
||||||
|
|
||||||
namespace Core
|
namespace Core
|
||||||
{
|
{
|
||||||
@ -29,11 +30,6 @@ class CPUThreadGuard;
|
|||||||
class System;
|
class System;
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|
||||||
namespace OSD
|
|
||||||
{
|
|
||||||
struct Icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
class AchievementManager
|
class AchievementManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -47,16 +43,14 @@ public:
|
|||||||
using LeaderboardRank = u32;
|
using LeaderboardRank = u32;
|
||||||
static constexpr size_t RP_SIZE = 256;
|
static constexpr size_t RP_SIZE = 256;
|
||||||
using RichPresence = std::array<char, RP_SIZE>;
|
using RichPresence = std::array<char, RP_SIZE>;
|
||||||
using Badge = std::vector<u8>;
|
using Badge = VideoCommon::CustomTextureData::ArraySlice::Level;
|
||||||
using NamedIconMap = std::map<std::string, std::unique_ptr<OSD::Icon>, std::less<>>;
|
using NamedBadgeMap = std::unordered_map<std::string, const Badge*>;
|
||||||
static constexpr size_t MAX_DISPLAYED_LBOARDS = 4;
|
static constexpr size_t MAX_DISPLAYED_LBOARDS = 4;
|
||||||
|
|
||||||
struct BadgeStatus
|
static constexpr std::string_view DEFAULT_PLAYER_BADGE_FILENAME = "achievements_player.png";
|
||||||
{
|
static constexpr std::string_view DEFAULT_GAME_BADGE_FILENAME = "achievements_game.png";
|
||||||
std::string name = "";
|
static constexpr std::string_view DEFAULT_LOCKED_BADGE_FILENAME = "achievements_locked.png";
|
||||||
Badge badge{};
|
static constexpr std::string_view DEFAULT_UNLOCKED_BADGE_FILENAME = "achievements_unlocked.png";
|
||||||
};
|
|
||||||
|
|
||||||
static constexpr std::string_view GRAY = "transparent";
|
static constexpr std::string_view GRAY = "transparent";
|
||||||
static constexpr std::string_view GOLD = "#FFD700";
|
static constexpr std::string_view GOLD = "#FFD700";
|
||||||
static constexpr std::string_view BLUE = "#0B71C1";
|
static constexpr std::string_view BLUE = "#0B71C1";
|
||||||
@ -108,15 +102,15 @@ public:
|
|||||||
void SetSpectatorMode();
|
void SetSpectatorMode();
|
||||||
std::string_view GetPlayerDisplayName() const;
|
std::string_view GetPlayerDisplayName() const;
|
||||||
u32 GetPlayerScore() const;
|
u32 GetPlayerScore() const;
|
||||||
const BadgeStatus& GetPlayerBadge() const;
|
const Badge& GetPlayerBadge() const;
|
||||||
std::string_view GetGameDisplayName() const;
|
std::string_view GetGameDisplayName() const;
|
||||||
rc_client_t* GetClient();
|
rc_client_t* GetClient();
|
||||||
rc_api_fetch_game_data_response_t* GetGameData();
|
rc_api_fetch_game_data_response_t* GetGameData();
|
||||||
const BadgeStatus& GetGameBadge() const;
|
const Badge& GetGameBadge() const;
|
||||||
const BadgeStatus& GetAchievementBadge(AchievementId id, bool locked) const;
|
const Badge& GetAchievementBadge(AchievementId id, bool locked) const;
|
||||||
const LeaderboardStatus* GetLeaderboardInfo(AchievementId leaderboard_id);
|
const LeaderboardStatus* GetLeaderboardInfo(AchievementId leaderboard_id);
|
||||||
RichPresence GetRichPresence() const;
|
RichPresence GetRichPresence() const;
|
||||||
const NamedIconMap& GetChallengeIcons() const;
|
const NamedBadgeMap& GetChallengeIcons() const;
|
||||||
std::vector<std::string> GetActiveLeaderboards() const;
|
std::vector<std::string> GetActiveLeaderboards() const;
|
||||||
|
|
||||||
void DoState(PointerWrap& p);
|
void DoState(PointerWrap& p);
|
||||||
@ -134,8 +128,6 @@ private:
|
|||||||
std::unique_ptr<DiscIO::Volume> volume;
|
std::unique_ptr<DiscIO::Volume> volume;
|
||||||
};
|
};
|
||||||
|
|
||||||
const BadgeStatus m_default_badge;
|
|
||||||
|
|
||||||
static void* FilereaderOpenByFilepath(const char* path_utf8);
|
static void* FilereaderOpenByFilepath(const char* path_utf8);
|
||||||
static void* FilereaderOpenByVolume(const char* path_utf8);
|
static void* FilereaderOpenByVolume(const char* path_utf8);
|
||||||
static void FilereaderSeek(void* file_handle, int64_t offset, int origin);
|
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 size_t FilereaderRead(void* file_handle, void* buffer, size_t requested_bytes);
|
||||||
static void FilereaderClose(void* file_handle);
|
static void FilereaderClose(void* file_handle);
|
||||||
|
|
||||||
|
void LoadDefaultBadges();
|
||||||
static void LoginCallback(int result, const char* error_message, rc_client_t* client,
|
static void LoginCallback(int result, const char* error_message, rc_client_t* client,
|
||||||
void* userdata);
|
void* userdata);
|
||||||
|
|
||||||
@ -177,7 +170,7 @@ private:
|
|||||||
static void Request(const rc_api_request_t* request, rc_client_server_callback_t callback,
|
static void Request(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(Badge* badge, u32 badge_type, const BadgeNameFunction function,
|
||||||
const UpdatedItems callback_data);
|
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);
|
||||||
|
|
||||||
@ -187,20 +180,24 @@ private:
|
|||||||
bool m_is_runtime_initialized = false;
|
bool m_is_runtime_initialized = false;
|
||||||
UpdateCallback m_update_callback = [](const UpdatedItems&) {};
|
UpdateCallback m_update_callback = [](const UpdatedItems&) {};
|
||||||
std::unique_ptr<DiscIO::Volume> m_loading_volume;
|
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{};
|
Hash m_game_hash{};
|
||||||
u32 m_game_id = 0;
|
u32 m_game_id = 0;
|
||||||
rc_api_fetch_game_data_response_t m_game_data{};
|
rc_api_fetch_game_data_response_t m_game_data{};
|
||||||
bool m_is_game_loaded = false;
|
bool m_is_game_loaded = false;
|
||||||
BadgeStatus m_game_badge;
|
Badge m_game_badge;
|
||||||
bool m_display_welcome_message = false;
|
bool m_display_welcome_message = false;
|
||||||
std::unordered_map<AchievementId, BadgeStatus> m_unlocked_badges;
|
std::unordered_map<AchievementId, Badge> m_unlocked_badges;
|
||||||
std::unordered_map<AchievementId, BadgeStatus> m_locked_badges;
|
std::unordered_map<AchievementId, Badge> m_locked_badges;
|
||||||
RichPresence m_rich_presence;
|
RichPresence m_rich_presence;
|
||||||
std::chrono::steady_clock::time_point m_last_rp_time = std::chrono::steady_clock::now();
|
std::chrono::steady_clock::time_point m_last_rp_time = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
std::unordered_map<AchievementId, LeaderboardStatus> m_leaderboard_map;
|
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;
|
std::vector<rc_client_leaderboard_tracker_t> m_active_leaderboards;
|
||||||
|
|
||||||
Common::WorkQueueThread<std::function<void()>> m_queue;
|
Common::WorkQueueThread<std::function<void()>> m_queue;
|
||||||
|
@ -26,7 +26,6 @@ const Info<bool> RA_DISCORD_PRESENCE_ENABLED{
|
|||||||
{System::Achievements, "Achievements", "DiscordPresenceEnabled"}, false};
|
{System::Achievements, "Achievements", "DiscordPresenceEnabled"}, false};
|
||||||
const Info<bool> RA_PROGRESS_ENABLED{{System::Achievements, "Achievements", "ProgressEnabled"},
|
const Info<bool> RA_PROGRESS_ENABLED{{System::Achievements, "Achievements", "ProgressEnabled"},
|
||||||
false};
|
false};
|
||||||
const Info<bool> RA_BADGES_ENABLED{{System::Achievements, "Achievements", "BadgesEnabled"}, false};
|
|
||||||
} // namespace Config
|
} // namespace Config
|
||||||
|
|
||||||
#endif // USE_RETRO_ACHIEVEMENTS
|
#endif // USE_RETRO_ACHIEVEMENTS
|
||||||
|
@ -20,7 +20,6 @@ extern const Info<bool> RA_ENCORE_ENABLED;
|
|||||||
extern const Info<bool> RA_SPECTATOR_ENABLED;
|
extern const Info<bool> RA_SPECTATOR_ENABLED;
|
||||||
extern const Info<bool> RA_DISCORD_PRESENCE_ENABLED;
|
extern const Info<bool> RA_DISCORD_PRESENCE_ENABLED;
|
||||||
extern const Info<bool> RA_PROGRESS_ENABLED;
|
extern const Info<bool> RA_PROGRESS_ENABLED;
|
||||||
extern const Info<bool> RA_BADGES_ENABLED;
|
|
||||||
} // namespace Config
|
} // namespace Config
|
||||||
|
|
||||||
#endif // USE_RETRO_ACHIEVEMENTS
|
#endif // USE_RETRO_ACHIEVEMENTS
|
||||||
|
@ -61,22 +61,11 @@ void AchievementBox::UpdateData()
|
|||||||
color = AchievementManager::GOLD;
|
color = AchievementManager::GOLD;
|
||||||
else if (m_achievement->unlocked & RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE)
|
else if (m_achievement->unlocked & RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE)
|
||||||
color = AchievementManager::BLUE;
|
color = AchievementManager::BLUE;
|
||||||
if (Config::Get(Config::RA_BADGES_ENABLED) && badge.name != "")
|
QImage i_badge(&badge.data.front(), badge.width, badge.height, QImage::Format_RGBA8888);
|
||||||
{
|
m_badge->setPixmap(
|
||||||
QImage i_badge{};
|
QPixmap::fromImage(i_badge).scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||||
if (i_badge.loadFromData(&badge.badge.front(), static_cast<int>(badge.badge.size())))
|
m_badge->adjustSize();
|
||||||
{
|
m_badge->setStyleSheet(QStringLiteral("border: 4px solid %1").arg(QtUtils::FromStdString(color)));
|
||||||
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({});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_achievement->state == RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED)
|
if (m_achievement->state == RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED)
|
||||||
{
|
{
|
||||||
|
@ -68,24 +68,20 @@ void AchievementHeaderWidget::UpdateData()
|
|||||||
|
|
||||||
QString user_name = QtUtils::FromStdString(instance.GetPlayerDisplayName());
|
QString user_name = QtUtils::FromStdString(instance.GetPlayerDisplayName());
|
||||||
QString game_name = QtUtils::FromStdString(instance.GetGameDisplayName());
|
QString game_name = QtUtils::FromStdString(instance.GetGameDisplayName());
|
||||||
AchievementManager::BadgeStatus player_badge = instance.GetPlayerBadge();
|
const AchievementManager::Badge& player_badge = instance.GetPlayerBadge();
|
||||||
AchievementManager::BadgeStatus game_badge = instance.GetGameBadge();
|
const AchievementManager::Badge& game_badge = instance.GetGameBadge();
|
||||||
|
|
||||||
m_user_icon->setVisible(false);
|
m_user_icon->setVisible(false);
|
||||||
m_user_icon->clear();
|
m_user_icon->clear();
|
||||||
m_user_icon->setText({});
|
m_user_icon->setText({});
|
||||||
if (Config::Get(Config::RA_BADGES_ENABLED) && !player_badge.name.empty())
|
QImage i_user_icon(&player_badge.data.front(), player_badge.width, player_badge.height,
|
||||||
{
|
QImage::Format_RGBA8888);
|
||||||
QImage i_user_icon{};
|
m_user_icon->setPixmap(QPixmap::fromImage(i_user_icon)
|
||||||
if (i_user_icon.loadFromData(&player_badge.badge.front(), (int)player_badge.badge.size()))
|
.scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||||
{
|
m_user_icon->adjustSize();
|
||||||
m_user_icon->setPixmap(QPixmap::fromImage(i_user_icon)
|
m_user_icon->setStyleSheet(QStringLiteral("border: 4px solid transparent"));
|
||||||
.scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
m_user_icon->setVisible(true);
|
||||||
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->setVisible(false);
|
||||||
m_game_icon->clear();
|
m_game_icon->clear();
|
||||||
m_game_icon->setText({});
|
m_game_icon->setText({});
|
||||||
@ -94,26 +90,19 @@ void AchievementHeaderWidget::UpdateData()
|
|||||||
{
|
{
|
||||||
rc_client_user_game_summary_t game_summary;
|
rc_client_user_game_summary_t game_summary;
|
||||||
rc_client_get_user_game_summary(instance.GetClient(), &game_summary);
|
rc_client_get_user_game_summary(instance.GetClient(), &game_summary);
|
||||||
|
QImage i_game_icon(&game_badge.data.front(), game_badge.width, game_badge.height,
|
||||||
if (Config::Get(Config::RA_BADGES_ENABLED) && !game_badge.name.empty())
|
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{};
|
color = instance.IsHardcoreModeActive() ? AchievementManager::GOLD : AchievementManager::BLUE;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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_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")
|
m_points->setText(tr("%1 has unlocked %2/%3 achievements worth %4/%5 points")
|
||||||
|
@ -105,11 +105,6 @@ void AchievementSettingsWidget::CreateLayout()
|
|||||||
tr("Enable progress notifications on achievements.<br><br>Displays a brief popup message "
|
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, "
|
"whenever the player makes progress on an achievement that tracks an accumulated value, "
|
||||||
"such as 60 out of 120 stars."));
|
"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_integration_enabled_input);
|
||||||
m_common_layout->addWidget(m_common_username_label);
|
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);
|
m_common_layout->addWidget(m_common_discord_presence_enabled_input);
|
||||||
#endif // USE_DISCORD_PRESENCE
|
#endif // USE_DISCORD_PRESENCE
|
||||||
m_common_layout->addWidget(m_common_progress_enabled_input);
|
m_common_layout->addWidget(m_common_progress_enabled_input);
|
||||||
m_common_layout->addWidget(m_common_badges_enabled_input);
|
|
||||||
|
|
||||||
m_common_layout->setAlignment(Qt::AlignTop);
|
m_common_layout->setAlignment(Qt::AlignTop);
|
||||||
setLayout(m_common_layout);
|
setLayout(m_common_layout);
|
||||||
@ -153,8 +147,6 @@ void AchievementSettingsWidget::ConnectWidgets()
|
|||||||
&AchievementSettingsWidget::ToggleDiscordPresence);
|
&AchievementSettingsWidget::ToggleDiscordPresence);
|
||||||
connect(m_common_progress_enabled_input, &QCheckBox::toggled, this,
|
connect(m_common_progress_enabled_input, &QCheckBox::toggled, this,
|
||||||
&AchievementSettingsWidget::ToggleProgress);
|
&AchievementSettingsWidget::ToggleProgress);
|
||||||
connect(m_common_badges_enabled_input, &QCheckBox::toggled, this,
|
|
||||||
&AchievementSettingsWidget::ToggleBadges);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementSettingsWidget::OnControllerInterfaceConfigure()
|
void AchievementSettingsWidget::OnControllerInterfaceConfigure()
|
||||||
@ -214,9 +206,6 @@ void AchievementSettingsWidget::LoadSettings()
|
|||||||
SignalBlocking(m_common_progress_enabled_input)
|
SignalBlocking(m_common_progress_enabled_input)
|
||||||
->setChecked(Config::Get(Config::RA_PROGRESS_ENABLED));
|
->setChecked(Config::Get(Config::RA_PROGRESS_ENABLED));
|
||||||
SignalBlocking(m_common_progress_enabled_input)->setEnabled(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()
|
void AchievementSettingsWidget::SaveSettings()
|
||||||
@ -235,7 +224,6 @@ void AchievementSettingsWidget::SaveSettings()
|
|||||||
m_common_discord_presence_enabled_input->isChecked());
|
m_common_discord_presence_enabled_input->isChecked());
|
||||||
Config::SetBaseOrCurrent(Config::RA_PROGRESS_ENABLED,
|
Config::SetBaseOrCurrent(Config::RA_PROGRESS_ENABLED,
|
||||||
m_common_progress_enabled_input->isChecked());
|
m_common_progress_enabled_input->isChecked());
|
||||||
Config::SetBaseOrCurrent(Config::RA_BADGES_ENABLED, m_common_badges_enabled_input->isChecked());
|
|
||||||
Config::Save();
|
Config::Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,11 +296,4 @@ void AchievementSettingsWidget::ToggleProgress()
|
|||||||
SaveSettings();
|
SaveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementSettingsWidget::ToggleBadges()
|
|
||||||
{
|
|
||||||
SaveSettings();
|
|
||||||
AchievementManager::GetInstance().FetchPlayerBadge();
|
|
||||||
AchievementManager::GetInstance().FetchGameBadges();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // USE_RETRO_ACHIEVEMENTS
|
#endif // USE_RETRO_ACHIEVEMENTS
|
||||||
|
@ -38,7 +38,6 @@ private:
|
|||||||
void ToggleSpectator();
|
void ToggleSpectator();
|
||||||
void ToggleDiscordPresence();
|
void ToggleDiscordPresence();
|
||||||
void ToggleProgress();
|
void ToggleProgress();
|
||||||
void ToggleBadges();
|
|
||||||
|
|
||||||
QGroupBox* m_common_box;
|
QGroupBox* m_common_box;
|
||||||
QVBoxLayout* m_common_layout;
|
QVBoxLayout* m_common_layout;
|
||||||
@ -56,7 +55,6 @@ private:
|
|||||||
ToolTipCheckBox* m_common_spectator_enabled_input;
|
ToolTipCheckBox* m_common_spectator_enabled_input;
|
||||||
ToolTipCheckBox* m_common_discord_presence_enabled_input;
|
ToolTipCheckBox* m_common_discord_presence_enabled_input;
|
||||||
ToolTipCheckBox* m_common_progress_enabled_input;
|
ToolTipCheckBox* m_common_progress_enabled_input;
|
||||||
ToolTipCheckBox* m_common_badges_enabled_input;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // USE_RETRO_ACHIEVEMENTS
|
#endif // USE_RETRO_ACHIEVEMENTS
|
||||||
|
@ -574,6 +574,14 @@ bool LoadPNGTexture(CustomTextureData::ArraySlice::Level* level, const std::stri
|
|||||||
std::vector<u8> buffer(file.GetSize());
|
std::vector<u8> buffer(file.GetSize());
|
||||||
file.ReadBytes(buffer.data(), 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))
|
if (!Common::LoadPNG(buffer, &level->data, &level->width, &level->height))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -33,4 +33,5 @@ bool LoadDDSTexture(CustomTextureData* texture, const std::string& filename);
|
|||||||
bool LoadDDSTexture(CustomTextureData::ArraySlice::Level* level, const std::string& filename,
|
bool LoadDDSTexture(CustomTextureData::ArraySlice::Level* level, const std::string& filename,
|
||||||
u32 mip_level);
|
u32 mip_level);
|
||||||
bool LoadPNGTexture(CustomTextureData::ArraySlice::Level* level, const std::string& filename);
|
bool LoadPNGTexture(CustomTextureData::ArraySlice::Level* level, const std::string& filename);
|
||||||
|
bool LoadPNGTexture(CustomTextureData::ArraySlice::Level* level, const std::vector<u8>& buffer);
|
||||||
} // namespace VideoCommon
|
} // namespace VideoCommon
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "VideoCommon/AbstractGfx.h"
|
#include "VideoCommon/AbstractGfx.h"
|
||||||
#include "VideoCommon/AbstractTexture.h"
|
#include "VideoCommon/AbstractTexture.h"
|
||||||
|
#include "VideoCommon/Assets/CustomTextureData.h"
|
||||||
#include "VideoCommon/TextureConfig.h"
|
#include "VideoCommon/TextureConfig.h"
|
||||||
|
|
||||||
namespace OSD
|
namespace OSD
|
||||||
@ -36,8 +37,9 @@ static std::atomic<int> s_obscured_pixels_top = 0;
|
|||||||
struct Message
|
struct Message
|
||||||
{
|
{
|
||||||
Message() = default;
|
Message() = default;
|
||||||
Message(std::string text_, u32 duration_, u32 color_, std::unique_ptr<Icon> icon_ = nullptr)
|
Message(std::string text_, u32 duration_, u32 color_,
|
||||||
: text(std::move(text_)), duration(duration_), color(color_), icon(std::move(icon_))
|
const VideoCommon::CustomTextureData::ArraySlice::Level* icon_ = nullptr)
|
||||||
|
: text(std::move(text_)), duration(duration_), color(color_), icon(icon_)
|
||||||
{
|
{
|
||||||
timer.Start();
|
timer.Start();
|
||||||
}
|
}
|
||||||
@ -48,7 +50,7 @@ struct Message
|
|||||||
bool ever_drawn = false;
|
bool ever_drawn = false;
|
||||||
bool should_discard = false;
|
bool should_discard = false;
|
||||||
u32 color = 0;
|
u32 color = 0;
|
||||||
std::unique_ptr<Icon> icon;
|
const VideoCommon::CustomTextureData::ArraySlice::Level* icon;
|
||||||
std::unique_ptr<AbstractTexture> texture;
|
std::unique_ptr<AbstractTexture> texture;
|
||||||
};
|
};
|
||||||
static std::multimap<MessageType, Message> s_messages;
|
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);
|
msg.texture = g_gfx->CreateTexture(tex_config);
|
||||||
if (msg.texture)
|
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);
|
sizeof(u32) * width * height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// don't try again next time
|
// 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,
|
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};
|
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)));
|
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};
|
std::lock_guard lock{s_messages_mutex};
|
||||||
s_messages.emplace(MessageType::Typeless, Message(std::move(message), ms, argb, std::move(icon)));
|
s_messages.emplace(MessageType::Typeless, Message(std::move(message), ms, argb, std::move(icon)));
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
|
#include "VideoCommon/Assets/CustomTextureData.h"
|
||||||
|
|
||||||
namespace OSD
|
namespace OSD
|
||||||
{
|
{
|
||||||
enum class MessageType
|
enum class MessageType
|
||||||
@ -37,18 +39,12 @@ constexpr u32 NORMAL = 5000;
|
|||||||
constexpr u32 VERY_LONG = 10000;
|
constexpr u32 VERY_LONG = 10000;
|
||||||
}; // namespace Duration
|
}; // 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)
|
// On-screen message display (colored yellow by default)
|
||||||
void AddMessage(std::string message, u32 ms = Duration::SHORT, u32 argb = Color::YELLOW,
|
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,
|
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.
|
// Draw the current messages on the screen. Only call once per frame.
|
||||||
void DrawMessages();
|
void DrawMessages();
|
||||||
|
@ -358,7 +358,7 @@ void OnScreenUI::DrawChallengesAndLeaderboards()
|
|||||||
TextureConfig tex_config(width, height, 1, 1, 1, AbstractTextureFormat::RGBA8, 0,
|
TextureConfig tex_config(width, height, 1, 1, 1, AbstractTextureFormat::RGBA8, 0,
|
||||||
AbstractTextureType::Texture_2DArray);
|
AbstractTextureType::Texture_2DArray);
|
||||||
auto res = m_challenge_texture_map.insert_or_assign(name, g_gfx->CreateTexture(tex_config));
|
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);
|
sizeof(u32) * width * height);
|
||||||
}
|
}
|
||||||
for (auto& [name, texture] : m_challenge_texture_map)
|
for (auto& [name, texture] : m_challenge_texture_map)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user