diff --git a/src/Engine.cpp b/src/Engine.cpp index c10e3e7..3469a33 100644 --- a/src/Engine.cpp +++ b/src/Engine.cpp @@ -4,7 +4,7 @@ namespace ougge { Engine::Engine() - : gameObjectPool(GAMEOBJECTPOOL_SIZE) + : gameObjectPool(GAMEOBJECTPOOL_SIZE), textures(&resourceManager) { } @@ -17,7 +17,7 @@ void Engine::init(){ } void Engine::openMainWindow(const std::string& window_title){ - mainWindow.open(window_title); + mainWindow.open(window_title, resourceManager); } void Engine::startLoop(){ diff --git a/src/Engine.hpp b/src/Engine.hpp index 413cbcb..d55609e 100644 --- a/src/Engine.hpp +++ b/src/Engine.hpp @@ -1,50 +1,51 @@ -#pragma once - -#include "common/function_shared_ptr.hpp" -#include "mono/mono.hpp" -#include "game/GameObjectPool.hpp" -#include "gui/MainWindow.hpp" -#include "resources/textures.hpp" - -namespace ougge { - -#define GAMEOBJECTPOOL_SIZE 64*1024 - -using UpdateFunc_t = function_shared_ptr; - -class Engine { - bool loop_running = false; - - game::GameObjectPool gameObjectPool; - u64 obj_id = 0; - MonoClass* gameObjectClass; - Mono::Method gameObjectCtor; - Mono::Method gameObjectInvokeUpdate; - Mono::Method gameObjectTryCreateComponent; - -public: - gui::MainWindow mainWindow; - UpdateFunc_t updateCallback; - - Mono::RuntimeJIT mono; - std::shared_ptr engineManagedAssembly; - - resources::CacheStorage textures; - - Engine(); - void init(); - void openMainWindow(const std::string& window_title); - // start game loop on the current thread - void startLoop(); - void stopLoop(); - - game::GameObject& createGameObject(); - bool tryCreateComponent(game::GameObject& obj, const std::string& componentClassName); - - -private: - void tryDrawFrame(f64 deltaTime); - void updateGameObjects(f64 deltaTime); -}; - -} +#pragma once + +#include "common/function_shared_ptr.hpp" +#include "mono/mono.hpp" +#include "game/GameObjectPool.hpp" +#include "gui/MainWindow.hpp" +#include "resources/textures.hpp" + +namespace ougge { + +#define GAMEOBJECTPOOL_SIZE 64*1024 + +using UpdateFunc_t = function_shared_ptr; + +class Engine { + bool loop_running = false; + + game::GameObjectPool gameObjectPool; + u64 obj_id = 0; + MonoClass* gameObjectClass; + Mono::Method gameObjectCtor; + Mono::Method gameObjectInvokeUpdate; + Mono::Method gameObjectTryCreateComponent; + +public: + gui::MainWindow mainWindow; + UpdateFunc_t updateCallback; + + Mono::RuntimeJIT mono; + std::shared_ptr engineManagedAssembly; + + resources::ResourceManager resourceManager; + resources::CacheStorage textures; + + Engine(); + void init(); + void openMainWindow(const std::string& window_title); + // start game loop on the current thread + void startLoop(); + void stopLoop(); + + game::GameObject& createGameObject(); + bool tryCreateComponent(game::GameObject& obj, const std::string& componentClassName); + + +private: + void tryDrawFrame(f64 deltaTime); + void updateGameObjects(f64 deltaTime); +}; + +} diff --git a/src/GUI/MainWindow.cpp b/src/GUI/MainWindow.cpp index a895cfb..d130517 100644 --- a/src/GUI/MainWindow.cpp +++ b/src/GUI/MainWindow.cpp @@ -4,8 +4,6 @@ #include "MainWindow.hpp" #include "gui_exceptions.hpp" #include "../common/ougge_format.hpp" -#include "../resources/fonts.hpp" -#include "../resources/textures.hpp" #include "../common/math.hpp" namespace ougge::gui { @@ -21,7 +19,7 @@ f32 MainWindow::getDPI(){ return dpi; } -void MainWindow::open(const std::string& window_title){ +void MainWindow::open(const std::string& window_title, resources::ResourceManager& resourceManager){ SDL_TRY(SDL_Init(SDL_INIT_EVERYTHING)); SDL_version v; SDL_GetVersion(&v); @@ -72,8 +70,12 @@ void MainWindow::open(const std::string& window_title){ // Setup Dear ImGui style ImGui::StyleColorsDark(); + + resources::ResourceFactory* font_res = resourceManager.tryGetResource(default_font_path); + if(font_res == nullptr) + throw UsefulException("can't find default font resource"); f32 dpi = getDPI(); - io.FontDefault = resources::ImFont_LoadFromResource(default_font, default_font_size, dpi); + io.FontDefault = resources::ImFont_LoadFromResource(font_res, default_font_size, dpi); } void MainWindow::close(){ diff --git a/src/GUI/MainWindow.hpp b/src/GUI/MainWindow.hpp index 70fad7a..c2c7b67 100644 --- a/src/GUI/MainWindow.hpp +++ b/src/GUI/MainWindow.hpp @@ -1,45 +1,47 @@ -#pragma once - -#include -#include -#include "../common/std.hpp" -#include "../common/time.hpp" - -/// converts hex color to float vector -#define RGBAHexToF(R8,G8,B8,A8) ImVec4(((u8)35)/255.0f, ((u8)35)/255.0f, ((u8)50)/255.0f, ((u8)255)/255.0f) -/// converts float vector to hex color -#define RGBAFToHex(VEC4) {(u8)(VEC4.x*255), (u8)(VEC4.y*255), (u8)(VEC4.z*255), (u8)(VEC4.w*255)} - -namespace ougge::gui { - -#define default_font "DroidSans" - -class MainWindow { -public: - i32 fps_max = 60; - f32 default_font_size = 14.0f; - ImVec4 clear_color = RGBAHexToF(35,35,50,255); - SDL_Window* sdl_window = nullptr; - SDL_Renderer* sdl_renderer = nullptr; - -private: - bool show_debug_window = true; - bool show_demo_window = false; - bool show_metrics_window = false; - -public: - void open(const std::string& window_title); - void close(); - - /// process io events happened since previous frame - void pollEvents(bool* loopRunning); - void beginFrame(); - void endFrame(); - - f32 getDPI(); -private: - void draw_debug_window(); - void draw_bg_window(); -}; - -} +#pragma once + +#include +#include +#include "../common/std.hpp" +#include "../common/time.hpp" +#include "../resources/resources.hpp" +#include "../resources/fonts.hpp" + +/// converts hex color to float vector +#define RGBAHexToF(R8,G8,B8,A8) ImVec4(((u8)35)/255.0f, ((u8)35)/255.0f, ((u8)50)/255.0f, ((u8)255)/255.0f) +/// converts float vector to hex color +#define RGBAFToHex(VEC4) {(u8)(VEC4.x*255), (u8)(VEC4.y*255), (u8)(VEC4.z*255), (u8)(VEC4.w*255)} + +namespace ougge::gui { + +#define default_font_path "fonts/DroidSans.ttf" + +class MainWindow { +public: + i32 fps_max = 60; + f32 default_font_size = 14.0f; + ImVec4 clear_color = RGBAHexToF(35,35,50,255); + SDL_Window* sdl_window = nullptr; + SDL_Renderer* sdl_renderer = nullptr; + +private: + bool show_debug_window = true; + bool show_demo_window = false; + bool show_metrics_window = false; + +public: + void open(const std::string& window_title, resources::ResourceManager& resourceManager); + void close(); + + /// process io events happened since previous frame + void pollEvents(bool* loopRunning); + void beginFrame(); + void endFrame(); + + f32 getDPI(); +private: + void draw_debug_window(); + void draw_bg_window(); +}; + +} diff --git a/src/Resources/MemorySteam.cpp b/src/Resources/MemorySteam.cpp new file mode 100644 index 0000000..fea56e5 --- /dev/null +++ b/src/Resources/MemorySteam.cpp @@ -0,0 +1,40 @@ +#include "MemoryStream.hpp" + +class MemoryStreamBuf : public std::streambuf { +public: + MemoryStreamBuf(void* p, const std::size_t n); + + virtual std::istream::pos_type seekoff( + std::istream::off_type off, + std::ios_base::seekdir dir, + std::ios_base::openmode which); +}; + +MemoryStreamBuf::MemoryStreamBuf(void* _p, const std::size_t n){ + char* p=(char*)_p; + setg(p, p, p + n); + setp(p, p + n); +} + +std::istream::pos_type MemoryStreamBuf::seekoff( + std::istream::off_type off, + std::ios_base::seekdir dir, + std::ios_base::openmode which) +{ + if (dir == std::ios_base::cur) + gbump(off); + else if (dir == std::ios_base::end) + setg(eback(), egptr() + off, egptr()); + else if (dir == std::ios_base::beg) + setg(eback(), eback() + off, egptr()); + return gptr() - eback(); +} + + +MemoryStreamRead::MemoryStreamRead(const void* p, const std::size_t n) + : std::istream(new MemoryStreamBuf((void*)p, n)) +{} + +MemoryStreamRead::~MemoryStreamRead(){ + delete rdbuf(); +} diff --git a/src/Resources/MemoryStream.hpp b/src/Resources/MemoryStream.hpp new file mode 100644 index 0000000..0f1ced9 --- /dev/null +++ b/src/Resources/MemoryStream.hpp @@ -0,0 +1,8 @@ +#include + +class MemoryStreamRead : public std::istream { +public: + MemoryStreamRead(const void* p, const std::size_t n); + + virtual ~MemoryStreamRead(); +}; \ No newline at end of file diff --git a/src/Resources/fonts.cpp b/src/Resources/fonts.cpp index 3ce4b5b..96cde0f 100644 --- a/src/Resources/fonts.cpp +++ b/src/Resources/fonts.cpp @@ -1,7 +1,4 @@ -#include -#include "resources.hpp" -#include -#include +#include "fonts.hpp" namespace ougge::resources { @@ -16,17 +13,16 @@ ImFont* ImFont_LoadFromFile(const std::string& file_path, f32 font_size, f32 dpi return io.Fonts->AddFontFromFileTTF(file_path.c_str(), font_size, nullptr, glyph_ranges); } -ImFont* ImFont_LoadFromResource(const std::string& font_name, f32 font_size, f32 dpi){ +ImFont* ImFont_LoadFromResource(ResourceFactory* res, f32 font_size, f32 dpi){ ImGuiIO& io = ImGui::GetIO(); font_size *= dpi; ImFontConfig font_cfg = ImFontConfig(); - std::sprintf(font_cfg.Name, "%s %ipx", font_name.c_str(), (i32)font_size); + std::sprintf(font_cfg.Name, "%s %ipx", res->path.c_str(), (i32)font_size); - auto& res = getResource("fonts/" + font_name + ".ttf"); - char* font_data = new char[res.size]; - res.openStream()->read(font_data, res.size); + char* font_data = new char[res->size]; + res->openStream()->read(font_data, res->size); - return io.Fonts->AddFontFromMemoryTTF((void*)(font_data), res.size, + return io.Fonts->AddFontFromMemoryTTF((void*)(font_data), res->size, font_size, &font_cfg, glyph_ranges); } diff --git a/src/Resources/fonts.hpp b/src/Resources/fonts.hpp index 22bf712..6ab1b08 100644 --- a/src/Resources/fonts.hpp +++ b/src/Resources/fonts.hpp @@ -1,12 +1,13 @@ #pragma once -#include "imgui.h" +#include #include "../common/std.hpp" +#include "resources.hpp" namespace ougge::resources { ImFont* ImFont_LoadFromFile(const std::string& file_path, f32 font_size, f32 dpi); -ImFont* ImFont_LoadFromResource(const std::string& font_name, f32 font_size, f32 dpi); +ImFont* ImFont_LoadFromResource(ResourceFactory* res, f32 font_size, f32 dpi); } diff --git a/src/common/ougge_format.cpp b/src/common/ougge_format.cpp index a8f5a6d..f3f7642 100644 --- a/src/common/ougge_format.cpp +++ b/src/common/ougge_format.cpp @@ -1,65 +1,84 @@ -#include -#include -#include "ougge_format.hpp" -#include "UsefulException.hpp" - -std::string _ougge_format(const std::string& format_str, const size_t args_count, ...){ - va_list vl; - va_start(vl, args_count); - std::stringstream ss; - - for(size_t i = 0; i < format_str.length(); i++){ - char c = format_str[i]; - - // format specifier - if(c == '%'){ - c = format_str[++i]; - bool l = false; - while(c == 'l'){ - l = true; - c = format_str[++i]; - } - - switch(c){ - case 'u': - if(l) ss<<(u64)va_arg(vl, u64); - else ss<<(u32)va_arg(vl, u32); - break; - case 'i': - case 'd': - if(l) ss<<(i64)va_arg(vl, i64); - else ss<<(i32)va_arg(vl, i32); - break; - case 'f': - // f32 is promoted to f64 when passed through '...' - ss<<(f64)va_arg(vl, f64); - break; - case 'p': - ss<<(void*)va_arg(vl, void*); - break; - case 'x': - if(l) ss<"; - break; - } - case 'c': - ss<<(char)va_arg(vl,int); - break; - default: - throw UsefulException("invalid format cpecifier"); - } - } - - // regular character - else ss< +#include +#include "ougge_format.hpp" +#include "UsefulException.hpp" + +std::string _ougge_format(const std::string& format_str, const size_t args_count, ...){ + va_list vl; + va_start(vl, args_count); + std::stringstream ss; + + for(size_t i = 0; i < format_str.length(); i++){ + char c = format_str[i]; + + // format specifier + if(c == '%'){ + c = format_str[++i]; + bool l = false; + while(c == 'l'){ + l = true; + c = format_str[++i]; + } + + switch(c){ + case 'u': + if(l) ss<<(u64)va_arg(vl, u64); + else ss<<(u32)va_arg(vl, u32); + break; + case 'i': + case 'd': + if(l) ss<<(i64)va_arg(vl, i64); + else ss<<(i32)va_arg(vl, i32); + break; + case 'f': + // f32 is promoted to f64 when passed through '...' + ss<<(f64)va_arg(vl, f64); + break; + case 'p': + ss<<(void*)va_arg(vl, void*); + break; + case 'x': + if(l) ss<"; + break; + } + case 'c': + ss<<(char)va_arg(vl,int); + break; + default: + throw UsefulException("invalid format cpecifier"); + } + } + + // regular character + else ss< -#include -#include "../common/std.hpp" -#include "../common/time.hpp" - -/// converts hex color to float vector -#define RGBAHexToF(R8,G8,B8,A8) ImVec4(((u8)35)/255.0f, ((u8)35)/255.0f, ((u8)50)/255.0f, ((u8)255)/255.0f) -/// converts float vector to hex color -#define RGBAFToHex(VEC4) {(u8)(VEC4.x*255), (u8)(VEC4.y*255), (u8)(VEC4.z*255), (u8)(VEC4.w*255)} - -namespace ougge::gui { - -#define default_font "DroidSans" - -class MainWindow { -public: - i32 fps_max = 60; - f32 default_font_size = 14.0f; - ImVec4 clear_color = RGBAHexToF(35,35,50,255); - SDL_Window* sdl_window = nullptr; - SDL_Renderer* sdl_renderer = nullptr; - -private: - bool show_debug_window = true; - bool show_demo_window = false; - bool show_metrics_window = false; - -public: - void open(const std::string& window_title); - void close(); - - /// process io events happened since previous frame - void pollEvents(bool* loopRunning); - void beginFrame(); - void endFrame(); - - f32 getDPI(); -private: - void draw_debug_window(); - void draw_bg_window(); -}; - -} +#pragma once + +#include +#include +#include "../common/std.hpp" +#include "../common/time.hpp" +#include "../resources/resources.hpp" +#include "../resources/fonts.hpp" + +/// converts hex color to float vector +#define RGBAHexToF(R8,G8,B8,A8) ImVec4(((u8)35)/255.0f, ((u8)35)/255.0f, ((u8)50)/255.0f, ((u8)255)/255.0f) +/// converts float vector to hex color +#define RGBAFToHex(VEC4) {(u8)(VEC4.x*255), (u8)(VEC4.y*255), (u8)(VEC4.z*255), (u8)(VEC4.w*255)} + +namespace ougge::gui { + +#define default_font_path "fonts/DroidSans.ttf" + +class MainWindow { +public: + i32 fps_max = 60; + f32 default_font_size = 14.0f; + ImVec4 clear_color = RGBAHexToF(35,35,50,255); + SDL_Window* sdl_window = nullptr; + SDL_Renderer* sdl_renderer = nullptr; + +private: + bool show_debug_window = true; + bool show_demo_window = false; + bool show_metrics_window = false; + +public: + void open(const std::string& window_title, resources::ResourceManager& resourceManager); + void close(); + + /// process io events happened since previous frame + void pollEvents(bool* loopRunning); + void beginFrame(); + void endFrame(); + + f32 getDPI(); +private: + void draw_debug_window(); + void draw_bg_window(); +}; + +} diff --git a/src/main.cpp b/src/main.cpp index 8d4c823..cf5dd7d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,63 +1,65 @@ -#define SDL_MAIN_HANDLED -#include -#include -#include "common/UsefulException.hpp" -#include "common/ougge_format.hpp" -#include "Engine.hpp" -#include "gui/gui.hpp" - -using namespace ougge; - -void drawTutel(Engine& engine){ - resources::Texture& tutel = engine.textures.getOrCreate("tutel.png", engine.mainWindow.sdl_renderer); - resources::SDL_RenderCopyExF_Params params; - params.target_section = SDL_FRectConstruct(100, 100, 400, 400); - static i32 si = 1; - params.rotation_angle = M_PI_4 * (si++ / engine.mainWindow.fps_max); - tutel.render(params); -} - -int main(int argc, const char** argv){ - try { - resources::init(); - std::cout<<"initialized resource loader"< void { - drawTutel(engine); - }; - - engine.openMainWindow("ougge"); - std::cout<<"created sdl window"< +#include +#include "common/UsefulException.hpp" +#include "common/ougge_format.hpp" +#include "Engine.hpp" +#include "gui/gui.hpp" + +using namespace ougge; + +void drawTutel(Engine& engine){ + resources::Texture* tutel = engine.textures.tryGetOrCreate("tutel.png", engine.mainWindow.sdl_renderer); + if(tutel == nullptr){ + throw new UsefulException("couldn't find resource 'tutel.png'"); + } + resources::SDL_RenderCopyExF_Params params; + params.target_section = SDL_FRectConstruct(100, 100, 400, 400); + static i32 si = 1; + params.rotation_angle = M_PI_4 * (si++ / engine.mainWindow.fps_max); + tutel->render(params); +} + +int main(int argc, const char** argv){ + try { + std::cout<<"initialized resource loader"< void { + drawTutel(engine); + }; + + engine.openMainWindow("ougge"); + std::cout<<"created sdl window"< + +class MemoryStreamRead : public std::istream { +public: + MemoryStreamRead(const void* p, const std::size_t n); + + virtual ~MemoryStreamRead(); +}; \ No newline at end of file diff --git a/src/resources/fonts.cpp b/src/resources/fonts.cpp index 3ce4b5b..96cde0f 100644 --- a/src/resources/fonts.cpp +++ b/src/resources/fonts.cpp @@ -1,7 +1,4 @@ -#include -#include "resources.hpp" -#include -#include +#include "fonts.hpp" namespace ougge::resources { @@ -16,17 +13,16 @@ ImFont* ImFont_LoadFromFile(const std::string& file_path, f32 font_size, f32 dpi return io.Fonts->AddFontFromFileTTF(file_path.c_str(), font_size, nullptr, glyph_ranges); } -ImFont* ImFont_LoadFromResource(const std::string& font_name, f32 font_size, f32 dpi){ +ImFont* ImFont_LoadFromResource(ResourceFactory* res, f32 font_size, f32 dpi){ ImGuiIO& io = ImGui::GetIO(); font_size *= dpi; ImFontConfig font_cfg = ImFontConfig(); - std::sprintf(font_cfg.Name, "%s %ipx", font_name.c_str(), (i32)font_size); + std::sprintf(font_cfg.Name, "%s %ipx", res->path.c_str(), (i32)font_size); - auto& res = getResource("fonts/" + font_name + ".ttf"); - char* font_data = new char[res.size]; - res.openStream()->read(font_data, res.size); + char* font_data = new char[res->size]; + res->openStream()->read(font_data, res->size); - return io.Fonts->AddFontFromMemoryTTF((void*)(font_data), res.size, + return io.Fonts->AddFontFromMemoryTTF((void*)(font_data), res->size, font_size, &font_cfg, glyph_ranges); } diff --git a/src/resources/fonts.hpp b/src/resources/fonts.hpp index 22bf712..6ab1b08 100644 --- a/src/resources/fonts.hpp +++ b/src/resources/fonts.hpp @@ -1,12 +1,13 @@ #pragma once -#include "imgui.h" +#include #include "../common/std.hpp" +#include "resources.hpp" namespace ougge::resources { ImFont* ImFont_LoadFromFile(const std::string& file_path, f32 font_size, f32 dpi); -ImFont* ImFont_LoadFromResource(const std::string& font_name, f32 font_size, f32 dpi); +ImFont* ImFont_LoadFromResource(ResourceFactory* res, f32 font_size, f32 dpi); } diff --git a/src/resources/resources.cpp b/src/resources/resources.cpp index a996571..5591582 100644 --- a/src/resources/resources.cpp +++ b/src/resources/resources.cpp @@ -4,45 +4,22 @@ #include "../common/ougge_format.hpp" #include "resources.hpp" #include "embedded_resources.h" - +#include "MemoryStream.hpp" namespace ougge::resources { -Resource::Resource(const std::string& path, const std::size_t size, StreamFactoryMethod open_read_steam_func) +ResourceFactory::ResourceFactory(const std::string& path, const std::size_t size, StreamFactoryMethod open_read_steam_func) : path(path), size(size), openStream(open_read_steam_func) {} -MemoryStreamBuf::MemoryStreamBuf(void* _p, const std::size_t n){ - char* p=(char*)_p; - setg(p, p, p + n); - setp(p, p + n); -} -std::istream::pos_type MemoryStreamBuf::seekoff( - std::istream::off_type off, - std::ios_base::seekdir dir, - std::ios_base::openmode which) -{ - if (dir == std::ios_base::cur) - gbump(off); - else if (dir == std::ios_base::end) - setg(eback(), egptr() + off, egptr()); - else if (dir == std::ios_base::beg) - setg(eback(), eback() + off, egptr()); - return gptr() - eback(); -} +std::shared_ptr ResourceManager::_embeddedResourcesMap; -MemoryStreamRead::MemoryStreamRead(const void* p, const std::size_t n) - : std::istream(new MemoryStreamBuf((void*)p, n)) -{} +void ResourceManager::loadEmbeddedResources(){ + if(_embeddedResourcesMap != nullptr) + return; -MemoryStreamRead::~MemoryStreamRead(){ - delete rdbuf(); -} - -static std::unordered_map* _resourceMap = nullptr; - -void loadEmbeddedresources(){ + _embeddedResourcesMap = std::make_shared(); for(int i = 0; i < EmbeddedResource_table_count; i++){ const EmbeddedResource& e = EmbeddedResource_table[i]; std::cout <<"loading resource '" << e.path << "' " @@ -52,43 +29,36 @@ void loadEmbeddedresources(){ return std::make_unique(e.data, e.size); }; - auto r = _resourceMap->emplace(e.path, - Resource(e.path, e.size, embedded_resource_factory)); + auto r = _embeddedResourcesMap->emplace(e.path, + ResourceFactory(e.path, e.size, embedded_resource_factory)); if(!r.second) throw UsefulException(ougge_format("can't load duplicate resource '%s'", e.path)); } -} - -void init(){ - if(_resourceMap != nullptr) - throw UsefulException("resource has been initialized already"); - _resourceMap = new std::unordered_map(); - loadEmbeddedresources(); -} - -Resource& getResource(const std::string& path){ - auto it = _resourceMap->find(path); - if(it == _resourceMap->end()) - throw UsefulException(ougge_format("can't find resource '%s'", path.c_str())); - return it->second; -} - -std::string formatSizeHumanReadable(std::size_t b){ - std::stringstream ss; - ss.precision(3); - std::size_t k = b / 1024; - std::size_t m = k / 1024; - std::size_t g = m / 1024; - if(g) - ss<find(path); + + // resource not found + if(resource_iterator == map->end()) + return nullptr; + + return &resource_iterator->second; + } + + return nullptr; } } diff --git a/src/resources/resources.hpp b/src/resources/resources.hpp index 3b266df..2e6d8e6 100644 --- a/src/resources/resources.hpp +++ b/src/resources/resources.hpp @@ -4,60 +4,71 @@ #include #include #include +#include +#include namespace ougge::resources { -// call this in main() -void init(); - -std::string formatSizeHumanReadable(std::size_t byte_n); - -class Resource { +class ResourceFactory { public: const std::string path; const std::size_t size; using StreamFactoryMethod = std::function< std::unique_ptr () >; - Resource(const std::string& path, const std::size_t size, StreamFactoryMethod open_read_steam_func); + ResourceFactory(const std::string& path, const std::size_t size, StreamFactoryMethod open_read_steam_func); const StreamFactoryMethod openStream; }; -class MemoryStreamBuf : public std::streambuf { +using ResourceMap = std::unordered_map; + +class ResourceManager { + std::list> _resourceMaps; + static std::shared_ptr _embeddedResourcesMap; + void loadEmbeddedResources(); + public: - MemoryStreamBuf(void* p, const std::size_t n); + ResourceManager(); - virtual std::istream::pos_type seekoff( - std::istream::off_type off, - std::ios_base::seekdir dir, - std::ios_base::openmode which); + void addResourceMap(std::shared_ptr m); + + std::shared_ptr loadResouceMap(); + void removeResourceMap(); + + ResourceFactory* tryGetResource(const std::string& path); }; -class MemoryStreamRead : public std::istream { -public: - MemoryStreamRead(const void* p, const std::size_t n); - - virtual ~MemoryStreamRead(); -}; - -Resource& getResource(const std::string& path); - /// @brief stores requested resources in memory -/// @tparam T must implement constructor `T(const Resource&, ...)` +/// @tparam T must implement constructor `T(ResourceFactory*, ...)` template class CacheStorage { std::unordered_map _map; + ResourceManager* _resourceManager; public: + CacheStorage(ResourceManager*); + CacheStorage(CacheStorage&&) = delete; + CacheStorage(const CacheStorage&) = delete; + template - T& getOrCreate(const std::string& name, TCtorArgs&&... ctor_args){ + T* tryGetOrCreate(const std::string& name, TCtorArgs&&... ctor_args){ auto it = _map.find(name); if(it != _map.end()) - return it->second; - auto& res = getResource(name); + return &it->second; + + ResourceFactory* res = _resourceManager->tryGetResource(name); + if(res == nullptr) + return nullptr; + auto e = _map.emplace(name, T(res, ctor_args...)); - return e.first->second; + return &e.first->second; } }; + + +template inline CacheStorage::CacheStorage(ResourceManager* resourceManager) + : _resourceManager(resourceManager) +{} + } diff --git a/src/resources/textures.cpp b/src/resources/textures.cpp index 2476a2b..ec6b672 100644 --- a/src/resources/textures.cpp +++ b/src/resources/textures.cpp @@ -4,8 +4,8 @@ namespace ougge::resources { -Texture::Texture(const Resource& r, SDL_Renderer* renderer) - : Texture(*r.openStream(), r.size, renderer) +Texture::Texture(ResourceFactory* r, SDL_Renderer* renderer) + : Texture(*r->openStream(), r->size, renderer) {} Texture::Texture(std::istream& s, size_t size, SDL_Renderer* renderer) diff --git a/src/resources/textures.hpp b/src/resources/textures.hpp index 2c05b7c..4869f77 100644 --- a/src/resources/textures.hpp +++ b/src/resources/textures.hpp @@ -33,7 +33,7 @@ struct Texture { i32 w; i32 h; - Texture(const Resource& r, SDL_Renderer* renderer); + Texture(ResourceFactory* r, SDL_Renderer* renderer); Texture(std::istream& s, size_t size, SDL_Renderer* renderer); void render(const SDL_FRect& target_section);