Now with folders! Folders will appear as a green entry in the games list. BUTTON2 can be used to 'go back.' If you're updating, you'll need to delete ~/.es_input.cfg to map BUTTON2.

This commit is contained in:
Aloshi 2012-07-27 11:58:27 -05:00
parent 77f82134bb
commit d736aba22c
14 changed files with 203 additions and 107 deletions

View file

@ -1,7 +1,7 @@
CC=g++ CC=g++
CFLAGS=-c -Wall CFLAGS=-c -Wall
LDFLAGS=-lSDL -lSDL_ttf -lboost_system -lboost_filesystem LDFLAGS=-lSDL -lSDL_ttf -lboost_system -lboost_filesystem
SRCSOURCES=main.cpp Renderer.cpp Renderer_draw.cpp GuiComponent.cpp InputManager.cpp SystemData.cpp GameData.cpp components/GuiTitleScreen.cpp components/GuiList.cpp components/GuiGameList.cpp components/GuiInputConfig.cpp SRCSOURCES=main.cpp Renderer.cpp Renderer_draw.cpp GuiComponent.cpp InputManager.cpp SystemData.cpp GameData.cpp FolderData.cpp components/GuiTitleScreen.cpp components/GuiList.cpp components/GuiGameList.cpp components/GuiInputConfig.cpp
SOURCES=$(addprefix src/,$(SRCSOURCES)) SOURCES=$(addprefix src/,$(SRCSOURCES))
OBJECTS=$(SOURCES:.cpp=.o) OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=emulationstation EXECUTABLE=emulationstation

14
src/FileData.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef _FILEDATA_H_
#define _FILEDATA_H_
#include <string>
class FileData
{
public:
virtual bool isFolder() = 0;
virtual std::string getName() = 0;
virtual std::string getPath() = 0;
};
#endif

31
src/FolderData.cpp Normal file
View file

@ -0,0 +1,31 @@
#include "FolderData.h"
#include "SystemData.h"
bool FolderData::isFolder() { return true; }
std::string FolderData::getName() { return mName; }
std::string FolderData::getPath() { return mPath; }
unsigned int FolderData::getFileCount() { return mFileVector.size(); }
FileData* FolderData::getFile(unsigned int i) { return mFileVector.at(i); }
FolderData::FolderData(SystemData* system, std::string path, std::string name)
{
mSystem = system;
mPath = path;
mName = name;
}
FolderData::~FolderData()
{
for(unsigned int i = 0; i < mFileVector.size(); i++)
{
delete mFileVector.at(i);
}
mFileVector.clear();
}
void FolderData::pushFileData(FileData* file)
{
mFileVector.push_back(file);
}

30
src/FolderData.h Normal file
View file

@ -0,0 +1,30 @@
#ifndef _FOLDER_H_
#define _FOLDER_H_
#include "FileData.h"
#include <vector>
class SystemData;
class FolderData : public FileData
{
public:
FolderData(SystemData* system, std::string path, std::string name);
~FolderData();
bool isFolder();
std::string getName();
std::string getPath();
unsigned int getFileCount();
FileData* getFile(unsigned int i);
void pushFileData(FileData* file);
private:
SystemData* mSystem;
std::string mPath;
std::string mName;
std::vector<FileData*> mFileVector;
};
#endif

View file

@ -1,6 +1,9 @@
#include "GameData.h" #include "GameData.h"
#include <iostream> #include <iostream>
bool GameData::isFolder() { return false; }
std::string GameData::getName() { return mName; }
GameData::GameData(SystemData* system, std::string path, std::string name) GameData::GameData(SystemData* system, std::string path, std::string name)
{ {
mSystem = system; mSystem = system;
@ -8,14 +11,7 @@ GameData::GameData(SystemData* system, std::string path, std::string name)
mName = name; mName = name;
} }
std::string GameData::getName() std::string GameData::getPath()
{
return mName;
}
std::string GameData::getValidPath()
{ {
//a quick and dirty way to insert a backslash before most characters that would mess up a bash path //a quick and dirty way to insert a backslash before most characters that would mess up a bash path
std::string path = mPath; std::string path = mPath;

View file

@ -2,16 +2,17 @@
#define _GAMEDATA_H_ #define _GAMEDATA_H_
#include <string> #include <string>
#include "FileData.h"
#include "SystemData.h" #include "SystemData.h"
class GameData class GameData : public FileData
{ {
public: public:
GameData(SystemData* system, std::string path, std::string name); GameData(SystemData* system, std::string path, std::string name);
std::string getName(); std::string getName();
std::string getValidPath(); std::string getPath();
bool isFolder();
private: private:
SystemData* mSystem; SystemData* mSystem;
std::string mPath; std::string mPath;

View file

@ -61,6 +61,9 @@ void InputManager::processEvent(SDL_Event* event)
case SDLK_RETURN: case SDLK_RETURN:
button = BUTTON1; button = BUTTON1;
break; break;
case SDLK_ESCAPE:
button = BUTTON2;
break;
default: default:
button = UNKNOWN; button = UNKNOWN;

View file

@ -12,15 +12,34 @@ namespace fs = boost::filesystem;
SystemData::SystemData(std::string name, std::string startPath, std::string extension, std::string command) SystemData::SystemData(std::string name, std::string startPath, std::string extension, std::string command)
{ {
mName = name; mName = name;
//expand home symbol if the startpath contains it
if(startPath[0] == '~')
{
startPath.erase(0, 1);
std::string home = getenv("HOME");
if(home.empty())
{
std::cerr << "ERROR - System start path contains ~ but $HOME is not set!\n";
return;
}else{
startPath.insert(0, home);
}
}
mStartPath = startPath; mStartPath = startPath;
mSearchExtension = extension; mSearchExtension = extension;
mLaunchCommand = command; mLaunchCommand = command;
buildGameList();
mRootFolder = new FolderData(this, mStartPath, "Search Root");
populateFolder(mRootFolder);
} }
SystemData::~SystemData() SystemData::~SystemData()
{ {
deleteGames(); delete mRootFolder;
} }
std::string strreplace(std::string& str, std::string replace, std::string with) std::string strreplace(std::string& str, std::string replace, std::string with)
@ -30,7 +49,7 @@ std::string strreplace(std::string& str, std::string replace, std::string with)
return str.replace(pos, replace.length(), with.c_str(), with.length()); return str.replace(pos, replace.length(), with.c_str(), with.length());
} }
void SystemData::launchGame(unsigned int i) void SystemData::launchGame(GameData* game)
{ {
std::cout << "Attempting to launch game...\n"; std::cout << "Attempting to launch game...\n";
@ -38,9 +57,8 @@ void SystemData::launchGame(unsigned int i)
SDL_JoystickEventState(0); SDL_JoystickEventState(0);
std::string command = mLaunchCommand; std::string command = mLaunchCommand;
GameData* game = mGameVector.at(i);
command = strreplace(command, "%ROM%", game->getValidPath()); command = strreplace(command, "%ROM%", game->getPath());
std::cout << " " << command << "\n"; std::cout << " " << command << "\n";
std::cout << "=====================================================\n"; std::cout << "=====================================================\n";
@ -53,74 +71,34 @@ void SystemData::launchGame(unsigned int i)
SDL_JoystickEventState(1); SDL_JoystickEventState(1);
} }
void SystemData::deleteGames() void SystemData::populateFolder(FolderData* folder)
{ {
for(unsigned int i = 0; i < mGameVector.size(); i++) std::string folderPath = folder->getPath();
if(!fs::is_directory(folderPath))
{ {
delete mGameVector.at(i); std::cerr << "Error - folder with path \"" << folderPath << "\" is not a directory!\n";
}
mGameVector.clear();
}
void SystemData::buildGameList()
{
std::cout << "System " << mName << " building game list...\n";
deleteGames();
//expand home symbol if necessary
if(mStartPath[0] == '~')
{
mStartPath.erase(0, 1);
std::string home = getenv("HOME");
if(home.empty())
{
std::cerr << "ERROR - System start path contains ~ but $HOME is not set!\n";
return;
}else{
mStartPath.insert(0, home);
}
}
if(!fs::is_directory(mStartPath))
{
std::cout << "Error - system \"" << mName << "\"'s start path does not exist!\n";
return; return;
} }
for(fs::recursive_directory_iterator end, dir(mStartPath); dir != end; ++dir) for(fs::directory_iterator end, dir(folderPath); dir != end; ++dir)
{ {
//std::cout << "File found: " << *dir << "\n"; fs::path filePath = (*dir).path();
fs::path path = (*dir).path(); if(fs::is_directory(filePath))
if(fs::is_directory(path))
continue;
std::string name = path.stem().string();
std::string extension = path.extension().string();
if(extension == mSearchExtension)
{ {
mGameVector.push_back(new GameData(this, path.string(), name)); FolderData* newFolder = new FolderData(this, filePath.string(), filePath.stem().string());
std::cout << " Added game \"" << name << "\"\n"; populateFolder(newFolder);
folder->pushFileData(newFolder);
}else{
if(filePath.extension().string() == mSearchExtension)
{
GameData* newGame = new GameData(this, filePath.string(), filePath.stem().string());
folder->pushFileData(newGame);
}
} }
} }
std::cout << "...done! Found " << mGameVector.size() << " games.\n";
} }
unsigned int SystemData::getGameCount()
{
return mGameVector.size();
}
GameData* SystemData::getGame(unsigned int i)
{
return mGameVector.at(i);
}
std::string SystemData::getName() std::string SystemData::getName()
{ {
@ -252,3 +230,8 @@ std::string SystemData::getConfigPath()
return(home + "/.es_systems.cfg"); return(home + "/.es_systems.cfg");
} }
FolderData* SystemData::getRootFolder()
{
return mRootFolder;
}

View file

@ -3,6 +3,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include "FolderData.h"
class GameData; class GameData;
@ -12,12 +13,10 @@ public:
SystemData(std::string name, std::string startPath, std::string extension, std::string command); SystemData(std::string name, std::string startPath, std::string extension, std::string command);
~SystemData(); ~SystemData();
unsigned int getGameCount(); FolderData* getRootFolder();
GameData* getGame(unsigned int i);
std::string getName(); std::string getName();
void buildGameList(); void launchGame(GameData* game);
void launchGame(unsigned int i);
static void deleteSystems(); static void deleteSystems();
static void loadConfig(); static void loadConfig();
static void writeExampleConfig(); static void writeExampleConfig();
@ -30,9 +29,9 @@ private:
std::string mSearchExtension; std::string mSearchExtension;
std::string mLaunchCommand; std::string mLaunchCommand;
std::vector<GameData*> mGameVector; void populateFolder(FolderData* folder);
void deleteGames(); FolderData* mRootFolder;
}; };
#endif #endif

View file

@ -40,6 +40,11 @@ void GuiGameList::setSystemId(int id)
mSystemId = id; mSystemId = id;
mSystem = SystemData::sSystemVector.at(mSystemId); mSystem = SystemData::sSystemVector.at(mSystemId);
//clear the folder stack (I can't look up the proper method right now)
while(mFolderStack.size()){ mFolderStack.pop(); }
mFolder = mSystem->getRootFolder();
updateList(); updateList();
} }
@ -52,10 +57,29 @@ void GuiGameList::onRender()
void GuiGameList::onInput(InputManager::InputButton button, bool keyDown) void GuiGameList::onInput(InputManager::InputButton button, bool keyDown)
{ {
if(button == InputManager::BUTTON1 && mSystem->getGameCount() > 0) if(button == InputManager::BUTTON1 && mFolder->getFileCount() > 0)
{ {
if(!keyDown) if(!keyDown)
mSystem->launchGame(mList->getSelection()); {
FileData* file = (FileData*)mList->getSelectedObject();
if(file->isFolder())
{
//set current directory to this or something
mFolderStack.push(mFolder);
mFolder = (FolderData*)file;
updateList();
}else{
mSystem->launchGame((GameData*)file);
}
}
}
//std::cout << "mFolderStack.size(): " << mFolderStack.size() << "\n";
if(button == InputManager::BUTTON2 && keyDown && mFolderStack.size())
{
mFolder = mFolderStack.top();
mFolderStack.pop();
updateList();
} }
if(button == InputManager::RIGHT && keyDown) if(button == InputManager::RIGHT && keyDown)
@ -72,10 +96,13 @@ void GuiGameList::updateList()
{ {
mList->clear(); mList->clear();
for(unsigned int i = 0; i < mSystem->getGameCount(); i++) for(unsigned int i = 0; i < mFolder->getFileCount(); i++)
{ {
GameData* game = mSystem->getGame(i); FileData* file = mFolder->getFile(i);
mList->addObject(game->getName(), game); if(file->isFolder())
mList->addObject(file->getName(), file, 0x00C000);
else
mList->addObject(file->getName(), file);
} }
} }

View file

@ -4,8 +4,10 @@
#include "../GuiComponent.h" #include "../GuiComponent.h"
#include "GuiList.h" #include "GuiList.h"
#include <string> #include <string>
#include <stack>
#include "../SystemData.h" #include "../SystemData.h"
#include "../GameData.h" #include "../GameData.h"
#include "../FolderData.h"
class GuiGameList : GuiComponent class GuiGameList : GuiComponent
{ {
@ -18,8 +20,11 @@ public:
void onRender(); void onRender();
void onInput(InputManager::InputButton button, bool keyDown); void onInput(InputManager::InputButton button, bool keyDown);
private: private:
SystemData* mSystem; SystemData* mSystem;
FolderData* mFolder;
std::stack<FolderData*> mFolderStack;
int mSystemId; int mSystemId;
GuiList* mList; GuiList* mList;
}; };

View file

@ -4,8 +4,8 @@
#include <fstream> #include <fstream>
std::string GuiInputConfig::sConfigPath = "./input.cfg"; std::string GuiInputConfig::sConfigPath = "./input.cfg";
std::string GuiInputConfig::sInputs[] = { "UNKNOWN", "UP", "DOWN", "LEFT", "RIGHT", "BUTTON1", "BUTTON2" }; //must be same order as InputManager::InputButton enum std::string GuiInputConfig::sInputs[] = { "UNKNOWN", "UP", "DOWN", "LEFT", "RIGHT", "BUTTON1 (Accept)", "BUTTON2 (Back)" }; //must be same order as InputManager::InputButton enum
int GuiInputConfig::sInputCount = 6; int GuiInputConfig::sInputCount = 7;
GuiInputConfig::GuiInputConfig() GuiInputConfig::GuiInputConfig()
{ {

View file

@ -23,27 +23,27 @@ void GuiList::onRender()
int screenCount = (Renderer::getScreenHeight() - cutoff) / entrySize; int screenCount = (Renderer::getScreenHeight() - cutoff) / entrySize;
screenCount -= 1; screenCount -= 1;
if((int)mNameVector.size() >= screenCount) if((int)mRowVector.size() >= screenCount)
{ {
startEntry = mSelection - (screenCount * 0.5); startEntry = mSelection - (screenCount * 0.5);
if(startEntry < 0) if(startEntry < 0)
startEntry = 0; startEntry = 0;
if(startEntry >= (int)mNameVector.size() - screenCount) if(startEntry >= (int)mRowVector.size() - screenCount)
startEntry = mNameVector.size() - screenCount; startEntry = mRowVector.size() - screenCount;
} }
int y = cutoff; int y = cutoff;
int color = 0xFF0000; int color = 0xFF0000;
if(mNameVector.size() == 0) if(mRowVector.size() == 0)
{ {
Renderer::drawCenteredText("The list is empty.", y, color); Renderer::drawCenteredText("The list is empty.", y, color);
return; return;
} }
int listCutoff = startEntry + screenCount; int listCutoff = startEntry + screenCount;
if(listCutoff > (int)mNameVector.size()) if(listCutoff > (int)mRowVector.size())
listCutoff = mNameVector.size(); listCutoff = mRowVector.size();
for(int i = startEntry; i < listCutoff; i++) for(int i = startEntry; i < listCutoff; i++)
{ {
@ -52,14 +52,15 @@ void GuiList::onRender()
Renderer::drawRect(0, y, Renderer::getScreenWidth(), 52, 0x000000); Renderer::drawRect(0, y, Renderer::getScreenWidth(), 52, 0x000000);
} }
Renderer::drawCenteredText(mNameVector.at((unsigned int)i), y, color); ListRow row = mRowVector.at((unsigned int)i);
Renderer::drawCenteredText(row.name, y, row.color);
y += 40; y += 40;
} }
} }
void GuiList::onInput(InputManager::InputButton button, bool keyDown) void GuiList::onInput(InputManager::InputButton button, bool keyDown)
{ {
if(mNameVector.size() > 0 && keyDown) if(mRowVector.size() > 0 && keyDown)
{ {
if(button == InputManager::DOWN) if(button == InputManager::DOWN)
mSelection++; mSelection++;
@ -68,34 +69,33 @@ void GuiList::onInput(InputManager::InputButton button, bool keyDown)
mSelection--; mSelection--;
if(mSelection < 0) if(mSelection < 0)
mSelection += mNameVector.size(); mSelection += mRowVector.size();
if(mSelection >= (int)mNameVector.size()) if(mSelection >= (int)mRowVector.size())
mSelection -= mNameVector.size(); mSelection -= mRowVector.size();
} }
} }
void GuiList::addObject(std::string name, void* obj) void GuiList::addObject(std::string name, void* obj, int color)
{ {
mNameVector.push_back(name); ListRow row = {name, obj, color};
mPointerVector.push_back(obj); mRowVector.push_back(row);
} }
void GuiList::clear() void GuiList::clear()
{ {
mNameVector.clear(); mRowVector.clear();
mPointerVector.clear();
mSelection = 0; mSelection = 0;
} }
std::string GuiList::getSelectedName() std::string GuiList::getSelectedName()
{ {
return mNameVector.at(mSelection); return mRowVector.at(mSelection).name;
} }
void* GuiList::getSelectedObject() void* GuiList::getSelectedObject()
{ {
return mPointerVector.at(mSelection); return mRowVector.at(mSelection).object;
} }
int GuiList::getSelection() int GuiList::getSelection()

View file

@ -7,6 +7,14 @@
#include <vector> #include <vector>
#include <string> #include <string>
struct ListRow
{
std::string name;
void* object;
int color;
};
//this should really be a template
class GuiList : public GuiComponent class GuiList : public GuiComponent
{ {
public: public:
@ -16,15 +24,14 @@ public:
void onRender(); void onRender();
void onInput(InputManager::InputButton button, bool keyDown); void onInput(InputManager::InputButton button, bool keyDown);
void addObject(std::string name, void* obj); void addObject(std::string name, void* obj, int color = 0xFF0000);
void clear(); void clear();
std::string getSelectedName(); std::string getSelectedName();
void* getSelectedObject(); void* getSelectedObject();
int getSelection(); int getSelection();
private: private:
std::vector<std::string> mNameVector; std::vector<ListRow> mRowVector;
std::vector<void*> mPointerVector;
int mSelection; int mSelection;
}; };