diff --git a/INSTALL.md b/INSTALL.md index 6facac11c..4d4370002 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -560,6 +560,7 @@ You can use `--help` or `-h` to view a list of command line options, as shown he --gamelist-only Skip automatic game ROM search, only read from gamelist.xml --ignore-gamelist Ignore the gamelist files (useful for troubleshooting) --show-hidden-files Show hidden files and folders +--show-hidden-games Show hidden games --draw-framerate Display the framerate --no-exit Don't show the exit option in the menu --no-splash Don't show the splash screen @@ -570,6 +571,7 @@ You can use `--help` or `-h` to view a list of command line options, as shown he --vsync [1/on or 0/off] Turn vsync on or off (default is on) --max-vram [size] Max VRAM to use in Mb before swapping Set to at least 20 to avoid unpredictable behavior +--force-full Force the UI mode to Full --force-kid Force the UI mode to Kid --force-kiosk Force the UI mode to Kiosk --force-disable-filters Force the UI to ignore applied filters in gamelist @@ -585,6 +587,7 @@ You can use `--help` or `-h` to view a list of command line options, as shown he --gamelist-only Skip automatic game ROM search, only read from gamelist.xml --ignore-gamelist Ignore the gamelist files (useful for troubleshooting) --show-hidden-files Show hidden files and folders +--show-hidden-games Show hidden games --draw-framerate Display the framerate --no-exit Don't show the exit option in the menu --no-splash Don't show the splash screen @@ -592,6 +595,7 @@ You can use `--help` or `-h` to view a list of command line options, as shown he --vsync [1/on or 0/off] Turn vsync on or off (default is on) --max-vram [size] Max VRAM to use in Mb before swapping Set to at least 20 to avoid unpredictable behavior +--force-full Force the UI mode to Full --force-kid Force the UI mode to Kid --force-kiosk Force the UI mode to Kiosk --force-disable-filters Force the UI to ignore applied filters in gamelist diff --git a/NEWS.md b/NEWS.md index cd0a3e066..e26c27056 100644 --- a/NEWS.md +++ b/NEWS.md @@ -17,6 +17,8 @@ v1.0.0 * Seamless (almost) launch of games without showing the desktop when starting and returning from RetroArch and other emulators * Per-game launch command override, so that different cores or emulators can be used on a per-game basis (saved to gamelist.xml) * Core location can be defined relative to the emulator binary using the %EMUPATH% varible in es_systems.cfg (mostly useful for Windows) +* Properly implemented the option to show or hide hidden files and folders +* Properly implemented the option to show or hide games flagged as hidden in the metadata editor * Help system updated and expanded to the complete application (previously it was only partially implemented) * Improved input device configuration, and default keyboard mappings are now applied if the keyboard has not been configured by the user * GUI-configurable option to sort favorite games on the top of the game lists (favorites marked with stars) diff --git a/es-app/src/CollectionSystemManager.cpp b/es-app/src/CollectionSystemManager.cpp index 85f4aa993..680062fb0 100644 --- a/es-app/src/CollectionSystemManager.cpp +++ b/es-app/src/CollectionSystemManager.cpp @@ -873,7 +873,7 @@ void CollectionSystemManager::populateCustomCollection(CollectionSystemData* sys // Get the ROM directory, either as configured in es_settings.cfg, or if no value // is set there, then use the default hardcoded path. - const std::string rompath = FileData::getROMDirectory(); + const std::string rompath = FileData::getROMDirectory(); // Iterate list of files in the config file. for (std::string gameKey; getline(input, gameKey); ) { diff --git a/es-app/src/FileData.cpp b/es-app/src/FileData.cpp index 904c8f694..02c57b912 100644 --- a/es-app/src/FileData.cpp +++ b/es-app/src/FileData.cpp @@ -110,6 +110,32 @@ const bool FileData::getFavorite() return false; } +const bool FileData::getHidden() +{ + if (metadata.get("hidden") == "true") + return true; + else + return false; +} + +const std::vector FileData::getChildrenRercursive() const +{ + std::vector childrenRecursive; + + for (auto it = mChildrenByFilename.cbegin(); + it != mChildrenByFilename.cend(); it++) { + childrenRecursive.push_back((*it).second); + // Recurse through any subdirectories. + if ((*it).second->getType() == FOLDER) { + std::vector childrenSubdirectory = (*it).second->getChildrenRercursive(); + childrenRecursive.insert(childrenRecursive.end(), + childrenSubdirectory.begin(), childrenSubdirectory.end()); + } + } + + return childrenRecursive; +} + const std::string FileData::getROMDirectory() { std::string romDirSetting = Settings::getInstance()->getString("ROMDirectory"); @@ -346,6 +372,24 @@ void FileData::removeChild(FileData* file) void FileData::sort(ComparisonFunction& comparator, bool ascending) { mFirstLetterIndex.clear(); + + // Only run this section of code if the setting to show hidden games has been disabled, + // in order to avoid unnecessary processing. + if (!Settings::getInstance()->getBool("ShowHiddenGames")) { + std::vector mChildrenShown; + for (unsigned int i = 0; i < mChildren.size(); i++) { + if (mChildren[i]->getHidden()) { + LOG(LogDebug) << "Debug - FileData::sort(): Skipping hidden game '" << + mChildren[i]->getName() << "'"; + continue; + } + mChildrenShown.push_back(mChildren[i]); + } + mChildren.erase(mChildren.begin(), mChildren.end()); + mChildren.reserve(mChildrenShown.size()); + mChildren.insert(mChildren.end(), mChildrenShown.begin(), mChildrenShown.end()); + } + std::stable_sort(mChildren.begin(), mChildren.end(), comparator); for (auto it = mChildren.cbegin(); it != mChildren.cend(); it++) { @@ -371,8 +415,16 @@ void FileData::sortFavoritesOnTop(ComparisonFunction& comparator, bool ascending mFirstLetterIndex.clear(); std::vector mChildrenFavorites; std::vector mChildrenOthers; + bool showHiddenGames = Settings::getInstance()->getBool("ShowHiddenGames"); for (unsigned int i = 0; i < mChildren.size(); i++) { + // Exclude game if it's marked as hidden and the hide setting has been set. + if (!showHiddenGames && mChildren[i]->getHidden()) { + LOG(LogDebug) << "Debug - FileData::sortFavoritesOnTop(): Skipping hidden game '" << + mChildren[i]->getName() << "'"; + continue; + } + if (mChildren[i]->getFavorite()) { mChildrenFavorites.push_back(mChildren[i]); } diff --git a/es-app/src/FileData.h b/es-app/src/FileData.h index 2297c0ce4..9353e81d6 100644 --- a/es-app/src/FileData.h +++ b/es-app/src/FileData.h @@ -47,6 +47,8 @@ public: virtual const std::string& getName(); const std::string& getSortName(); const bool getFavorite(); + const bool getHidden(); + const std::vector getChildrenRercursive() const; inline FileType getType() const { return mType; } inline const std::string& getPath() const { return mPath; } inline FileData* getParent() const { return mParent; } diff --git a/es-app/src/Gamelist.cpp b/es-app/src/Gamelist.cpp index fe7e2d855..0a3739f77 100644 --- a/es-app/src/Gamelist.cpp +++ b/es-app/src/Gamelist.cpp @@ -128,7 +128,7 @@ void parseGamelist(SystemData* system) relativeTo, false); if (!trustGamelist && !Utils::FileSystem::exists(path)) { - LOG(LogWarning) << "File \"" << path << "\" does not exist! Ignoring."; + LOG(LogWarning) << "Warning - File \"" << path << "\" does not exist, ignoring."; continue; } diff --git a/es-app/src/SystemData.cpp b/es-app/src/SystemData.cpp index 8ad83df51..01bb0976c 100644 --- a/es-app/src/SystemData.cpp +++ b/es-app/src/SystemData.cpp @@ -315,7 +315,24 @@ bool SystemData::loadConfig() envData->mPlatformIds = platformIds; SystemData* newSys = new SystemData(name, fullname, envData, themeFolder); - if (newSys->getRootFolder()->getChildrenByFilename().size() == 0) { + bool onlyHidden = false; + + // If the option to show hidden games has been disabled, then check whether all + // games for the system are hidden. That will flag the system as empty. + if (!Settings::getInstance()->getBool("ShowHiddenGames")) { + std::vector recursiveGames = + newSys->getRootFolder()->getChildrenRercursive(); + onlyHidden = true; + for (auto it = recursiveGames.cbegin(); it != recursiveGames.cend(); it++) { + if ((*it)->getType() != FOLDER) { + onlyHidden = (*it)->getHidden(); + if (!onlyHidden) + break; + } + } + } + + if (newSys->getRootFolder()->getChildrenByFilename().size() == 0 || onlyHidden) { LOG(LogDebug) << "SystemData::loadConfig(): System \"" << name << "\" has no games, ignoring it."; delete newSys; diff --git a/es-app/src/emulationstation.6.gz b/es-app/src/emulationstation.6.gz index 653c0d1a3..46527c692 100644 Binary files a/es-app/src/emulationstation.6.gz and b/es-app/src/emulationstation.6.gz differ diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index 448c2041a..6a3417b1e 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -618,6 +618,22 @@ void GuiMenu::openOtherSettings() s->addSaveFunc([launchcommand_override] { Settings::getInstance()-> setBool("LaunchCommandOverride", launchcommand_override->getState()); }); + // Hidden files. + auto hidden_files = std::make_shared(mWindow); + hidden_files->setState(Settings::getInstance()->getBool("ShowHiddenFiles")); + s->addWithLabel("SHOW HIDDEN FILES AND FOLDERS (REQUIRES RESTART)", hidden_files); + s->addSaveFunc([hidden_files] { Settings::getInstance()->setBool("ShowHiddenFiles", + hidden_files->getState()); }); + + // Hidden games. + auto hidden_games = std::make_shared(mWindow); + hidden_games->setState(Settings::getInstance()->getBool("ShowHiddenGames")); + s->addWithLabel("SHOW HIDDEN GAMES (REQUIRES RESTART)", hidden_games); + s->addSaveFunc([hidden_games] { + Settings::getInstance()->setBool("ShowHiddenGames", + hidden_games->getState()); + }); + // Custom event scripts, fired using Scripting::fireEvent(). auto custom_eventscripts = std::make_shared(mWindow); custom_eventscripts->setState(Settings::getInstance()->getBool("CustomEventScripts")); @@ -637,13 +653,6 @@ void GuiMenu::openOtherSettings() s->addSaveFunc([local_art] { Settings::getInstance()-> setBool("LocalArt", local_art->getState()); }); - // Hidden files. - auto hidden_files = std::make_shared(mWindow); - hidden_files->setState(Settings::getInstance()->getBool("ShowHiddenFiles")); - s->addWithLabel("SHOW HIDDEN FILES AND FOLDERS (REQUIRES RESTART)", hidden_files); - s->addSaveFunc([hidden_files] { Settings::getInstance()->setBool("ShowHiddenFiles", - hidden_files->getState()); }); - // Framerate. auto framerate = std::make_shared(mWindow); framerate->setState(Settings::getInstance()->getBool("DrawFramerate")); diff --git a/es-app/src/guis/GuiMetaDataEd.cpp b/es-app/src/guis/GuiMetaDataEd.cpp index 12c891aa5..e46e95c36 100644 --- a/es-app/src/guis/GuiMetaDataEd.cpp +++ b/es-app/src/guis/GuiMetaDataEd.cpp @@ -26,6 +26,7 @@ #include "CollectionSystemManager.h" #include "FileData.h" #include "FileFilterIndex.h" +#include "Gamelist.h" #include "SystemData.h" #include "Window.h" @@ -283,10 +284,19 @@ void GuiMetaDataEd::save() // Remove game from index. mScraperParams.system->getIndex()->removeFromIndex(mScraperParams.game); + // We need this to handle the special situation where the user sets a game to hidden while + // ShowHiddenGames is set to false, meaning it will immediately disappear from the gamelist. + bool showHiddenGames = Settings::getInstance()->getBool("ShowHiddenGames"); + bool hideGameWhileHidden = false; + for (unsigned int i = 0; i < mEditors.size(); i++) { if (mMetaDataDecl.at(i).isStatistic) continue; + if (!showHiddenGames && mMetaDataDecl.at(i).key == "hidden" && + mEditors.at(i)->getValue() != mMetaData->get("hidden")) + hideGameWhileHidden = true; + // If the user has entered a blank game name, then set the name to the ROM // filename (minus the extension). if (mMetaDataDecl.at(i).key == "name" && mEditors.at(i)->getValue() == "") { @@ -298,6 +308,14 @@ void GuiMetaDataEd::save() } } + // If hidden games are not shown and the hide flag was set for the game, then write the + // metadata immediately regardless of the SaveGamelistsMode setting. Otherwise the file + // will never be written as the game will be filtered from the gamelist. This solution is not + // really good as the gamelist will be written twice, but it's a very special and hopefully + // rare situation. + if (hideGameWhileHidden) + updateGamelist(mScraperParams.system); + // Enter game in index. mScraperParams.system->getIndex()->addToIndex(mScraperParams.game); diff --git a/es-app/src/main.cpp b/es-app/src/main.cpp index 688100832..0071ed265 100644 --- a/es-app/src/main.cpp +++ b/es-app/src/main.cpp @@ -232,6 +232,9 @@ bool parseArgs(int argc, char* argv[]) else if (strcmp(argv[i], "--show-hidden-files") == 0) { Settings::getInstance()->setBool("ShowHiddenFiles", true); } + else if (strcmp(argv[i], "--show-hidden-games") == 0) { + Settings::getInstance()->setBool("ShowHiddenGames", true); + } else if (strcmp(argv[i], "--draw-framerate") == 0) { Settings::getInstance()->setBool("DrawFramerate", true); } @@ -263,6 +266,9 @@ bool parseArgs(int argc, char* argv[]) Settings::getInstance()->setBool("VSync", vsync); i++; // Skip vsync value. } + else if (strcmp(argv[i], "--force-full") == 0) { + Settings::getInstance()->setString("UIMode", "Full"); + } else if (strcmp(argv[i], "--force-kiosk") == 0) { Settings::getInstance()->setBool("ForceKiosk", true); } @@ -286,6 +292,7 @@ bool parseArgs(int argc, char* argv[]) " --gamelist-only Skip automatic game ROM search, only read from gamelist.xml\n" " --ignore-gamelist Ignore the gamelist files (useful for troubleshooting)\n" " --show-hidden-files Show hidden files and folders\n" +" --show-hidden-games Show hidden games\n" " --draw-framerate Display the framerate\n" " --no-exit Don't show the exit option in the menu\n" " --no-splash Don't show the splash screen\n" @@ -298,6 +305,7 @@ bool parseArgs(int argc, char* argv[]) " --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\n" " Set to at least 20 to avoid unpredictable behavior\n" +" --force-full Force the UI mode to Full\n" " --force-kid Force the UI mode to Kid\n" " --force-kiosk Force the UI mode to Kiosk\n" " --force-disable-filters Force the UI to ignore applied filters in gamelist\n" diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index d2e482fa1..bc8d3f20c 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -194,7 +194,8 @@ void Settings::setDefaults() mBoolMap["CustomEventScripts"] = false; mBoolMap["ParseGamelistOnly"] = false; mBoolMap["LocalArt"] = false; - mBoolMap["ShowHiddenFiles"] = false; + mBoolMap["ShowHiddenFiles"] = true; + mBoolMap["ShowHiddenGames"] = true; mBoolMap["DrawFramerate"] = false; mBoolMap["ShowRebootSystem"] = true; mBoolMap["ShowPoweroffSystem"] = true;