FullscreenUI: Add more missing options

This commit is contained in:
Connor McLaughlin 2022-09-03 13:39:59 +10:00
parent 35f272b336
commit 26159981ce
2 changed files with 170 additions and 163 deletions

View File

@ -741,7 +741,7 @@ void FullscreenUI::DoStartFile()
CloseFileSelector(); CloseFileSelector();
}; };
OpenFileSelector(ICON_FA_COMPACT_DISC " Select Disc Image", false, std::move(callback), GetDiscImageFilters()); OpenFileSelector(ICON_FA_COMPACT_DISC " Select Disc Image", false, std::move(callback), GetDiscImageFilters());
} }
void FullscreenUI::DoStartBIOS() void FullscreenUI::DoStartBIOS()
@ -795,7 +795,7 @@ void FullscreenUI::DoChangeDiscFromFile()
ReturnToMainWindow(); ReturnToMainWindow();
}; };
OpenFileSelector(ICON_FA_COMPACT_DISC " Select Disc Image", false, std::move(callback), GetDiscImageFilters(), OpenFileSelector(ICON_FA_COMPACT_DISC " Select Disc Image", false, std::move(callback), GetDiscImageFilters(),
std::string(Path::GetDirectory(System::GetRunningPath()))); std::string(Path::GetDirectory(System::GetRunningPath())));
} }
@ -833,7 +833,7 @@ void FullscreenUI::DoChangeDisc()
ReturnToMainWindow(); ReturnToMainWindow();
}; };
OpenChoiceDialog(ICON_FA_COMPACT_DISC " Select Disc Image", true, std::move(options), std::move(callback)); OpenChoiceDialog(ICON_FA_COMPACT_DISC " Select Disc Image", true, std::move(options), std::move(callback));
} }
void FullscreenUI::DoCheatsMenu() void FullscreenUI::DoCheatsMenu()
@ -875,7 +875,7 @@ void FullscreenUI::DoCheatsMenu()
else else
System::SetCheatCodeState(static_cast<u32>(index), checked, true); System::SetCheatCodeState(static_cast<u32>(index), checked, true);
}; };
OpenChoiceDialog(ICON_FA_FROWN " Cheat List", true, std::move(options), std::move(callback)); OpenChoiceDialog(ICON_FA_FROWN " Cheat List", true, std::move(options), std::move(callback));
} }
void FullscreenUI::DoToggleAnalogMode() void FullscreenUI::DoToggleAnalogMode()
@ -943,38 +943,36 @@ void FullscreenUI::DrawLandingWindow()
BeginMenuButtons(7, 0.5f); BeginMenuButtons(7, 0.5f);
if (MenuButton(" " ICON_FA_PLAY_CIRCLE " Resume", if (MenuButton(ICON_FA_PLAY_CIRCLE " Resume", "Starts the console from where it was before it was last closed."))
"Starts the console from where it was before it was last closed."))
{ {
System::GetMostRecentResumeSaveStatePath(); System::GetMostRecentResumeSaveStatePath();
DoResume(); DoResume();
} }
if (MenuButton(" " ICON_FA_FOLDER_OPEN " Start File", "Launch a game by selecting a file/disc image.")) if (MenuButton(ICON_FA_FOLDER_OPEN " Start File", "Launch a game by selecting a file/disc image."))
{ {
DoStartFile(); DoStartFile();
} }
if (MenuButton(" " ICON_FA_TOOLBOX " Start BIOS", "Start the console without any disc inserted.")) if (MenuButton(ICON_FA_TOOLBOX " Start BIOS", "Start the console without any disc inserted."))
{ {
DoStartBIOS(); DoStartBIOS();
} }
if (MenuButton(" " ICON_FA_UNDO " Load State", "Loads a global save state.")) if (MenuButton(ICON_FA_UNDO " Load State", "Loads a global save state."))
{ {
OpenSaveStateSelector(true); OpenSaveStateSelector(true);
} }
if (MenuButton(" " ICON_FA_LIST " Open Game List", if (MenuButton(ICON_FA_LIST " Open Game List", "Launch a game from images scanned from your game directories."))
"Launch a game from images scanned from your game directories."))
{ {
SwitchToGameList(); SwitchToGameList();
} }
if (MenuButton(" " ICON_FA_SLIDERS_H " Settings", "Change settings for the emulator.")) if (MenuButton(ICON_FA_SLIDERS_H " Settings", "Change settings for the emulator."))
SwitchToSettings(); SwitchToSettings();
if (MenuButton(" " ICON_FA_SIGN_OUT_ALT " Exit", "Exits the program.")) if (MenuButton(ICON_FA_SIGN_OUT_ALT " Exit", "Exits the program."))
{ {
DoRequestExit(); DoRequestExit();
} }
@ -1128,17 +1126,17 @@ void FullscreenUI::DrawInputBindingButton(SettingsInterface* bsi, Controller::Co
switch (type) switch (type)
{ {
case Controller::ControllerBindingType::Button: case Controller::ControllerBindingType::Button:
title = fmt::format(ICON_FA_DOT_CIRCLE " {}", display_name); title = fmt::format(ICON_FA_DOT_CIRCLE " {}", display_name);
break; break;
case Controller::ControllerBindingType::Axis: case Controller::ControllerBindingType::Axis:
case Controller::ControllerBindingType::HalfAxis: case Controller::ControllerBindingType::HalfAxis:
title = fmt::format(ICON_FA_BULLSEYE " {}", display_name); title = fmt::format(ICON_FA_BULLSEYE " {}", display_name);
break; break;
case Controller::ControllerBindingType::Motor: case Controller::ControllerBindingType::Motor:
title = fmt::format(ICON_FA_BELL " {}", display_name); title = fmt::format(ICON_FA_BELL " {}", display_name);
break; break;
case Controller::ControllerBindingType::Macro: case Controller::ControllerBindingType::Macro:
title = fmt::format(ICON_FA_PIZZA_SLICE " {}", display_name); title = fmt::format(ICON_FA_PIZZA_SLICE " {}", display_name);
break; break;
default: default:
title = display_name; title = display_name;
@ -1246,7 +1244,7 @@ void FullscreenUI::DrawInputBindingWindow()
return; return;
} }
const char* title = ICON_FA_GAMEPAD " Set Input Binding"; const char* title = ICON_FA_GAMEPAD " Set Input Binding";
ImGui::SetNextWindowSize(LayoutScale(500.0f, 0.0f)); ImGui::SetNextWindowSize(LayoutScale(500.0f, 0.0f));
ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
ImGui::OpenPopup(title); ImGui::OpenPopup(title);
@ -1917,7 +1915,7 @@ void FullscreenUI::DrawSettingsWindow()
if (BeginFullscreenWindow(ImVec2(0.0f, 0.0f), heading_size, "settings_category", UIPrimaryColor)) if (BeginFullscreenWindow(ImVec2(0.0f, 0.0f), heading_size, "settings_category", UIPrimaryColor))
{ {
static constexpr float ITEM_WIDTH = 22.0f; static constexpr float ITEM_WIDTH = 25.0f;
static constexpr const char* global_icons[] = { static constexpr const char* global_icons[] = {
ICON_FA_WINDOW_MAXIMIZE, ICON_FA_LIST, ICON_FA_HDD, ICON_FA_SLIDERS_H, ICON_FA_WINDOW_MAXIMIZE, ICON_FA_LIST, ICON_FA_HDD, ICON_FA_SLIDERS_H,
@ -1972,7 +1970,7 @@ void FullscreenUI::DrawSettingsWindow()
ReturnToMainWindow(); ReturnToMainWindow();
if (s_game_settings_entry) if (s_game_settings_entry)
NavTitle(fmt::format("{} ({})", titles[static_cast<u32>(pages[index])], s_game_settings_entry->title).c_str()); NavTitle(s_game_settings_entry->title.c_str());
else else
NavTitle(titles[static_cast<u32>(pages[index])]); NavTitle(titles[static_cast<u32>(pages[index])]);
@ -2075,41 +2073,41 @@ void FullscreenUI::DrawSummarySettingsPage()
if (s_game_settings_entry) if (s_game_settings_entry)
{ {
if (MenuButton(ICON_FA_WINDOW_MAXIMIZE " Title", s_game_settings_entry->title.c_str(), true)) if (MenuButton(ICON_FA_WINDOW_MAXIMIZE " Title", s_game_settings_entry->title.c_str(), true))
CopyTextToClipboard("Game title copied to clipboard.", s_game_settings_entry->title); CopyTextToClipboard("Game title copied to clipboard.", s_game_settings_entry->title);
if (MenuButton(ICON_FA_PAGER " Serial", s_game_settings_entry->serial.c_str(), true)) if (MenuButton(ICON_FA_PAGER " Serial", s_game_settings_entry->serial.c_str(), true))
CopyTextToClipboard("Game serial copied to clipboard.", s_game_settings_entry->serial); CopyTextToClipboard("Game serial copied to clipboard.", s_game_settings_entry->serial);
if (MenuButton(ICON_FA_COMPACT_DISC " Type", GameList::GetEntryTypeDisplayName(s_game_settings_entry->type), true)) if (MenuButton(ICON_FA_COMPACT_DISC " Type", GameList::GetEntryTypeDisplayName(s_game_settings_entry->type), true))
{ {
CopyTextToClipboard("Game type copied to clipboard.", CopyTextToClipboard("Game type copied to clipboard.",
GameList::GetEntryTypeDisplayName(s_game_settings_entry->type)); GameList::GetEntryTypeDisplayName(s_game_settings_entry->type));
} }
if (MenuButton(ICON_FA_BOX " Region", Settings::GetDiscRegionDisplayName(s_game_settings_entry->region), true)) if (MenuButton(ICON_FA_BOX " Region", Settings::GetDiscRegionDisplayName(s_game_settings_entry->region), true))
{ {
CopyTextToClipboard("Game region copied to clipboard.", CopyTextToClipboard("Game region copied to clipboard.",
Settings::GetDiscRegionDisplayName(s_game_settings_entry->region)); Settings::GetDiscRegionDisplayName(s_game_settings_entry->region));
} }
if (MenuButton(ICON_FA_STAR " Compatibility Rating", if (MenuButton(ICON_FA_STAR " Compatibility Rating",
GameDatabase::GetCompatibilityRatingDisplayName(s_game_settings_entry->compatibility), true)) GameDatabase::GetCompatibilityRatingDisplayName(s_game_settings_entry->compatibility), true))
{ {
CopyTextToClipboard("Game compatibility rating copied to clipboard.", CopyTextToClipboard("Game compatibility rating copied to clipboard.",
GameDatabase::GetCompatibilityRatingDisplayName(s_game_settings_entry->compatibility)); GameDatabase::GetCompatibilityRatingDisplayName(s_game_settings_entry->compatibility));
} }
if (MenuButton(ICON_FA_FOLDER_OPEN " Path", s_game_settings_entry->path.c_str(), true)) if (MenuButton(ICON_FA_FOLDER_OPEN " Path", s_game_settings_entry->path.c_str(), true))
{ {
CopyTextToClipboard("Game path copied to clipboard.", s_game_settings_entry->path); CopyTextToClipboard("Game path copied to clipboard.", s_game_settings_entry->path);
} }
} }
else else
{ {
MenuButton(ICON_FA_BAN " Details unavailable for game not scanned in game list.", ""); MenuButton(ICON_FA_BAN " Details unavailable for game not scanned in game list.", "");
} }
MenuHeading("Options"); MenuHeading("Options");
if (MenuButton(ICON_FA_COPY " Copy Settings", "Copies the current global settings to this game.")) if (MenuButton(ICON_FA_COPY " Copy Settings", "Copies the current global settings to this game."))
DoCopyGameSettings(); DoCopyGameSettings();
if (MenuButton(ICON_FA_TRASH " Clear Settings", "Clears all settings set for this game.")) if (MenuButton(ICON_FA_TRASH " Clear Settings", "Clears all settings set for this game."))
DoClearGameSettings(); DoClearGameSettings();
EndMenuButtons(); EndMenuButtons();
@ -2123,64 +2121,73 @@ void FullscreenUI::DrawInterfaceSettingsPage()
MenuHeading("Behavior"); MenuHeading("Behavior");
DrawToggleSetting(bsi, "Pause On Start", "Pauses the emulator when a game is started.", "Main", "StartPaused", false); DrawToggleSetting(bsi, ICON_FA_PAUSE " Pause On Start", "Pauses the emulator when a game is started.", "Main",
DrawToggleSetting(bsi, "Pause On Focus Loss", "StartPaused", false);
DrawToggleSetting(bsi, ICON_FA_VIDEO " Pause On Focus Loss",
"Pauses the emulator when you minimize the window or switch to another " "Pauses the emulator when you minimize the window or switch to another "
"application, and unpauses when you switch back.", "application, and unpauses when you switch back.",
"Main", "PauseOnFocusLoss", false); "Main", "PauseOnFocusLoss", false);
DrawToggleSetting(bsi, "Pause On Menu", DrawToggleSetting(bsi, ICON_FA_WINDOW_MAXIMIZE " Pause On Menu",
"Pauses the emulator when you open the quick menu, and unpauses when you close it.", "Main", "Pauses the emulator when you open the quick menu, and unpauses when you close it.", "Main",
"PauseOnMenu", true); "PauseOnMenu", true);
DrawToggleSetting(bsi, "Confirm Power Off", DrawToggleSetting(bsi, ICON_FA_POWER_OFF " Confirm Power Off",
"Determines whether a prompt will be displayed to confirm shutting down the emulator/game " "Determines whether a prompt will be displayed to confirm shutting down the emulator/game "
"when the hotkey is pressed.", "when the hotkey is pressed.",
"Main", "ConfirmPowerOff", true); "Main", "ConfirmPowerOff", true);
DrawToggleSetting(bsi, "Save State On Exit", DrawToggleSetting(bsi, ICON_FA_SAVE " Save State On Exit",
"Automatically saves the emulator state when powering down or exiting. You can then " "Automatically saves the emulator state when powering down or exiting. You can then "
"resume directly from where you left off next time.", "resume directly from where you left off next time.",
"Main", "SaveStateOnExit", true); "Main", "SaveStateOnExit", true);
DrawToggleSetting(bsi, "Start Fullscreen", "Automatically switches to fullscreen mode when the program is started.", DrawToggleSetting(bsi, ICON_FA_TV " Start Fullscreen",
"Main", "StartFullscreen", false); "Automatically switches to fullscreen mode when the program is started.", "Main", "StartFullscreen",
DrawToggleSetting(bsi, "Hide Cursor In Fullscreen", false);
DrawToggleSetting(bsi, ICON_FA_MOUSE " Double-Click Toggles Fullscreen",
"Switches between full screen and windowed when the window is double-clicked.", "Main",
"DoubleClickTogglesFullscreen", true);
DrawToggleSetting(bsi, ICON_FA_MOUSE_POINTER "Hide Cursor In Fullscreen",
"Hides the mouse pointer/cursor when the emulator is in fullscreen mode.", "Main", "Hides the mouse pointer/cursor when the emulator is in fullscreen mode.", "Main",
"HideCursorInFullscreen", true); "HideCursorInFullscreen", true);
DrawToggleSetting(bsi, "Inhibit Screensaver", DrawToggleSetting(bsi, ICON_FA_MAGIC " Inhibit Screensaver",
"Prevents the screen saver from activating and the host from sleeping while emulation is running.", "Prevents the screen saver from activating and the host from sleeping while emulation is running.",
"Main", "InhibitScreensaver", true); "Main", "InhibitScreensaver", true);
DrawToggleSetting(bsi, "Load Devices From Save States", DrawToggleSetting(bsi, ICON_FA_GAMEPAD " Load Devices From Save States",
"When enabled, memory cards and controllers will be overwritten when save states are loaded.", "When enabled, memory cards and controllers will be overwritten when save states are loaded.",
"Main", "LoadDevicesFromSaveStates", false); "Main", "LoadDevicesFromSaveStates", false);
DrawToggleSetting(bsi, "Apply Per-Game Settings", DrawToggleSetting(bsi, ICON_FA_COGS " Apply Per-Game Settings",
"When enabled, per-game settings will be applied, and incompatible enhancements will be disabled.", "When enabled, per-game settings will be applied, and incompatible enhancements will be disabled.",
"Main", "ApplyGameSettings", true); "Main", "ApplyGameSettings", true);
DrawToggleSetting(bsi, "Automatically Load Cheats", "Automatically loads and applies cheats on game start.", "Main", DrawToggleSetting(bsi, ICON_FA_FROWN " Automatically Load Cheats",
"AutoLoadCheats", true); "Automatically loads and applies cheats on game start.", "Main", "AutoLoadCheats", true);
#ifdef WITH_DISCORD_PRESENCE #ifdef WITH_DISCORD_PRESENCE
MenuHeading("Integration"); MenuHeading("Integration");
DrawToggleSetting(bsi, "Enable Discord Presence", DrawToggleSetting(bsi, ICON_FA_CHARGING_STATION " Enable Discord Presence",
"Shows the game you are currently playing as part of your profile on Discord.", "Main", "Shows the game you are currently playing as part of your profile on Discord.", "Main",
"EnableDiscordPresence", false); "EnableDiscordPresence", false);
#endif #endif
MenuHeading("On-Screen Display"); MenuHeading("On-Screen Display");
DrawToggleSetting(bsi, "Show OSD Messages", "Shows on-screen-display messages when events occur.", "Display", DrawIntRangeSetting(bsi, ICON_FA_SEARCH " OSD Scale", "Determines how large the on-screen messages and monitor are.",
"ShowOSDMessages", true); "Display", "OSDScale", 100, 25, 500, "%d%%");
DrawToggleSetting(bsi, "Show Game Frame Rate", DrawToggleSetting(bsi, ICON_FA_LIST " Show OSD Messages", "Shows on-screen-display messages when events occur.",
"Shows the internal frame rate of the game in the top-right corner of the display.", "Display", "Display", "ShowOSDMessages", true);
"ShowFPS", false);
DrawToggleSetting(bsi, "Show FPS",
"Shows the number of frames (or v-syncs) displayed per second by the system "
"in the top-right corner of the display.",
"Display", "ShowFPS", false);
DrawToggleSetting( DrawToggleSetting(
bsi, "Show Speed", bsi, ICON_FA_CLOCK " Show Speed",
"Shows the current emulation speed of the system in the top-right corner of the display as a percentage.", "Shows the current emulation speed of the system in the top-right corner of the display as a percentage.",
"Display", "ShowSpeed", false); "Display", "ShowSpeed", false);
DrawToggleSetting(bsi, "Show Resolution", DrawToggleSetting(bsi, ICON_FA_RULER " Show FPS",
"Shows the number of frames (or v-syncs) displayed per second by the system in the top-right "
"corner of the display.",
"Display", "ShowFPS", false);
DrawToggleSetting(bsi, ICON_FA_BATTERY_HALF " Show CPU Usage",
"Shows the CPU usage based on threads in the top-right corner of the display.", "Display",
"ShowCPU", false);
DrawToggleSetting(bsi, ICON_FA_SPINNER " Show GPU Usage",
"Shows the host's GPU usage in the top-right corner of the display.", "Display", "ShowGPU", false);
DrawToggleSetting(bsi, ICON_FA_RULER_VERTICAL " Show Resolution",
"Shows the current rendering resolution of the system in the top-right corner of the display.", "Shows the current rendering resolution of the system in the top-right corner of the display.",
"Display", "ShowResolution", false); "Display", "ShowResolution", false);
DrawToggleSetting(bsi, "Show Controller Input", DrawToggleSetting(bsi, ICON_FA_GAMEPAD " Show Controller Input",
"Shows the current controller state of the system in the bottom-left corner of the display.", "Shows the current controller state of the system in the bottom-left corner of the display.",
"Display", "ShowInputs", false); "Display", "ShowInputs", false);
@ -2193,9 +2200,9 @@ void FullscreenUI::DrawGameListSettingsPage()
MenuHeading("Game List"); MenuHeading("Game List");
if (MenuButton(ICON_FA_FOLDER_PLUS " Add Search Directory", "Adds a new directory to the game search list.")) if (MenuButton(ICON_FA_FOLDER_PLUS " Add Search Directory", "Adds a new directory to the game search list."))
{ {
OpenFileSelector(ICON_FA_FOLDER_PLUS " Add Search Directory", true, [](const std::string& dir) { OpenFileSelector(ICON_FA_FOLDER_PLUS " Add Search Directory", true, [](const std::string& dir) {
if (!dir.empty()) if (!dir.empty())
{ {
auto lock = Host::GetSettingsLock(); auto lock = Host::GetSettingsLock();
@ -2212,10 +2219,10 @@ void FullscreenUI::DrawGameListSettingsPage()
}); });
} }
if (MenuButton(ICON_FA_FOLDER_OPEN " Change Recursive Directories", if (MenuButton(ICON_FA_FOLDER_OPEN " Change Recursive Directories",
"Sets whether subdirectories are searched for each game directory")) "Sets whether subdirectories are searched for each game directory"))
{ {
OpenChoiceDialog(ICON_FA_FOLDER_OPEN " Change Recursive Directories", true, GetGameListDirectoryOptions(true), OpenChoiceDialog(ICON_FA_FOLDER_OPEN " Change Recursive Directories", true, GetGameListDirectoryOptions(true),
[](s32 index, const std::string& title, bool checked) { [](s32 index, const std::string& title, bool checked) {
if (index < 0) if (index < 0)
return; return;
@ -2239,9 +2246,9 @@ void FullscreenUI::DrawGameListSettingsPage()
}); });
} }
if (MenuButton(ICON_FA_FOLDER_MINUS " Remove Search Directory", "Removes a directory from the game search list.")) if (MenuButton(ICON_FA_FOLDER_MINUS " Remove Search Directory", "Removes a directory from the game search list."))
{ {
OpenChoiceDialog(ICON_FA_FOLDER_MINUS " Remove Search Directory", false, GetGameListDirectoryOptions(false), OpenChoiceDialog(ICON_FA_FOLDER_MINUS " Remove Search Directory", false, GetGameListDirectoryOptions(false),
[](s32 index, const std::string& title, bool checked) { [](s32 index, const std::string& title, bool checked) {
if (index < 0) if (index < 0)
return; return;
@ -2257,9 +2264,9 @@ void FullscreenUI::DrawGameListSettingsPage()
}); });
} }
if (MenuButton(ICON_FA_SEARCH " Scan For New Games", "Identifies any new files added to the game directories.")) if (MenuButton(ICON_FA_SEARCH " Scan For New Games", "Identifies any new files added to the game directories."))
Host::RefreshGameListAsync(false); Host::RefreshGameListAsync(false);
if (MenuButton(ICON_FA_SEARCH_PLUS " Rescan All Games", "Forces a full rescan of all games previously identified.")) if (MenuButton(ICON_FA_SEARCH_PLUS " Rescan All Games", "Forces a full rescan of all games previously identified."))
Host::RefreshGameListAsync(true); Host::RefreshGameListAsync(true);
MenuHeading("Search Directories"); MenuHeading("Search Directories");
@ -2541,7 +2548,7 @@ void FullscreenUI::DoLoadInputProfile()
coptions.reserve(profiles.size()); coptions.reserve(profiles.size());
for (std::string& name : profiles) for (std::string& name : profiles)
coptions.emplace_back(std::move(name), false); coptions.emplace_back(std::move(name), false);
OpenChoiceDialog(ICON_FA_FOLDER_OPEN " Load Profile", false, std::move(coptions), OpenChoiceDialog(ICON_FA_FOLDER_OPEN " Load Profile", false, std::move(coptions),
[](s32 index, const std::string& title, bool checked) { [](s32 index, const std::string& title, bool checked) {
if (index < 0) if (index < 0)
return; return;
@ -2591,7 +2598,7 @@ void FullscreenUI::DoSaveInputProfile()
for (std::string& name : profiles) for (std::string& name : profiles)
coptions.emplace_back(std::move(name), false); coptions.emplace_back(std::move(name), false);
OpenChoiceDialog( OpenChoiceDialog(
ICON_FA_SAVE " Save Profile", false, std::move(coptions), [](s32 index, const std::string& title, bool checked) { ICON_FA_SAVE " Save Profile", false, std::move(coptions), [](s32 index, const std::string& title, bool checked) {
if (index < 0) if (index < 0)
return; return;
@ -2604,8 +2611,8 @@ void FullscreenUI::DoSaveInputProfile()
CloseChoiceDialog(); CloseChoiceDialog();
OpenInputStringDialog(ICON_FA_SAVE " Save Profile", "Enter the name of the input profile you wish to create.", OpenInputStringDialog(ICON_FA_SAVE " Save Profile", "Enter the name of the input profile you wish to create.",
std::string(), ICON_FA_FOLDER_PLUS " Create", [](std::string title) { std::string(), ICON_FA_FOLDER_PLUS " Create", [](std::string title) {
if (!title.empty()) if (!title.empty())
DoSaveInputProfile(title); DoSaveInputProfile(title);
}); });
@ -2631,7 +2638,7 @@ void FullscreenUI::DrawControllerSettingsPage()
if (IsEditingGameSettings(bsi)) if (IsEditingGameSettings(bsi))
{ {
if (DrawToggleSetting(bsi, ICON_FA_COG " Per-Game Configuration", if (DrawToggleSetting(bsi, ICON_FA_COG " Per-Game Configuration",
"Uses game-specific settings for controllers for this game.", "Pad", "Uses game-specific settings for controllers for this game.", "Pad",
"UseGameSettingsForController", false, IsEditingGameSettings(bsi), false)) "UseGameSettingsForController", false, IsEditingGameSettings(bsi), false))
{ {
@ -2654,24 +2661,23 @@ void FullscreenUI::DrawControllerSettingsPage()
if (IsEditingGameSettings(bsi)) if (IsEditingGameSettings(bsi))
{ {
if (MenuButton(ICON_FA_COPY " Copy Global Settings", "Copies the global controller configuration to this game.")) if (MenuButton(ICON_FA_COPY " Copy Global Settings", "Copies the global controller configuration to this game."))
CopyGlobalControllerSettingsToGame(); CopyGlobalControllerSettingsToGame();
} }
else else
{ {
if (MenuButton(ICON_FA_FOLDER_MINUS " Reset Settings", if (MenuButton(ICON_FA_FOLDER_MINUS " Reset Settings",
"Resets all configuration to defaults (including bindings).")) "Resets all configuration to defaults (including bindings)."))
{ {
ResetControllerSettings(); ResetControllerSettings();
} }
} }
if (MenuButton(ICON_FA_FOLDER_OPEN " Load Profile", if (MenuButton(ICON_FA_FOLDER_OPEN " Load Profile", "Replaces these settings with a previously saved input profile."))
"Replaces these settings with a previously saved input profile."))
{ {
DoLoadInputProfile(); DoLoadInputProfile();
} }
if (MenuButton(ICON_FA_SAVE " Save Profile", "Stores the current settings to an input profile.")) if (MenuButton(ICON_FA_SAVE " Save Profile", "Stores the current settings to an input profile."))
{ {
DoSaveInputProfile(); DoSaveInputProfile();
} }
@ -2679,25 +2685,25 @@ void FullscreenUI::DrawControllerSettingsPage()
MenuHeading("Input Sources"); MenuHeading("Input Sources");
#ifdef WITH_SDL2 #ifdef WITH_SDL2
DrawToggleSetting(bsi, ICON_FA_COG " Enable SDL Input Source", "The SDL input source supports most controllers.", DrawToggleSetting(bsi, ICON_FA_COG " Enable SDL Input Source", "The SDL input source supports most controllers.",
"InputSources", "SDL", true, true, false); "InputSources", "SDL", true, true, false);
DrawToggleSetting(bsi, ICON_FA_WIFI " SDL DualShock 4 / DualSense Enhanced Mode", DrawToggleSetting(bsi, ICON_FA_WIFI " SDL DualShock 4 / DualSense Enhanced Mode",
"Provides vibration and LED control support over Bluetooth.", "InputSources", "Provides vibration and LED control support over Bluetooth.", "InputSources",
"SDLControllerEnhancedMode", false, bsi->GetBoolValue("InputSources", "SDL", true), false); "SDLControllerEnhancedMode", false, bsi->GetBoolValue("InputSources", "SDL", true), false);
#endif #endif
#ifdef WITH_EVDEV #ifdef WITH_EVDEV
DrawToggleSetting(bsi, ICON_FA_COG " Enable Evdev Input Source", DrawToggleSetting(bsi, ICON_FA_COG " Enable Evdev Input Source",
"You can use evdev as a fallback if SDL doesn't work with your device.", "InputSources", "Evdev", "You can use evdev as a fallback if SDL doesn't work with your device.", "InputSources", "Evdev",
false); false);
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
DrawToggleSetting(bsi, ICON_FA_COG " Enable XInput Input Source", DrawToggleSetting(bsi, ICON_FA_COG " Enable XInput Input Source",
"The XInput source provides support for XBox 360/XBox One/XBox Series controllers.", "InputSources", "The XInput source provides support for XBox 360/XBox One/XBox Series controllers.", "InputSources",
"XInput", false); "XInput", false);
#endif #endif
MenuHeading("Multitap"); MenuHeading("Multitap");
DrawEnumSetting(bsi, ICON_FA_PLUS_SQUARE " Multitap Mode", DrawEnumSetting(bsi, ICON_FA_PLUS_SQUARE " Multitap Mode",
"Enables an additional three controller slots on each port. Not supported in all games.", "Enables an additional three controller slots on each port. Not supported in all games.",
"ControllerPorts", "MultitapMode", Settings::DEFAULT_MULTITAP_MODE, &Settings::ParseMultitapModeName, "ControllerPorts", "MultitapMode", Settings::DEFAULT_MULTITAP_MODE, &Settings::ParseMultitapModeName,
&Settings::GetMultitapModeName, &Settings::GetMultitapModeDisplayName, MultitapMode::Count); &Settings::GetMultitapModeName, &Settings::GetMultitapModeDisplayName, MultitapMode::Count);
@ -2726,14 +2732,14 @@ void FullscreenUI::DrawControllerSettingsPage()
continue; continue;
MenuHeading((mtap_enabled[mtap_port] ? MenuHeading((mtap_enabled[mtap_port] ?
fmt::format(ICON_FA_PLUG " Controller Port {}{}", mtap_port + 1, mtap_slot_names[mtap_slot]) : fmt::format(ICON_FA_PLUG " Controller Port {}{}", mtap_port + 1, mtap_slot_names[mtap_slot]) :
fmt::format(ICON_FA_PLUG " Controller Port {}", mtap_port + 1)) fmt::format(ICON_FA_PLUG " Controller Port {}", mtap_port + 1))
.c_str()); .c_str());
const std::string section(fmt::format("Pad{}", global_slot + 1)); const std::string section(fmt::format("Pad{}", global_slot + 1));
const std::string type(bsi->GetStringValue(section.c_str(), "Type", Controller::GetDefaultPadType(global_slot))); const std::string type(bsi->GetStringValue(section.c_str(), "Type", Controller::GetDefaultPadType(global_slot)));
const Controller::ControllerInfo* ci = Controller::GetControllerInfo(type); const Controller::ControllerInfo* ci = Controller::GetControllerInfo(type);
if (MenuButton(fmt::format(ICON_FA_GAMEPAD " Controller Type##type{}", global_slot).c_str(), if (MenuButton(fmt::format(ICON_FA_GAMEPAD " Controller Type##type{}", global_slot).c_str(),
ci ? ci->display_name : "Unknown")) ci ? ci->display_name : "Unknown"))
{ {
std::vector<std::pair<std::string, std::string>> raw_options(Controller::GetControllerTypeNames()); std::vector<std::pair<std::string, std::string>> raw_options(Controller::GetControllerTypeNames());
@ -2760,7 +2766,7 @@ void FullscreenUI::DrawControllerSettingsPage()
if (!ci || ci->num_bindings == 0) if (!ci || ci->num_bindings == 0)
continue; continue;
if (MenuButton(ICON_FA_MAGIC " Automatic Mapping", "Attempts to map the selected port to a chosen controller.")) if (MenuButton(ICON_FA_MAGIC " Automatic Mapping", "Attempts to map the selected port to a chosen controller."))
StartAutomaticBinding(global_slot); StartAutomaticBinding(global_slot);
for (u32 i = 0; i < ci->num_bindings; i++) for (u32 i = 0; i < ci->num_bindings; i++)
@ -2769,9 +2775,9 @@ void FullscreenUI::DrawControllerSettingsPage()
DrawInputBindingButton(bsi, bi.type, section.c_str(), bi.name, bi.display_name, true); DrawInputBindingButton(bsi, bi.type, section.c_str(), bi.name, bi.display_name, true);
} }
MenuHeading((mtap_enabled[mtap_port] ? fmt::format(ICON_FA_MICROCHIP " Controller Port {}{} Macros", mtap_port + 1, MenuHeading((mtap_enabled[mtap_port] ? fmt::format(ICON_FA_MICROCHIP " Controller Port {}{} Macros", mtap_port + 1,
mtap_slot_names[mtap_slot]) : mtap_slot_names[mtap_slot]) :
fmt::format(ICON_FA_MICROCHIP " Controller Port {} Macros", mtap_port + 1)) fmt::format(ICON_FA_MICROCHIP " Controller Port {} Macros", mtap_port + 1))
.c_str()); .c_str());
for (u32 macro_index = 0; macro_index < InputManager::NUM_MACRO_BUTTONS_PER_CONTROLLER; macro_index++) for (u32 macro_index = 0; macro_index < InputManager::NUM_MACRO_BUTTONS_PER_CONTROLLER; macro_index++)
@ -2782,7 +2788,7 @@ void FullscreenUI::DrawControllerSettingsPage()
std::string binds_string( std::string binds_string(
bsi->GetStringValue(section.c_str(), fmt::format("Macro{}Binds", macro_index + 1).c_str())); bsi->GetStringValue(section.c_str(), fmt::format("Macro{}Binds", macro_index + 1).c_str()));
if (MenuButton(fmt::format(ICON_FA_KEYBOARD " Macro {} Buttons", macro_index + 1).c_str(), if (MenuButton(fmt::format(ICON_FA_KEYBOARD " Macro {} Buttons", macro_index + 1).c_str(),
binds_string.empty() ? "No Buttons Selected" : binds_string.c_str())) binds_string.empty() ? "No Buttons Selected" : binds_string.c_str()))
{ {
std::vector<std::string_view> buttons_split(StringUtil::SplitString(binds_string, '&', true)); std::vector<std::string_view> buttons_split(StringUtil::SplitString(binds_string, '&', true));
@ -2848,7 +2854,7 @@ void FullscreenUI::DrawControllerSettingsPage()
} }
const std::string freq_key(fmt::format("Macro{}Frequency", macro_index + 1)); const std::string freq_key(fmt::format("Macro{}Frequency", macro_index + 1));
const std::string freq_title(fmt::format(ICON_FA_LIGHTBULB " Macro {} Frequency", macro_index + 1)); const std::string freq_title(fmt::format(ICON_FA_LIGHTBULB " Macro {} Frequency", macro_index + 1));
s32 frequency = bsi->GetIntValue(section.c_str(), freq_key.c_str(), 0); s32 frequency = bsi->GetIntValue(section.c_str(), freq_key.c_str(), 0);
const std::string freq_summary((frequency == 0) ? std::string("Macro will not auto-toggle.") : const std::string freq_summary((frequency == 0) ? std::string("Macro will not auto-toggle.") :
fmt::format("Macro will toggle every {} frames.", frequency)); fmt::format("Macro will toggle every {} frames.", frequency));
@ -2891,15 +2897,15 @@ void FullscreenUI::DrawControllerSettingsPage()
{ {
MenuHeading( MenuHeading(
(mtap_enabled[mtap_port] ? (mtap_enabled[mtap_port] ?
fmt::format(ICON_FA_SLIDERS_H " Controller Port {}{} Settings", mtap_port + 1, mtap_slot_names[mtap_slot]) : fmt::format(ICON_FA_SLIDERS_H " Controller Port {}{} Settings", mtap_port + 1, mtap_slot_names[mtap_slot]) :
fmt::format(ICON_FA_SLIDERS_H " Controller Port {} Settings", mtap_port + 1)) fmt::format(ICON_FA_SLIDERS_H " Controller Port {} Settings", mtap_port + 1))
.c_str()); .c_str());
for (u32 i = 0; i < ci->num_settings; i++) for (u32 i = 0; i < ci->num_settings; i++)
{ {
const SettingInfo& si = ci->settings[i]; const SettingInfo& si = ci->settings[i];
TinyString title; TinyString title;
title.Fmt(ICON_FA_COG " {}", si.display_name); title.Fmt(ICON_FA_COG " {}", si.display_name);
switch (si.type) switch (si.type)
{ {
case SettingInfo::Type::Boolean: case SettingInfo::Type::Boolean:
@ -2959,11 +2965,11 @@ void FullscreenUI::DrawMemoryCardSettingsPage()
BeginMenuButtons(); BeginMenuButtons();
MenuHeading("Settings and Operations"); MenuHeading("Settings and Operations");
if (MenuButton(ICON_FA_PLUS " Create Memory Card", "Creates a new memory card file or folder.")) if (MenuButton(ICON_FA_PLUS " Create Memory Card", "Creates a new memory card file or folder."))
{ {
OpenInputStringDialog( OpenInputStringDialog(
ICON_FA_PLUS " Create Memory Card", "Enter the name of the memory card you wish to create.", ICON_FA_PLUS " Create Memory Card", "Enter the name of the memory card you wish to create.",
"Card Name: ", ICON_FA_FOLDER_PLUS " Create", [](std::string memcard_name) { "Card Name: ", ICON_FA_FOLDER_PLUS " Create", [](std::string memcard_name) {
if (memcard_name.empty()) if (memcard_name.empty())
return; return;
@ -2989,17 +2995,17 @@ void FullscreenUI::DrawMemoryCardSettingsPage()
}); });
} }
DrawFolderSetting(bsi, ICON_FA_FOLDER_OPEN " Memory Card Directory", "MemoryCards", "Directory", DrawFolderSetting(bsi, ICON_FA_FOLDER_OPEN " Memory Card Directory", "MemoryCards", "Directory",
EmuFolders::MemoryCards); EmuFolders::MemoryCards);
if (!game_settings && MenuButton(ICON_FA_MAGIC " Reset Memory Card Directory", if (!game_settings && MenuButton(ICON_FA_MAGIC " Reset Memory Card Directory",
"Resets memory card directory to default (user directory).")) "Resets memory card directory to default (user directory)."))
{ {
bsi->SetStringValue("MemoryCards", "Directory", "memcards"); bsi->SetStringValue("MemoryCards", "Directory", "memcards");
SetSettingsChanged(bsi); SetSettingsChanged(bsi);
} }
DrawToggleSetting(bsi, ICON_FA_SEARCH " Use Single Card For Sub-Images", DrawToggleSetting(bsi, ICON_FA_SEARCH " Use Single Card For Sub-Images",
"When using a multi-disc image (m3u/pbp) and per-game (title) memory cards, " "When using a multi-disc image (m3u/pbp) and per-game (title) memory cards, "
"use a single memory card for all discs.", "use a single memory card for all discs.",
"MemoryCards", "UsePlaylistTitle", true); "MemoryCards", "UsePlaylistTitle", true);
@ -3010,7 +3016,7 @@ void FullscreenUI::DrawMemoryCardSettingsPage()
const MemoryCardType default_type = const MemoryCardType default_type =
(i == 0) ? Settings::DEFAULT_MEMORY_CARD_1_TYPE : Settings::DEFAULT_MEMORY_CARD_2_TYPE; (i == 0) ? Settings::DEFAULT_MEMORY_CARD_1_TYPE : Settings::DEFAULT_MEMORY_CARD_2_TYPE;
DrawEnumSetting(bsi, TinyString::FromFmt(ICON_FA_SD_CARD " Memory Card {} Type", i + 1), DrawEnumSetting(bsi, TinyString::FromFmt(ICON_FA_SD_CARD " Memory Card {} Type", i + 1),
SmallString::FromFmt("Sets which sort of memory card image will be used for slot {}.", i + 1), SmallString::FromFmt("Sets which sort of memory card image will be used for slot {}.", i + 1),
"MemoryCards", type_keys[i], default_type, &Settings::ParseMemoryCardTypeName, "MemoryCards", type_keys[i], default_type, &Settings::ParseMemoryCardTypeName,
&Settings::GetMemoryCardTypeName, &Settings::GetMemoryCardTypeDisplayName, MemoryCardType::Count); &Settings::GetMemoryCardTypeName, &Settings::GetMemoryCardTypeDisplayName, MemoryCardType::Count);
@ -3027,7 +3033,7 @@ void FullscreenUI::DrawMemoryCardSettingsPage()
std::optional<const char*>((i == 0) ? "shared_card_1.mcd" : "shared_card_2.mcd"))); std::optional<const char*>((i == 0) ? "shared_card_1.mcd" : "shared_card_2.mcd")));
TinyString title; TinyString title;
title.Fmt(ICON_FA_FILE " Shared Card Name##card_name_{}", i); title.Fmt(ICON_FA_FILE " Shared Card Name##card_name_{}", i);
if (MenuButtonWithValue(title, "The selected memory card image will be used in shared mode for this slot.", if (MenuButtonWithValue(title, "The selected memory card image will be used in shared mode for this slot.",
path_value.has_value() ? path_value->c_str() : "Use Global Setting", is_shared)) path_value.has_value() ? path_value->c_str() : "Use Global Setting", is_shared))
{ {
@ -3143,7 +3149,7 @@ void FullscreenUI::DrawDisplaySettingsPage()
ShowToast(std::string(), "GPU adapter will be applied after restarting.", 10.0f); ShowToast(std::string(), "GPU adapter will be applied after restarting.", 10.0f);
CloseChoiceDialog(); CloseChoiceDialog();
}; };
OpenChoiceDialog(ICON_FA_TV " GPU Adapter", false, std::move(options), std::move(callback)); OpenChoiceDialog(ICON_FA_TV " GPU Adapter", false, std::move(options), std::move(callback));
} }
std::optional<std::string> fsmode(bsi->GetOptionalStringValue( std::optional<std::string> fsmode(bsi->GetOptionalStringValue(
@ -3187,7 +3193,7 @@ void FullscreenUI::DrawDisplaySettingsPage()
ShowToast(std::string(), "Resolution change will be applied after restarting.", 10.0f); ShowToast(std::string(), "Resolution change will be applied after restarting.", 10.0f);
CloseChoiceDialog(); CloseChoiceDialog();
}; };
OpenChoiceDialog(ICON_FA_TV " Fullscreen Resolution", false, std::move(options), std::move(callback)); OpenChoiceDialog(ICON_FA_TV " Fullscreen Resolution", false, std::move(options), std::move(callback));
} }
switch (renderer) switch (renderer)
@ -3426,8 +3432,8 @@ void FullscreenUI::DrawAchievementsSettingsPage()
if (Achievements::IsUsingRAIntegration()) if (Achievements::IsUsingRAIntegration())
{ {
BeginMenuButtons(); BeginMenuButtons();
ActiveButton(ICON_FA_BAN " RAIntegration is being used instead of the built-in achievements implementation.", ActiveButton(ICON_FA_BAN " RAIntegration is being used instead of the built-in achievements implementation.", false,
false, false, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); false, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
EndMenuButtons(); EndMenuButtons();
return; return;
} }
@ -3442,17 +3448,17 @@ void FullscreenUI::DrawAchievementsSettingsPage()
BeginMenuButtons(); BeginMenuButtons();
MenuHeading("Settings"); MenuHeading("Settings");
DrawToggleSetting(bsi, ICON_FA_TROPHY " Enable Achievements", DrawToggleSetting(bsi, ICON_FA_TROPHY " Enable Achievements",
"When enabled and logged in, DuckStation will scan for achievements on startup.", "Cheevos", "When enabled and logged in, DuckStation will scan for achievements on startup.", "Cheevos",
"Enabled", false); "Enabled", false);
const bool enabled = bsi->GetBoolValue("Cheevos", "Enabled", false); const bool enabled = bsi->GetBoolValue("Cheevos", "Enabled", false);
const bool challenge = bsi->GetBoolValue("Cheevos", "ChallengeMode", false); const bool challenge = bsi->GetBoolValue("Cheevos", "ChallengeMode", false);
DrawToggleSetting(bsi, ICON_FA_USER_FRIENDS " Rich Presence", DrawToggleSetting(bsi, ICON_FA_USER_FRIENDS " Rich Presence",
"When enabled, rich presence information will be collected and sent to the server where supported.", "When enabled, rich presence information will be collected and sent to the server where supported.",
"Cheevos", "RichPresence", true, enabled); "Cheevos", "RichPresence", true, enabled);
if (DrawToggleSetting(bsi, ICON_FA_HARD_HAT " Hardcore Mode", if (DrawToggleSetting(bsi, ICON_FA_HARD_HAT " Hardcore Mode",
"\"Challenge\" mode for achievements. Disables save state, cheats, and slowdown functions, but " "\"Challenge\" mode for achievements. Disables save state, cheats, and slowdown functions, but "
"you receive double the " "you receive double the "
"achievement points.", "achievement points.",
@ -3461,14 +3467,14 @@ void FullscreenUI::DrawAchievementsSettingsPage()
if (System::IsValid() && bsi->GetBoolValue("Cheevos", "ChallengeMode", false)) if (System::IsValid() && bsi->GetBoolValue("Cheevos", "ChallengeMode", false))
ShowToast(std::string(), "Hardcore mode will be enabled on next game restart."); ShowToast(std::string(), "Hardcore mode will be enabled on next game restart.");
} }
DrawToggleSetting(bsi, ICON_FA_LIST_OL " Leaderboards", DrawToggleSetting(bsi, ICON_FA_LIST_OL " Leaderboards",
"Enables tracking and submission of leaderboards in supported games.", "Cheevos", "Leaderboards", "Enables tracking and submission of leaderboards in supported games.", "Cheevos", "Leaderboards",
true, enabled && challenge); true, enabled && challenge);
DrawToggleSetting(bsi, ICON_FA_MEDAL " Test Unofficial Achievements", DrawToggleSetting(bsi, ICON_FA_MEDAL " Test Unofficial Achievements",
"When enabled, DuckStation will list achievements from unofficial sets. These achievements are not " "When enabled, DuckStation will list achievements from unofficial sets. These achievements are not "
"tracked by RetroAchievements.", "tracked by RetroAchievements.",
"Cheevos", "UnofficialTestMode", false, enabled); "Cheevos", "UnofficialTestMode", false, enabled);
DrawToggleSetting(bsi, ICON_FA_STETHOSCOPE " Test Mode", DrawToggleSetting(bsi, ICON_FA_STETHOSCOPE " Test Mode",
"When enabled, DuckStation will assume all achievements are locked and not send any unlock " "When enabled, DuckStation will assume all achievements are locked and not send any unlock "
"notifications to the server.", "notifications to the server.",
"Cheevos", "TestMode", false, enabled); "Cheevos", "TestMode", false, enabled);
@ -3477,34 +3483,34 @@ void FullscreenUI::DrawAchievementsSettingsPage()
if (Achievements::IsLoggedIn()) if (Achievements::IsLoggedIn())
{ {
ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImGui::GetStyle().Colors[ImGuiCol_Text]); ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImGui::GetStyle().Colors[ImGuiCol_Text]);
ActiveButton(SmallString::FromFormat(ICON_FA_USER " Username: %s", Achievements::GetUsername().c_str()), false, ActiveButton(SmallString::FromFormat(ICON_FA_USER " Username: %s", Achievements::GetUsername().c_str()), false,
false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
TinyString ts_string; TinyString ts_string;
ts_string.AppendFmtString( ts_string.AppendFmtString(
"{:%Y-%m-%d %H:%M:%S}", "{:%Y-%m-%d %H:%M:%S}",
fmt::localtime(StringUtil::FromChars<u64>(bsi->GetStringValue("Cheevos", "LoginTimestamp", "0")).value_or(0))); fmt::localtime(StringUtil::FromChars<u64>(bsi->GetStringValue("Cheevos", "LoginTimestamp", "0")).value_or(0)));
ActiveButton(SmallString::FromFormat(ICON_FA_CLOCK " Login token generated on %s", ts_string.GetCharArray()), ActiveButton(SmallString::FromFormat(ICON_FA_CLOCK " Login token generated on %s", ts_string.GetCharArray()), false,
false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
ImGui::PopStyleColor(); ImGui::PopStyleColor();
if (MenuButton(ICON_FA_KEY " Logout", "Logs out of RetroAchievements.")) if (MenuButton(ICON_FA_KEY " Logout", "Logs out of RetroAchievements."))
{ {
Host::RunOnCPUThread([]() { Achievements::Logout(); }); Host::RunOnCPUThread([]() { Achievements::Logout(); });
} }
} }
else if (Achievements::IsActive()) else if (Achievements::IsActive())
{ {
ActiveButton(ICON_FA_USER " Not Logged In", false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); ActiveButton(ICON_FA_USER " Not Logged In", false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
if (MenuButton(ICON_FA_KEY " Login", "Logs in to RetroAchievements.")) if (MenuButton(ICON_FA_KEY " Login", "Logs in to RetroAchievements."))
ImGui::OpenPopup("Achievements Login"); ImGui::OpenPopup("Achievements Login");
DrawAchievementsLoginWindow(); DrawAchievementsLoginWindow();
} }
else else
{ {
ActiveButton(ICON_FA_USER " Achievements are disabled.", false, false, ActiveButton(ICON_FA_USER " Achievements are disabled.", false, false,
ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
} }
@ -3512,11 +3518,11 @@ void FullscreenUI::DrawAchievementsSettingsPage()
if (Achievements::HasActiveGame()) if (Achievements::HasActiveGame())
{ {
ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImGui::GetStyle().Colors[ImGuiCol_Text]); ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImGui::GetStyle().Colors[ImGuiCol_Text]);
ActiveButton(fmt::format(ICON_FA_BOOKMARK " Game ID: {}", Achievements::GetGameID()).c_str(), false, false, ActiveButton(fmt::format(ICON_FA_BOOKMARK " Game ID: {}", Achievements::GetGameID()).c_str(), false, false,
LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
ActiveButton(fmt::format(ICON_FA_BOOK " Game Title: {}", Achievements::GetGameTitle()).c_str(), false, false, ActiveButton(fmt::format(ICON_FA_BOOK " Game Title: {}", Achievements::GetGameTitle()).c_str(), false, false,
LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
ActiveButton(fmt::format(ICON_FA_TROPHY " Achievements: {} ({} points)", Achievements::GetAchievementCount(), ActiveButton(fmt::format(ICON_FA_TROPHY " Achievements: {} ({} points)", Achievements::GetAchievementCount(),
Achievements::GetMaximumPointsForGame()) Achievements::GetMaximumPointsForGame())
.c_str(), .c_str(),
false, false, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); false, false, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
@ -3524,12 +3530,12 @@ void FullscreenUI::DrawAchievementsSettingsPage()
const std::string& rich_presence_string = Achievements::GetRichPresenceString(); const std::string& rich_presence_string = Achievements::GetRichPresenceString();
if (!rich_presence_string.empty()) if (!rich_presence_string.empty())
{ {
ActiveButton(fmt::format(ICON_FA_MAP " {}", rich_presence_string).c_str(), false, false, ActiveButton(fmt::format(ICON_FA_MAP " {}", rich_presence_string).c_str(), false, false,
LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
} }
else else
{ {
ActiveButton(ICON_FA_MAP " Rich presence inactive or unsupported.", false, false, ActiveButton(ICON_FA_MAP " Rich presence inactive or unsupported.", false, false,
LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
} }
@ -3537,7 +3543,7 @@ void FullscreenUI::DrawAchievementsSettingsPage()
} }
else else
{ {
ActiveButton(ICON_FA_BAN " Game not loaded or no RetroAchievements available.", false, false, ActiveButton(ICON_FA_BAN " Game not loaded or no RetroAchievements available.", false, false,
LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
} }
@ -3581,7 +3587,7 @@ void FullscreenUI::DrawAchievementsLoginWindow()
const bool login_enabled = (std::strlen(username) > 0 && std::strlen(password) > 0); const bool login_enabled = (std::strlen(username) > 0 && std::strlen(password) > 0);
if (ActiveButton(ICON_FA_KEY " Login", false, login_enabled)) if (ActiveButton(ICON_FA_KEY " Login", false, login_enabled))
{ {
Achievements::LoginAsync(username, password); Achievements::LoginAsync(username, password);
std::memset(username, 0, sizeof(username)); std::memset(username, 0, sizeof(username));
@ -3589,7 +3595,7 @@ void FullscreenUI::DrawAchievementsLoginWindow()
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
if (ActiveButton(ICON_FA_TIMES " Cancel", false)) if (ActiveButton(ICON_FA_TIMES " Cancel", false))
{ {
std::memset(username, 0, sizeof(username)); std::memset(username, 0, sizeof(username));
std::memset(password, 0, sizeof(password)); std::memset(password, 0, sizeof(password));
@ -3610,7 +3616,7 @@ void FullscreenUI::DrawAchievementsLoginWindow()
void FullscreenUI::DrawAchievementsSettingsPage() void FullscreenUI::DrawAchievementsSettingsPage()
{ {
BeginMenuButtons(); BeginMenuButtons();
ActiveButton(ICON_FA_BAN " This build was not compiled with RetroAchivements support.", false, false, ActiveButton(ICON_FA_BAN " This build was not compiled with RetroAchivements support.", false, false,
ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
EndMenuButtons(); EndMenuButtons();
} }
@ -3796,47 +3802,47 @@ void FullscreenUI::DrawPauseMenu(MainWindowType type)
// NOTE: Menu close must come first, because otherwise VM destruction options will race. // NOTE: Menu close must come first, because otherwise VM destruction options will race.
const bool can_load_or_save_state = System::IsValid(); const bool can_load_or_save_state = System::IsValid();
if (ActiveButton(ICON_FA_PLAY " Resume Game", false) || WantsToCloseMenu()) if (ActiveButton(ICON_FA_PLAY " Resume Game", false) || WantsToCloseMenu())
ClosePauseMenu(); ClosePauseMenu();
if (ActiveButton(ICON_FA_FAST_FORWARD " Toggle Fast Forward", false)) if (ActiveButton(ICON_FA_FAST_FORWARD " Toggle Fast Forward", false))
{ {
ClosePauseMenu(); ClosePauseMenu();
DoToggleFastForward(); DoToggleFastForward();
} }
if (ActiveButton(ICON_FA_UNDO " Load State", false, can_load_or_save_state)) if (ActiveButton(ICON_FA_UNDO " Load State", false, can_load_or_save_state))
{ {
if (OpenSaveStateSelector(true)) if (OpenSaveStateSelector(true))
s_current_main_window = MainWindowType::None; s_current_main_window = MainWindowType::None;
} }
if (ActiveButton(ICON_FA_DOWNLOAD " Save State", false, can_load_or_save_state)) if (ActiveButton(ICON_FA_DOWNLOAD " Save State", false, can_load_or_save_state))
{ {
if (OpenSaveStateSelector(false)) if (OpenSaveStateSelector(false))
s_current_main_window = MainWindowType::None; s_current_main_window = MainWindowType::None;
} }
if (ActiveButton(ICON_FA_FROWN_OPEN " Cheat List", false, if (ActiveButton(ICON_FA_FROWN_OPEN " Cheat List", false,
!System::GetRunningCode().empty() && !Achievements::ChallengeModeActive())) !System::GetRunningCode().empty() && !Achievements::ChallengeModeActive()))
{ {
s_current_main_window = MainWindowType::None; s_current_main_window = MainWindowType::None;
DoCheatsMenu(); DoCheatsMenu();
} }
if (ActiveButton(ICON_FA_GAMEPAD " Toggle Analog", false)) if (ActiveButton(ICON_FA_GAMEPAD " Toggle Analog", false))
{ {
ClosePauseMenu(); ClosePauseMenu();
DoToggleAnalogMode(); DoToggleAnalogMode();
} }
if (ActiveButton(ICON_FA_WRENCH " Game Properties", false, !System::GetRunningCode().empty())) if (ActiveButton(ICON_FA_WRENCH " Game Properties", false, !System::GetRunningCode().empty()))
{ {
SwitchToGameSettings(); SwitchToGameSettings();
} }
#ifdef WITH_CHEEVOS #ifdef WITH_CHEEVOS
if (ActiveButton(ICON_FA_TROPHY " Achievements", false, if (ActiveButton(ICON_FA_TROPHY " Achievements", false,
Achievements::HasActiveGame() && Achievements::SafeHasAchievementsOrLeaderboards())) Achievements::HasActiveGame() && Achievements::SafeHasAchievementsOrLeaderboards()))
{ {
const auto lock = Achievements::GetLock(); const auto lock = Achievements::GetLock();
@ -3848,25 +3854,25 @@ void FullscreenUI::DrawPauseMenu(MainWindowType type)
OpenPauseSubMenu(PauseSubMenu::Achievements); OpenPauseSubMenu(PauseSubMenu::Achievements);
} }
#else #else
ActiveButton(ICON_FA_TROPHY " Achievements", false, false); ActiveButton(ICON_FA_TROPHY " Achievements", false, false);
#endif #endif
if (ActiveButton(ICON_FA_CAMERA " Save Screenshot", false)) if (ActiveButton(ICON_FA_CAMERA " Save Screenshot", false))
{ {
System::SaveScreenshot(); System::SaveScreenshot();
ClosePauseMenu(); ClosePauseMenu();
} }
if (ActiveButton(ICON_FA_COMPACT_DISC " Change Disc", false)) if (ActiveButton(ICON_FA_COMPACT_DISC " Change Disc", false))
{ {
s_current_main_window = MainWindowType::None; s_current_main_window = MainWindowType::None;
DoChangeDisc(); DoChangeDisc();
} }
if (ActiveButton(ICON_FA_SLIDERS_H " Settings", false)) if (ActiveButton(ICON_FA_SLIDERS_H " Settings", false))
SwitchToSettings(); SwitchToSettings();
if (ActiveButton(ICON_FA_POWER_OFF " Close Game", false)) if (ActiveButton(ICON_FA_POWER_OFF " Close Game", false))
{ {
// skip submenu when we can't save anyway // skip submenu when we can't save anyway
if (!can_load_or_save_state) if (!can_load_or_save_state)
@ -3880,23 +3886,23 @@ void FullscreenUI::DrawPauseMenu(MainWindowType type)
case PauseSubMenu::Exit: case PauseSubMenu::Exit:
{ {
if (just_focused) if (just_focused)
ImGui::SetFocusID(ImGui::GetID(ICON_FA_POWER_OFF " Exit Without Saving"), ImGui::GetCurrentWindow()); ImGui::SetFocusID(ImGui::GetID(ICON_FA_POWER_OFF " Exit Without Saving"), ImGui::GetCurrentWindow());
if (ActiveButton(ICON_FA_BACKWARD " Back To Pause Menu", false)) if (ActiveButton(ICON_FA_BACKWARD " Back To Pause Menu", false))
{ {
OpenPauseSubMenu(PauseSubMenu::None); OpenPauseSubMenu(PauseSubMenu::None);
} }
if (ActiveButton(ICON_FA_SYNC " Reset System", false)) if (ActiveButton(ICON_FA_SYNC " Reset System", false))
{ {
ClosePauseMenu(); ClosePauseMenu();
DoReset(); DoReset();
} }
if (ActiveButton(ICON_FA_SAVE " Exit And Save State", false)) if (ActiveButton(ICON_FA_SAVE " Exit And Save State", false))
DoShutdown(true); DoShutdown(true);
if (ActiveButton(ICON_FA_POWER_OFF " Exit Without Saving", false)) if (ActiveButton(ICON_FA_POWER_OFF " Exit Without Saving", false))
DoShutdown(false); DoShutdown(false);
} }
break; break;
@ -3904,13 +3910,13 @@ void FullscreenUI::DrawPauseMenu(MainWindowType type)
#ifdef WITH_CHEEVOS #ifdef WITH_CHEEVOS
case PauseSubMenu::Achievements: case PauseSubMenu::Achievements:
{ {
if (ActiveButton(ICON_FA_BACKWARD " Back To Pause Menu", false)) if (ActiveButton(ICON_FA_BACKWARD " Back To Pause Menu", false))
OpenPauseSubMenu(PauseSubMenu::None); OpenPauseSubMenu(PauseSubMenu::None);
if (ActiveButton(ICON_FA_TROPHY " Achievements", false)) if (ActiveButton(ICON_FA_TROPHY " Achievements", false))
OpenAchievementsWindow(); OpenAchievementsWindow();
if (ActiveButton(ICON_FA_STOPWATCH " Leaderboards", false)) if (ActiveButton(ICON_FA_STOPWATCH " Leaderboards", false))
OpenLeaderboardsWindow(); OpenLeaderboardsWindow();
} }
break; break;
@ -4470,7 +4476,7 @@ void FullscreenUI::DrawGameListWindow()
ImGui::SetCursorPosY(ImGui::GetWindowHeight() - LayoutScale(50.0f)); ImGui::SetCursorPosY(ImGui::GetWindowHeight() - LayoutScale(50.0f));
BeginMenuButtons(); BeginMenuButtons();
if (ActiveButton(ICON_FA_BACKWARD " Back", false)) if (ActiveButton(ICON_FA_BACKWARD " Back", false))
ReturnToMainWindow(); ReturnToMainWindow();
EndMenuButtons(); EndMenuButtons();
} }
@ -4582,14 +4588,14 @@ void FullscreenUI::DrawAboutWindow()
ImGui::NewLine(); ImGui::NewLine();
BeginMenuButtons(); BeginMenuButtons();
if (ActiveButton(ICON_FA_GLOBE " GitHub Repository", false)) if (ActiveButton(ICON_FA_GLOBE " GitHub Repository", false))
ExitFullscreenAndOpenURL("https://github.com/stenzek/duckstation/"); ExitFullscreenAndOpenURL("https://github.com/stenzek/duckstation/");
if (ActiveButton(ICON_FA_BUG " Issue Tracker", false)) if (ActiveButton(ICON_FA_BUG " Issue Tracker", false))
ExitFullscreenAndOpenURL("https://github.com/stenzek/duckstation/issues"); ExitFullscreenAndOpenURL("https://github.com/stenzek/duckstation/issues");
if (ActiveButton(ICON_FA_COMMENT " Discord Server", false)) if (ActiveButton(ICON_FA_COMMENT " Discord Server", false))
ExitFullscreenAndOpenURL("https://discord.gg/Buktv3t"); ExitFullscreenAndOpenURL("https://discord.gg/Buktv3t");
if (ActiveButton(ICON_FA_WINDOW_CLOSE " Close", false)) if (ActiveButton(ICON_FA_WINDOW_CLOSE " Close", false))
{ {
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
s_about_window_open = false; s_about_window_open = false;
@ -4625,7 +4631,7 @@ bool FullscreenUI::DrawErrorWindow(const char* message)
BeginMenuButtons(); BeginMenuButtons();
if (ActiveButton(ICON_FA_WINDOW_CLOSE " Close", false)) if (ActiveButton(ICON_FA_WINDOW_CLOSE " Close", false))
{ {
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
is_open = false; is_open = false;
@ -4666,13 +4672,13 @@ bool FullscreenUI::DrawConfirmWindow(const char* message, bool* result)
bool done = false; bool done = false;
if (ActiveButton(ICON_FA_CHECK " Yes", false)) if (ActiveButton(ICON_FA_CHECK " Yes", false))
{ {
*result = true; *result = true;
done = true; done = true;
} }
if (ActiveButton(ICON_FA_TIMES " No", false)) if (ActiveButton(ICON_FA_TIMES " No", false))
{ {
*result = false; *result = false;
done = true; done = true;

View File

@ -461,20 +461,21 @@ bool ImGuiManager::AddIconFonts(float size)
static constexpr ImWchar range_fa[] = { static constexpr ImWchar range_fa[] = {
0xf002, 0xf002, 0xf005, 0xf005, 0xf007, 0xf007, 0xf00c, 0xf00e, 0xf011, 0xf011, 0xf013, 0xf013, 0xf017, 0xf017, 0xf002, 0xf002, 0xf005, 0xf005, 0xf007, 0xf007, 0xf00c, 0xf00e, 0xf011, 0xf011, 0xf013, 0xf013, 0xf017, 0xf017,
0xf019, 0xf019, 0xf021, 0xf021, 0xf025, 0xf025, 0xf027, 0xf028, 0xf02d, 0xf02e, 0xf030, 0xf030, 0xf03a, 0xf03a, 0xf019, 0xf019, 0xf021, 0xf021, 0xf025, 0xf025, 0xf027, 0xf028, 0xf02d, 0xf02e, 0xf030, 0xf030, 0xf03a, 0xf03a,
0xf049, 0xf04c, 0xf050, 0xf050, 0xf059, 0xf059, 0xf05e, 0xf05e, 0xf065, 0xf065, 0xf067, 0xf067, 0xf071, 0xf071, 0xf03d, 0xf03d, 0xf049, 0xf04c, 0xf050, 0xf050, 0xf059, 0xf059, 0xf05e, 0xf05e, 0xf065, 0xf065, 0xf067, 0xf067,
0xf075, 0xf075, 0xf077, 0xf078, 0xf07b, 0xf07c, 0xf084, 0xf084, 0xf091, 0xf091, 0xf0a0, 0xf0a0, 0xf0ac, 0xf0ad, 0xf071, 0xf071, 0xf075, 0xf075, 0xf077, 0xf078, 0xf07b, 0xf07c, 0xf084, 0xf085, 0xf091, 0xf091, 0xf0a0, 0xf0a0,
0xf0c5, 0xf0c5, 0xf0c7, 0xf0c8, 0xf0cb, 0xf0cb, 0xf0d0, 0xf0d0, 0xf0e2, 0xf0e2, 0xf0eb, 0xf0eb, 0xf0f1, 0xf0f1, 0xf0ac, 0xf0ad, 0xf0c5, 0xf0c5, 0xf0c7, 0xf0c8, 0xf0cb, 0xf0cb, 0xf0d0, 0xf0d0, 0xf0e2, 0xf0e2, 0xf0eb, 0xf0eb,
0xf0f3, 0xf0f3, 0xf0fe, 0xf0fe, 0xf119, 0xf119, 0xf11b, 0xf11c, 0xf140, 0xf140, 0xf144, 0xf144, 0xf14a, 0xf14a, 0xf0f1, 0xf0f1, 0xf0f3, 0xf0f3, 0xf0fe, 0xf0fe, 0xf110, 0xf110, 0xf119, 0xf119, 0xf11b, 0xf11c, 0xf140, 0xf140,
0xf15b, 0xf15b, 0xf188, 0xf188, 0xf191, 0xf192, 0xf1dd, 0xf1de, 0xf1e6, 0xf1e6, 0xf1eb, 0xf1eb, 0xf1f8, 0xf1f8, 0xf144, 0xf144, 0xf14a, 0xf14a, 0xf15b, 0xf15b, 0xf188, 0xf188, 0xf191, 0xf192, 0xf1dd, 0xf1de, 0xf1e6, 0xf1e6,
0xf26c, 0xf26c, 0xf279, 0xf279, 0xf2d0, 0xf2d0, 0xf2db, 0xf2db, 0xf2f2, 0xf2f2, 0xf2f5, 0xf2f5, 0xf410, 0xf410, 0xf1eb, 0xf1eb, 0xf1f8, 0xf1f8, 0xf242, 0xf242, 0xf245, 0xf245, 0xf26c, 0xf26c, 0xf279, 0xf279, 0xf2d0, 0xf2d0,
0xf466, 0xf466, 0xf500, 0xf500, 0xf51f, 0xf51f, 0xf552, 0xf552, 0xf57a, 0xf57a, 0xf5a2, 0xf5a2, 0xf65d, 0xf65e, 0xf2db, 0xf2db, 0xf2f2, 0xf2f2, 0xf2f5, 0xf2f5, 0xf410, 0xf410, 0xf466, 0xf466, 0xf500, 0xf500, 0xf51f, 0xf51f,
0xf6a9, 0xf6a9, 0xf7c2, 0xf7c2, 0xf807, 0xf807, 0xf815, 0xf815, 0xf818, 0xf818, 0x0, 0x0}; 0xf545, 0xf545, 0xf548, 0xf548, 0xf552, 0xf552, 0xf57a, 0xf57a, 0xf5a2, 0xf5a2, 0xf5e7, 0xf5e7, 0xf65d, 0xf65e,
0xf6a9, 0xf6a9, 0xf7c2, 0xf7c2, 0xf807, 0xf807, 0xf815, 0xf815, 0xf818, 0xf818, 0xf8cc, 0xf8cc, 0x0, 0x0};
ImFontConfig cfg; ImFontConfig cfg;
cfg.MergeMode = true; cfg.MergeMode = true;
cfg.PixelSnapH = true; cfg.PixelSnapH = true;
cfg.GlyphMinAdvanceX = size * 0.75f; cfg.GlyphMinAdvanceX = size;
cfg.GlyphMaxAdvanceX = size * 0.75f; cfg.GlyphMaxAdvanceX = size;
cfg.FontDataOwnedByAtlas = false; cfg.FontDataOwnedByAtlas = false;
return (ImGui::GetIO().Fonts->AddFontFromMemoryTTF(s_icon_font_data.data(), static_cast<int>(s_icon_font_data.size()), return (ImGui::GetIO().Fonts->AddFontFromMemoryTTF(s_icon_font_data.data(), static_cast<int>(s_icon_font_data.size()),