FullscreenUI: Add custom title/disc set title/serial editing

This commit is contained in:
Stenzek
2026-07-04 13:04:52 +10:00
parent f9cf0db0bd
commit 4616c8513a
2 changed files with 211 additions and 7 deletions
+187 -7
View File
@@ -101,6 +101,11 @@ static void ProcessImageVerificationResults(std::string path, GameDatabase::Trac
static void DrawSummarySettingsPage(bool show_localized_titles);
static void DrawSummarySettingsTrackList();
static void OpenGameTitleActions(const std::string_view& path, const std::string_view& title, bool has_custom_title,
bool is_disc_set_title);
static void OpenGameSerialActions(const std::string& path, const std::string& serial, bool has_custom_serial);
static void SaveCustomTitle(const std::string& path, const std::string& title);
static void SaveCustomSerial(const std::string& path, const std::string& serial);
static void DrawInterfaceSettingsPage();
static void DrawGameListSettingsPage();
static void DrawBIOSSettingsPage();
@@ -1720,7 +1725,7 @@ bool FullscreenUI::SwitchToGameSettingsForPath(const std::string& path, Settings
const GameList::Entry* entry = !path.empty() ? GameList::GetEntryForPath(path) : nullptr;
// playlists will always contain the first disc's serial, so use the current game instead
if (!entry || entry->serial.empty() || entry->type == GameList::EntryType::Playlist)
if (!entry || entry->serial.empty() || (entry->type == GameList::EntryType::Playlist && VideoThread::HasGPUBackend()))
{
Host::RunOnCoreThread([page]() {
Error error;
@@ -2142,6 +2147,8 @@ void FullscreenUI::DrawSettingsWindow()
void FullscreenUI::DrawSummarySettingsPage(bool show_localized_titles)
{
SmallString sstr;
BeginMenuButtons();
ResetFocusHere();
@@ -2156,14 +2163,68 @@ void FullscreenUI::DrawSummarySettingsPage(bool show_localized_titles)
if (s_settings_locals.game_settings_entry)
{
if (MenuButton(FSUI_ICONVSTR(ICON_FA_WINDOW_MAXIMIZE, "Title"),
s_settings_locals.game_settings_entry->GetDisplayTitle(show_localized_titles), true))
const bool allow_customization = !s_settings_locals.game_settings_entry->is_runtime_populated;
const std::string_view title = s_settings_locals.game_settings_entry->GetDisplayTitle(show_localized_titles);
if (MenuButton(FSUI_ICONVSTR(ICON_FA_WINDOW_MAXIMIZE, "Title"), title, true))
{
CopyTextToClipboard(FSUI_STR("Game title copied to clipboard."),
s_settings_locals.game_settings_entry->GetDisplayTitle(show_localized_titles));
if (allow_customization)
{
OpenGameTitleActions(s_settings_locals.game_settings_entry->path, title,
s_settings_locals.game_settings_entry->has_custom_title, false);
}
else
{
CopyTextToClipboard(FSUI_STR("Game title copied to clipboard."), title);
}
}
if (MenuButton(FSUI_ICONVSTR(ICON_FA_PAGER, "Serial"), s_settings_locals.game_settings_entry->serial, true))
CopyTextToClipboard(FSUI_STR("Game serial copied to clipboard."), s_settings_locals.game_settings_entry->serial);
if (s_settings_locals.game_settings_entry->disc_set_member)
{
const std::string_view disc_set_name = s_settings_locals.game_settings_entry->GetDiscSetEntry()->GetSaveTitle();
std::string disc_set_title;
bool has_custom_disc_set_title = false;
{
const auto lock = GameList::GetLock();
const GameList::Entry* const disc_set_entry = GameList::GetEntryForPath(disc_set_name);
if (disc_set_entry)
{
disc_set_title = disc_set_entry->GetDisplayTitle(show_localized_titles);
has_custom_disc_set_title = disc_set_entry->has_custom_title;
}
}
if (!disc_set_title.empty() &&
MenuButton(FSUI_ICONVSTR(ICON_FA_LAYER_GROUP, "Disc Set Title"), disc_set_title, true))
{
if (allow_customization)
OpenGameTitleActions(disc_set_name, disc_set_title, has_custom_disc_set_title, true);
else
CopyTextToClipboard(FSUI_STR("Disc set title copied to clipboard."), disc_set_title);
}
}
std::string_view visible_serial = s_settings_locals.game_settings_entry->serial;
if (s_settings_locals.game_settings_entry->has_custom_serial)
{
sstr.format(FSUI_FSTR("{} (Custom)"), s_settings_locals.game_settings_entry->serial);
visible_serial = sstr;
}
if (MenuButton(FSUI_ICONVSTR(ICON_FA_PAGER, "Serial"), visible_serial, true))
{
if (allow_customization)
{
OpenGameSerialActions(s_settings_locals.game_settings_entry->path,
s_settings_locals.game_settings_entry->serial,
s_settings_locals.game_settings_entry->has_custom_serial);
}
else
{
CopyTextToClipboard(FSUI_STR("Game serial copied to clipboard."),
s_settings_locals.game_settings_entry->serial);
}
}
if (MenuButton(FSUI_ICONVSTR(ICON_FA_COMPACT_DISC, "Type"),
GameList::GetEntryTypeDisplayName(s_settings_locals.game_settings_entry->type), true))
{
@@ -2226,6 +2287,125 @@ void FullscreenUI::DrawSummarySettingsPage(bool show_localized_titles)
EndMenuButtons();
}
void FullscreenUI::OpenGameTitleActions(const std::string_view& path, const std::string_view& title,
bool has_custom_title, bool is_disc_set_title)
{
ChoiceDialogOptions options;
options.reserve(has_custom_title ? 4 : 3);
options.emplace_back(FSUI_ICONSTR(ICON_FA_FILE_PEN, "Change Title"), false);
if (has_custom_title)
options.emplace_back(FSUI_ICONSTR(ICON_FA_ARROW_ROTATE_LEFT, "Reset Title"), false);
options.emplace_back(FSUI_ICONSTR(ICON_FA_COPY, "Copy Title"), false);
options.emplace_back(FSUI_ICONSTR(ICON_FA_SQUARE_XMARK, "Close Menu"), false);
OpenChoiceDialog(is_disc_set_title ? FSUI_ICONVSTR(ICON_FA_LAYER_GROUP, "Disc Set Title") :
FSUI_ICONVSTR(ICON_FA_WINDOW_MAXIMIZE, "Game Title"),
false, std::move(options),
[path = std::string(path), title = std::string(title), has_custom_title,
is_disc_set_title](s32 index, const std::string&, bool) mutable {
if (index < 0)
return;
if (index == 0)
{
OpenInputStringDialog(is_disc_set_title ?
FSUI_ICONSTR(ICON_FA_LAYER_GROUP, "Change Disc Set Title") :
FSUI_ICONSTR(ICON_FA_WINDOW_MAXIMIZE, "Change Game Title"),
is_disc_set_title ? FSUI_STR("Enter a new title for this disc set.") :
FSUI_STR("Enter a new title for this game."),
FSUI_STR("Title:"), FSUI_ICONSTR(ICON_FA_CHECK, "Save"), title,
[path = std::move(path)](std::string new_title) mutable {
if (!new_title.empty())
SaveCustomTitle(std::move(path), std::move(new_title));
});
}
else if (has_custom_title && index == 1)
{
SaveCustomTitle(std::move(path), {});
}
else if (index == (has_custom_title ? 2 : 1))
{
CopyTextToClipboard(is_disc_set_title ? FSUI_STR("Disc set title copied to clipboard.") :
FSUI_STR("Game title copied to clipboard."),
title);
}
});
}
void FullscreenUI::OpenGameSerialActions(const std::string& path, const std::string& serial, bool has_custom_serial)
{
ChoiceDialogOptions options;
options.reserve(has_custom_serial ? 4 : 3);
options.emplace_back(FSUI_ICONSTR(ICON_FA_FILE_PEN, "Change Serial"), false);
if (has_custom_serial)
options.emplace_back(FSUI_ICONSTR(ICON_FA_ARROW_ROTATE_LEFT, "Reset Serial"), false);
options.emplace_back(FSUI_ICONSTR(ICON_FA_COPY, "Copy Serial"), false);
options.emplace_back(FSUI_ICONSTR(ICON_FA_SQUARE_XMARK, "Close Menu"), false);
OpenChoiceDialog(FSUI_ICONVSTR(ICON_FA_PAGER, "Game Serial"), false, std::move(options),
[path, serial, has_custom_serial](s32 index, const std::string&, bool) mutable {
if (index < 0)
return;
if (index == 0)
{
OpenInputStringDialog(FSUI_ICONSTR(ICON_FA_PAGER, "Change Game Serial"),
FSUI_STR("Enter a new serial for this game."), FSUI_STR("Serial:"),
FSUI_ICONSTR(ICON_FA_CHECK, "Save"), serial,
[path = std::move(path)](std::string new_serial) mutable {
StringUtil::StripWhitespace(&new_serial);
if (!new_serial.empty())
SaveCustomSerial(std::move(path), std::move(new_serial));
});
}
else if (has_custom_serial && index == 1)
{
SaveCustomSerial(std::move(path), {});
}
else if (index == (has_custom_serial ? 2 : 1))
{
CopyTextToClipboard(FSUI_STR("Game serial copied to clipboard."), serial);
}
});
}
void FullscreenUI::SaveCustomTitle(const std::string& path, const std::string& title)
{
if (!GameList::SaveCustomTitleForPath(path, title))
{
ShowToast(OSDMessageType::Error, {}, FSUI_STR("Failed to save custom title."));
return;
}
if (!s_settings_locals.game_settings_entry || s_settings_locals.game_settings_entry->path != path)
return;
const auto lock = GameList::GetLock();
const GameList::Entry* const entry = GameList::GetEntryForPath(path);
if (entry)
{
SwitchToGameSettings(entry, SettingsPage::Summary);
ShowToast(OSDMessageType::Info, {}, FSUI_STR("Game title updated."));
}
}
void FullscreenUI::SaveCustomSerial(const std::string& path, const std::string& serial)
{
if (!GameList::SaveCustomSerialForPath(path, serial))
{
ShowToast(OSDMessageType::Error, {}, FSUI_STR("Failed to save custom serial."));
return;
}
const auto lock = GameList::GetLock();
const GameList::Entry* const entry = GameList::GetEntryForPath(path);
if (entry)
{
SwitchToGameSettings(entry, SettingsPage::Summary);
ShowToast(OSDMessageType::Info, {}, FSUI_STR("Game serial updated."));
}
}
void FullscreenUI::DrawSummarySettingsTrackList()
{
DebugAssert(!s_settings_locals.image_track_list.empty());
+24
View File
@@ -143,8 +143,13 @@ TRANSLATE_NOOP("FullscreenUI", "Cancel");
TRANSLATE_NOOP("FullscreenUI", "Capture");
TRANSLATE_NOOP("FullscreenUI", "Challenge Indicators");
TRANSLATE_NOOP("FullscreenUI", "Change Disc");
TRANSLATE_NOOP("FullscreenUI", "Change Disc Set Title");
TRANSLATE_NOOP("FullscreenUI", "Change Game Serial");
TRANSLATE_NOOP("FullscreenUI", "Change Game Title");
TRANSLATE_NOOP("FullscreenUI", "Change Page");
TRANSLATE_NOOP("FullscreenUI", "Change Selection");
TRANSLATE_NOOP("FullscreenUI", "Change Serial");
TRANSLATE_NOOP("FullscreenUI", "Change Title");
TRANSLATE_NOOP("FullscreenUI", "Change View");
TRANSLATE_NOOP("FullscreenUI", "Changes settings for the application.");
TRANSLATE_NOOP("FullscreenUI", "Changes the aspect ratio used to display the console's output to the screen.");
@@ -185,7 +190,9 @@ TRANSLATE_NOOP("FullscreenUI", "Controls the volume of the audio played on the h
TRANSLATE_NOOP("FullscreenUI", "Copies the current global settings to this game.");
TRANSLATE_NOOP("FullscreenUI", "Copies the global controller configuration to this game.");
TRANSLATE_NOOP("FullscreenUI", "Copy Global Settings");
TRANSLATE_NOOP("FullscreenUI", "Copy Serial");
TRANSLATE_NOOP("FullscreenUI", "Copy Settings");
TRANSLATE_NOOP("FullscreenUI", "Copy Title");
TRANSLATE_NOOP("FullscreenUI", "Could not find any CD/DVD-ROM devices. Please ensure you have a drive connected and sufficient permissions to access it.");
TRANSLATE_NOOP("FullscreenUI", "Cover Download Error");
TRANSLATE_NOOP("FullscreenUI", "Cover Downloader");
@@ -265,6 +272,8 @@ TRANSLATE_NOOP("FullscreenUI", "Disabled");
TRANSLATE_NOOP("FullscreenUI", "Disables texture emulation in the GPU, forcing all primitives to only show vertex colours.");
TRANSLATE_NOOP("FullscreenUI", "Disables vertex lighting in the GPU, forcing all primitives to only show raw texture colours.");
TRANSLATE_NOOP("FullscreenUI", "Disc");
TRANSLATE_NOOP("FullscreenUI", "Disc Set Title");
TRANSLATE_NOOP("FullscreenUI", "Disc set title copied to clipboard.");
TRANSLATE_NOOP("FullscreenUI", "Discord Server");
TRANSLATE_NOOP("FullscreenUI", "Display Area");
TRANSLATE_NOOP("FullscreenUI", "Displays only the game title in the list, instead of the title and serial/file name.");
@@ -332,6 +341,9 @@ TRANSLATE_NOOP("FullscreenUI", "Enables the replacement of background textures i
TRANSLATE_NOOP("FullscreenUI", "Encore Mode");
TRANSLATE_NOOP("FullscreenUI", "Ensures every frame generated is displayed for optimal pacing. Enable for variable refresh displays, such as GSync/FreeSync. Disable if you are having speed or sound issues.");
TRANSLATE_NOOP("FullscreenUI", "Enter Value");
TRANSLATE_NOOP("FullscreenUI", "Enter a new serial for this game.");
TRANSLATE_NOOP("FullscreenUI", "Enter a new title for this disc set.");
TRANSLATE_NOOP("FullscreenUI", "Enter a new title for this game.");
TRANSLATE_NOOP("FullscreenUI", "Enter the name of the controller preset you wish to create.");
TRANSLATE_NOOP("FullscreenUI", "Error");
TRANSLATE_NOOP("FullscreenUI", "Error Message Duration");
@@ -351,6 +363,8 @@ TRANSLATE_NOOP("FullscreenUI", "Failed to load '{}'.");
TRANSLATE_NOOP("FullscreenUI", "Failed to load resume save state info.");
TRANSLATE_NOOP("FullscreenUI", "Failed to load shader {}. It may be invalid.\nError was:");
TRANSLATE_NOOP("FullscreenUI", "Failed to save controller preset '{}'.");
TRANSLATE_NOOP("FullscreenUI", "Failed to save custom serial.");
TRANSLATE_NOOP("FullscreenUI", "Failed to save custom title.");
TRANSLATE_NOOP("FullscreenUI", "Fast Boot");
TRANSLATE_NOOP("FullscreenUI", "Fast Forward Boot");
TRANSLATE_NOOP("FullscreenUI", "Fast Forward Memory Card Access");
@@ -382,14 +396,18 @@ TRANSLATE_NOOP("FullscreenUI", "Game List Settings");
TRANSLATE_NOOP("FullscreenUI", "Game Patches");
TRANSLATE_NOOP("FullscreenUI", "Game Properties");
TRANSLATE_NOOP("FullscreenUI", "Game Quick Save");
TRANSLATE_NOOP("FullscreenUI", "Game Serial");
TRANSLATE_NOOP("FullscreenUI", "Game Slot {0}##game_slot_{0}");
TRANSLATE_NOOP("FullscreenUI", "Game Title");
TRANSLATE_NOOP("FullscreenUI", "Game compatibility rating copied to clipboard.");
TRANSLATE_NOOP("FullscreenUI", "Game path copied to clipboard.");
TRANSLATE_NOOP("FullscreenUI", "Game region copied to clipboard.");
TRANSLATE_NOOP("FullscreenUI", "Game serial copied to clipboard.");
TRANSLATE_NOOP("FullscreenUI", "Game serial updated.");
TRANSLATE_NOOP("FullscreenUI", "Game settings have been cleared for '{}'.");
TRANSLATE_NOOP("FullscreenUI", "Game settings initialized with global settings for '{}'.");
TRANSLATE_NOOP("FullscreenUI", "Game title copied to clipboard.");
TRANSLATE_NOOP("FullscreenUI", "Game title updated.");
TRANSLATE_NOOP("FullscreenUI", "Game type copied to clipboard.");
TRANSLATE_NOOP("FullscreenUI", "Gamepad Button Type");
TRANSLATE_NOOP("FullscreenUI", "Genre: ");
@@ -613,7 +631,9 @@ TRANSLATE_NOOP("FullscreenUI", "Rescan All Games");
TRANSLATE_NOOP("FullscreenUI", "Reset");
TRANSLATE_NOOP("FullscreenUI", "Reset Controller Settings");
TRANSLATE_NOOP("FullscreenUI", "Reset Play Time");
TRANSLATE_NOOP("FullscreenUI", "Reset Serial");
TRANSLATE_NOOP("FullscreenUI", "Reset Settings");
TRANSLATE_NOOP("FullscreenUI", "Reset Title");
TRANSLATE_NOOP("FullscreenUI", "Reset To Default");
TRANSLATE_NOOP("FullscreenUI", "Resets all configuration to defaults (including bindings).");
TRANSLATE_NOOP("FullscreenUI", "Resets all settings to the defaults.");
@@ -641,6 +661,7 @@ TRANSLATE_NOOP("FullscreenUI", "Runs the software renderer in parallel for VRAM
TRANSLATE_NOOP("FullscreenUI", "SDL DualSense Player LED");
TRANSLATE_NOOP("FullscreenUI", "SDL DualShock 4 / DualSense Enhanced Mode");
TRANSLATE_NOOP("FullscreenUI", "Safe Mode");
TRANSLATE_NOOP("FullscreenUI", "Save");
TRANSLATE_NOOP("FullscreenUI", "Save Controller Preset");
TRANSLATE_NOOP("FullscreenUI", "Save Locations");
TRANSLATE_NOOP("FullscreenUI", "Save Preset");
@@ -698,6 +719,7 @@ TRANSLATE_NOOP("FullscreenUI", "Selects the type of emulated controller for this
TRANSLATE_NOOP("FullscreenUI", "Selects the view that the game list will open to.");
TRANSLATE_NOOP("FullscreenUI", "Selects which location on the screen messages are displayed.");
TRANSLATE_NOOP("FullscreenUI", "Serial");
TRANSLATE_NOOP("FullscreenUI", "Serial:");
TRANSLATE_NOOP("FullscreenUI", "Session: {}");
TRANSLATE_NOOP("FullscreenUI", "Set Cover Image");
TRANSLATE_NOOP("FullscreenUI", "Set Input Binding");
@@ -812,6 +834,7 @@ TRANSLATE_NOOP("FullscreenUI", "Time Played");
TRANSLATE_NOOP("FullscreenUI", "Time Played: ");
TRANSLATE_NOOP("FullscreenUI", "Timing out in {:.0f} seconds...");
TRANSLATE_NOOP("FullscreenUI", "Title");
TRANSLATE_NOOP("FullscreenUI", "Title:");
TRANSLATE_NOOP("FullscreenUI", "To use achievements, please log in with your retroachievements.org account.");
TRANSLATE_NOOP("FullscreenUI", "Toggle Analog");
TRANSLATE_NOOP("FullscreenUI", "Toggle Fast Forward");
@@ -900,6 +923,7 @@ TRANSLATE_NOOP("FullscreenUI", "change disc");
TRANSLATE_NOOP("FullscreenUI", "restart");
TRANSLATE_NOOP("FullscreenUI", "shut down");
TRANSLATE_NOOP("FullscreenUI", "{0} achievement unlocks have not been confirmed by the server. Continuing to {1} will result in loss of these unlocks. Once network connectivity has been re-established, these unlocks will be confirmed automatically.\n\nDo you want to {1} anyway?");
TRANSLATE_NOOP("FullscreenUI", "{} (Custom)");
TRANSLATE_NOOP("FullscreenUI", "{} Frames");
TRANSLATE_NOOP("FullscreenUI", "{} deleted.");
TRANSLATE_NOOP("FullscreenUI", "{} does not exist.");