ES-DE/es-core/src/components/GameSelectorComponent.h

163 lines
5.7 KiB
C++

// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// GameSelectorComponent.h
//
// Makes a selection of games based on theme-controlled criteria.
//
#ifndef ES_CORE_COMPONENTS_GAME_SELECTOR_COMPONENT_H
#define ES_CORE_COMPONENTS_GAME_SELECTOR_COMPONENT_H
#include "GuiComponent.h"
#include "Log.h"
#include "Settings.h"
#include "ThemeData.h"
class GameSelectorComponent : public GuiComponent
{
public:
GameSelectorComponent(SystemData* system)
: mSystem {system}
, mGameSelection {GameSelection::RANDOM}
, mNeedsRefresh {false}
, mGameCount {1}
{
mSystem->getRootFolder()->setUpdateListCallback([&]() { mNeedsRefresh = true; });
}
~GameSelectorComponent()
{
if (std::find(SystemData::sSystemVector.cbegin(), SystemData::sSystemVector.cend(),
mSystem) != SystemData::sSystemVector.cend())
mSystem->getRootFolder()->setUpdateListCallback(nullptr);
}
enum class GameSelection {
RANDOM,
LAST_PLAYED,
MOST_PLAYED
};
const std::vector<FileData*>& getGames() const { return mGames; }
void setNeedsRefresh() { mNeedsRefresh = true; }
const bool getNeedsRefresh() { return mNeedsRefresh; }
const GameSelection getGameSelection() const { return mGameSelection; }
const std::string& getSelectorName() const { return mSelectorName; }
void refreshGames()
{
if (!mNeedsRefresh)
return;
FileData* lastGame {nullptr};
if (mGameCount == 1 && !mGames.empty())
lastGame = mGames.front();
mGames.clear();
mNeedsRefresh = false;
bool isKidMode {(Settings::getInstance()->getString("UIMode") == "kid" ||
Settings::getInstance()->getBool("ForceKid"))};
if (mGameSelection == GameSelection::RANDOM) {
for (int i = 0; i < mGameCount; ++i) {
if (mSystem->getRootFolder()->getGameCount().first == 0)
break;
FileData* randomGame {nullptr};
if (mGameCount > 1 || lastGame == nullptr ||
mSystem->getRootFolder()->getGameCount().first == 1)
randomGame = mSystem->getRandomGame(nullptr, true);
else
randomGame = mSystem->getRandomGame(lastGame, true);
if (randomGame != nullptr)
mGames.emplace_back(randomGame);
}
}
else if (mGameSelection == GameSelection::LAST_PLAYED) {
for (auto& child : mSystem->getRootFolder()->getChildrenLastPlayed()) {
if (child->getType() != GAME)
continue;
if (!child->getCountAsGame())
continue;
if (isKidMode && !child->getKidgame())
continue;
if (child->metadata.get("lastplayed") == "0")
continue;
mGames.emplace_back(child);
if (static_cast<int>(mGames.size()) == mGameCount)
break;
}
}
else if (mGameSelection == GameSelection::MOST_PLAYED) {
for (auto& child : mSystem->getRootFolder()->getChildrenMostPlayed()) {
if (child->getType() != GAME)
continue;
if (!child->getCountAsGame())
continue;
if (isKidMode && !child->getKidgame())
continue;
if (child->metadata.get("playcount") == "0")
continue;
mGames.emplace_back(child);
if (static_cast<int>(mGames.size()) == mGameCount)
break;
}
}
}
void applyTheme(const std::shared_ptr<ThemeData>& theme,
const std::string& view,
const std::string& element,
unsigned int properties)
{
const ThemeData::ThemeElement* elem {theme->getElement(view, element, "gameselector")};
if (!elem)
return;
// Remove the leading "gameselector_" part of the element string in order to directly
// match with the optional "gameselector" property used in other elements.
mSelectorName = element.substr(13, std::string::npos);
if (elem->has("selection")) {
const std::string selection {elem->get<std::string>("selection")};
if (selection == "random") {
mGameSelection = GameSelection::RANDOM;
}
else if (selection == "lastplayed") {
mGameSelection = GameSelection::LAST_PLAYED;
mSystem->getRootFolder()->setUpdateChildrenLastPlayed(true);
mSystem->getRootFolder()->updateLastPlayedList();
}
else if (selection == "mostplayed") {
mGameSelection = GameSelection::MOST_PLAYED;
mSystem->getRootFolder()->setUpdateChildrenMostPlayed(true);
mSystem->getRootFolder()->updateMostPlayedList();
}
else {
mGameSelection = GameSelection::RANDOM;
LOG(LogWarning) << "GameSelectorComponent: Invalid theme configuration, property "
"<selection> defined as \""
<< selection << "\"";
}
}
if (elem->has("gameCount"))
mGameCount = glm::clamp(static_cast<int>(elem->get<unsigned int>("gameCount")), 1, 30);
}
private:
SystemData* mSystem;
std::vector<FileData*> mGames;
std::string mSelectorName;
GameSelection mGameSelection;
bool mNeedsRefresh;
int mGameCount;
};
#endif // ES_CORE_COMPONENTS_GAME_SELECTOR_COMPONENT_H