Fixed multiple issues with random selection of systems and games.

This commit is contained in:
Leon Styhre 2020-07-28 15:19:54 +02:00
parent ce9d5c2599
commit ea59d9f9c4
8 changed files with 115 additions and 35 deletions

View file

@ -62,6 +62,9 @@ Many bugs have been fixed, and numerous features that were only partially implem
* Toggling the screensaver didn't work as expected * Toggling the screensaver didn't work as expected
* The setting to enable or disable audio for the video screensaver only worked on Raspberry Pi * The setting to enable or disable audio for the video screensaver only worked on Raspberry Pi
* The screensaver random function did not consider the previously selected game and could potentially show the same image or video over and over again * The screensaver random function did not consider the previously selected game and could potentially show the same image or video over and over again
* The random system selection did not consider the currently selected system
* The random game selection did not consider the currently selected game
* The random game selection traversed folders, i.e. a game could be selected inside a subdirectory and vice versa
* Deleting a game did not delete the game media files or its entry in the gamelist.xml file * Deleting a game did not delete the game media files or its entry in the gamelist.xml file
* SystemView didn't properly loop the systems if only two systems were available * SystemView didn't properly loop the systems if only two systems were available
* Hidden files still showed up if they had a gamelist.xml entry * Hidden files still showed up if they had a gamelist.xml entry

View file

@ -729,9 +729,11 @@ void CollectionSystemManager::updateCollectionFolderMetadata(SystemData* sys)
FileData* randomGame = sys->getRandomGame(); FileData* randomGame = sys->getRandomGame();
video = randomGame->getVideoPath(); if (randomGame) {
thumbnail = randomGame->getThumbnailPath(); video = randomGame->getVideoPath();
image = randomGame->getImagePath(); thumbnail = randomGame->getThumbnailPath();
image = randomGame->getImagePath();
}
} }
rootFolder->metadata.set("desc", desc); rootFolder->metadata.set("desc", desc);

View file

@ -114,7 +114,7 @@ const bool FileData::getHidden()
return false; return false;
} }
const std::vector<FileData*> FileData::getChildrenRercursive() const const std::vector<FileData*> FileData::getChildrenRecursive() const
{ {
std::vector<FileData*> childrenRecursive; std::vector<FileData*> childrenRecursive;
@ -123,7 +123,7 @@ const std::vector<FileData*> FileData::getChildrenRercursive() const
childrenRecursive.push_back((*it).second); childrenRecursive.push_back((*it).second);
// Recurse through any subdirectories. // Recurse through any subdirectories.
if ((*it).second->getType() == FOLDER) { if ((*it).second->getType() == FOLDER) {
std::vector<FileData*> childrenSubdirectory = (*it).second->getChildrenRercursive(); std::vector<FileData*> childrenSubdirectory = (*it).second->getChildrenRecursive();
childrenRecursive.insert(childrenRecursive.end(), childrenRecursive.insert(childrenRecursive.end(),
childrenSubdirectory.begin(), childrenSubdirectory.end()); childrenSubdirectory.begin(), childrenSubdirectory.end());
} }

View file

@ -48,7 +48,7 @@ public:
const std::string& getSortName(); const std::string& getSortName();
const bool getFavorite(); const bool getFavorite();
const bool getHidden(); const bool getHidden();
const std::vector<FileData*> getChildrenRercursive() const; const std::vector<FileData*> getChildrenRecursive() const;
inline FileType getType() const { return mType; } inline FileType getType() const { return mType; }
inline const std::string& getPath() const { return mPath; } inline const std::string& getPath() const { return mPath; }
inline FileData* getParent() const { return mParent; } inline FileData* getParent() const { return mParent; }

View file

@ -329,7 +329,7 @@ bool SystemData::loadConfig()
// games for the system are hidden. That will flag the system as empty. // games for the system are hidden. That will flag the system as empty.
if (!Settings::getInstance()->getBool("ShowHiddenGames")) { if (!Settings::getInstance()->getBool("ShowHiddenGames")) {
std::vector<FileData*> recursiveGames = std::vector<FileData*> recursiveGames =
newSys->getRootFolder()->getChildrenRercursive(); newSys->getRootFolder()->getChildrenRecursive();
onlyHidden = true; onlyHidden = true;
for (auto it = recursiveGames.cbegin(); it != recursiveGames.cend(); it++) { for (auto it = recursiveGames.cbegin(); it != recursiveGames.cend(); it++) {
if ((*it)->getType() != FOLDER) { if ((*it)->getType() != FOLDER) {
@ -490,44 +490,110 @@ unsigned int SystemData::getGameCount() const
return (unsigned int)mRootFolder->getFilesRecursive(GAME).size(); return (unsigned int)mRootFolder->getFilesRecursive(GAME).size();
} }
SystemData* SystemData::getRandomSystem() SystemData* SystemData::getRandomSystem(const SystemData* currentSystem)
{ {
// This is a bit brute force.
// It might be more efficient to just do a while (!gameSystem) do random again...
unsigned int total = 0; unsigned int total = 0;
for (auto it = sSystemVector.cbegin(); it != sSystemVector.cend(); it++) { for (auto it = sSystemVector.cbegin(); it != sSystemVector.cend(); it++) {
if ((*it)->isGameSystem()) if ((*it)->isGameSystem())
total++; total++;
} }
// Get a random number in range. if (total < 2)
int target = (int)Math::round((std::rand() / (float)RAND_MAX) * (total - 1)); return nullptr;
for (auto it = sSystemVector.cbegin(); it != sSystemVector.cend(); it++)
{ SystemData* randomSystem;
if ((*it)->isGameSystem()) {
if (target > 0) do {
target--; // Get a random number in range.
else int target = (int)Math::round((std::rand() / (float)RAND_MAX) * (total - 1));
return (*it);
for (auto it = sSystemVector.cbegin(); it != sSystemVector.cend(); it++) {
if ((*it)->isGameSystem()) {
if (target > 0) {
target--;
}
else {
randomSystem = (*it);
break;
}
}
}
}
while (randomSystem == currentSystem);
return randomSystem;
}
FileData* SystemData::getRandomCollectionFolder(const FileData* currentFolder)
{
if (!currentFolder)
return nullptr;
std::vector<FileData*> collectionFolders = currentFolder->getParent()->getChildren();
unsigned int total = collectionFolders.size();
int target = 0;
if (total < 2)
return nullptr;
do {
// Get a random number in range.
target = (int)Math::round((std::rand() / (float)RAND_MAX) * (total - 1));
}
while (collectionFolders.at(target) == currentFolder);
return collectionFolders.at(target);
}
FileData* SystemData::getRandomGame(const FileData* currentGame)
{
std::vector<FileData*> gameList = mRootFolder->getFilesRecursive(GAME, true);
if (currentGame) {
// If the game is inside a folder, update gameList to only contain the games
// inside this folder.
if (currentGame->getParent()->getFullPath() !=
currentGame->getSystem()->getRootFolder()->getFullPath()) {
std::vector<FileData*> folderList;
for (auto it = gameList.cbegin(); it != gameList.cend(); it++) {
if ((*it)->getParent()->getFullPath() == currentGame->getParent()->getFullPath())
folderList.push_back((*it));
}
gameList.erase(gameList.cbegin(), gameList.cend());
gameList.reserve(folderList.size());
gameList.insert(gameList.cend(), folderList.cbegin(), folderList.cend());
}
// If the game is not inside a folder, update gameList to exclude all folders.
else {
std::vector<FileData*> childrenList = mRootFolder->getChildren();
std::vector<FileData*> noFolderList;
for (auto it = childrenList.cbegin(); it != childrenList.cend(); it++) {
if ((*it)->getType() == GAME)
noFolderList.push_back((*it));
}
gameList.erase(gameList.cbegin(), gameList.cend());
gameList.reserve(noFolderList.size());
gameList.insert(gameList.cend(), noFolderList.cbegin(), noFolderList.cend());
} }
} }
// If we end up here, there is no valid system. unsigned int total = (int)gameList.size();
return nullptr;
}
FileData* SystemData::getRandomGame()
{
std::vector<FileData*> list = mRootFolder->getFilesRecursive(GAME, true);
unsigned int total = (int)list.size();
int target = 0; int target = 0;
// Get a random number in range. if (total < 2)
if (total == 0)
return nullptr; return nullptr;
target = (int)Math::round((std::rand() / (float)RAND_MAX) * (total - 1));
return list.at(target); do {
// Get a random number in range.
target = (int)Math::round((std::rand() / (float)RAND_MAX) * (total - 1));
}
while (currentGame && gameList.at(target) == currentGame);
return gameList.at(target);
} }
unsigned int SystemData::getDisplayedGameCount() const unsigned int SystemData::getDisplayedGameCount() const

View file

@ -86,8 +86,9 @@ public:
SystemData* getNext() const; SystemData* getNext() const;
SystemData* getPrev() const; SystemData* getPrev() const;
static SystemData* getRandomSystem(); static SystemData* getRandomSystem(const SystemData* currentSystem);
FileData* getRandomGame(); static FileData* getRandomCollectionFolder(const FileData* currentFolder);
FileData* getRandomGame(const FileData* currentGame = nullptr);
// Load or re-load theme. // Load or re-load theme.
void loadTheme(); void loadTheme();

View file

@ -195,7 +195,7 @@ bool SystemView::input(InputConfig* config, Input input)
// Get random system. // Get random system.
// Go to system. // Go to system.
NavigationSounds::getInstance()->playThemeNavigationSound(SYSTEMBROWSESOUND); NavigationSounds::getInstance()->playThemeNavigationSound(SYSTEMBROWSESOUND);
setCursor(SystemData::getRandomSystem()); setCursor(SystemData::getRandomSystem(getSelected()));
return true; return true;
} }
} }

View file

@ -141,9 +141,17 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
if (mRoot->getSystem()->isGameSystem()) { if (mRoot->getSystem()->isGameSystem()) {
// Go to random system game. // Go to random system game.
NavigationSounds::getInstance()->playThemeNavigationSound(SCROLLSOUND); NavigationSounds::getInstance()->playThemeNavigationSound(SCROLLSOUND);
FileData* randomGame = getCursor()->getSystem()->getRandomGame(); FileData* randomGame = getCursor()->getSystem()->getRandomGame(getCursor());
if (randomGame) if (randomGame)
setCursor(randomGame); setCursor(randomGame);
// If it's not a game, maybe it's a folder for an unthemed collection.
else if (getCursor()->getSystem()->isCollection()) {
FileData* randomFolder =
mRoot->getSystem()->getRandomCollectionFolder(getCursor());
if (randomFolder)
setCursor(randomFolder);
}
return true; return true;
} }
} }