Achievements: Backports from PCSX2

This commit is contained in:
Stenzek 2023-09-18 22:29:47 +10:00
parent 4b24bf74f4
commit 846f74c86d
16 changed files with 234 additions and 208 deletions

View file

@ -121,11 +121,10 @@ static void ClearGameInfo();
static void ClearGameHash();
static std::string GetUserAgent();
static std::string GetGameHash(CDImage* image);
static void SetChallengeMode(bool enabled);
static void SetHardcoreMode(bool enabled);
static bool IsLoggedIn();
static void ShowLoginSuccess(const rc_client_t* client);
static void ShowLoginNotification();
static void CancelGameLoad();
static void IdentifyGame(const std::string& path, CDImage* image);
static void BeginLoadGame();
static void UpdateGameSummary();
@ -349,6 +348,11 @@ bool Achievements::HasAchievementsOrLeaderboards()
return s_has_achievements || s_has_leaderboards;
}
bool Achievements::HasAchievements()
{
return s_has_achievements;
}
bool Achievements::HasLeaderboards()
{
return s_has_leaderboards;
@ -389,7 +393,7 @@ bool Achievements::Initialize()
rc_client_set_event_handler(s_client, ClientEventHandler);
rc_client_set_hardcore_enabled(s_client, s_hardcore_mode);
rc_client_set_encore_mode_enabled(s_client, g_settings.achievements_spectator_mode);
rc_client_set_encore_mode_enabled(s_client, g_settings.achievements_encore_mode);
rc_client_set_unofficial_enabled(s_client, g_settings.achievements_unofficial_test_mode);
rc_client_set_spectator_mode_enabled(s_client, g_settings.achievements_spectator_mode);
@ -476,22 +480,35 @@ void Achievements::UpdateSettings(const Settings& old_config)
}
else if (!s_hardcore_mode && g_settings.achievements_hardcore_mode)
{
ImGuiFullscreen::ShowToast(std::string(),
TRANSLATE_STR("Achievements", "Hardcore mode will be enabled on system reset."),
Host::OSD_WARNING_DURATION);
if (HasActiveGame() && FullscreenUI::Initialize())
{
ImGuiFullscreen::ShowToast(std::string(),
TRANSLATE_STR("Achievements", "Hardcore mode will be enabled on system reset."),
Host::OSD_WARNING_DURATION);
}
}
}
// These cannot be modified while a game is loaded, so just toss state and reload.
if (HasActiveGame() &&
(g_settings.achievements_encore_mode != old_config.achievements_encore_mode ||
g_settings.achievements_spectator_mode != old_config.achievements_spectator_mode ||
g_settings.achievements_unofficial_test_mode != old_config.achievements_unofficial_test_mode ||
g_settings.achievements_use_first_disc_from_playlist != old_config.achievements_use_first_disc_from_playlist))
if (HasActiveGame())
{
Shutdown(false);
Initialize();
return;
if (g_settings.achievements_encore_mode != old_config.achievements_encore_mode ||
g_settings.achievements_spectator_mode != old_config.achievements_spectator_mode ||
g_settings.achievements_unofficial_test_mode != old_config.achievements_unofficial_test_mode)
{
Shutdown(false);
Initialize();
return;
}
}
else
{
if (g_settings.achievements_encore_mode != old_config.achievements_encore_mode)
rc_client_set_encore_mode_enabled(s_client, g_settings.achievements_encore_mode);
if (g_settings.achievements_spectator_mode != old_config.achievements_spectator_mode)
rc_client_set_spectator_mode_enabled(s_client, g_settings.achievements_spectator_mode);
if (g_settings.achievements_unofficial_test_mode != old_config.achievements_unofficial_test_mode)
rc_client_set_unofficial_enabled(s_client, g_settings.achievements_unofficial_test_mode);
}
// in case cache directory changed
@ -520,6 +537,7 @@ bool Achievements::Shutdown(bool allow_cancel)
ClearGameInfo();
ClearGameHash();
DisableHardcoreMode();
if (s_load_game_request)
{
@ -765,30 +783,6 @@ void Achievements::GameChanged(const std::string& path, CDImage* image)
IdentifyGame(path, image);
}
void Achievements::CancelGameLoad()
{
Log_ErrorPrint("Cancelling game load");
if (s_load_game_request)
{
rc_client_abort_async(s_client, s_load_game_request);
s_load_game_request = nullptr;
}
rc_client_unload_game(s_client);
ClearGameHash();
ClearGameInfo();
DisableHardcoreMode();
Host::OnAchievementsRefreshed();
#ifdef ENABLE_RAINTEGRATION
if (IsUsingRAIntegration())
{
RAIntegration::GameChanged();
return;
}
#endif
}
void Achievements::IdentifyGame(const std::string& path, CDImage* image)
{
if (s_game_path == path)
@ -804,24 +798,19 @@ void Achievements::IdentifyGame(const std::string& path, CDImage* image)
temp_image = CDImage::Open(path.c_str(), g_settings.cdrom_load_image_patches, nullptr);
image = temp_image.get();
if (!temp_image)
{
Log_ErrorPrintf("Failed to open temporary CD image '%s'", path.c_str());
CancelGameLoad();
return;
}
}
std::string game_hash;
if (image)
{
game_hash = GetGameHash(image);
if (s_game_hash == game_hash)
{
// only the path has changed - different format/save state/etc.
Log_InfoPrintf("Detected path change from '%s' to '%s'", s_game_path.c_str(), path.c_str());
s_game_path = path;
return;
}
if (s_game_hash == game_hash)
{
// only the path has changed - different format/save state/etc.
Log_InfoPrintf("Detected path change from '%s' to '%s'", s_game_path.c_str(), path.c_str());
s_game_path = path;
return;
}
ClearGameHash();
@ -843,6 +832,7 @@ void Achievements::IdentifyGame(const std::string& path, CDImage* image)
if (!IsLoggedIn())
{
Log_InfoPrintf("Skipping load game because we're not logged in.");
DisableHardcoreMode();
return;
}
@ -859,7 +849,6 @@ void Achievements::BeginLoadGame()
}
ClearGameInfo();
Host::OnAchievementsRefreshed();
if (s_game_hash.empty())
{
@ -870,7 +859,7 @@ void Achievements::BeginLoadGame()
"Failed to read executable from disc. Achievements disabled.", Host::OSD_ERROR_DURATION);
}
rc_client_unload_game(s_client);
DisableHardcoreMode();
return;
}
@ -881,10 +870,17 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
{
s_load_game_request = nullptr;
if (result != RC_OK)
if (result == RC_NO_GAME_LOADED)
{
// Unknown game.
Log_InfoPrintf("Unknown game '%s', disabling achievements.", s_game_hash.c_str());
DisableHardcoreMode();
return;
}
else if (result != RC_OK)
{
ReportFmtError("Loading game failed: {}", error_message);
SetChallengeMode(false);
DisableHardcoreMode();
return;
}
@ -892,7 +888,7 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
if (!info)
{
ReportError("rc_client_get_game_info() returned NULL");
SetChallengeMode(false);
DisableHardcoreMode();
return;
}
@ -935,6 +931,14 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
void Achievements::ClearGameInfo()
{
ClearUIState();
if (s_load_game_request)
{
rc_client_abort_async(s_client, s_load_game_request);
s_load_game_request = nullptr;
}
rc_client_unload_game(s_client);
s_active_leaderboard_trackers = {};
s_active_challenge_indicators = {};
s_active_progress_indicator.reset();
@ -946,6 +950,8 @@ void Achievements::ClearGameInfo()
s_has_rich_presence = false;
s_rich_presence_string = {};
s_game_summary = {};
Host::OnAchievementsRefreshed();
}
void Achievements::ClearGameHash()
@ -1014,8 +1020,8 @@ void Achievements::HandleUnlockEvent(const rc_client_event_t* event)
std::string badge_path = GetAchievementBadgePath(cheevo, cheevo->state);
ImGuiFullscreen::AddNotification(fmt::format("achievement_unlock_{}", cheevo->id),
g_settings.achievements_notification_duration, std::move(title),
cheevo->description, std::move(badge_path));
static_cast<float>(g_settings.achievements_notification_duration),
std::move(title), cheevo->description, std::move(badge_path));
}
if (g_settings.achievements_sound_effects)
@ -1075,21 +1081,22 @@ void Achievements::HandleLeaderboardSubmittedEvent(const rc_client_event_t* even
if (g_settings.achievements_leaderboard_notifications && FullscreenUI::Initialize())
{
static const char* value_strings[NUM_RC_CLIENT_LEADERBOARD_FORMATS] = {
TRANSLATE_NOOP("Achievements", "Your Time: {} (Submitting)"),
TRANSLATE_NOOP("Achievements", "Your Score: {} (Submitting)"),
TRANSLATE_NOOP("Achievements", "Your Value: {} (Submitting)"),
TRANSLATE_NOOP("Achievements", "Your Time: {}{}"),
TRANSLATE_NOOP("Achievements", "Your Score: {}{}"),
TRANSLATE_NOOP("Achievements", "Your Value: {}{}"),
};
std::string title = event->leaderboard->title;
std::string message =
fmt::format(fmt::runtime(Host::TranslateToStringView(
"Achievements",
value_strings[std::min<u8>(event->leaderboard->format, NUM_RC_CLIENT_LEADERBOARD_FORMATS - 1)])),
event->leaderboard->tracker_value ? event->leaderboard->tracker_value : "Unknown");
std::string message = fmt::format(
fmt::runtime(Host::TranslateToStringView(
"Achievements",
value_strings[std::min<u8>(event->leaderboard->format, NUM_RC_CLIENT_LEADERBOARD_FORMATS - 1)])),
event->leaderboard->tracker_value ? event->leaderboard->tracker_value : "Unknown",
g_settings.achievements_spectator_mode ? std::string_view() : TRANSLATE_SV("Achievements", " (Submitting)"));
ImGuiFullscreen::AddNotification(fmt::format("leaderboard_{}", event->leaderboard->id),
g_settings.achievements_leaderboard_duration, std::move(title), std::move(message),
s_game_icon);
static_cast<float>(g_settings.achievements_leaderboard_duration), std::move(title),
std::move(message), s_game_icon);
}
if (g_settings.achievements_sound_effects)
@ -1119,8 +1126,8 @@ void Achievements::HandleLeaderboardScoreboardEvent(const rc_client_event_t* eve
event->leaderboard_scoreboard->new_rank, event->leaderboard_scoreboard->num_entries);
ImGuiFullscreen::AddNotification(fmt::format("leaderboard_{}", event->leaderboard->id),
g_settings.achievements_leaderboard_duration, std::move(title), std::move(message),
s_game_icon);
static_cast<float>(g_settings.achievements_leaderboard_duration), std::move(title),
std::move(message), s_game_icon);
}
}
@ -1319,7 +1326,7 @@ void Achievements::DisableHardcoreMode()
#endif
if (s_hardcore_mode)
SetChallengeMode(false);
SetHardcoreMode(false);
}
bool Achievements::ResetHardcoreMode()
@ -1335,11 +1342,11 @@ bool Achievements::ResetHardcoreMode()
if (s_hardcore_mode == wanted_hardcore_mode)
return false;
SetChallengeMode(wanted_hardcore_mode);
SetHardcoreMode(wanted_hardcore_mode);
return true;
}
void Achievements::SetChallengeMode(bool enabled)
void Achievements::SetHardcoreMode(bool enabled)
{
if (enabled == s_hardcore_mode)
return;
@ -1347,7 +1354,7 @@ void Achievements::SetChallengeMode(bool enabled)
// new mode
s_hardcore_mode = enabled;
if (HasActiveGame())
if (HasActiveGame() && FullscreenUI::Initialize())
{
ImGuiFullscreen::ShowToast(std::string(),
enabled ? TRANSLATE_STR("Achievements", "Hardcore mode is now enabled.") :
@ -1363,7 +1370,7 @@ void Achievements::SetChallengeMode(bool enabled)
// Toss away UI state, because it's invalid now
ClearUIState();
Host::OnAchievementsHardcoreModeChanged();
Host::OnAchievementsHardcoreModeChanged(enabled);
}
bool Achievements::DoState(StateWrapper& sw)
@ -1693,11 +1700,7 @@ void Achievements::Logout()
const auto lock = GetLock();
if (HasActiveGame())
{
ClearGameInfo();
ClearGameHash();
Host::OnAchievementsRefreshed();
}
Log_InfoPrint("Logging out...");
rc_client_logout(s_client);
@ -1743,7 +1746,7 @@ bool Achievements::ConfirmHardcoreModeDisable(const char* trigger)
void Achievements::ClearUIState()
{
if (FullscreenUI::IsAchievementsWindowOpen() || FullscreenUI::IsLeaderboardsWindowOpen())
FullscreenUI::ReturnToMainWindow();
FullscreenUI::ReturnToPreviousWindow();
s_achievement_badge_paths = {};
@ -2008,9 +2011,6 @@ void Achievements::DrawAchievementsWindow()
auto lock = Achievements::GetLock();
// ensure image downloads still happen while we're paused
Achievements::IdleUpdate();
static constexpr float alpha = 0.8f;
static constexpr float heading_alpha = 0.95f;
static constexpr float heading_height_unscaled = 110.0f;
@ -2058,7 +2058,7 @@ void Achievements::DrawAchievementsWindow()
g_large_font) ||
ImGuiFullscreen::WantsToCloseMenu())
{
FullscreenUI::ReturnToMainWindow();
FullscreenUI::ReturnToPreviousWindow();
}
const ImRect title_bb(ImVec2(left, top), ImVec2(right, top + g_large_font->FontSize));
@ -2124,6 +2124,12 @@ void Achievements::DrawAchievementsWindow()
background, 0.0f, 0.0f, 0))
{
static bool buckets_collapsed[NUM_RC_CLIENT_ACHIEVEMENT_BUCKETS] = {};
static const char* bucket_names[NUM_RC_CLIENT_ACHIEVEMENT_BUCKETS] = {
TRANSLATE_NOOP("Achievements", "Unknown"), TRANSLATE_NOOP("Achievements", "Locked"),
TRANSLATE_NOOP("Achievements", "Unlocked"), TRANSLATE_NOOP("Achievements", "Unsupported"),
TRANSLATE_NOOP("Achievements", "Unofficial"), TRANSLATE_NOOP("Achievements", "Recently Unlocked"),
TRANSLATE_NOOP("Achievements", "Active Challenges"), TRANSLATE_NOOP("Achievements", "Almost There"),
};
ImGuiFullscreen::BeginMenuButtons();
@ -2140,10 +2146,11 @@ void Achievements::DrawAchievementsWindow()
DebugAssert(bucket.bucket_type < NUM_RC_CLIENT_ACHIEVEMENT_BUCKETS);
// TODO: This should be translated.
// TODO: Once subsets are supported, this will need to change.
bool& bucket_collapsed = buckets_collapsed[bucket.bucket_type];
bucket_collapsed ^= ImGuiFullscreen::MenuHeadingButton(bucket.label, bucket_collapsed ? ICON_FA_CHEVRON_DOWN :
ICON_FA_CHEVRON_UP);
bucket_collapsed ^=
ImGuiFullscreen::MenuHeadingButton(Host::TranslateToCString("Achievements", bucket_names[bucket.bucket_type]),
bucket_collapsed ? ICON_FA_CHEVRON_DOWN : ICON_FA_CHEVRON_UP);
if (!bucket_collapsed)
{
for (u32 i = 0; i < bucket.num_achievements; i++)
@ -2310,9 +2317,6 @@ void Achievements::DrawLeaderboardsWindow()
auto lock = Achievements::GetLock();
// ensure image downloads still happen while we're paused
Achievements::IdleUpdate();
const bool is_leaderboard_open = (s_open_leaderboard != nullptr);
bool close_leaderboard_on_exit = false;
@ -2381,7 +2385,7 @@ void Achievements::DrawLeaderboardsWindow()
g_large_font) ||
ImGuiFullscreen::WantsToCloseMenu())
{
FullscreenUI::ReturnToMainWindow();
FullscreenUI::ReturnToPreviousWindow();
}
}
else

View file

@ -91,6 +91,9 @@ u32 GetGameID();
/// Returns true if the current game has any achievements or leaderboards.
bool HasAchievementsOrLeaderboards();
/// Returns true if the current game has any leaderboards.
bool HasAchievements();
/// Returns true if the current game has any leaderboards.
bool HasLeaderboards();
@ -153,5 +156,5 @@ void OnAchievementsLoginSuccess(const char* display_name, u32 points, u32 sc_poi
void OnAchievementsRefreshed();
/// Called whenever hardcore mode is toggled.
void OnAchievementsHardcoreModeChanged();
void OnAchievementsHardcoreModeChanged(bool enabled);
} // namespace Host

View file

@ -217,11 +217,11 @@ static void CancelAsyncOps();
// Main
//////////////////////////////////////////////////////////////////////////
static void ToggleTheme();
static void PauseForMenuOpen();
static void PauseForMenuOpen(bool set_pause_menu_open);
static void ClosePauseMenu();
static void OpenPauseSubMenu(PauseSubMenu submenu);
static void DrawLandingWindow();
static void DrawPauseMenu(MainWindowType type);
static void DrawPauseMenu();
static void ExitFullscreenAndOpenURL(const std::string_view& url);
static void CopyTextToClipboard(std::string title, const std::string_view& text);
static void DrawAboutWindow();
@ -616,7 +616,7 @@ void FullscreenUI::CheckForConfigChanges(const Settings& old_settings)
if (old_settings.achievements_enabled && !g_settings.achievements_enabled)
{
if (s_current_main_window == MainWindowType::Achievements || s_current_main_window == MainWindowType::Leaderboards)
ReturnToMainWindow();
ReturnToPreviousWindow();
}
}
@ -647,6 +647,8 @@ void FullscreenUI::OnSystemDestroyed()
return;
s_pause_menu_was_open = false;
s_was_paused_on_quick_menu_open = false;
s_current_pause_submenu = PauseSubMenu::None;
SwitchToLanding();
}
@ -671,13 +673,13 @@ void FullscreenUI::ToggleTheme()
ImGuiFullscreen::SetTheme(new_light);
}
void FullscreenUI::PauseForMenuOpen()
void FullscreenUI::PauseForMenuOpen(bool set_pause_menu_open)
{
s_was_paused_on_quick_menu_open = (System::GetState() == System::State::Paused);
if (g_settings.pause_on_menu && !s_was_paused_on_quick_menu_open)
Host::RunOnCPUThread([]() { System::PauseSystem(true); });
s_pause_menu_was_open = true;
s_pause_menu_was_open |= set_pause_menu_open;
}
void FullscreenUI::OpenPauseMenu()
@ -688,7 +690,7 @@ void FullscreenUI::OpenPauseMenu()
if (!Initialize() || s_current_main_window != MainWindowType::None)
return;
PauseForMenuOpen();
PauseForMenuOpen(true);
s_current_main_window = MainWindowType::PauseMenu;
s_current_pause_submenu = PauseSubMenu::None;
QueueResetFocus();
@ -762,7 +764,7 @@ void FullscreenUI::Render()
DrawSettingsWindow();
break;
case MainWindowType::PauseMenu:
DrawPauseMenu(s_current_main_window);
DrawPauseMenu();
break;
case MainWindowType::Achievements:
Achievements::DrawAchievementsWindow();
@ -818,11 +820,22 @@ void FullscreenUI::InvalidateCoverCache()
Host::RunOnCPUThread([]() { s_cover_image_map.clear(); });
}
void FullscreenUI::ReturnToPreviousWindow()
{
if (System::IsValid() && s_pause_menu_was_open)
{
s_current_main_window = MainWindowType::PauseMenu;
QueueResetFocus();
}
else
{
ReturnToMainWindow();
}
}
void FullscreenUI::ReturnToMainWindow()
{
if (s_pause_menu_was_open)
ClosePauseMenu();
ClosePauseMenu();
s_current_main_window = System::IsValid() ? MainWindowType::None : MainWindowType::Landing;
}
@ -956,7 +969,7 @@ void FullscreenUI::DoChangeDiscFromFile()
QueueResetFocus();
CloseFileSelector();
ReturnToMainWindow();
ReturnToPreviousWindow();
};
OpenFileSelector(FSUI_ICONSTR(ICON_FA_COMPACT_DISC, "Select Disc Image"), false, std::move(callback),
@ -991,7 +1004,7 @@ void FullscreenUI::DoChangeDisc()
QueueResetFocus();
CloseChoiceDialog();
ReturnToMainWindow();
ReturnToPreviousWindow();
};
OpenChoiceDialog(FSUI_ICONSTR(ICON_FA_COMPACT_DISC, "Select Disc Image"), true, std::move(options),
@ -1055,7 +1068,7 @@ void FullscreenUI::DoCheatsMenu()
{
Host::AddKeyedOSDMessage("load_cheat_list",
fmt::format(FSUI_FSTR("No cheats found for {}."), System::GetGameTitle()), 10.0f);
ReturnToMainWindow();
ReturnToPreviousWindow();
return;
}
}
@ -1071,7 +1084,7 @@ void FullscreenUI::DoCheatsMenu()
auto callback = [](s32 index, const std::string& title, bool checked) {
if (index < 0)
{
ReturnToMainWindow();
ReturnToPreviousWindow();
return;
}
@ -2537,7 +2550,7 @@ void FullscreenUI::DrawSettingsWindow()
}
if (NavButton(ICON_FA_BACKWARD, true, true))
ReturnToMainWindow();
ReturnToPreviousWindow();
if (s_game_settings_entry)
NavTitle(s_game_settings_entry->title.c_str());
@ -2568,7 +2581,7 @@ void FullscreenUI::DrawSettingsWindow()
if (WantsToCloseMenu())
{
if (ImGui::IsWindowFocused())
ReturnToMainWindow();
ReturnToPreviousWindow();
}
auto lock = Host::GetSettingsLock();
@ -4429,10 +4442,6 @@ void FullscreenUI::DrawAchievementsSettingsPage()
}
#endif
const auto lock = Achievements::GetLock();
if (Achievements::IsActive() && !System::IsRunning())
Achievements::IdleUpdate();
SettingsInterface* bsi = GetEditingSettingsInterface();
BeginMenuButtons();
@ -4443,7 +4452,6 @@ void FullscreenUI::DrawAchievementsSettingsPage()
"Cheevos", "Enabled", false);
const bool enabled = bsi->GetBoolValue("Cheevos", "Enabled", false);
const bool hardcore = bsi->GetBoolValue("Cheevos", "ChallengeMode", false);
if (DrawToggleSetting(
bsi, FSUI_ICONSTR(ICON_FA_HARD_HAT, "Hardcore Mode"),
@ -4460,7 +4468,7 @@ void FullscreenUI::DrawAchievementsSettingsPage()
"Notifications", true, enabled);
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_LIST_OL, "Leaderboard Notifications"),
FSUI_CSTR("Displays popup messages when starting, submitting, or failing a leaderboard challenge."),
"Cheevos", "LeaderboardNotifications", true, enabled && hardcore);
"Cheevos", "LeaderboardNotifications", true, enabled);
DrawToggleSetting(
bsi, FSUI_ICONSTR(ICON_FA_HEADPHONES, "Sound Effects"),
FSUI_CSTR("Plays sound effects for events such as achievement unlocks and leaderboard submissions."), "Cheevos",
@ -4518,6 +4526,8 @@ void FullscreenUI::DrawAchievementsSettingsPage()
MenuHeading(FSUI_CSTR("Current Game"));
if (Achievements::HasActiveGame())
{
const auto lock = Achievements::GetLock();
ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImGui::GetStyle().Colors[ImGuiCol_Text]);
ActiveButton(SmallString::FromFmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_BOOKMARK, "Game: {} ({})")),
Achievements::GetGameID(), Achievements::GetGameTitle()),
@ -4656,7 +4666,7 @@ void FullscreenUI::DrawAdvancedSettingsPage()
EndMenuButtons();
}
void FullscreenUI::DrawPauseMenu(MainWindowType type)
void FullscreenUI::DrawPauseMenu()
{
SmallString buffer;
@ -4779,6 +4789,9 @@ void FullscreenUI::DrawPauseMenu(MainWindowType type)
// NOTE: Menu close must come first, because otherwise VM destruction options will race.
const bool has_game = System::IsValid() && !System::GetGameSerial().empty();
if (just_focused)
ImGui::SetFocusID(ImGui::GetID(FSUI_ICONSTR(ICON_FA_PLAY, "Resume Game")), ImGui::GetCurrentWindow());
if (ActiveButton(FSUI_ICONSTR(ICON_FA_PLAY, "Resume Game"), false) || WantsToCloseMenu())
ClosePauseMenu();
@ -4819,7 +4832,7 @@ void FullscreenUI::DrawPauseMenu(MainWindowType type)
}
if (ActiveButton(FSUI_ICONSTR(ICON_FA_TROPHY, "Achievements"), false,
Achievements::HasActiveGame() && Achievements::HasAchievementsOrLeaderboards()))
Achievements::HasAchievementsOrLeaderboards()))
{
// skip second menu and go straight to cheevos if there's no lbs
if (!Achievements::HasLeaderboards())
@ -4857,14 +4870,14 @@ void FullscreenUI::DrawPauseMenu(MainWindowType type)
case PauseSubMenu::Exit:
{
if (just_focused)
{
ImGui::SetFocusID(ImGui::GetID(FSUI_ICONSTR(ICON_FA_POWER_OFF, "Exit Without Saving")),
ImGui::GetCurrentWindow());
if (ActiveButton(FSUI_ICONSTR(ICON_FA_BACKWARD, "Back To Pause Menu"), false))
{
OpenPauseSubMenu(PauseSubMenu::None);
}
if (ActiveButton(FSUI_ICONSTR(ICON_FA_BACKWARD, "Back To Pause Menu"), false) || WantsToCloseMenu())
OpenPauseSubMenu(PauseSubMenu::None);
if (ActiveButton(FSUI_ICONSTR(ICON_FA_SYNC, "Reset System"), false))
{
ClosePauseMenu();
@ -4881,7 +4894,13 @@ void FullscreenUI::DrawPauseMenu(MainWindowType type)
case PauseSubMenu::Achievements:
{
if (ActiveButton(FSUI_ICONSTR(ICON_FA_BACKWARD, "Back To Pause Menu"), false))
if (just_focused)
{
ImGui::SetFocusID(ImGui::GetID(FSUI_ICONSTR(ICON_FA_BACKWARD, "Back To Pause Menu")),
ImGui::GetCurrentWindow());
}
if (ActiveButton(FSUI_ICONSTR(ICON_FA_BACKWARD, "Back To Pause Menu"), false) || WantsToCloseMenu())
OpenPauseSubMenu(PauseSubMenu::None);
if (ActiveButton(FSUI_ICONSTR(ICON_FA_TROPHY, "Achievements"), false))
@ -5057,8 +5076,6 @@ void FullscreenUI::CloseSaveStateSelector()
s_save_state_selector_loading = false;
s_save_state_selector_resuming = false;
s_save_state_selector_game_path = {};
if (s_current_main_window != MainWindowType::GameList)
ReturnToMainWindow();
}
void FullscreenUI::DrawSaveStateSelector(bool is_loading)
@ -5089,7 +5106,10 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading)
ImGui::PopStyleVar(5);
if (!is_open)
{
CloseSaveStateSelector();
ReturnToPreviousWindow();
}
return;
}
@ -5102,7 +5122,10 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading)
{
BeginNavBar();
if (NavButton(ICON_FA_BACKWARD, true, true))
{
CloseSaveStateSelector();
ReturnToPreviousWindow();
}
NavTitle(is_loading ? FSUI_CSTR("Load State") : FSUI_CSTR("Save State"));
EndNavBar();
@ -5206,12 +5229,14 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading)
{
DoLoadState(entry.path);
CloseSaveStateSelector();
ReturnToPreviousWindow();
break;
}
else
{
DoSaveState(entry.slot, entry.global);
CloseSaveStateSelector();
ReturnToPreviousWindow();
break;
}
}
@ -5268,6 +5293,7 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading)
DoSaveState(entry.slot, entry.global);
CloseSaveStateSelector();
ReturnToPreviousWindow();
closed = true;
}
@ -5287,6 +5313,7 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading)
if (s_save_state_selector_slots.empty())
{
CloseSaveStateSelector();
ReturnToPreviousWindow();
closed = true;
}
else
@ -5352,7 +5379,10 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading)
ImGui::PopStyleVar(5);
if (!close_handled && WantsToCloseMenu())
{
CloseSaveStateSelector();
ReturnToPreviousWindow();
}
}
bool FullscreenUI::OpenLoadStateSelectorForGameResume(const GameList::Entry* entry)
@ -5599,7 +5629,7 @@ void FullscreenUI::DrawGameListWindow()
}
if (NavButton(ICON_FA_BACKWARD, true, true))
ReturnToMainWindow();
ReturnToPreviousWindow();
NavTitle(Host::TranslateToCString(TR_CONTEXT, titles[static_cast<u32>(s_game_list_page)]));
RightAlignNavButtons(count, ITEM_WIDTH, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
@ -5851,7 +5881,7 @@ void FullscreenUI::DrawGameGrid(const ImVec2& heading_size)
if (WantsToCloseMenu())
{
if (ImGui::IsWindowFocused())
ReturnToMainWindow();
ReturnToPreviousWindow();
}
ResetFocusHere();
@ -6018,7 +6048,7 @@ void FullscreenUI::DrawGameListSettingsPage(const ImVec2& heading_size)
if (WantsToCloseMenu())
{
if (ImGui::IsWindowFocused())
ReturnToMainWindow();
ReturnToPreviousWindow();
}
auto lock = Host::GetSettingsLock();
@ -6459,20 +6489,29 @@ bool FullscreenUI::DrawConfirmWindow(const char* message, bool* result)
return !is_open;
}
bool FullscreenUI::OpenAchievementsWindow()
void FullscreenUI::OpenAchievementsWindow()
{
if (!System::IsValid() || !Achievements::HasActiveGame() || !Initialize() ||
!Achievements::PrepareAchievementsWindow())
if (!Achievements::IsActive())
{
return false;
Host::AddKeyedOSDMessage("achievements_disabled", FSUI_STR("Achievements are not enabled."),
Host::OSD_INFO_DURATION);
return;
}
if (!System::IsValid() || !Initialize())
return;
if (!Achievements::HasAchievements() || !Achievements::PrepareAchievementsWindow())
{
ShowToast(std::string(), FSUI_STR("This game has no achievements."));
return;
}
if (s_current_main_window != MainWindowType::PauseMenu)
PauseForMenuOpen();
PauseForMenuOpen(false);
s_current_main_window = MainWindowType::Achievements;
QueueResetFocus();
return true;
}
bool FullscreenUI::IsAchievementsWindowOpen()
@ -6480,17 +6519,29 @@ bool FullscreenUI::IsAchievementsWindowOpen()
return (s_current_main_window == MainWindowType::Achievements);
}
bool FullscreenUI::OpenLeaderboardsWindow()
void FullscreenUI::OpenLeaderboardsWindow()
{
if (!Achievements::HasLeaderboards() || !Initialize() || !Achievements::PrepareLeaderboardsWindow())
return false;
if (!Achievements::IsActive())
{
Host::AddKeyedOSDMessage("achievements_disabled", FSUI_STR("Leaderboards are not enabled."),
Host::OSD_INFO_DURATION);
return;
}
if (!System::IsValid() || !Initialize())
return;
if (!Achievements::HasLeaderboards() || !Achievements::PrepareLeaderboardsWindow())
{
ShowToast(std::string(), FSUI_STR("This game has no leaderboards."));
return;
}
if (s_current_main_window != MainWindowType::PauseMenu)
PauseForMenuOpen();
PauseForMenuOpen(false);
s_current_main_window = MainWindowType::Leaderboards;
QueueResetFocus();
return true;
}
bool FullscreenUI::IsLeaderboardsWindowOpen()

View file

@ -22,11 +22,12 @@ void OnSystemResumed();
void OnSystemDestroyed();
void OnRunningGameChanged();
void OpenPauseMenu();
bool OpenAchievementsWindow();
void OpenAchievementsWindow();
bool IsAchievementsWindowOpen();
bool OpenLeaderboardsWindow();
void OpenLeaderboardsWindow();
bool IsLeaderboardsWindowOpen();
void ReturnToMainWindow();
void ReturnToPreviousWindow();
void Shutdown();
void Render();

View file

@ -164,25 +164,13 @@ DEFINE_HOTKEY("Screenshot", TRANSLATE_NOOP("Hotkeys", "General"), TRANSLATE_NOOP
DEFINE_HOTKEY("OpenAchievements", TRANSLATE_NOOP("Hotkeys", "General"),
TRANSLATE_NOOP("Hotkeys", "Open Achievement List"), [](s32 pressed) {
if (!pressed)
{
if (!FullscreenUI::OpenAchievementsWindow())
{
Host::AddOSDMessage(
TRANSLATE_STR("OSDMessage", "Achievements are disabled or unavailable for game."), 10.0f);
}
}
FullscreenUI::OpenAchievementsWindow();
})
DEFINE_HOTKEY("OpenLeaderboards", TRANSLATE_NOOP("Hotkeys", "General"),
TRANSLATE_NOOP("Hotkeys", "Open Leaderboard List"), [](s32 pressed) {
if (!pressed)
{
if (!FullscreenUI::OpenLeaderboardsWindow())
{
Host::AddOSDMessage(
TRANSLATE_STR("OSDMessage", "Leaderboards are disabled or unavailable for game."), 10.0f);
}
}
FullscreenUI::OpenLeaderboardsWindow();
})
#endif // !defined(__ANDROID__)

View file

@ -376,9 +376,9 @@ void Settings::Load(SettingsInterface& si)
achievements_use_first_disc_from_playlist = si.GetBoolValue("Cheevos", "UseFirstDiscFromPlaylist", true);
achievements_use_raintegration = si.GetBoolValue("Cheevos", "UseRAIntegration", false);
achievements_notification_duration =
si.GetFloatValue("Cheevos", "NotificationsDuration", DEFAULT_ACHIEVEMENT_NOTIFICATION_TIME);
si.GetIntValue("Cheevos", "NotificationsDuration", DEFAULT_ACHIEVEMENT_NOTIFICATION_TIME);
achievements_leaderboard_duration =
si.GetFloatValue("Cheevos", "LeaderboardsDuration", DEFAULT_LEADERBOARD_NOTIFICATION_TIME);
si.GetIntValue("Cheevos", "LeaderboardsDuration", DEFAULT_LEADERBOARD_NOTIFICATION_TIME);
log_level = ParseLogLevelName(si.GetStringValue("Logging", "LogLevel", GetLogLevelName(DEFAULT_LOG_LEVEL)).c_str())
.value_or(DEFAULT_LOG_LEVEL);
@ -578,8 +578,8 @@ void Settings::Save(SettingsInterface& si) const
si.SetBoolValue("Cheevos", "UnofficialTestMode", achievements_unofficial_test_mode);
si.SetBoolValue("Cheevos", "UseFirstDiscFromPlaylist", achievements_use_first_disc_from_playlist);
si.SetBoolValue("Cheevos", "UseRAIntegration", achievements_use_raintegration);
si.SetFloatValue("Cheevos", "NotificationsDuration", achievements_notification_duration);
si.SetFloatValue("Cheevos", "LeaderboardsDuration", achievements_leaderboard_duration);
si.SetIntValue("Cheevos", "NotificationsDuration", achievements_notification_duration);
si.SetIntValue("Cheevos", "LeaderboardsDuration", achievements_leaderboard_duration);
si.SetStringValue("Logging", "LogLevel", GetLogLevelName(log_level));
si.SetStringValue("Logging", "LogFilter", log_filter.c_str());

View file

@ -190,8 +190,8 @@ struct Settings
bool achievements_unofficial_test_mode = false;
bool achievements_use_first_disc_from_playlist = true;
bool achievements_use_raintegration = false;
float achievements_notification_duration = DEFAULT_ACHIEVEMENT_NOTIFICATION_TIME;
float achievements_leaderboard_duration = DEFAULT_LEADERBOARD_NOTIFICATION_TIME;
s32 achievements_notification_duration = DEFAULT_ACHIEVEMENT_NOTIFICATION_TIME;
s32 achievements_leaderboard_duration = DEFAULT_LEADERBOARD_NOTIFICATION_TIME;
struct DebugSettings
{
@ -475,8 +475,8 @@ struct Settings
static constexpr MemoryCardType DEFAULT_MEMORY_CARD_2_TYPE = MemoryCardType::None;
static constexpr MultitapMode DEFAULT_MULTITAP_MODE = MultitapMode::Disabled;
static constexpr float DEFAULT_ACHIEVEMENT_NOTIFICATION_TIME = 10.0f;
static constexpr float DEFAULT_LEADERBOARD_NOTIFICATION_TIME = 10.0f;
static constexpr s32 DEFAULT_ACHIEVEMENT_NOTIFICATION_TIME = 5;
static constexpr s32 DEFAULT_LEADERBOARD_NOTIFICATION_TIME = 10;
static constexpr LOGLEVEL DEFAULT_LOG_LEVEL = LOGLEVEL_INFO;

View file

@ -4752,31 +4752,15 @@ void System::UpdateDiscordPresence()
rp.largeImageKey = "duckstation_logo";
rp.largeImageText = "DuckStation PS1/PSX Emulator";
rp.startTimestamp = std::time(nullptr);
rp.details = System::IsValid() ? System::GetGameTitle().c_str() : "No Game Running";
SmallString details_string;
if (!System::IsShutdown())
{
details_string.AppendFormattedString("%s (%s)", System::GetGameTitle().c_str(), System::GetGameSerial().c_str());
}
else
{
details_string.AppendString("No Game Running");
}
SmallString state_string;
std::string state_string;
if (Achievements::HasRichPresence())
{
const auto lock = Achievements::GetLock();
const std::string_view richp = Achievements::GetRichPresenceString();
if (richp.length() >= 128)
state_string.AppendFmtString("{}...", richp.substr(0, 124));
else
state_string.Assign(richp);
rp.state = state_string;
state_string = StringUtil::Ellipsise(Achievements::GetRichPresenceString(), 128);
rp.state = state_string.c_str();
}
rp.details = details_string;
Discord_UpdatePresence(&rp);
}

View file

@ -766,7 +766,7 @@ void Host::OnAchievementsRefreshed()
// noop
}
void Host::OnAchievementsHardcoreModeChanged()
void Host::OnAchievementsHardcoreModeChanged(bool enabled)
{
// noop
}

View file

@ -159,16 +159,16 @@ void AchievementSettingsWidget::onHardcoreModeStateChanged()
void AchievementSettingsWidget::onAchievementsNotificationDurationSliderChanged()
{
const float duration = m_dialog->getEffectiveFloatValue("Cheevos", "NotificationsDuration",
Settings::DEFAULT_ACHIEVEMENT_NOTIFICATION_TIME);
m_ui.achievementNotificationsDurationLabel->setText(tr("%n seconds", nullptr, static_cast<int>(duration)));
const int duration =
m_dialog->getEffectiveIntValue("Cheevos", "NotificationsDuration", Settings::DEFAULT_ACHIEVEMENT_NOTIFICATION_TIME);
m_ui.achievementNotificationsDurationLabel->setText(tr("%n seconds", nullptr, duration));
}
void AchievementSettingsWidget::onLeaderboardsNotificationDurationSliderChanged()
{
const float duration = m_dialog->getEffectiveFloatValue("Cheevos", "LeaderboardsDuration",
Settings::DEFAULT_ACHIEVEMENT_NOTIFICATION_TIME);
m_ui.leaderboardNotificationsDurationLabel->setText(tr("%n seconds", nullptr, static_cast<int>(duration)));
const int duration =
m_dialog->getEffectiveIntValue("Cheevos", "LeaderboardsDuration", Settings::DEFAULT_LEADERBOARD_NOTIFICATION_TIME);
m_ui.leaderboardNotificationsDurationLabel->setText(tr("%n seconds", nullptr, duration));
}
void AchievementSettingsWidget::updateLoginState()

View file

@ -2657,10 +2657,9 @@ void MainWindow::onAchievementsLoginSucceeded(const QString& display_name, quint
m_ui.statusBar->showMessage(message);
}
void MainWindow::onAchievementsChallengeModeChanged()
void MainWindow::onAchievementsChallengeModeChanged(bool enabled)
{
const bool active = Achievements::IsHardcoreModeActive();
if (active)
if (enabled)
{
if (m_cheat_manager_dialog)
{
@ -2677,7 +2676,7 @@ void MainWindow::onAchievementsChallengeModeChanged()
}
}
updateEmulationActions(false, System::IsValid(), active);
updateEmulationActions(false, System::IsValid(), enabled);
}
void MainWindow::onToolsMemoryCardEditorTriggered()

View file

@ -134,7 +134,7 @@ private Q_SLOTS:
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
void onAchievementsLoginSucceeded(const QString& display_name, quint32 points, quint32 sc_points,
quint32 unread_messages);
void onAchievementsChallengeModeChanged();
void onAchievementsChallengeModeChanged(bool enabled);
void onApplicationStateChanged(Qt::ApplicationState state);
void onStartFileActionTriggered();

View file

@ -1231,7 +1231,7 @@ void Host::OnAchievementsRefreshed()
const std::string& rich_presence_string = Achievements::GetRichPresenceString();
if (Achievements::HasRichPresence() && !rich_presence_string.empty())
game_info.append(QString::fromStdString(rich_presence_string));
game_info.append(QString::fromStdString(StringUtil::Ellipsise(rich_presence_string, 128)));
else
game_info.append(qApp->translate("EmuThread", "Rich presence inactive or unsupported."));
}
@ -1243,9 +1243,9 @@ void Host::OnAchievementsRefreshed()
emit g_emu_thread->achievementsRefreshed(game_id, game_info);
}
void Host::OnAchievementsHardcoreModeChanged()
void Host::OnAchievementsHardcoreModeChanged(bool enabled)
{
emit g_emu_thread->achievementsChallengeModeChanged();
emit g_emu_thread->achievementsChallengeModeChanged(enabled);
}
void EmuThread::doBackgroundControllerPoll()

View file

@ -144,7 +144,7 @@ Q_SIGNALS:
void achievementsLoginSucceeded(const QString& display_name, quint32 points, quint32 sc_points,
quint32 unread_messages);
void achievementsRefreshed(quint32 id, const QString& game_info_string);
void achievementsChallengeModeChanged();
void achievementsChallengeModeChanged(bool enabled);
void cheatEnabled(quint32 index, bool enabled);
public Q_SLOTS:

View file

@ -340,7 +340,7 @@ void Host::OnAchievementsRefreshed()
// noop
}
void Host::OnAchievementsHardcoreModeChanged()
void Host::OnAchievementsHardcoreModeChanged(bool enabled)
{
// noop
}

View file

@ -80,6 +80,7 @@ ImVec4 UISecondaryTextColor;
static u32 s_menu_button_index = 0;
static u32 s_close_button_state = 0;
static bool s_focus_reset_queued = false;
static bool s_light_theme = false;
static LRUCache<std::string, std::shared_ptr<GPUTexture>> s_texture_cache(128, true);
static std::shared_ptr<GPUTexture> s_placeholder_texture;
@ -2484,17 +2485,10 @@ void ImGuiFullscreen::DrawNotifications(ImVec2& position, float spacing)
ImFont* const title_font = ImGuiFullscreen::g_large_font;
ImFont* const text_font = ImGuiFullscreen::g_medium_font;
#if 0
static constexpr u32 toast_background_color = IM_COL32(241, 241, 241, 255);
static constexpr u32 toast_border_color = IM_COL32(0x88, 0x88, 0x88, 255);
static constexpr u32 toast_title_color = IM_COL32(1, 1, 1, 255);
static constexpr u32 toast_text_color = IM_COL32(0, 0, 0, 255);
#else
static constexpr u32 toast_background_color = IM_COL32(0x21, 0x21, 0x21, 255);
static constexpr u32 toast_border_color = IM_COL32(0x48, 0x48, 0x48, 255);
static constexpr u32 toast_title_color = IM_COL32(0xff, 0xff, 0xff, 255);
static constexpr u32 toast_text_color = IM_COL32(0xff, 0xff, 0xff, 255);
#endif
const u32 toast_background_color = s_light_theme ? IM_COL32(241, 241, 241, 255) : IM_COL32(0x21, 0x21, 0x21, 255);
const u32 toast_border_color = s_light_theme ? IM_COL32(0x88, 0x88, 0x88, 255) : IM_COL32(0x48, 0x48, 0x48, 255);
const u32 toast_title_color = s_light_theme ? IM_COL32(1, 1, 1, 255) : IM_COL32(0xff, 0xff, 0xff, 255);
const u32 toast_text_color = s_light_theme ? IM_COL32(0, 0, 0, 255) : IM_COL32(0xff, 0xff, 0xff, 255);
for (u32 index = 0; index < static_cast<u32>(s_notifications.size());)
{
@ -2668,6 +2662,8 @@ void ImGuiFullscreen::DrawToast()
void ImGuiFullscreen::SetTheme(bool light)
{
s_light_theme = light;
if (!light)
{
// dark