Merge pull request #37 from twolife/master

Add a new directory for gamelist.xml & theme.xml for each system
This commit is contained in:
Aloshi 2012-12-18 06:39:27 -08:00
commit 56ae7c1b69
8 changed files with 76 additions and 32 deletions

View file

@ -111,7 +111,7 @@ An example gamelist.xml:
</gameList>
```
The path element should be the absolute path of the ROM. Special characters SHOULD NOT be escaped. The image element is the absolute path to an image to display above the description (like a screenshot or boxart). Most formats can be used (including png, jpg, gif, etc.). Not all elements need to be used.
The path element should be the absolute path of the ROM. Special characters SHOULD NOT be escaped. The image element is the path to an image to display above the description (like a screenshot or boxart). Most formats can be used (including png, jpg, gif, etc.). Not all elements need to be used.
The switch `--gamelist-only` can be used to skip automatic searching, and only display games defined in the system's gamelist.xml.
The switch `--ignore-gamelist` can be used to ignore the gamelist and use the non-detailed view.

View file

@ -3,7 +3,10 @@ Themes
EmulationStation allows each system to have its own "theme." A theme is a collection of display settings and images defined in an XML document.
ES will check two places for a theme: first, the system's search directory for theme.xml. Then, if that's not found, $HOME/.emulationstation/es_theme.xml will be used.
ES will check 3 places for a theme, in the following order:
- a theme.xml file in the sysytem's %PATH% directory.
- $HOME/.emulationstation/%NAME%/theme.xml
- $HOME/.emulationstation/es_theme.xml
Almost all positions, dimensions, origins, etc. work in percentages - that is, they are a decimal between 0 and 1, representing the percentage of the screen on that axis to use. This ensures that themes look similar at every resolution.

View file

@ -18,9 +18,10 @@ extern bool IGNOREGAMELIST;
std::string SystemData::getStartPath() { return mStartPath; }
std::string SystemData::getExtension() { return mSearchExtension; }
SystemData::SystemData(std::string name, std::string startPath, std::string extension, std::string command)
SystemData::SystemData(std::string name, std::string desc, std::string startPath, std::string extension, std::string command)
{
mName = name;
mDesc = desc;
//expand home symbol if the startpath contains it
if(startPath[0] == '~')
@ -41,7 +42,6 @@ SystemData::SystemData(std::string name, std::string startPath, std::string exte
mSearchExtension = extension;
mLaunchCommand = command;
mRootFolder = new FolderData(this, mStartPath, "Search Root");
if(!PARSEGAMELISTONLY)
@ -153,14 +153,15 @@ void SystemData::populateFolder(FolderData* folder)
}
}
std::string SystemData::getName()
{
return mName;
}
std::string SystemData::getDesc()
{
return mDesc;
}
//creates systems from information located in a config file
void SystemData::loadConfig()
@ -175,7 +176,7 @@ void SystemData::loadConfig()
if(file.is_open())
{
std::string line;
std::string sysName, sysPath, sysExtension, sysCommand;
std::string sysName, sysDesc, sysPath, sysExtension, sysCommand;
while(file.good())
{
std::getline(file, line);
@ -203,6 +204,8 @@ void SystemData::loadConfig()
//map the value to the appropriate variable
if(varName == "NAME")
sysName = varValue;
else if(varName == "DESC")
sysDesc = varValue;
else if(varName == "PATH")
{
if(varValue[varValue.length() - 1] == '/')
@ -215,9 +218,9 @@ void SystemData::loadConfig()
sysCommand = varValue;
//we have all our variables - create the system object
if(!sysName.empty() && !sysPath.empty() &&!sysExtension.empty() && !sysCommand.empty())
if(!sysName.empty() && !sysDesc.empty() && !sysPath.empty() &&!sysExtension.empty() && !sysCommand.empty())
{
SystemData* newSystem = new SystemData(sysName, sysPath, sysExtension, sysCommand);
SystemData* newSystem = new SystemData(sysName, sysDesc, sysPath, sysExtension, sysCommand);
if(newSystem->getRootFolder()->getFileCount() == 0)
{
std::cout << "System \"" << sysName << "\" has no games! Deleting.\n";
@ -227,7 +230,7 @@ void SystemData::loadConfig()
}
//reset the variables for the next block (should there be one)
sysName = ""; sysPath = ""; sysExtension = ""; sysCommand = "";
sysName = ""; sysDesc = ""; sysPath = ""; sysExtension = ""; sysCommand = "" ;
}
}else{
std::cerr << "Error reading config file \"" << path << "\" - no equals sign found on line \"" << line << "\"!\n";
@ -252,18 +255,21 @@ void SystemData::writeExampleConfig()
file << "# This is the EmulationStation Systems configuration file." << std::endl;
file << "# Lines that begin with a hash (#) are ignored, as are empty lines." << std::endl;
file << "# A sample system might look like this:" << std::endl;
file << "#NAME=Nintendo Entertainment System" << std::endl;
file << "#NAME=nes" << std::endl;
file << "#DESC=Nintendo Entertainment System" << std::endl;
file << "#PATH=~/ROMs/nes/" << std::endl;
file << "#EXTENSION=.nes .NES" << std::endl;
file << "#COMMAND=retroarch -L ~/cores/libretro-fceumm.so %ROM%" << std::endl << std::endl;
file << "#NAME is just a name to identify the system." << std::endl;
file << "#NAME is a short name used internaly." << std::endl;
file << "#DESC is just a pretty desciption to identify the system." << std::endl;
file << "#PATH is the path to start the recursive search for ROMs in. ~ will be expanded into the $HOME variable." << std::endl;
file << "#EXTENSION is a list of extensions to search for, separated by spaces. You MUST include the period, and it must be exact - it's case sensitive, and no wildcards." << std::endl;
file << "#COMMAND is the shell command to execute when a game is selected. %ROM% will be replaced with the (bash special-character escaped) path to the ROM." << std::endl << std::endl;
file << "#Now try your own!" << std::endl;
file << "NAME=" << std::endl;
file << "DESC=" << std::endl;
file << "PATH=" << std::endl;
file << "EXTENSION=" << std::endl;
file << "COMMAND=" << std::endl;
@ -298,7 +304,26 @@ FolderData* SystemData::getRootFolder()
return mRootFolder;
}
std::string SystemData::getGamelistPath(){
std::string filePath;
filePath = mRootFolder->getPath() + "/gamelist.xml";
if(fs::exists(filePath))
return filePath;
filePath = getenv("HOME");
filePath += "/.emulationstation/"+ getName() + "/gamelist.xml";
if(fs::exists(filePath))
return filePath;
return "";
}
bool SystemData::hasGamelist()
{
return fs::exists(mRootFolder->getPath() + "/gamelist.xml");
if(getGamelistPath().empty())
return false;
else
return true;
}

View file

@ -10,13 +10,15 @@ class GameData;
class SystemData
{
public:
SystemData(std::string name, std::string startPath, std::string extension, std::string command);
SystemData(std::string name, std::string desc, std::string startPath, std::string extension, std::string command);
~SystemData();
FolderData* getRootFolder();
std::string getName();
std::string getDesc();
std::string getStartPath();
std::string getExtension();
std::string getGamelistPath();
bool hasGamelist();
void launchGame(GameData* game);
@ -29,6 +31,7 @@ public:
static std::vector<SystemData*> sSystemVector;
private:
std::string mName;
std::string mDesc;
std::string mStartPath;
std::string mSearchExtension;
std::string mLaunchCommand;

View file

@ -102,10 +102,10 @@ GameData* createGameFromPath(std::string gameAbsPath, SystemData* system)
void parseGamelist(SystemData* system)
{
if(!system->hasGamelist())
return;
std::string xmlpath = system->getGamelistPath();
std::string xmlpath = system->getRootFolder()->getPath() + "/gamelist.xml";
if(xmlpath.empty())
return;
std::cout << "Parsing XML file \"" << xmlpath << "\"...";
@ -166,7 +166,8 @@ void parseGamelist(SystemData* system)
if(newImage[0] == '.')
{
newImage.erase(0, 1);
newImage.insert(0, system->getRootFolder()->getPath());
boost::filesystem::path pathname(xmlpath);
newImage.insert(0, pathname.parent_path().string() );
}
//if the image doesn't exist, forget it

View file

@ -91,7 +91,7 @@ void GuiGameList::onRender()
//header
if(!mTheme->getBool("hideHeader"))
Renderer::drawCenteredText(mSystem->getName(), 0, 1, 0xFF0000FF, Renderer::getDefaultFont(Renderer::LARGE));
Renderer::drawCenteredText(mSystem->getDesc(), 0, 1, 0xFF0000FF, Renderer::getDefaultFont(Renderer::LARGE));
if(mDetailed)
{
@ -204,21 +204,33 @@ void GuiGameList::updateList()
}
}
std::string GuiGameList::getThemeFile() {
std::string themePath;
themePath = getenv("HOME");
themePath += "/.emulationstation/" + mSystem->getName() + "/theme.xml";
if(boost::filesystem::exists(themePath))
return themePath;
themePath = mSystem->getStartPath() + "/theme.xml";
if(boost::filesystem::exists(themePath))
return themePath;
themePath = getenv("HOME");
themePath += "/.emulationstation/es_theme.xml";
if(boost::filesystem::exists(themePath))
return themePath;
return "";
}
void GuiGameList::updateTheme()
{
if(!mTheme)
return;
std::string defaultPath = getenv("HOME");
defaultPath += "/.emulationstation/es_theme.xml";
std::string themePath = mSystem->getStartPath() + "/theme.xml";
if(boost::filesystem::exists(themePath))
mTheme->readXML(themePath);
else if(boost::filesystem::exists(defaultPath))
mTheme->readXML(defaultPath);
else
mTheme->readXML(""); //clears any current theme
mTheme->readXML( getThemeFile() );
mList->setSelectorColor(mTheme->getColor("selector"));
mList->setSelectedTextColor(mTheme->getColor("selected"));
@ -296,7 +308,6 @@ void GuiGameList::onInit()
mTheme->init();
}
extern bool IGNOREGAMELIST; //defined in main.cpp (as a command line argument)
GuiGameList* GuiGameList::create()
{

View file

@ -37,6 +37,7 @@ private:
void updateTheme();
void updateDetailData();
void clearDetailData();
std::string getThemeFile();
SystemData* mSystem;
FolderData* mFolder;

View file

@ -151,7 +151,7 @@ void GuiTheme::readXML(std::string path)
if(path.empty())
return;
//std::cout << "Loading theme \"" << path << "\"...\n";
std::cout << "Loading theme \"" << path << "\"...\n";
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(path.c_str());