From 77e14423b9210287298a49af0653010027931777 Mon Sep 17 00:00:00 2001 From: Aloshi Date: Thu, 25 Oct 2012 12:36:30 -0500 Subject: [PATCH] Added the gameImageNotFound tag. See THEMES.md for details. --- THEMES.md | 15 ++++++++++++--- changelog.txt | 3 +++ src/XMLReader.cpp | 4 ++++ src/components/GuiGameList.cpp | 9 +++++++-- src/components/GuiTheme.cpp | 21 ++++++++++++++++++++- src/components/GuiTheme.h | 9 ++++++--- 6 files changed, 52 insertions(+), 9 deletions(-) diff --git a/THEMES.md b/THEMES.md index f312e3cbb..4d79aa620 100644 --- a/THEMES.md +++ b/THEMES.md @@ -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 `` tree - for example, they can't be inside a component tag. They are not required. + +**Game list attributes:** + `` - the hex font color to use for games on the GuiGameList. `` - 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 ~~`` - the percentage to offset the displayed game image by. Default is the height of the header font.~~ + + +**Game image attributes:** + `` - two values for the position of the game art, in the form of `[x] [y]`, as a percentage. Default is `$infoWidth/2 $headerHeight`. `` - 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. -`` 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). +`` - 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). + +`` - 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:** `` - the hex color to use for the letter display on the Fast Select box. diff --git a/changelog.txt b/changelog.txt index 53dd6ac62..c0f1af6a3 100644 --- a/changelog.txt +++ b/changelog.txt @@ -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. diff --git a/src/XMLReader.cpp b/src/XMLReader.cpp index 3132a7319..67ba20c11 100644 --- a/src/XMLReader.cpp +++ b/src/XMLReader.cpp @@ -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); diff --git a/src/components/GuiGameList.cpp b/src/components/GuiGameList.cpp index c011e80cd..f47f5d684 100644 --- a/src/components/GuiGameList.cpp +++ b/src/components/GuiGameList.cpp @@ -23,7 +23,7 @@ GuiGameList::GuiGameList(bool useDetail) { mList = new GuiList(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()); - mScreenshot->setImage(((GameData*)mList->getSelectedObject())->getImagePath()); + + 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{ diff --git a/src/components/GuiTheme.cpp b/src/components/GuiTheme.cpp index f51709c5d..aa7d9fd6e 100644 --- a/src/components/GuiTheme.cpp +++ b/src/components/GuiTheme.cpp @@ -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); +} diff --git a/src/components/GuiTheme.h b/src/components/GuiTheme.h index 9d2036bf2..fd7538875 100644 --- a/src/components/GuiTheme.h +++ b/src/components/GuiTheme.h @@ -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 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