Commit f640bcf3 authored by Jean-Baptiste Demonte's avatar Jean-Baptiste Demonte Committed by MikaXII

feat(menu): game list: update buttons configuration (select => toggle favorite...

feat(menu): game list: update buttons configuration (select => toggle favorite view, start => option menu)
refactor(menu): avoid compound help (sharing some global menu)
parent 8484b9b3
......@@ -44,32 +44,18 @@ namespace FileSorts
return 1; // f2 is a folder
}
static int compareFavorites(FileData* const fd1, FileData* const fd2)
{
bool f1 = fd1->Metadata().Favorite();
bool f2 = fd2->Metadata().Favorite();
if (f1 == f2) return 0; // Both favorite or not
if (f1) return -1; // f1 is favorite, not f2
return 1; // f2 is favorite
}
#define CheckFavorites(f1, f2) { int favoriteComparison = compareFavorites(f1, f2); if (favoriteComparison != 0) return favoriteComparison; }
#define CheckFoldersAndGames(f1, f2) { int folderComparison = compareFoldersAndGames(f1, f2); if (folderComparison != 0) return folderComparison; }
//returns if file1 should come before file2
//returns if file1 should come before file2
ImplementSortMethod(compareFileName)
{
CheckFavorites(file1, file2);
CheckFoldersAndGames(file1, file2);
return simpleCompareUppercase(file1->getName(), file2->getName());
}
ImplementSortMethod(compareRating)
{
CheckFavorites(file1, file2);
CheckFoldersAndGames(file1, file2);
float c = file1->Metadata().Rating() - file2->Metadata().Rating();
if (c < 0) { return -1; }
if (c > 0) { return 1; }
......@@ -78,9 +64,7 @@ namespace FileSorts
ImplementSortMethod(compareTimesPlayed)
{
CheckFavorites(file1, file2);
CheckFoldersAndGames(file1, file2);
int playCount = (file1)->Metadata().PlayCount() - (file2)->Metadata().PlayCount();
if (playCount != 0) return playCount;
return simpleCompareUppercase(file1->getName(), file2->getName());
......@@ -88,20 +72,20 @@ namespace FileSorts
ImplementSortMethod(compareLastPlayed)
{
CheckFavorites(file1, file2);
CheckFoldersAndGames(file1, file2);
TimeSpan ts = (file1)->Metadata().LastPlayed() - (file2)->Metadata().LastPlayed();
if (ts.IsNull()) { simpleCompareUppercase(file1->getName(), file2->getName()); }
if (ts.IsNegative()) { return -1; }
return 1;
int ep1 = (file1)->Metadata().LastPlayedEpoc();
int ep2 = (file2)->Metadata().LastPlayedEpoc();
if (!ep1 || !ep2) {
if (ep1) return 1;
if (ep2) return -1;
return simpleCompareUppercase(file1->getName(), file2->getName());
}
return ep1 < ep2 ? -1 : 1;
}
ImplementSortMethod(compareNumberPlayers)
{
CheckFavorites(file1, file2);
CheckFoldersAndGames(file1, file2);
int players = (file1)->Metadata().PlayerRange() - (file2)->Metadata().PlayerRange();
if (players != 0) return players;
return simpleCompareUppercase(file1->getName(), file2->getName());
......@@ -109,17 +93,13 @@ namespace FileSorts
ImplementSortMethod(compareDevelopper)
{
CheckFavorites(file1, file2);
CheckFoldersAndGames(file1, file2);
return simpleCompareUppercase(file1->Metadata().Developer(), file2->Metadata().Developer());
}
ImplementSortMethod(compareGenre)
{
CheckFavorites(file1, file2);
CheckFoldersAndGames(file1, file2);
return simpleCompareUppercase(file1->Metadata().Genre(), file2->Metadata().Genre());
}
};
......@@ -22,13 +22,13 @@ GuiGamelistOptions::GuiGamelistOptions(Window* window, SystemData* system)
auto menuTheme = MenuThemeData::getInstance()->getCurrentTheme();
addChild(&mMenu);
// jump to letter
auto curChar = (char) toupper(getGamelist()->getCursor()->getName()[0]);
mJumpToLetterList = std::make_shared<LetterList>(mWindow, _("JUMP TO LETTER"), false);
std::vector<std::string> letters = getAvailableLetters();
if (!letters.empty()) { // should not arrive
std::vector<std::string> letters = getGamelist()->getAvailableLetters();
if (!letters.empty()) { // may happen if only contains folders
// jump to letter
auto curChar = (char) toupper(getGamelist()->getCursor()->getName()[0]);
// if curChar not found in available letter, take first one
if (std::find(letters.begin(), letters.end(), std::string(1, curChar)) == letters.end()) {
......@@ -197,24 +197,6 @@ void GuiGamelistOptions::openMetaDataEd() {
}, file->getSystem(), true));
}
std::vector<std::string> GuiGamelistOptions::getAvailableLetters()
{
// TODO: Algorithm!!! Use 128 array bitflag - Use better returning type - kill all vectors
// TODO: Be consistent! Use gamelist items, not FileData
std::vector<std::string> letters;
FileData::List files = getGamelist()->getFileDataList();
for (auto file : files) {
std::string letter = std::string(1, toupper(file->getName()[0]));
if ( ( (letter[0] >= '0' && letter[0] <= '9') || (letter[0] >= 'A' && letter[0] <= 'Z') ) ) {
if (std::find(letters.begin(), letters.end(), letter) == letters.end()) {
letters.push_back(letter);
}
}
}
std::sort(letters.begin(), letters.end());
return letters;
}
void GuiGamelistOptions::jumpToLetter() {
char letter = mJumpToLetterList->getSelected();
auto sortId = (unsigned int) mListSort->getSelected();
......@@ -234,36 +216,7 @@ void GuiGamelistOptions::jumpToLetter() {
gamelist->onFileChanged(mSystem->getRootFolder(), FileChangeType::Sorted);
}
FileData::List files = gamelist->getFileDataList();
long min = 0;
long max = files.size() - 1;
long mid = 0;
if (sortId == 1) {
// sort Alpha DESC
}
while(max >= min) {
mid = ((max - min) / 2) + min;
// game somehow has no first character to check
if (files.at(mid)->getName().empty()) {
continue;
}
char checkLetter = (char) toupper(files.at(mid)->getName()[0]);
if (checkLetter < letter) {
min = mid + 1;
} else if (checkLetter > letter || (mid > 0 && (letter == toupper(files.at(mid - 1)->getName()[0])))) {
max = mid - 1;
} else {
break; //exact match found
}
}
gamelist->setCursor(files.at(mid));
gamelist->jumpToLetter(letter);
delete this;
}
......
......@@ -20,7 +20,6 @@ public:
private:
void openMetaDataEd();
std::vector<std::string> getAvailableLetters();
void jumpToLetter();
MenuComponent mMenu;
......
......@@ -15,6 +15,7 @@
#include <RecalboxConf.h>
#include <guis/GuiNetPlay.h>
#include <guis/GuiLoading.h>
#include "guis/GuiMenu.h"
#include <NetPlayThread.h>
#include "ThemeData.h"
#include "MenuThemeData.h"
......@@ -168,7 +169,7 @@ bool SystemView::input(InputConfig* config, Input input)
{
if(input.value != 0)
{
if(config->getDeviceId() == DEVICE_KEYBOARD && input.value && input.id == SDLK_r && SDL_GetModState() & KMOD_LCTRL && Settings::getInstance()->getBool("Debug"))
if(config->getDeviceId() == DEVICE_KEYBOARD && input.id == SDLK_r && SDL_GetModState() & KMOD_LCTRL && Settings::getInstance()->getBool("Debug"))
{
LOG(LogInfo) << " Reloading all";
ViewController::get()->reloadAll();
......@@ -203,13 +204,14 @@ bool SystemView::input(InputConfig* config, Input input)
}
break;
}
if(config->isMappedTo("b", input))
if (config->isMappedTo("b", input))
{
stopScrolling();
ViewController::get()->goToGameList(getSelected());
return true;
}
if( config->isMappedTo("x", input) && input.value) {
if (config->isMappedTo("x", input))
{
bool kodiEnabled = RecalboxConf::getInstance()->get("kodi.enabled") == "1";
bool kodiX = RecalboxConf::getInstance()->get("kodi.xbutton") == "1";
bool netplay = RecalboxConf::getInstance()->get("global.netplay") == "1";
......@@ -254,7 +256,7 @@ bool SystemView::input(InputConfig* config, Input input)
}
if(config->isMappedTo("select", input) && RecalboxConf::getInstance()->get("emulationstation.menu") != "none")
if (config->isMappedTo("select", input) && RecalboxConf::getInstance()->get("emulationstation.menu") != "none")
{
auto s = new GuiSettings(mWindow, _("QUIT").c_str());
auto menuTheme = MenuThemeData::getInstance()->getCurrentTheme();
......@@ -323,8 +325,14 @@ bool SystemView::input(InputConfig* config, Input input)
mWindow->pushGui(s);
}
}else{
if(config->isMappedTo("left", input) ||
if (config->isMappedTo("start", input) && RecalboxConf::getInstance()->get("emulationstation.menu") != "none")
{
mWindow->pushGui(new GuiMenu(mWindow));
return true;
}
} else {
if (config->isMappedTo("left", input) ||
config->isMappedTo("right", input) ||
config->isMappedTo("up", input) ||
config->isMappedTo("down", input))
......@@ -522,22 +530,27 @@ void SystemView::render(const Eigen::Affine3f& parentTrans)
}
std::vector<HelpPrompt> SystemView::getHelpPrompts()
{
{
std::vector<HelpPrompt> prompts;
if (mCarousel.type == VERTICAL)
prompts.push_back(HelpPrompt("up/down", _("CHOOSE")));
else
prompts.push_back(HelpPrompt("left/right", _("CHOOSE")));
prompts.push_back(HelpPrompt("b", _("SELECT")));
if (RecalboxConf::getInstance()->get("kodi.enabled") == "1" && RecalboxConf::getInstance()->get("kodi.xbutton") == "1") {
if (RecalboxConf::getInstance()->get("global.netplay") == "1") {
prompts.push_back(HelpPrompt("x", _("KODI/NETPLAY")));
} else {
prompts.push_back(HelpPrompt("x", _("START KODI")));
}
} else if (RecalboxConf::getInstance()->get("global.netplay") == "1") {
prompts.push_back(HelpPrompt("x", _("NETPLAY")));
}
if (RecalboxConf::getInstance()->get("kodi.enabled") == "1" && RecalboxConf::getInstance()->get("kodi.xbutton") == "1")
{
if (RecalboxConf::getInstance()->get("global.netplay") == "1")
prompts.push_back(HelpPrompt("x", _("KODI/NETPLAY")));
else
prompts.push_back(HelpPrompt("x", _("START KODI")));
} else if (RecalboxConf::getInstance()->get("global.netplay") == "1")
prompts.push_back(HelpPrompt("x", _("NETPLAY")));
prompts.push_back(HelpPrompt("select", _("QUIT")));
prompts.push_back(HelpPrompt("start", _("MENU")));
return prompts;
}
......
......@@ -130,7 +130,7 @@ void ViewController::goToGameList(SystemData* system)
mCamera.translation().x() -= offX;
}
if (mInvalidGameList[system] == true)
if (mInvalidGameList[system])
{
if(!system->isFavorite()) {
updateFavorite(system, getGameListView(system).get()->getCursor());
......@@ -335,27 +335,16 @@ std::shared_ptr<SystemView> ViewController::getSystemListView()
bool ViewController::input(InputConfig* config, Input input)
{
if(mLockInput)
return true;
if (mLockInput) return true;
/* if we receive a button pressure for a non configured joystick, suggest the joystick configuration */
if(config->isConfigured() == false) {
if(input.type == TYPE_BUTTON) {
mWindow->pushGui(new GuiDetectDevice(mWindow, false, nullptr));
return true;
}
}
// open menu
if(config->isMappedTo("start", input) && input.value != 0 && RecalboxConf::getInstance()->get("emulationstation.menu") != "none" )
if (!config->isConfigured() && (input.type == TYPE_BUTTON) )
{
// open menu
mWindow->pushGui(new GuiMenu(mWindow));
mWindow->pushGui(new GuiDetectDevice(mWindow, false, nullptr));
return true;
}
if(mCurrentView)
return mCurrentView->input(config, input);
if (mCurrentView) return mCurrentView->input(config, input);
return false;
}
......@@ -501,22 +490,6 @@ void ViewController::reloadAll()
updateHelpPrompts();
}
void ViewController::reloadGamesLists()
{
mGameListViews.clear();
if(mState.viewing == GAME_LIST)
{
mCurrentView = getGameListView(mState.getSystem());
}else if(mState.viewing == SYSTEM_SELECT)
{
mSystemListView->goToSystem(mState.getSystem(), false);
mCurrentView = mSystemListView;
}else{
goToSystemView(SystemData::sSystemVector.front());
}
}
void ViewController::setInvalidGamesList(SystemData* system)
{
for (auto& mGameListView : mGameListViews)
......@@ -543,16 +516,7 @@ void ViewController::setAllInvalidGamesList(SystemData* systemExclude)
std::vector<HelpPrompt> ViewController::getHelpPrompts()
{
std::vector<HelpPrompt> prompts;
if(!mCurrentView)
return prompts;
prompts = mCurrentView->getHelpPrompts();
if(RecalboxConf::getInstance()->get("emulationstation.menu") != "none"){
prompts.push_back(HelpPrompt("select", _("QUIT")));
prompts.push_back(HelpPrompt("start", _("MENU")));
}
return prompts;
return mCurrentView ? mCurrentView->getHelpPrompts() : prompts;
}
HelpStyle ViewController::getHelpStyle()
......
......@@ -24,7 +24,6 @@ public:
void reloadGameListView(IGameListView* gamelist, bool reloadTheme = false);
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 reloadGamesLists();
void setInvalidGamesList(SystemData* system);
void setAllInvalidGamesList(SystemData* systemExclude);
......
......@@ -133,7 +133,7 @@ void BasicGameListView::populateList(const FolderData* folder)
if (Settings::getInstance()->getBool("ShowHidden"))
filter |= FileData::Filter::Hidden;
// Favorites only?
if (Settings::getInstance()->getBool("FavoritesOnly"))
if (mFavoritesOnly)
filter = FileData::Filter::Favorite;
// Get items
......@@ -167,89 +167,11 @@ void BasicGameListView::populateList(const FolderData* folder)
}
}
/*void BasicGameListView::populateList(const FileData* folder)
{
mPopulatedFolder = folder;
auto files = folder->getChildren();
mList.clear();
mHeaderText.setText(mSystem->getFullName());
bool favoritesOnly = false;
// find at least one favorite, else, show all items
if (Settings::getInstance()->getBool("FavoritesOnly") && !mSystem->isFavorite()) {
for (auto it = files.begin(); it != files.end(); it++) {
if ((*it)->getType() == GAME) {
if ((*it)->Metadata().Favorite()) {
favoritesOnly = true;
break;
}
}
}
}
bool showHidden = Settings::getInstance()->getBool("ShowHidden");
const FileSorts::SortType& sortType = mSystem->getSortType();
// Do not show double names in favorite system.
if (!mSystem->isFavorite() && !favoritesOnly) {
for (auto it = files.begin(); it != files.end(); it++) {
bool isHidden = (*it)->Metadata().Hidden();
if (showHidden || !isHidden) {
addItem(*it);
}
}
mList.sortByObject(sortType.comparisonFunction, sortType.ascending);
}
addFavorites(files, sortType);
if (mSystem->isFavorite() || favoritesOnly) {
listingOffset = 0;
}
}*/
void BasicGameListView::refreshList()
{
populateList(mPopulatedFolder);
}
/*void BasicGameListView::addFavorites(const FileData::List& files, const FileSorts::SortType& sortType) {
FileData::List favorites;
getFavorites(files, favorites);
std::sort(favorites.begin(), favorites.end(), *sortType.comparisonFunction);
// Reverse to unshift
if (sortType.ascending) {
std::reverse(favorites.begin(), favorites.end());
}
listingOffset = favorites.size();
for (auto it = favorites.begin(); it != favorites.end(); it++) {
addItem(*it, true);
}
}
void BasicGameListView::getFavorites(const FileData::List& files, FileData::List& favorites) {
bool showHidden = Settings::getInstance()->getBool("ShowHidden");
for (auto it = files.begin(); it != files.end(); it++) {
bool isGame = (*it)->getType() == GAME;
bool isFavorite = isGame && ((*it)->Metadata().Favorite());
bool isHidden = (*it)->Metadata().Hidden();
if (isFavorite && (showHidden || !isHidden)) {
favorites.push_back(*it);
} else if (!isGame) {
getFavorites((*it)->getChildren(), favorites);
}
}
}*/
FileData::List BasicGameListView::getFileDataList()
{
FileData::List objects = mList.getObjects();
......@@ -261,45 +183,6 @@ FileData::List BasicGameListView::getFileDataList()
return slice;
}
/*void BasicGameListView::addItem(FileData* file, bool toTheBeginning)
{
if (file->getType() == FOLDER)
{
FileData::List children = file->getChildren();
if (RecalboxConf::getInstance()->getBool(getRoot()->getSystem()->getName() + ".flatfolder"))
{
for (auto it = children.begin(); it != children.end(); it++)
{
addItem(*it);
}
return ;
}
else if (file->isSingleGameFolder())
{
addItem(children.at(0));
return ;
}
}
std::string name = file->getName();
bool isGame = file->getType() == GAME;
bool isFavorite = isGame && (file->Metadata().Favorite());
bool isHidden = file->Metadata().Hidden();
if (isHidden)
{
name = "\uF070 " + name;
}
if (isFavorite) {
if ((favorites_icons_map.find(file->getSystem()->getName())) != favorites_icons_map.end()) {
name = (favorites_icons_map.find(file->getSystem()->getName())->second) + name;
} else {
name = "\uF006 " + name;
}
}
mList.add(name, file, !isGame, toTheBeginning);
}*/
FileData* BasicGameListView::getCursor() {
return mList.getSelected();
}
......@@ -318,6 +201,10 @@ int BasicGameListView::getCursorIndex()
return mList.getCursorIndex();
}
int BasicGameListView::getCursorIndexMax(){
return mList.size() - 1;
}
void BasicGameListView::setCursor(FileData* cursor)
{
if(!mList.setCursor(cursor, listingOffset))
......@@ -350,22 +237,4 @@ void BasicGameListView::setCursor(FileData* cursor)
void BasicGameListView::launch(FileData* game) {
ViewController::get()->launch(game);
}
std::vector<HelpPrompt> BasicGameListView::getHelpPrompts() {
std::vector<HelpPrompt> prompts;
bool hideSystemView = RecalboxConf::getInstance()->get("emulationstation.hidesystemview") == "1";
if(Settings::getInstance()->getBool("QuickSystemSelect") && !hideSystemView)
prompts.push_back(HelpPrompt("left/right", _("SYSTEM")));
prompts.push_back(HelpPrompt("up/down", _("CHOOSE")));
prompts.push_back(HelpPrompt("b", _("LAUNCH")));
if ((RecalboxConf::getInstance()->get("global.netplay") == "1") && (RecalboxConf::getInstance()->isInList("global.netplay.systems", getCursor()->getSystem()->getName())))
prompts.push_back(HelpPrompt("x", _("NETPLAY")));
if(!hideSystemView)
prompts.push_back(HelpPrompt("a", _("BACK")));
if(getRoot()->getSystem() != SystemData::getFavoriteSystem()) {
prompts.push_back(HelpPrompt("y", _("Favorite")));
prompts.push_back(HelpPrompt("select", _("OPTIONS")));
}
return prompts;
}
}
\ No newline at end of file
......@@ -15,15 +15,14 @@ public:
virtual FileData* getCursor() override;
virtual int getCursorIndex() override;
virtual int getCursorIndexMax() override;
virtual void setCursor(FileData* file) override;
virtual void setCursorIndex(int index) override;
virtual const char* getName() const override { return "basic"; }
virtual std::vector<HelpPrompt> getHelpPrompts() override;
virtual void populateList(const FolderData* folder) override;
virtual void refreshList() override;
virtual void refreshList() override;
virtual inline void updateInfoPanel() override {}
......
......@@ -450,25 +450,4 @@ std::vector<GuiComponent*> DetailedGameListView::getMDValues() {
return ret;
}
std::vector<HelpPrompt> DetailedGameListView::getHelpPrompts()
{
std::vector<HelpPrompt> prompts;
bool hideSystemView = RecalboxConf::getInstance()->get("emulationstation.hidesystemview") == "1";
if (Settings::getInstance()->getBool("QuickSystemSelect") && !hideSystemView)
{
prompts.push_back(HelpPrompt("left/right", _("SYSTEM")));
}
prompts.push_back(HelpPrompt("up/down", _("CHOOSE")));
prompts.push_back(HelpPrompt("b", _("LAUNCH")));
if ((RecalboxConf::getInstance()->get("global.netplay") == "1") && (RecalboxConf::getInstance()->isInList("global.netplay.systems", getCursor()->getSystem()->getName())))
prompts.push_back(HelpPrompt("x", _("NETPLAY")));
if(!hideSystemView)
prompts.push_back(HelpPrompt("a", _("BACK")));
if(getRoot()->getSystem() != SystemData::getFavoriteSystem()) {
prompts.push_back(HelpPrompt("y", _("Favorite")));
prompts.push_back(HelpPrompt("select", _("OPTIONS")));
}
return prompts;
}
......@@ -20,8 +20,6 @@ public:
protected:
virtual void launch(FileData* game) override;
virtual std::vector<HelpPrompt> getHelpPrompts() override;
private:
void initMDLabels();
void initMDValues();
......
......@@ -2,7 +2,6 @@
#include "Window.h"
#include "guis/GuiMetaDataEd.h"
#include "guis/GuiMenu.h"
#include "guis/GuiGamelistOptions.h"
#include "views/ViewController.h"
#include "Settings.h"
#include "Log.h"
......@@ -10,15 +9,7 @@
bool IGameListView::input(InputConfig* config, Input input)
{
// select to open GuiGamelistOptions
if(config->isMappedTo("select", input) && input.value && getRoot()->getSystem() != SystemData::getFavoriteSystem())
{
//Sound::getFromTheme(mTheme, getName(), "menuOpen")->play();
mWindow->pushGui(new GuiGamelistOptions(mWindow, this->mRoot->getSystem()));
return true;
// Ctrl-R to reload a view when debugging
}else if(Settings::getInstance()->getBool("Debug") && config->getDeviceId() == DEVICE_KEYBOARD &&
if(Settings::getInstance()->getBool("Debug") && config->getDeviceId() == DEVICE_KEYBOARD &&
(SDL_GetModState() & (KMOD_LCTRL | KMOD_RCTRL)) && input.id == SDLK_r && input.value != 0)
{
LOG(LogDebug) << "reloading view";
......
......@@ -68,4 +68,6 @@ class IGameListView : public GuiComponent
virtual void refreshList() = 0;
virtual FileData::List getFileDataList() = 0;
virtual std::vector<std::string> getAvailableLetters() = 0;
virtual void jumpToLetter(char letter) = 0;
};
......@@ -19,6 +19,7 @@ public:
virtual FileData* getCursor() = 0;
virtual int getCursorIndex() = 0;
virtual int getCursorIndexMax() = 0;
virtual void setCursor(FileData*) = 0;
virtual void setCursorIndex(int) = 0;
......@@ -27,7 +28,13 @@ public:
virtual inline void updateInfoPanel() override {}
virtual inline void populateList(const FolderData* folder) override { (void)folder; }
virtual inline void refreshList() override {};
virtual inline void refreshList() override {};
virtual std::vector<HelpPrompt> getHelpPrompts() override;
virtual std::vector<std::string> getAvailableLetters() override;
virtual void jumpToLetter(char letter) override;
void jumpToNextLetter(int increment);
protected:
virtual void launch(FileData* game) = 0;
......@@ -41,7 +48,9 @@ protected:
ThemeExtras mThemeExtras;
std::stack<FolderData*> mCursorStack;
bool mFavoritesOnly;
private:
bool mFavoriteChange;
int mFavoritesCount;
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment