mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-01-17 22:25:37 +00:00
Achievements: Show primed/challenge-in-progress achievements
This commit is contained in:
parent
a55ca69b87
commit
cba4bb4ab2
|
@ -9,7 +9,8 @@ namespace Achievements {
|
||||||
#ifdef WITH_CHEEVOS
|
#ifdef WITH_CHEEVOS
|
||||||
|
|
||||||
// Implemented in Host.
|
// Implemented in Host.
|
||||||
extern bool Reset();
|
extern bool ConfirmSystemReset();
|
||||||
|
extern void ResetRuntime();
|
||||||
extern bool DoState(StateWrapper& sw);
|
extern bool DoState(StateWrapper& sw);
|
||||||
extern void GameChanged(const std::string& path, CDImage* image);
|
extern void GameChanged(const std::string& path, CDImage* image);
|
||||||
|
|
||||||
|
@ -28,10 +29,11 @@ extern bool ChallengeModeActive();
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// Make noops when compiling without cheevos.
|
// Make noops when compiling without cheevos.
|
||||||
static inline bool Reset()
|
static inline bool ConfirmSystemReset()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
static inline void ResetRuntime() {}
|
||||||
static inline bool DoState(StateWrapper& sw)
|
static inline bool DoState(StateWrapper& sw)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -898,6 +898,11 @@ void System::ResetSystem()
|
||||||
if (!IsValid())
|
if (!IsValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef WITH_CHEEVOS
|
||||||
|
if (!Achievements::ConfirmSystemReset())
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
InternalReset();
|
InternalReset();
|
||||||
ResetPerformanceCounters();
|
ResetPerformanceCounters();
|
||||||
ResetThrottler();
|
ResetThrottler();
|
||||||
|
@ -1650,7 +1655,7 @@ bool System::DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool u
|
||||||
{
|
{
|
||||||
#ifdef WITH_CHEEVOS
|
#ifdef WITH_CHEEVOS
|
||||||
// loading an old state without cheevos, so reset the runtime
|
// loading an old state without cheevos, so reset the runtime
|
||||||
Achievements::Reset();
|
Achievements::ResetRuntime();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1686,7 +1691,7 @@ void System::InternalReset()
|
||||||
ResetPerformanceCounters();
|
ResetPerformanceCounters();
|
||||||
|
|
||||||
#ifdef WITH_CHEEVOS
|
#ifdef WITH_CHEEVOS
|
||||||
Achievements::Reset();
|
Achievements::ResetRuntime();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
g_gpu->ResetGraphicsAPIState();
|
g_gpu->ResetGraphicsAPIState();
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "util/cd_image.h"
|
#include "util/cd_image.h"
|
||||||
#include "util/state_wrapper.h"
|
#include "util/state_wrapper.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <atomic>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
@ -60,6 +61,10 @@ static unsigned PeekMemory(unsigned address, unsigned num_bytes, void* ud);
|
||||||
static void ActivateLockedAchievements();
|
static void ActivateLockedAchievements();
|
||||||
static bool ActivateAchievement(Achievement* achievement);
|
static bool ActivateAchievement(Achievement* achievement);
|
||||||
static void DeactivateAchievement(Achievement* achievement);
|
static void DeactivateAchievement(Achievement* achievement);
|
||||||
|
static void UnlockAchievement(u32 achievement_id, bool add_notification = true);
|
||||||
|
static void AchievementPrimed(u32 achievement_id);
|
||||||
|
static void AchievementUnprimed(u32 achievement_id);
|
||||||
|
static void SubmitLeaderboard(u32 leaderboard_id, int value);
|
||||||
static void SendPing();
|
static void SendPing();
|
||||||
static void SendPlaying();
|
static void SendPlaying();
|
||||||
static void UpdateRichPresence();
|
static void UpdateRichPresence();
|
||||||
|
@ -115,6 +120,7 @@ static std::string s_game_title;
|
||||||
static std::string s_game_icon;
|
static std::string s_game_icon;
|
||||||
static std::vector<Achievements::Achievement> s_achievements;
|
static std::vector<Achievements::Achievement> s_achievements;
|
||||||
static std::vector<Achievements::Leaderboard> s_leaderboards;
|
static std::vector<Achievements::Leaderboard> s_leaderboards;
|
||||||
|
static std::atomic<u32> s_primed_achievement_count{0};
|
||||||
|
|
||||||
static bool s_has_rich_presence = false;
|
static bool s_has_rich_presence = false;
|
||||||
static std::string s_rich_presence_string;
|
static std::string s_rich_presence_string;
|
||||||
|
@ -328,6 +334,7 @@ void Achievements::ClearGameInfo(bool clear_achievements, bool clear_leaderboard
|
||||||
DeactivateAchievement(&ach);
|
DeactivateAchievement(&ach);
|
||||||
s_achievements.pop_back();
|
s_achievements.pop_back();
|
||||||
}
|
}
|
||||||
|
s_primed_achievement_count.store(0, std::memory_order_release);
|
||||||
}
|
}
|
||||||
if (clear_leaderboards)
|
if (clear_leaderboards)
|
||||||
{
|
{
|
||||||
|
@ -459,7 +466,7 @@ void Achievements::UpdateSettings(const Settings& old_config)
|
||||||
if (!g_settings.achievements_enabled)
|
if (!g_settings.achievements_enabled)
|
||||||
{
|
{
|
||||||
// we're done here
|
// we're done here
|
||||||
Shutdown();
|
OnSystemShutdown();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,7 +498,7 @@ void Achievements::UpdateSettings(const Settings& old_config)
|
||||||
g_settings.achievements_use_first_disc_from_playlist != old_config.achievements_use_first_disc_from_playlist ||
|
g_settings.achievements_use_first_disc_from_playlist != old_config.achievements_use_first_disc_from_playlist ||
|
||||||
g_settings.achievements_rich_presence != old_config.achievements_rich_presence)
|
g_settings.achievements_rich_presence != old_config.achievements_rich_presence)
|
||||||
{
|
{
|
||||||
Shutdown();
|
OnSystemShutdown();
|
||||||
Initialize();
|
Initialize();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -584,7 +591,7 @@ void Achievements::SetChallengeMode(bool enabled)
|
||||||
GetUserUnlocks();
|
GetUserUnlocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Achievements::Shutdown()
|
bool Achievements::OnSystemShutdown()
|
||||||
{
|
{
|
||||||
#ifdef WITH_RAINTEGRATION
|
#ifdef WITH_RAINTEGRATION
|
||||||
if (IsUsingRAIntegration())
|
if (IsUsingRAIntegration())
|
||||||
|
@ -619,29 +626,35 @@ bool Achievements::Shutdown()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Achievements::Reset()
|
bool Achievements::ConfirmSystemReset()
|
||||||
|
{
|
||||||
|
#ifdef WITH_RAINTEGRATION
|
||||||
|
if (IsUsingRAIntegration())
|
||||||
|
return RA_ConfirmLoadNewRom(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Achievements::ResetRuntime()
|
||||||
{
|
{
|
||||||
#ifdef WITH_RAINTEGRATION
|
#ifdef WITH_RAINTEGRATION
|
||||||
if (IsUsingRAIntegration())
|
if (IsUsingRAIntegration())
|
||||||
{
|
{
|
||||||
if (!RA_ConfirmLoadNewRom(false))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
RA_OnReset();
|
RA_OnReset();
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!s_active)
|
if (!s_active)
|
||||||
return true;
|
return;
|
||||||
|
|
||||||
std::unique_lock lock(s_achievements_mutex);
|
std::unique_lock lock(s_achievements_mutex);
|
||||||
Log_DevPrint("Resetting rcheevos state...");
|
Log_DevPrint("Resetting rcheevos state...");
|
||||||
rc_runtime_reset(&s_rcheevos_runtime);
|
rc_runtime_reset(&s_rcheevos_runtime);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Achievements::OnPaused(bool paused)
|
void Achievements::OnSystemPaused(bool paused)
|
||||||
{
|
{
|
||||||
#ifdef WITH_RAINTEGRATION
|
#ifdef WITH_RAINTEGRATION
|
||||||
if (IsUsingRAIntegration())
|
if (IsUsingRAIntegration())
|
||||||
|
@ -1131,6 +1144,7 @@ void Achievements::GetPatchesCallback(s32 status_code, std::string content_type,
|
||||||
cheevo.badge_name = defn.badge_name;
|
cheevo.badge_name = defn.badge_name;
|
||||||
cheevo.locked = true;
|
cheevo.locked = true;
|
||||||
cheevo.active = false;
|
cheevo.active = false;
|
||||||
|
cheevo.primed = false;
|
||||||
cheevo.points = defn.points;
|
cheevo.points = defn.points;
|
||||||
cheevo.category = static_cast<AchievementCategory>(defn.category);
|
cheevo.category = static_cast<AchievementCategory>(defn.category);
|
||||||
s_achievements.push_back(std::move(cheevo));
|
s_achievements.push_back(std::move(cheevo));
|
||||||
|
@ -1352,7 +1366,9 @@ void Achievements::GameChanged(const std::string& path, CDImage* image)
|
||||||
|
|
||||||
if (s_http_downloader->HasAnyRequests())
|
if (s_http_downloader->HasAnyRequests())
|
||||||
{
|
{
|
||||||
Host::DisplayLoadingScreen("Downloading achievements data...");
|
if (image && System::IsValid())
|
||||||
|
Host::DisplayLoadingScreen("Downloading achievements data...");
|
||||||
|
|
||||||
s_http_downloader->WaitForAllRequests();
|
s_http_downloader->WaitForAllRequests();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1655,6 +1671,12 @@ void Achievements::DeactivateAchievement(Achievement* achievement)
|
||||||
rc_runtime_deactivate_achievement(&s_rcheevos_runtime, achievement->id);
|
rc_runtime_deactivate_achievement(&s_rcheevos_runtime, achievement->id);
|
||||||
achievement->active = false;
|
achievement->active = false;
|
||||||
|
|
||||||
|
if (achievement->primed)
|
||||||
|
{
|
||||||
|
achievement->primed = false;
|
||||||
|
s_primed_achievement_count.fetch_sub(std::memory_order_acq_rel);
|
||||||
|
}
|
||||||
|
|
||||||
Log_DevPrintf("Deactivated achievement %s (%u)", achievement->title.c_str(), achievement->id);
|
Log_DevPrintf("Deactivated achievement %s (%u)", achievement->title.c_str(), achievement->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1711,6 +1733,8 @@ void Achievements::SubmitLeaderboardCallback(s32 status_code, std::string conten
|
||||||
|
|
||||||
void Achievements::UnlockAchievement(u32 achievement_id, bool add_notification /* = true*/)
|
void Achievements::UnlockAchievement(u32 achievement_id, bool add_notification /* = true*/)
|
||||||
{
|
{
|
||||||
|
std::unique_lock lock(s_achievements_mutex);
|
||||||
|
|
||||||
Achievement* achievement = GetMutableAchievementByID(achievement_id);
|
Achievement* achievement = GetMutableAchievementByID(achievement_id);
|
||||||
if (!achievement)
|
if (!achievement)
|
||||||
{
|
{
|
||||||
|
@ -1783,6 +1807,8 @@ void Achievements::SubmitLeaderboard(u32 leaderboard_id, int value)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_lock lock(s_achievements_mutex);
|
||||||
|
|
||||||
s_submitting_lboard_id = leaderboard_id;
|
s_submitting_lboard_id = leaderboard_id;
|
||||||
|
|
||||||
RAPIRequest<rc_api_submit_lboard_entry_request_t, rc_api_init_submit_lboard_entry_request> request;
|
RAPIRequest<rc_api_submit_lboard_entry_request_t, rc_api_init_submit_lboard_entry_request> request;
|
||||||
|
@ -1794,6 +1820,28 @@ void Achievements::SubmitLeaderboard(u32 leaderboard_id, int value)
|
||||||
request.Send(SubmitLeaderboardCallback);
|
request.Send(SubmitLeaderboardCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Achievements::AchievementPrimed(u32 achievement_id)
|
||||||
|
{
|
||||||
|
std::unique_lock lock(s_achievements_mutex);
|
||||||
|
Achievement* achievement = GetMutableAchievementByID(achievement_id);
|
||||||
|
if (!achievement || achievement->primed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
achievement->primed = true;
|
||||||
|
s_primed_achievement_count.fetch_add(std::memory_order_acq_rel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Achievements::AchievementUnprimed(u32 achievement_id)
|
||||||
|
{
|
||||||
|
std::unique_lock lock(s_achievements_mutex);
|
||||||
|
Achievement* achievement = GetMutableAchievementByID(achievement_id);
|
||||||
|
if (!achievement || !achievement->primed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
achievement->primed = false;
|
||||||
|
s_primed_achievement_count.fetch_sub(std::memory_order_acq_rel);
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<u32, u32> Achievements::GetAchievementProgress(const Achievement& achievement)
|
std::pair<u32, u32> Achievements::GetAchievementProgress(const Achievement& achievement)
|
||||||
{
|
{
|
||||||
std::pair<u32, u32> result;
|
std::pair<u32, u32> result;
|
||||||
|
@ -1841,6 +1889,12 @@ std::string Achievements::GetAchievementBadgeURL(const Achievement& achievement)
|
||||||
return request.GetURL();
|
return request.GetURL();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 Achievements::GetPrimedAchievementCount()
|
||||||
|
{
|
||||||
|
// Relaxed is fine here, worst that happens is we draw the triggers one frame late.
|
||||||
|
return s_primed_achievement_count.load(std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
void Achievements::CheevosEventHandler(const rc_runtime_event_t* runtime_event)
|
void Achievements::CheevosEventHandler(const rc_runtime_event_t* runtime_event)
|
||||||
{
|
{
|
||||||
static const char* events[] = {"RC_RUNTIME_EVENT_ACHIEVEMENT_ACTIVATED", "RC_RUNTIME_EVENT_ACHIEVEMENT_PAUSED",
|
static const char* events[] = {"RC_RUNTIME_EVENT_ACHIEVEMENT_ACTIVATED", "RC_RUNTIME_EVENT_ACHIEVEMENT_PAUSED",
|
||||||
|
@ -1853,10 +1907,27 @@ void Achievements::CheevosEventHandler(const rc_runtime_event_t* runtime_event)
|
||||||
((unsigned)runtime_event->type >= countof(events)) ? "unknown" : events[(unsigned)runtime_event->type];
|
((unsigned)runtime_event->type >= countof(events)) ? "unknown" : events[(unsigned)runtime_event->type];
|
||||||
Log_DevPrintf("Cheevos Event %s for %u", event_text, runtime_event->id);
|
Log_DevPrintf("Cheevos Event %s for %u", event_text, runtime_event->id);
|
||||||
|
|
||||||
if (runtime_event->type == RC_RUNTIME_EVENT_ACHIEVEMENT_TRIGGERED)
|
switch (runtime_event->type)
|
||||||
UnlockAchievement(runtime_event->id);
|
{
|
||||||
else if (runtime_event->type == RC_RUNTIME_EVENT_LBOARD_TRIGGERED)
|
case RC_RUNTIME_EVENT_ACHIEVEMENT_TRIGGERED:
|
||||||
SubmitLeaderboard(runtime_event->id, runtime_event->value);
|
UnlockAchievement(runtime_event->id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RC_RUNTIME_EVENT_ACHIEVEMENT_PRIMED:
|
||||||
|
AchievementPrimed(runtime_event->id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RC_RUNTIME_EVENT_ACHIEVEMENT_UNPRIMED:
|
||||||
|
AchievementUnprimed(runtime_event->id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RC_RUNTIME_EVENT_LBOARD_TRIGGERED:
|
||||||
|
SubmitLeaderboard(runtime_event->id, runtime_event->value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Achievements::PeekMemory(unsigned address, unsigned num_bytes, void* ud)
|
unsigned Achievements::PeekMemory(unsigned address, unsigned num_bytes, void* ud)
|
||||||
|
|
|
@ -13,7 +13,7 @@ class CDImage;
|
||||||
class StateWrapper;
|
class StateWrapper;
|
||||||
|
|
||||||
namespace Achievements {
|
namespace Achievements {
|
||||||
enum class AchievementCategory : u32
|
enum class AchievementCategory : u8
|
||||||
{
|
{
|
||||||
Local = 0,
|
Local = 0,
|
||||||
Core = 3,
|
Core = 3,
|
||||||
|
@ -36,6 +36,7 @@ struct Achievement
|
||||||
AchievementCategory category;
|
AchievementCategory category;
|
||||||
bool locked;
|
bool locked;
|
||||||
bool active;
|
bool active;
|
||||||
|
bool primed;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Leaderboard
|
struct Leaderboard
|
||||||
|
@ -85,13 +86,13 @@ void Initialize();
|
||||||
void UpdateSettings(const Settings& old_config);
|
void UpdateSettings(const Settings& old_config);
|
||||||
|
|
||||||
/// Called when the system is being reset. If it returns false, the reset should be aborted.
|
/// Called when the system is being reset. If it returns false, the reset should be aborted.
|
||||||
bool Reset();
|
bool ConfirmSystemReset();
|
||||||
|
|
||||||
/// Called when the system is being shut down. If Shutdown() returns false, the shutdown should be aborted.
|
/// Called when the system is being shut down. If Shutdown() returns false, the shutdown should be aborted.
|
||||||
bool Shutdown();
|
bool OnSystemShutdown();
|
||||||
|
|
||||||
/// Called when the system is being paused and resumed.
|
/// Called when the system is being paused and resumed.
|
||||||
void OnPaused(bool paused);
|
void OnSystemPaused(bool paused);
|
||||||
|
|
||||||
/// Called once a frame at vsync time on the CPU thread.
|
/// Called once a frame at vsync time on the CPU thread.
|
||||||
void FrameUpdate();
|
void FrameUpdate();
|
||||||
|
@ -141,6 +142,7 @@ std::optional<bool> TryEnumerateLeaderboardEntries(u32 id, std::function<bool(co
|
||||||
const Leaderboard* GetLeaderboardByID(u32 id);
|
const Leaderboard* GetLeaderboardByID(u32 id);
|
||||||
u32 GetLeaderboardCount();
|
u32 GetLeaderboardCount();
|
||||||
bool IsLeaderboardTimeType(const Leaderboard& leaderboard);
|
bool IsLeaderboardTimeType(const Leaderboard& leaderboard);
|
||||||
|
u32 GetPrimedAchievementCount();
|
||||||
|
|
||||||
const Achievement* GetAchievementByID(u32 id);
|
const Achievement* GetAchievementByID(u32 id);
|
||||||
std::pair<u32, u32> GetAchievementProgress(const Achievement& achievement);
|
std::pair<u32, u32> GetAchievementProgress(const Achievement& achievement);
|
||||||
|
@ -148,9 +150,6 @@ std::string GetAchievementProgressText(const Achievement& achievement);
|
||||||
const std::string& GetAchievementBadgePath(const Achievement& achievement, bool download_if_missing = true);
|
const std::string& GetAchievementBadgePath(const Achievement& achievement, bool download_if_missing = true);
|
||||||
std::string GetAchievementBadgeURL(const Achievement& achievement);
|
std::string GetAchievementBadgeURL(const Achievement& achievement);
|
||||||
|
|
||||||
void UnlockAchievement(u32 achievement_id, bool add_notification = true);
|
|
||||||
void SubmitLeaderboard(u32 leaderboard_id, int value);
|
|
||||||
|
|
||||||
#ifdef WITH_RAINTEGRATION
|
#ifdef WITH_RAINTEGRATION
|
||||||
void SwitchToRAIntegration();
|
void SwitchToRAIntegration();
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ void CommonHost::Shutdown()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_CHEEVOS
|
#ifdef WITH_CHEEVOS
|
||||||
Achievements::Shutdown();
|
Achievements::OnSystemShutdown();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
InputManager::CloseSources();
|
InputManager::CloseSources();
|
||||||
|
|
|
@ -430,6 +430,7 @@ static GameListPage s_game_list_page = GameListPage::Grid;
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
static void DrawAchievementsWindow();
|
static void DrawAchievementsWindow();
|
||||||
static void DrawAchievement(const Achievements::Achievement& cheevo);
|
static void DrawAchievement(const Achievements::Achievement& cheevo);
|
||||||
|
static void DrawPrimedAchievements();
|
||||||
static void DrawLeaderboardsWindow();
|
static void DrawLeaderboardsWindow();
|
||||||
static void DrawLeaderboardListEntry(const Achievements::Leaderboard& lboard);
|
static void DrawLeaderboardListEntry(const Achievements::Leaderboard& lboard);
|
||||||
static void DrawLeaderboardEntry(const Achievements::LeaderboardEntry& lbEntry, float rank_column_width,
|
static void DrawLeaderboardEntry(const Achievements::LeaderboardEntry& lbEntry, float rank_column_width,
|
||||||
|
@ -710,6 +711,12 @@ void FullscreenUI::Render()
|
||||||
|
|
||||||
ImGuiFullscreen::BeginLayout();
|
ImGuiFullscreen::BeginLayout();
|
||||||
|
|
||||||
|
#ifdef WITH_CHEEVOS
|
||||||
|
// Primed achievements must come first, because we don't want the pause screen to be behind them.
|
||||||
|
if (Achievements::GetPrimedAchievementCount() > 0)
|
||||||
|
DrawPrimedAchievements();
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (s_current_main_window)
|
switch (s_current_main_window)
|
||||||
{
|
{
|
||||||
case MainWindowType::Landing:
|
case MainWindowType::Landing:
|
||||||
|
@ -5556,6 +5563,37 @@ void FullscreenUI::DrawAchievementsWindow()
|
||||||
EndFullscreenWindow();
|
EndFullscreenWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FullscreenUI::DrawPrimedAchievements()
|
||||||
|
{
|
||||||
|
const ImVec2 image_size(LayoutScale(LAYOUT_MENU_BUTTON_HEIGHT, LAYOUT_MENU_BUTTON_HEIGHT));
|
||||||
|
const float spacing = LayoutScale(10.0f);
|
||||||
|
const float padding = LayoutScale(10.0f);
|
||||||
|
|
||||||
|
const ImGuiIO& io = ImGui::GetIO();
|
||||||
|
const float x_advance = image_size.x + spacing;
|
||||||
|
ImVec2 position(io.DisplaySize.x - padding - image_size.x, io.DisplaySize.y - padding - image_size.y);
|
||||||
|
|
||||||
|
auto lock = Achievements::GetLock();
|
||||||
|
Achievements::EnumerateAchievements(
|
||||||
|
[&image_size, &x_advance, &position](const Achievements::Achievement& achievement) {
|
||||||
|
if (!achievement.primed)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
const std::string& badge_path = Achievements::GetAchievementBadgePath(achievement);
|
||||||
|
if (badge_path.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
HostDisplayTexture* badge = GetCachedTextureAsync(badge_path.c_str());
|
||||||
|
if (!badge)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
ImDrawList* dl = ImGui::GetBackgroundDrawList();
|
||||||
|
dl->AddImage(badge->GetHandle(), position, position + image_size);
|
||||||
|
position.x -= x_advance;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
bool FullscreenUI::OpenLeaderboardsWindow()
|
bool FullscreenUI::OpenLeaderboardsWindow()
|
||||||
{
|
{
|
||||||
if (!System::IsValid() || !Achievements::HasActiveGame() || Achievements::GetLeaderboardCount() == 0 || !Initialize())
|
if (!System::IsValid() || !Achievements::HasActiveGame() || Achievements::GetLeaderboardCount() == 0 || !Initialize())
|
||||||
|
|
Loading…
Reference in a new issue