diff --git a/README.md b/README.md index a17dcf6a6..bd10749c8 100644 --- a/README.md +++ b/README.md @@ -100,9 +100,12 @@ You can use `--help` or `-h` to view a list of command-line options. Briefly out --draw-framerate - draw the framerate. --no-exit - do not display 'exit' in the ES menu. --debug - show the console window on Windows, do slightly more logging ---windowed - run ES in a window, works best in conjunction with --resolution [w] [h]. +--windowed - run ES in a window, works best in conjunction with --resolution [w] [h]. --vsync [1/on or 0/off] - turn vsync on or off (default is on). ---scrape - run the interactive command-line metadata scraper. +--scrape - run the interactive command-line metadata scraper. +--no-splash - don't show the splash screen. +--max-vram [size] - Max VRAM to use in Mb before swapping. 0 for unlimited. +--force-kiosk - Force the UI mode to be Kiosk. ``` As long as ES hasn't frozen, you can always press F4 to close the application. diff --git a/es-app/src/guis/GuiGamelistOptions.cpp b/es-app/src/guis/GuiGamelistOptions.cpp index ef48600cd..b02f21a19 100644 --- a/es-app/src/guis/GuiGamelistOptions.cpp +++ b/es-app/src/guis/GuiGamelistOptions.cpp @@ -1,6 +1,7 @@ #include "GuiGamelistOptions.h" #include "GuiMetaDataEd.h" #include "Util.h" +#include "Settings.h" #include "views/gamelist/IGameListView.h" #include "views/ViewController.h" #include "CollectionSystemManager.h" @@ -64,8 +65,10 @@ GuiGamelistOptions::GuiGamelistOptions(Window* window, SystemData* system) : Gui mMenu.addRow(row); std::map customCollections = CollectionSystemManager::get()->getCustomCollectionSystems(); - if((customCollections.find(system->getName()) != customCollections.end() && CollectionSystemManager::get()->getEditingCollection() != system->getName()) || - CollectionSystemManager::get()->getCustomCollectionsBundle()->getName() == system->getName()) + + if(ViewController::get()->isUIModeFull() && + ((customCollections.find(system->getName()) != customCollections.end() && CollectionSystemManager::get()->getEditingCollection() != system->getName()) || + CollectionSystemManager::get()->getCustomCollectionsBundle()->getName() == system->getName())) { row.elements.clear(); row.addElement(std::make_shared(mWindow, "ADD/REMOVE GAMES TO THIS GAME COLLECTION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); @@ -73,7 +76,7 @@ GuiGamelistOptions::GuiGamelistOptions(Window* window, SystemData* system) : Gui mMenu.addRow(row); } - if(CollectionSystemManager::get()->isEditing()) + if(ViewController::get()->isUIModeFull() && CollectionSystemManager::get()->isEditing()) { row.elements.clear(); row.addElement(std::make_shared(mWindow, "FINISH EDITING '" + strToUpper(CollectionSystemManager::get()->getEditingCollection()) + "' COLLECTION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); @@ -81,8 +84,8 @@ GuiGamelistOptions::GuiGamelistOptions(Window* window, SystemData* system) : Gui mMenu.addRow(row); } - if (!fromPlaceholder && !(mSystem->isCollection() && file->getType() == FOLDER)) { - + if (ViewController::get()->isUIModeFull() && !fromPlaceholder && !(mSystem->isCollection() && file->getType() == FOLDER)) + { row.elements.clear(); row.addElement(std::make_shared(mWindow, "EDIT THIS GAME'S METADATA", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); row.addElement(makeArrow(mWindow), false); diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index a9e19e268..05a782289 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -23,381 +23,419 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MENU"), mVersion(window) { - // MAIN MENU + bool isFullUI = ViewController::get()->isUIModeFull(); - // SCRAPER > - // SOUND SETTINGS > - // UI SETTINGS > - // CONFIGURE INPUT > - // QUIT > + if (isFullUI) + addEntry("SCRAPER", 0x777777FF, true, [this] { openScraperSettings(); }); - // [version] + addEntry("SOUND SETTINGS", 0x777777FF, true, [this] { openSoundSettings(); }); + + if (isFullUI) + addEntry("UI SETTINGS", 0x777777FF, true, [this] { openUISettings(); }); + + if (isFullUI) + addEntry("GAME COLLECTION SETTINGS", 0x777777FF, true, [this] { openCollectionSystemSettings(); }); + + if (isFullUI) + addEntry("OTHER SETTINGS", 0x777777FF, true, [this] { openOtherSettings(); }); + + if (isFullUI) + addEntry("CONFIGURE INPUT", 0x777777FF, true, [this] { openConfigInput(); }); + + addEntry("QUIT", 0x777777FF, true, [this] {openQuitMenu(); }); + + addChild(&mMenu); + addVersionInfo(); + setSize(mMenu.getSize()); + setPosition((Renderer::getScreenWidth() - mSize.x()) / 2, Renderer::getScreenHeight() * 0.15f); +} + +void GuiMenu::openScraperSettings() +{ + auto s = new GuiSettings(mWindow, "SCRAPER"); + + // scrape from + auto scraper_list = std::make_shared< OptionListComponent< std::string > >(mWindow, "SCRAPE FROM", false); + std::vector scrapers = getScraperList(); + for(auto it = scrapers.begin(); it != scrapers.end(); it++) + scraper_list->add(*it, *it, *it == Settings::getInstance()->getString("Scraper")); + + s->addWithLabel("SCRAPE FROM", scraper_list); + s->addSaveFunc([scraper_list] { Settings::getInstance()->setString("Scraper", scraper_list->getSelected()); }); + + // scrape ratings + auto scrape_ratings = std::make_shared(mWindow); + scrape_ratings->setState(Settings::getInstance()->getBool("ScrapeRatings")); + s->addWithLabel("SCRAPE RATINGS", scrape_ratings); + s->addSaveFunc([scrape_ratings] { Settings::getInstance()->setBool("ScrapeRatings", scrape_ratings->getState()); }); + + // scrape now + ComponentListRow row; auto openScrapeNow = [this] { mWindow->pushGui(new GuiScraperStart(mWindow)); }; - addEntry("SCRAPER", 0x777777FF, true, - [this, openScrapeNow] { - auto s = new GuiSettings(mWindow, "SCRAPER"); + std::function openAndSave = openScrapeNow; + openAndSave = [s, openAndSave] { s->save(); openAndSave(); }; + row.makeAcceptInputHandler(openAndSave); - // scrape from - auto scraper_list = std::make_shared< OptionListComponent< std::string > >(mWindow, "SCRAPE FROM", false); - std::vector scrapers = getScraperList(); - for(auto it = scrapers.begin(); it != scrapers.end(); it++) - scraper_list->add(*it, *it, *it == Settings::getInstance()->getString("Scraper")); + auto scrape_now = std::make_shared(mWindow, "SCRAPE NOW", Font::get(FONT_SIZE_MEDIUM), 0x777777FF); + auto bracket = makeArrow(mWindow); + row.addElement(scrape_now, true); + row.addElement(bracket, false); + s->addRow(row); - s->addWithLabel("SCRAPE FROM", scraper_list); - s->addSaveFunc([scraper_list] { Settings::getInstance()->setString("Scraper", scraper_list->getSelected()); }); + mWindow->pushGui(s); +} - // scrape ratings - auto scrape_ratings = std::make_shared(mWindow); - scrape_ratings->setState(Settings::getInstance()->getBool("ScrapeRatings")); - s->addWithLabel("SCRAPE RATINGS", scrape_ratings); - s->addSaveFunc([scrape_ratings] { Settings::getInstance()->setBool("ScrapeRatings", scrape_ratings->getState()); }); +void GuiMenu::openSoundSettings() +{ + auto s = new GuiSettings(mWindow, "SOUND SETTINGS"); - // scrape now - ComponentListRow row; - std::function openAndSave = openScrapeNow; - openAndSave = [s, openAndSave] { s->save(); openAndSave(); }; - row.makeAcceptInputHandler(openAndSave); - - auto scrape_now = std::make_shared(mWindow, "SCRAPE NOW", Font::get(FONT_SIZE_MEDIUM), 0x777777FF); - auto bracket = makeArrow(mWindow); - row.addElement(scrape_now, true); - row.addElement(bracket, false); - s->addRow(row); - - mWindow->pushGui(s); - }); - - addEntry("SOUND SETTINGS", 0x777777FF, true, - [this] { - auto s = new GuiSettings(mWindow, "SOUND SETTINGS"); - - // volume - auto volume = std::make_shared(mWindow, 0.f, 100.f, 1.f, "%"); - volume->setValue((float)VolumeControl::getInstance()->getVolume()); - s->addWithLabel("SYSTEM VOLUME", volume); - s->addSaveFunc([volume] { VolumeControl::getInstance()->setVolume((int)round(volume->getValue())); }); - - #ifdef _RPI_ - // volume control device - auto vol_dev = std::make_shared< OptionListComponent >(mWindow, "AUDIO DEVICE", false); - std::vector transitions; - transitions.push_back("PCM"); - transitions.push_back("Speaker"); - transitions.push_back("Master"); - for(auto it = transitions.begin(); it != transitions.end(); it++) - vol_dev->add(*it, *it, Settings::getInstance()->getString("AudioDevice") == *it); - s->addWithLabel("AUDIO DEVICE", vol_dev); - s->addSaveFunc([vol_dev] { - Settings::getInstance()->setString("AudioDevice", vol_dev->getSelected()); - VolumeControl::getInstance()->deinit(); - VolumeControl::getInstance()->init(); - }); - #endif - - // disable sounds - auto sounds_enabled = std::make_shared(mWindow); - sounds_enabled->setState(Settings::getInstance()->getBool("EnableSounds")); - s->addWithLabel("ENABLE NAVIGATION SOUNDS", sounds_enabled); - s->addSaveFunc([sounds_enabled] { Settings::getInstance()->setBool("EnableSounds", sounds_enabled->getState()); }); - - auto video_audio = std::make_shared(mWindow); - video_audio->setState(Settings::getInstance()->getBool("VideoAudio")); - s->addWithLabel("ENABLE VIDEO AUDIO", video_audio); - s->addSaveFunc([video_audio] { Settings::getInstance()->setBool("VideoAudio", video_audio->getState()); }); + // volume + auto volume = std::make_shared(mWindow, 0.f, 100.f, 1.f, "%"); + volume->setValue((float)VolumeControl::getInstance()->getVolume()); + s->addWithLabel("SYSTEM VOLUME", volume); + s->addSaveFunc([volume] { VolumeControl::getInstance()->setVolume((int)round(volume->getValue())); }); + if (ViewController::get()->isUIModeFull()) + { #ifdef _RPI_ - // OMX player Audio Device - auto omx_audio_dev = std::make_shared< OptionListComponent >(mWindow, "OMX PLAYER AUDIO DEVICE", false); - std::vector devices; - devices.push_back("local"); - devices.push_back("hdmi"); - devices.push_back("both"); - // USB audio - devices.push_back("alsa:hw:0,0"); - devices.push_back("alsa:hw:1,0"); - for (auto it = devices.begin(); it != devices.end(); it++) - omx_audio_dev->add(*it, *it, Settings::getInstance()->getString("OMXAudioDev") == *it); - s->addWithLabel("OMX PLAYER AUDIO DEVICE", omx_audio_dev); - s->addSaveFunc([omx_audio_dev] { - if (Settings::getInstance()->getString("OMXAudioDev") != omx_audio_dev->getSelected()) - Settings::getInstance()->setString("OMXAudioDev", omx_audio_dev->getSelected()); - }); + // volume control device + auto vol_dev = std::make_shared< OptionListComponent >(mWindow, "AUDIO DEVICE", false); + std::vector transitions; + transitions.push_back("PCM"); + transitions.push_back("Speaker"); + transitions.push_back("Master"); + for(auto it = transitions.begin(); it != transitions.end(); it++) + vol_dev->add(*it, *it, Settings::getInstance()->getString("AudioDevice") == *it); + s->addWithLabel("AUDIO DEVICE", vol_dev); + s->addSaveFunc([vol_dev] { + Settings::getInstance()->setString("AudioDevice", vol_dev->getSelected()); + VolumeControl::getInstance()->deinit(); + VolumeControl::getInstance()->init(); + }); #endif - mWindow->pushGui(s); - }); + // disable sounds + auto sounds_enabled = std::make_shared(mWindow); + sounds_enabled->setState(Settings::getInstance()->getBool("EnableSounds")); + s->addWithLabel("ENABLE NAVIGATION SOUNDS", sounds_enabled); + s->addSaveFunc([sounds_enabled] { Settings::getInstance()->setBool("EnableSounds", sounds_enabled->getState()); }); - addEntry("UI SETTINGS", 0x777777FF, true, - [this] { - auto s = new GuiSettings(mWindow, "UI SETTINGS"); + auto video_audio = std::make_shared(mWindow); + video_audio->setState(Settings::getInstance()->getBool("VideoAudio")); + s->addWithLabel("ENABLE VIDEO AUDIO", video_audio); + s->addSaveFunc([video_audio] { Settings::getInstance()->setBool("VideoAudio", video_audio->getState()); }); - ComponentListRow screensaver_row; - screensaver_row.elements.clear(); - screensaver_row.addElement(std::make_shared(mWindow, "SCREENSAVER SETTINGS", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); - screensaver_row.addElement(makeArrow(mWindow), false); - screensaver_row.makeAcceptInputHandler(std::bind(&GuiMenu::openScreensaverOptions, this)); - s->addRow(screensaver_row); - - // quick system select (left/right in game list view) - auto quick_sys_select = std::make_shared(mWindow); - quick_sys_select->setState(Settings::getInstance()->getBool("QuickSystemSelect")); - s->addWithLabel("QUICK SYSTEM SELECT", quick_sys_select); - s->addSaveFunc([quick_sys_select] { Settings::getInstance()->setBool("QuickSystemSelect", quick_sys_select->getState()); }); - - // carousel transition option - auto move_carousel = std::make_shared(mWindow); - move_carousel->setState(Settings::getInstance()->getBool("MoveCarousel")); - s->addWithLabel("CAROUSEL TRANSITIONS", move_carousel); - s->addSaveFunc([move_carousel] { - if (move_carousel->getState() - && !Settings::getInstance()->getBool("MoveCarousel") - && PowerSaver::getMode() == PowerSaver::INSTANT) - { - Settings::getInstance()->setString("PowerSaverMode", "default"); - PowerSaver::init(); - } - Settings::getInstance()->setBool("MoveCarousel", move_carousel->getState()); - }); - - // transition style - auto transition_style = std::make_shared< OptionListComponent >(mWindow, "TRANSITION STYLE", false); - std::vector transitions; - transitions.push_back("fade"); - transitions.push_back("slide"); - transitions.push_back("instant"); - for(auto it = transitions.begin(); it != transitions.end(); it++) - transition_style->add(*it, *it, Settings::getInstance()->getString("TransitionStyle") == *it); - s->addWithLabel("TRANSITION STYLE", transition_style); - s->addSaveFunc([transition_style] { - if (Settings::getInstance()->getString("TransitionStyle") == "instant" - && transition_style->getSelected() != "instant" - && PowerSaver::getMode() == PowerSaver::INSTANT) - { - Settings::getInstance()->setString("PowerSaverMode", "default"); - PowerSaver::init(); - } - Settings::getInstance()->setString("TransitionStyle", transition_style->getSelected()); - }); - - // theme set - auto themeSets = ThemeData::getThemeSets(); - - if(!themeSets.empty()) - { - auto selectedSet = themeSets.find(Settings::getInstance()->getString("ThemeSet")); - if(selectedSet == themeSets.end()) - selectedSet = themeSets.begin(); - - auto theme_set = std::make_shared< OptionListComponent >(mWindow, "THEME SET", false); - for(auto it = themeSets.begin(); it != themeSets.end(); it++) - theme_set->add(it->first, it->first, it == selectedSet); - s->addWithLabel("THEME SET", theme_set); - - Window* window = mWindow; - s->addSaveFunc([window, theme_set] - { - bool needReload = false; - if(Settings::getInstance()->getString("ThemeSet") != theme_set->getSelected()) - needReload = true; - - Settings::getInstance()->setString("ThemeSet", theme_set->getSelected()); - - if(needReload) - { - CollectionSystemManager::get()->updateSystemsList(); - ViewController::get()->reloadAll(); // TODO - replace this with some sort of signal-based implementation - } - }); - } - - // GameList view style - auto gamelist_style = std::make_shared< OptionListComponent >(mWindow, "GAMELIST VIEW STYLE", false); - std::vector styles; - styles.push_back("automatic"); - styles.push_back("basic"); - styles.push_back("detailed"); - styles.push_back("video"); - for (auto it = styles.begin(); it != styles.end(); it++) - gamelist_style->add(*it, *it, Settings::getInstance()->getString("GamelistViewStyle") == *it); - s->addWithLabel("GAMELIST VIEW STYLE", gamelist_style); - s->addSaveFunc([gamelist_style] { - bool needReload = false; - if (Settings::getInstance()->getString("GamelistViewStyle") != gamelist_style->getSelected()) - needReload = true; - Settings::getInstance()->setString("GamelistViewStyle", gamelist_style->getSelected()); - if (needReload) - ViewController::get()->reloadAll(); - }); - - // show help - auto show_help = std::make_shared(mWindow); - show_help->setState(Settings::getInstance()->getBool("ShowHelpPrompts")); - s->addWithLabel("ON-SCREEN HELP", show_help); - s->addSaveFunc([show_help] { Settings::getInstance()->setBool("ShowHelpPrompts", show_help->getState()); }); - - mWindow->pushGui(s); - }); - - addEntry("GAME COLLECTION SETTINGS", 0x777777FF, true, - [this] { openCollectionSystemSettings(); +#ifdef _RPI_ + // OMX player Audio Device + auto omx_audio_dev = std::make_shared< OptionListComponent >(mWindow, "OMX PLAYER AUDIO DEVICE", false); + std::vector devices; + devices.push_back("local"); + devices.push_back("hdmi"); + devices.push_back("both"); + // USB audio + devices.push_back("alsa:hw:0,0"); + devices.push_back("alsa:hw:1,0"); + for (auto it = devices.begin(); it != devices.end(); it++) + omx_audio_dev->add(*it, *it, Settings::getInstance()->getString("OMXAudioDev") == *it); + s->addWithLabel("OMX PLAYER AUDIO DEVICE", omx_audio_dev); + s->addSaveFunc([omx_audio_dev] { + if (Settings::getInstance()->getString("OMXAudioDev") != omx_audio_dev->getSelected()) + Settings::getInstance()->setString("OMXAudioDev", omx_audio_dev->getSelected()); }); +#endif + } - addEntry("OTHER SETTINGS", 0x777777FF, true, - [this] { - auto s = new GuiSettings(mWindow, "OTHER SETTINGS"); + mWindow->pushGui(s); - // maximum vram - auto max_vram = std::make_shared(mWindow, 0.f, 1000.f, 10.f, "Mb"); - max_vram->setValue((float)(Settings::getInstance()->getInt("MaxVRAM"))); - s->addWithLabel("VRAM LIMIT", max_vram); - s->addSaveFunc([max_vram] { Settings::getInstance()->setInt("MaxVRAM", (int)round(max_vram->getValue())); }); +} - // power saver - auto power_saver = std::make_shared< OptionListComponent >(mWindow, "POWER SAVER MODES", false); - std::vector modes; - modes.push_back("disabled"); - modes.push_back("default"); - modes.push_back("enhanced"); - modes.push_back("instant"); - for (auto it = modes.begin(); it != modes.end(); it++) - power_saver->add(*it, *it, Settings::getInstance()->getString("PowerSaverMode") == *it); - s->addWithLabel("POWER SAVER MODES", power_saver); - s->addSaveFunc([this, power_saver] { - if (Settings::getInstance()->getString("PowerSaverMode") != "instant" && power_saver->getSelected() == "instant") { - Settings::getInstance()->setString("TransitionStyle", "instant"); - Settings::getInstance()->setBool("MoveCarousel", false); - } - Settings::getInstance()->setString("PowerSaverMode", power_saver->getSelected()); - PowerSaver::init(); - }); +void GuiMenu::openUISettings() +{ + auto s = new GuiSettings(mWindow, "UI SETTINGS"); - // gamelists - auto save_gamelists = std::make_shared(mWindow); - save_gamelists->setState(Settings::getInstance()->getBool("SaveGamelistsOnExit")); - s->addWithLabel("SAVE METADATA ON EXIT", save_gamelists); - s->addSaveFunc([save_gamelists] { Settings::getInstance()->setBool("SaveGamelistsOnExit", save_gamelists->getState()); }); + //UI mode + auto UImodeSelection = std::make_shared< OptionListComponent >(mWindow, "UI MODE", false); + std::vector UImodes = ViewController::get()->getUIModes(); + for (auto it = UImodes.begin(); it != UImodes.end(); it++) + UImodeSelection->add(*it, *it, Settings::getInstance()->getString("UIMode") == *it); + s->addWithLabel("UI MODE", UImodeSelection); + Window* window = mWindow; + s->addSaveFunc([UImodeSelection, window] + { + LOG(LogDebug) << "Setting UI mode to" << UImodeSelection->getSelected(); + Settings::getInstance()->setString("UIMode", UImodeSelection->getSelected()); + }); - auto parse_gamelists = std::make_shared(mWindow); - parse_gamelists->setState(Settings::getInstance()->getBool("ParseGamelistOnly")); - s->addWithLabel("PARSE GAMESLISTS ONLY", parse_gamelists); - s->addSaveFunc([parse_gamelists] { Settings::getInstance()->setBool("ParseGamelistOnly", parse_gamelists->getState()); }); + // screensaver + ComponentListRow screensaver_row; + screensaver_row.elements.clear(); + screensaver_row.addElement(std::make_shared(mWindow, "SCREENSAVER SETTINGS", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); + screensaver_row.addElement(makeArrow(mWindow), false); + screensaver_row.makeAcceptInputHandler(std::bind(&GuiMenu::openScreensaverOptions, this)); + s->addRow(screensaver_row); + + // quick system select (left/right in game list view) + auto quick_sys_select = std::make_shared(mWindow); + quick_sys_select->setState(Settings::getInstance()->getBool("QuickSystemSelect")); + s->addWithLabel("QUICK SYSTEM SELECT", quick_sys_select); + s->addSaveFunc([quick_sys_select] { Settings::getInstance()->setBool("QuickSystemSelect", quick_sys_select->getState()); }); + + // carousel transition option + auto move_carousel = std::make_shared(mWindow); + move_carousel->setState(Settings::getInstance()->getBool("MoveCarousel")); + s->addWithLabel("CAROUSEL TRANSITIONS", move_carousel); + s->addSaveFunc([move_carousel] { + if (move_carousel->getState() + && !Settings::getInstance()->getBool("MoveCarousel") + && PowerSaver::getMode() == PowerSaver::INSTANT) + { + Settings::getInstance()->setString("PowerSaverMode", "default"); + PowerSaver::init(); + } + Settings::getInstance()->setBool("MoveCarousel", move_carousel->getState()); + }); + + // transition style + auto transition_style = std::make_shared< OptionListComponent >(mWindow, "TRANSITION STYLE", false); + std::vector transitions; + transitions.push_back("fade"); + transitions.push_back("slide"); + transitions.push_back("instant"); + for(auto it = transitions.begin(); it != transitions.end(); it++) + transition_style->add(*it, *it, Settings::getInstance()->getString("TransitionStyle") == *it); + s->addWithLabel("TRANSITION STYLE", transition_style); + s->addSaveFunc([transition_style] { + if (Settings::getInstance()->getString("TransitionStyle") == "instant" + && transition_style->getSelected() != "instant" + && PowerSaver::getMode() == PowerSaver::INSTANT) + { + Settings::getInstance()->setString("PowerSaverMode", "default"); + PowerSaver::init(); + } + Settings::getInstance()->setString("TransitionStyle", transition_style->getSelected()); + }); + + // theme set + auto themeSets = ThemeData::getThemeSets(); + + if(!themeSets.empty()) + { + auto selectedSet = themeSets.find(Settings::getInstance()->getString("ThemeSet")); + if(selectedSet == themeSets.end()) + selectedSet = themeSets.begin(); + + auto theme_set = std::make_shared< OptionListComponent >(mWindow, "THEME SET", false); + for(auto it = themeSets.begin(); it != themeSets.end(); it++) + theme_set->add(it->first, it->first, it == selectedSet); + s->addWithLabel("THEME SET", theme_set); + + Window* window = mWindow; + s->addSaveFunc([window, theme_set] + { + bool needReload = false; + if(Settings::getInstance()->getString("ThemeSet") != theme_set->getSelected()) + needReload = true; + + Settings::getInstance()->setString("ThemeSet", theme_set->getSelected()); + + if(needReload) + { + CollectionSystemManager::get()->updateSystemsList(); + ViewController::get()->reloadAll(); // TODO - replace this with some sort of signal-based implementation + } + }); + } + + // GameList view style + auto gamelist_style = std::make_shared< OptionListComponent >(mWindow, "GAMELIST VIEW STYLE", false); + std::vector styles; + styles.push_back("automatic"); + styles.push_back("basic"); + styles.push_back("detailed"); + styles.push_back("video"); + for (auto it = styles.begin(); it != styles.end(); it++) + gamelist_style->add(*it, *it, Settings::getInstance()->getString("GamelistViewStyle") == *it); + s->addWithLabel("GAMELIST VIEW STYLE", gamelist_style); + s->addSaveFunc([gamelist_style] { + bool needReload = false; + if (Settings::getInstance()->getString("GamelistViewStyle") != gamelist_style->getSelected()) + needReload = true; + Settings::getInstance()->setString("GamelistViewStyle", gamelist_style->getSelected()); + if (needReload) + ViewController::get()->reloadAll(); + }); + + // show help + auto show_help = std::make_shared(mWindow); + show_help->setState(Settings::getInstance()->getBool("ShowHelpPrompts")); + s->addWithLabel("ON-SCREEN HELP", show_help); + s->addSaveFunc([show_help] { Settings::getInstance()->setBool("ShowHelpPrompts", show_help->getState()); }); + + mWindow->pushGui(s); + +} + +void GuiMenu::openOtherSettings() +{ + auto s = new GuiSettings(mWindow, "OTHER SETTINGS"); + + // maximum vram + auto max_vram = std::make_shared(mWindow, 0.f, 1000.f, 10.f, "Mb"); + max_vram->setValue((float)(Settings::getInstance()->getInt("MaxVRAM"))); + s->addWithLabel("VRAM LIMIT", max_vram); + s->addSaveFunc([max_vram] { Settings::getInstance()->setInt("MaxVRAM", (int)round(max_vram->getValue())); }); + + // power saver + auto power_saver = std::make_shared< OptionListComponent >(mWindow, "POWER SAVER MODES", false); + std::vector modes; + modes.push_back("disabled"); + modes.push_back("default"); + modes.push_back("enhanced"); + modes.push_back("instant"); + for (auto it = modes.begin(); it != modes.end(); it++) + power_saver->add(*it, *it, Settings::getInstance()->getString("PowerSaverMode") == *it); + s->addWithLabel("POWER SAVER MODES", power_saver); + s->addSaveFunc([this, power_saver] { + if (Settings::getInstance()->getString("PowerSaverMode") != "instant" && power_saver->getSelected() == "instant") { + Settings::getInstance()->setString("TransitionStyle", "instant"); + Settings::getInstance()->setBool("MoveCarousel", false); + } + Settings::getInstance()->setString("PowerSaverMode", power_saver->getSelected()); + PowerSaver::init(); + }); + + // gamelists + auto save_gamelists = std::make_shared(mWindow); + save_gamelists->setState(Settings::getInstance()->getBool("SaveGamelistsOnExit")); + s->addWithLabel("SAVE METADATA ON EXIT", save_gamelists); + s->addSaveFunc([save_gamelists] { Settings::getInstance()->setBool("SaveGamelistsOnExit", save_gamelists->getState()); }); + + auto parse_gamelists = std::make_shared(mWindow); + parse_gamelists->setState(Settings::getInstance()->getBool("ParseGamelistOnly")); + s->addWithLabel("PARSE GAMESLISTS ONLY", parse_gamelists); + s->addSaveFunc([parse_gamelists] { Settings::getInstance()->setBool("ParseGamelistOnly", parse_gamelists->getState()); }); #ifndef WIN32 - // hidden files - auto hidden_files = std::make_shared(mWindow); - hidden_files->setState(Settings::getInstance()->getBool("ShowHiddenFiles")); - s->addWithLabel("SHOW HIDDEN FILES", hidden_files); - s->addSaveFunc([hidden_files] { Settings::getInstance()->setBool("ShowHiddenFiles", hidden_files->getState()); }); + // hidden files + auto hidden_files = std::make_shared(mWindow); + hidden_files->setState(Settings::getInstance()->getBool("ShowHiddenFiles")); + s->addWithLabel("SHOW HIDDEN FILES", hidden_files); + s->addSaveFunc([hidden_files] { Settings::getInstance()->setBool("ShowHiddenFiles", hidden_files->getState()); }); #endif #ifdef _RPI_ - // Video Player - VideoOmxPlayer - auto omx_player = std::make_shared(mWindow); - omx_player->setState(Settings::getInstance()->getBool("VideoOmxPlayer")); - s->addWithLabel("USE OMX PLAYER (HW ACCELERATED)", omx_player); - s->addSaveFunc([omx_player] - { - // need to reload all views to re-create the right video components - bool needReload = false; - if(Settings::getInstance()->getBool("VideoOmxPlayer") != omx_player->getState()) - needReload = true; + // Video Player - VideoOmxPlayer + auto omx_player = std::make_shared(mWindow); + omx_player->setState(Settings::getInstance()->getBool("VideoOmxPlayer")); + s->addWithLabel("USE OMX PLAYER (HW ACCELERATED)", omx_player); + s->addSaveFunc([omx_player] + { + // need to reload all views to re-create the right video components + bool needReload = false; + if(Settings::getInstance()->getBool("VideoOmxPlayer") != omx_player->getState()) + needReload = true; - Settings::getInstance()->setBool("VideoOmxPlayer", omx_player->getState()); + Settings::getInstance()->setBool("VideoOmxPlayer", omx_player->getState()); - if(needReload) - ViewController::get()->reloadAll(); - }); + if(needReload) + ViewController::get()->reloadAll(); + }); #endif - // framerate - auto framerate = std::make_shared(mWindow); - framerate->setState(Settings::getInstance()->getBool("DrawFramerate")); - s->addWithLabel("SHOW FRAMERATE", framerate); - s->addSaveFunc([framerate] { Settings::getInstance()->setBool("DrawFramerate", framerate->getState()); }); + // framerate + auto framerate = std::make_shared(mWindow); + framerate->setState(Settings::getInstance()->getBool("DrawFramerate")); + s->addWithLabel("SHOW FRAMERATE", framerate); + s->addSaveFunc([framerate] { Settings::getInstance()->setBool("DrawFramerate", framerate->getState()); }); - mWindow->pushGui(s); - }); + mWindow->pushGui(s); - addEntry("CONFIGURE INPUT", 0x777777FF, true, - [this] { - Window* window = mWindow; - window->pushGui(new GuiMsgBox(window, "ARE YOU SURE YOU WANT TO CONFIGURE INPUT?", "YES", - [window] { - window->pushGui(new GuiDetectDevice(window, false, nullptr)); - }, "NO", nullptr) - ); - }); +} - addEntry("QUIT", 0x777777FF, true, - [this] { - auto s = new GuiSettings(mWindow, "QUIT"); +void GuiMenu::openConfigInput() +{ + Window* window = mWindow; + window->pushGui(new GuiMsgBox(window, "ARE YOU SURE YOU WANT TO CONFIGURE INPUT?", "YES", + [window] { + window->pushGui(new GuiDetectDevice(window, false, nullptr)); + }, "NO", nullptr) + ); - Window* window = mWindow; +} - ComponentListRow row; - row.makeAcceptInputHandler([window] { - window->pushGui(new GuiMsgBox(window, "REALLY RESTART?", "YES", +void GuiMenu::openQuitMenu() +{ + auto s = new GuiSettings(mWindow, "QUIT"); + + Window* window = mWindow; + + ComponentListRow row; + if (ViewController::get()->isUIModeFull()) + { + row.makeAcceptInputHandler([window] { + window->pushGui(new GuiMsgBox(window, "REALLY RESTART?", "YES", [] { - if(quitES("/tmp/es-restart") != 0) - LOG(LogWarning) << "Restart terminated with non-zero result!"; - }, "NO", nullptr)); - }); - row.addElement(std::make_shared(window, "RESTART EMULATIONSTATION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); - s->addRow(row); + if(quitES("/tmp/es-restart") != 0) + LOG(LogWarning) << "Restart terminated with non-zero result!"; + }, "NO", nullptr)); + }); + row.addElement(std::make_shared(window, "RESTART EMULATIONSTATION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); + s->addRow(row); + + + if(Settings::getInstance()->getBool("ShowExit")) + { row.elements.clear(); row.makeAcceptInputHandler([window] { - window->pushGui(new GuiMsgBox(window, "REALLY RESTART?", "YES", - [] { - if(quitES("/tmp/es-sysrestart") != 0) - LOG(LogWarning) << "Restart terminated with non-zero result!"; - }, "NO", nullptr)); - }); - row.addElement(std::make_shared(window, "RESTART SYSTEM", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); - s->addRow(row); - - row.elements.clear(); - row.makeAcceptInputHandler([window] { - window->pushGui(new GuiMsgBox(window, "REALLY SHUTDOWN?", "YES", - [] { - if(quitES("/tmp/es-shutdown") != 0) - LOG(LogWarning) << "Shutdown terminated with non-zero result!"; - }, "NO", nullptr)); - }); - row.addElement(std::make_shared(window, "SHUTDOWN SYSTEM", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); - s->addRow(row); - - if(Settings::getInstance()->getBool("ShowExit")) - { - row.elements.clear(); - row.makeAcceptInputHandler([window] { - window->pushGui(new GuiMsgBox(window, "REALLY QUIT?", "YES", + window->pushGui(new GuiMsgBox(window, "REALLY QUIT?", "YES", [] { - SDL_Event ev; - ev.type = SDL_QUIT; - SDL_PushEvent(&ev); - }, "NO", nullptr)); - }); - row.addElement(std::make_shared(window, "QUIT EMULATIONSTATION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); - s->addRow(row); - } + SDL_Event ev; + ev.type = SDL_QUIT; + SDL_PushEvent(&ev); + }, "NO", nullptr)); + }); + row.addElement(std::make_shared(window, "QUIT EMULATIONSTATION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); + s->addRow(row); + } + } - mWindow->pushGui(s); + row.elements.clear(); + row.makeAcceptInputHandler([window] { + window->pushGui(new GuiMsgBox(window, "REALLY RESTART?", "YES", + [] { + if(quitES("/tmp/es-sysrestart") != 0) + LOG(LogWarning) << "Restart terminated with non-zero result!"; + }, "NO", nullptr)); }); + row.addElement(std::make_shared(window, "RESTART SYSTEM", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); + s->addRow(row); + row.elements.clear(); + row.makeAcceptInputHandler([window] { + window->pushGui(new GuiMsgBox(window, "REALLY SHUTDOWN?", "YES", + [] { + if (quitES("/tmp/es-shutdown") != 0) + LOG(LogWarning) << "Shutdown terminated with non-zero result!"; + }, "NO", nullptr)); + }); + row.addElement(std::make_shared(window, "SHUTDOWN SYSTEM", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); + s->addRow(row); + + mWindow->pushGui(s); +} + +void GuiMenu::addVersionInfo() +{ mVersion.setFont(Font::get(FONT_SIZE_SMALL)); mVersion.setColor(0x5E5E5EFF); mVersion.setText("EMULATIONSTATION V" + strToUpper(PROGRAM_VERSION_STRING)); mVersion.setHorizontalAlignment(ALIGN_CENTER); - - addChild(&mMenu); addChild(&mVersion); - setSize(mMenu.getSize()); - setPosition((Renderer::getScreenWidth() - mSize.x()) / 2, Renderer::getScreenHeight() * 0.15f); } void GuiMenu::openScreensaverOptions() { diff --git a/es-app/src/guis/GuiMenu.h b/es-app/src/guis/GuiMenu.h index 8d99f14e4..f52987fa0 100644 --- a/es-app/src/guis/GuiMenu.h +++ b/es-app/src/guis/GuiMenu.h @@ -16,8 +16,16 @@ public: private: void addEntry(const char* name, unsigned int color, bool add_arrow, const std::function& func); - void openScreensaverOptions(); + void addVersionInfo(); void openCollectionSystemSettings(); + void openConfigInput(); + void openOtherSettings(); + void openQuitMenu(); + void openScraperSettings(); + void openScreensaverOptions(); + void openSoundSettings(); + void openUISettings(); + MenuComponent mMenu; TextComponent mVersion; }; diff --git a/es-app/src/main.cpp b/es-app/src/main.cpp index 058121e65..9f89b38d4 100644 --- a/es-app/src/main.cpp +++ b/es-app/src/main.cpp @@ -85,6 +85,10 @@ bool parseArgs(int argc, char* argv[], unsigned int* width, unsigned int* height { int maxVRAM = atoi(argv[i + 1]); Settings::getInstance()->setInt("MaxVRAM", maxVRAM); + } + else if (strcmp(argv[i], "--force-kiosk") == 0) + { + Settings::getInstance()->setBool("ForceKiosk", true); }else if(strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { #ifdef WIN32 @@ -111,6 +115,7 @@ bool parseArgs(int argc, char* argv[], unsigned int* width, unsigned int* height "--windowed not fullscreen, should be used with --resolution\n" "--vsync [1/on or 0/off] turn vsync on or off (default is on)\n" "--max-vram [size] Max VRAM to use in Mb before swapping. 0 for unlimited\n" + "--force-kiosk Force the UI mode to be Kiosk\n" "--help, -h summon a sentient, angry tuba\n\n" "More information available in README.md.\n"; return false; //exit after printing help diff --git a/es-app/src/views/ViewController.cpp b/es-app/src/views/ViewController.cpp index 2b0016b8c..abba8b380 100644 --- a/es-app/src/views/ViewController.cpp +++ b/es-app/src/views/ViewController.cpp @@ -33,6 +33,7 @@ ViewController::ViewController(Window* window) : GuiComponent(window), mCurrentView(nullptr), mCamera(Eigen::Affine3f::Identity()), mFadeOpacity(0), mLockInput(false) { mState.viewing = NOTHING; + mCurUIMode = Settings::getInstance()->getString("UIMode"); } ViewController::~ViewController() @@ -43,10 +44,6 @@ ViewController::~ViewController() void ViewController::goToStart() { - // TODO - /* mState.viewing = START_SCREEN; - mCurrentView.reset(); - playViewTransition(); */ goToSystemView(SystemData::sSystemVector.at(0)); } @@ -399,6 +396,9 @@ void ViewController::render(const Eigen::Affine3f& parentTrans) Eigen::Vector3f viewStart = trans.inverse().translation(); Eigen::Vector3f viewEnd = trans.inverse() * Eigen::Vector3f((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight(), 0); + // Keep track of UI mode changes. + monitorUIMode(); + // draw systemview getSystemListView()->render(trans); @@ -499,6 +499,22 @@ void ViewController::reloadAll() updateHelpPrompts(); } +void ViewController::monitorUIMode() +{ + std::string uimode = Settings::getInstance()->getString("UIMode"); + if (uimode != mCurUIMode) // UIMODE HAS CHANGED + { + mCurUIMode = uimode; + reloadAll(); + goToStart(); + } +} + +bool ViewController::isUIModeFull() +{ + return ((mCurUIMode == "Full") && ! Settings::getInstance()->getBool("ForceKiosk")); +} + std::vector ViewController::getHelpPrompts() { std::vector prompts; diff --git a/es-app/src/views/ViewController.h b/es-app/src/views/ViewController.h index 94ed9f562..1b93fc5ed 100644 --- a/es-app/src/views/ViewController.h +++ b/es-app/src/views/ViewController.h @@ -5,6 +5,8 @@ class SystemData; +const std::vector UIModes = { "Full", "Kiosk" }; + // Used to smoothly transition the camera between multiple views (e.g. from system to system, from gamelist to gamelist). class ViewController : public GuiComponent { @@ -24,6 +26,10 @@ public: inline void reloadGameListView(SystemData* system, bool reloadTheme = false) { reloadGameListView(getGameListView(system).get(), reloadTheme); } void reloadAll(); // Reload everything with a theme. Used when the "ThemeSet" setting changes. + void monitorUIMode(); + bool isUIModeFull(); + inline std::vector getUIModes() { return UIModes; }; + // Navigation. void goToNextGameList(); void goToPrevGameList(); @@ -95,4 +101,5 @@ private: bool mLockInput; State mState; + std::string mCurUIMode; }; diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index 1397dee3b..c72cf81ee 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -13,12 +13,13 @@ std::vector settings_dont_save = boost::assign::list_of ("Debug") ("DebugGrid") ("DebugText") - ("ShowExit") - ("Windowed") - ("VSync") - ("HideConsole") + ("ForceKiosk") ("IgnoreGamelist") - ("SplashScreen"); + ("HideConsole") + ("ShowExit") + ("SplashScreen") + ("VSync") + ("Windowed"); Settings::Settings() { @@ -124,6 +125,9 @@ void Settings::setDefaults() mStringMap["AudioDevice"] = "Master"; #endif + mStringMap["UIMode"] = "Full"; + mStringMap["UIMode_passkey"] = "uuddlrlrba"; + mBoolMap["ForceKiosk"] = false; } template diff --git a/es-core/src/Window.cpp b/es-core/src/Window.cpp index 4f6b8037d..89b2543ae 100644 --- a/es-core/src/Window.cpp +++ b/es-core/src/Window.cpp @@ -14,6 +14,7 @@ Window::Window() : mNormalizeNextUpdate(false), mFrameTimeElapsed(0), mFrameCoun { mHelp = new HelpComponent(this); mBackgroundOverlay = new ImageComponent(this); + mPassKeyListener = new PassKeyListener; } Window::~Window() @@ -170,8 +171,11 @@ void Window::input(InputConfig* config, Input input) } else { - if(peekGui()) - this->peekGui()->input(config, input); + if (!mPassKeyListener->isUIModeChanged(config, input, this) && // check if UI mode has changed due to passphrase completion + peekGui()) + { + this->peekGui()->input(config, input); // this is where the majority of inputs will be consumed: the GuiComponent Stack + } } } @@ -435,3 +439,43 @@ void Window::startScreenSaver() mScreenSaver->renderScreenSaver(); } +bool Window::PassKeyListener::isUIModeChanged(InputConfig * config, Input input, Window* window) +{ + // This function reads the current input to listen for the passkey + // sequence to unlock the UI mode. The progress is saved in mPassKeyCounter + // supported sequence-inputs: u (up), d (down), l (left), r (right), a, b, x, y + // default passkeyseq = "uuddlrlrba", as defined in the setting 'UIMode_passkey'. + + if ((Settings::getInstance()->getString("UIMode") == "Full") || (!input.value)) + { + return false; // Already unlocked, or no keydown, nothing to do here. + } + + bool foundMatch = false; + + for (auto valstring : mInputVals) + { + if (config->isMappedTo(valstring, input) && + (this->mPassKeySequence[this->mPassKeyCounter] == valstring[0])) + { + this->mPassKeyCounter ++; + foundMatch = true; + } + } + + if (!foundMatch) + { + this->mPassKeyCounter = 0; // current input is incorrect, reset counter + } + + if (this->mPassKeyCounter == (this->mPassKeySequence.length())) + { + // When we have reached the end of the list, trigger UI_mode unlock + LOG(LogDebug) << " Window::PassKeyListener::isUIModeChanged(): Passkey sequence completed, switching UIMode to full"; + Settings::getInstance()->setString("UIMode", "Full"); + Settings::getInstance()->saveFile(); + this->mPassKeyCounter = 0; + return true; + } + return false; +} diff --git a/es-core/src/Window.h b/es-core/src/Window.h index 75b78e6c5..3cd363657 100644 --- a/es-core/src/Window.h +++ b/es-core/src/Window.h @@ -1,9 +1,10 @@ #pragma once #include "GuiComponent.h" +#include "InputManager.h" +#include "Settings.h" #include #include "resources/Font.h" -#include "InputManager.h" class FileData; class HelpComponent; @@ -32,6 +33,20 @@ public: virtual ~InfoPopup() {}; }; + class PassKeyListener { + public: + bool isUIModeChanged(InputConfig* config, Input input, Window* window); + PassKeyListener() + { + mPassKeySequence = Settings::getInstance()->getString("UIMode_passkey"); + mPassKeyCounter = 0; + } + private: + std::string mPassKeySequence; + int mPassKeyCounter; + const std::vector mInputVals = { "up", "down", "left", "right", "a", "b", "x", "y" }; + }; + Window(); ~Window(); @@ -79,6 +94,7 @@ private: ScreenSaver* mScreenSaver; InfoPopup* mInfoPopup; bool mRenderScreenSaver; + PassKeyListener* mPassKeyListener; std::vector mGuiStack;