Bug fixes and a few minor requested changes.

See changelog.txt (August 13, part 2) for specifics.
This commit is contained in:
Aloshi 2012-08-13 20:27:39 -05:00
parent aefefd5bff
commit 06dd1a9f60
10 changed files with 87 additions and 30 deletions

View file

@ -6,6 +6,8 @@ A simple front-end for emulators made with SDL, designed for controller navigati
RetroArch for the Raspberry Pi can be found here: https://github.com/ToadKing/RetroArch-Rpi RetroArch for the Raspberry Pi can be found here: https://github.com/ToadKing/RetroArch-Rpi
I'm not associated with RetroArch in any way! I'm not associated with RetroArch in any way!
If you're lazy, a cool guy named petrockblog made a script which automatically installs RetroArch, its cores, and ES: https://github.com/petrockblog/RetroPie-Setup
Building Building
======== ========
@ -51,6 +53,7 @@ The path element should be the absolute path of the ROM. Special characters SHOU
The switch `--gamelist-only` can be used to skip automatic searching, and only display games defined in the system's gamelist.xml. The switch `--gamelist-only` can be used to skip automatic searching, and only display games defined in the system's gamelist.xml.
A cool guy named Pendor made a scraper which automatically generates a gamelist.xml for you, with boxart automatically downloaded: https://github.com/jpzapa/ES-thegamesdb-scraper
Themes Themes
====== ======

View file

@ -66,6 +66,8 @@ 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.
`<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.
@ -74,11 +76,10 @@ Display tags must be at the root of the <theme> tree - for example, they can't b
List of variables List of variables
================= =================
Variables can be used in position and dimension definitions. They can be added, subtracted, multiplied, and divided. Parenthesis are valid. Variables can be used in position and dimension definitions. They can be added, subtracted, multiplied, and divided. Parenthesis are valid. They are a percentage of the screen.
Currently, there's only one variable defined:
`$headerHeight` - height of the system name header. `$headerHeight` - height of the system name header.
`$infoWidth` - where the center of the horizontal divider is drawn.
-Aloshi -Aloshi
http://www.aloshi.com http://www.aloshi.com

View file

@ -3,6 +3,15 @@ August 13
-I've added a THEMES.md file for documentation on theming. -I've added a THEMES.md file for documentation on theming.
-A CREDITS.md file. -A CREDITS.md file.
-Fixed theme defaults not resetting when theme changes.
-The game image on the GuiGameList now maintains its alpha channel.
-Descriptions can now contain newline characters.
-Changed the size of the game info column to be 50% of the screen (previously 40%).
-Adjusted description to have a 3% left and right margins.
-Added $infoWidth variable for playing with the size of the game info column.
-Added <listLeftAlign /> tag that makes the game list left aligned instead of centered.
-Made Renderer::LARGE (header) fontsize slightly bigger
August 12 August 12
-If a theme.xml is not found in a system's directory, ES will now check for $HOME/.emulationstation/es_theme.xml. If present, it will load that. -If a theme.xml is not found in a system's directory, ES will now check for $HOME/.emulationstation/es_theme.xml. If present, it will load that.
-Themes can now be used without the detailed GuiGameList. -Themes can now be used without the detailed GuiGameList.

View file

@ -11,6 +11,7 @@ TTF_Font* Renderer::fonts[3];
int Renderer::fontHeight[3]; int Renderer::fontHeight[3];
//a utility function to convert an int (usually defined as hex) to the SDL color struct
SDL_Color getSDLColor(int& color) SDL_Color getSDLColor(int& color)
{ {
char* c = (char*)(&color); char* c = (char*)(&color);
@ -23,8 +24,6 @@ SDL_Color getSDLColor(int& color)
return ret; return ret;
} }
void Renderer::drawRect(int x, int y, int h, int w, int color) void Renderer::drawRect(int x, int y, int h, int w, int color)
{ {
SDL_Rect rect = {x, y, h, w}; SDL_Rect rect = {x, y, h, w};
@ -43,8 +42,7 @@ bool Renderer::loadFonts()
std::cerr << fontPath << " (which may not exist).\n"; std::cerr << fontPath << " (which may not exist).\n";
} }
//int sizeArray[] = {Renderer::getScreenHeight() * 0.025, Renderer::getScreenHeight() * 0.05, Renderer::getScreenHeight() * 0.075}; int sizeArray[] = {Renderer::getScreenWidth() * 0.015, Renderer::getScreenWidth() * 0.03, Renderer::getScreenWidth() * 0.062};
int sizeArray[] = {Renderer::getScreenWidth() * 0.015, Renderer::getScreenWidth() * 0.03, Renderer::getScreenWidth() * 0.05};
//the three here should be the font count but, again, I don't remember the syntax //the three here should be the font count but, again, I don't remember the syntax
@ -117,6 +115,7 @@ void Renderer::drawCenteredText(std::string text, int xOffset, int y, int color,
} }
//this could probably be optimized //this could probably be optimized
//draws text and ensures it's never longer than xLen
void Renderer::drawWrappedText(std::string text, int xStart, int yStart, int xLen, int color, FontSize fontsize) void Renderer::drawWrappedText(std::string text, int xStart, int yStart, int xLen, int color, FontSize fontsize)
{ {
if(!loadedFonts) if(!loadedFonts)
@ -128,40 +127,53 @@ void Renderer::drawWrappedText(std::string text, int xStart, int yStart, int xLe
std::string line, word, temp; std::string line, word, temp;
int w, h; int w, h;
size_t space; size_t space, newline;
while(text.length() > 0 || !line.empty()) while(text.length() > 0 || !line.empty()) //while there's text or we still have text to render
{ {
space = text.find(' ', 0); space = text.find(' ', 0);
if(space == std::string::npos) if(space == std::string::npos)
space = text.length() - 1; space = text.length() - 1;
word = text.substr(0, space + 1); word = text.substr(0, space + 1);
text.erase(0, space + 1);
//check if the next word contains a newline
newline = word.find('\n', 0);
if(newline != std::string::npos)
{
word = word.substr(0, newline);
text.erase(0, newline + 1);
}else{
text.erase(0, space + 1);
}
temp = line + word; temp = line + word;
TTF_SizeText(font, temp.c_str(), &w, &h); TTF_SizeText(font, temp.c_str(), &w, &h);
//if we're on the last word and it'll fit on the line, just add it to the line
if(w <= xLen && text.length() == 0) if((w <= xLen && text.length() == 0) || newline != std::string::npos)
{ {
line = temp; line = temp;
word = ""; word = "";
} }
if(w > xLen || text.length() == 0)
//if the next line will be too long or we're on the last of the text, render it
if(w > xLen || text.length() == 0 || newline != std::string::npos)
{ {
//render line now //render line now
drawText(line, xStart, y, color, fontsize); if(w > 0) //make sure it's not blank
drawText(line, xStart, y, color, fontsize);
//increment y by height and some extra padding for the next line //increment y by height and some extra padding for the next line
y += h + 4; y += h + 4;
//draw the word we skipped on the next line //move the word we skipped to the next line
line = word; line = word;
}else{ }else{
//there's still space, continue //there's still space, continue building the line
line = temp; line = temp;
} }

View file

@ -11,6 +11,8 @@
extern float FRAMERATE; extern float FRAMERATE;
#endif #endif
const float GuiGameList::sInfoWidth = 0.5;
GuiGameList::GuiGameList(bool useDetail) GuiGameList::GuiGameList(bool useDetail)
{ {
std::cout << "Creating GuiGameList\n"; std::cout << "Creating GuiGameList\n";
@ -21,10 +23,11 @@ GuiGameList::GuiGameList(bool useDetail)
//Those with smaller displays may prefer the older view. //Those with smaller displays may prefer the older view.
if(mDetailed) if(mDetailed)
{ {
mList = new GuiList<FileData*>(Renderer::getScreenWidth() * 0.4, Renderer::getFontHeight(Renderer::LARGE) + 2); mList = new GuiList<FileData*>(Renderer::getScreenWidth() * sInfoWidth, Renderer::getFontHeight(Renderer::LARGE) + 2);
mScreenshot = new GuiImage(Renderer::getScreenWidth() * 0.2, Renderer::getFontHeight(Renderer::LARGE) + 2, "", Renderer::getScreenWidth() * 0.3); mScreenshot = new GuiImage(Renderer::getScreenWidth() * 0.2, Renderer::getFontHeight(Renderer::LARGE) + 2, "", Renderer::getScreenWidth() * 0.3);
mScreenshot->setOrigin(0.5, 0.0); mScreenshot->setOrigin(0.5, 0.0);
mScreenshot->setAlpha(true); //slower, but requested
addChild(mScreenshot); addChild(mScreenshot);
}else{ }else{
mList = new GuiList<FileData*>(0, Renderer::getFontHeight(Renderer::LARGE) + 2); mList = new GuiList<FileData*>(0, Renderer::getFontHeight(Renderer::LARGE) + 2);
@ -103,8 +106,9 @@ void GuiGameList::onRender()
if(mDetailed) if(mDetailed)
{ {
//divider
if(!mTheme->getDividersHidden()) if(!mTheme->getDividersHidden())
Renderer::drawRect(Renderer::getScreenWidth() * 0.4, Renderer::getFontHeight(Renderer::LARGE) + 2, 8, Renderer::getScreenHeight(), 0x0000FF); Renderer::drawRect(Renderer::getScreenWidth() * sInfoWidth - 4, Renderer::getFontHeight(Renderer::LARGE) + 2, 8, Renderer::getScreenHeight(), 0x0000FF);
//if we have selected a non-folder //if we have selected a non-folder
if(mList->getSelectedObject() && !mList->getSelectedObject()->isFolder()) if(mList->getSelectedObject() && !mList->getSelectedObject()->isFolder())
@ -114,7 +118,7 @@ void GuiGameList::onRender()
//todo: cache this //todo: cache this
std::string desc = game->getDescription(); std::string desc = game->getDescription();
if(!desc.empty()) if(!desc.empty())
Renderer::drawWrappedText(desc, 2, Renderer::getFontHeight(Renderer::LARGE) + mScreenshot->getHeight() + 10, Renderer::getScreenWidth() * 0.4, mTheme->getDescColor(), Renderer::SMALL); Renderer::drawWrappedText(desc, Renderer::getScreenWidth() * 0.03, Renderer::getFontHeight(Renderer::LARGE) + mScreenshot->getHeight() + 10, Renderer::getScreenWidth() * 0.47, mTheme->getDescColor(), Renderer::SMALL);
} }
} }
} }
@ -126,9 +130,8 @@ void GuiGameList::onInput(InputManager::InputButton button, bool keyDown)
if(!keyDown) if(!keyDown)
{ {
FileData* file = mList->getSelectedObject(); FileData* file = mList->getSelectedObject();
if(file->isFolder()) if(file->isFolder()) //if you selected a folder, add this directory to the stack, and use the selected one
{ {
//set current directory to this or something
mFolderStack.push(mFolder); mFolderStack.push(mFolder);
mFolder = (FolderData*)file; mFolder = (FolderData*)file;
updateList(); updateList();
@ -138,6 +141,7 @@ void GuiGameList::onInput(InputManager::InputButton button, bool keyDown)
} }
} }
//if there's something on the directory stack, return to it
if(button == InputManager::BUTTON2 && keyDown && mFolderStack.size()) if(button == InputManager::BUTTON2 && keyDown && mFolderStack.size())
{ {
mFolder = mFolderStack.top(); mFolder = mFolderStack.top();
@ -204,6 +208,7 @@ void GuiGameList::updateTheme()
mTheme->readXML(""); //clears any current theme mTheme->readXML(""); //clears any current theme
mList->setSelectorColor(mTheme->getSelectorColor()); mList->setSelectorColor(mTheme->getSelectorColor());
mList->setCentered(mTheme->getListCentered());
} }
void GuiGameList::updateDetailData() void GuiGameList::updateDetailData()

View file

@ -24,6 +24,7 @@ public:
void onPause(); void onPause();
void onResume(); void onResume();
static const float sInfoWidth;
private: private:
void updateList(); void updateList();
void updateTheme(); void updateTheme();

View file

@ -14,6 +14,7 @@ GuiList<listType>::GuiList(int offsetX, int offsetY, Renderer::FontSize fontsize
mFont = fontsize; mFont = fontsize;
mSelectorColor = 0x000000; mSelectorColor = 0x000000;
mDrawCentered = true;
InputManager::registerComponent(this); InputManager::registerComponent(this);
} }
@ -65,7 +66,12 @@ void GuiList<listType>::onRender()
} }
ListRow row = mRowVector.at((unsigned int)i); ListRow row = mRowVector.at((unsigned int)i);
Renderer::drawCenteredText(row.name, mOffsetX, y, row.color, mFont);
if(mDrawCentered)
Renderer::drawCenteredText(row.name, mOffsetX, y, row.color, mFont);
else
Renderer::drawText(row.name, mOffsetX, y, row.color, mFont);
y += entrySize; y += entrySize;
} }
} }
@ -195,3 +201,9 @@ void GuiList<listType>::setSelectorColor(int selectorColor)
{ {
mSelectorColor = selectorColor; mSelectorColor = selectorColor;
} }
template<typename listType>
void GuiList<listType>::setCentered(bool centered)
{
mDrawCentered = centered;
}

View file

@ -33,12 +33,14 @@ public:
int getSelection(); int getSelection();
void setSelectorColor(int selectorColor); void setSelectorColor(int selectorColor);
void setCentered(bool centered);
private: private:
int mScrollDir, mScrollAccumulator; int mScrollDir, mScrollAccumulator;
bool mScrolling; bool mScrolling;
Renderer::FontSize mFont; Renderer::FontSize mFont;
int mSelectorColor; int mSelectorColor;
bool mDrawCentered;
int mOffsetX, mOffsetY; int mOffsetX, mOffsetY;

View file

@ -1,6 +1,7 @@
#include "GuiTheme.h" #include "GuiTheme.h"
#include "../MathExp.h" #include "../MathExp.h"
#include <iostream> #include <iostream>
#include "GuiGameList.h"
#include "GuiImage.h" #include "GuiImage.h"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <sstream> #include <sstream>
@ -11,15 +12,11 @@ int GuiTheme::getSelectorColor() { return mListSelectorColor; }
int GuiTheme::getDescColor() { return mDescColor; } int GuiTheme::getDescColor() { return mDescColor; }
bool GuiTheme::getHeaderHidden() { return mHideHeader; } bool GuiTheme::getHeaderHidden() { return mHideHeader; }
bool GuiTheme::getDividersHidden() { return mHideDividers; } bool GuiTheme::getDividersHidden() { return mHideDividers; }
bool GuiTheme::getListCentered() { return mListCentered; }
GuiTheme::GuiTheme(std::string path) GuiTheme::GuiTheme(std::string path)
{ {
mListPrimaryColor = 0x0000FF; setDefaults();
mListSecondaryColor = 0x00FF00;
mListSelectorColor = 0x000000;
mDescColor = 0x0000FF;
mHideHeader = false;
mHideDividers = false;
if(!path.empty()) if(!path.empty())
readXML(path); readXML(path);
@ -30,6 +27,17 @@ GuiTheme::~GuiTheme()
deleteComponents(); deleteComponents();
} }
void GuiTheme::setDefaults()
{
mListPrimaryColor = 0x0000FF;
mListSecondaryColor = 0x00FF00;
mListSelectorColor = 0x000000;
mDescColor = 0x0000FF;
mHideHeader = false;
mHideDividers = false;
mListCentered = true;
}
void GuiTheme::deleteComponents() void GuiTheme::deleteComponents()
{ {
for(unsigned int i = 0; i < mComponentVector.size(); i++) for(unsigned int i = 0; i < mComponentVector.size(); i++)
@ -49,6 +57,7 @@ void GuiTheme::readXML(std::string path)
if(mPath == path) if(mPath == path)
return; return;
setDefaults();
deleteComponents(); deleteComponents();
mPath = path; mPath = path;
@ -77,6 +86,7 @@ void GuiTheme::readXML(std::string path)
mDescColor = resolveColor(root.child("descColor").text().get(), 0x0000FF); mDescColor = resolveColor(root.child("descColor").text().get(), 0x0000FF);
mHideHeader = root.child("hideHeader"); mHideHeader = root.child("hideHeader");
mHideDividers = root.child("hideDividers"); mHideDividers = root.child("hideDividers");
mListCentered = !root.child("listLeftAlign");
for(pugi::xml_node data = root.child("component"); data; data = data.next_sibling("component")) for(pugi::xml_node data = root.child("component"); data; data = data.next_sibling("component"))
{ {
@ -163,6 +173,7 @@ float GuiTheme::resolveExp(std::string str)
//set variables //set variables
exp.setVariable("headerHeight", Renderer::getFontHeight(Renderer::LARGE) / Renderer::getScreenHeight()); exp.setVariable("headerHeight", Renderer::getFontHeight(Renderer::LARGE) / Renderer::getScreenHeight());
exp.setVariable("infoWidth", GuiGameList::sInfoWidth);
return exp.eval(); return exp.eval();
} }
@ -177,7 +188,6 @@ int GuiTheme::resolveColor(std::string str, int defaultColor)
ss << std::hex << str; ss << std::hex << str;
ss >> ret; ss >> ret;
std::cout << "resolved " << str << " to " << ret << "\n";
return ret; return ret;
} }

View file

@ -18,7 +18,9 @@ public:
int getDescColor(); int getDescColor();
bool getHeaderHidden(); bool getHeaderHidden();
bool getDividersHidden(); bool getDividersHidden();
bool getListCentered();
private: private:
void setDefaults();
void deleteComponents(); void deleteComponents();
GuiComponent* createElement(pugi::xml_node data, GuiComponent* parent); GuiComponent* createElement(pugi::xml_node data, GuiComponent* parent);
@ -32,7 +34,7 @@ private:
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; bool mHideHeader, mHideDividers, mListCentered;
}; };
#endif #endif