mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 23:55:38 +00:00
Bug fixes and a few minor requested changes.
See changelog.txt (August 13, part 2) for specifics.
This commit is contained in:
parent
aefefd5bff
commit
06dd1a9f60
|
@ -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
|
||||
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
|
||||
========
|
||||
|
||||
|
@ -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.
|
||||
|
||||
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
|
||||
======
|
||||
|
|
|
@ -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.
|
||||
|
||||
`<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).
|
||||
|
||||
`<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
|
||||
=================
|
||||
|
||||
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.
|
||||
|
||||
`$infoWidth` - where the center of the horizontal divider is drawn.
|
||||
|
||||
-Aloshi
|
||||
http://www.aloshi.com
|
||||
|
|
|
@ -3,6 +3,15 @@ August 13
|
|||
-I've added a THEMES.md file for documentation on theming.
|
||||
-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
|
||||
-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.
|
||||
|
|
|
@ -11,6 +11,7 @@ TTF_Font* Renderer::fonts[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)
|
||||
{
|
||||
char* c = (char*)(&color);
|
||||
|
@ -23,8 +24,6 @@ SDL_Color getSDLColor(int& color)
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Renderer::drawRect(int x, int y, int h, int w, int color)
|
||||
{
|
||||
SDL_Rect rect = {x, y, h, w};
|
||||
|
@ -43,8 +42,7 @@ bool Renderer::loadFonts()
|
|||
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.05};
|
||||
int sizeArray[] = {Renderer::getScreenWidth() * 0.015, Renderer::getScreenWidth() * 0.03, Renderer::getScreenWidth() * 0.062};
|
||||
|
||||
|
||||
//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
|
||||
//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)
|
||||
{
|
||||
if(!loadedFonts)
|
||||
|
@ -128,40 +127,53 @@ void Renderer::drawWrappedText(std::string text, int xStart, int yStart, int xLe
|
|||
|
||||
std::string line, word, temp;
|
||||
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);
|
||||
if(space == std::string::npos)
|
||||
space = text.length() - 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;
|
||||
|
||||
TTF_SizeText(font, temp.c_str(), &w, &h);
|
||||
|
||||
|
||||
if(w <= xLen && text.length() == 0)
|
||||
//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) || newline != std::string::npos)
|
||||
{
|
||||
line = temp;
|
||||
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
|
||||
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
|
||||
y += h + 4;
|
||||
|
||||
//draw the word we skipped on the next line
|
||||
//move the word we skipped to the next line
|
||||
line = word;
|
||||
}else{
|
||||
//there's still space, continue
|
||||
//there's still space, continue building the line
|
||||
line = temp;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
extern float FRAMERATE;
|
||||
#endif
|
||||
|
||||
const float GuiGameList::sInfoWidth = 0.5;
|
||||
|
||||
GuiGameList::GuiGameList(bool useDetail)
|
||||
{
|
||||
std::cout << "Creating GuiGameList\n";
|
||||
|
@ -21,10 +23,11 @@ GuiGameList::GuiGameList(bool useDetail)
|
|||
//Those with smaller displays may prefer the older view.
|
||||
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->setOrigin(0.5, 0.0);
|
||||
mScreenshot->setAlpha(true); //slower, but requested
|
||||
addChild(mScreenshot);
|
||||
}else{
|
||||
mList = new GuiList<FileData*>(0, Renderer::getFontHeight(Renderer::LARGE) + 2);
|
||||
|
@ -103,8 +106,9 @@ void GuiGameList::onRender()
|
|||
|
||||
if(mDetailed)
|
||||
{
|
||||
//divider
|
||||
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(mList->getSelectedObject() && !mList->getSelectedObject()->isFolder())
|
||||
|
@ -114,7 +118,7 @@ void GuiGameList::onRender()
|
|||
//todo: cache this
|
||||
std::string desc = game->getDescription();
|
||||
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)
|
||||
{
|
||||
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);
|
||||
mFolder = (FolderData*)file;
|
||||
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())
|
||||
{
|
||||
mFolder = mFolderStack.top();
|
||||
|
@ -204,6 +208,7 @@ void GuiGameList::updateTheme()
|
|||
mTheme->readXML(""); //clears any current theme
|
||||
|
||||
mList->setSelectorColor(mTheme->getSelectorColor());
|
||||
mList->setCentered(mTheme->getListCentered());
|
||||
}
|
||||
|
||||
void GuiGameList::updateDetailData()
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
void onPause();
|
||||
void onResume();
|
||||
|
||||
static const float sInfoWidth;
|
||||
private:
|
||||
void updateList();
|
||||
void updateTheme();
|
||||
|
|
|
@ -14,6 +14,7 @@ GuiList<listType>::GuiList(int offsetX, int offsetY, Renderer::FontSize fontsize
|
|||
|
||||
mFont = fontsize;
|
||||
mSelectorColor = 0x000000;
|
||||
mDrawCentered = true;
|
||||
|
||||
InputManager::registerComponent(this);
|
||||
}
|
||||
|
@ -65,7 +66,12 @@ void GuiList<listType>::onRender()
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -195,3 +201,9 @@ void GuiList<listType>::setSelectorColor(int selectorColor)
|
|||
{
|
||||
mSelectorColor = selectorColor;
|
||||
}
|
||||
|
||||
template<typename listType>
|
||||
void GuiList<listType>::setCentered(bool centered)
|
||||
{
|
||||
mDrawCentered = centered;
|
||||
}
|
||||
|
|
|
@ -33,12 +33,14 @@ public:
|
|||
int getSelection();
|
||||
|
||||
void setSelectorColor(int selectorColor);
|
||||
void setCentered(bool centered);
|
||||
private:
|
||||
int mScrollDir, mScrollAccumulator;
|
||||
bool mScrolling;
|
||||
|
||||
Renderer::FontSize mFont;
|
||||
int mSelectorColor;
|
||||
bool mDrawCentered;
|
||||
|
||||
int mOffsetX, mOffsetY;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "GuiTheme.h"
|
||||
#include "../MathExp.h"
|
||||
#include <iostream>
|
||||
#include "GuiGameList.h"
|
||||
#include "GuiImage.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <sstream>
|
||||
|
@ -11,15 +12,11 @@ int GuiTheme::getSelectorColor() { return mListSelectorColor; }
|
|||
int GuiTheme::getDescColor() { return mDescColor; }
|
||||
bool GuiTheme::getHeaderHidden() { return mHideHeader; }
|
||||
bool GuiTheme::getDividersHidden() { return mHideDividers; }
|
||||
bool GuiTheme::getListCentered() { return mListCentered; }
|
||||
|
||||
GuiTheme::GuiTheme(std::string path)
|
||||
{
|
||||
mListPrimaryColor = 0x0000FF;
|
||||
mListSecondaryColor = 0x00FF00;
|
||||
mListSelectorColor = 0x000000;
|
||||
mDescColor = 0x0000FF;
|
||||
mHideHeader = false;
|
||||
mHideDividers = false;
|
||||
setDefaults();
|
||||
|
||||
if(!path.empty())
|
||||
readXML(path);
|
||||
|
@ -30,6 +27,17 @@ GuiTheme::~GuiTheme()
|
|||
deleteComponents();
|
||||
}
|
||||
|
||||
void GuiTheme::setDefaults()
|
||||
{
|
||||
mListPrimaryColor = 0x0000FF;
|
||||
mListSecondaryColor = 0x00FF00;
|
||||
mListSelectorColor = 0x000000;
|
||||
mDescColor = 0x0000FF;
|
||||
mHideHeader = false;
|
||||
mHideDividers = false;
|
||||
mListCentered = true;
|
||||
}
|
||||
|
||||
void GuiTheme::deleteComponents()
|
||||
{
|
||||
for(unsigned int i = 0; i < mComponentVector.size(); i++)
|
||||
|
@ -49,6 +57,7 @@ void GuiTheme::readXML(std::string path)
|
|||
if(mPath == path)
|
||||
return;
|
||||
|
||||
setDefaults();
|
||||
deleteComponents();
|
||||
|
||||
mPath = path;
|
||||
|
@ -77,6 +86,7 @@ void GuiTheme::readXML(std::string path)
|
|||
mDescColor = resolveColor(root.child("descColor").text().get(), 0x0000FF);
|
||||
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"))
|
||||
{
|
||||
|
@ -163,6 +173,7 @@ float GuiTheme::resolveExp(std::string str)
|
|||
|
||||
//set variables
|
||||
exp.setVariable("headerHeight", Renderer::getFontHeight(Renderer::LARGE) / Renderer::getScreenHeight());
|
||||
exp.setVariable("infoWidth", GuiGameList::sInfoWidth);
|
||||
|
||||
return exp.eval();
|
||||
}
|
||||
|
@ -177,7 +188,6 @@ int GuiTheme::resolveColor(std::string str, int defaultColor)
|
|||
ss << std::hex << str;
|
||||
ss >> ret;
|
||||
|
||||
std::cout << "resolved " << str << " to " << ret << "\n";
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,9 @@ public:
|
|||
int getDescColor();
|
||||
bool getHeaderHidden();
|
||||
bool getDividersHidden();
|
||||
bool getListCentered();
|
||||
private:
|
||||
void setDefaults();
|
||||
void deleteComponents();
|
||||
GuiComponent* createElement(pugi::xml_node data, GuiComponent* parent);
|
||||
|
||||
|
@ -32,7 +34,7 @@ private:
|
|||
std::vector<GuiComponent*> mComponentVector;
|
||||
std::string mPath;
|
||||
int mListPrimaryColor, mListSecondaryColor, mListSelectorColor, mDescColor;
|
||||
bool mHideHeader, mHideDividers;
|
||||
bool mHideHeader, mHideDividers, mListCentered;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue