mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-02-16 20:15:38 +00:00
Fixed tiling being super slow.
See changelog.txt (September 7) for a list of everything.
This commit is contained in:
parent
b2d800efb9
commit
80740a2bd0
|
@ -33,7 +33,7 @@ All themes must be enclosed in a `<theme>` tag.
|
||||||
|
|
||||||
Components
|
Components
|
||||||
==========
|
==========
|
||||||
A theme is made up of components, which have various types. At the moment, the only type is `image`. Components can be nested for your own organization. Components are rendered in the order they are defined - that means you'll want to define the background first, a header image second, etc.
|
A theme is made up of components, which have various types. At the moment, the only type is `image`. Components are rendered in the order they are defined - that means you'll want to define the background first, a header image second, etc.
|
||||||
|
|
||||||
|
|
||||||
The "image" component
|
The "image" component
|
||||||
|
@ -48,7 +48,7 @@ Used to display an image.
|
||||||
|
|
||||||
`<origin>` - the point on the image that `<pos>` defines, as an image percentage. "0.5 0.5", the center of the image, by default.
|
`<origin>` - the point on the image that `<pos>` defines, as an image percentage. "0.5 0.5", the center of the image, by default.
|
||||||
|
|
||||||
`<tiled />` - if present, the image is tiled instead of resized. Tiling isn't exact at the moment, but good enough for backgrounds.
|
`<tiled />` - if present, the image is tiled instead of resized. A smaller image tiled many times is **slower** than a larger immage tiled few times.
|
||||||
|
|
||||||
|
|
||||||
Display tags
|
Display tags
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
September 7
|
||||||
|
-Tiling is now much faster.
|
||||||
|
-Added --draw-framerate and --help/-h command-line parameters.
|
||||||
|
-Fixed themes not properly re-initializing.
|
||||||
|
-Commented most headers. Things should be kind of understandable now.
|
||||||
|
-Finally increased scrolling speed.
|
||||||
|
|
||||||
September 3
|
September 3
|
||||||
-Everything is now rendered with OpenGL, leading to a (roughly) 600%+ speedup!
|
-Everything is now rendered with OpenGL, leading to a (roughly) 600%+ speedup!
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
//This is a really basic class that the GameData and FolderData subclass from.
|
||||||
|
//This lets us keep everything in one vector and not have to differentiate between files and folders when we just want to check the name, etc.
|
||||||
class FileData
|
class FileData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
class SystemData;
|
class SystemData;
|
||||||
|
|
||||||
|
//This class lets us hold a vector of FileDatas within under a common name.
|
||||||
class FolderData : public FileData
|
class FolderData : public FileData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
15
src/Font.h
15
src/Font.h
|
@ -1,4 +1,3 @@
|
||||||
//A truetype font loader and renderer, using FreeType 2 and OpenGL.
|
|
||||||
|
|
||||||
#ifndef _FONT_H_
|
#ifndef _FONT_H_
|
||||||
#define _FONT_H_
|
#define _FONT_H_
|
||||||
|
@ -8,6 +7,7 @@
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
|
//A TrueType Font renderer that uses FreeType and OpenGL. initLibrary() MUST be called before using it.
|
||||||
class Font
|
class Font
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -18,6 +18,7 @@ public:
|
||||||
|
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
|
|
||||||
|
//contains sizing information for every glyph.
|
||||||
struct charPosData {
|
struct charPosData {
|
||||||
int texX;
|
int texX;
|
||||||
int texY;
|
int texY;
|
||||||
|
@ -34,18 +35,18 @@ public:
|
||||||
|
|
||||||
GLuint textureID;
|
GLuint textureID;
|
||||||
|
|
||||||
void drawText(std::string text, int startx, int starty, int color);
|
void drawText(std::string text, int startx, int starty, int color); //Render some text using this font.
|
||||||
void sizeText(std::string text, int* w, int* h);
|
void sizeText(std::string text, int* w, int* h); //Sets the width and height of a given string to given pointers. Skipped if pointer is NULL.
|
||||||
private:
|
|
||||||
|
|
||||||
|
private:
|
||||||
static int getDpiX();
|
static int getDpiX();
|
||||||
static int getDpiY();
|
static int getDpiY();
|
||||||
static FT_Library sLibrary;
|
static FT_Library sLibrary;
|
||||||
|
|
||||||
void buildAtlas();
|
void buildAtlas(); //Builds a "texture atlas," one big OpenGL texture with glyphs 32 to 128.
|
||||||
|
|
||||||
int textureWidth;
|
int textureWidth; //OpenGL texture width
|
||||||
int textureHeight;
|
int textureHeight; //OpenGL texture height
|
||||||
int mMaxGlyphHeight;
|
int mMaxGlyphHeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "FileData.h"
|
#include "FileData.h"
|
||||||
#include "SystemData.h"
|
#include "SystemData.h"
|
||||||
|
|
||||||
|
//This class holds information about a game: at the least, its name, system, and path. Additional information is optional and read by other classes.
|
||||||
class GameData : public FileData
|
class GameData : public FileData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -5,6 +5,17 @@
|
||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
#include "InputManager.h"
|
#include "InputManager.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
The GuiComponent class is what everything that is rendered, updated by time (ticking), or takes input is subclassed from.
|
||||||
|
GuiComponents have a list of child GuiComponents. Rendering, ticking, pausing/resuming, init/deinit, are all automatically sent to children.
|
||||||
|
You can rely on the parent getting called first - this way, you can control what order components are rendered in.
|
||||||
|
You can also manually call the render/pause/resume/init/deinit methods if you so desire (e.g. want a child to render *before* its parent).
|
||||||
|
|
||||||
|
To make a GuiComponent render/take input, you must register with the Renderer or InputManager respectively (Renderer::registerComponent(comp) or InputManager::registerComponent(comp)).
|
||||||
|
All components are automatically ticked every frame, just add an onTick(int deltaTime) method.
|
||||||
|
onInput calls arrive before onRender calls.
|
||||||
|
*/
|
||||||
|
|
||||||
class GuiComponent
|
class GuiComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
class GuiComponent;
|
class GuiComponent;
|
||||||
|
|
||||||
|
//The InputManager takes native system input and abstracts it into InputButtons.
|
||||||
|
//GuiComponents can be registered to receive onInput() events.
|
||||||
namespace InputManager {
|
namespace InputManager {
|
||||||
void registerComponent(GuiComponent* comp);
|
void registerComponent(GuiComponent* comp);
|
||||||
void unregisterComponent(GuiComponent* comp);
|
void unregisterComponent(GuiComponent* comp);
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
//A reusable class that evaluates simple mathematical expressions.
|
||||||
|
//Includes variable support - just use setVariable(name, value), and any instance of $name will be replaced with value.
|
||||||
class MathExp {
|
class MathExp {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
class GuiComponent;
|
class GuiComponent;
|
||||||
|
|
||||||
|
//The Renderer provides several higher-level functions for drawing (rectangles, text, etc.).
|
||||||
|
//Defined in multiple files - Renderer.cpp has the GuiComponent stuff, Renderer_draw_* includes renderer-specific drawing implementations, and Renderer_init_* includes renderer-specific init/deinit.
|
||||||
namespace Renderer
|
namespace Renderer
|
||||||
{
|
{
|
||||||
void registerComponent(GuiComponent* comp);
|
void registerComponent(GuiComponent* comp);
|
||||||
|
|
|
@ -191,7 +191,7 @@ void SystemData::loadConfig()
|
||||||
SystemData* newSystem = new SystemData(sysName, sysPath, sysExtension, sysCommand);
|
SystemData* newSystem = new SystemData(sysName, sysPath, sysExtension, sysCommand);
|
||||||
if(newSystem->getRootFolder()->getFileCount() == 0)
|
if(newSystem->getRootFolder()->getFileCount() == 0)
|
||||||
{
|
{
|
||||||
std::cerr << "Error - system \"" << sysName << "\" has no games! Deleting.\n";
|
std::cout << "System \"" << sysName << "\" has no games! Deleting.\n";
|
||||||
delete newSystem;
|
delete newSystem;
|
||||||
}else{
|
}else{
|
||||||
sSystemVector.push_back(newSystem);
|
sSystemVector.push_back(newSystem);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
class SystemData;
|
class SystemData;
|
||||||
|
|
||||||
|
//Loads gamelist.xml data into a SystemData.
|
||||||
void parseGamelist(SystemData* system);
|
void parseGamelist(SystemData* system);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,10 +4,6 @@
|
||||||
#include "GuiMenu.h"
|
#include "GuiMenu.h"
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
#ifdef DRAWFRAMERATE
|
|
||||||
#include <sstream>
|
|
||||||
extern float FRAMERATE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const float GuiGameList::sInfoWidth = 0.5;
|
const float GuiGameList::sInfoWidth = 0.5;
|
||||||
|
|
||||||
|
@ -85,19 +81,9 @@ void GuiGameList::setSystemId(int id)
|
||||||
|
|
||||||
void GuiGameList::onRender()
|
void GuiGameList::onRender()
|
||||||
{
|
{
|
||||||
//Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0xFFFFFF);
|
|
||||||
|
|
||||||
if(mTheme)
|
if(mTheme)
|
||||||
mTheme->render();
|
mTheme->render();
|
||||||
|
|
||||||
#ifdef DRAWFRAMERATE
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << FRAMERATE;
|
|
||||||
std::string fps;
|
|
||||||
ss >> fps;
|
|
||||||
Renderer::drawText(fps, 100, 50, 0x00FF00);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//header
|
//header
|
||||||
if(!mTheme->getHeaderHidden())
|
if(!mTheme->getHeaderHidden())
|
||||||
Renderer::drawCenteredText(mSystem->getName(), 0, 1, 0xFF0000, Renderer::LARGE);
|
Renderer::drawCenteredText(mSystem->getName(), 0, 1, 0xFF0000, Renderer::LARGE);
|
||||||
|
@ -148,13 +134,17 @@ void GuiGameList::onInput(InputManager::InputButton button, bool keyDown)
|
||||||
updateDetailData();
|
updateDetailData();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(button == InputManager::RIGHT && keyDown)
|
//only allow switching systems if more than one exists (otherwise it'll reset your position when you switch and it's annoying)
|
||||||
|
if(SystemData::sSystemVector.size() > 1)
|
||||||
{
|
{
|
||||||
setSystemId(mSystemId + 1);
|
if(button == InputManager::RIGHT && keyDown)
|
||||||
}
|
{
|
||||||
if(button == InputManager::LEFT && keyDown)
|
setSystemId(mSystemId + 1);
|
||||||
{
|
}
|
||||||
setSystemId(mSystemId - 1);
|
if(button == InputManager::LEFT && keyDown)
|
||||||
|
{
|
||||||
|
setSystemId(mSystemId - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(button == InputManager::MENU && keyDown)
|
if(button == InputManager::MENU && keyDown)
|
||||||
|
@ -236,6 +226,8 @@ void GuiGameList::onResume()
|
||||||
InputManager::registerComponent(this);
|
InputManager::registerComponent(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//called when the renderer shuts down/returns
|
||||||
|
//we have to manually call init/deinit on mTheme because it is not our child
|
||||||
void GuiGameList::onDeinit()
|
void GuiGameList::onDeinit()
|
||||||
{
|
{
|
||||||
mTheme->deinit();
|
mTheme->deinit();
|
||||||
|
@ -243,5 +235,5 @@ void GuiGameList::onDeinit()
|
||||||
|
|
||||||
void GuiGameList::onInit()
|
void GuiGameList::onInit()
|
||||||
{
|
{
|
||||||
mTheme->onInit();
|
mTheme->init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,9 @@
|
||||||
#include "../GameData.h"
|
#include "../GameData.h"
|
||||||
#include "../FolderData.h"
|
#include "../FolderData.h"
|
||||||
|
|
||||||
#define DRAWFRAMERATE
|
|
||||||
|
|
||||||
|
//This is where the magic happens - GuiGameList is the parent of almost every graphical element in ES at the moment.
|
||||||
|
//It has a GuiList child that handles the game list, a GuiTheme that handles the theming system, and a GuiImage for game images.
|
||||||
class GuiGameList : GuiComponent
|
class GuiGameList : GuiComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#include "GuiImage.h"
|
#include "GuiImage.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
int GuiImage::getWidth() { return mWidth; }
|
unsigned int GuiImage::getWidth() { return mWidth; }
|
||||||
int GuiImage::getHeight() { return mHeight; }
|
unsigned int GuiImage::getHeight() { return mHeight; }
|
||||||
|
|
||||||
GuiImage::GuiImage(int offsetX, int offsetY, std::string path, unsigned int resizeWidth, unsigned int resizeHeight, bool resizeExact)
|
GuiImage::GuiImage(int offsetX, int offsetY, std::string path, unsigned int resizeWidth, unsigned int resizeHeight, bool resizeExact)
|
||||||
{
|
{
|
||||||
|
@ -12,7 +13,7 @@ GuiImage::GuiImage(int offsetX, int offsetY, std::string path, unsigned int resi
|
||||||
mOffsetX = offsetX;
|
mOffsetX = offsetX;
|
||||||
mOffsetY = offsetY;
|
mOffsetY = offsetY;
|
||||||
|
|
||||||
//default origin (center of image)
|
//default origin is the center of image
|
||||||
mOriginX = 0.5;
|
mOriginX = 0.5;
|
||||||
mOriginY = 0.5;
|
mOriginY = 0.5;
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ void GuiImage::loadImage(std::string path)
|
||||||
unsigned int width, height;
|
unsigned int width, height;
|
||||||
|
|
||||||
//detect the filetype
|
//detect the filetype
|
||||||
//format = FreeImage_GetFileType(path.c_str(), 0);
|
format = FreeImage_GetFileType(path.c_str(), 0);
|
||||||
if(format == FIF_UNKNOWN)
|
if(format == FIF_UNKNOWN)
|
||||||
format = FreeImage_GetFIFFromFilename(path.c_str());
|
format = FreeImage_GetFIFFromFilename(path.c_str());
|
||||||
if(format == FIF_UNKNOWN)
|
if(format == FIF_UNKNOWN)
|
||||||
|
@ -85,6 +86,7 @@ void GuiImage::loadImage(std::string path)
|
||||||
FreeImage_Unload(image);
|
FreeImage_Unload(image);
|
||||||
image = imgConv;
|
image = imgConv;
|
||||||
|
|
||||||
|
//get a pointer to the image data as BGRA
|
||||||
imageData = FreeImage_GetBits(image);
|
imageData = FreeImage_GetBits(image);
|
||||||
if(!imageData)
|
if(!imageData)
|
||||||
{
|
{
|
||||||
|
@ -97,13 +99,37 @@ void GuiImage::loadImage(std::string path)
|
||||||
width = FreeImage_GetWidth(image);
|
width = FreeImage_GetWidth(image);
|
||||||
height = FreeImage_GetHeight(image);
|
height = FreeImage_GetHeight(image);
|
||||||
|
|
||||||
|
//if width or height are zero then something is clearly wrong
|
||||||
if(!width || !height)
|
if(!width || !height)
|
||||||
{
|
{
|
||||||
std::cerr << "Width or height are zero for image \"" << path << "\"!\n";
|
std::cerr << "Width or height are zero for image \"" << path << "\"!\n";
|
||||||
|
FreeImage_Unload(image);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
//set width/height to powers of 2 for OpenGL
|
||||||
|
for(unsigned int i = 0; i < 22; i++)
|
||||||
|
{
|
||||||
|
unsigned int pwrOf2 = pow(2, i);
|
||||||
|
if(!widthPwrOf2 && pwrOf2 >= width)
|
||||||
|
widthPwrOf2 = pwrOf2;
|
||||||
|
if(!heightPwrOf2 && pwrOf2 >= height)
|
||||||
|
heightPwrOf2 = pwrOf2;
|
||||||
|
|
||||||
|
if(widthPwrOf2 && heightPwrOf2)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!widthPwrOf2 || !heightPwrOf2)
|
||||||
|
{
|
||||||
|
std::cerr << "Error assigning power of two for width or height of image!\n";
|
||||||
|
FreeImage_Unload(image);
|
||||||
|
return;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
//convert from BGRA to RGBA
|
//convert from BGRA to RGBA
|
||||||
GLubyte* imageRGBA = new GLubyte[4*width*height];
|
GLubyte* imageRGBA = new GLubyte[4*width*height];
|
||||||
for(unsigned int i = 0; i < width*height; i++)
|
for(unsigned int i = 0; i < width*height; i++)
|
||||||
|
@ -133,7 +159,6 @@ void GuiImage::loadImage(std::string path)
|
||||||
//free the memory from that pointer
|
//free the memory from that pointer
|
||||||
delete[] imageRGBA;
|
delete[] imageRGBA;
|
||||||
|
|
||||||
//a simple way to resize: lie about our real texture size!
|
|
||||||
//(we don't resize tiled images)
|
//(we don't resize tiled images)
|
||||||
if(!mTiled)
|
if(!mTiled)
|
||||||
{
|
{
|
||||||
|
@ -209,27 +234,33 @@ void GuiImage::onRender()
|
||||||
{
|
{
|
||||||
if(mTiled)
|
if(mTiled)
|
||||||
{
|
{
|
||||||
for(unsigned int x = 0; x < (unsigned int)((float)mResizeWidth/mWidth + 1.5); x++)
|
unsigned int xCount = (unsigned int)((float)mResizeWidth/mWidth + 1.5);
|
||||||
|
unsigned int yCount = (unsigned int)((float)mResizeHeight/mHeight + 1.5);
|
||||||
|
|
||||||
|
//std::cout << "Array size: " << xCount << "x" << yCount << "\n";
|
||||||
|
|
||||||
|
GLfloat* points = new GLfloat[xCount * yCount * 12];
|
||||||
|
GLfloat* texs = new GLfloat[xCount * yCount * 12];
|
||||||
|
for(unsigned int x = 0; x < xCount; x++)
|
||||||
{
|
{
|
||||||
for(unsigned int y = 0; y < (unsigned int)((float)mResizeHeight/mHeight + 1.5); y++)
|
for(unsigned int y = 0; y < yCount; y++)
|
||||||
{
|
{
|
||||||
drawImage(mOffsetX + x*mWidth, mOffsetY + y*mHeight);
|
buildImageArray(mOffsetX + x*mWidth, mOffsetY + y*mHeight, points + (12 * (x*yCount + y)), texs + (12 * (x*yCount + y)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
drawImageArray(points, texs, xCount * yCount * 6);
|
||||||
|
delete[] points;
|
||||||
|
delete[] texs;
|
||||||
}else{
|
}else{
|
||||||
drawImage(mOffsetX, mOffsetY);
|
GLfloat points[12], texs[12];
|
||||||
|
buildImageArray(mOffsetX, mOffsetY, points, texs);
|
||||||
|
drawImageArray(points, texs, 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiImage::drawImage(int posX, int posY)
|
void GuiImage::buildImageArray(int posX, int posY, GLfloat* points, GLfloat* texs)
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D, mTextureID);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
|
||||||
GLfloat points[12];
|
|
||||||
points[0] = posX - (mWidth * mOriginX); points[1] = posY - (mHeight * mOriginY);
|
points[0] = posX - (mWidth * mOriginX); points[1] = posY - (mHeight * mOriginY);
|
||||||
points[2] = posX - (mWidth * mOriginX); points[3] = posY + (mHeight * (1 - mOriginY));
|
points[2] = posX - (mWidth * mOriginX); points[3] = posY + (mHeight * (1 - mOriginY));
|
||||||
points[4] = posX + (mWidth * (1 - mOriginX)); points[5] = posY - (mHeight * mOriginY);
|
points[4] = posX + (mWidth * (1 - mOriginX)); points[5] = posY - (mHeight * mOriginY);
|
||||||
|
@ -238,10 +269,8 @@ void GuiImage::drawImage(int posX, int posY)
|
||||||
points[8] = posX - (mWidth * mOriginX); points[9] = posY + (mHeight * (1 - mOriginY));
|
points[8] = posX - (mWidth * mOriginX); points[9] = posY + (mHeight * (1 - mOriginY));
|
||||||
points[10] = posX + (mWidth * (1 -mOriginX)); points[11] = posY + (mHeight * (1 - mOriginY));
|
points[10] = posX + (mWidth * (1 -mOriginX)); points[11] = posY + (mHeight * (1 - mOriginY));
|
||||||
|
|
||||||
//std::cout << "x: " << points[0] << " y: " << points[1] << " to x: " << points[10] << " y: " << points[11] << std::endl;
|
|
||||||
//std::cout << "(w: " << mWidth << " h: " << mHeight << ")" << std::endl;
|
|
||||||
|
|
||||||
GLfloat texs[12];
|
|
||||||
texs[0] = 0; texs[1] = 1;
|
texs[0] = 0; texs[1] = 1;
|
||||||
texs[2] = 0; texs[3] = 0;
|
texs[2] = 0; texs[3] = 0;
|
||||||
texs[4] = 1; texs[5] = 1;
|
texs[4] = 1; texs[5] = 1;
|
||||||
|
@ -249,6 +278,14 @@ void GuiImage::drawImage(int posX, int posY)
|
||||||
texs[6] = 1; texs[7] = 1;
|
texs[6] = 1; texs[7] = 1;
|
||||||
texs[8] = 0; texs[9] = 0;
|
texs[8] = 0; texs[9] = 0;
|
||||||
texs[10] = 1; texs[11] = 0;
|
texs[10] = 1; texs[11] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiImage::drawImageArray(GLfloat* points, GLfloat* texs, unsigned int numArrays)
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D, mTextureID);
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
@ -257,7 +294,7 @@ void GuiImage::drawImage(int posX, int posY)
|
||||||
glVertexPointer(2, GL_FLOAT, 0, points);
|
glVertexPointer(2, GL_FLOAT, 0, points);
|
||||||
glTexCoordPointer(2, GL_FLOAT, 0, texs);
|
glTexCoordPointer(2, GL_FLOAT, 0, texs);
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
glDrawArrays(GL_TRIANGLES, 0, numArrays);
|
||||||
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
@ -269,9 +306,7 @@ void GuiImage::drawImage(int posX, int posY)
|
||||||
void GuiImage::onInit()
|
void GuiImage::onInit()
|
||||||
{
|
{
|
||||||
if(!mPath.empty())
|
if(!mPath.empty())
|
||||||
{
|
|
||||||
loadImage(mPath);
|
loadImage(mPath);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiImage::onDeinit()
|
void GuiImage::onDeinit()
|
||||||
|
|
|
@ -9,18 +9,22 @@
|
||||||
class GuiImage : public GuiComponent
|
class GuiImage : public GuiComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
//Creates a new GuiImage at the given location. If given an image, it will be loaded. If maxWidth and/or maxHeight are nonzero, the image will be
|
||||||
|
//resized to fix. If only one axis is specified, the other will be resized in accordance with the image's aspect ratio. If resizeExact is false,
|
||||||
|
//the image will only be downscaled, never upscaled (the image's size must surpass at least one nonzero bound).
|
||||||
GuiImage(int offsetX = 0, int offsetY = 0, std::string path = "", unsigned int maxWidth = 0, unsigned int maxHeight = 0, bool resizeExact = false);
|
GuiImage(int offsetX = 0, int offsetY = 0, std::string path = "", unsigned int maxWidth = 0, unsigned int maxHeight = 0, bool resizeExact = false);
|
||||||
~GuiImage();
|
~GuiImage();
|
||||||
|
|
||||||
void setImage(std::string path);
|
void setImage(std::string path); //Loads the image at the given filepath.
|
||||||
void setOrigin(float originX, float originY);
|
void setOrigin(float originX, float originY); //Sets the origin as a percentage of this image (e.g. (0, 0) is top left, (0.5, 0.5) is the center)
|
||||||
void setTiling(bool tile);
|
void setTiling(bool tile); //Enables or disables tiling. Must be called before loading an image or resizing will be weird.
|
||||||
|
|
||||||
int getWidth();
|
unsigned int getWidth(); //Returns render width in pixels. May be different than actual texture width.
|
||||||
int getHeight();
|
unsigned int getHeight(); //Returns render height in pixels. May be different than actual texture height.
|
||||||
|
|
||||||
void onRender();
|
void onRender();
|
||||||
|
|
||||||
|
//Image textures will be deleted on renderer deinitialization, and recreated on reinitialization (if mPath is not empty).
|
||||||
void onInit();
|
void onInit();
|
||||||
void onDeinit();
|
void onDeinit();
|
||||||
|
|
||||||
|
@ -30,13 +34,14 @@ private:
|
||||||
bool mResizeExact, mTiled;
|
bool mResizeExact, mTiled;
|
||||||
|
|
||||||
void loadImage(std::string path);
|
void loadImage(std::string path);
|
||||||
void drawImage(int x, int y);
|
void buildImageArray(int x, int y, GLfloat* points, GLfloat* texs); //writes 12 GLfloat points and 12 GLfloat texture coordinates to a given array at a given position
|
||||||
|
void drawImageArray(GLfloat* points, GLfloat* texs, unsigned int count = 6); //draws the given set of points and texture coordinates, number of coordinate pairs may be specified (default 6)
|
||||||
void unloadImage();
|
void unloadImage();
|
||||||
|
|
||||||
std::string mPath;
|
std::string mPath;
|
||||||
|
|
||||||
int mOffsetX, mOffsetY;
|
int mOffsetX, mOffsetY;
|
||||||
unsigned int mWidth, mHeight;
|
unsigned int mWidth, mHeight; //Our rendered size.
|
||||||
|
|
||||||
GLuint mTextureID;
|
GLuint mTextureID;
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,9 +8,10 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#define SCROLLDELAY 507
|
#define SCROLLDELAY 507
|
||||||
#define SCROLLTIME (57*5)
|
#define SCROLLTIME 200
|
||||||
|
|
||||||
//this should really be a template
|
//A graphical list. Supports multiple colors for rows and scrolling.
|
||||||
|
//TODO - add truncation to text rendering if name exceeds a maximum width (a trailing elipses, perhaps).
|
||||||
template <typename listType>
|
template <typename listType>
|
||||||
class GuiList : public GuiComponent
|
class GuiList : public GuiComponent
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../GuiComponent.h"
|
#include "../GuiComponent.h"
|
||||||
#include "GuiList.h"
|
#include "GuiList.h"
|
||||||
|
|
||||||
|
//This is a very simple menu that is opened by pressing the Menu key.
|
||||||
class GuiMenu : public GuiComponent
|
class GuiMenu : public GuiComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -137,8 +137,6 @@ GuiComponent* GuiTheme::createElement(pugi::xml_node data, GuiComponent* parent)
|
||||||
float ox = strToFloat(originX);
|
float ox = strToFloat(originX);
|
||||||
float oy = strToFloat(originY);
|
float oy = strToFloat(originY);
|
||||||
|
|
||||||
std::cout << "w: " << w << "px, h: " << h << "px\n";
|
|
||||||
|
|
||||||
GuiImage* comp = new GuiImage(x, y, "", w, h, true);
|
GuiImage* comp = new GuiImage(x, y, "", w, h, true);
|
||||||
comp->setOrigin(ox, oy);
|
comp->setOrigin(ox, oy);
|
||||||
comp->setTiling(tiled);
|
comp->setTiling(tiled);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../GuiComponent.h"
|
#include "../GuiComponent.h"
|
||||||
#include "../pugiXML/pugixml.hpp"
|
#include "../pugiXML/pugixml.hpp"
|
||||||
|
|
||||||
|
//This class loads an XML-defined list of GuiComponents.
|
||||||
class GuiTheme : public GuiComponent
|
class GuiTheme : public GuiComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
74
src/main.cpp
74
src/main.cpp
|
@ -1,3 +1,5 @@
|
||||||
|
//EmulationStation, a graphical front-end for ROM browsing. Created by Alec "Aloshi" Lofquist.
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
#include "components/GuiGameList.h"
|
#include "components/GuiGameList.h"
|
||||||
|
@ -6,13 +8,12 @@
|
||||||
#include "components/GuiInputConfig.h"
|
#include "components/GuiInputConfig.h"
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <bcm_host.h>
|
#include <bcm_host.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
//these can be set by command-line arguments
|
||||||
bool PARSEGAMELISTONLY = false;
|
bool PARSEGAMELISTONLY = false;
|
||||||
bool IGNOREGAMELIST = false;
|
bool IGNOREGAMELIST = false;
|
||||||
|
bool DRAWFRAMERATE = false;
|
||||||
#ifdef DRAWFRAMERATE
|
|
||||||
float FRAMERATE = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace fs = boost::filesystem;
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
|
@ -22,13 +23,12 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
bool running = true;
|
bool running = true;
|
||||||
|
|
||||||
//by the way, if anyone ever tries to port this to a different renderer but leave SDL as input -
|
//ALWAYS INITIALIZE VIDEO. It starts SDL's event system, and without it, input won't work.
|
||||||
//KEEP INITIALIZING VIDEO. It starts SDL's event system, and without it, input won't work.
|
|
||||||
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) != 0)
|
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) != 0)
|
||||||
{
|
{
|
||||||
std::cerr << "Error - could not initialize SDL!\n";
|
std::cerr << "Error - could not initialize SDL!\n";
|
||||||
std::cerr << " " << SDL_GetError() << "\n";
|
std::cerr << " " << SDL_GetError() << "\n";
|
||||||
std::cerr << "Are you in the 'video' and 'input' groups? Are you running with X closed?\n";
|
std::cerr << "Are you in the 'video' and 'input' groups? Are you running with X closed? Is your firmware up to date?\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,21 @@ int main(int argc, char* argv[])
|
||||||
}else if(strcmp(argv[i], "--ignore-gamelist") == 0)
|
}else if(strcmp(argv[i], "--ignore-gamelist") == 0)
|
||||||
{
|
{
|
||||||
IGNOREGAMELIST = true;
|
IGNOREGAMELIST = true;
|
||||||
|
}else if(strcmp(argv[i], "--draw-framerate") == 0)
|
||||||
|
{
|
||||||
|
DRAWFRAMERATE = true;
|
||||||
|
}else if(strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0)
|
||||||
|
{
|
||||||
|
std::cout << "EmulationStation, a graphical front-end for ROM browsing.\n";
|
||||||
|
std::cout << "Command line arguments:\n";
|
||||||
|
std::cout << "-w [width in pixels] set screen width\n";
|
||||||
|
std::cout << "-h [height in pixels] set screen height\n";
|
||||||
|
std::cout << "--gamelist-only skip automatic game detection, only read from gamelist.xml\n";
|
||||||
|
std::cout << "--ignore-gamelist ignore the gamelist (useful for troubleshooting)\n";
|
||||||
|
std::cout << "--draw-framerate display the framerate\n";
|
||||||
|
std::cout << "--help summon a sentient, angry tuba\n\n";
|
||||||
|
std::cout << "More information available in README.md.\n";
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,22 +94,6 @@ int main(int argc, char* argv[])
|
||||||
fs::create_directory(configDir);
|
fs::create_directory(configDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if there are config files in the old places, and if so, move them to the new directory
|
|
||||||
std::string oldSysPath = home + "/.es_systems.cfg";
|
|
||||||
std::string oldInpPath = home + "/.es_input.cfg";
|
|
||||||
if(fs::exists(oldSysPath))
|
|
||||||
{
|
|
||||||
std::cout << "Moving old system config file " << oldSysPath << " to new path at " << SystemData::getConfigPath() << "\n";
|
|
||||||
fs::copy_file(oldSysPath, SystemData::getConfigPath());
|
|
||||||
fs::remove(oldSysPath);
|
|
||||||
}
|
|
||||||
if(fs::exists(oldInpPath))
|
|
||||||
{
|
|
||||||
std::cout << "Deleting old input config file\n";
|
|
||||||
fs::remove(oldInpPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//try loading the system config file
|
//try loading the system config file
|
||||||
if(!fs::exists(SystemData::getConfigPath())) //if it doesn't exist, create the example and quit
|
if(!fs::exists(SystemData::getConfigPath())) //if it doesn't exist, create the example and quit
|
||||||
|
@ -109,7 +108,7 @@ int main(int argc, char* argv[])
|
||||||
if(SystemData::sSystemVector.size() == 0) //if it exists but was empty, notify the user and quit
|
if(SystemData::sSystemVector.size() == 0) //if it exists but was empty, notify the user and quit
|
||||||
{
|
{
|
||||||
std::cerr << "A system config file in " << SystemData::getConfigPath() << " was found, but contained no systems.\n";
|
std::cerr << "A system config file in " << SystemData::getConfigPath() << " was found, but contained no systems.\n";
|
||||||
std::cerr << "You should probably go read that, or delete it.\n";
|
std::cerr << "Does at least one system have a game presesnt?\n";
|
||||||
running = false;
|
running = false;
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
|
@ -128,19 +127,19 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//choose which Gui to open up
|
//choose which GUI to open depending on Input configuration
|
||||||
if(fs::exists(InputManager::getConfigPath()))
|
if(fs::exists(InputManager::getConfigPath()))
|
||||||
{
|
{
|
||||||
|
//an input config already exists - load it and proceed to the gamelist as usual.
|
||||||
InputManager::loadConfig();
|
InputManager::loadConfig();
|
||||||
new GuiGameList(useDetail);
|
new GuiGameList(useDetail);
|
||||||
}else{
|
}else{
|
||||||
|
//if no input.cfg is present, but a joystick is connected, launch the input config GUI
|
||||||
if(SDL_NumJoysticks() > 0)
|
if(SDL_NumJoysticks() > 0)
|
||||||
{
|
|
||||||
new GuiInputConfig();
|
new GuiInputConfig();
|
||||||
}else{
|
else
|
||||||
std::cout << "Note - it looks like you have no joysticks connected.\n";
|
|
||||||
new GuiGameList(useDetail);
|
new GuiGameList(useDetail);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,13 +171,20 @@ int main(int argc, char* argv[])
|
||||||
int deltaTime = curTime - lastTime;
|
int deltaTime = curTime - lastTime;
|
||||||
lastTime = curTime;
|
lastTime = curTime;
|
||||||
|
|
||||||
#ifdef DRAWFRAMERATE
|
|
||||||
FRAMERATE = 1/((float)deltaTime)*1000;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GuiComponent::processTicks(deltaTime);
|
GuiComponent::processTicks(deltaTime);
|
||||||
|
|
||||||
Renderer::render();
|
Renderer::render();
|
||||||
|
|
||||||
|
if(DRAWFRAMERATE)
|
||||||
|
{
|
||||||
|
float framerate = 1/((float)deltaTime)*1000;
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << framerate;
|
||||||
|
std::string fps;
|
||||||
|
ss >> fps;
|
||||||
|
Renderer::drawText(fps, 50, 50, 0x00FF00);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Renderer::swapBuffers();
|
Renderer::swapBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue