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.
`<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).
`<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
=================

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
-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).

View file

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

View file

@ -7,6 +7,9 @@ std::vector<GuiComponent*> GuiComponent::sComponentVector;
GuiComponent::GuiComponent()
{
sComponentVector.push_back(this);
mOffsetX = 0;
mOffsetY = 0;
}
GuiComponent::~GuiComponent()
@ -97,3 +100,8 @@ void GuiComponent::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(); }
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);
private:
int mOffsetX, mOffsetY;
static std::vector<GuiComponent*> sComponentVector;
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
FolderData* folder = system->getRootFolder();
unsigned int separator = 0;
unsigned int nextSeparator = 0;
size_t separator = 0;
size_t nextSeparator = 0;
unsigned int loops = 0;
while(nextSeparator != std::string::npos)
{
@ -83,7 +83,8 @@ GameData* createGameFromPath(std::string gameAbsPath, SystemData* system)
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";
break;

View file

@ -13,6 +13,9 @@ GuiGameList::GuiGameList(bool useDetail)
std::cout << "Creating GuiGameList\n";
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 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.
@ -20,7 +23,7 @@ GuiGameList::GuiGameList(bool useDetail)
{
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);
addChild(mScreenshot);
}else{
@ -28,8 +31,6 @@ GuiGameList::GuiGameList(bool useDetail)
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);
setSystemId(0);
@ -99,10 +100,9 @@ void GuiGameList::onRender()
{
GameData* game = (GameData*)mList->getSelectedObject();
//todo: cache this
std::string desc = game->getDescription();
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->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()

View file

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

View file

@ -41,7 +41,6 @@ private:
std::string mPath;
int mOffsetX, mOffsetY;
unsigned int mWidth, mHeight; //Our rendered size.
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 <iostream>
@ -9,8 +11,10 @@ GuiList<listType>::GuiList(int offsetX, int offsetY, Renderer::FontSize fontsize
mScrolling = 0;
mScrollAccumulator = 0;
mOffsetX = offsetX;
mOffsetY = offsetY;
setOffsetX(offsetX);
setOffsetY(offsetY);
mTextOffsetX = 0;
mFont = fontsize;
mSelectorColor = 0x000000;
@ -28,7 +32,7 @@ GuiList<listType>::~GuiList()
template <typename listType>
void GuiList<listType>::onRender()
{
const int cutoff = mOffsetY;
const int cutoff = getOffsetY();
const int entrySize = Renderer::getFontHeight(mFont) + 5;
int startEntry = 0;
@ -62,15 +66,15 @@ void GuiList<listType>::onRender()
{
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);
if(mDrawCentered)
Renderer::drawCenteredText(row.name, mOffsetX, y, row.color, mFont);
Renderer::drawCenteredText(row.name, getOffsetX(), y, row.color, mFont);
else
Renderer::drawText(row.name, mOffsetX, y, row.color, mFont);
Renderer::drawText(row.name, getOffsetX() + mTextOffsetX, y, row.color, mFont);
y += entrySize;
}
@ -213,3 +217,9 @@ void GuiList<listType>::setCentered(bool 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 setCentered(bool centered);
void setTextOffsetX(int textoffsetx);
private:
int mScrollDir, mScrollAccumulator;
bool mScrolling;
@ -44,7 +47,7 @@ private:
int mSelectorColor;
bool mDrawCentered;
int mOffsetX, mOffsetY;
int mTextOffsetX;
struct ListRow
{

View file

@ -5,6 +5,7 @@
#include "GuiImage.h"
#include <boost/filesystem.hpp>
#include <sstream>
#include "../Renderer.h"
int GuiTheme::getPrimaryColor() { return mListPrimaryColor; }
int GuiTheme::getSecondaryColor() { return mListSecondaryColor; }
@ -14,6 +15,11 @@ bool GuiTheme::getHeaderHidden() { return mHideHeader; }
bool GuiTheme::getDividersHidden() { return mHideDividers; }
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)
{
setDefaults();
@ -36,6 +42,10 @@ void GuiTheme::setDefaults()
mHideHeader = false;
mHideDividers = false;
mListCentered = true;
mListOffsetX = 0.5;
mListTextOffsetX = 0.005;
mGameImageOffsetY = (float)Renderer::getFontHeight(Renderer::LARGE) / Renderer::getScreenHeight();
}
void GuiTheme::deleteComponents()
@ -80,22 +90,35 @@ void GuiTheme::readXML(std::string path)
pugi::xml_node root = doc.child("theme");
//load non-component theme stuff
mListPrimaryColor = resolveColor(root.child("listPrimaryColor").text().get(), 0x0000FF);
mListSecondaryColor = resolveColor(root.child("listSecondaryColor").text().get(), 0x00FF00);
mListSelectorColor = resolveColor(root.child("listSelectorColor").text().get(), 0x000000);
mDescColor = resolveColor(root.child("descColor").text().get(), 0x0000FF);
mListPrimaryColor = resolveColor(root.child("listPrimaryColor").text().get(), mListPrimaryColor);
mListSecondaryColor = resolveColor(root.child("listSecondaryColor").text().get(), mListSecondaryColor);
mListSelectorColor = resolveColor(root.child("listSelectorColor").text().get(), mListSelectorColor);
mDescColor = resolveColor(root.child("descColor").text().get(), mDescColor);
mHideHeader = root.child("hideHeader");
mHideDividers = root.child("hideDividers");
mListCentered = !root.child("listLeftAlign");
for(pugi::xml_node data = root.child("component"); data; data = data.next_sibling("component"))
{
createElement(data, this);
}
mListOffsetX = strToFloat(root.child("listOffsetX").text().get(), mListOffsetX);
mGameImageOffsetY = strToFloat(root.child("gameImageOffsetY").text().get(), mGameImageOffsetY);
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";
}
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)
{
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);
}
float GuiTheme::strToFloat(std::string str)
float GuiTheme::strToFloat(std::string str, float defaultVal)
{
if(str.empty())
return 0;
return defaultVal;
float ret;
std::stringstream ss;

View file

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