2020-09-15 20:57:54 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
2020-05-24 08:29:29 +00:00
|
|
|
//
|
2020-09-15 20:57:54 +00:00
|
|
|
// EmulationStation Desktop Edition
|
2020-06-21 12:25:28 +00:00
|
|
|
// GuiMenu.cpp
|
2020-05-24 08:29:29 +00:00
|
|
|
//
|
2020-06-21 12:25:28 +00:00
|
|
|
// Main menu.
|
|
|
|
// Some submenus are covered in separate source files.
|
2020-05-24 08:29:29 +00:00
|
|
|
//
|
|
|
|
|
2014-06-25 16:29:58 +00:00
|
|
|
#include "guis/GuiMenu.h"
|
2017-11-01 22:21:10 +00:00
|
|
|
|
2022-04-11 22:18:51 +00:00
|
|
|
#if defined(_WIN64)
|
|
|
|
// Why this is needed here is anyone's guess but without it the compilation fails.
|
|
|
|
#include <winsock2.h>
|
|
|
|
#endif
|
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
#include "CollectionSystemsManager.h"
|
|
|
|
#include "EmulationStation.h"
|
|
|
|
#include "FileFilterIndex.h"
|
|
|
|
#include "FileSorts.h"
|
|
|
|
#include "Scripting.h"
|
|
|
|
#include "SystemData.h"
|
2022-01-17 20:53:23 +00:00
|
|
|
#include "UIModeController.h"
|
2021-07-07 18:03:42 +00:00
|
|
|
#include "VolumeControl.h"
|
2017-11-01 22:21:10 +00:00
|
|
|
#include "components/OptionListComponent.h"
|
|
|
|
#include "components/SliderComponent.h"
|
|
|
|
#include "components/SwitchComponent.h"
|
2021-08-22 13:26:38 +00:00
|
|
|
#include "guis/GuiAlternativeEmulators.h"
|
2017-06-12 16:38:59 +00:00
|
|
|
#include "guis/GuiCollectionSystemsOptions.h"
|
2014-06-25 16:29:58 +00:00
|
|
|
#include "guis/GuiDetectDevice.h"
|
2021-05-16 11:12:31 +00:00
|
|
|
#include "guis/GuiMediaViewerOptions.h"
|
2017-11-01 22:21:10 +00:00
|
|
|
#include "guis/GuiMsgBox.h"
|
2020-06-06 11:10:33 +00:00
|
|
|
#include "guis/GuiScraperMenu.h"
|
2021-05-16 11:12:31 +00:00
|
|
|
#include "guis/GuiScreensaverOptions.h"
|
2021-09-17 20:23:41 +00:00
|
|
|
#include "guis/GuiTextEditKeyboardPopup.h"
|
|
|
|
#include "guis/GuiTextEditPopup.h"
|
2022-01-10 17:56:04 +00:00
|
|
|
#include "utils/PlatformUtil.h"
|
2020-06-26 16:03:55 +00:00
|
|
|
|
|
|
|
#include <SDL2/SDL_events.h>
|
2021-07-07 18:03:42 +00:00
|
|
|
#include <algorithm>
|
2020-06-26 16:03:55 +00:00
|
|
|
|
2022-01-19 17:01:54 +00:00
|
|
|
GuiMenu::GuiMenu()
|
|
|
|
: mMenu {"MAIN MENU"}
|
2014-06-25 16:29:58 +00:00
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
bool isFullUI = UIModeController::getInstance()->isUIModeFull();
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
if (isFullUI)
|
2021-05-22 20:48:44 +00:00
|
|
|
addEntry("SCRAPER", 0x777777FF, true, [this] { openScraperOptions(); });
|
2020-06-06 11:10:33 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
if (isFullUI)
|
2021-05-22 20:48:44 +00:00
|
|
|
addEntry("UI SETTINGS", 0x777777FF, true, [this] { openUIOptions(); });
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2021-05-22 20:48:44 +00:00
|
|
|
addEntry("SOUND SETTINGS", 0x777777FF, true, [this] { openSoundOptions(); });
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2021-05-23 08:35:59 +00:00
|
|
|
if (isFullUI)
|
2021-07-07 18:03:42 +00:00
|
|
|
addEntry("INPUT DEVICE SETTINGS", 0x777777FF, true, [this] { openInputDeviceOptions(); });
|
2021-05-23 08:35:59 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
if (isFullUI)
|
2021-07-07 18:03:42 +00:00
|
|
|
addEntry("GAME COLLECTION SETTINGS", 0x777777FF, true,
|
|
|
|
[this] { openCollectionSystemOptions(); });
|
2017-09-08 14:49:47 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
if (isFullUI)
|
2021-05-22 20:48:44 +00:00
|
|
|
addEntry("OTHER SETTINGS", 0x777777FF, true, [this] { openOtherOptions(); });
|
2017-09-08 14:49:47 +00:00
|
|
|
|
2021-10-18 16:12:19 +00:00
|
|
|
// TEMPORARY: Disabled for now, will be used in the future.
|
2021-07-07 18:03:42 +00:00
|
|
|
// if (isFullUI)
|
|
|
|
// addEntry("UTILITIES", 0x777777FF, true, [this] {
|
|
|
|
// openUtilitiesMenu(); });
|
2021-05-23 09:03:56 +00:00
|
|
|
|
2020-12-17 22:45:29 +00:00
|
|
|
if (!Settings::getInstance()->getBool("ForceKiosk") &&
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getString("UIMode") != "kiosk") {
|
2020-12-17 22:45:29 +00:00
|
|
|
if (Settings::getInstance()->getBool("ShowQuitMenu"))
|
2021-07-07 18:03:42 +00:00
|
|
|
addEntry("QUIT", 0x777777FF, true, [this] { openQuitMenu(); });
|
2020-12-17 22:45:29 +00:00
|
|
|
else
|
2021-07-07 18:03:42 +00:00
|
|
|
addEntry("QUIT EMULATIONSTATION", 0x777777FF, false, [this] { openQuitMenu(); });
|
2020-12-17 22:45:29 +00:00
|
|
|
}
|
2017-09-08 14:49:47 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
addChild(&mMenu);
|
|
|
|
addVersionInfo();
|
|
|
|
setSize(mMenu.getSize());
|
2021-08-16 16:25:01 +00:00
|
|
|
setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f, Renderer::getScreenHeight() * 0.13f);
|
2017-09-08 14:49:47 +00:00
|
|
|
}
|
|
|
|
|
2020-09-15 20:57:54 +00:00
|
|
|
GuiMenu::~GuiMenu()
|
|
|
|
{
|
|
|
|
// This is required for the situation where scrolling started just before the menu
|
|
|
|
// was openened. Without this, the scrolling would run until manually stopped after
|
|
|
|
// the menu has been closed.
|
2022-01-04 20:49:22 +00:00
|
|
|
ViewController::getInstance()->stopScrolling();
|
2022-02-19 16:04:23 +00:00
|
|
|
|
|
|
|
ViewController::getInstance()->startViewVideos();
|
2020-09-15 20:57:54 +00:00
|
|
|
}
|
|
|
|
|
2021-08-22 12:29:43 +00:00
|
|
|
void GuiMenu::openScraperOptions()
|
|
|
|
{
|
|
|
|
// Open the scraper menu.
|
2022-01-19 17:01:54 +00:00
|
|
|
mWindow->pushGui(new GuiScraperMenu("SCRAPER"));
|
2021-08-22 12:29:43 +00:00
|
|
|
}
|
2017-09-08 14:49:47 +00:00
|
|
|
|
2021-05-22 20:48:44 +00:00
|
|
|
void GuiMenu::openUIOptions()
|
2017-09-08 14:49:47 +00:00
|
|
|
{
|
2022-01-19 17:01:54 +00:00
|
|
|
auto s = new GuiSettings("UI SETTINGS");
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2022-01-31 22:53:32 +00:00
|
|
|
// Theme options section.
|
|
|
|
|
2022-04-09 13:57:37 +00:00
|
|
|
std::map<std::string, ThemeData::ThemeSet, ThemeData::StringComparator> themeSets {
|
|
|
|
ThemeData::getThemeSets()};
|
|
|
|
std::map<std::string, ThemeData::ThemeSet, ThemeData::StringComparator>::const_iterator
|
|
|
|
selectedSet;
|
2022-01-31 22:53:32 +00:00
|
|
|
|
2022-02-01 17:06:32 +00:00
|
|
|
auto theme_set =
|
|
|
|
std::make_shared<OptionListComponent<std::string>>(getHelpStyle(), "THEME SET", false);
|
|
|
|
|
2022-01-31 22:53:32 +00:00
|
|
|
// Theme selection.
|
|
|
|
if (!themeSets.empty()) {
|
|
|
|
selectedSet = themeSets.find(Settings::getInstance()->getString("ThemeSet"));
|
|
|
|
if (selectedSet == themeSets.cend())
|
|
|
|
selectedSet = themeSets.cbegin();
|
|
|
|
|
|
|
|
for (auto it = themeSets.cbegin(); it != themeSets.cend(); ++it) {
|
|
|
|
// If required, abbreviate the theme set name so it doesn't overlap the setting name.
|
|
|
|
float maxNameLength = mSize.x * 0.62f;
|
|
|
|
theme_set->add(it->first, it->first, it == selectedSet, maxNameLength);
|
2020-07-15 16:02:11 +00:00
|
|
|
}
|
2022-01-31 22:53:32 +00:00
|
|
|
s->addWithLabel("THEME SET", theme_set);
|
|
|
|
s->addSaveFunc([this, theme_set, s] {
|
|
|
|
if (theme_set->getSelected() != Settings::getInstance()->getString("ThemeSet")) {
|
|
|
|
Scripting::fireEvent("theme-changed", theme_set->getSelected(),
|
|
|
|
Settings::getInstance()->getString("ThemeSet"));
|
|
|
|
Settings::getInstance()->setString("ThemeSet", theme_set->getSelected());
|
|
|
|
mWindow->setChangedThemeSet();
|
|
|
|
// This is required so that the custom collection system does not disappear
|
|
|
|
// if the user is editing a custom collection when switching theme sets.
|
2022-03-24 22:05:23 +00:00
|
|
|
if (CollectionSystemsManager::getInstance()->isEditing())
|
2022-01-31 22:53:32 +00:00
|
|
|
CollectionSystemsManager::getInstance()->exitEditMode();
|
2022-03-24 22:05:23 +00:00
|
|
|
// TODO: Eliminate this extra reload or only execute it when switching from
|
|
|
|
// a legacy theme to a non-legacy theme.
|
|
|
|
ViewController::getInstance()->reloadAll();
|
2022-01-31 22:53:32 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsReloading();
|
|
|
|
s->setNeedsGoToStart();
|
2022-03-24 22:05:23 +00:00
|
|
|
s->setNeedsCollectionsUpdate();
|
2022-01-31 22:53:32 +00:00
|
|
|
s->setInvalidateCachedBackground();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
}
|
2022-01-31 22:53:32 +00:00
|
|
|
|
|
|
|
// Theme variants.
|
|
|
|
auto themeVariant =
|
|
|
|
std::make_shared<OptionListComponent<std::string>>(getHelpStyle(), "THEME VARIANT", false);
|
2022-02-01 17:06:32 +00:00
|
|
|
s->addWithLabel("THEME VARIANT", themeVariant);
|
|
|
|
s->addSaveFunc([themeVariant, s] {
|
|
|
|
if (themeVariant->getSelected() != Settings::getInstance()->getString("ThemeVariant")) {
|
|
|
|
Settings::getInstance()->setString("ThemeVariant", themeVariant->getSelected());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsReloading();
|
|
|
|
s->setInvalidateCachedBackground();
|
2020-11-05 17:18:11 +00:00
|
|
|
}
|
2022-02-01 17:06:32 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
auto themeVariantsFunc = [=](const std::string& selectedTheme,
|
|
|
|
const std::string& selectedVariant) {
|
2022-04-09 13:57:37 +00:00
|
|
|
std::map<std::string, ThemeData::ThemeSet, ThemeData::StringComparator>::const_iterator
|
|
|
|
currentSet {themeSets.find(selectedTheme)};
|
2022-02-01 17:06:32 +00:00
|
|
|
if (currentSet == themeSets.cend())
|
|
|
|
return;
|
|
|
|
// We need to recreate the OptionListComponent entries.
|
|
|
|
themeVariant->clearEntries();
|
|
|
|
int selectableVariants {0};
|
|
|
|
for (auto& variant : currentSet->second.capabilities.variants) {
|
|
|
|
if (variant.selectable)
|
|
|
|
++selectableVariants;
|
|
|
|
}
|
|
|
|
if (selectableVariants > 0) {
|
|
|
|
for (auto& variant : currentSet->second.capabilities.variants) {
|
|
|
|
if (variant.selectable) {
|
|
|
|
// If required, abbreviate the variant name so it doesn't overlap the
|
|
|
|
// setting name.
|
|
|
|
float maxNameLength {mSize.x * 0.62f};
|
|
|
|
themeVariant->add(variant.label, variant.name, variant.name == selectedVariant,
|
|
|
|
maxNameLength);
|
|
|
|
}
|
2022-01-31 22:53:32 +00:00
|
|
|
}
|
2022-02-01 17:06:32 +00:00
|
|
|
if (themeVariant->getSelectedObjects().size() == 0)
|
|
|
|
themeVariant->selectEntry(0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (currentSet->second.capabilities.legacyTheme)
|
|
|
|
themeVariant->add("Legacy theme set", "none", true);
|
|
|
|
else
|
|
|
|
themeVariant->add("None defined", "none", true);
|
|
|
|
themeVariant->setEnabled(false);
|
|
|
|
themeVariant->setOpacity(DISABLED_OPACITY);
|
|
|
|
themeVariant->getParent()
|
|
|
|
->getChild(themeVariant->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
themeVariantsFunc(Settings::getInstance()->getString("ThemeSet"),
|
|
|
|
Settings::getInstance()->getString("ThemeVariant"));
|
2022-01-31 22:53:32 +00:00
|
|
|
|
|
|
|
// Theme aspect ratios.
|
|
|
|
auto themeAspectRatio = std::make_shared<OptionListComponent<std::string>>(
|
|
|
|
getHelpStyle(), "THEME ASPECT RATIO", false);
|
2022-02-01 17:06:32 +00:00
|
|
|
s->addWithLabel("THEME ASPECT RATIO", themeAspectRatio);
|
|
|
|
s->addSaveFunc([themeAspectRatio, s] {
|
|
|
|
if (themeAspectRatio->getSelected() !=
|
|
|
|
Settings::getInstance()->getString("ThemeAspectRatio")) {
|
|
|
|
Settings::getInstance()->setString("ThemeAspectRatio", themeAspectRatio->getSelected());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsReloading();
|
|
|
|
s->setInvalidateCachedBackground();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
auto themeAspectRatiosFunc = [=](const std::string& selectedTheme,
|
|
|
|
const std::string& selectedAspectRatio) {
|
2022-04-09 13:57:37 +00:00
|
|
|
std::map<std::string, ThemeData::ThemeSet, ThemeData::StringComparator>::const_iterator
|
|
|
|
currentSet {themeSets.find(selectedTheme)};
|
2022-02-01 17:06:32 +00:00
|
|
|
if (currentSet == themeSets.cend())
|
|
|
|
return;
|
|
|
|
// We need to recreate the OptionListComponent entries.
|
|
|
|
themeAspectRatio->clearEntries();
|
|
|
|
if (currentSet->second.capabilities.aspectRatios.size() > 0) {
|
|
|
|
for (auto& aspectRatio : currentSet->second.capabilities.aspectRatios)
|
|
|
|
themeAspectRatio->add(ThemeData::getAspectRatioLabel(aspectRatio), aspectRatio,
|
|
|
|
aspectRatio == selectedAspectRatio);
|
|
|
|
if (themeAspectRatio->getSelectedObjects().size() == 0)
|
|
|
|
themeAspectRatio->selectEntry(0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (currentSet->second.capabilities.legacyTheme)
|
|
|
|
themeAspectRatio->add("Legacy theme set", "none", true);
|
|
|
|
else
|
|
|
|
themeAspectRatio->add("None defined", "none", true);
|
|
|
|
themeAspectRatio->setEnabled(false);
|
|
|
|
themeAspectRatio->setOpacity(DISABLED_OPACITY);
|
|
|
|
themeAspectRatio->getParent()
|
|
|
|
->getChild(themeAspectRatio->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
themeAspectRatiosFunc(Settings::getInstance()->getString("ThemeSet"),
|
|
|
|
Settings::getInstance()->getString("ThemeAspectRatio"));
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2022-01-31 22:53:32 +00:00
|
|
|
// Legacy gamelist view style.
|
2021-07-07 18:03:42 +00:00
|
|
|
auto gamelist_view_style = std::make_shared<OptionListComponent<std::string>>(
|
2022-01-31 22:53:32 +00:00
|
|
|
getHelpStyle(), "LEGACY GAMELIST VIEW STYLE", false);
|
2021-03-21 10:21:45 +00:00
|
|
|
std::string selectedViewStyle = Settings::getInstance()->getString("GamelistViewStyle");
|
|
|
|
gamelist_view_style->add("automatic", "automatic", selectedViewStyle == "automatic");
|
|
|
|
gamelist_view_style->add("basic", "basic", selectedViewStyle == "basic");
|
|
|
|
gamelist_view_style->add("detailed", "detailed", selectedViewStyle == "detailed");
|
|
|
|
gamelist_view_style->add("video", "video", selectedViewStyle == "video");
|
|
|
|
// If there are no objects returned, then there must be a manually modified entry in the
|
|
|
|
// configuration file. Simply set the view style to Automatic in this case.
|
|
|
|
if (gamelist_view_style->getSelectedObjects().size() == 0)
|
|
|
|
gamelist_view_style->selectEntry(0);
|
2022-01-31 22:53:32 +00:00
|
|
|
s->addWithLabel("LEGACY GAMELIST VIEW STYLE", gamelist_view_style);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([gamelist_view_style, s] {
|
|
|
|
if (gamelist_view_style->getSelected() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getString("GamelistViewStyle")) {
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setString("GamelistViewStyle",
|
2021-07-07 18:03:42 +00:00
|
|
|
gamelist_view_style->getSelected());
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsReloading();
|
2021-03-21 17:46:45 +00:00
|
|
|
s->setInvalidateCachedBackground();
|
2020-11-05 17:18:11 +00:00
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
});
|
|
|
|
|
2022-01-31 22:53:32 +00:00
|
|
|
// Legacy ransition style.
|
2021-07-07 18:03:42 +00:00
|
|
|
auto transition_style = std::make_shared<OptionListComponent<std::string>>(
|
2022-01-31 22:53:32 +00:00
|
|
|
getHelpStyle(), "LEGACY TRANSITION STYLE", false);
|
2020-06-21 12:25:28 +00:00
|
|
|
std::vector<std::string> transitions;
|
|
|
|
transitions.push_back("slide");
|
2020-12-25 16:25:23 +00:00
|
|
|
transitions.push_back("fade");
|
2020-06-21 12:25:28 +00:00
|
|
|
transitions.push_back("instant");
|
2021-11-17 16:35:34 +00:00
|
|
|
for (auto it = transitions.cbegin(); it != transitions.cend(); ++it)
|
2021-07-07 18:03:42 +00:00
|
|
|
transition_style->add(*it, *it,
|
|
|
|
Settings::getInstance()->getString("TransitionStyle") == *it);
|
2022-01-31 22:53:32 +00:00
|
|
|
s->addWithLabel("LEGACY TRANSITION STYLE", transition_style);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([transition_style, s] {
|
|
|
|
if (transition_style->getSelected() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getString("TransitionStyle")) {
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setString("TransitionStyle", transition_style->getSelected());
|
|
|
|
s->setNeedsSaving();
|
2020-06-21 12:25:28 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2022-01-31 22:53:32 +00:00
|
|
|
// Optionally start in selected system/gamelist.
|
|
|
|
auto startupSystem = std::make_shared<OptionListComponent<std::string>>(
|
|
|
|
getHelpStyle(), "GAMELIST ON STARTUP", false);
|
|
|
|
startupSystem->add("NONE", "", Settings::getInstance()->getString("StartupSystem") == "");
|
|
|
|
for (auto it = SystemData::sSystemVector.cbegin(); // Line break.
|
|
|
|
it != SystemData::sSystemVector.cend(); ++it) {
|
|
|
|
if ((*it)->getName() != "retropie") {
|
|
|
|
// If required, abbreviate the system name so it doesn't overlap the setting name.
|
|
|
|
float maxNameLength = mSize.x * 0.48f;
|
|
|
|
startupSystem->add((*it)->getFullName(), (*it)->getName(),
|
|
|
|
Settings::getInstance()->getString("StartupSystem") ==
|
|
|
|
(*it)->getName(),
|
|
|
|
maxNameLength);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// This can probably not happen but as an extra precaution select the "NONE" entry if no
|
|
|
|
// entry is selected.
|
|
|
|
if (startupSystem->getSelectedObjects().size() == 0)
|
|
|
|
startupSystem->selectEntry(0);
|
|
|
|
s->addWithLabel("GAMELIST ON STARTUP", startupSystem);
|
|
|
|
s->addSaveFunc([startupSystem, s] {
|
|
|
|
if (startupSystem->getSelected() != Settings::getInstance()->getString("StartupSystem")) {
|
|
|
|
Settings::getInstance()->setString("StartupSystem", startupSystem->getSelected());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Default gamelist sort order.
|
|
|
|
std::string sortOrder;
|
|
|
|
auto default_sort_order = std::make_shared<OptionListComponent<const FileData::SortType*>>(
|
|
|
|
getHelpStyle(), "DEFAULT SORT ORDER", false);
|
|
|
|
// Exclude the System sort options.
|
|
|
|
unsigned int numSortTypes = static_cast<unsigned int>(FileSorts::SortTypes.size() - 2);
|
|
|
|
for (unsigned int i = 0; i < numSortTypes; ++i) {
|
|
|
|
if (FileSorts::SortTypes[i].description ==
|
|
|
|
Settings::getInstance()->getString("DefaultSortOrder")) {
|
|
|
|
sortOrder = FileSorts::SortTypes[i].description;
|
|
|
|
break;
|
2021-10-09 11:09:14 +00:00
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
}
|
2022-01-31 22:53:32 +00:00
|
|
|
// If an invalid sort order was defined in es_settings.xml, then apply the default
|
|
|
|
// sort order 'filename, ascending'.
|
|
|
|
if (sortOrder == "")
|
|
|
|
sortOrder = Settings::getInstance()->getDefaultString("DefaultSortOrder");
|
|
|
|
for (unsigned int i = 0; i < numSortTypes; ++i) {
|
|
|
|
const FileData::SortType& sort = FileSorts::SortTypes[i];
|
|
|
|
if (sort.description == sortOrder)
|
|
|
|
default_sort_order->add(sort.description, &sort, true);
|
|
|
|
else
|
|
|
|
default_sort_order->add(sort.description, &sort, false);
|
|
|
|
}
|
|
|
|
s->addWithLabel("DEFAULT SORT ORDER", default_sort_order);
|
|
|
|
s->addSaveFunc([default_sort_order, sortOrder, s] {
|
|
|
|
std::string selectedSortOrder = default_sort_order.get()->getSelected()->description;
|
|
|
|
if (selectedSortOrder != sortOrder) {
|
|
|
|
Settings::getInstance()->setString("DefaultSortOrder", selectedSortOrder);
|
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsSorting();
|
|
|
|
s->setNeedsSortingCollections();
|
|
|
|
s->setInvalidateCachedBackground();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Open menu effect.
|
|
|
|
auto menu_opening_effect = std::make_shared<OptionListComponent<std::string>>(
|
|
|
|
getHelpStyle(), "MENU OPENING EFFECT", false);
|
|
|
|
std::string selectedMenuEffect = Settings::getInstance()->getString("MenuOpeningEffect");
|
|
|
|
menu_opening_effect->add("SCALE-UP", "scale-up", selectedMenuEffect == "scale-up");
|
|
|
|
menu_opening_effect->add("NONE", "none", selectedMenuEffect == "none");
|
|
|
|
// If there are no objects returned, then there must be a manually modified entry in the
|
|
|
|
// configuration file. Simply set the opening effect to "scale-up" in this case.
|
|
|
|
if (menu_opening_effect->getSelectedObjects().size() == 0)
|
|
|
|
menu_opening_effect->selectEntry(0);
|
|
|
|
s->addWithLabel("MENU OPENING EFFECT", menu_opening_effect);
|
|
|
|
s->addSaveFunc([menu_opening_effect, s] {
|
|
|
|
if (menu_opening_effect->getSelected() !=
|
|
|
|
Settings::getInstance()->getString("MenuOpeningEffect")) {
|
|
|
|
Settings::getInstance()->setString("MenuOpeningEffect",
|
|
|
|
menu_opening_effect->getSelected());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Launch screen duration.
|
|
|
|
auto launch_screen_duration = std::make_shared<OptionListComponent<std::string>>(
|
|
|
|
getHelpStyle(), "LAUNCH SCREEN DURATION", false);
|
|
|
|
std::string selectedDuration = Settings::getInstance()->getString("LaunchScreenDuration");
|
|
|
|
launch_screen_duration->add("NORMAL", "normal", selectedDuration == "normal");
|
|
|
|
launch_screen_duration->add("BRIEF", "brief", selectedDuration == "brief");
|
|
|
|
launch_screen_duration->add("LONG", "long", selectedDuration == "long");
|
|
|
|
launch_screen_duration->add("DISABLED", "disabled", selectedDuration == "disabled");
|
|
|
|
// If there are no objects returned, then there must be a manually modified entry in the
|
|
|
|
// configuration file. Simply set the duration to "normal" in this case.
|
|
|
|
if (launch_screen_duration->getSelectedObjects().size() == 0)
|
|
|
|
launch_screen_duration->selectEntry(0);
|
|
|
|
s->addWithLabel("LAUNCH SCREEN DURATION", launch_screen_duration);
|
|
|
|
s->addSaveFunc([launch_screen_duration, s] {
|
|
|
|
if (launch_screen_duration->getSelected() !=
|
|
|
|
Settings::getInstance()->getString("LaunchScreenDuration")) {
|
|
|
|
Settings::getInstance()->setString("LaunchScreenDuration",
|
|
|
|
launch_screen_duration->getSelected());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
// UI mode.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto ui_mode =
|
|
|
|
std::make_shared<OptionListComponent<std::string>>(getHelpStyle(), "UI MODE", false);
|
2020-11-05 17:18:11 +00:00
|
|
|
std::vector<std::string> uiModes;
|
|
|
|
uiModes.push_back("full");
|
|
|
|
uiModes.push_back("kiosk");
|
|
|
|
uiModes.push_back("kid");
|
2020-12-17 22:45:29 +00:00
|
|
|
std::string setMode;
|
|
|
|
if (Settings::getInstance()->getBool("ForceKiosk"))
|
|
|
|
setMode = "kiosk";
|
|
|
|
else if (Settings::getInstance()->getBool("ForceKid"))
|
|
|
|
setMode = "kid";
|
|
|
|
else
|
|
|
|
setMode = Settings::getInstance()->getString("UIMode");
|
2021-11-17 16:35:34 +00:00
|
|
|
for (auto it = uiModes.cbegin(); it != uiModes.cend(); ++it)
|
2020-12-17 22:45:29 +00:00
|
|
|
ui_mode->add(*it, *it, setMode == *it);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addWithLabel("UI MODE", ui_mode);
|
|
|
|
s->addSaveFunc([ui_mode, this, s] {
|
|
|
|
std::string selectedMode = ui_mode->getSelected();
|
2021-01-05 09:45:32 +00:00
|
|
|
// If any of the force flags are set, then always apply and save the setting.
|
|
|
|
if (selectedMode == Settings::getInstance()->getString("UIMode") &&
|
2021-07-07 18:03:42 +00:00
|
|
|
!Settings::getInstance()->getBool("ForceFull") &&
|
|
|
|
!Settings::getInstance()->getBool("ForceKiosk") &&
|
|
|
|
!Settings::getInstance()->getBool("ForceKid")) {
|
2021-01-05 09:45:32 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (selectedMode != "full") {
|
2021-01-17 10:11:07 +00:00
|
|
|
std::string msg = "YOU ARE CHANGING THE UI TO THE RESTRICTED MODE\n'" +
|
2021-07-07 18:03:42 +00:00
|
|
|
Utils::String::toUpper(selectedMode) + "'\n";
|
2021-01-17 10:11:07 +00:00
|
|
|
if (selectedMode == "kiosk") {
|
|
|
|
msg += "THIS WILL HIDE MOST MENU OPTIONS TO PREVENT\n";
|
|
|
|
msg += "CHANGES TO THE SYSTEM\n";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
msg += "THIS WILL LIMIT THE AVAILABLE GAMES TO THE ONES\n";
|
|
|
|
msg += "FLAGGED SUITABLE FOR CHILDREN\n";
|
|
|
|
}
|
2020-06-22 15:27:53 +00:00
|
|
|
msg += "TO UNLOCK AND RETURN TO THE FULL UI, ENTER THIS CODE: \n";
|
2021-01-17 10:11:07 +00:00
|
|
|
msg += UIModeController::getInstance()->getFormattedPassKeyStr() + "\n\n";
|
2020-06-22 15:27:53 +00:00
|
|
|
msg += "DO YOU WANT TO PROCEED?";
|
2021-07-07 18:03:42 +00:00
|
|
|
mWindow->pushGui(new GuiMsgBox(
|
2022-01-19 17:01:54 +00:00
|
|
|
this->getHelpStyle(), msg, "YES",
|
2021-07-07 18:03:42 +00:00
|
|
|
[this, selectedMode] {
|
|
|
|
LOG(LogDebug) << "GuiMenu::openUISettings(): Setting UI mode to '"
|
|
|
|
<< selectedMode << "'.";
|
|
|
|
Settings::getInstance()->setString("UIMode", selectedMode);
|
|
|
|
Settings::getInstance()->setBool("ForceFull", false);
|
|
|
|
Settings::getInstance()->setBool("ForceKiosk", false);
|
|
|
|
Settings::getInstance()->setBool("ForceKid", false);
|
|
|
|
Settings::getInstance()->saveFile();
|
|
|
|
UIModeController::getInstance()->setCurrentUIMode(selectedMode);
|
|
|
|
for (auto it = SystemData::sSystemVector.cbegin();
|
2021-11-17 16:35:34 +00:00
|
|
|
it != SystemData::sSystemVector.cend(); ++it) {
|
2021-07-07 18:03:42 +00:00
|
|
|
if ((*it)->getThemeFolder() == "custom-collections") {
|
|
|
|
for (FileData* customSystem :
|
|
|
|
(*it)->getRootFolder()->getChildrenListToDisplay())
|
|
|
|
customSystem->getSystem()->getIndex()->resetFilters();
|
|
|
|
}
|
|
|
|
(*it)->sortSystem();
|
|
|
|
(*it)->getIndex()->resetFilters();
|
2021-01-05 09:45:32 +00:00
|
|
|
}
|
2022-01-04 20:49:22 +00:00
|
|
|
ViewController::getInstance()->reloadAll();
|
|
|
|
ViewController::getInstance()->goToSystem(SystemData::sSystemVector.front(),
|
|
|
|
false);
|
2021-07-07 18:03:42 +00:00
|
|
|
mWindow->invalidateCachedBackground();
|
|
|
|
},
|
|
|
|
"NO", nullptr));
|
2020-11-05 17:18:11 +00:00
|
|
|
}
|
2021-01-05 09:45:32 +00:00
|
|
|
else {
|
2021-07-07 18:03:42 +00:00
|
|
|
LOG(LogDebug) << "GuiMenu::openUISettings(): Setting UI mode to '" << selectedMode
|
|
|
|
<< "'.";
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setString("UIMode", ui_mode->getSelected());
|
2020-12-17 22:45:29 +00:00
|
|
|
Settings::getInstance()->setBool("ForceFull", false);
|
|
|
|
Settings::getInstance()->setBool("ForceKiosk", false);
|
|
|
|
Settings::getInstance()->setBool("ForceKid", false);
|
2021-01-05 09:45:32 +00:00
|
|
|
UIModeController::getInstance()->setCurrentUIMode("full");
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
2021-01-05 09:45:32 +00:00
|
|
|
s->setNeedsSorting();
|
|
|
|
s->setNeedsSortingCollections();
|
|
|
|
s->setNeedsResetFilters();
|
|
|
|
s->setNeedsReloading();
|
|
|
|
s->setNeedsGoToSystem(SystemData::sSystemVector.front());
|
2021-03-21 17:46:45 +00:00
|
|
|
s->setInvalidateCachedBackground();
|
2020-06-21 12:25:28 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-08-22 12:29:43 +00:00
|
|
|
// Media viewer.
|
|
|
|
ComponentListRow media_viewer_row;
|
|
|
|
media_viewer_row.elements.clear();
|
2022-01-19 17:01:54 +00:00
|
|
|
media_viewer_row.addElement(std::make_shared<TextComponent>("MEDIA VIEWER SETTINGS",
|
2021-08-22 12:29:43 +00:00
|
|
|
Font::get(FONT_SIZE_MEDIUM),
|
|
|
|
0x777777FF),
|
|
|
|
true);
|
2022-01-19 17:01:54 +00:00
|
|
|
media_viewer_row.addElement(makeArrow(), false);
|
2021-08-22 12:29:43 +00:00
|
|
|
media_viewer_row.makeAcceptInputHandler(std::bind(&GuiMenu::openMediaViewerOptions, this));
|
|
|
|
s->addRow(media_viewer_row);
|
|
|
|
|
|
|
|
// Screensaver.
|
|
|
|
ComponentListRow screensaver_row;
|
|
|
|
screensaver_row.elements.clear();
|
2022-01-19 17:01:54 +00:00
|
|
|
screensaver_row.addElement(std::make_shared<TextComponent>(
|
|
|
|
"SCREENSAVER SETTINGS", Font::get(FONT_SIZE_MEDIUM), 0x777777FF),
|
2021-08-22 12:29:43 +00:00
|
|
|
true);
|
2022-01-19 17:01:54 +00:00
|
|
|
screensaver_row.addElement(makeArrow(), false);
|
2021-08-22 12:29:43 +00:00
|
|
|
screensaver_row.makeAcceptInputHandler(std::bind(&GuiMenu::openScreensaverOptions, this));
|
|
|
|
s->addRow(screensaver_row);
|
|
|
|
|
2021-03-18 18:46:45 +00:00
|
|
|
// Blur background when the menu is open.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto menu_blur_background = std::make_shared<SwitchComponent>();
|
2021-03-18 18:46:45 +00:00
|
|
|
menu_blur_background->setState(Settings::getInstance()->getBool("MenuBlurBackground"));
|
|
|
|
s->addWithLabel("BLUR BACKGROUND WHEN MENU IS OPEN", menu_blur_background);
|
|
|
|
s->addSaveFunc([menu_blur_background, s] {
|
|
|
|
if (menu_blur_background->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("MenuBlurBackground")) {
|
2021-03-18 18:46:45 +00:00
|
|
|
Settings::getInstance()->setBool("MenuBlurBackground",
|
2021-07-07 18:03:42 +00:00
|
|
|
menu_blur_background->getState());
|
2021-03-18 18:46:45 +00:00
|
|
|
s->setNeedsSaving();
|
2021-03-21 17:46:45 +00:00
|
|
|
s->setInvalidateCachedBackground();
|
2021-03-18 18:46:45 +00:00
|
|
|
}
|
|
|
|
});
|
2020-09-13 12:28:06 +00:00
|
|
|
|
2020-11-17 16:20:25 +00:00
|
|
|
// Display pillarboxes (and letterboxes) for videos in the gamelists.
|
2022-02-12 16:47:59 +00:00
|
|
|
auto gamelistVideoPillarbox = std::make_shared<SwitchComponent>();
|
|
|
|
gamelistVideoPillarbox->setState(Settings::getInstance()->getBool("GamelistVideoPillarbox"));
|
|
|
|
s->addWithLabel("DISPLAY PILLARBOXES FOR GAMELIST VIDEOS", gamelistVideoPillarbox);
|
|
|
|
s->addSaveFunc([gamelistVideoPillarbox, s] {
|
|
|
|
if (gamelistVideoPillarbox->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("GamelistVideoPillarbox")) {
|
2020-11-17 16:20:25 +00:00
|
|
|
Settings::getInstance()->setBool("GamelistVideoPillarbox",
|
2022-02-12 16:47:59 +00:00
|
|
|
gamelistVideoPillarbox->getState());
|
2020-11-17 16:20:25 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
// Render scanlines for videos in the gamelists.
|
2022-02-12 16:47:59 +00:00
|
|
|
auto gamelistVideoScanlines = std::make_shared<SwitchComponent>();
|
|
|
|
gamelistVideoScanlines->setState(Settings::getInstance()->getBool("GamelistVideoScanlines"));
|
|
|
|
s->addWithLabel("RENDER SCANLINES FOR GAMELIST VIDEOS", gamelistVideoScanlines);
|
|
|
|
s->addSaveFunc([gamelistVideoScanlines, s] {
|
|
|
|
if (gamelistVideoScanlines->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("GamelistVideoScanlines")) {
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setBool("GamelistVideoScanlines",
|
2022-02-12 16:47:59 +00:00
|
|
|
gamelistVideoScanlines->getState());
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-09-13 11:21:38 +00:00
|
|
|
|
2020-07-28 17:44:17 +00:00
|
|
|
// Sort folders on top of the gamelists.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto folders_on_top = std::make_shared<SwitchComponent>();
|
2020-07-28 17:44:17 +00:00
|
|
|
folders_on_top->setState(Settings::getInstance()->getBool("FoldersOnTop"));
|
|
|
|
s->addWithLabel("SORT FOLDERS ON TOP OF GAMELISTS", folders_on_top);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([folders_on_top, s] {
|
2021-07-07 18:03:42 +00:00
|
|
|
if (folders_on_top->getState() != Settings::getInstance()->getBool("FoldersOnTop")) {
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setBool("FoldersOnTop", folders_on_top->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsSorting();
|
2021-03-21 17:46:45 +00:00
|
|
|
s->setInvalidateCachedBackground();
|
2020-07-28 17:44:17 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Sort favorites on top of non-favorites in the gamelists.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto favorites_first = std::make_shared<SwitchComponent>();
|
2020-07-28 17:44:17 +00:00
|
|
|
favorites_first->setState(Settings::getInstance()->getBool("FavoritesFirst"));
|
|
|
|
s->addWithLabel("SORT FAVORITE GAMES ABOVE NON-FAVORITES", favorites_first);
|
2021-07-07 18:03:42 +00:00
|
|
|
s->addSaveFunc([favorites_first, s] {
|
|
|
|
if (favorites_first->getState() != Settings::getInstance()->getBool("FavoritesFirst")) {
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setBool("FavoritesFirst", favorites_first->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsSorting();
|
|
|
|
s->setNeedsSortingCollections();
|
2021-03-21 17:46:45 +00:00
|
|
|
s->setInvalidateCachedBackground();
|
2020-06-21 12:25:28 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-10-25 20:29:54 +00:00
|
|
|
// Enable gamelist star markings for favorite games.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto favorites_star = std::make_shared<SwitchComponent>();
|
2020-11-05 17:18:11 +00:00
|
|
|
favorites_star->setState(Settings::getInstance()->getBool("FavoritesStar"));
|
|
|
|
s->addWithLabel("ADD STAR MARKINGS TO FAVORITE GAMES", favorites_star);
|
|
|
|
s->addSaveFunc([favorites_star, s] {
|
|
|
|
if (favorites_star->getState() != Settings::getInstance()->getBool("FavoritesStar")) {
|
|
|
|
Settings::getInstance()->setBool("FavoritesStar", favorites_star->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsReloading();
|
2021-03-21 17:46:45 +00:00
|
|
|
s->setInvalidateCachedBackground();
|
2020-10-25 20:29:54 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-01-12 21:41:28 +00:00
|
|
|
// Enable quick list scrolling overlay.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto list_scroll_overlay = std::make_shared<SwitchComponent>();
|
2021-01-12 21:41:28 +00:00
|
|
|
list_scroll_overlay->setState(Settings::getInstance()->getBool("ListScrollOverlay"));
|
|
|
|
s->addWithLabel("ENABLE QUICK LIST SCROLLING OVERLAY", list_scroll_overlay);
|
|
|
|
s->addSaveFunc([list_scroll_overlay, s] {
|
|
|
|
if (list_scroll_overlay->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("ListScrollOverlay")) {
|
2021-01-12 21:41:28 +00:00
|
|
|
Settings::getInstance()->setBool("ListScrollOverlay", list_scroll_overlay->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-09-17 20:23:41 +00:00
|
|
|
// Enable virtual (on-screen) keyboard.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto virtual_keyboard = std::make_shared<SwitchComponent>();
|
2021-09-17 20:23:41 +00:00
|
|
|
virtual_keyboard->setState(Settings::getInstance()->getBool("VirtualKeyboard"));
|
|
|
|
s->addWithLabel("ENABLE VIRTUAL KEYBOARD", virtual_keyboard);
|
|
|
|
s->addSaveFunc([virtual_keyboard, s] {
|
|
|
|
if (virtual_keyboard->getState() != Settings::getInstance()->getBool("VirtualKeyboard")) {
|
|
|
|
Settings::getInstance()->setBool("VirtualKeyboard", virtual_keyboard->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setInvalidateCachedBackground();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-10-10 16:15:37 +00:00
|
|
|
// Enable menu scroll indicators.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto scroll_indicators = std::make_shared<SwitchComponent>();
|
2021-10-10 16:15:37 +00:00
|
|
|
scroll_indicators->setState(Settings::getInstance()->getBool("ScrollIndicators"));
|
|
|
|
s->addWithLabel("ENABLE MENU SCROLL INDICATORS", scroll_indicators);
|
|
|
|
s->addSaveFunc([scroll_indicators, s] {
|
|
|
|
if (scroll_indicators->getState() != Settings::getInstance()->getBool("ScrollIndicators")) {
|
|
|
|
Settings::getInstance()->setBool("ScrollIndicators", scroll_indicators->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setInvalidateCachedBackground();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-10-31 09:01:19 +00:00
|
|
|
// Enable the 'Y' button for tagging games as favorites.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto favorites_add_button = std::make_shared<SwitchComponent>();
|
2020-10-31 09:01:19 +00:00
|
|
|
favorites_add_button->setState(Settings::getInstance()->getBool("FavoritesAddButton"));
|
2021-05-16 12:03:13 +00:00
|
|
|
s->addWithLabel("ENABLE TOGGLE FAVORITES BUTTON", favorites_add_button);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([favorites_add_button, s] {
|
2020-10-31 09:01:19 +00:00
|
|
|
if (Settings::getInstance()->getBool("FavoritesAddButton") !=
|
2021-07-07 18:03:42 +00:00
|
|
|
favorites_add_button->getState()) {
|
2020-10-31 09:01:19 +00:00
|
|
|
Settings::getInstance()->setBool("FavoritesAddButton",
|
2021-07-07 18:03:42 +00:00
|
|
|
favorites_add_button->getState());
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
2020-10-31 09:01:19 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-05-16 12:03:13 +00:00
|
|
|
// Enable the thumbstick click buttons for jumping to a random system or game.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto random_add_button = std::make_shared<SwitchComponent>();
|
2021-05-16 12:03:13 +00:00
|
|
|
random_add_button->setState(Settings::getInstance()->getBool("RandomAddButton"));
|
|
|
|
s->addWithLabel("ENABLE RANDOM SYSTEM OR GAME BUTTON", random_add_button);
|
|
|
|
s->addSaveFunc([random_add_button, s] {
|
2021-07-07 18:03:42 +00:00
|
|
|
if (Settings::getInstance()->getBool("RandomAddButton") != random_add_button->getState()) {
|
|
|
|
Settings::getInstance()->setBool("RandomAddButton", random_add_button->getState());
|
2021-05-16 12:03:13 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
// Gamelist filters.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto gamelist_filters = std::make_shared<SwitchComponent>();
|
2020-11-05 17:18:11 +00:00
|
|
|
gamelist_filters->setState(Settings::getInstance()->getBool("GamelistFilters"));
|
|
|
|
s->addWithLabel("ENABLE GAMELIST FILTERS", gamelist_filters);
|
|
|
|
s->addSaveFunc([gamelist_filters, s] {
|
2021-07-07 18:03:42 +00:00
|
|
|
if (Settings::getInstance()->getBool("GamelistFilters") != gamelist_filters->getState()) {
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setBool("GamelistFilters", gamelist_filters->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsReloading();
|
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
});
|
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
// Quick system select (navigate left/right in gamelist view).
|
2022-01-19 17:01:54 +00:00
|
|
|
auto quick_system_select = std::make_shared<SwitchComponent>();
|
2020-11-05 17:18:11 +00:00
|
|
|
quick_system_select->setState(Settings::getInstance()->getBool("QuickSystemSelect"));
|
|
|
|
s->addWithLabel("ENABLE QUICK SYSTEM SELECT", quick_system_select);
|
|
|
|
s->addSaveFunc([quick_system_select, s] {
|
|
|
|
if (Settings::getInstance()->getBool("QuickSystemSelect") !=
|
2021-07-07 18:03:42 +00:00
|
|
|
quick_system_select->getState()) {
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setBool("QuickSystemSelect", quick_system_select->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
// On-screen help prompts.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto show_help_prompts = std::make_shared<SwitchComponent>();
|
2020-11-05 17:18:11 +00:00
|
|
|
show_help_prompts->setState(Settings::getInstance()->getBool("ShowHelpPrompts"));
|
|
|
|
s->addWithLabel("DISPLAY ON-SCREEN HELP", show_help_prompts);
|
|
|
|
s->addSaveFunc([show_help_prompts, s] {
|
|
|
|
if (Settings::getInstance()->getBool("ShowHelpPrompts") != show_help_prompts->getState()) {
|
|
|
|
Settings::getInstance()->setBool("ShowHelpPrompts", show_help_prompts->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2022-02-12 16:47:59 +00:00
|
|
|
// When the theme set entries are scrolled or selected, update the relevant rows.
|
|
|
|
auto scrollThemeSetFunc = [=](const std::string& themeName, bool firstRun = false) {
|
|
|
|
auto selectedSet = themeSets.find(themeName);
|
|
|
|
if (selectedSet == themeSets.cend())
|
|
|
|
return;
|
|
|
|
if (!firstRun) {
|
|
|
|
themeVariantsFunc(themeName, themeVariant->getSelected());
|
|
|
|
themeAspectRatiosFunc(themeName, themeAspectRatio->getSelected());
|
|
|
|
}
|
|
|
|
int selectableVariants {0};
|
|
|
|
for (auto& variant : selectedSet->second.capabilities.variants) {
|
|
|
|
if (variant.selectable)
|
|
|
|
++selectableVariants;
|
|
|
|
}
|
|
|
|
if (!selectedSet->second.capabilities.legacyTheme && selectableVariants > 0) {
|
|
|
|
themeVariant->setEnabled(true);
|
|
|
|
themeVariant->setOpacity(1.0f);
|
|
|
|
themeVariant->getParent()
|
|
|
|
->getChild(themeVariant->getChildIndex() - 1)
|
|
|
|
->setOpacity(1.0f);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
themeVariant->setEnabled(false);
|
|
|
|
themeVariant->setOpacity(DISABLED_OPACITY);
|
|
|
|
themeVariant->getParent()
|
|
|
|
->getChild(themeVariant->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!selectedSet->second.capabilities.legacyTheme &&
|
|
|
|
selectedSet->second.capabilities.aspectRatios.size() > 0) {
|
|
|
|
themeAspectRatio->setEnabled(true);
|
|
|
|
themeAspectRatio->setOpacity(1.0f);
|
|
|
|
themeAspectRatio->getParent()
|
|
|
|
->getChild(themeAspectRatio->getChildIndex() - 1)
|
|
|
|
->setOpacity(1.0f);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
themeAspectRatio->setEnabled(false);
|
|
|
|
themeAspectRatio->setOpacity(DISABLED_OPACITY);
|
|
|
|
themeAspectRatio->getParent()
|
|
|
|
->getChild(themeAspectRatio->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
|
|
|
}
|
|
|
|
if (!selectedSet->second.capabilities.legacyTheme) {
|
|
|
|
gamelist_view_style->setEnabled(false);
|
|
|
|
gamelist_view_style->setOpacity(DISABLED_OPACITY);
|
|
|
|
gamelist_view_style->getParent()
|
|
|
|
->getChild(gamelist_view_style->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
|
|
|
// TEMPORARY
|
|
|
|
// transition_style->setEnabled(false);
|
|
|
|
transition_style->setOpacity(DISABLED_OPACITY);
|
|
|
|
transition_style->getParent()
|
|
|
|
->getChild(transition_style->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
|
|
|
|
|
|
|
// Pillarboxes are theme-controlled for newer themes.
|
|
|
|
gamelistVideoPillarbox->setEnabled(false);
|
|
|
|
gamelistVideoPillarbox->setOpacity(DISABLED_OPACITY);
|
|
|
|
gamelistVideoPillarbox->getParent()
|
|
|
|
->getChild(gamelistVideoPillarbox->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
|
|
|
|
|
|
|
// Scanlines are theme-controlled for newer themes.
|
|
|
|
gamelistVideoScanlines->setEnabled(false);
|
|
|
|
gamelistVideoScanlines->setOpacity(DISABLED_OPACITY);
|
|
|
|
gamelistVideoScanlines->getParent()
|
|
|
|
->getChild(gamelistVideoScanlines->getChildIndex() - 1)
|
|
|
|
->setOpacity(DISABLED_OPACITY);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
gamelist_view_style->setEnabled(true);
|
|
|
|
gamelist_view_style->setOpacity(1.0f);
|
|
|
|
gamelist_view_style->getParent()
|
|
|
|
->getChild(gamelist_view_style->getChildIndex() - 1)
|
|
|
|
->setOpacity(1.0f);
|
|
|
|
|
|
|
|
transition_style->setEnabled(true);
|
|
|
|
transition_style->setOpacity(1.0f);
|
|
|
|
transition_style->getParent()
|
|
|
|
->getChild(transition_style->getChildIndex() - 1)
|
|
|
|
->setOpacity(1.0f);
|
|
|
|
|
|
|
|
gamelistVideoPillarbox->setEnabled(true);
|
|
|
|
gamelistVideoPillarbox->setOpacity(1.0f);
|
|
|
|
gamelistVideoPillarbox->getParent()
|
|
|
|
->getChild(gamelistVideoPillarbox->getChildIndex() - 1)
|
|
|
|
->setOpacity(1.0f);
|
|
|
|
|
|
|
|
gamelistVideoScanlines->setEnabled(true);
|
|
|
|
gamelistVideoScanlines->setOpacity(1.0f);
|
|
|
|
gamelistVideoScanlines->getParent()
|
|
|
|
->getChild(gamelistVideoScanlines->getChildIndex() - 1)
|
|
|
|
->setOpacity(1.0f);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
scrollThemeSetFunc(selectedSet->first, true);
|
|
|
|
theme_set->setCallback(scrollThemeSetFunc);
|
|
|
|
|
2021-10-24 12:11:19 +00:00
|
|
|
s->setSize(mSize);
|
2020-06-21 12:25:28 +00:00
|
|
|
mWindow->pushGui(s);
|
2017-09-08 14:49:47 +00:00
|
|
|
}
|
|
|
|
|
2021-05-22 20:48:44 +00:00
|
|
|
void GuiMenu::openSoundOptions()
|
2020-11-05 17:18:11 +00:00
|
|
|
{
|
2022-01-19 17:01:54 +00:00
|
|
|
auto s = new GuiSettings("SOUND SETTINGS");
|
2020-11-05 17:18:11 +00:00
|
|
|
|
2021-10-18 16:12:19 +00:00
|
|
|
// TODO: Hide the volume slider on macOS and BSD Unix until the volume control logic has been
|
|
|
|
// implemented for these operating systems.
|
2021-07-07 18:03:42 +00:00
|
|
|
#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
|
2020-11-05 17:18:11 +00:00
|
|
|
// System volume.
|
2022-01-04 20:21:26 +00:00
|
|
|
// The reason to create the VolumeControl object every time instead of making it a singleton
|
|
|
|
// is that this is the easiest way to detect new default audio devices or changes to the
|
|
|
|
// audio volume done by the operating system. And we don't really need this object laying
|
|
|
|
// around anyway as it's only used here.
|
|
|
|
VolumeControl volumeControl;
|
|
|
|
int currentVolume = volumeControl.getVolume();
|
|
|
|
|
2022-01-19 17:01:54 +00:00
|
|
|
auto systemVolume = std::make_shared<SliderComponent>(0.f, 100.f, 1.f, "%");
|
2022-01-04 20:21:26 +00:00
|
|
|
systemVolume->setValue(static_cast<float>(currentVolume));
|
|
|
|
s->addWithLabel("SYSTEM VOLUME", systemVolume);
|
|
|
|
s->addSaveFunc([systemVolume, currentVolume] {
|
|
|
|
// No need to create the VolumeControl object unless the volume has actually been changed.
|
|
|
|
if (static_cast<int>(systemVolume->getValue()) != currentVolume) {
|
|
|
|
VolumeControl volumeControl;
|
|
|
|
volumeControl.setVolume(static_cast<int>(std::round(systemVolume->getValue())));
|
|
|
|
}
|
2020-11-05 17:18:11 +00:00
|
|
|
});
|
2021-07-07 18:03:42 +00:00
|
|
|
#endif
|
2020-11-05 17:18:11 +00:00
|
|
|
|
2020-12-20 15:41:58 +00:00
|
|
|
// Volume for navigation sounds.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto sound_volume_navigation = std::make_shared<SliderComponent>(0.f, 100.f, 1.f, "%");
|
2021-07-07 18:03:42 +00:00
|
|
|
sound_volume_navigation->setValue(
|
|
|
|
static_cast<float>(Settings::getInstance()->getInt("SoundVolumeNavigation")));
|
2020-12-20 23:23:22 +00:00
|
|
|
s->addWithLabel("NAVIGATION SOUNDS VOLUME", sound_volume_navigation);
|
2020-12-20 15:41:58 +00:00
|
|
|
s->addSaveFunc([sound_volume_navigation, s] {
|
|
|
|
if (sound_volume_navigation->getValue() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
static_cast<float>(Settings::getInstance()->getInt("SoundVolumeNavigation"))) {
|
2020-12-20 15:41:58 +00:00
|
|
|
Settings::getInstance()->setInt("SoundVolumeNavigation",
|
2021-07-07 18:03:42 +00:00
|
|
|
static_cast<int>(sound_volume_navigation->getValue()));
|
2020-12-20 15:41:58 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Volume for videos.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto sound_volume_videos = std::make_shared<SliderComponent>(0.f, 100.f, 1.f, "%");
|
2021-07-07 18:03:42 +00:00
|
|
|
sound_volume_videos->setValue(
|
|
|
|
static_cast<float>(Settings::getInstance()->getInt("SoundVolumeVideos")));
|
2020-12-20 23:23:22 +00:00
|
|
|
s->addWithLabel("VIDEO PLAYER VOLUME", sound_volume_videos);
|
2020-12-20 15:41:58 +00:00
|
|
|
s->addSaveFunc([sound_volume_videos, s] {
|
|
|
|
if (sound_volume_videos->getValue() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
static_cast<float>(Settings::getInstance()->getInt("SoundVolumeVideos"))) {
|
2020-12-20 15:41:58 +00:00
|
|
|
Settings::getInstance()->setInt("SoundVolumeVideos",
|
2021-07-07 18:03:42 +00:00
|
|
|
static_cast<int>(sound_volume_videos->getValue()));
|
2020-12-20 15:41:58 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
if (UIModeController::getInstance()->isUIModeFull()) {
|
2021-05-16 11:12:31 +00:00
|
|
|
// Play audio for gamelist videos.
|
2022-02-20 15:07:27 +00:00
|
|
|
auto viewsVideoAudio = std::make_shared<SwitchComponent>();
|
|
|
|
viewsVideoAudio->setState(Settings::getInstance()->getBool("ViewsVideoAudio"));
|
|
|
|
s->addWithLabel("PLAY AUDIO FOR GAMELIST AND SYSTEM VIEW VIDEOS", viewsVideoAudio);
|
|
|
|
s->addSaveFunc([viewsVideoAudio, s] {
|
|
|
|
if (viewsVideoAudio->getState() !=
|
|
|
|
Settings::getInstance()->getBool("ViewsVideoAudio")) {
|
|
|
|
Settings::getInstance()->setBool("ViewsVideoAudio", viewsVideoAudio->getState());
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-05-16 11:12:31 +00:00
|
|
|
// Play audio for media viewer videos.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto media_viewer_video_audio = std::make_shared<SwitchComponent>();
|
2021-07-07 18:03:42 +00:00
|
|
|
media_viewer_video_audio->setState(
|
|
|
|
Settings::getInstance()->getBool("MediaViewerVideoAudio"));
|
2021-05-16 11:12:31 +00:00
|
|
|
s->addWithLabel("PLAY AUDIO FOR MEDIA VIEWER VIDEOS", media_viewer_video_audio);
|
|
|
|
s->addSaveFunc([media_viewer_video_audio, s] {
|
|
|
|
if (media_viewer_video_audio->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("MediaViewerVideoAudio")) {
|
2021-05-16 11:12:31 +00:00
|
|
|
Settings::getInstance()->setBool("MediaViewerVideoAudio",
|
2021-07-07 18:03:42 +00:00
|
|
|
media_viewer_video_audio->getState());
|
2021-05-16 11:12:31 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Play audio for screensaver videos.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto screensaver_video_audio = std::make_shared<SwitchComponent>();
|
2021-07-07 18:03:42 +00:00
|
|
|
screensaver_video_audio->setState(
|
|
|
|
Settings::getInstance()->getBool("ScreensaverVideoAudio"));
|
2021-05-16 11:12:31 +00:00
|
|
|
s->addWithLabel("PLAY AUDIO FOR SCREENSAVER VIDEOS", screensaver_video_audio);
|
|
|
|
s->addSaveFunc([screensaver_video_audio, s] {
|
|
|
|
if (screensaver_video_audio->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("ScreensaverVideoAudio")) {
|
2021-05-16 11:12:31 +00:00
|
|
|
Settings::getInstance()->setBool("ScreensaverVideoAudio",
|
2021-07-07 18:03:42 +00:00
|
|
|
screensaver_video_audio->getState());
|
2021-05-16 11:12:31 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
// Navigation sounds.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto navigation_sounds = std::make_shared<SwitchComponent>();
|
2021-07-07 18:03:42 +00:00
|
|
|
navigation_sounds->setState(Settings::getInstance()->getBool("NavigationSounds"));
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addWithLabel("ENABLE NAVIGATION SOUNDS", navigation_sounds);
|
|
|
|
s->addSaveFunc([navigation_sounds, s] {
|
|
|
|
if (navigation_sounds->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("NavigationSounds")) {
|
|
|
|
Settings::getInstance()->setBool("NavigationSounds", navigation_sounds->getState());
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-10-24 12:11:19 +00:00
|
|
|
s->setSize(mSize);
|
2020-11-05 17:18:11 +00:00
|
|
|
mWindow->pushGui(s);
|
|
|
|
}
|
|
|
|
|
2021-05-23 08:35:59 +00:00
|
|
|
void GuiMenu::openInputDeviceOptions()
|
|
|
|
{
|
2022-01-19 17:01:54 +00:00
|
|
|
auto s = new GuiSettings("INPUT DEVICE SETTINGS");
|
2021-05-23 08:35:59 +00:00
|
|
|
|
2021-05-23 17:12:31 +00:00
|
|
|
// Controller type.
|
2021-07-07 18:03:42 +00:00
|
|
|
auto input_controller_type = std::make_shared<OptionListComponent<std::string>>(
|
2022-01-19 17:01:54 +00:00
|
|
|
getHelpStyle(), "CONTROLLER TYPE", false);
|
2021-05-23 17:12:31 +00:00
|
|
|
std::string selectedPlayer = Settings::getInstance()->getString("InputControllerType");
|
|
|
|
input_controller_type->add("XBOX", "xbox", selectedPlayer == "xbox");
|
2021-05-23 17:19:00 +00:00
|
|
|
input_controller_type->add("XBOX 360", "xbox360", selectedPlayer == "xbox360");
|
|
|
|
input_controller_type->add("PLAYSTATION 4", "ps4", selectedPlayer == "ps4");
|
|
|
|
input_controller_type->add("PLAYSTATION 5", "ps5", selectedPlayer == "ps5");
|
2021-05-23 17:12:31 +00:00
|
|
|
input_controller_type->add("SNES", "snes", selectedPlayer == "snes");
|
|
|
|
// If there are no objects returned, then there must be a manually modified entry in the
|
|
|
|
// configuration file. Simply set the controller type to "xbox" in this case.
|
|
|
|
if (input_controller_type->getSelectedObjects().size() == 0)
|
|
|
|
input_controller_type->selectEntry(0);
|
|
|
|
s->addWithLabel("CONTROLLER TYPE", input_controller_type);
|
|
|
|
s->addSaveFunc([input_controller_type, s] {
|
|
|
|
if (input_controller_type->getSelected() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getString("InputControllerType")) {
|
2021-05-23 17:12:31 +00:00
|
|
|
Settings::getInstance()->setString("InputControllerType",
|
2021-07-07 18:03:42 +00:00
|
|
|
input_controller_type->getSelected());
|
2021-05-23 17:12:31 +00:00
|
|
|
s->setNeedsReloadHelpPrompts();
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-05-23 09:45:45 +00:00
|
|
|
// Whether to only accept input from the first controller.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto input_only_first_controller = std::make_shared<SwitchComponent>();
|
2021-07-07 18:03:42 +00:00
|
|
|
input_only_first_controller->setState(
|
|
|
|
Settings::getInstance()->getBool("InputOnlyFirstController"));
|
2021-05-23 09:45:45 +00:00
|
|
|
s->addWithLabel("ONLY ACCEPT INPUT FROM FIRST CONTROLLER", input_only_first_controller);
|
|
|
|
s->addSaveFunc([input_only_first_controller, s] {
|
|
|
|
if (Settings::getInstance()->getBool("InputOnlyFirstController") !=
|
2021-07-07 18:03:42 +00:00
|
|
|
input_only_first_controller->getState()) {
|
2021-05-23 09:45:45 +00:00
|
|
|
Settings::getInstance()->setBool("InputOnlyFirstController",
|
2021-07-07 18:03:42 +00:00
|
|
|
input_only_first_controller->getState());
|
2021-05-23 09:45:45 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-05-23 08:35:59 +00:00
|
|
|
// Configure keyboard and controllers.
|
|
|
|
ComponentListRow configure_input_row;
|
|
|
|
configure_input_row.elements.clear();
|
2021-07-07 18:03:42 +00:00
|
|
|
configure_input_row.addElement(
|
2022-01-19 17:01:54 +00:00
|
|
|
std::make_shared<TextComponent>("CONFIGURE KEYBOARD AND CONTROLLERS",
|
2021-07-07 18:03:42 +00:00
|
|
|
Font::get(FONT_SIZE_MEDIUM), 0x777777FF),
|
|
|
|
true);
|
2022-01-19 17:01:54 +00:00
|
|
|
configure_input_row.addElement(makeArrow(), false);
|
2021-06-28 16:12:08 +00:00
|
|
|
configure_input_row.makeAcceptInputHandler(std::bind(&GuiMenu::openConfigInput, this, s));
|
2021-05-23 08:35:59 +00:00
|
|
|
s->addRow(configure_input_row);
|
|
|
|
|
2021-10-24 12:11:19 +00:00
|
|
|
s->setSize(mSize);
|
2021-05-23 08:35:59 +00:00
|
|
|
mWindow->pushGui(s);
|
|
|
|
}
|
|
|
|
|
2021-06-28 16:12:08 +00:00
|
|
|
void GuiMenu::openConfigInput(GuiSettings* settings)
|
2021-05-23 08:35:59 +00:00
|
|
|
{
|
2021-06-28 16:12:08 +00:00
|
|
|
// Always save the settings before starting the input configuration, in case the
|
|
|
|
// controller type was changed.
|
|
|
|
settings->save();
|
|
|
|
// Also unset the save flag so that a double saving does not take place when closing
|
|
|
|
// the input device settings menu later on.
|
|
|
|
settings->setNeedsSaving(false);
|
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
std::string message = "THE KEYBOARD AND CONTROLLERS ARE AUTOMATICALLY\n"
|
|
|
|
"CONFIGURED, BUT USING THIS CONFIGURATION TOOL\n"
|
|
|
|
"YOU CAN OVERRIDE THE DEFAULT BUTTON MAPPINGS\n"
|
|
|
|
"(THIS WILL NOT AFFECT THE HELP PROMPTS)\n"
|
|
|
|
"CONTINUE?";
|
2021-05-23 08:35:59 +00:00
|
|
|
|
2022-01-19 17:01:54 +00:00
|
|
|
Window* window {mWindow};
|
2021-07-07 18:03:42 +00:00
|
|
|
window->pushGui(new GuiMsgBox(
|
2022-01-19 17:01:54 +00:00
|
|
|
getHelpStyle(), message, "YES",
|
|
|
|
[window] { window->pushGui(new GuiDetectDevice(false, false, nullptr)); }, "NO", nullptr));
|
2021-05-23 08:35:59 +00:00
|
|
|
}
|
|
|
|
|
2021-05-22 20:48:44 +00:00
|
|
|
void GuiMenu::openOtherOptions()
|
2017-09-08 14:49:47 +00:00
|
|
|
{
|
2022-01-19 17:01:54 +00:00
|
|
|
auto s = new GuiSettings("OTHER SETTINGS");
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2021-08-22 13:26:38 +00:00
|
|
|
// Alternative emulators GUI.
|
|
|
|
ComponentListRow alternativeEmulatorsRow;
|
|
|
|
alternativeEmulatorsRow.elements.clear();
|
2022-01-19 17:01:54 +00:00
|
|
|
alternativeEmulatorsRow.addElement(std::make_shared<TextComponent>("ALTERNATIVE EMULATORS",
|
|
|
|
Font::get(FONT_SIZE_MEDIUM),
|
|
|
|
0x777777FF),
|
|
|
|
true);
|
|
|
|
alternativeEmulatorsRow.addElement(makeArrow(), false);
|
2021-08-22 13:26:38 +00:00
|
|
|
alternativeEmulatorsRow.makeAcceptInputHandler(
|
2022-01-19 17:01:54 +00:00
|
|
|
std::bind([this] { mWindow->pushGui(new GuiAlternativeEmulators); }));
|
2021-08-22 13:26:38 +00:00
|
|
|
s->addRow(alternativeEmulatorsRow);
|
|
|
|
|
2021-08-22 12:29:43 +00:00
|
|
|
// Game media directory.
|
|
|
|
ComponentListRow rowMediaDir;
|
2022-01-19 17:01:54 +00:00
|
|
|
auto media_directory = std::make_shared<TextComponent>("GAME MEDIA DIRECTORY",
|
2021-08-22 12:29:43 +00:00
|
|
|
Font::get(FONT_SIZE_MEDIUM), 0x777777FF);
|
2022-01-19 17:01:54 +00:00
|
|
|
auto bracketMediaDirectory = std::make_shared<ImageComponent>();
|
2021-08-22 12:29:43 +00:00
|
|
|
bracketMediaDirectory->setImage(":/graphics/arrow.svg");
|
|
|
|
bracketMediaDirectory->setResize(
|
2022-01-16 11:09:55 +00:00
|
|
|
glm::vec2 {0.0f, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight()});
|
2021-08-22 12:29:43 +00:00
|
|
|
rowMediaDir.addElement(media_directory, true);
|
|
|
|
rowMediaDir.addElement(bracketMediaDirectory, false);
|
|
|
|
std::string titleMediaDir = "ENTER GAME MEDIA DIRECTORY";
|
|
|
|
std::string mediaDirectoryStaticText = "Default directory:";
|
|
|
|
std::string defaultDirectoryText = "~/.emulationstation/downloaded_media/";
|
|
|
|
std::string initValueMediaDir = Settings::getInstance()->getString("MediaDirectory");
|
|
|
|
bool multiLineMediaDir = false;
|
|
|
|
auto updateValMediaDir = [this](const std::string& newVal) {
|
|
|
|
Settings::getInstance()->setString("MediaDirectory", newVal);
|
|
|
|
Settings::getInstance()->saveFile();
|
2022-01-04 20:49:22 +00:00
|
|
|
ViewController::getInstance()->reloadAll();
|
2021-08-22 12:29:43 +00:00
|
|
|
mWindow->invalidateCachedBackground();
|
|
|
|
};
|
|
|
|
rowMediaDir.makeAcceptInputHandler([this, titleMediaDir, mediaDirectoryStaticText,
|
|
|
|
defaultDirectoryText, initValueMediaDir, updateValMediaDir,
|
|
|
|
multiLineMediaDir] {
|
2021-09-17 20:23:41 +00:00
|
|
|
if (Settings::getInstance()->getBool("VirtualKeyboard")) {
|
|
|
|
mWindow->pushGui(new GuiTextEditKeyboardPopup(
|
2022-01-19 17:01:54 +00:00
|
|
|
getHelpStyle(), titleMediaDir, Settings::getInstance()->getString("MediaDirectory"),
|
|
|
|
updateValMediaDir, multiLineMediaDir, "SAVE", "SAVE CHANGES?",
|
|
|
|
mediaDirectoryStaticText, defaultDirectoryText, "load default directory"));
|
2021-09-17 20:23:41 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
mWindow->pushGui(new GuiTextEditPopup(
|
2022-01-19 17:01:54 +00:00
|
|
|
getHelpStyle(), titleMediaDir, Settings::getInstance()->getString("MediaDirectory"),
|
|
|
|
updateValMediaDir, multiLineMediaDir, "SAVE", "SAVE CHANGES?",
|
|
|
|
mediaDirectoryStaticText, defaultDirectoryText, "load default directory"));
|
2021-09-17 20:23:41 +00:00
|
|
|
}
|
2021-08-22 12:29:43 +00:00
|
|
|
});
|
|
|
|
s->addRow(rowMediaDir);
|
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
// Maximum VRAM.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto max_vram = std::make_shared<SliderComponent>(80.f, 1024.f, 8.f, "MiB");
|
2020-11-05 17:18:11 +00:00
|
|
|
max_vram->setValue(static_cast<float>(Settings::getInstance()->getInt("MaxVRAM")));
|
2020-06-21 12:25:28 +00:00
|
|
|
s->addWithLabel("VRAM LIMIT", max_vram);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([max_vram, s] {
|
|
|
|
if (max_vram->getValue() != Settings::getInstance()->getInt("MaxVRAM")) {
|
|
|
|
Settings::getInstance()->setInt("MaxVRAM",
|
2021-07-07 18:03:42 +00:00
|
|
|
static_cast<int>(std::round(max_vram->getValue())));
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2021-01-24 22:44:50 +00:00
|
|
|
// Display/monitor.
|
2021-07-07 18:03:42 +00:00
|
|
|
auto display_index = std::make_shared<OptionListComponent<std::string>>(
|
2022-01-19 17:01:54 +00:00
|
|
|
getHelpStyle(), "DISPLAY/MONITOR INDEX", false);
|
2021-01-24 22:44:50 +00:00
|
|
|
std::vector<std::string> displayIndex;
|
|
|
|
displayIndex.push_back("1");
|
|
|
|
displayIndex.push_back("2");
|
|
|
|
displayIndex.push_back("3");
|
|
|
|
displayIndex.push_back("4");
|
2021-11-17 16:35:34 +00:00
|
|
|
for (auto it = displayIndex.cbegin(); it != displayIndex.cend(); ++it)
|
2021-01-24 22:44:50 +00:00
|
|
|
display_index->add(*it, *it,
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getInt("DisplayIndex") == atoi((*it).c_str()));
|
2021-01-24 22:54:43 +00:00
|
|
|
s->addWithLabel("DISPLAY/MONITOR INDEX (REQUIRES RESTART)", display_index);
|
2021-01-24 22:44:50 +00:00
|
|
|
s->addSaveFunc([display_index, s] {
|
|
|
|
if (atoi(display_index->getSelected().c_str()) !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getInt("DisplayIndex")) {
|
2021-01-24 22:44:50 +00:00
|
|
|
Settings::getInstance()->setInt("DisplayIndex",
|
2021-07-07 18:03:42 +00:00
|
|
|
atoi(display_index->getSelected().c_str()));
|
2021-01-24 22:44:50 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-07-07 12:28:09 +00:00
|
|
|
// Exit button configuration.
|
2021-08-11 10:09:58 +00:00
|
|
|
auto exit_button_config = std::make_shared<OptionListComponent<std::string>>(
|
2022-01-19 17:01:54 +00:00
|
|
|
getHelpStyle(), "EXIT BUTTON COMBO", false);
|
2021-07-07 12:28:09 +00:00
|
|
|
std::string selectedExitButtonCombo = Settings::getInstance()->getString("ExitButtonCombo");
|
|
|
|
exit_button_config->add("F4", "F4", selectedExitButtonCombo == "F4");
|
|
|
|
exit_button_config->add("Alt + F4", "AltF4", selectedExitButtonCombo == "AltF4");
|
2021-08-11 10:09:58 +00:00
|
|
|
#if defined(_WIN64) || defined(__unix__)
|
2021-07-07 12:28:09 +00:00
|
|
|
exit_button_config->add("Alt + Q", "AltQ", selectedExitButtonCombo == "AltQ");
|
2021-08-11 10:09:58 +00:00
|
|
|
#endif
|
|
|
|
#if defined(__APPLE__)
|
2021-07-07 12:28:09 +00:00
|
|
|
exit_button_config->add("\u2318 + Q", "CmdQ", selectedExitButtonCombo == "CmdQ");
|
2021-08-11 10:09:58 +00:00
|
|
|
#endif
|
2021-07-07 12:28:09 +00:00
|
|
|
s->addWithLabel("EXIT BUTTON COMBO", exit_button_config);
|
|
|
|
s->addSaveFunc([exit_button_config, s] {
|
|
|
|
if (exit_button_config->getSelected() !=
|
|
|
|
Settings::getInstance()->getString("ExitButtonCombo")) {
|
|
|
|
Settings::getInstance()->setString("ExitButtonCombo",
|
2021-08-11 10:09:58 +00:00
|
|
|
exit_button_config->getSelected());
|
2021-07-07 12:28:09 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
// When to save game metadata.
|
2021-07-07 18:03:42 +00:00
|
|
|
auto save_gamelist_mode = std::make_shared<OptionListComponent<std::string>>(
|
2022-01-19 17:01:54 +00:00
|
|
|
getHelpStyle(), "WHEN TO SAVE METADATA", false);
|
2020-06-21 12:25:28 +00:00
|
|
|
std::vector<std::string> saveModes;
|
|
|
|
saveModes.push_back("on exit");
|
|
|
|
saveModes.push_back("always");
|
|
|
|
saveModes.push_back("never");
|
2021-11-17 16:35:34 +00:00
|
|
|
for (auto it = saveModes.cbegin(); it != saveModes.cend(); ++it) {
|
2021-07-07 18:03:42 +00:00
|
|
|
save_gamelist_mode->add(*it, *it,
|
|
|
|
Settings::getInstance()->getString("SaveGamelistsMode") == *it);
|
2020-07-15 16:02:11 +00:00
|
|
|
}
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addWithLabel("WHEN TO SAVE GAME METADATA", save_gamelist_mode);
|
|
|
|
s->addSaveFunc([save_gamelist_mode, s] {
|
|
|
|
if (save_gamelist_mode->getSelected() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getString("SaveGamelistsMode")) {
|
2020-10-19 15:16:57 +00:00
|
|
|
Settings::getInstance()->setString("SaveGamelistsMode",
|
2021-07-07 18:03:42 +00:00
|
|
|
save_gamelist_mode->getSelected());
|
|
|
|
// Always save the gamelist.xml files if switching to "always" as there may
|
2020-10-19 15:16:57 +00:00
|
|
|
// be changes that will otherwise be lost.
|
|
|
|
if (Settings::getInstance()->getString("SaveGamelistsMode") == "always") {
|
|
|
|
for (auto it = SystemData::sSystemVector.cbegin();
|
2021-11-17 16:35:34 +00:00
|
|
|
it != SystemData::sSystemVector.cend(); ++it)
|
2020-10-19 15:16:57 +00:00
|
|
|
(*it)->writeMetaData();
|
|
|
|
}
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
2020-10-19 15:16:57 +00:00
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
});
|
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
#if defined(_WIN64)
|
2021-11-12 18:49:24 +00:00
|
|
|
// Hide taskbar during the program session.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto hide_taskbar = std::make_shared<SwitchComponent>();
|
2020-07-18 11:21:44 +00:00
|
|
|
hide_taskbar->setState(Settings::getInstance()->getBool("HideTaskbar"));
|
|
|
|
s->addWithLabel("HIDE TASKBAR (REQUIRES RESTART)", hide_taskbar);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([hide_taskbar, s] {
|
2021-07-07 18:03:42 +00:00
|
|
|
if (hide_taskbar->getState() != Settings::getInstance()->getBool("HideTaskbar")) {
|
|
|
|
Settings::getInstance()->setBool("HideTaskbar", hide_taskbar->getState());
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2021-07-07 18:03:42 +00:00
|
|
|
#endif
|
2020-07-19 20:08:14 +00:00
|
|
|
|
|
|
|
// Run ES in the background when a game has been launched.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto run_in_background = std::make_shared<SwitchComponent>();
|
2020-07-19 20:08:14 +00:00
|
|
|
run_in_background->setState(Settings::getInstance()->getBool("RunInBackground"));
|
|
|
|
s->addWithLabel("RUN IN BACKGROUND (WHILE GAME IS LAUNCHED)", run_in_background);
|
2021-07-07 18:03:42 +00:00
|
|
|
s->addSaveFunc([run_in_background, s] {
|
2020-11-05 17:18:11 +00:00
|
|
|
if (run_in_background->getState() != Settings::getInstance()->getBool("RunInBackground")) {
|
|
|
|
Settings::getInstance()->setBool("RunInBackground", run_in_background->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-07-18 11:21:44 +00:00
|
|
|
|
2021-11-07 22:54:52 +00:00
|
|
|
#if defined(VIDEO_HW_DECODING)
|
2021-07-14 17:13:25 +00:00
|
|
|
// Whether to enable hardware decoding for the FFmpeg video player.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto video_hardware_decoding = std::make_shared<SwitchComponent>();
|
2021-07-14 17:13:25 +00:00
|
|
|
video_hardware_decoding->setState(Settings::getInstance()->getBool("VideoHardwareDecoding"));
|
|
|
|
s->addWithLabel("VIDEO HARDWARE DECODING (EXPERIMENTAL)", video_hardware_decoding);
|
|
|
|
s->addSaveFunc([video_hardware_decoding, s] {
|
|
|
|
if (video_hardware_decoding->getState() !=
|
|
|
|
Settings::getInstance()->getBool("VideoHardwareDecoding")) {
|
|
|
|
Settings::getInstance()->setBool("VideoHardwareDecoding",
|
|
|
|
video_hardware_decoding->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
#endif
|
2021-06-30 16:08:13 +00:00
|
|
|
|
2021-05-29 08:55:40 +00:00
|
|
|
// Whether to upscale the video frame rate to 60 FPS.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto video_upscale_frame_rate = std::make_shared<SwitchComponent>();
|
2021-05-29 08:55:40 +00:00
|
|
|
video_upscale_frame_rate->setState(Settings::getInstance()->getBool("VideoUpscaleFrameRate"));
|
2021-06-22 22:24:15 +00:00
|
|
|
s->addWithLabel("UPSCALE VIDEO FRAME RATE TO 60 FPS", video_upscale_frame_rate);
|
2021-05-29 08:55:40 +00:00
|
|
|
s->addSaveFunc([video_upscale_frame_rate, s] {
|
|
|
|
if (video_upscale_frame_rate->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("VideoUpscaleFrameRate")) {
|
|
|
|
Settings::getInstance()->setBool("VideoUpscaleFrameRate",
|
|
|
|
video_upscale_frame_rate->getState());
|
2021-05-29 08:55:40 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-09-04 09:21:55 +00:00
|
|
|
// Whether to enable alternative emulators per game (the option to disable this is intended
|
|
|
|
// primarily for testing purposes).
|
2022-01-19 17:01:54 +00:00
|
|
|
auto alternativeEmulatorPerGame = std::make_shared<SwitchComponent>();
|
2021-09-04 09:21:55 +00:00
|
|
|
alternativeEmulatorPerGame->setState(
|
|
|
|
Settings::getInstance()->getBool("AlternativeEmulatorPerGame"));
|
|
|
|
s->addWithLabel("ENABLE ALTERNATIVE EMULATORS PER GAME", alternativeEmulatorPerGame);
|
|
|
|
s->addSaveFunc([alternativeEmulatorPerGame, s] {
|
|
|
|
if (alternativeEmulatorPerGame->getState() !=
|
|
|
|
Settings::getInstance()->getBool("AlternativeEmulatorPerGame")) {
|
|
|
|
Settings::getInstance()->setBool("AlternativeEmulatorPerGame",
|
|
|
|
alternativeEmulatorPerGame->getState());
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
2021-11-10 21:38:25 +00:00
|
|
|
s->setNeedsReloading();
|
|
|
|
s->setInvalidateCachedBackground();
|
2020-11-05 17:18:11 +00:00
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
// Show hidden files.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto show_hidden_files = std::make_shared<SwitchComponent>();
|
2020-11-05 17:18:11 +00:00
|
|
|
show_hidden_files->setState(Settings::getInstance()->getBool("ShowHiddenFiles"));
|
|
|
|
s->addWithLabel("SHOW HIDDEN FILES AND FOLDERS (REQUIRES RESTART)", show_hidden_files);
|
|
|
|
s->addSaveFunc([show_hidden_files, s] {
|
|
|
|
if (show_hidden_files->getState() != Settings::getInstance()->getBool("ShowHiddenFiles")) {
|
|
|
|
Settings::getInstance()->setBool("ShowHiddenFiles", show_hidden_files->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-07-26 20:19:29 +00:00
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
// Show hidden games.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto show_hidden_games = std::make_shared<SwitchComponent>();
|
2020-11-05 17:18:11 +00:00
|
|
|
show_hidden_games->setState(Settings::getInstance()->getBool("ShowHiddenGames"));
|
|
|
|
s->addWithLabel("SHOW HIDDEN GAMES (REQUIRES RESTART)", show_hidden_games);
|
|
|
|
s->addSaveFunc([show_hidden_games, s] {
|
|
|
|
if (show_hidden_games->getState() != Settings::getInstance()->getBool("ShowHiddenGames")) {
|
|
|
|
Settings::getInstance()->setBool("ShowHiddenGames", show_hidden_games->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
2020-07-26 20:19:29 +00:00
|
|
|
});
|
|
|
|
|
2020-07-15 16:02:11 +00:00
|
|
|
// Custom event scripts, fired using Scripting::fireEvent().
|
2022-01-19 17:01:54 +00:00
|
|
|
auto custom_eventscripts = std::make_shared<SwitchComponent>();
|
2020-07-09 17:24:20 +00:00
|
|
|
custom_eventscripts->setState(Settings::getInstance()->getBool("CustomEventScripts"));
|
2020-10-31 09:01:19 +00:00
|
|
|
s->addWithLabel("ENABLE CUSTOM EVENT SCRIPTS", custom_eventscripts);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([custom_eventscripts, s] {
|
|
|
|
if (custom_eventscripts->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("CustomEventScripts")) {
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setBool("CustomEventScripts", custom_eventscripts->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Only show ROMs included in the gamelist.xml files.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto parse_gamelist_only = std::make_shared<SwitchComponent>();
|
2020-11-05 17:18:11 +00:00
|
|
|
parse_gamelist_only->setState(Settings::getInstance()->getBool("ParseGamelistOnly"));
|
|
|
|
s->addWithLabel("ONLY SHOW ROMS FROM GAMELIST.XML FILES", parse_gamelist_only);
|
|
|
|
s->addSaveFunc([parse_gamelist_only, s] {
|
|
|
|
if (parse_gamelist_only->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("ParseGamelistOnly")) {
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setBool("ParseGamelistOnly", parse_gamelist_only->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
#if defined(__unix__)
|
2021-02-22 20:13:06 +00:00
|
|
|
// Whether to disable desktop composition.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto disable_composition = std::make_shared<SwitchComponent>();
|
2021-02-22 20:13:06 +00:00
|
|
|
disable_composition->setState(Settings::getInstance()->getBool("DisableComposition"));
|
|
|
|
s->addWithLabel("DISABLE DESKTOP COMPOSITION (REQUIRES RESTART)", disable_composition);
|
|
|
|
s->addSaveFunc([disable_composition, s] {
|
|
|
|
if (disable_composition->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("DisableComposition")) {
|
|
|
|
Settings::getInstance()->setBool("DisableComposition", disable_composition->getState());
|
2021-02-22 20:13:06 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2021-07-07 18:03:42 +00:00
|
|
|
#endif
|
2021-02-22 20:13:06 +00:00
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
// GPU statistics overlay.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto display_gpu_statistics = std::make_shared<SwitchComponent>();
|
2020-11-05 17:18:11 +00:00
|
|
|
display_gpu_statistics->setState(Settings::getInstance()->getBool("DisplayGPUStatistics"));
|
|
|
|
s->addWithLabel("DISPLAY GPU STATISTICS OVERLAY", display_gpu_statistics);
|
|
|
|
s->addSaveFunc([display_gpu_statistics, s] {
|
|
|
|
if (display_gpu_statistics->getState() !=
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getBool("DisplayGPUStatistics")) {
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setBool("DisplayGPUStatistics",
|
2021-07-07 18:03:42 +00:00
|
|
|
display_gpu_statistics->getState());
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-12-17 22:45:29 +00:00
|
|
|
// Whether to enable the menu in Kid mode.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto enable_menu_kid_mode = std::make_shared<SwitchComponent>();
|
2020-12-17 22:45:29 +00:00
|
|
|
enable_menu_kid_mode->setState(Settings::getInstance()->getBool("EnableMenuKidMode"));
|
|
|
|
s->addWithLabel("ENABLE MENU IN KID MODE", enable_menu_kid_mode);
|
|
|
|
s->addSaveFunc([enable_menu_kid_mode, s] {
|
|
|
|
if (Settings::getInstance()->getBool("EnableMenuKidMode") !=
|
2021-07-07 18:03:42 +00:00
|
|
|
enable_menu_kid_mode->getState()) {
|
2020-12-17 22:45:29 +00:00
|
|
|
Settings::getInstance()->setBool("EnableMenuKidMode", enable_menu_kid_mode->getState());
|
|
|
|
s->setNeedsSaving();
|
2020-11-05 17:18:11 +00:00
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
// macOS requires root privileges to reboot and power off so it doesn't make much
|
|
|
|
// sense to enable this setting and menu entry for that operating system.
|
|
|
|
#if !defined(__APPLE__)
|
2020-12-17 22:45:29 +00:00
|
|
|
// Whether to show the quit menu with the options to reboot and shutdown the computer.
|
2022-01-19 17:01:54 +00:00
|
|
|
auto show_quit_menu = std::make_shared<SwitchComponent>();
|
2020-12-17 22:45:29 +00:00
|
|
|
show_quit_menu->setState(Settings::getInstance()->getBool("ShowQuitMenu"));
|
|
|
|
s->addWithLabel("SHOW QUIT MENU (REBOOT AND POWER OFF ENTRIES)", show_quit_menu);
|
|
|
|
s->addSaveFunc([this, show_quit_menu, s] {
|
2021-07-07 18:03:42 +00:00
|
|
|
if (show_quit_menu->getState() != Settings::getInstance()->getBool("ShowQuitMenu")) {
|
2020-12-17 22:45:29 +00:00
|
|
|
Settings::getInstance()->setBool("ShowQuitMenu", show_quit_menu->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
GuiMenu::close(false);
|
2020-11-05 17:18:11 +00:00
|
|
|
}
|
|
|
|
});
|
2021-07-07 18:03:42 +00:00
|
|
|
#endif
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2021-10-24 12:11:19 +00:00
|
|
|
s->setSize(mSize);
|
2020-06-21 12:25:28 +00:00
|
|
|
mWindow->pushGui(s);
|
2017-09-08 14:49:47 +00:00
|
|
|
}
|
2017-06-01 20:08:44 +00:00
|
|
|
|
2021-05-23 09:03:56 +00:00
|
|
|
void GuiMenu::openUtilitiesMenu()
|
|
|
|
{
|
2022-01-19 17:01:54 +00:00
|
|
|
auto s = new GuiSettings("UTILITIES");
|
2021-10-24 12:11:19 +00:00
|
|
|
s->setSize(mSize);
|
2021-05-23 09:03:56 +00:00
|
|
|
mWindow->pushGui(s);
|
|
|
|
}
|
|
|
|
|
2017-09-08 14:49:47 +00:00
|
|
|
void GuiMenu::openQuitMenu()
|
|
|
|
{
|
2020-12-17 22:45:29 +00:00
|
|
|
if (!Settings::getInstance()->getBool("ShowQuitMenu")) {
|
2021-07-07 18:03:42 +00:00
|
|
|
mWindow->pushGui(new GuiMsgBox(
|
2022-01-19 17:01:54 +00:00
|
|
|
this->getHelpStyle(), "REALLY QUIT?", "YES",
|
2021-07-07 18:03:42 +00:00
|
|
|
[this] {
|
|
|
|
Scripting::fireEvent("quit");
|
|
|
|
close(true);
|
2022-01-10 17:43:17 +00:00
|
|
|
Utils::Platform::quitES();
|
2021-07-07 18:03:42 +00:00
|
|
|
},
|
|
|
|
"NO", nullptr));
|
2020-12-17 22:45:29 +00:00
|
|
|
}
|
|
|
|
else {
|
2022-01-19 17:01:54 +00:00
|
|
|
auto s = new GuiSettings("QUIT");
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2022-01-19 17:01:54 +00:00
|
|
|
Window* window {mWindow};
|
2020-12-17 22:45:29 +00:00
|
|
|
HelpStyle style = getHelpStyle();
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-12-17 22:45:29 +00:00
|
|
|
ComponentListRow row;
|
|
|
|
|
|
|
|
row.makeAcceptInputHandler([window, this] {
|
2021-07-07 18:03:42 +00:00
|
|
|
window->pushGui(new GuiMsgBox(
|
2022-01-19 17:01:54 +00:00
|
|
|
this->getHelpStyle(), "REALLY QUIT?", "YES",
|
2021-07-07 18:03:42 +00:00
|
|
|
[this] {
|
2020-12-17 22:45:29 +00:00
|
|
|
Scripting::fireEvent("quit");
|
|
|
|
close(true);
|
2022-01-10 17:43:17 +00:00
|
|
|
Utils::Platform::quitES();
|
2021-07-07 18:03:42 +00:00
|
|
|
},
|
|
|
|
"NO", nullptr));
|
2020-12-17 22:45:29 +00:00
|
|
|
});
|
2022-01-19 17:01:54 +00:00
|
|
|
auto quitText = std::make_shared<TextComponent>("QUIT EMULATIONSTATION",
|
2021-10-14 20:21:21 +00:00
|
|
|
Font::get(FONT_SIZE_MEDIUM), 0x777777FF);
|
|
|
|
quitText->setSelectable(true);
|
|
|
|
row.addElement(quitText, true);
|
2020-12-17 22:45:29 +00:00
|
|
|
s->addRow(row);
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
row.elements.clear();
|
|
|
|
row.makeAcceptInputHandler([window, this] {
|
2021-07-07 18:03:42 +00:00
|
|
|
window->pushGui(new GuiMsgBox(
|
2022-01-19 17:01:54 +00:00
|
|
|
this->getHelpStyle(), "REALLY REBOOT?", "YES",
|
2021-07-07 18:03:42 +00:00
|
|
|
[] {
|
2020-06-21 12:25:28 +00:00
|
|
|
Scripting::fireEvent("quit", "reboot");
|
|
|
|
Scripting::fireEvent("reboot");
|
2022-01-10 17:43:17 +00:00
|
|
|
if (Utils::Platform::quitES(Utils::Platform::QuitMode::REBOOT) != 0) {
|
2020-06-21 12:25:28 +00:00
|
|
|
LOG(LogWarning) << "Reboot terminated with non-zero result!";
|
2020-06-25 17:52:38 +00:00
|
|
|
}
|
2021-07-07 18:03:42 +00:00
|
|
|
},
|
|
|
|
"NO", nullptr));
|
2020-06-21 12:25:28 +00:00
|
|
|
});
|
2022-01-19 17:01:54 +00:00
|
|
|
auto rebootText = std::make_shared<TextComponent>("REBOOT SYSTEM",
|
2021-10-14 20:21:21 +00:00
|
|
|
Font::get(FONT_SIZE_MEDIUM), 0x777777FF);
|
|
|
|
rebootText->setSelectable(true);
|
|
|
|
row.addElement(rebootText, true);
|
2020-06-21 12:25:28 +00:00
|
|
|
s->addRow(row);
|
|
|
|
|
|
|
|
row.elements.clear();
|
|
|
|
row.makeAcceptInputHandler([window, this] {
|
2021-07-07 18:03:42 +00:00
|
|
|
window->pushGui(new GuiMsgBox(
|
2022-01-19 17:01:54 +00:00
|
|
|
this->getHelpStyle(), "REALLY POWER OFF?", "YES",
|
2021-07-07 18:03:42 +00:00
|
|
|
[] {
|
2020-06-21 12:25:28 +00:00
|
|
|
Scripting::fireEvent("quit", "poweroff");
|
|
|
|
Scripting::fireEvent("poweroff");
|
2022-01-10 17:43:17 +00:00
|
|
|
if (Utils::Platform::quitES(Utils::Platform::QuitMode::POWEROFF) != 0) {
|
2020-06-21 12:25:28 +00:00
|
|
|
LOG(LogWarning) << "Power off terminated with non-zero result!";
|
2020-06-25 17:52:38 +00:00
|
|
|
}
|
2021-07-07 18:03:42 +00:00
|
|
|
},
|
|
|
|
"NO", nullptr));
|
2020-06-21 12:25:28 +00:00
|
|
|
});
|
2021-10-14 20:21:21 +00:00
|
|
|
auto powerOffText = std::make_shared<TextComponent>(
|
2022-01-19 17:01:54 +00:00
|
|
|
"POWER OFF SYSTEM", Font::get(FONT_SIZE_MEDIUM), 0x777777FF);
|
2021-10-14 20:21:21 +00:00
|
|
|
powerOffText->setSelectable(true);
|
|
|
|
row.addElement(powerOffText, true);
|
2020-06-21 12:25:28 +00:00
|
|
|
s->addRow(row);
|
|
|
|
|
2021-10-24 12:11:19 +00:00
|
|
|
s->setSize(mSize);
|
2020-12-17 22:45:29 +00:00
|
|
|
mWindow->pushGui(s);
|
|
|
|
}
|
2017-09-08 14:49:47 +00:00
|
|
|
}
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2017-09-08 14:49:47 +00:00
|
|
|
void GuiMenu::addVersionInfo()
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
mVersion.setFont(Font::get(FONT_SIZE_SMALL));
|
|
|
|
mVersion.setColor(0x5E5E5EFF);
|
2022-04-19 15:27:04 +00:00
|
|
|
|
|
|
|
#if defined(MENU_BUILD_DATE)
|
|
|
|
mVersion.setText("EMULATIONSTATION-DE V" + Utils::String::toUpper(PROGRAM_VERSION_STRING) +
|
|
|
|
" (Built " + __DATE__ + ")");
|
|
|
|
#else
|
2020-06-21 12:25:28 +00:00
|
|
|
mVersion.setText("EMULATIONSTATION-DE V" + Utils::String::toUpper(PROGRAM_VERSION_STRING));
|
2022-04-19 15:27:04 +00:00
|
|
|
#endif
|
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
mVersion.setHorizontalAlignment(ALIGN_CENTER);
|
|
|
|
addChild(&mVersion);
|
2014-06-25 16:29:58 +00:00
|
|
|
}
|
|
|
|
|
2021-05-16 11:12:31 +00:00
|
|
|
void GuiMenu::openMediaViewerOptions()
|
|
|
|
{
|
2022-01-19 17:01:54 +00:00
|
|
|
mWindow->pushGui(new GuiMediaViewerOptions("MEDIA VIEWER SETTINGS"));
|
2021-05-16 11:12:31 +00:00
|
|
|
}
|
|
|
|
|
2020-11-06 19:27:41 +00:00
|
|
|
void GuiMenu::openScreensaverOptions()
|
|
|
|
{
|
2022-01-19 17:01:54 +00:00
|
|
|
mWindow->pushGui(new GuiScreensaverOptions("SCREENSAVER SETTINGS"));
|
2017-06-12 16:38:59 +00:00
|
|
|
}
|
|
|
|
|
2021-05-22 20:48:44 +00:00
|
|
|
void GuiMenu::openCollectionSystemOptions()
|
2020-11-06 19:27:41 +00:00
|
|
|
{
|
2022-01-19 17:01:54 +00:00
|
|
|
mWindow->pushGui(new GuiCollectionSystemsOptions("GAME COLLECTION SETTINGS"));
|
2017-06-01 20:08:44 +00:00
|
|
|
}
|
|
|
|
|
2014-06-25 16:29:58 +00:00
|
|
|
void GuiMenu::onSizeChanged()
|
|
|
|
{
|
2021-08-16 16:25:01 +00:00
|
|
|
mVersion.setSize(mSize.x, 0.0f);
|
|
|
|
mVersion.setPosition(0.0f, mSize.y - mVersion.getSize().y);
|
2014-06-25 16:29:58 +00:00
|
|
|
}
|
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
void GuiMenu::addEntry(const std::string& name,
|
|
|
|
unsigned int color,
|
|
|
|
bool add_arrow,
|
|
|
|
const std::function<void()>& func)
|
2014-06-25 16:29:58 +00:00
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
std::shared_ptr<Font> font = Font::get(FONT_SIZE_MEDIUM);
|
2017-03-25 17:02:28 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
// Populate the list.
|
|
|
|
ComponentListRow row;
|
2022-01-19 17:01:54 +00:00
|
|
|
row.addElement(std::make_shared<TextComponent>(name, font, color), true);
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
if (add_arrow) {
|
2022-01-19 17:01:54 +00:00
|
|
|
std::shared_ptr<ImageComponent> bracket {makeArrow()};
|
2020-06-21 12:25:28 +00:00
|
|
|
row.addElement(bracket, false);
|
|
|
|
}
|
2017-03-25 17:02:28 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
row.makeAcceptInputHandler(func);
|
|
|
|
mMenu.addRow(row);
|
2014-06-25 16:29:58 +00:00
|
|
|
}
|
|
|
|
|
2020-06-09 18:03:31 +00:00
|
|
|
void GuiMenu::close(bool closeAllWindows)
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
std::function<void()> closeFunc;
|
|
|
|
if (!closeAllWindows) {
|
|
|
|
closeFunc = [this] { delete this; };
|
|
|
|
}
|
|
|
|
else {
|
2022-01-19 17:01:54 +00:00
|
|
|
Window* window {mWindow};
|
2021-09-19 12:37:10 +00:00
|
|
|
closeFunc = [window] {
|
2022-01-04 20:49:22 +00:00
|
|
|
while (window->peekGui() != ViewController::getInstance())
|
2020-06-21 12:25:28 +00:00
|
|
|
delete window->peekGui();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
closeFunc();
|
2020-06-09 18:03:31 +00:00
|
|
|
}
|
|
|
|
|
2014-06-25 16:29:58 +00:00
|
|
|
bool GuiMenu::input(InputConfig* config, Input input)
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
if (GuiComponent::input(config, input))
|
|
|
|
return true;
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
const bool isStart = config->isMappedTo("start", input);
|
|
|
|
if (input.value != 0 && (config->isMappedTo("b", input) || isStart)) {
|
|
|
|
close(isStart);
|
|
|
|
return true;
|
|
|
|
}
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
return false;
|
2014-06-25 16:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<HelpPrompt> GuiMenu::getHelpPrompts()
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
std::vector<HelpPrompt> prompts;
|
|
|
|
prompts.push_back(HelpPrompt("up/down", "choose"));
|
|
|
|
prompts.push_back(HelpPrompt("a", "select"));
|
|
|
|
prompts.push_back(HelpPrompt("b", "close menu"));
|
|
|
|
prompts.push_back(HelpPrompt("start", "close menu"));
|
|
|
|
return prompts;
|
2014-06-25 16:29:58 +00:00
|
|
|
}
|