Moved to class-individualized static gets for resources.

See issue #95 for discussion.
This commit is contained in:
Aloshi 2013-07-09 00:44:24 -05:00
parent c99324060b
commit c8900f4099
20 changed files with 246 additions and 178 deletions

View file

@ -151,7 +151,6 @@ set(ES_HEADERS
${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/Resource.h
${CMAKE_CURRENT_SOURCE_DIR}/src/resources/TextureResource.h
${CMAKE_CURRENT_SOURCE_DIR}/data/Resources.h
)
@ -193,7 +192,6 @@ set(ES_SOURCES
${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/Resource.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

View file

@ -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,8 +71,9 @@ void Font::initLibrary()
}
}
Font::Font(int size) : fontScale(1.0f), mSize(size)
Font::Font(const ResourceManager& rm, const std::string& path, int size) : fontScale(1.0f), mSize(size), mPath(path)
{
reload(rm);
}
Font::~Font()
@ -78,6 +81,38 @@ 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)
@ -96,7 +131,7 @@ void Font::deinit()
void Font::buildAtlas(ResourceData data)
{
if(FT_New_Memory_Face(sLibrary, data.ptr, data.length, 0, &face))
if(FT_New_Memory_Face(sLibrary, data.ptr.get(), data.length, 0, &face))
{
LOG(LogError) << "Error creating font face!";
return;
@ -206,9 +241,8 @@ void Font::buildAtlas(ResourceData data)
mSize = (int)(mSize * (1.0f / fontScale));
deinit();
init(data);
}
else {
//LOG(LogInfo) << "Created font with size " << mSize << ".";
}else{
LOG(LogInfo) << "Created font with size " << mSize << ".";
}
}

View file

@ -7,7 +7,7 @@
#include <ft2build.h>
#include FT_FREETYPE_H
#include "Vector2.h"
#include "resources/Resource.h"
#include "resources/ResourceManager.h"
class TextCache;
@ -17,12 +17,13 @@ class TextCache;
//A TrueType Font renderer that uses FreeType and OpenGL.
//The library is automatically initialized when it's needed.
class Font : public Resource
class Font : public IReloadable
{
public:
static void initLibrary();
Font(int size);
static std::shared_ptr<Font> get(ResourceManager& rm, const std::string& path, int size);
~Font();
FT_Face face;
@ -55,12 +56,11 @@ public:
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(ResourceData data) override;
void deinit() override;
void unload(const ResourceManager& rm) override;
void reload(const ResourceManager& rm) override;
int getSize();
@ -72,6 +72,13 @@ private:
static FT_Library sLibrary;
static bool libraryInitialized;
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
@ -80,6 +87,7 @@ private:
float fontScale; //!<Font scale factor. It is > 1.0 if the font would be to big for the texture
int mSize;
const std::string mPath;
};
class TextCache

View file

@ -8,9 +8,9 @@ Window::Window()
{
mInputManager = new InputManager(this);
mDefaultFonts.push_back(mResourceManager.getFont(Font::getDefaultPath(), FONT_SIZE_SMALL));
mDefaultFonts.push_back(mResourceManager.getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM));
mDefaultFonts.push_back(mResourceManager.getFont(Font::getDefaultPath(), FONT_SIZE_LARGE));
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()
@ -59,7 +59,7 @@ void Window::init()
{
mInputManager->init(); //shouldn't this go AFTER renderer initialization?
Renderer::init(0, 0);
mResourceManager.init();
mResourceManager.reloadAll();
for(unsigned int i = 0; i < mGuiStack.size(); i++)
{
@ -75,7 +75,7 @@ void Window::deinit()
}
mInputManager->deinit();
mResourceManager.deinit();
mResourceManager.unloadAll();
Renderer::deinit();
}

View file

@ -5,6 +5,7 @@
#include "InputManager.h"
#include "resources/ResourceManager.h"
#include <vector>
#include "Font.h"
class Window
{

View file

@ -83,7 +83,7 @@ void GuiDetectDevice::update(int deltaTime)
void GuiDetectDevice::render()
{
std::shared_ptr<Font> font = mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM);
std::shared_ptr<Font> font = Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM);
std::string playerString;
std::stringstream stream;

View file

@ -26,7 +26,7 @@ bool GuiGameList::isDetailed() const
GuiGameList::GuiGameList(Window* window) : GuiComponent(window),
mTheme(new ThemeComponent(mWindow)),
mList(window, 0, 0, window->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM)),
mList(window, 0, 0, Font::get(*window->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM)),
mScreenshot(window),
mDescription(window),
mDescContainer(window),
@ -114,7 +114,7 @@ void GuiGameList::render()
if(mTheme)
mTheme->render();
std::shared_ptr<Font> headerFont = mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_LARGE);
std::shared_ptr<Font> headerFont = Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_LARGE);
//header
if(!mTheme->getBool("hideHeader"))

View file

@ -77,7 +77,7 @@ bool GuiInputConfig::input(InputConfig* config, Input input)
void GuiInputConfig::render()
{
std::shared_ptr<Font> font = mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM);
std::shared_ptr<Font> font = Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM);
std::stringstream stream;
stream << "PLAYER " << mTargetConfig->getPlayerNum() + 1 << ", press...";

View file

@ -11,7 +11,7 @@ GuiMenu::GuiMenu(Window* window, GuiGameList* parent) : GuiComponent(window)
{
mParent = parent;
std::shared_ptr<Font> font = mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_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();

View file

@ -86,7 +86,11 @@ void ImageComponent::setImage(std::string path)
mPath = path;
mTexture = mWindow->getResourceManager()->getTexture(path);
if(mPath.empty() || !mWindow->getResourceManager()->fileExists(mPath))
mTexture.reset();
else
mTexture = TextureResource::get(*mWindow->getResourceManager(), mPath);
resize();
}
@ -229,7 +233,7 @@ void ImageComponent::copyScreen()
{
mTexture.reset();
mTexture = std::make_shared<TextureResource>();
mTexture = TextureResource::get(*mWindow->getResourceManager(), "");
mTexture->initFromScreen();
resize();

View file

@ -8,7 +8,7 @@ SwitchComponent::SwitchComponent(Window* window, bool state) : GuiComponent(wind
//mSize = Vector2u((unsigned int)(Renderer::getScreenWidth() * 0.05),
// (unsigned int)(Renderer::getScreenHeight() * 0.05));
mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_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)
@ -26,7 +26,7 @@ void SwitchComponent::onRender()
{
Renderer::pushClipRect(getGlobalOffset(), getSize());
mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM)->drawText(mState ? "ON" : "OFF", 0, 0, mState ? 0x00FF00FF : 0xFF0000FF);
Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM)->drawText(mState ? "ON" : "OFF", 0, 0, mState ? 0x00FF00FF : 0xFF0000FF);
Renderer::popClipRect();

View file

@ -53,7 +53,7 @@ std::shared_ptr<Font> TextComponent::getFont() const
if(mFont)
return mFont;
else
return mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM);
return Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM);
}
void TextComponent::onRender()

View file

@ -40,7 +40,7 @@ std::shared_ptr<Font> ThemeComponent::getListFont()
if(mListFont)
return mListFont;
else
return mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM);
return Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM);
}
std::shared_ptr<Font> ThemeComponent::getDescriptionFont()
@ -48,7 +48,7 @@ std::shared_ptr<Font> ThemeComponent::getDescriptionFont()
if(mDescFont)
return mDescFont;
else
return mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_SMALL);
return Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_SMALL);
}
std::shared_ptr<Font> ThemeComponent::getFastSelectFont()
@ -56,7 +56,7 @@ std::shared_ptr<Font> ThemeComponent::getFastSelectFont()
if(mFastSelectFont == NULL)
return mFastSelectFont;
else
return mWindow->getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_LARGE);
return Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_LARGE);
}
ThemeComponent::ThemeComponent(Window* window) : GuiComponent(window)
@ -410,5 +410,5 @@ std::shared_ptr<Font> ThemeComponent::resolveFont(pugi::xml_node node, std::stri
size = defaultSize;
}
return mWindow->getResourceManager()->getFont(path, size);
return Font::get(*mWindow->getResourceManager(), path, size);
}

View file

@ -211,7 +211,7 @@ int main(int argc, char* argv[])
nrOfFrames = 0;
timeElapsed = 0;
}
window.getResourceManager()->getFont(Font::getDefaultPath(), FONT_SIZE_MEDIUM)->drawText(fpsString, 50, 50, 0x00FF00FF);
Font::get(*window.getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM)->drawText(fpsString, 50, 50, 0x00FF00FF);
}
//sleep if we're past our threshold

View file

@ -1,14 +0,0 @@
#pragma once
struct ResourceData
{
const unsigned char* ptr;
const size_t length;
};
class Resource
{
public:
virtual void init(ResourceData data) = 0;
virtual void deinit() = 0;
};

View file

@ -1,6 +1,13 @@
#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;
@ -18,96 +25,35 @@ struct EmbeddedResource
static const int embedded_resource_count = 2;
static const EmbeddedResource embedded_resources[embedded_resource_count] = {
{ "internal://es_logo_16.png", {es_logo_16_data, es_logo_16_data_len} },
{ "internal://es_logo_32.png", {es_logo_32_data, es_logo_32_data_len} }
{ "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} }
};
std::shared_ptr<TextureResource> ResourceManager::getTexture(const std::string& path)
{
if(path.empty())
return std::shared_ptr<TextureResource>(); //NULL pointer
if(mTextureMap[path].expired())
{
std::shared_ptr<TextureResource> ret(new TextureResource());
mTextureMap[path] = std::weak_ptr<TextureResource>(ret);
initializeResource(path, ret);
return ret;
}
return mTextureMap[path].lock();
}
std::shared_ptr<Font> ResourceManager::getFont(const std::string& path, int size)
{
if(path.empty() || size == 0)
return std::shared_ptr<Font>(); //NULL pointer
std::pair<std::string, int> fontDef(path, size);
if(mFontMap[fontDef].expired())
{
std::shared_ptr<Font> ret(new Font(size));
mFontMap[fontDef] = std::weak_ptr<Font>(ret);
initializeResource(path, ret);
return ret;
}
return mFontMap[fontDef].lock();
}
void ResourceManager::init()
{
for(auto iter = mTextureMap.begin(); iter != mTextureMap.end(); iter++)
{
if(!iter->second.expired())
initializeResource(iter->first, iter->second.lock());
}
for(auto iter = mFontMap.begin(); iter != mFontMap.end(); iter++)
{
if(!iter->second.expired())
initializeResource(iter->first.first, iter->second.lock());
}
}
void ResourceManager::deinit()
{
for(auto iter = mTextureMap.begin(); iter != mTextureMap.end(); iter++)
{
if(!iter->second.expired())
iter->second.lock()->deinit();
}
for(auto iter = mFontMap.begin(); iter != mFontMap.end(); iter++)
{
if(!iter->second.expired())
iter->second.lock()->deinit();
}
}
void ResourceManager::initializeResource(const std::string& path, std::shared_ptr<Resource> resource)
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
resource->init(embedded_resources[i].resourceData);
return;
return embedded_resources[i].resourceData;
}
}
//it's not embedded; load the file, initialize with it, then free the file
ResourceData data = loadFile(path);
resource->init(data);
delete[] data.ptr;
//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)
ResourceData ResourceManager::loadFile(const std::string& path) const
{
std::ifstream stream(path, std::ios::binary);
@ -115,10 +61,48 @@ ResourceData ResourceManager::loadFile(const std::string& path)
size_t size = (size_t)stream.tellg();
stream.seekg(0, stream.beg);
unsigned char* data = new unsigned char[size];
stream.read((char*)data, size);
//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()
{
for(auto iter = mReloadables.begin(); iter != mReloadables.end(); iter++)
{
if(!iter->expired())
iter->lock()->unload(*this);
}
}
void ResourceManager::reloadAll()
{
for(auto iter = mReloadables.begin(); iter != mReloadables.end(); iter++)
{
if(!iter->expired())
iter->lock()->reload(*this);
}
}
void ResourceManager::addReloadable(std::weak_ptr<IReloadable> reloadable)
{
mReloadables.push_back(reloadable);
}

View file

@ -3,35 +3,40 @@
#include <stddef.h>
#include <memory>
#include <map>
#include "Resource.h"
#include "TextureResource.h"
#include "../Font.h"
#include <vector>
//The ResourceManager exists to:
//1. Automatically deal with initializing/deinitializing various resources (OpenGL textures, SDL audio)
//2. Allow loading resources embedded into the executable like an actual file.
// a. Allow embedded resources to be optionally remapped to actual files for further customization.
//3. Keep from creating duplicate resources.
//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.
//The ResourceManager returns resources as std::shared_ptrs.
//When the resource no longer has any references, it will be automatically freed.
//If ES launches a game, all resources will have deinit() called on them and SDL will deinitialize.
//Once the game exits and ES returns, resources will have init() called on them.
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:
std::shared_ptr<TextureResource> getTexture(const std::string& path);
std::shared_ptr<Font> getFont(const std::string& path, int size);
void addReloadable(std::weak_ptr<IReloadable> reloadable);
void init();
void deinit();
void unloadAll();
void reloadAll();
const ResourceData getFileData(const std::string& path) const;
bool fileExists(const std::string& path) const;
private:
void initializeResource(const std::string& path, std::shared_ptr<Resource> resource);
ResourceData loadFile(const std::string& path);
ResourceData loadFile(const std::string& path) const;
std::map< std::string, std::weak_ptr<TextureResource> > mTextureMap;
std::map< std::pair<std::string, int>, std::weak_ptr<Font> > mFontMap;
std::vector< std::weak_ptr<IReloadable> > mReloadables;
};

View file

@ -5,8 +5,11 @@
#include "../ImageIO.h"
#include "../Renderer.h"
TextureResource::TextureResource() : mTextureID(0)
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()
@ -14,17 +17,28 @@ TextureResource::~TextureResource()
deinit();
}
void TextureResource::init(ResourceData data)
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(data.ptr, data.length, 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!";
LOG(LogError) << "Could not initialize texture (invalid resource data)!";
return;
}
@ -44,25 +58,6 @@ void TextureResource::init(ResourceData data)
mTextureSize.y = height;
}
void TextureResource::deinit()
{
if(mTextureID != 0)
{
glDeleteTextures(1, &mTextureID);
mTextureID = 0;
}
}
Vector2u TextureResource::getSize()
{
return mTextureSize;
}
void TextureResource::bind()
{
glBindTexture(GL_TEXTURE_2D, mTextureID);
}
void TextureResource::initFromScreen()
{
deinit();
@ -84,3 +79,46 @@ void TextureResource::initFromScreen()
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;
}

View file

@ -1,27 +1,37 @@
#pragma once
#include "Resource.h"
#include "ResourceManager.h"
#include <string>
#include "../Vector2.h"
#include "../platform.h"
#include GLHEADER
class TextureResource : public Resource
class TextureResource : public IReloadable
{
public:
TextureResource();
~TextureResource();
static std::shared_ptr<TextureResource> get(ResourceManager& rm, const std::string& path);
void init(ResourceData data) override;
void deinit() override;
Vector2u getSize();
void bind();
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;
};