Font size is now dependent on resolution width.

Scrolling will now occur if the input is held (not just keyboards anymore!).
Initial XML gamelist support. If a file named gamelist.xml is present in the directory ES is run from, it will be parsed and the detailed GuiGameList will be used. Games are matched by absolute path, and a name, description, and image path can be read.
PugiXML is used for parsing XML files - its license can be found in src/pugiXML/pugiXML_license.txt.
SDL_image is used for loading screenshots with the detailed GuiGameList.
Almost all invalid bash characters should be escaped in ROM paths now - including !$^&*()[]<>?;'"\.
This commit is contained in:
Aloshi 2012-08-01 20:43:55 -05:00
parent fbfa0d436c
commit 4f99dec7c2
25 changed files with 12138 additions and 98 deletions

View file

@ -1,7 +1,7 @@
CC=g++
CFLAGS=-c -Wall
LDFLAGS=-lSDL -lSDL_ttf -lboost_system -lboost_filesystem
SRCSOURCES=main.cpp Renderer.cpp Renderer_draw.cpp GuiComponent.cpp InputManager.cpp SystemData.cpp GameData.cpp FolderData.cpp components/GuiTitleScreen.cpp components/GuiList.cpp components/GuiGameList.cpp components/GuiInputConfig.cpp
LDFLAGS=-lSDL -lSDL_ttf -lSDL_image -lboost_system -lboost_filesystem
SRCSOURCES=main.cpp Renderer.cpp Renderer_draw.cpp GuiComponent.cpp InputManager.cpp SystemData.cpp GameData.cpp FolderData.cpp XMLReader.cpp components/GuiList.cpp components/GuiGameList.cpp components/GuiInputConfig.cpp components/GuiImage.cpp pugiXML/pugixml.cpp
SOURCES=$(addprefix src/,$(SRCSOURCES))
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=emulationstation

View file

@ -1,28 +1,53 @@
#include "GameData.h"
#include <boost/filesystem.hpp>
#include <iostream>
bool GameData::isFolder() { return false; }
std::string GameData::getName() { return mName; }
std::string GameData::getPath() { return mPath; }
std::string GameData::getDescription() { return mDescription; }
std::string GameData::getImagePath() { return mImagePath; }
GameData::GameData(SystemData* system, std::string path, std::string name)
{
mSystem = system;
mPath = path;
mName = name;
mDescription = "";
mImagePath = "";
}
std::string GameData::getPath()
std::string GameData::getBashPath()
{
//a quick and dirty way to insert a backslash before most characters that would mess up a bash path
std::string path = mPath;
const char* invalidChars = " '\"\\!$^&*(){}[]?;<>";
for(unsigned int i = 0; i < path.length(); i++)
{
if(path[i] == *" " || path[i] == *"'" || path[i] == *"\"" || path[i] == *"\\")
char c;
unsigned int charNum = 0;
do {
c = invalidChars[charNum];
if(path[i] == c)
{
path.insert(i, "\\");
i++;
break;
}
charNum++;
} while(c != '\0');
}
return path;
}
void GameData::set(std::string name, std::string description, std::string imagePath)
{
if(!name.empty())
mName = name;
if(!description.empty())
mDescription = description;
if(!imagePath.empty() && boost::filesystem::exists(imagePath))
mImagePath = imagePath;
}

View file

@ -10,13 +10,24 @@ class GameData : public FileData
public:
GameData(SystemData* system, std::string path, std::string name);
void set(std::string name = "", std::string description = "", std::string imagePath = "");
std::string getName();
std::string getPath();
std::string getBashPath();
std::string getDescription();
std::string getImagePath();
bool isFolder();
private:
SystemData* mSystem;
std::string mPath;
std::string mName;
//extra data
std::string mDescription;
std::string mImagePath;
};
#endif

View file

@ -2,6 +2,24 @@
#include "Renderer.h"
#include <iostream>
std::vector<GuiComponent*> GuiComponent::sComponentVector;
GuiComponent::GuiComponent()
{
sComponentVector.push_back(this);
}
GuiComponent::~GuiComponent()
{
for(unsigned int i = 0; i < sComponentVector.size(); i++)
{
if(sComponentVector.at(i) == this)
{
sComponentVector.erase(sComponentVector.begin() + i);
}
}
}
void GuiComponent::addChild(GuiComponent* comp)
{
mChildren.push_back(comp);
@ -21,6 +39,14 @@ void GuiComponent::removeChild(GuiComponent* comp)
std::cerr << "Error - tried to remove GuiComponent child, but couldn't find it!\n";
}
void GuiComponent::processTicks(int deltaTime)
{
for(unsigned int i = 0; i < sComponentVector.size(); i++)
{
sComponentVector.at(i)->onTick(deltaTime);
}
}
void GuiComponent::render()
{
onRender();
@ -30,3 +56,4 @@ void GuiComponent::render()
mChildren.at(i)->render();
}
}

View file

@ -8,16 +8,23 @@
class GuiComponent
{
public:
GuiComponent();
virtual ~GuiComponent();
void render();
virtual void onRender() { };
virtual void onTick(int deltaTime) { };
virtual void onInput(InputManager::InputButton button, bool keyDown) { };
virtual unsigned int getLayer() { return BIT(0); };
void addChild(GuiComponent* comp);
void removeChild(GuiComponent* comp);
unsigned int getChildCount() { return mChildren.size(); }
GuiComponent* getChild(unsigned int i) { return mChildren.at(i); }
static void processTicks(int deltaTime);
private:
static std::vector<GuiComponent*> sComponentVector;
std::vector<GuiComponent*> mChildren;
};

View file

@ -34,14 +34,9 @@ void Renderer::deleteAll()
void Renderer::render()
{
for(unsigned int layer = 0; layer < LAYER_COUNT; layer++)
{
unsigned int layerBit = BIT(layer);
for(unsigned int i = 0; i < renderVector.size(); i++)
{
if(renderVector.at(i)->getLayer() & layerBit)
renderVector.at(i)->render();
}
}
}

View file

@ -26,12 +26,18 @@ namespace Renderer
unsigned int getScreenWidth();
unsigned int getScreenHeight();
enum FontSize { SMALL, MEDIUM, LARGE };
bool loadFonts();
extern bool loadedFonts;
extern TTF_Font* fonts[3]; //should be FontSize size but I don't remember the syntax
extern int fontHeight[3]; //same
int getFontHeight(FontSize size); //sometimes font size is needed before fonts have been loaded; this takes care of that
//drawing commands
void drawRect(int x, int y, int w, int h, int color);
void drawText(std::string text, int x, int y, int color);
void drawCenteredText(std::string text, int y, int color);
void loadFonts();
void drawText(std::string text, int x, int y, int color, FontSize fontsize = MEDIUM);
void drawCenteredText(std::string text, int xOffset, int y, int color, FontSize fontsize = MEDIUM);
void drawWrappedText(std::string text, int xStart, int yStart, int xLen, int color, FontSize fontsize = MEDIUM);
}
#endif

View file

@ -2,10 +2,12 @@
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include <iostream>
#include <string>
SDL_Surface* Renderer::screen;
TTF_Font* Renderer::font;
bool Renderer::loadedFonts = false;
TTF_Font* Renderer::fonts[3];
int Renderer::fontHeight[3];
void Renderer::drawRect(int x, int y, int h, int w, int color)
{
@ -13,22 +15,47 @@ void Renderer::drawRect(int x, int y, int h, int w, int color)
SDL_FillRect(Renderer::screen, &rect, color);
}
void Renderer::loadFonts()
bool Renderer::loadFonts()
{
font = TTF_OpenFont("LinLibertine_R.ttf", 36);
const char* fontPath = "LinLibertine_R.ttf";
//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};
//the three here should be the font count but, again, I don't remember the syntax
for(unsigned int i = 0; i < 3; i++)
{
TTF_Font* font = TTF_OpenFont(fontPath, sizeArray[i]);
if(!font)
{
std::cerr << "Error - could not load font!\n";
std::cerr << TTF_GetError() << "\n";
return;
return false;
}
fonts[i] = font;
TTF_SizeText(font, "HEIGHT", NULL, &fontHeight[i]); //gets the height of the string "HEIGHT" in this font (in pixels)
}
loadedFonts = true;
return true;
}
void Renderer::drawText(std::string text, int x, int y, int color)
int Renderer::getFontHeight(FontSize size)
{
if(!font)
if(!loadedFonts)
loadFonts();
return fontHeight[size];
}
void Renderer::drawText(std::string text, int x, int y, int color, FontSize fontsize)
{
if(!loadedFonts)
loadFonts();
TTF_Font* font = fonts[fontsize];
//SDL_Color is a struct of four bytes, with the first three being colors. An int is four bytes.
//So, we can just pretend the int is an SDL_Color.
SDL_Color* sdlcolor = (SDL_Color*)&color;
@ -46,16 +73,72 @@ void Renderer::drawText(std::string text, int x, int y, int color)
SDL_FreeSurface(textSurf);
}
void Renderer::drawCenteredText(std::string text, int y, int color)
void Renderer::drawCenteredText(std::string text, int xOffset, int y, int color, FontSize fontsize)
{
if(!font)
if(!loadedFonts)
loadFonts();
TTF_Font* font = fonts[fontsize];
int w, h;
TTF_SizeText(font, text.c_str(), &w, &h);
int x = (int)getScreenWidth() - w;
x *= 0.5;
drawText(text, x, y, color);
x += xOffset * 0.5;
drawText(text, x, y, color, fontsize);
}
//this could probably be optimized
void Renderer::drawWrappedText(std::string text, int xStart, int yStart, int xLen, int color, FontSize fontsize)
{
if(!loadedFonts)
loadFonts();
TTF_Font* font = fonts[fontsize];
int y = yStart;
std::string line, word, temp;
int w, h;
size_t space;
while(text.length() > 0 || !line.empty())
{
space = text.find(' ', 0);
if(space == std::string::npos)
space = text.length() - 1;
word = text.substr(0, space + 1);
text.erase(0, space + 1);
temp = line + word;
TTF_SizeText(font, temp.c_str(), &w, &h);
if(w <= xLen && text.length() == 0)
{
line = temp;
word = "";
}
if(w > xLen || text.length() == 0)
{
//render line now
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
line = word;
}else{
//there's still space, continue
line = temp;
}
}
}

View file

@ -58,7 +58,7 @@ void SystemData::launchGame(GameData* game)
std::string command = mLaunchCommand;
command = strreplace(command, "%ROM%", game->getPath());
command = strreplace(command, "%ROM%", game->getBashPath());
std::cout << " " << command << "\n";
std::cout << "=====================================================\n";

89
src/XMLReader.cpp Normal file
View file

@ -0,0 +1,89 @@
#include "XMLReader.h"
#include "SystemData.h"
#include "GameData.h"
#include "pugiXML/pugixml.hpp"
#include <boost/filesystem.hpp>
//this is obviously an incredibly inefficient way to go about searching
//some day I may change this to use hash tables or something
//but I don't think it'll matter too much with the size of most collections
GameData* searchFolderByPath(FolderData* folder, std::string const& path)
{
for(unsigned int i = 0; i < folder->getFileCount(); i++)
{
FileData* file = folder->getFile(i);
if(file->isFolder())
{
GameData* result = searchFolderByPath((FolderData*)file, path);
if(result)
return (GameData*)result;
}else{
if(file->getPath() == path)
return (GameData*)file;
}
}
return NULL;
}
void parseXMLFile(std::string xmlpath)
{
std::cout << "Parsing XML file \"" << xmlpath << "\"...\n";
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(xmlpath.c_str());
if(!result)
{
std::cerr << "Error parsing XML file \"" << xmlpath << "\"!\n";
std::cerr << " " << result.description() << "\n";
return;
}
pugi::xml_node root = doc.child("gameList");
if(!root)
{
std::cerr << "Error - could not find <gameList> node in XML document!\n";
return;
}
for(pugi::xml_node gameNode = root.child("game"); gameNode; gameNode = gameNode.next_sibling("game"))
{
pugi::xml_node pathNode = gameNode.child("path");
if(!pathNode)
{
std::cerr << "Error - <game> node contains no <path> child!\n";
return;
}
std::string path = pathNode.text().get();
GameData* game = NULL;
for(unsigned int i = 0; i < SystemData::sSystemVector.size(); i++)
{
game = searchFolderByPath(SystemData::sSystemVector.at(i)->getRootFolder(), path);
if(game != NULL)
break;
}
if(game == NULL)
{
std::cerr << "Error - game of path \"" << path << "\" was not found by the system's search. Ignoring.\n";
}else{
//actually gather the information in the XML doc, then pass it to the game's set method
std::string newName, newDesc, newImage;
if(gameNode.child("name"))
newName = gameNode.child("name").text().get();
if(gameNode.child("desc"))
newDesc = gameNode.child("desc").text().get();
if(gameNode.child("image"))
newImage = gameNode.child("image").text().get();
game->set(newName, newDesc, newImage);
}
}
std::cout << "XML parsing complete.\n";
}

9
src/XMLReader.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef _XMLREADER_H_
#define _XMLREADER_H_
#include <string>
class SystemData;
void parseXMLFile(std::string xmlpath);
#endif

View file

@ -2,11 +2,28 @@
#include "../InputManager.h"
#include <iostream>
GuiGameList::GuiGameList()
#define SCREENSHOTWIDTH 256
#define SCREENSHOTHEIGHT 256
GuiGameList::GuiGameList(bool useDetail)
{
std::cout << "Creating GuiGameList\n";
mDetailed = useDetail;
//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 a screenshto and description.
//Those with smaller displays may prefer the older view.
if(mDetailed)
{
mList = new GuiList(Renderer::getScreenWidth() * 0.4, Renderer::getFontHeight(Renderer::LARGE) + 2);
mScreenshot = new GuiImage(Renderer::getScreenWidth() * 0.2 - (SCREENSHOTWIDTH / 2), Renderer::getFontHeight(Renderer::LARGE) + 2);
addChild(mScreenshot);
}else{
mList = new GuiList(0, Renderer::getFontHeight(Renderer::LARGE) + 2);
mScreenshot = NULL;
}
mList = new GuiList();
addChild(mList);
setSystemId(0);
@ -20,6 +37,11 @@ GuiGameList::~GuiGameList()
Renderer::unregisterComponent(this);
delete mList;
if(mDetailed)
{
delete mScreenshot;
}
InputManager::unregisterComponent(this);
}
@ -52,7 +74,23 @@ void GuiGameList::onRender()
{
Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0xFFFFFF);
Renderer::drawCenteredText(mSystem->getName(), 2, 0x0000FF);
Renderer::drawCenteredText(mSystem->getName(), 0, 1, 0x0000FF, Renderer::LARGE);
if(mDetailed)
{
Renderer::drawRect(Renderer::getScreenWidth() * 0.4, Renderer::getFontHeight(Renderer::LARGE) + 2, 8, Renderer::getScreenHeight(), 0x0000FF);
//if we have selected a non-folder
if(mList->getSelectedObject() && !((FileData*)mList->getSelectedObject())->isFolder())
{
GameData* game = (GameData*)mList->getSelectedObject();
std::string desc = game->getDescription();
if(!desc.empty())
Renderer::drawWrappedText(desc, 2, Renderer::getFontHeight(Renderer::LARGE) + SCREENSHOTHEIGHT + 12, Renderer::getScreenWidth() * 0.4, 0xFF0000);
}
}
}
void GuiGameList::onInput(InputManager::InputButton button, bool keyDown)
@ -74,7 +112,6 @@ void GuiGameList::onInput(InputManager::InputButton button, bool keyDown)
}
}
//std::cout << "mFolderStack.size(): " << mFolderStack.size() << "\n";
if(button == InputManager::BUTTON2 && keyDown && mFolderStack.size())
{
mFolder = mFolderStack.top();
@ -90,10 +127,26 @@ void GuiGameList::onInput(InputManager::InputButton button, bool keyDown)
{
setSystemId(mSystemId - 1);
}
if(mDetailed)
{
if(!keyDown && (button == InputManager::UP || button == InputManager::DOWN))
{
if(mList->getSelectedObject() && !((FileData*)mList->getSelectedObject())->isFolder())
{
mScreenshot->setImage(((GameData*)mList->getSelectedObject())->getImagePath());
}else{
mScreenshot->setImage("");
}
}
}
}
void GuiGameList::updateList()
{
if(mDetailed)
mScreenshot->setImage("");
mList->clear();
for(unsigned int i = 0; i < mFolder->getFileCount(); i++)

View file

@ -3,6 +3,7 @@
#include "../GuiComponent.h"
#include "GuiList.h"
#include "GuiImage.h"
#include <string>
#include <stack>
#include "../SystemData.h"
@ -12,7 +13,7 @@
class GuiGameList : GuiComponent
{
public:
GuiGameList();
GuiGameList(bool useDetail = false);
~GuiGameList();
void updateList();
@ -26,7 +27,10 @@ private:
FolderData* mFolder;
std::stack<FolderData*> mFolderStack;
int mSystemId;
bool mDetailed;
GuiList* mList;
GuiImage* mScreenshot;
};
#endif

View file

@ -0,0 +1,44 @@
#include "GuiImage.h"
#include <SDL/SDL_image.h>
#include <iostream>
GuiImage::GuiImage(int offsetX, int offsetY, std::string path)
{
mSurface = NULL;
SDL_Rect newRect = {offsetX, offsetY, 0, 0};
mRect = newRect;
if(!path.empty())
setImage(path);
}
GuiImage::~GuiImage()
{
if(mSurface)
SDL_FreeSurface(mSurface);
}
void GuiImage::setImage(std::string path)
{
//if we already have an image, clear it
if(mSurface)
{
SDL_FreeSurface(mSurface);
mSurface = NULL;
}
if(!path.empty())
{
mSurface = IMG_Load(path.c_str());
if(mSurface == NULL)
std::cerr << "Error loading image \"" << path.c_str() << "\"\n";
}
}
void GuiImage::onRender()
{
if(mSurface)
SDL_BlitSurface(mSurface, NULL, Renderer::screen, &mRect);
}

22
src/components/GuiImage.h Normal file
View file

@ -0,0 +1,22 @@
#ifndef _GUIIMAGE_H_
#define _GUIIMAGE_H_
#include "../GuiComponent.h"
#include <SDL/SDL.h>
#include <string>
class GuiImage : public GuiComponent
{
public:
GuiImage(int offsetX = 0, int offsetY = 0, std::string path = "");
~GuiImage();
void setImage(std::string path);
void onRender();
private:
SDL_Surface* mSurface;
SDL_Rect mRect;
};
#endif

View file

@ -38,15 +38,18 @@ void GuiInputConfig::onRender()
{
Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0xFFFFFF);
Renderer::drawCenteredText("It looks like you have a joystick plugged in!", 2, 0x000000);
Renderer::drawCenteredText("POV hats (some D-Pads) are automatically mapped to directions.", 90, 0x000000);
Renderer::drawCenteredText("You can press a keyboard key to skip any input.", 130, 0x000000);
Renderer::drawCenteredText("If you want to remap later, just delete ~/.es_input.cfg.", 170, 0x000000);
int height = Renderer::getFontHeight(Renderer::MEDIUM) + 6;
Renderer::drawCenteredText("It looks like you have a joystick plugged in!", 0, 2, 0x000000);
Renderer::drawCenteredText("POV hats (some D-Pads) are automatically mapped to directions.", 0, height, 0x000000);
Renderer::drawCenteredText("You can press a keyboard key to skip any input.", 0, height * 2, 0x000000);
Renderer::drawCenteredText("If you want to remap later, just delete ~/.es_input.cfg.", 0, height * 3, 0x000000);
Renderer::drawCenteredText("Remember - you'll need to set up your emulator separately!", 0, Renderer::getScreenHeight() - height, 0x000000);
if(mDone)
Renderer::drawCenteredText("All done! Press a keyboard key to continue.", 250, 0x00BB00);
Renderer::drawCenteredText("All done! Press a keyboard key to continue.", 0, height * 5, 0x00BB00);
else
Renderer::drawCenteredText("Please press the axis/button for " + sInputs[mInputNum], 250, 0x00C000);
Renderer::drawCenteredText("Please press the axis/button for " + sInputs[mInputNum], 0, height * 5, 0x00C000);
}
void GuiInputConfig::onInput(InputManager::InputButton button, bool keyDown)
@ -71,7 +74,7 @@ void GuiInputConfig::onInput(InputManager::InputButton button, bool keyDown)
if(event->type == SDL_JOYBUTTONDOWN)
{
mButtonMap[event->jbutton.button] = (InputManager::InputButton)mInputNum;
std::cout << " Mapping " << sInputs[mInputNum] << " to button " << event->jbutton.button << "\n";
std::cout << " Mapping " << sInputs[mInputNum] << " to button " << (int)event->jbutton.button << "\n";
mInputNum++;
}
@ -90,13 +93,13 @@ void GuiInputConfig::onInput(InputManager::InputButton button, bool keyDown)
mAxisPosMap[event->jaxis.axis] = (InputManager::InputButton)mInputNum;
mInputNum++;
mLastAxis = event->jaxis.axis;
std::cout << " Mapping " << sInputs[mInputNum] << " to axis+ " << mLastAxis << "\n";
std::cout << " Mapping " << sInputs[mInputNum - 1] << " to axis+ " << mLastAxis << "\n";
}else if(event->jaxis.value < -InputManager::deadzone)
{
mAxisNegMap[event->jaxis.axis] = (InputManager::InputButton)mInputNum;
mInputNum++;
mLastAxis = event->jaxis.axis;
std::cout << " Mapping " << sInputs[mInputNum] << " to axis- " << mLastAxis << "\n";
std::cout << " Mapping " << sInputs[mInputNum - 1] << " to axis- " << mLastAxis << "\n";
}
}

View file

@ -1,9 +1,16 @@
#include "GuiList.h"
#include <iostream>
GuiList::GuiList()
GuiList::GuiList(int offsetX, int offsetY)
{
mSelection = 0;
mScrollDir = 0;
mScrolling = 0;
mScrollAccumulator = 0;
mOffsetX = offsetX;
mOffsetY = offsetY;
InputManager::registerComponent(this);
}
@ -14,8 +21,10 @@ GuiList::~GuiList()
void GuiList::onRender()
{
const int cutoff = 40;
const int entrySize = 40;
Renderer::FontSize fontsize = Renderer::MEDIUM;
const int cutoff = mOffsetY;
const int entrySize = Renderer::getFontHeight(fontsize) + 5;
int startEntry = 0;
@ -33,11 +42,10 @@ void GuiList::onRender()
}
int y = cutoff;
int color = 0xFF0000;
if(mRowVector.size() == 0)
{
Renderer::drawCenteredText("The list is empty.", y, color);
Renderer::drawCenteredText("The list is empty.", 0, y, 0xFF0000);
return;
}
@ -49,24 +57,40 @@ void GuiList::onRender()
{
if(mSelection == i)
{
Renderer::drawRect(0, y, Renderer::getScreenWidth(), 52, 0x000000);
Renderer::drawRect(mOffsetX, y, Renderer::getScreenWidth(), Renderer::getFontHeight(fontsize), 0x000000);
}
ListRow row = mRowVector.at((unsigned int)i);
Renderer::drawCenteredText(row.name, y, row.color);
y += 40;
Renderer::drawCenteredText(row.name, mOffsetX, y, row.color);
y += entrySize;
}
}
void GuiList::onInput(InputManager::InputButton button, bool keyDown)
{
if(mRowVector.size() > 0 && keyDown)
if(mRowVector.size() > 0)
{
if(keyDown)
{
if(button == InputManager::DOWN)
{
mScrollDir = 1;
mSelection++;
}
if(button == InputManager::UP)
{
mScrollDir = -1;
mSelection--;
}
}else{
if((button == InputManager::DOWN && mScrollDir > 0) || (button == InputManager::UP && mScrollDir < 0))
{
mScrollAccumulator = 0;
mScrolling = false;
mScrollDir = 0;
}
}
if(mSelection < 0)
mSelection += mRowVector.size();
@ -76,6 +100,40 @@ void GuiList::onInput(InputManager::InputButton button, bool keyDown)
}
}
void GuiList::onTick(int deltaTime)
{
if(mScrollDir != 0)
{
mScrollAccumulator += deltaTime;
if(!mScrolling)
{
if(mScrollAccumulator >= SCROLLDELAY)
{
mScrollAccumulator = SCROLLTIME;
mScrolling = true;
}
}
if(mScrolling)
{
mScrollAccumulator += deltaTime;
while(mScrollAccumulator >= SCROLLTIME)
{
mScrollAccumulator -= SCROLLTIME;
mSelection += mScrollDir;
if(mSelection < 0)
mSelection += mRowVector.size();
if(mSelection >= (int)mRowVector.size())
mSelection -= mRowVector.size();
}
}
}
}
//list management stuff
void GuiList::addObject(std::string name, void* obj, int color)
{
ListRow row = {name, obj, color};

View file

@ -7,6 +7,9 @@
#include <vector>
#include <string>
#define SCROLLDELAY 507
#define SCROLLTIME (57*6)
struct ListRow
{
std::string name;
@ -18,10 +21,11 @@ struct ListRow
class GuiList : public GuiComponent
{
public:
GuiList();
GuiList(int offsetX = 0, int offsetY = 0);
~GuiList();
void onRender();
void onTick(int deltaTime);
void onInput(InputManager::InputButton button, bool keyDown);
void addObject(std::string name, void* obj, int color = 0xFF0000);
@ -31,6 +35,10 @@ public:
void* getSelectedObject();
int getSelection();
private:
int mScrollDir, mScrollAccumulator;
bool mScrolling;
int mOffsetX, mOffsetY;
std::vector<ListRow> mRowVector;
int mSelection;
};

View file

@ -1,16 +0,0 @@
#include "GuiTitleScreen.h"
#include "../Renderer.h"
#include <iostream>
GuiTitleScreen::GuiTitleScreen()
{
Renderer::registerComponent(this);
//add children here
}
void GuiTitleScreen::onRender()
{
Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0xFFFFFF);
Renderer::drawCenteredText("EmulationStation", 5, 0x00FF00);
}

View file

@ -1,13 +0,0 @@
#ifndef _GUITITLESCREEN_H_
#define _GUITITLESCREEN_H_
#include "../GuiComponent.h"
class GuiTitleScreen : public GuiComponent
{
public:
GuiTitleScreen();
void onRender();
};
#endif

View file

@ -6,6 +6,7 @@
#include "SystemData.h"
#include <boost/filesystem.hpp>
#include "components/GuiInputConfig.h"
#include "XMLReader.h"
int main(int argc, char* argv[])
{
@ -44,7 +45,7 @@ int main(int argc, char* argv[])
}
}
Renderer::screen = SDL_SetVideoMode(width, height, 16, SDL_SWSURFACE | SDL_FULLSCREEN);
Renderer::screen = SDL_SetVideoMode(width, height, 16, SDL_SWSURFACE); //| SDL_FULLSCREEN);
if(Renderer::screen == NULL)
{
@ -57,7 +58,6 @@ int main(int argc, char* argv[])
}
SDL_ShowCursor(false);
SDL_EnableKeyRepeat(500, 100);
SDL_JoystickEventState(SDL_ENABLE);
if(!boost::filesystem::exists(SystemData::getConfigPath()))
@ -75,23 +75,33 @@ int main(int argc, char* argv[])
std::cerr << "You should probably go read that, or delete it.\n";
running = false;
}else{
bool useDetail = false;
//loaded system config, so try parsing the test XML doc
if(boost::filesystem::exists("gamelist.xml"))
{
parseXMLFile("gamelist.xml");
useDetail = true;
}
if(boost::filesystem::exists(InputManager::getConfigPath()))
{
InputManager::loadConfig();
new GuiGameList();
new GuiGameList(useDetail);
}else{
if(SDL_NumJoysticks() > 0)
{
new GuiInputConfig();
}else{
std::cout << "Note - it looks like you have no joysticks connected.\n";
new GuiGameList();
new GuiGameList(useDetail);
}
}
}
}
int lastTime = 0;
while(running)
{
SDL_Event event;
@ -104,8 +114,6 @@ int main(int argc, char* argv[])
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
case SDL_KEYDOWN:
InputManager::processEvent(&event);
break;
case SDL_KEYUP:
InputManager::processEvent(&event);
break;
@ -116,6 +124,12 @@ int main(int argc, char* argv[])
}
}
int curTime = SDL_GetTicks();
int deltaTime = curTime - lastTime;
lastTime = curTime;
GuiComponent::processTicks(deltaTime);
Renderer::render();
SDL_Flip(Renderer::screen);
}

View file

@ -0,0 +1,27 @@
pugixml 1.2 - an XML processing library
This library is distributed under the MIT License:
Copyright (c) 2006-2012 Arseny Kapoulkine
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,69 @@
/**
* pugixml parser - version 1.2
* --------------------------------------------------------
* Copyright (C) 2006-2012, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at http://pugixml.org/
*
* This library is distributed under the MIT License. See notice at the end
* of this file.
*
* This work is based on the pugxml parser, which is:
* Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
*/
#ifndef HEADER_PUGICONFIG_HPP
#define HEADER_PUGICONFIG_HPP
// Uncomment this to enable wchar_t mode
// #define PUGIXML_WCHAR_MODE
// Uncomment this to disable XPath
// #define PUGIXML_NO_XPATH
// Uncomment this to disable STL
// #define PUGIXML_NO_STL
// Uncomment this to disable exceptions
// #define PUGIXML_NO_EXCEPTIONS
// Set this to control attributes for public classes/functions, i.e.:
// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL
// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL
// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall
// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead
// Uncomment this to switch to header-only version
// #define PUGIXML_HEADER_ONLY
// #include "pugixml.cpp"
// Tune these constants to adjust memory-related behavior
// #define PUGIXML_MEMORY_PAGE_SIZE 32768
// #define PUGIXML_MEMORY_OUTPUT_STACK 10240
// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096
#endif
/**
* Copyright (c) 2006-2012 Arseny Kapoulkine
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

10250
src/pugiXML/pugixml.cpp Normal file

File diff suppressed because it is too large Load diff

1265
src/pugiXML/pugixml.hpp Normal file

File diff suppressed because it is too large Load diff