mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-21 21:55:38 +00:00
Moved to class-individualized static gets for resources.
See issue #95 for discussion.
This commit is contained in:
parent
c99324060b
commit
c8900f4099
|
@ -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
|
||||
|
|
44
src/Font.cpp
44
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,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 << ".";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
20
src/Font.h
20
src/Font.h
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "InputManager.h"
|
||||
#include "resources/ResourceManager.h"
|
||||
#include <vector>
|
||||
#include "Font.h"
|
||||
|
||||
class Window
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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...";
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue