Added the gameImageNotFound tag. See THEMES.md for details.

This commit is contained in:
Aloshi 2012-10-25 12:36:30 -05:00
parent aa6506aec1
commit 77e14423b9
6 changed files with 52 additions and 9 deletions

View file

@ -3,7 +3,7 @@ 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.
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.
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.
@ -56,6 +56,9 @@ Display tags
============
Display tags define some "meta" display attributes about your theme. Display tags must be at the root of the `<theme>` tree - for example, they can't be inside a component tag. They are not required.
**Game list attributes:**
`<listPrimaryColor>` - the hex font color to use for games on the GuiGameList.
`<listSecondaryColor>` - the hex font color to use for folders on the GuiGameList.
@ -78,15 +81,21 @@ Display tags define some "meta" display attributes about your theme. Display tag
~~`<gameImageOffsetY>` - the percentage to offset the displayed game image by. Default is the height of the header font.~~
**Game image attributes:**
`<gameImagePos>` - two values for the position of the game art, in the form of `[x] [y]`, as a percentage. Default is `$infoWidth/2 $headerHeight`.
`<gameImageDim>` - two values for the dimensions of the game art, in the form of `[width] [height]`, as a percentage of the screen. Default is `$infoWidth/2 0` (width fits within the info column). The image will only be resized if at least one axis is nonzero *and* exceeded by the image's size. You should always leave at least one axis as zero to preserve the aspect ratio.
`<gameImageOrigin>` two values for the origin of the game art, in the form of `[x] [y]`, as a percentage. Default is `0.5 0` (top-center of the image).
`<gameImageOrigin>` - two values for the origin of the game art, in the form of `[x] [y]`, as a percentage. Default is `0.5 0` (top-center of the image).
`<gameImageNotFound>` - path to the image to display if a game's image is missing. '.' and '~' are expanded.
**The Fast Select box can be themed with these tags:**
**Fast Select box attributes:**
`<fastSelectColor>` - the hex color to use for the letter display on the Fast Select box.

View file

@ -1,3 +1,6 @@
October 25
-Added gameImageNotFound tag for an image to display if a game image is not found/defined.
October 17
-Added GuiAnimation class which animates its children.
-The game image on the game list now slides/fades in and out.

View file

@ -168,6 +168,10 @@ void parseGamelist(SystemData* system)
newImage.erase(0, 1);
newImage.insert(0, system->getRootFolder()->getPath());
}
//if the image doesn't exist, forget it
if(!boost::filesystem::exists(newImage))
newImage = "";
}
game->set(newName, newDesc, newImage);

View file

@ -23,7 +23,7 @@ GuiGameList::GuiGameList(bool useDetail)
{
mList = new GuiList<FileData*>(Renderer::getScreenWidth() * sInfoWidth, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2);
mScreenshot = new GuiImage(Renderer::getScreenWidth() * sInfoWidth * 0.5, Renderer::getScreenHeight() * mTheme->getGameImageOffsetY(), "", Renderer::getScreenWidth() * sInfoWidth * 0.7, 0, false);
mScreenshot = new GuiImage(Renderer::getScreenWidth() * mTheme->getGameImageOffsetX(), Renderer::getScreenHeight() * mTheme->getGameImageOffsetY(), "", Renderer::getScreenWidth() * sInfoWidth * 0.7, 0, false);
mScreenshot->setOrigin(mTheme->getGameImageOriginX(), mTheme->getGameImageOriginY());
//addChild(mScreenshot);
@ -248,7 +248,12 @@ void GuiGameList::updateDetailData()
if(mList->getSelectedObject() && !mList->getSelectedObject()->isFolder())
{
mScreenshot->setOffset((mTheme->getGameImageOffsetX() - 0.05) * Renderer::getScreenWidth(), mTheme->getGameImageOffsetY() * Renderer::getScreenHeight());
if(((GameData*)mList->getSelectedObject())->getImagePath().empty())
mScreenshot->setImage(mTheme->getImageNotFoundPath());
else
mScreenshot->setImage(((GameData*)mList->getSelectedObject())->getImagePath());
mImageAnimation->fadeIn(15);
mImageAnimation->move((int)(0.05 * Renderer::getScreenWidth()), 0, 5);
}else{

View file

@ -34,6 +34,8 @@ float GuiTheme::getGameImageHeight() { return mGameImageHeight; }
float GuiTheme::getGameImageOriginX() { return mGameImageOriginX; }
float GuiTheme::getGameImageOriginY() { return mGameImageOriginY; }
std::string GuiTheme::getImageNotFoundPath() { return mImageNotFoundPath; }
GuiTheme::GuiTheme(std::string path)
{
setDefaults();
@ -81,6 +83,8 @@ void GuiTheme::setDefaults()
mMenuSelectSound.loadFile("");
mMenuBackSound.loadFile("");
mMenuOpenSound.loadFile("");
mImageNotFoundPath = "";
}
void GuiTheme::deleteComponents()
@ -148,7 +152,6 @@ void GuiTheme::readXML(std::string path)
mListOffsetX = strToFloat(root.child("listOffsetX").text().get(), mListOffsetX);
mListTextOffsetX = strToFloat(root.child("listTextOffsetX").text().get(), mListTextOffsetX);
//game image stuff
std::string artPos = root.child("gameImagePos").text().get();
std::string artDim = root.child("gameImageDim").text().get();
@ -166,12 +169,17 @@ void GuiTheme::readXML(std::string path)
mGameImageOriginX = resolveExp(artOriginX, mGameImageOriginX);
mGameImageOriginY = resolveExp(artOriginY, mGameImageOriginY);
mImageNotFoundPath = expandPath(root.child("gameImageNotFound").text().get());
//sounds
mMenuScrollSound.loadFile(expandPath(root.child("menuScrollSound").text().get()));
mMenuSelectSound.loadFile(expandPath(root.child("menuSelectSound").text().get()));
mMenuBackSound.loadFile(expandPath(root.child("menuBackSound").text().get()));
mMenuOpenSound.loadFile(expandPath(root.child("menuOpenSound").text().get()));
//fonts
//mListFont = resolveFont(root.child("listFont"), NULL);
//actually read the components
createComponentChildren(root, this);
}
@ -322,3 +330,14 @@ float GuiTheme::strToFloat(std::string str, float defaultVal)
ss >> ret;
return ret;
}
Font* GuiTheme::resolveFont(pugi::xml_node node, Font* def)
{
if(!node)
return def;
std::string path = expandPath(node.child("path").text().get());
int size = (int)(strToFloat(node.child("size").value()) * Renderer::getScreenHeight());
return new Font(path, size);
}

View file

@ -5,6 +5,7 @@
#include "../pugiXML/pugixml.hpp"
#include "GuiBox.h"
#include "../Sound.h"
#include "../Font.h"
//This class loads an XML-defined list of GuiComponents.
class GuiTheme : public GuiComponent
@ -41,6 +42,8 @@ public:
Sound* getMenuSelectSound();
Sound* getMenuBackSound();
Sound* getMenuOpenSound();
std::string getImageNotFoundPath();
private:
void setDefaults();
void deleteComponents();
@ -53,17 +56,17 @@ private:
unsigned int resolveColor(std::string str, unsigned int defaultColor = 0x000000FF);
void splitString(std::string str, char delim, std::string* before, std::string* after);
float strToFloat(std::string str, float defaultVal = 0.0f);
Font* resolveFont(pugi::xml_node node, Font* def);
std::vector<GuiComponent*> mComponentVector;
std::string mPath;
unsigned int mListPrimaryColor, mListSecondaryColor, mListSelectorColor, mListSelectedColor, mDescColor, mFastSelectColor;
bool mHideHeader, mHideDividers, mListCentered;
float mListOffsetX, mListTextOffsetX, mGameImageOffsetX, mGameImageOffsetY, mGameImageWidth, mGameImageHeight, mGameImageOriginX, mGameImageOriginY;
GuiBoxData mBoxData;
Sound mMenuScrollSound, mMenuSelectSound, mMenuBackSound, mMenuOpenSound;
std::string mImageNotFoundPath;
};
#endif