mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-02-16 12:05:38 +00:00
This commit is contained in:
commit
b1b1d23337
|
@ -150,6 +150,8 @@ set(ES_HEADERS
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiSettingsMenu.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pugiXML/pugiconfig.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pugiXML/pugixml.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/resources/ResourceManager.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/resources/TextureResource.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/data/Resources.h
|
||||
)
|
||||
set(ES_SOURCES
|
||||
|
@ -189,6 +191,8 @@ set(ES_SOURCES
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMenu.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiSettingsMenu.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pugiXML/pugixml.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/resources/ResourceManager.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/resources/TextureResource.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/data/logo/ES_logo_16.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/data/logo/ES_logo_32.cpp
|
||||
)
|
||||
|
|
206
src/Font.cpp
206
src/Font.cpp
|
@ -14,6 +14,8 @@ int Font::getDpiY() { return 96; }
|
|||
|
||||
int Font::getSize() { return mSize; }
|
||||
|
||||
std::map< std::pair<std::string, int>, std::weak_ptr<Font> > Font::sFontMap;
|
||||
|
||||
std::string Font::getDefaultPath()
|
||||
{
|
||||
const int fontCount = 4;
|
||||
|
@ -69,23 +71,56 @@ void Font::initLibrary()
|
|||
}
|
||||
}
|
||||
|
||||
Font::Font(std::string path, int size)
|
||||
: fontScale(1.0f)
|
||||
Font::Font(const ResourceManager& rm, const std::string& path, int size) : fontScale(1.0f), mSize(size), mPath(path)
|
||||
{
|
||||
mPath = path;
|
||||
mSize = size;
|
||||
|
||||
init();
|
||||
reload(rm);
|
||||
}
|
||||
|
||||
void Font::init()
|
||||
Font::~Font()
|
||||
{
|
||||
deinit();
|
||||
}
|
||||
|
||||
void Font::reload(const ResourceManager& rm)
|
||||
{
|
||||
init(rm.getFileData(mPath));
|
||||
}
|
||||
|
||||
void Font::unload(const ResourceManager& rm)
|
||||
{
|
||||
deinit();
|
||||
}
|
||||
|
||||
std::shared_ptr<Font> Font::get(ResourceManager& rm, const std::string& path, int size)
|
||||
{
|
||||
if(path.empty())
|
||||
{
|
||||
LOG(LogError) << "Tried to get font with no path!";
|
||||
return std::shared_ptr<Font>();
|
||||
}
|
||||
|
||||
std::pair<std::string, int> def(path, size);
|
||||
auto foundFont = sFontMap.find(def);
|
||||
if(foundFont != sFontMap.end())
|
||||
{
|
||||
if(!foundFont->second.expired())
|
||||
return foundFont->second.lock();
|
||||
}
|
||||
|
||||
std::shared_ptr<Font> font = std::shared_ptr<Font>(new Font(rm, path, size));
|
||||
sFontMap[def] = std::weak_ptr<Font>(font);
|
||||
rm.addReloadable(font);
|
||||
return font;
|
||||
}
|
||||
|
||||
void Font::init(ResourceData data)
|
||||
{
|
||||
if(!libraryInitialized)
|
||||
initLibrary();
|
||||
|
||||
mMaxGlyphHeight = 0;
|
||||
|
||||
buildAtlas();
|
||||
buildAtlas(data);
|
||||
}
|
||||
|
||||
void Font::deinit()
|
||||
|
@ -94,11 +129,11 @@ void Font::deinit()
|
|||
glDeleteTextures(1, &textureID);
|
||||
}
|
||||
|
||||
void Font::buildAtlas()
|
||||
void Font::buildAtlas(ResourceData data)
|
||||
{
|
||||
if(FT_New_Face(sLibrary, mPath.c_str(), 0, &face))
|
||||
if(FT_New_Memory_Face(sLibrary, data.ptr.get(), data.length, 0, &face))
|
||||
{
|
||||
LOG(LogError) << "Error creating font face! (path: " << mPath.c_str();
|
||||
LOG(LogError) << "Error creating font face!";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -205,19 +240,12 @@ void Font::buildAtlas()
|
|||
fontScale *= 1.25f;
|
||||
mSize = (int)(mSize * (1.0f / fontScale));
|
||||
deinit();
|
||||
init();
|
||||
}
|
||||
else {
|
||||
init(data);
|
||||
}else{
|
||||
LOG(LogInfo) << "Created font with size " << mSize << ".";
|
||||
}
|
||||
}
|
||||
|
||||
Font::~Font()
|
||||
{
|
||||
if(textureID)
|
||||
glDeleteTextures(1, &textureID);
|
||||
}
|
||||
|
||||
|
||||
void Font::drawText(std::string text, int startx, int starty, int color)
|
||||
{
|
||||
|
@ -294,6 +322,144 @@ int Font::getHeight()
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Font::drawCenteredText(std::string text, int xOffset, int y, unsigned int color)
|
||||
{
|
||||
int w, h;
|
||||
sizeText(text, &w, &h);
|
||||
|
||||
int x = Renderer::getScreenWidth() - w;
|
||||
x = x / 2;
|
||||
x += xOffset / 2;
|
||||
|
||||
drawText(text, x, y, color);
|
||||
}
|
||||
|
||||
//this could probably be optimized
|
||||
//draws text and ensures it's never longer than xLen
|
||||
void Font::drawWrappedText(std::string text, int xStart, int yStart, int xLen, unsigned int color)
|
||||
{
|
||||
int y = yStart;
|
||||
|
||||
std::string line, word, temp;
|
||||
int w, h;
|
||||
size_t space, newline;
|
||||
|
||||
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);
|
||||
|
||||
//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;
|
||||
|
||||
sizeText(temp, &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) || newline != std::string::npos)
|
||||
{
|
||||
line = temp;
|
||||
word = "";
|
||||
}
|
||||
|
||||
|
||||
//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
|
||||
if(w > 0) //make sure it's not blank
|
||||
drawText(line, xStart, y, color);
|
||||
|
||||
//increment y by height and some extra padding for the next line
|
||||
y += h + 4;
|
||||
|
||||
//move the word we skipped to the next line
|
||||
line = word;
|
||||
}else{
|
||||
//there's still space, continue building the line
|
||||
line = temp;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Font::sizeWrappedText(std::string text, int xLen, int* xOut, int* yOut)
|
||||
{
|
||||
//this is incorrect for text that is so short it doesn't need to wrap
|
||||
if(xOut != NULL)
|
||||
*xOut = xLen;
|
||||
|
||||
int y = 0;
|
||||
|
||||
std::string line, word, temp;
|
||||
int w, h;
|
||||
size_t space, newline;
|
||||
|
||||
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);
|
||||
|
||||
//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;
|
||||
|
||||
sizeText(temp, &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) || newline != std::string::npos)
|
||||
{
|
||||
line = temp;
|
||||
word = "";
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
//increment y by height and some extra padding for the next line
|
||||
y += h + 4;
|
||||
|
||||
//move the word we skipped to the next line
|
||||
line = word;
|
||||
}else{
|
||||
//there's still space, continue building the line
|
||||
line = temp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(yOut != NULL)
|
||||
*yOut = y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
//TextCache
|
||||
//=============================================================================================================
|
||||
|
|
30
src/Font.h
30
src/Font.h
|
@ -7,17 +7,23 @@
|
|||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include "Vector2.h"
|
||||
#include "resources/ResourceManager.h"
|
||||
|
||||
class TextCache;
|
||||
|
||||
#define FONT_SIZE_SMALL ((unsigned int)(0.035f * Renderer::getScreenHeight()))
|
||||
#define FONT_SIZE_MEDIUM ((unsigned int)(0.045f * Renderer::getScreenHeight()))
|
||||
#define FONT_SIZE_LARGE ((unsigned int)(0.1f * Renderer::getScreenHeight()))
|
||||
|
||||
//A TrueType Font renderer that uses FreeType and OpenGL.
|
||||
//The library is automatically initialized when it's needed.
|
||||
class Font
|
||||
class Font : public IReloadable
|
||||
{
|
||||
public:
|
||||
static void initLibrary();
|
||||
|
||||
Font(std::string path, int size);
|
||||
static std::shared_ptr<Font> get(ResourceManager& rm, const std::string& path, int size);
|
||||
|
||||
~Font();
|
||||
|
||||
FT_Face face;
|
||||
|
@ -46,10 +52,15 @@ public:
|
|||
//Create a TextCache, render with it, then delete it. Best used for short text or text that changes frequently.
|
||||
void drawText(std::string text, int startx, int starty, int color);
|
||||
void sizeText(std::string text, int* w, int* h); //Sets the width and height of a given string to supplied pointers. A dimension is skipped if its pointer is NULL.
|
||||
|
||||
void drawWrappedText(std::string text, int xStart, int yStart, int xLen, unsigned int color);
|
||||
void sizeWrappedText(std::string text, int xLen, int* xOut, int* yOut);
|
||||
void drawCenteredText(std::string text, int xOffset, int y, unsigned int color);
|
||||
|
||||
int getHeight();
|
||||
|
||||
void init();
|
||||
void deinit();
|
||||
void unload(const ResourceManager& rm) override;
|
||||
void reload(const ResourceManager& rm) override;
|
||||
|
||||
int getSize();
|
||||
|
||||
|
@ -61,15 +72,22 @@ private:
|
|||
static FT_Library sLibrary;
|
||||
static bool libraryInitialized;
|
||||
|
||||
void buildAtlas(); //Builds a "texture atlas," one big OpenGL texture with glyphs 32 to 128.
|
||||
static std::map< std::pair<std::string, int>, std::weak_ptr<Font> > sFontMap;
|
||||
|
||||
Font(const ResourceManager& rm, const std::string& path, int size);
|
||||
|
||||
void init(ResourceData data);
|
||||
void deinit();
|
||||
|
||||
void buildAtlas(ResourceData data); //Builds a "texture atlas," one big OpenGL texture with glyphs 32 to 128.
|
||||
|
||||
int textureWidth; //OpenGL texture width
|
||||
int textureHeight; //OpenGL texture height
|
||||
int mMaxGlyphHeight;
|
||||
float fontScale; //!<Font scale factor. It is > 1.0 if the font would be to big for the texture
|
||||
|
||||
std::string mPath;
|
||||
int mSize;
|
||||
const std::string mPath;
|
||||
};
|
||||
|
||||
class TextCache
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "Log.h"
|
||||
#include "Renderer.h"
|
||||
|
||||
GuiComponent::GuiComponent(Window* window) : mWindow(window), mParent(NULL)
|
||||
GuiComponent::GuiComponent(Window* window) : mWindow(window), mParent(NULL), mOpacity(255)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ std::vector<unsigned char> ImageIO::loadFromMemoryRGBA32(const unsigned char * d
|
|||
rawData = std::vector<unsigned char>(tempData, tempData + width * height * 4);
|
||||
//free bitmap data
|
||||
FreeImage_Unload(fiBitmap);
|
||||
delete[] tempData;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -25,8 +25,6 @@ namespace Renderer
|
|||
unsigned int getScreenWidth();
|
||||
unsigned int getScreenHeight();
|
||||
|
||||
enum FontSize { SMALL, MEDIUM, LARGE, FONT_SIZE_COUNT };
|
||||
Font* getDefaultFont(FontSize size);
|
||||
void buildGLColorArray(GLubyte* ptr, unsigned int color, unsigned int vertCount);
|
||||
|
||||
//graphics commands
|
||||
|
@ -40,10 +38,6 @@ namespace Renderer
|
|||
void popClipRect();
|
||||
|
||||
void drawRect(int x, int y, int w, int h, unsigned int color);
|
||||
void drawText(std::string text, int x, int y, unsigned int color, Font* font);
|
||||
void drawCenteredText(std::string text, int xOffset, int y, unsigned int color, Font* font);
|
||||
void drawWrappedText(std::string text, int xStart, int yStart, int xLen, unsigned int color, Font* font);
|
||||
void sizeWrappedText(std::string text, int xLen, Font* font, int* xOut, int* yOut);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
#include <stack>
|
||||
|
||||
namespace Renderer {
|
||||
bool loadedFonts = false;
|
||||
|
||||
std::stack<Rect> clipStack;
|
||||
|
||||
void setColor4bArray(GLubyte* array, unsigned int color)
|
||||
|
@ -120,195 +118,4 @@ namespace Renderer {
|
|||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisable(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Font* fonts[3] = {NULL, NULL, NULL};
|
||||
|
||||
/*void unloadFonts()
|
||||
{
|
||||
std::cout << "unloading fonts...";
|
||||
|
||||
for(unsigned int i = 0; i < 3; i++)
|
||||
{
|
||||
delete fonts[i];
|
||||
fonts[i] = NULL;
|
||||
}
|
||||
|
||||
loadedFonts = false;
|
||||
|
||||
std::cout << "done.\n";
|
||||
}*/
|
||||
|
||||
//creates the default fonts (which shouldn't ever be deleted)
|
||||
void loadFonts()
|
||||
{
|
||||
if(loadedFonts)
|
||||
return;
|
||||
|
||||
std::string fontPath = Font::getDefaultPath();
|
||||
|
||||
//make sure our font exists
|
||||
if(!boost::filesystem::exists(fontPath))
|
||||
{
|
||||
LOG(LogError) << "System font wasn't found! Try installing the DejaVu truetype font (pacman -S ttf-dejavu on Arch, sudo apt-get install ttf-dejavu on Debian)";
|
||||
return;
|
||||
}
|
||||
|
||||
float fontSizes[] = {0.035f, 0.045f, 0.1f};
|
||||
for(unsigned int i = 0; i < 3; i++)
|
||||
{
|
||||
fonts[i] = new Font(fontPath, (unsigned int)(fontSizes[i] * getScreenHeight()));
|
||||
}
|
||||
|
||||
loadedFonts = true;
|
||||
|
||||
LOG(LogInfo) << "Loaded fonts successfully.";
|
||||
}
|
||||
|
||||
Font* getDefaultFont(FontSize size)
|
||||
{
|
||||
if(!loadedFonts)
|
||||
loadFonts();
|
||||
|
||||
return fonts[size];
|
||||
}
|
||||
|
||||
void drawText(std::string text, int x, int y, unsigned int color, Font* font)
|
||||
{
|
||||
font->drawText(text, x, y, color);
|
||||
}
|
||||
|
||||
void drawCenteredText(std::string text, int xOffset, int y, unsigned int color, Font* font)
|
||||
{
|
||||
int w, h;
|
||||
font->sizeText(text, &w, &h);
|
||||
|
||||
int x = getScreenWidth() - w;
|
||||
x = x / 2;
|
||||
x += xOffset / 2;
|
||||
|
||||
drawText(text, x, y, color, font);
|
||||
}
|
||||
|
||||
//this could probably be optimized
|
||||
//draws text and ensures it's never longer than xLen
|
||||
void drawWrappedText(std::string text, int xStart, int yStart, int xLen, unsigned int color, Font* font)
|
||||
{
|
||||
int y = yStart;
|
||||
|
||||
std::string line, word, temp;
|
||||
int w, h;
|
||||
size_t space, newline;
|
||||
|
||||
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);
|
||||
|
||||
//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;
|
||||
|
||||
font->sizeText(temp, &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) || newline != std::string::npos)
|
||||
{
|
||||
line = temp;
|
||||
word = "";
|
||||
}
|
||||
|
||||
|
||||
//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
|
||||
if(w > 0) //make sure it's not blank
|
||||
drawText(line, xStart, y, color, font);
|
||||
|
||||
//increment y by height and some extra padding for the next line
|
||||
y += h + 4;
|
||||
|
||||
//move the word we skipped to the next line
|
||||
line = word;
|
||||
}else{
|
||||
//there's still space, continue building the line
|
||||
line = temp;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void sizeWrappedText(std::string text, int xLen, Font* font, int* xOut, int* yOut)
|
||||
{
|
||||
if(xOut != NULL)
|
||||
*xOut = xLen;
|
||||
|
||||
int y = 0;
|
||||
|
||||
std::string line, word, temp;
|
||||
int w, h;
|
||||
size_t space, newline;
|
||||
|
||||
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);
|
||||
|
||||
//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;
|
||||
|
||||
font->sizeText(temp, &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) || newline != std::string::npos)
|
||||
{
|
||||
line = temp;
|
||||
word = "";
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
//increment y by height and some extra padding for the next line
|
||||
y += h + 4;
|
||||
|
||||
//move the word we skipped to the next line
|
||||
line = word;
|
||||
}else{
|
||||
//there's still space, continue building the line
|
||||
line = temp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(yOut != NULL)
|
||||
*yOut = y;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -7,17 +7,9 @@ namespace Renderer
|
|||
{
|
||||
void onInit()
|
||||
{
|
||||
for(int i = 0; i < (int)FONT_SIZE_COUNT; i++)
|
||||
{
|
||||
getDefaultFont((FontSize)i)->init();
|
||||
}
|
||||
}
|
||||
|
||||
void onDeinit()
|
||||
{
|
||||
for(int i = 0; i < (int)FONT_SIZE_COUNT; i++)
|
||||
{
|
||||
getDefaultFont((FontSize)i)->deinit();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
Window::Window()
|
||||
{
|
||||
mInputManager = new InputManager(this);
|
||||
|
||||
mDefaultFonts.push_back(Font::get(mResourceManager, Font::getDefaultPath(), FONT_SIZE_SMALL));
|
||||
mDefaultFonts.push_back(Font::get(mResourceManager, Font::getDefaultPath(), FONT_SIZE_MEDIUM));
|
||||
mDefaultFonts.push_back(Font::get(mResourceManager, Font::getDefaultPath(), FONT_SIZE_LARGE));
|
||||
}
|
||||
|
||||
Window::~Window()
|
||||
|
@ -53,8 +57,9 @@ void Window::render()
|
|||
|
||||
void Window::init()
|
||||
{
|
||||
mInputManager->init();
|
||||
mInputManager->init(); //shouldn't this go AFTER renderer initialization?
|
||||
Renderer::init(0, 0);
|
||||
mResourceManager.reloadAll();
|
||||
|
||||
for(unsigned int i = 0; i < mGuiStack.size(); i++)
|
||||
{
|
||||
|
@ -70,6 +75,7 @@ void Window::deinit()
|
|||
}
|
||||
|
||||
mInputManager->deinit();
|
||||
mResourceManager.unloadAll();
|
||||
Renderer::deinit();
|
||||
}
|
||||
|
||||
|
@ -97,3 +103,8 @@ InputManager* Window::getInputManager()
|
|||
{
|
||||
return mInputManager;
|
||||
}
|
||||
|
||||
ResourceManager* Window::getResourceManager()
|
||||
{
|
||||
return &mResourceManager;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
#include "GuiComponent.h"
|
||||
#include "InputManager.h"
|
||||
#include "resources/ResourceManager.h"
|
||||
#include <vector>
|
||||
#include "Font.h"
|
||||
|
||||
class Window
|
||||
{
|
||||
|
@ -23,10 +25,14 @@ public:
|
|||
void deinit();
|
||||
|
||||
InputManager* getInputManager();
|
||||
ResourceManager* getResourceManager();
|
||||
|
||||
private:
|
||||
InputManager* mInputManager;
|
||||
ResourceManager mResourceManager;
|
||||
std::vector<GuiComponent*> mGuiStack;
|
||||
|
||||
std::vector< std::shared_ptr<Font> > mDefaultFonts;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -83,25 +83,25 @@ void GuiDetectDevice::update(int deltaTime)
|
|||
|
||||
void GuiDetectDevice::render()
|
||||
{
|
||||
Font* font = Renderer::getDefaultFont(Renderer::MEDIUM);
|
||||
std::shared_ptr<Font> font = Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM);
|
||||
|
||||
std::string playerString;
|
||||
std::stringstream stream;
|
||||
stream << (mCurrentPlayer + 1);
|
||||
stream >> playerString;
|
||||
|
||||
Renderer::drawCenteredText("Press a button on the device for", 0, Renderer::getScreenHeight() / 3, 0x000000FF, font);
|
||||
Renderer::drawCenteredText("PLAYER " + playerString, 0, (int)(Renderer::getScreenHeight()*1.5f) / 3, 0x333333FF, font);
|
||||
font->drawCenteredText("Press a button on the device for", 0, Renderer::getScreenHeight() / 3, 0x000000FF);
|
||||
font->drawCenteredText("PLAYER " + playerString, 0, (int)(Renderer::getScreenHeight()*1.5f) / 3, 0x333333FF);
|
||||
|
||||
if(mWindow->getInputManager()->getNumPlayers() > 0)
|
||||
{
|
||||
Renderer::drawCenteredText("(P1 - hold a button to finish)", 0, (Renderer::getScreenHeight()*2) / 3, (mHoldingFinish ? 0x0000FFFF : 0x000066FF), font);
|
||||
font->drawCenteredText("(P1 - hold a button to finish)", 0, (Renderer::getScreenHeight()*2) / 3, (mHoldingFinish ? 0x0000FFFF : 0x000066FF));
|
||||
}
|
||||
|
||||
if(mWindow->getInputManager()->getNumJoysticks() == 0)
|
||||
{
|
||||
Renderer::drawCenteredText("No joysticks detected!", 0, Renderer::getScreenHeight() - (font->getHeight()*2)-10, 0xFF0000FF, font);
|
||||
font->drawCenteredText("No joysticks detected!", 0, Renderer::getScreenHeight() - (font->getHeight()*2)-10, 0xFF0000FF);
|
||||
}
|
||||
|
||||
Renderer::drawCenteredText("Press F4 to quit.", 0, Renderer::getScreenHeight() - font->getHeight() - 2 , 0x000000FF, font);
|
||||
font->drawCenteredText("Press F4 to quit.", 0, Renderer::getScreenHeight() - font->getHeight() - 2 , 0x000000FF);
|
||||
}
|
||||
|
|
|
@ -41,10 +41,11 @@ void GuiFastSelect::render()
|
|||
|
||||
mBox->render();
|
||||
|
||||
Renderer::drawCenteredText(LETTERS.substr(mLetterID, 1), 0, (int)(sh * 0.5f - (mTheme->getFastSelectFont()->getHeight() * 0.5f)), mTextColor, mTheme->getFastSelectFont());
|
||||
Renderer::drawCenteredText("Sort order:", 0, (int)(sh * 0.6f - (mTheme->getDescriptionFont()->getHeight() * 0.5f)), mTextColor, mTheme->getDescriptionFont());
|
||||
mTheme->getFastSelectFont()->drawCenteredText(LETTERS.substr(mLetterID, 1), 0, (int)(sh * 0.5f - (mTheme->getFastSelectFont()->getHeight() * 0.5f)), mTextColor);
|
||||
mTheme->getDescriptionFont()->drawCenteredText("Sort order:", 0, (int)(sh * 0.6f - (mTheme->getDescriptionFont()->getHeight() * 0.5f)), mTextColor);
|
||||
|
||||
std::string sortString = "<- " + mParent->getSortState().description + " ->";
|
||||
Renderer::drawCenteredText(sortString, 0, (int)(sh * 0.6f + (mTheme->getDescriptionFont()->getHeight() * 0.5f)), mTextColor, mTheme->getDescriptionFont());
|
||||
mTheme->getDescriptionFont()->drawCenteredText(sortString, 0, (int)(sh * 0.6f + (mTheme->getDescriptionFont()->getHeight() * 0.5f)), mTextColor);
|
||||
}
|
||||
|
||||
bool GuiFastSelect::input(InputConfig* config, Input input)
|
||||
|
|
|
@ -26,7 +26,7 @@ bool GuiGameList::isDetailed() const
|
|||
|
||||
GuiGameList::GuiGameList(Window* window) : GuiComponent(window),
|
||||
mTheme(new ThemeComponent(mWindow)),
|
||||
mList(window, 0, 0, Renderer::getDefaultFont(Renderer::MEDIUM)),
|
||||
mList(window, 0, 0, Font::get(*window->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM)),
|
||||
mScreenshot(window),
|
||||
mDescription(window),
|
||||
mDescContainer(window),
|
||||
|
@ -114,15 +114,17 @@ void GuiGameList::render()
|
|||
if(mTheme)
|
||||
mTheme->render();
|
||||
|
||||
std::shared_ptr<Font> headerFont = Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_LARGE);
|
||||
|
||||
//header
|
||||
if(!mTheme->getBool("hideHeader"))
|
||||
Renderer::drawCenteredText(mSystem->getDescName(), 0, 1, 0xFF0000FF, Renderer::getDefaultFont(Renderer::LARGE));
|
||||
headerFont->drawCenteredText(mSystem->getDescName(), 0, 1, 0xFF0000FF);
|
||||
|
||||
if(isDetailed())
|
||||
{
|
||||
//divider
|
||||
if(!mTheme->getBool("hideDividers"))
|
||||
Renderer::drawRect((int)(Renderer::getScreenWidth() * mTheme->getFloat("listOffsetX")) - 4, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2, 8, Renderer::getScreenHeight(), 0x0000FFFF);
|
||||
Renderer::drawRect((int)(Renderer::getScreenWidth() * mTheme->getFloat("listOffsetX")) - 4, headerFont->getHeight() + 2, 8, Renderer::getScreenHeight(), 0x0000FFFF);
|
||||
|
||||
mScreenshot.render();
|
||||
mDescContainer.render();
|
||||
|
@ -324,7 +326,7 @@ void GuiGameList::updateTheme()
|
|||
mList.setScrollSound(mTheme->getSound("menuScroll"));
|
||||
|
||||
mList.setFont(mTheme->getListFont());
|
||||
mList.setOffset(0, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2);
|
||||
mList.setOffset(0, Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_LARGE)->getHeight() + 2);
|
||||
|
||||
if(isDetailed())
|
||||
{
|
||||
|
|
|
@ -77,25 +77,25 @@ bool GuiInputConfig::input(InputConfig* config, Input input)
|
|||
|
||||
void GuiInputConfig::render()
|
||||
{
|
||||
Font* font = Renderer::getDefaultFont(Renderer::MEDIUM);
|
||||
std::shared_ptr<Font> font = Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM);
|
||||
|
||||
std::stringstream stream;
|
||||
stream << "PLAYER " << mTargetConfig->getPlayerNum() + 1 << ", press...";
|
||||
Renderer::drawText(stream.str(), 10, 10, 0x000000FF, font);
|
||||
font->drawText(stream.str(), 10, 10, 0x000000FF);
|
||||
|
||||
int y = 14 + font->getHeight();
|
||||
for(int i = 0; i < mCurInputId; i++)
|
||||
{
|
||||
Renderer::drawText(inputDispName[i], 10, y, 0x00CC00FF, font);
|
||||
font->drawText(inputDispName[i], 10, y, 0x00CC00FF);
|
||||
y += font->getHeight() + 5;
|
||||
}
|
||||
|
||||
if(mCurInputId >= inputCount)
|
||||
{
|
||||
Renderer::drawCenteredText("Basic config done!", 0, (int)(Renderer::getScreenHeight() * 0.4), 0x00CC00FF, font);
|
||||
Renderer::drawCenteredText("Press any button to continue.", 0, (int)(Renderer::getScreenHeight() * 0.4) + font->getHeight() + 4, 0x000000FF, font);
|
||||
font->drawCenteredText("Basic config done!", 0, (int)(Renderer::getScreenHeight() * 0.4), 0x00CC00FF);
|
||||
font->drawCenteredText("Press any button to continue.", 0, (int)(Renderer::getScreenHeight() * 0.4) + font->getHeight() + 4, 0x000000FF);
|
||||
}else{
|
||||
Renderer::drawText(inputDispName[mCurInputId], 10, y, 0x000000FF, font);
|
||||
font->drawText(inputDispName[mCurInputId], 10, y, 0x000000FF);
|
||||
if(mCanSkip)
|
||||
{
|
||||
int textWidth = 0;
|
||||
|
@ -105,10 +105,10 @@ void GuiInputConfig::render()
|
|||
if(Renderer::getScreenWidth() / 2.5f > textWidth)
|
||||
textWidth = (int)(Renderer::getScreenWidth() / 2.5f);
|
||||
|
||||
Renderer::drawText("press Accept to skip", textWidth, y, 0x0000AAFF, font);
|
||||
font->drawText("press Accept to skip", textWidth, y, 0x0000AAFF);
|
||||
}
|
||||
}
|
||||
|
||||
if(!mErrorMsg.empty())
|
||||
Renderer::drawCenteredText(mErrorMsg, 0, Renderer::getScreenHeight() - font->getHeight() - 10, 0xFF0000FF, font);
|
||||
font->drawCenteredText(mErrorMsg, 0, Renderer::getScreenHeight() - font->getHeight() - 10, 0xFF0000FF);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ GuiMenu::GuiMenu(Window* window, GuiGameList* parent) : GuiComponent(window)
|
|||
{
|
||||
mParent = parent;
|
||||
|
||||
mList = new TextListComponent<std::string>(mWindow, 0, Renderer::getDefaultFont(Renderer::LARGE)->getHeight() + 2, Renderer::getDefaultFont(Renderer::LARGE));
|
||||
std::shared_ptr<Font> font = Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_LARGE);
|
||||
mList = new TextListComponent<std::string>(mWindow, 0, font->getHeight() + 2, font);
|
||||
mList->setSelectedTextColor(0x0000FFFF);
|
||||
populateList();
|
||||
}
|
||||
|
|
|
@ -4,13 +4,18 @@
|
|||
#include <math.h>
|
||||
#include "../Log.h"
|
||||
#include "../Renderer.h"
|
||||
#include "../Window.h"
|
||||
|
||||
Vector2u ImageComponent::getTextureSize() { return mTextureSize; }
|
||||
Vector2u ImageComponent::getTextureSize()
|
||||
{
|
||||
if(mTexture)
|
||||
return mTexture->getSize();
|
||||
else
|
||||
return Vector2u(0, 0);
|
||||
}
|
||||
|
||||
ImageComponent::ImageComponent(Window* window, int offsetX, int offsetY, std::string path, unsigned int resizeWidth, unsigned int resizeHeight, bool allowUpscale) : GuiComponent(window)
|
||||
{
|
||||
mTextureID = 0;
|
||||
|
||||
setOffset(Vector2i(offsetX, offsetY));
|
||||
|
||||
//default origin is the center of image
|
||||
|
@ -35,120 +40,15 @@ ImageComponent::ImageComponent(Window* window, int offsetX, int offsetY, std::st
|
|||
|
||||
ImageComponent::~ImageComponent()
|
||||
{
|
||||
unloadImage();
|
||||
}
|
||||
|
||||
void ImageComponent::loadImage(std::string path)
|
||||
{
|
||||
//make sure the file *exists*
|
||||
if(!boost::filesystem::exists(path))
|
||||
{
|
||||
LOG(LogError) << "Image \"" << path << "\" not found!";
|
||||
return;
|
||||
}
|
||||
|
||||
//make sure we don't already have an image
|
||||
unloadImage();
|
||||
|
||||
|
||||
FREE_IMAGE_FORMAT format = FIF_UNKNOWN;
|
||||
FIBITMAP* image = NULL;
|
||||
BYTE* imageData = NULL;
|
||||
unsigned int width, height;
|
||||
|
||||
//detect the filetype
|
||||
format = FreeImage_GetFileType(path.c_str(), 0);
|
||||
if(format == FIF_UNKNOWN)
|
||||
format = FreeImage_GetFIFFromFilename(path.c_str());
|
||||
if(format == FIF_UNKNOWN)
|
||||
{
|
||||
LOG(LogError) << "Error - could not detect filetype for image \"" << path << "\"!";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//make sure we can read this filetype first, then load it
|
||||
if(FreeImage_FIFSupportsReading(format))
|
||||
{
|
||||
image = FreeImage_Load(format, path.c_str());
|
||||
}else{
|
||||
LOG(LogError) << "Error - file format reading not supported for image \"" << path << "\"!";
|
||||
return;
|
||||
}
|
||||
|
||||
//make sure it loaded properly
|
||||
if(!image)
|
||||
{
|
||||
LOG(LogError) << "Error loading image \"" << path << "\"!";
|
||||
return;
|
||||
}
|
||||
|
||||
//convert to 32bit
|
||||
FIBITMAP* imgConv = FreeImage_ConvertTo32Bits(image);
|
||||
FreeImage_Unload(image);
|
||||
image = imgConv;
|
||||
|
||||
//get a pointer to the image data as BGRA
|
||||
imageData = FreeImage_GetBits(image);
|
||||
if(!imageData)
|
||||
{
|
||||
LOG(LogError) << "Error retriving bits from image \"" << path << "\"!";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
width = FreeImage_GetWidth(image);
|
||||
height = FreeImage_GetHeight(image);
|
||||
|
||||
//if width or height are zero then something is clearly wrong
|
||||
if(!width || !height)
|
||||
{
|
||||
LOG(LogError) << "Width or height are zero for image \"" << path << "\"!";
|
||||
FreeImage_Unload(image);
|
||||
return;
|
||||
}
|
||||
|
||||
//convert from BGRA to RGBA
|
||||
GLubyte* imageRGBA = new GLubyte[4*width*height];
|
||||
for(unsigned int i = 0; i < width*height; i++)
|
||||
{
|
||||
imageRGBA[i*4+0] = imageData[i*4+2];
|
||||
imageRGBA[i*4+1] = imageData[i*4+1];
|
||||
imageRGBA[i*4+2] = imageData[i*4+0];
|
||||
imageRGBA[i*4+3] = imageData[i*4+3];
|
||||
}
|
||||
|
||||
|
||||
|
||||
//now for the openGL texture stuff
|
||||
glGenTextures(1, &mTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, mTextureID);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageRGBA);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
mTextureSize.x = width;
|
||||
mTextureSize.y = height;
|
||||
|
||||
//free the image data
|
||||
FreeImage_Unload(image);
|
||||
|
||||
//free the memory from that pointer
|
||||
delete[] imageRGBA;
|
||||
|
||||
resize();
|
||||
}
|
||||
|
||||
void ImageComponent::resize()
|
||||
{
|
||||
mSize.x = mTextureSize.x;
|
||||
mSize.y = mTextureSize.y;
|
||||
if(!mTexture)
|
||||
return;
|
||||
|
||||
mSize.x = getTextureSize().x;
|
||||
mSize.y = getTextureSize().y;
|
||||
|
||||
//(we don't resize tiled images)
|
||||
if(!mTiled && (mTargetSize.x || mTargetSize.y))
|
||||
|
@ -176,19 +76,7 @@ void ImageComponent::resize()
|
|||
}
|
||||
|
||||
if(mTiled)
|
||||
{
|
||||
mSize = mTargetSize;
|
||||
}
|
||||
}
|
||||
|
||||
void ImageComponent::unloadImage()
|
||||
{
|
||||
if(mTextureID)
|
||||
{
|
||||
glDeleteTextures(1, &mTextureID);
|
||||
|
||||
mTextureID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ImageComponent::setImage(std::string path)
|
||||
|
@ -198,10 +86,12 @@ void ImageComponent::setImage(std::string path)
|
|||
|
||||
mPath = path;
|
||||
|
||||
unloadImage();
|
||||
if(!path.empty())
|
||||
loadImage(path);
|
||||
if(mPath.empty() || !mWindow->getResourceManager()->fileExists(mPath))
|
||||
mTexture.reset();
|
||||
else
|
||||
mTexture = TextureResource::get(*mWindow->getResourceManager(), mPath);
|
||||
|
||||
resize();
|
||||
}
|
||||
|
||||
void ImageComponent::setOrigin(float originX, float originY)
|
||||
|
@ -240,15 +130,15 @@ void ImageComponent::setFlipY(bool flip)
|
|||
|
||||
void ImageComponent::onRender()
|
||||
{
|
||||
if(mTextureID && getOpacity() > 0)
|
||||
if(mTexture && getOpacity() > 0)
|
||||
{
|
||||
GLfloat points[12], texs[12];
|
||||
GLubyte colors[6*4];
|
||||
|
||||
if(mTiled)
|
||||
{
|
||||
float xCount = (float)mSize.x / mTextureSize.x;
|
||||
float yCount = (float)mSize.y / mTextureSize.y;
|
||||
float xCount = (float)mSize.x / getTextureSize().x;
|
||||
float yCount = (float)mSize.y / getTextureSize().y;
|
||||
|
||||
Renderer::buildGLColorArray(colors, 0xFFFFFF00 | (getOpacity()), 6);
|
||||
buildImageArray(0, 0, points, texs, xCount, yCount);
|
||||
|
@ -303,7 +193,8 @@ void ImageComponent::buildImageArray(int posX, int posY, GLfloat* points, GLfloa
|
|||
|
||||
void ImageComponent::drawImageArray(GLfloat* points, GLfloat* texs, GLubyte* colors, unsigned int numArrays)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, mTextureID);
|
||||
mTexture->bind();
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
@ -332,21 +223,6 @@ void ImageComponent::drawImageArray(GLfloat* points, GLfloat* texs, GLubyte* col
|
|||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void ImageComponent::init()
|
||||
{
|
||||
if(!mPath.empty())
|
||||
loadImage(mPath);
|
||||
|
||||
GuiComponent::init();
|
||||
}
|
||||
|
||||
void ImageComponent::deinit()
|
||||
{
|
||||
unloadImage();
|
||||
|
||||
GuiComponent::deinit();
|
||||
}
|
||||
|
||||
bool ImageComponent::hasImage()
|
||||
{
|
||||
return !mPath.empty();
|
||||
|
@ -355,32 +231,10 @@ bool ImageComponent::hasImage()
|
|||
|
||||
void ImageComponent::copyScreen()
|
||||
{
|
||||
unloadImage();
|
||||
|
||||
int width = Renderer::getScreenWidth();
|
||||
int height = Renderer::getScreenHeight();
|
||||
mTexture.reset();
|
||||
|
||||
//glReadBuffer(GL_FRONT);
|
||||
|
||||
/*char* data = new char[width*height*3];
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, data);*/
|
||||
|
||||
glGenTextures(1, &mTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, mTextureID);
|
||||
|
||||
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
|
||||
//delete[] data;
|
||||
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, width, height, 0);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
mTextureSize.x = height;
|
||||
mTextureSize.y = height;
|
||||
mTexture = TextureResource::get(*mWindow->getResourceManager(), "");
|
||||
mTexture->initFromScreen();
|
||||
|
||||
resize();
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
#include "../GuiComponent.h"
|
||||
#include <string>
|
||||
#include <FreeImage.h>
|
||||
|
||||
#include <memory>
|
||||
#include "../resources/TextureResource.h"
|
||||
|
||||
class ImageComponent : public GuiComponent
|
||||
{
|
||||
|
@ -18,8 +18,7 @@ public:
|
|||
ImageComponent(Window* window, int offsetX = 0, int offsetY = 0, std::string path = "", unsigned int maxWidth = 0, unsigned int maxHeight = 0, bool allowUpscale = false);
|
||||
virtual ~ImageComponent();
|
||||
|
||||
//Copy the entire screen into a texture for us to use.
|
||||
void copyScreen();
|
||||
void copyScreen(); //Copy the entire screen into a texture for us to use.
|
||||
void setImage(std::string path); //Loads the image at the given filepath.
|
||||
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); //Enables or disables tiling. Must be called before loading an image or resizing will be weird.
|
||||
|
@ -31,32 +30,24 @@ public:
|
|||
//You can get the rendered size of the ImageComponent with getSize().
|
||||
Vector2u getTextureSize();
|
||||
|
||||
|
||||
bool hasImage();
|
||||
|
||||
//Image textures will be deleted on renderer deinitialization, and recreated on reinitialization (if mPath is not empty).
|
||||
void init();
|
||||
void deinit();
|
||||
|
||||
protected:
|
||||
void onRender();
|
||||
|
||||
private:
|
||||
Vector2u mTargetSize;
|
||||
Vector2u mTextureSize;
|
||||
Vector2f mOrigin;
|
||||
|
||||
bool mAllowUpscale, mTiled, mFlipX, mFlipY;
|
||||
|
||||
void loadImage(std::string path);
|
||||
void resize();
|
||||
void buildImageArray(int x, int y, GLfloat* points, GLfloat* texs, float percentageX = 1, float percentageY = 1); //writes 12 GLfloat points and 12 GLfloat texture coordinates to a given array at a given position
|
||||
void drawImageArray(GLfloat* points, GLfloat* texs, GLubyte* colors, unsigned int count = 6); //draws the given set of points and texture coordinates, number of coordinate pairs may be specified (default 6)
|
||||
void unloadImage();
|
||||
|
||||
std::string mPath;
|
||||
|
||||
GLuint mTextureID;
|
||||
std::shared_ptr<TextureResource> mTexture;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#include "SwitchComponent.h"
|
||||
#include "../Renderer.h"
|
||||
#include "../Font.h"
|
||||
#include "../Window.h"
|
||||
|
||||
SwitchComponent::SwitchComponent(Window* window, bool state) : GuiComponent(window), mState(state)
|
||||
{
|
||||
//mSize = Vector2u((unsigned int)(Renderer::getScreenWidth() * 0.05),
|
||||
// (unsigned int)(Renderer::getScreenHeight() * 0.05));
|
||||
|
||||
Renderer::getDefaultFont(Renderer::MEDIUM)->sizeText("OFF", (int*)&mSize.x, (int*)&mSize.y);
|
||||
Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM)->sizeText("OFF", (int*)&mSize.x, (int*)&mSize.y);
|
||||
}
|
||||
|
||||
bool SwitchComponent::input(InputConfig* config, Input input)
|
||||
|
@ -25,7 +26,7 @@ void SwitchComponent::onRender()
|
|||
{
|
||||
Renderer::pushClipRect(getGlobalOffset(), getSize());
|
||||
|
||||
Renderer::drawText(mState ? "ON" : "OFF", 0, 0, mState ? 0x00FF00FF : 0xFF0000FF, Renderer::getDefaultFont(Renderer::MEDIUM));
|
||||
Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM)->drawText(mState ? "ON" : "OFF", 0, 0, mState ? 0x00FF00FF : 0xFF0000FF);
|
||||
|
||||
Renderer::popClipRect();
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#include "TextComponent.h"
|
||||
#include "../Renderer.h"
|
||||
#include "../Log.h"
|
||||
#include "../Window.h"
|
||||
|
||||
TextComponent::TextComponent(Window* window) : GuiComponent(window),
|
||||
mFont(NULL), mColor(0x000000FF), mAutoCalcExtent(true, true)
|
||||
{
|
||||
}
|
||||
|
||||
TextComponent::TextComponent(Window* window, const std::string& text, Font* font, Vector2i pos, Vector2u size) : GuiComponent(window),
|
||||
TextComponent::TextComponent(Window* window, const std::string& text, std::shared_ptr<Font> font, Vector2i pos, Vector2u size) : GuiComponent(window),
|
||||
mFont(NULL), mColor(0x000000FF), mAutoCalcExtent(true, true)
|
||||
{
|
||||
setText(text);
|
||||
|
@ -28,7 +29,7 @@ void TextComponent::setExtent(Vector2u size)
|
|||
calculateExtent();
|
||||
}
|
||||
|
||||
void TextComponent::setFont(Font* font)
|
||||
void TextComponent::setFont(std::shared_ptr<Font> font)
|
||||
{
|
||||
mFont = font;
|
||||
|
||||
|
@ -47,23 +48,21 @@ void TextComponent::setText(const std::string& text)
|
|||
calculateExtent();
|
||||
}
|
||||
|
||||
Font* TextComponent::getFont() const
|
||||
std::shared_ptr<Font> TextComponent::getFont() const
|
||||
{
|
||||
return (mFont ? mFont : Renderer::getDefaultFont(Renderer::MEDIUM));;
|
||||
if(mFont)
|
||||
return mFont;
|
||||
else
|
||||
return Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM);
|
||||
}
|
||||
|
||||
void TextComponent::onRender()
|
||||
{
|
||||
Font* font = getFont();
|
||||
if(font == NULL)
|
||||
{
|
||||
LOG(LogError) << "TextComponent can't get a valid font!";
|
||||
return;
|
||||
}
|
||||
std::shared_ptr<Font> font = getFont();
|
||||
|
||||
//Renderer::pushClipRect(getGlobalOffset(), getSize());
|
||||
|
||||
Renderer::drawWrappedText(mText, 0, 0, mSize.x, mColor >> 8 << 8 | getOpacity(), font);
|
||||
font->drawWrappedText(mText, 0, 0, mSize.x, mColor >> 8 << 8 | getOpacity());
|
||||
|
||||
//Renderer::popClipRect();
|
||||
|
||||
|
@ -72,16 +71,11 @@ void TextComponent::onRender()
|
|||
|
||||
void TextComponent::calculateExtent()
|
||||
{
|
||||
Font* font = getFont();
|
||||
if(font == NULL)
|
||||
{
|
||||
LOG(LogError) << "TextComponent can't get a valid font!";
|
||||
return;
|
||||
}
|
||||
std::shared_ptr<Font> font = getFont();
|
||||
|
||||
if(mAutoCalcExtent.x)
|
||||
font->sizeText(mText, (int*)&mSize.x, (int*)&mSize.y);
|
||||
else
|
||||
if(mAutoCalcExtent.y)
|
||||
Renderer::sizeWrappedText(mText, getSize().x, mFont, NULL, (int*)&mSize.y);
|
||||
font->sizeWrappedText(mText, getSize().x, NULL, (int*)&mSize.y);
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@ class TextComponent : public GuiComponent
|
|||
{
|
||||
public:
|
||||
TextComponent(Window* window);
|
||||
TextComponent(Window* window, const std::string& text, Font* font, Vector2i pos, Vector2u size);
|
||||
TextComponent(Window* window, const std::string& text, std::shared_ptr<Font> font, Vector2i pos, Vector2u size);
|
||||
|
||||
void setFont(Font* font);
|
||||
void setFont(std::shared_ptr<Font> font);
|
||||
void setBox(Vector2i pos, Vector2u size);
|
||||
void setExtent(Vector2u size); //Use Vector2u(0, 0) to automatically generate extent on a single line. Use Vector2(value, 0) to automatically generate extent for wrapped text.
|
||||
void setText(const std::string& text);
|
||||
|
@ -19,12 +19,12 @@ public:
|
|||
void onRender() override;
|
||||
|
||||
private:
|
||||
Font* getFont() const;
|
||||
std::shared_ptr<Font> getFont() const;
|
||||
|
||||
void calculateExtent();
|
||||
|
||||
unsigned int mColor;
|
||||
Font* mFont;
|
||||
std::shared_ptr<Font> mFont;
|
||||
Vector2<bool> mAutoCalcExtent;
|
||||
std::string mText;
|
||||
};
|
||||
|
|
|
@ -19,7 +19,7 @@ template <typename T>
|
|||
class TextListComponent : public GuiComponent
|
||||
{
|
||||
public:
|
||||
TextListComponent(Window* window, int offsetX, int offsetY, Font* font);
|
||||
TextListComponent(Window* window, int offsetX, int offsetY, std::shared_ptr<Font> font);
|
||||
virtual ~TextListComponent();
|
||||
|
||||
bool input(InputConfig* config, Input input);
|
||||
|
@ -44,7 +44,7 @@ public:
|
|||
T getObject(int i);
|
||||
void setSelection(int i);
|
||||
|
||||
void setFont(Font* f);
|
||||
void setFont(std::shared_ptr<Font> f);
|
||||
|
||||
protected:
|
||||
void onRender();
|
||||
|
@ -62,7 +62,7 @@ private:
|
|||
int mMarqueeOffset;
|
||||
int mMarqueeTime;
|
||||
|
||||
Font* mFont;
|
||||
std::shared_ptr<Font> mFont;
|
||||
unsigned int mSelectorColor, mSelectedTextColorOverride;
|
||||
bool mDrawCentered;
|
||||
|
||||
|
@ -81,7 +81,7 @@ private:
|
|||
};
|
||||
|
||||
template <typename T>
|
||||
TextListComponent<T>::TextListComponent(Window* window, int offsetX, int offsetY, Font* font) : GuiComponent(window)
|
||||
TextListComponent<T>::TextListComponent(Window* window, int offsetX, int offsetY, std::shared_ptr<Font> font) : GuiComponent(window)
|
||||
{
|
||||
mSelection = 0;
|
||||
mScrollDir = 0;
|
||||
|
@ -132,7 +132,7 @@ void TextListComponent<T>::onRender()
|
|||
|
||||
if(mRowVector.size() == 0)
|
||||
{
|
||||
Renderer::drawCenteredText("The list is empty.", 0, y, 0xFF0000FF, mFont);
|
||||
mFont->drawCenteredText("The list is empty.", 0, y, 0xFF0000FF);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -156,9 +156,9 @@ void TextListComponent<T>::onRender()
|
|||
unsigned int color = (mSelection == i && mSelectedTextColorOverride != 0) ? mSelectedTextColorOverride : row.color;
|
||||
|
||||
if(mDrawCentered)
|
||||
Renderer::drawCenteredText(row.name, x, y, color, mFont);
|
||||
mFont->drawCenteredText(row.name, x, y, color);
|
||||
else
|
||||
Renderer::drawText(row.name, x, y, color, mFont);
|
||||
mFont->drawText(row.name, x, y, color);
|
||||
|
||||
y += entrySize;
|
||||
}
|
||||
|
@ -202,7 +202,6 @@ bool TextListComponent<T>::input(InputConfig* config, Input input)
|
|||
return true;
|
||||
}
|
||||
}else{
|
||||
//if((button == InputManager::DOWN && mScrollDir > 0) || (button == InputManager::PAGEDOWN && mScrollDir > 0) || (button == InputManager::UP && mScrollDir < 0) || (button == InputManager::PAGEUP && mScrollDir < 0))
|
||||
if(config->isMappedTo("down", input) || config->isMappedTo("up", input) || config->isMappedTo("pagedown", input) || config->isMappedTo("pageup", input))
|
||||
{
|
||||
stopScrolling();
|
||||
|
@ -397,7 +396,7 @@ void TextListComponent<T>::setScrollSound(std::shared_ptr<Sound> & sound)
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void TextListComponent<T>::setFont(Font* font)
|
||||
void TextListComponent<T>::setFont(std::shared_ptr<Font> font)
|
||||
{
|
||||
mFont = font;
|
||||
}
|
||||
|
|
|
@ -35,28 +35,28 @@ std::string ThemeComponent::getString(std::string name)
|
|||
|
||||
GuiBoxData ThemeComponent::getBoxData() { return mBoxData; }
|
||||
|
||||
Font* ThemeComponent::getListFont()
|
||||
std::shared_ptr<Font> ThemeComponent::getListFont()
|
||||
{
|
||||
if(mListFont == NULL)
|
||||
return Renderer::getDefaultFont(Renderer::MEDIUM);
|
||||
else
|
||||
if(mListFont)
|
||||
return mListFont;
|
||||
}
|
||||
|
||||
Font* ThemeComponent::getDescriptionFont()
|
||||
{
|
||||
if(mDescFont == NULL)
|
||||
return Renderer::getDefaultFont(Renderer::SMALL);
|
||||
else
|
||||
return mDescFont;
|
||||
return Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM);
|
||||
}
|
||||
|
||||
Font* ThemeComponent::getFastSelectFont()
|
||||
std::shared_ptr<Font> ThemeComponent::getDescriptionFont()
|
||||
{
|
||||
if(mDescFont)
|
||||
return mDescFont;
|
||||
else
|
||||
return Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_SMALL);
|
||||
}
|
||||
|
||||
std::shared_ptr<Font> ThemeComponent::getFastSelectFont()
|
||||
{
|
||||
if(mFastSelectFont == NULL)
|
||||
return Renderer::getDefaultFont(Renderer::LARGE);
|
||||
else
|
||||
return mFastSelectFont;
|
||||
else
|
||||
return Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_LARGE);
|
||||
}
|
||||
|
||||
ThemeComponent::ThemeComponent(Window* window) : GuiComponent(window)
|
||||
|
@ -72,9 +72,9 @@ ThemeComponent::ThemeComponent(Window* window) : GuiComponent(window)
|
|||
AudioManager::getInstance()->registerSound(mSoundMap["menuBack"]);
|
||||
AudioManager::getInstance()->registerSound(mSoundMap["menuOpen"]);
|
||||
|
||||
mListFont = NULL;
|
||||
mDescFont = NULL;
|
||||
mFastSelectFont = NULL;
|
||||
mListFont.reset();
|
||||
mDescFont.reset();
|
||||
mFastSelectFont.reset();
|
||||
|
||||
setDefaults();
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ void ThemeComponent::setDefaults()
|
|||
mFloatMap["gameImageOriginX"] = 0.5;
|
||||
mFloatMap["gameImageOriginY"] = 0;
|
||||
mFloatMap["gameImageOffsetX"] = mFloatMap["listOffsetX"] / 2;
|
||||
mFloatMap["gameImageOffsetY"] = (float)Renderer::getDefaultFont(Renderer::LARGE)->getHeight() / (float)Renderer::getScreenHeight();
|
||||
mFloatMap["gameImageOffsetY"] = (float)FONT_SIZE_LARGE / (float)Renderer::getScreenHeight();
|
||||
mFloatMap["gameImageWidth"] = mFloatMap["listOffsetX"];
|
||||
mFloatMap["gameImageHeight"] = 0;
|
||||
|
||||
|
@ -121,22 +121,9 @@ void ThemeComponent::setDefaults()
|
|||
mBoxData.verticalTiled = false;
|
||||
mBoxData.cornerPath = "";
|
||||
|
||||
if(mListFont != NULL)
|
||||
{
|
||||
delete mListFont;
|
||||
mListFont = NULL;
|
||||
}
|
||||
|
||||
if(mDescFont != NULL)
|
||||
{
|
||||
delete mDescFont;
|
||||
mDescFont = NULL;
|
||||
}
|
||||
if(mFastSelectFont != NULL)
|
||||
{
|
||||
delete mFastSelectFont;
|
||||
mFastSelectFont = NULL;
|
||||
}
|
||||
mListFont.reset();
|
||||
mDescFont.reset();
|
||||
mFastSelectFont.reset();
|
||||
}
|
||||
|
||||
void ThemeComponent::deleteComponents()
|
||||
|
@ -148,12 +135,10 @@ void ThemeComponent::deleteComponents()
|
|||
|
||||
clearChildren();
|
||||
|
||||
//deletes fonts if any were created
|
||||
setDefaults();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ThemeComponent::readXML(std::string path, bool detailed)
|
||||
{
|
||||
if(mPath == path)
|
||||
|
@ -248,9 +233,9 @@ void ThemeComponent::readXML(std::string path, bool detailed)
|
|||
mSoundMap["menuOpen"]->loadFile(expandPath(root.child("menuOpenSound").text().get()));
|
||||
|
||||
//fonts
|
||||
mListFont = resolveFont(root.child("listFont"), Font::getDefaultPath(), Renderer::getDefaultFont(Renderer::MEDIUM)->getSize());
|
||||
mDescFont = resolveFont(root.child("descriptionFont"), Font::getDefaultPath(), Renderer::getDefaultFont(Renderer::SMALL)->getSize());
|
||||
mFastSelectFont = resolveFont(root.child("fastSelectFont"), Font::getDefaultPath(), Renderer::getDefaultFont(Renderer::LARGE)->getSize());
|
||||
mListFont = resolveFont(root.child("listFont"), Font::getDefaultPath(), FONT_SIZE_MEDIUM);
|
||||
mDescFont = resolveFont(root.child("descriptionFont"), Font::getDefaultPath(), FONT_SIZE_SMALL);
|
||||
mFastSelectFont = resolveFont(root.child("fastSelectFont"), Font::getDefaultPath(), FONT_SIZE_LARGE);
|
||||
|
||||
//actually read the components
|
||||
createComponentChildren(root, this);
|
||||
|
@ -348,7 +333,7 @@ float ThemeComponent::resolveExp(std::string str, float defaultVal)
|
|||
exp.setExpression(str);
|
||||
|
||||
//set variables
|
||||
exp.setVariable("headerHeight", (float)(Renderer::getDefaultFont(Renderer::LARGE)->getHeight() / Renderer::getScreenHeight()));
|
||||
exp.setVariable("headerHeight", (float)(FONT_SIZE_LARGE / Renderer::getScreenHeight()));
|
||||
exp.setVariable("infoWidth", mFloatMap["listOffsetX"]);
|
||||
|
||||
return exp.eval();
|
||||
|
@ -407,7 +392,7 @@ float ThemeComponent::strToFloat(std::string str, float defaultVal)
|
|||
return ret;
|
||||
}
|
||||
|
||||
Font* ThemeComponent::resolveFont(pugi::xml_node node, std::string defaultPath, unsigned int defaultSize)
|
||||
std::shared_ptr<Font> ThemeComponent::resolveFont(pugi::xml_node node, std::string defaultPath, unsigned int defaultSize)
|
||||
{
|
||||
if(!node)
|
||||
return NULL;
|
||||
|
@ -425,25 +410,5 @@ Font* ThemeComponent::resolveFont(pugi::xml_node node, std::string defaultPath,
|
|||
size = defaultSize;
|
||||
}
|
||||
|
||||
return new Font(path, size);
|
||||
}
|
||||
|
||||
void ThemeComponent::init()
|
||||
{
|
||||
//fonts are special
|
||||
if(mListFont) mListFont->init();
|
||||
if(mDescFont) mDescFont->init();
|
||||
if(mFastSelectFont) mFastSelectFont->init();
|
||||
|
||||
GuiComponent::init();
|
||||
}
|
||||
|
||||
void ThemeComponent::deinit()
|
||||
{
|
||||
GuiComponent::deinit();
|
||||
|
||||
//fonts are special
|
||||
if(mListFont) mListFont->deinit();
|
||||
if(mDescFont) mDescFont->deinit();
|
||||
if(mFastSelectFont) mFastSelectFont->deinit();
|
||||
return Font::get(*mWindow->getResourceManager(), path, size);
|
||||
}
|
||||
|
|
|
@ -20,18 +20,15 @@ public:
|
|||
|
||||
GuiBoxData getBoxData();
|
||||
|
||||
void init();
|
||||
void deinit();
|
||||
|
||||
unsigned int getColor(std::string name);
|
||||
bool getBool(std::string name);
|
||||
float getFloat(std::string name);
|
||||
std::shared_ptr<Sound> & getSound(std::string name);
|
||||
std::string getString(std::string name);
|
||||
|
||||
Font* getListFont();
|
||||
Font* getDescriptionFont();
|
||||
Font* getFastSelectFont();
|
||||
std::shared_ptr<Font> getListFont();
|
||||
std::shared_ptr<Font> getDescriptionFont();
|
||||
std::shared_ptr<Font> getFastSelectFont();
|
||||
|
||||
private:
|
||||
void setDefaults();
|
||||
|
@ -45,7 +42,7 @@ private:
|
|||
unsigned int resolveColor(std::string str, unsigned int defaultColor = 0x000000FF);
|
||||
void splitString(std::string str, char delim, std::string* before, std::string* after);
|
||||
float strToFloat(std::string str, float defaultVal = 0.0f);
|
||||
Font* resolveFont(pugi::xml_node node, std::string defaultPath, unsigned int defaultSize);
|
||||
std::shared_ptr<Font> resolveFont(pugi::xml_node node, std::string defaultPath, unsigned int defaultSize);
|
||||
|
||||
std::string mPath;
|
||||
|
||||
|
@ -56,10 +53,10 @@ private:
|
|||
std::map<std::string, std::string> mStringMap;
|
||||
|
||||
GuiBoxData mBoxData;
|
||||
|
||||
Font* mListFont;
|
||||
Font* mDescFont;
|
||||
Font* mFastSelectFont;
|
||||
|
||||
std::shared_ptr<Font> mListFont;
|
||||
std::shared_ptr<Font> mDescFont;
|
||||
std::shared_ptr<Font> mFastSelectFont;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <bcm_host.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
@ -210,7 +211,7 @@ int main(int argc, char* argv[])
|
|||
nrOfFrames = 0;
|
||||
timeElapsed = 0;
|
||||
}
|
||||
Renderer::drawText(fpsString, 50, 50, 0x00FF00FF, Renderer::getDefaultFont(Renderer::MEDIUM));
|
||||
Font::get(*window.getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM)->drawText(fpsString, 50, 50, 0x00FF00FF);
|
||||
}
|
||||
|
||||
//sleep if we're past our threshold
|
||||
|
|
120
src/resources/ResourceManager.cpp
Normal file
120
src/resources/ResourceManager.cpp
Normal file
|
@ -0,0 +1,120 @@
|
|||
#include "ResourceManager.h"
|
||||
#include "../Log.h"
|
||||
#include <fstream>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
auto array_deleter = [](unsigned char* p) { delete[] p; };
|
||||
auto nop_deleter = [](unsigned char* p) { };
|
||||
|
||||
|
||||
//from ES_logo_16.cpp
|
||||
extern const size_t es_logo_16_data_len;
|
||||
extern const unsigned char es_logo_16_data[];
|
||||
|
||||
//from ES_logo_32.cpp
|
||||
extern const size_t es_logo_32_data_len;
|
||||
extern const unsigned char es_logo_32_data[];
|
||||
|
||||
struct EmbeddedResource
|
||||
{
|
||||
const char* internal_path;
|
||||
ResourceData resourceData;
|
||||
};
|
||||
|
||||
static const int embedded_resource_count = 2;
|
||||
static const EmbeddedResource embedded_resources[embedded_resource_count] = {
|
||||
{ "internal://es_logo_16.png", {std::shared_ptr<unsigned char>((unsigned char*)es_logo_16_data, nop_deleter), es_logo_16_data_len} },
|
||||
{ "internal://es_logo_32.png", {std::shared_ptr<unsigned char>((unsigned char*)es_logo_32_data, nop_deleter), es_logo_32_data_len} }
|
||||
};
|
||||
|
||||
|
||||
const ResourceData ResourceManager::getFileData(const std::string& path) const
|
||||
{
|
||||
for(int i = 0; i < embedded_resource_count; i++)
|
||||
{
|
||||
if(strcmp(embedded_resources[i].internal_path, path.c_str()) == 0)
|
||||
{
|
||||
//this embedded resource matches the filepath; use it
|
||||
return embedded_resources[i].resourceData;
|
||||
}
|
||||
}
|
||||
|
||||
//it's not embedded; load the file
|
||||
if(!fs::exists(path))
|
||||
{
|
||||
//if the file doesn't exist, return an "empty" ResourceData
|
||||
ResourceData data = {NULL, 0};
|
||||
return data;
|
||||
}else{
|
||||
ResourceData data = loadFile(path);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
ResourceData ResourceManager::loadFile(const std::string& path) const
|
||||
{
|
||||
std::ifstream stream(path, std::ios::binary);
|
||||
|
||||
stream.seekg(0, stream.end);
|
||||
size_t size = (size_t)stream.tellg();
|
||||
stream.seekg(0, stream.beg);
|
||||
|
||||
//supply custom deleter to properly free array
|
||||
std::shared_ptr<unsigned char> data(new unsigned char[size], array_deleter);
|
||||
stream.read((char*)data.get(), size);
|
||||
stream.close();
|
||||
|
||||
ResourceData ret = {data, size};
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ResourceManager::fileExists(const std::string& path) const
|
||||
{
|
||||
for(int i = 0; i < embedded_resource_count; i++)
|
||||
{
|
||||
if(strcmp(embedded_resources[i].internal_path, path.c_str()) == 0)
|
||||
{
|
||||
//this embedded resource matches the filepath
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return fs::exists(path);
|
||||
}
|
||||
|
||||
void ResourceManager::unloadAll()
|
||||
{
|
||||
auto iter = mReloadables.begin();
|
||||
while(iter != mReloadables.end())
|
||||
{
|
||||
if(!iter->expired())
|
||||
{
|
||||
iter->lock()->unload(*this);
|
||||
iter++;
|
||||
}else{
|
||||
mReloadables.erase(iter++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceManager::reloadAll()
|
||||
{
|
||||
auto iter = mReloadables.begin();
|
||||
while(iter != mReloadables.end())
|
||||
{
|
||||
if(!iter->expired())
|
||||
{
|
||||
iter->lock()->reload(*this);
|
||||
iter++;
|
||||
}else{
|
||||
mReloadables.erase(iter++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceManager::addReloadable(std::weak_ptr<IReloadable> reloadable)
|
||||
{
|
||||
mReloadables.push_back(reloadable);
|
||||
}
|
42
src/resources/ResourceManager.h
Normal file
42
src/resources/ResourceManager.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
//The ResourceManager exists to...
|
||||
//Allow loading resources embedded into the executable like an actual file.
|
||||
//Allow embedded resources to be optionally remapped to actual files for further customization.
|
||||
|
||||
struct ResourceData
|
||||
{
|
||||
const std::shared_ptr<unsigned char> ptr;
|
||||
const size_t length;
|
||||
};
|
||||
|
||||
class ResourceManager;
|
||||
|
||||
class IReloadable
|
||||
{
|
||||
public:
|
||||
virtual void unload(const ResourceManager& rm) = 0;
|
||||
virtual void reload(const ResourceManager& rm) = 0;
|
||||
};
|
||||
|
||||
class ResourceManager
|
||||
{
|
||||
public:
|
||||
void addReloadable(std::weak_ptr<IReloadable> reloadable);
|
||||
|
||||
void unloadAll();
|
||||
void reloadAll();
|
||||
|
||||
const ResourceData getFileData(const std::string& path) const;
|
||||
bool fileExists(const std::string& path) const;
|
||||
|
||||
private:
|
||||
ResourceData loadFile(const std::string& path) const;
|
||||
|
||||
std::list< std::weak_ptr<IReloadable> > mReloadables;
|
||||
};
|
124
src/resources/TextureResource.cpp
Normal file
124
src/resources/TextureResource.cpp
Normal file
|
@ -0,0 +1,124 @@
|
|||
#include "TextureResource.h"
|
||||
#include "../Log.h"
|
||||
#include "../platform.h"
|
||||
#include GLHEADER
|
||||
#include "../ImageIO.h"
|
||||
#include "../Renderer.h"
|
||||
|
||||
std::map< std::string, std::weak_ptr<TextureResource> > TextureResource::sTextureMap;
|
||||
|
||||
TextureResource::TextureResource(const ResourceManager& rm, const std::string& path) : mTextureID(0), mPath(path)
|
||||
{
|
||||
reload(rm);
|
||||
}
|
||||
|
||||
TextureResource::~TextureResource()
|
||||
{
|
||||
deinit();
|
||||
}
|
||||
|
||||
void TextureResource::unload(const ResourceManager& rm)
|
||||
{
|
||||
deinit();
|
||||
}
|
||||
|
||||
void TextureResource::reload(const ResourceManager& rm)
|
||||
{
|
||||
if(!mPath.empty())
|
||||
initFromResource(rm.getFileData(mPath));
|
||||
}
|
||||
|
||||
void TextureResource::initFromResource(const ResourceData data)
|
||||
{
|
||||
//make sure we aren't going to leak an old texture
|
||||
deinit();
|
||||
|
||||
size_t width, height;
|
||||
std::vector<unsigned char> imageRGBA = ImageIO::loadFromMemoryRGBA32(const_cast<unsigned char*>(data.ptr.get()), data.length, width, height);
|
||||
|
||||
if(imageRGBA.size() == 0)
|
||||
{
|
||||
LOG(LogError) << "Could not initialize texture (invalid resource data)!";
|
||||
return;
|
||||
}
|
||||
|
||||
//now for the openGL texture stuff
|
||||
glGenTextures(1, &mTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, mTextureID);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageRGBA.data());
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
mTextureSize.x = width;
|
||||
mTextureSize.y = height;
|
||||
}
|
||||
|
||||
void TextureResource::initFromScreen()
|
||||
{
|
||||
deinit();
|
||||
|
||||
int width = Renderer::getScreenWidth();
|
||||
int height = Renderer::getScreenHeight();
|
||||
|
||||
glGenTextures(1, &mTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, mTextureID);
|
||||
|
||||
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, width, height, 0);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
mTextureSize.x = height;
|
||||
mTextureSize.y = height;
|
||||
}
|
||||
|
||||
void TextureResource::deinit()
|
||||
{
|
||||
if(mTextureID != 0)
|
||||
{
|
||||
glDeleteTextures(1, &mTextureID);
|
||||
mTextureID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Vector2u TextureResource::getSize() const
|
||||
{
|
||||
return mTextureSize;
|
||||
}
|
||||
|
||||
void TextureResource::bind() const
|
||||
{
|
||||
if(mTextureID != 0)
|
||||
glBindTexture(GL_TEXTURE_2D, mTextureID);
|
||||
else
|
||||
LOG(LogError) << "Tried to bind uninitialized texture!";
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<TextureResource> TextureResource::get(ResourceManager& rm, const std::string& path)
|
||||
{
|
||||
if(path.empty())
|
||||
return std::shared_ptr<TextureResource>(new TextureResource(rm, path));
|
||||
|
||||
auto foundTexture = sTextureMap.find(path);
|
||||
if(foundTexture != sTextureMap.end())
|
||||
{
|
||||
if(!foundTexture->second.expired())
|
||||
{
|
||||
return foundTexture->second.lock();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<TextureResource> tex = std::shared_ptr<TextureResource>(new TextureResource(rm, path));
|
||||
sTextureMap[path] = std::weak_ptr<TextureResource>(tex);
|
||||
rm.addReloadable(tex);
|
||||
return tex;
|
||||
}
|
37
src/resources/TextureResource.h
Normal file
37
src/resources/TextureResource.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include "ResourceManager.h"
|
||||
|
||||
#include <string>
|
||||
#include "../Vector2.h"
|
||||
#include "../platform.h"
|
||||
#include GLHEADER
|
||||
|
||||
class TextureResource : public IReloadable
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<TextureResource> get(ResourceManager& rm, const std::string& path);
|
||||
|
||||
virtual ~TextureResource();
|
||||
|
||||
void unload(const ResourceManager& rm) override;
|
||||
void reload(const ResourceManager& rm) override;
|
||||
|
||||
Vector2u getSize() const;
|
||||
void bind() const;
|
||||
|
||||
void initFromScreen();
|
||||
|
||||
private:
|
||||
TextureResource(const ResourceManager& rm, const std::string& path);
|
||||
|
||||
void initFromPath();
|
||||
void initFromResource(const ResourceData data);
|
||||
void deinit();
|
||||
|
||||
Vector2u mTextureSize;
|
||||
GLuint mTextureID;
|
||||
const std::string mPath;
|
||||
|
||||
static std::map< std::string, std::weak_ptr<TextureResource> > sTextureMap;
|
||||
};
|
Loading…
Reference in a new issue