Added some new theming tags.

See changelog.txt (September 15) for more details.
This commit is contained in:
Aloshi 2012-09-15 16:24:33 -05:00
parent f87b6c48d7
commit 9901a07fb6
13 changed files with 107 additions and 33 deletions

View file

@ -63,12 +63,17 @@ Display tags must be at the root of the <theme> tree - for example, they can't b
`<listSelectorColor>` - the hex color to use for the "selector bar" on the GuiGameList. `<listSelectorColor>` - the hex color to use for the "selector bar" on the GuiGameList.
`<listLeftAlign />` - if present, the games list names will be left aligned to $infoWidth. `<listLeftAlign />` - if present, the games list names will be left aligned to the value of `<listOffsetX>` (default 0.5).
`<hideHeader />` - if present, the system name header won't be displayed (useful for replacing it with an image). `<hideHeader />` - if present, the system name header won't be displayed (useful for replacing it with an image).
`<hideDividers />` - if present, the divider between games on the detailed GuiGameList won't be displayed. `<hideDividers />` - if present, the divider between games on the detailed GuiGameList won't be displayed.
`<listOffsetX>` - the percentage to offset the list by. Default is 0.5 (half the screen). **Will also move the selector bar**.
`<listTextOffsetX>` - the percentage to offset the text in the list by. Default is 0.005. Only works in combination with `<listLeftAlign />`.
`<gameImageOffsetY>` - the percentage to offset the displayed game image by. Default is the height of the header font.
List of variables List of variables
================= =================

View file

@ -1,3 +1,7 @@
September 15
-Added <listOffsetX>, <listTextOffsetX>, and <gameImageOffsetY> theme tags. See THEMES.md for details.
-Fixed a bug causing gamelists to be read incorrectly.
September 14 September 14
-Joystick names are now saved during input configuration to es_input.cfg. -Joystick names are now saved during input configuration to es_input.cfg.
-When loading an input config, if JOYNAME is defined, load the first joystick with that name. If it is not present, load the first joystick (old behavior). -When loading an input config, if JOYNAME is defined, load the first joystick with that name. If it is not present, load the first joystick (old behavior).

View file

@ -170,7 +170,6 @@ void Font::drawText(std::string text, int startx, int starty, int color)
starty += mMaxGlyphHeight; starty += mMaxGlyphHeight;
//padding (another 0.5% is added to the bottom through the sizeText function) //padding (another 0.5% is added to the bottom through the sizeText function)
//starty += Renderer::getScreenHeight() * 0.01;
starty += mMaxGlyphHeight * 0.1; starty += mMaxGlyphHeight * 0.1;

View file

@ -7,6 +7,9 @@ std::vector<GuiComponent*> GuiComponent::sComponentVector;
GuiComponent::GuiComponent() GuiComponent::GuiComponent()
{ {
sComponentVector.push_back(this); sComponentVector.push_back(this);
mOffsetX = 0;
mOffsetY = 0;
} }
GuiComponent::~GuiComponent() GuiComponent::~GuiComponent()
@ -97,3 +100,8 @@ void GuiComponent::deinit()
mChildren.at(i)->deinit(); mChildren.at(i)->deinit();
} }
} }
void GuiComponent::setOffsetX(int val) { mOffsetX = val; }
void GuiComponent::setOffsetY(int val) { mOffsetY = val; }
int GuiComponent::getOffsetX() { return mOffsetX; }
int GuiComponent::getOffsetY() { return mOffsetY; }

View file

@ -44,8 +44,16 @@ public:
unsigned int getChildCount() { return mChildren.size(); } unsigned int getChildCount() { return mChildren.size(); }
GuiComponent* getChild(unsigned int i) { return mChildren.at(i); } GuiComponent* getChild(unsigned int i) { return mChildren.at(i); }
int getOffsetX();
int getOffsetY();
void setOffsetX(int val);
void setOffsetY(int val);
static void processTicks(int deltaTime); static void processTicks(int deltaTime);
private: private:
int mOffsetX, mOffsetY;
static std::vector<GuiComponent*> sComponentVector; static std::vector<GuiComponent*> sComponentVector;
std::vector<GuiComponent*> mChildren; std::vector<GuiComponent*> mChildren;
}; };

View file

@ -49,8 +49,8 @@ GameData* createGameFromPath(std::string gameAbsPath, SystemData* system)
//make our way through the directory tree finding each folder in our path or creating it if it doesn't exist //make our way through the directory tree finding each folder in our path or creating it if it doesn't exist
FolderData* folder = system->getRootFolder(); FolderData* folder = system->getRootFolder();
unsigned int separator = 0; size_t separator = 0;
unsigned int nextSeparator = 0; size_t nextSeparator = 0;
unsigned int loops = 0; unsigned int loops = 0;
while(nextSeparator != std::string::npos) while(nextSeparator != std::string::npos)
{ {
@ -83,7 +83,8 @@ GameData* createGameFromPath(std::string gameAbsPath, SystemData* system)
folder = newFolder; folder = newFolder;
} }
if(loops > gamePath.length()) //if for some reason this function is broken, break out of this while instead of freezing
if(loops > gamePath.length() * 2)
{ {
std::cerr << "breaking out of loop for path \"" << gamePath << "\"\n"; std::cerr << "breaking out of loop for path \"" << gamePath << "\"\n";
break; break;

View file

@ -13,6 +13,9 @@ GuiGameList::GuiGameList(bool useDetail)
std::cout << "Creating GuiGameList\n"; std::cout << "Creating GuiGameList\n";
mDetailed = useDetail; mDetailed = useDetail;
mTheme = new GuiTheme(); //not a child because it's rendered manually by GuiGameList::onRender (to make sure it's rendered first)
//The GuiGameList can use the older, simple game list if so desired. //The GuiGameList can use the older, simple game list if so desired.
//The old view only shows a list in the center of the screen; the new view can display an image and description. //The old view only shows a list in the center of the screen; the new view can display an image and description.
//Those with smaller displays may prefer the older view. //Those with smaller displays may prefer the older view.
@ -20,7 +23,7 @@ GuiGameList::GuiGameList(bool useDetail)
{ {
mList = new GuiList<FileData*>(Renderer::getScreenWidth() * sInfoWidth, Renderer::getFontHeight(Renderer::LARGE) + 2); mList = new GuiList<FileData*>(Renderer::getScreenWidth() * sInfoWidth, Renderer::getFontHeight(Renderer::LARGE) + 2);
mScreenshot = new GuiImage(Renderer::getScreenWidth() * sInfoWidth * 0.5, Renderer::getFontHeight(Renderer::LARGE) + 2, "", Renderer::getScreenWidth() * sInfoWidth * 0.7); mScreenshot = new GuiImage(Renderer::getScreenWidth() * sInfoWidth * 0.5, Renderer::getScreenHeight() * mTheme->getGameImageOffsetY(), "", Renderer::getScreenWidth() * sInfoWidth * 0.7);
mScreenshot->setOrigin(0.5, 0.0); mScreenshot->setOrigin(0.5, 0.0);
addChild(mScreenshot); addChild(mScreenshot);
}else{ }else{
@ -28,8 +31,6 @@ GuiGameList::GuiGameList(bool useDetail)
mScreenshot = NULL; mScreenshot = NULL;
} }
mTheme = new GuiTheme(); //not a child because it's rendered manually by GuiGameList::onRender (to make sure it's rendered first)
addChild(mList); addChild(mList);
setSystemId(0); setSystemId(0);
@ -99,10 +100,9 @@ void GuiGameList::onRender()
{ {
GameData* game = (GameData*)mList->getSelectedObject(); GameData* game = (GameData*)mList->getSelectedObject();
//todo: cache this
std::string desc = game->getDescription(); std::string desc = game->getDescription();
if(!desc.empty()) if(!desc.empty())
Renderer::drawWrappedText(desc, Renderer::getScreenWidth() * 0.03, Renderer::getFontHeight(Renderer::LARGE) + mScreenshot->getHeight() + 10, Renderer::getScreenWidth() * (sInfoWidth - 0.03), mTheme->getDescColor(), Renderer::SMALL); Renderer::drawWrappedText(desc, Renderer::getScreenWidth() * 0.03, mScreenshot->getOffsetY() + mScreenshot->getHeight() + 8, Renderer::getScreenWidth() * (sInfoWidth - 0.03), mTheme->getDescColor(), Renderer::SMALL);
} }
} }
} }
@ -200,6 +200,13 @@ void GuiGameList::updateTheme()
mList->setSelectorColor(mTheme->getSelectorColor()); mList->setSelectorColor(mTheme->getSelectorColor());
mList->setCentered(mTheme->getListCentered()); mList->setCentered(mTheme->getListCentered());
if(mDetailed)
{
mList->setOffsetX(mTheme->getListOffsetX() * Renderer::getScreenWidth());
mList->setTextOffsetX(mTheme->getListTextOffsetX() * Renderer::getScreenWidth());
mScreenshot->setOffsetY(mTheme->getGameImageOffsetY() * Renderer::getScreenHeight());
}
} }
void GuiGameList::updateDetailData() void GuiGameList::updateDetailData()

View file

@ -10,8 +10,8 @@ GuiImage::GuiImage(int offsetX, int offsetY, std::string path, unsigned int resi
{ {
mTextureID = 0; mTextureID = 0;
mOffsetX = offsetX; setOffsetX(offsetX);
mOffsetY = offsetY; setOffsetY(offsetY);
//default origin is the center of image //default origin is the center of image
mOriginX = 0.5; mOriginX = 0.5;
@ -245,7 +245,7 @@ void GuiImage::onRender()
{ {
for(unsigned int y = 0; y < yCount; y++) for(unsigned int y = 0; y < yCount; y++)
{ {
buildImageArray(mOffsetX + x*mWidth, mOffsetY + y*mHeight, points + (12 * (x*yCount + y)), texs + (12 * (x*yCount + y))); buildImageArray(getOffsetX() + x*mWidth, getOffsetY() + y*mHeight, points + (12 * (x*yCount + y)), texs + (12 * (x*yCount + y)));
} }
} }
drawImageArray(points, texs, xCount * yCount * 6); drawImageArray(points, texs, xCount * yCount * 6);
@ -253,7 +253,7 @@ void GuiImage::onRender()
delete[] texs; delete[] texs;
}else{ }else{
GLfloat points[12], texs[12]; GLfloat points[12], texs[12];
buildImageArray(mOffsetX, mOffsetY, points, texs); buildImageArray(getOffsetX(), getOffsetY(), points, texs);
drawImageArray(points, texs, 6); drawImageArray(points, texs, 6);
} }
} }

View file

@ -41,7 +41,6 @@ private:
std::string mPath; std::string mPath;
int mOffsetX, mOffsetY;
unsigned int mWidth, mHeight; //Our rendered size. unsigned int mWidth, mHeight; //Our rendered size.
GLuint mTextureID; GLuint mTextureID;

View file

@ -1,3 +1,5 @@
//This is *actually* part of the GuiList header and not meant to be compiled.
#include "GuiList.h" #include "GuiList.h"
#include <iostream> #include <iostream>
@ -9,8 +11,10 @@ GuiList<listType>::GuiList(int offsetX, int offsetY, Renderer::FontSize fontsize
mScrolling = 0; mScrolling = 0;
mScrollAccumulator = 0; mScrollAccumulator = 0;
mOffsetX = offsetX; setOffsetX(offsetX);
mOffsetY = offsetY; setOffsetY(offsetY);
mTextOffsetX = 0;
mFont = fontsize; mFont = fontsize;
mSelectorColor = 0x000000; mSelectorColor = 0x000000;
@ -28,7 +32,7 @@ GuiList<listType>::~GuiList()
template <typename listType> template <typename listType>
void GuiList<listType>::onRender() void GuiList<listType>::onRender()
{ {
const int cutoff = mOffsetY; const int cutoff = getOffsetY();
const int entrySize = Renderer::getFontHeight(mFont) + 5; const int entrySize = Renderer::getFontHeight(mFont) + 5;
int startEntry = 0; int startEntry = 0;
@ -62,15 +66,15 @@ void GuiList<listType>::onRender()
{ {
if(mSelection == i) if(mSelection == i)
{ {
Renderer::drawRect(mOffsetX, y, Renderer::getScreenWidth(), Renderer::getFontHeight(mFont), mSelectorColor); Renderer::drawRect(getOffsetX(), y, Renderer::getScreenWidth(), Renderer::getFontHeight(mFont), mSelectorColor);
} }
ListRow row = mRowVector.at((unsigned int)i); ListRow row = mRowVector.at((unsigned int)i);
if(mDrawCentered) if(mDrawCentered)
Renderer::drawCenteredText(row.name, mOffsetX, y, row.color, mFont); Renderer::drawCenteredText(row.name, getOffsetX(), y, row.color, mFont);
else else
Renderer::drawText(row.name, mOffsetX, y, row.color, mFont); Renderer::drawText(row.name, getOffsetX() + mTextOffsetX, y, row.color, mFont);
y += entrySize; y += entrySize;
} }
@ -213,3 +217,9 @@ void GuiList<listType>::setCentered(bool centered)
{ {
mDrawCentered = centered; mDrawCentered = centered;
} }
template<typename listType>
void GuiList<listType>::setTextOffsetX(int textoffsetx)
{
mTextOffsetX = textoffsetx;
}

View file

@ -36,6 +36,9 @@ public:
void setSelectorColor(int selectorColor); void setSelectorColor(int selectorColor);
void setCentered(bool centered); void setCentered(bool centered);
void setTextOffsetX(int textoffsetx);
private: private:
int mScrollDir, mScrollAccumulator; int mScrollDir, mScrollAccumulator;
bool mScrolling; bool mScrolling;
@ -44,7 +47,7 @@ private:
int mSelectorColor; int mSelectorColor;
bool mDrawCentered; bool mDrawCentered;
int mOffsetX, mOffsetY; int mTextOffsetX;
struct ListRow struct ListRow
{ {

View file

@ -5,6 +5,7 @@
#include "GuiImage.h" #include "GuiImage.h"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <sstream> #include <sstream>
#include "../Renderer.h"
int GuiTheme::getPrimaryColor() { return mListPrimaryColor; } int GuiTheme::getPrimaryColor() { return mListPrimaryColor; }
int GuiTheme::getSecondaryColor() { return mListSecondaryColor; } int GuiTheme::getSecondaryColor() { return mListSecondaryColor; }
@ -14,6 +15,11 @@ bool GuiTheme::getHeaderHidden() { return mHideHeader; }
bool GuiTheme::getDividersHidden() { return mHideDividers; } bool GuiTheme::getDividersHidden() { return mHideDividers; }
bool GuiTheme::getListCentered() { return mListCentered; } bool GuiTheme::getListCentered() { return mListCentered; }
//not yet implemented
float GuiTheme::getListOffsetX() { return mListOffsetX; }
float GuiTheme::getGameImageOffsetY() { return mGameImageOffsetY; }
float GuiTheme::getListTextOffsetX() { return mListTextOffsetX; }
GuiTheme::GuiTheme(std::string path) GuiTheme::GuiTheme(std::string path)
{ {
setDefaults(); setDefaults();
@ -36,6 +42,10 @@ void GuiTheme::setDefaults()
mHideHeader = false; mHideHeader = false;
mHideDividers = false; mHideDividers = false;
mListCentered = true; mListCentered = true;
mListOffsetX = 0.5;
mListTextOffsetX = 0.005;
mGameImageOffsetY = (float)Renderer::getFontHeight(Renderer::LARGE) / Renderer::getScreenHeight();
} }
void GuiTheme::deleteComponents() void GuiTheme::deleteComponents()
@ -80,22 +90,35 @@ void GuiTheme::readXML(std::string path)
pugi::xml_node root = doc.child("theme"); pugi::xml_node root = doc.child("theme");
//load non-component theme stuff //load non-component theme stuff
mListPrimaryColor = resolveColor(root.child("listPrimaryColor").text().get(), 0x0000FF); mListPrimaryColor = resolveColor(root.child("listPrimaryColor").text().get(), mListPrimaryColor);
mListSecondaryColor = resolveColor(root.child("listSecondaryColor").text().get(), 0x00FF00); mListSecondaryColor = resolveColor(root.child("listSecondaryColor").text().get(), mListSecondaryColor);
mListSelectorColor = resolveColor(root.child("listSelectorColor").text().get(), 0x000000); mListSelectorColor = resolveColor(root.child("listSelectorColor").text().get(), mListSelectorColor);
mDescColor = resolveColor(root.child("descColor").text().get(), 0x0000FF); mDescColor = resolveColor(root.child("descColor").text().get(), mDescColor);
mHideHeader = root.child("hideHeader"); mHideHeader = root.child("hideHeader");
mHideDividers = root.child("hideDividers"); mHideDividers = root.child("hideDividers");
mListCentered = !root.child("listLeftAlign"); mListCentered = !root.child("listLeftAlign");
for(pugi::xml_node data = root.child("component"); data; data = data.next_sibling("component")) mListOffsetX = strToFloat(root.child("listOffsetX").text().get(), mListOffsetX);
{ mGameImageOffsetY = strToFloat(root.child("gameImageOffsetY").text().get(), mGameImageOffsetY);
createElement(data, this); mListTextOffsetX = strToFloat(root.child("listTextOffsetX").text().get(), mListTextOffsetX);
}
//recursively create children for all <components> with proper parenting
createComponentChildren(root, this);
std::cout << "Finished parsing theme.\n"; std::cout << "Finished parsing theme.\n";
} }
void GuiTheme::createComponentChildren(pugi::xml_node node, GuiComponent* parent)
{
for(pugi::xml_node data = node.child("component"); data; data = data.next_sibling("component"))
{
GuiComponent* nextComp = createElement(data, parent);
if(nextComp)
createComponentChildren(data, nextComp);
}
}
GuiComponent* GuiTheme::createElement(pugi::xml_node data, GuiComponent* parent) GuiComponent* GuiTheme::createElement(pugi::xml_node data, GuiComponent* parent)
{ {
std::string type = data.child("type").text().get(); std::string type = data.child("type").text().get();
@ -197,10 +220,10 @@ void GuiTheme::splitString(std::string str, char delim, std::string* before, std
*after = str.substr(split + 1, str.length() - split - 1); *after = str.substr(split + 1, str.length() - split - 1);
} }
float GuiTheme::strToFloat(std::string str) float GuiTheme::strToFloat(std::string str, float defaultVal)
{ {
if(str.empty()) if(str.empty())
return 0; return defaultVal;
float ret; float ret;
std::stringstream ss; std::stringstream ss;

View file

@ -20,9 +20,14 @@ public:
bool getHeaderHidden(); bool getHeaderHidden();
bool getDividersHidden(); bool getDividersHidden();
bool getListCentered(); bool getListCentered();
float getListOffsetX();
float getListTextOffsetX();
float getGameImageOffsetY();
private: private:
void setDefaults(); void setDefaults();
void deleteComponents(); void deleteComponents();
void createComponentChildren(pugi::xml_node node, GuiComponent* parent);
GuiComponent* createElement(pugi::xml_node data, GuiComponent* parent); GuiComponent* createElement(pugi::xml_node data, GuiComponent* parent);
//utility functions //utility functions
@ -30,12 +35,14 @@ private:
float resolveExp(std::string str); float resolveExp(std::string str);
int resolveColor(std::string str, int defaultColor = 0x000000); int resolveColor(std::string str, int defaultColor = 0x000000);
void splitString(std::string str, char delim, std::string* before, std::string* after); void splitString(std::string str, char delim, std::string* before, std::string* after);
float strToFloat(std::string str); float strToFloat(std::string str, float defaultVal = 0.0f);
std::vector<GuiComponent*> mComponentVector; std::vector<GuiComponent*> mComponentVector;
std::string mPath; std::string mPath;
int mListPrimaryColor, mListSecondaryColor, mListSelectorColor, mDescColor; int mListPrimaryColor, mListSecondaryColor, mListSelectorColor, mDescColor;
bool mHideHeader, mHideDividers, mListCentered; bool mHideHeader, mHideDividers, mListCentered;
float mListOffsetX, mGameImageOffsetY, mListTextOffsetX;
}; };
#endif #endif