created ResourceManager

This commit is contained in:
Timerix 2025-05-19 03:26:18 +05:00
parent d700aae02e
commit 609f7337da
21 changed files with 503 additions and 400 deletions

View File

@ -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(){

View File

@ -29,6 +29,7 @@ public:
Mono::RuntimeJIT mono;
std::shared_ptr<Mono::Assembly> engineManagedAssembly;
resources::ResourceManager resourceManager;
resources::CacheStorage<resources::Texture> textures;
Engine();

View File

@ -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(){

View File

@ -4,6 +4,8 @@
#include <imgui.h>
#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)
@ -12,7 +14,7 @@
namespace ougge::gui {
#define default_font "DroidSans"
#define default_font_path "fonts/DroidSans.ttf"
class MainWindow {
public:
@ -28,7 +30,7 @@ private:
bool show_metrics_window = false;
public:
void open(const std::string& window_title);
void open(const std::string& window_title, resources::ResourceManager& resourceManager);
void close();
/// process io events happened since previous frame

View File

@ -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();
}

View File

@ -0,0 +1,8 @@
#include <iostream>
class MemoryStreamRead : public std::istream {
public:
MemoryStreamRead(const void* p, const std::size_t n);
virtual ~MemoryStreamRead();
};

View File

@ -1,7 +1,4 @@
#include <imgui.h>
#include "resources.hpp"
#include <cstdio>
#include <cstring>
#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);
}

View File

@ -1,12 +1,13 @@
#pragma once
#include "imgui.h"
#include <imgui.h>
#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);
}

View File

@ -63,3 +63,22 @@ std::string _ougge_format(const std::string& format_str, const size_t args_count
va_end(vl);
return ss.str();
}
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<<m / 1024.0f<<'G';
else if(m)
ss<<k / 1024.0f<<'M';
else if(k)
ss<<b / 1024.0f<<'K';
else ss<<b;
return ss.str();
}

View File

@ -4,3 +4,5 @@
std::string _ougge_format(const std::string& format_str, const size_t args_count, ...);
#define ougge_format(FORMAT_STR, ARGS...) _ougge_format(FORMAT_STR, count_args(ARGS) ,##ARGS)
std::string formatSizeHumanReadable(std::size_t byte_n);

View File

@ -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(){

View File

@ -4,6 +4,8 @@
#include <imgui.h>
#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)
@ -12,7 +14,7 @@
namespace ougge::gui {
#define default_font "DroidSans"
#define default_font_path "fonts/DroidSans.ttf"
class MainWindow {
public:
@ -28,7 +30,7 @@ private:
bool show_metrics_window = false;
public:
void open(const std::string& window_title);
void open(const std::string& window_title, resources::ResourceManager& resourceManager);
void close();
/// process io events happened since previous frame

View File

@ -9,17 +9,19 @@
using namespace ougge;
void drawTutel(Engine& engine){
resources::Texture& tutel = engine.textures.getOrCreate("tutel.png", engine.mainWindow.sdl_renderer);
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);
tutel->render(params);
}
int main(int argc, const char** argv){
try {
resources::init();
std::cout<<"initialized resource loader"<<std::endl;
Engine engine;

View File

@ -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();
}

View File

@ -0,0 +1,8 @@
#include <iostream>
class MemoryStreamRead : public std::istream {
public:
MemoryStreamRead(const void* p, const std::size_t n);
virtual ~MemoryStreamRead();
};

View File

@ -1,7 +1,4 @@
#include <imgui.h>
#include "resources.hpp"
#include <cstdio>
#include <cstring>
#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);
}

View File

@ -1,12 +1,13 @@
#pragma once
#include "imgui.h"
#include <imgui.h>
#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);
}

View File

@ -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<ResourceMap> 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<std::string, Resource>* _resourceMap = nullptr;
void loadEmbeddedresources(){
_embeddedResourcesMap = std::make_shared<ResourceMap>();
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<MemoryStreamRead>(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));
}
_resourceMaps.push_back(_embeddedResourcesMap);
}
void init(){
if(_resourceMap != nullptr)
throw UsefulException("resource has been initialized already");
_resourceMap = new std::unordered_map<std::string, Resource>();
loadEmbeddedresources();
ResourceManager::ResourceManager(){
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;
ResourceFactory* ResourceManager::tryGetResource(const std::string& path){
// reverse iteration of linked list
auto map_list_iterator = _resourceMaps.end();
while(map_list_iterator != _resourceMaps.begin()){
--map_list_iterator;
auto map = *map_list_iterator;
auto resource_iterator = map->find(path);
// resource not found
if(resource_iterator == map->end())
return nullptr;
return &resource_iterator->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<<m / 1024.0f<<'G';
else if(m)
ss<<k / 1024.0f<<'M';
else if(k)
ss<<b / 1024.0f<<'K';
else ss<<b;
return ss.str();
return nullptr;
}
}

View File

@ -4,60 +4,71 @@
#include <iostream>
#include <functional>
#include <unordered_map>
#include <memory>
#include <list>
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<std::istream> () >;
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<std::string, ResourceFactory>;
class ResourceManager {
std::list<std::shared_ptr<ResourceMap>> _resourceMaps;
static std::shared_ptr<ResourceMap> _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<ResourceMap> m);
std::shared_ptr<ResourceMap> 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 T>
class CacheStorage {
std::unordered_map<std::string, T> _map;
ResourceManager* _resourceManager;
public:
CacheStorage(ResourceManager*);
CacheStorage(CacheStorage&&) = delete;
CacheStorage(const CacheStorage&) = delete;
template<typename... TCtorArgs>
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 <class T> inline CacheStorage<T>::CacheStorage(ResourceManager* resourceManager)
: _resourceManager(resourceManager)
{}
}

View File

@ -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)

View File

@ -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);