implemented createModule() and getModule()
This commit is contained in:
parent
a288d0961f
commit
9a283a2904
@ -7,19 +7,14 @@
|
|||||||
|
|
||||||
namespace ougge {
|
namespace ougge {
|
||||||
|
|
||||||
EngineModule::EngineModule(Engine& engine, const std::string& name)
|
IEngineModule::IEngineModule(Engine& engine)
|
||||||
: engine(engine), name(name)
|
: engine(engine)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void EngineModule::beginFrame() {}
|
void IEngineModule::beginFrame() {}
|
||||||
void EngineModule::endFrame() {}
|
void IEngineModule::endFrame() {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Engine::addModule(EngineModule* m){
|
|
||||||
modules.push_back(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::startLoop()
|
void Engine::startLoop()
|
||||||
{
|
{
|
||||||
if(loop_running)
|
if(loop_running)
|
||||||
@ -50,10 +45,10 @@ void Engine::stopLoop(){
|
|||||||
loop_running = false;
|
loop_running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::handleModuleError(EngineModule* module, const char* type, const char* method, const char* error){
|
void Engine::handleModuleError(IEngineModule& module, const char* type, const char* method, const char* error){
|
||||||
std::string error_message = ougge_format(
|
std::string error_message = ougge_format(
|
||||||
"Catched %s at %s.%s(): %s",
|
"Catched %s at %s.%s(): %s",
|
||||||
type, module->name.c_str(), method, error);
|
type, module.getName(), method, error);
|
||||||
std::cerr<<error_message<<std::endl;
|
std::cerr<<error_message<<std::endl;
|
||||||
error_messages.push_back(error_message);
|
error_messages.push_back(error_message);
|
||||||
}
|
}
|
||||||
@ -62,10 +57,10 @@ void Engine::tryDrawFrame(){
|
|||||||
auto it = modules.begin();
|
auto it = modules.begin();
|
||||||
while(it != modules.end())
|
while(it != modules.end())
|
||||||
{
|
{
|
||||||
EngineModule* module = *it;
|
IEngineModule& module = **it;
|
||||||
it++;
|
it++;
|
||||||
try {
|
try {
|
||||||
module->beginFrame();
|
module.beginFrame();
|
||||||
}
|
}
|
||||||
catch(const std::exception& e){
|
catch(const std::exception& e){
|
||||||
handleModuleError(module, "exception", "beginFrame", e.what());
|
handleModuleError(module, "exception", "beginFrame", e.what());
|
||||||
@ -81,17 +76,13 @@ void Engine::tryDrawFrame(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: frame expeption display
|
|
||||||
// if(draw_error_window)
|
|
||||||
// gui::drawErrorWindow(error_message, &draw_error_window);
|
|
||||||
|
|
||||||
it = modules.end();
|
it = modules.end();
|
||||||
while(it != modules.begin())
|
while(it != modules.begin())
|
||||||
{
|
{
|
||||||
it--;
|
it--;
|
||||||
EngineModule* module = *it;
|
IEngineModule& module = **it;
|
||||||
try {
|
try {
|
||||||
module->endFrame();
|
module.endFrame();
|
||||||
}
|
}
|
||||||
catch(const std::exception& e){
|
catch(const std::exception& e){
|
||||||
handleModuleError(module, "exception", "endFrame", e.what());
|
handleModuleError(module, "exception", "endFrame", e.what());
|
||||||
|
|||||||
@ -4,32 +4,36 @@
|
|||||||
#include "common/std.hpp"
|
#include "common/std.hpp"
|
||||||
#include "common/UsefulException.hpp"
|
#include "common/UsefulException.hpp"
|
||||||
#include "common/ougge_format.hpp"
|
#include "common/ougge_format.hpp"
|
||||||
|
#include "common/type_name_demangled.hpp"
|
||||||
|
#include <type_traits>
|
||||||
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace ougge {
|
namespace ougge {
|
||||||
|
|
||||||
class Engine;
|
class Engine;
|
||||||
|
|
||||||
class EngineModule {
|
class IEngineModule {
|
||||||
public:
|
public:
|
||||||
EngineModule() = delete;
|
IEngineModule() = delete;
|
||||||
EngineModule(const EngineModule&) = delete;
|
IEngineModule(const IEngineModule&) = delete;
|
||||||
EngineModule& operator=(const EngineModule&) = delete;
|
IEngineModule& operator=(const IEngineModule&) = delete;
|
||||||
EngineModule(EngineModule&&) = delete;
|
IEngineModule(IEngineModule&&) = delete;
|
||||||
EngineModule& operator=(EngineModule&&) = delete;
|
IEngineModule& operator=(IEngineModule&&) = delete;
|
||||||
|
|
||||||
Engine& engine;
|
Engine& engine;
|
||||||
const std::string name;
|
virtual const std::string& getName() = 0;
|
||||||
|
|
||||||
virtual void beginFrame();
|
virtual void beginFrame();
|
||||||
virtual void endFrame();
|
virtual void endFrame();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
EngineModule(Engine& engine, const std::string& name);
|
IEngineModule(Engine& engine);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Engine {
|
class Engine {
|
||||||
std::vector<EngineModule*> modules;
|
std::vector<std::unique_ptr<IEngineModule>> modules;
|
||||||
bool loop_running = false;
|
bool loop_running = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -43,14 +47,60 @@ public:
|
|||||||
Engine(Engine&&) = delete;
|
Engine(Engine&&) = delete;
|
||||||
Engine& operator=(Engine&&) = delete;
|
Engine& operator=(Engine&&) = delete;
|
||||||
|
|
||||||
void addModule(EngineModule* m);
|
|
||||||
|
|
||||||
// start game loop on the current thread
|
// start game loop on the current thread
|
||||||
void startLoop();
|
void startLoop();
|
||||||
void stopLoop();
|
void stopLoop();
|
||||||
|
|
||||||
|
//TODO: add std::enable_if
|
||||||
|
template<typename ModuleT, typename... ConstructorArgsT>
|
||||||
|
ModuleT& createModule(ConstructorArgsT&&... args){
|
||||||
|
static_assert(std::is_base_of<IEngineModule, ModuleT>::value);
|
||||||
|
|
||||||
|
auto& module_type_name = ougge_type_name<ModuleT>();
|
||||||
|
//TODO: replace with some logger call
|
||||||
|
std::cout<<"Initializing module '"<<module_type_name<<"'"<<std::endl;
|
||||||
|
|
||||||
|
size_t module_index;
|
||||||
|
bool module_exists;
|
||||||
|
getOrCreateModuleIndex<ModuleT>(&module_index, &module_exists);
|
||||||
|
|
||||||
|
if(module_exists){
|
||||||
|
throw UsefulException(ougge_format("can't create second instance of module '%s'",
|
||||||
|
module_type_name.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: std::forward(args)...
|
||||||
|
modules.push_back(std::make_unique<ModuleT>(*this, args...));
|
||||||
|
return *static_cast<ModuleT*>(modules[module_index].get());
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: add std::enable_if
|
||||||
|
template<typename ModuleT>
|
||||||
|
ModuleT& getModule(){
|
||||||
|
static_assert(std::is_base_of<IEngineModule, ModuleT>::value);
|
||||||
|
|
||||||
|
size_t module_index;
|
||||||
|
bool module_exists;
|
||||||
|
getOrCreateModuleIndex<ModuleT>(&module_index, &module_exists);
|
||||||
|
if(!module_exists){
|
||||||
|
auto& module_type_name = ougge_type_name<ModuleT>();
|
||||||
|
throw UsefulException(ougge_format("engine has no module '%s'",
|
||||||
|
module_type_name.c_str()));
|
||||||
|
}
|
||||||
|
return *static_cast<ModuleT*>(modules[module_index].get());
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void tryDrawFrame();
|
void tryDrawFrame();
|
||||||
void handleModuleError(EngineModule *module, const char *type, const char *method, const char *error);
|
void handleModuleError(IEngineModule& module, const char *type, const char *method, const char *error);
|
||||||
|
|
||||||
|
//TODO: add std::enable_if
|
||||||
|
template<typename ModuleT>
|
||||||
|
void getOrCreateModuleIndex(size_t* out_index, bool* out_module_exists){
|
||||||
|
static size_t module_index = modules.size();
|
||||||
|
*out_index = module_index;
|
||||||
|
// if module_index == modules.size(), then the module hasn't been pushed to the vector yet
|
||||||
|
*out_module_exists = module_index != modules.size();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class UsefulException_ : public std::exception {
|
|||||||
public:
|
public:
|
||||||
UsefulException_(const std::string& msg, const std::string& _file, const std::string& _func, int line_n);
|
UsefulException_(const std::string& msg, const std::string& _file, const std::string& _func, int line_n);
|
||||||
|
|
||||||
virtual char const* what() const noexcept;
|
char const* what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define useful_assert(EXPR, ERRMSG) if(!(EXPR)) throw UsefulException(ERRMSG);
|
#define useful_assert(EXPR, ERRMSG) if(!(EXPR)) throw UsefulException(ERRMSG);
|
||||||
|
|||||||
@ -35,6 +35,7 @@ public:
|
|||||||
std::enable_if_t<!std::is_void<RT>::value, RT> operator()(ArgTypes... args){
|
std::enable_if_t<!std::is_void<RT>::value, RT> operator()(ArgTypes... args){
|
||||||
if(func_ptr == nullptr)
|
if(func_ptr == nullptr)
|
||||||
throw UsefulException("function_shared_ptr is null");
|
throw UsefulException("function_shared_ptr is null");
|
||||||
|
//TODO: think about std::forward(args)...
|
||||||
return func_ptr->operator()(args...);
|
return func_ptr->operator()(args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,6 @@ typedef double f64;
|
|||||||
/// anonymous pointer without specified freeMembers() func
|
/// anonymous pointer without specified freeMembers() func
|
||||||
typedef void* Pointer;
|
typedef void* Pointer;
|
||||||
|
|
||||||
#define nameof(V) #V
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma comment(lib, "mincore_downlevel.lib") // Support OS older than SDK
|
#pragma comment(lib, "mincore_downlevel.lib") // Support OS older than SDK
|
||||||
|
|||||||
44
src/common/type_name_demangled.hpp
Normal file
44
src/common/type_name_demangled.hpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// https://stackoverflow.com/a/53865723
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#include <cxxabi.h>
|
||||||
|
#endif
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
std::string _ougge_type_name_demangled()
|
||||||
|
{
|
||||||
|
typedef typename std::remove_reference<T>::type TR;
|
||||||
|
const char* type_name_mangled = typeid(TR).name();
|
||||||
|
std::unique_ptr<char, void(*)(void*)> own
|
||||||
|
(
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
abi::__cxa_demangle(type_name_mangled, nullptr, nullptr, nullptr),
|
||||||
|
#else
|
||||||
|
nullptr,
|
||||||
|
#endif
|
||||||
|
std::free
|
||||||
|
);
|
||||||
|
std::string r = own ? own.get() : type_name_mangled;
|
||||||
|
|
||||||
|
if (std::is_const<TR>::value)
|
||||||
|
r += " const";
|
||||||
|
if (std::is_volatile<TR>::value)
|
||||||
|
r += " volatile";
|
||||||
|
if (std::is_lvalue_reference<T>::value)
|
||||||
|
r += "&";
|
||||||
|
else if (std::is_rvalue_reference<T>::value)
|
||||||
|
r += "&&";
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @return human-readable type name
|
||||||
|
template <class T>
|
||||||
|
const std::string& ougge_type_name(){
|
||||||
|
static std::string name = _ougge_type_name_demangled<T>();
|
||||||
|
return name;
|
||||||
|
}
|
||||||
54
src/main.cpp
54
src/main.cpp
@ -8,18 +8,22 @@
|
|||||||
|
|
||||||
using namespace ougge;
|
using namespace ougge;
|
||||||
|
|
||||||
class TutelModule : public EngineModule {
|
class TutelModule : public IEngineModule {
|
||||||
resources::CacheStorage<resources::Texture> textures;
|
resources::CacheStorage<resources::Texture> textures;
|
||||||
modules::MainWindowSDL2& mainWindow;
|
|
||||||
public:
|
public:
|
||||||
TutelModule(Engine& engine, resources::ResourceManager& resourceManager, modules::MainWindowSDL2& mainWindow) :
|
TutelModule(Engine& engine, resources::ResourceManager& resourceManager) :
|
||||||
EngineModule(engine, nameof(TutelModule)),
|
IEngineModule(engine),
|
||||||
textures(&resourceManager),
|
textures(&resourceManager)
|
||||||
mainWindow(mainWindow)
|
|
||||||
{
|
{
|
||||||
|
//TODO: add something like `assert(requireModule(MainWindow))`
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void beginFrame(){
|
const std::string& getName() override {
|
||||||
|
return ougge_type_name<TutelModule>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void beginFrame() override {
|
||||||
|
auto& mainWindow = engine.getModule<modules::MainWindowSDL2>();
|
||||||
resources::Texture* tutel = textures.tryGetOrCreate("tutel.png", mainWindow.sdl_renderer);
|
resources::Texture* tutel = textures.tryGetOrCreate("tutel.png", mainWindow.sdl_renderer);
|
||||||
if(tutel == nullptr){
|
if(tutel == nullptr){
|
||||||
throw new UsefulException("couldn't find resource 'tutel.png'");
|
throw new UsefulException("couldn't find resource 'tutel.png'");
|
||||||
@ -33,31 +37,27 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void createExampleObject(Engine& engine){
|
||||||
|
std::cout<<"creating ExampleObject"<<std::endl;
|
||||||
|
auto& monoSystem = engine.getModule<modules::MonoGameObjectSystem>();
|
||||||
|
game::GameObject& exampleObj = monoSystem.createGameObject();
|
||||||
|
std::string componentClassName = "Ougge.ExampleComponent";
|
||||||
|
if(!monoSystem.tryCreateComponent(exampleObj, componentClassName))
|
||||||
|
throw UsefulException(ougge_format("couldn't create component '%s'", componentClassName.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, const char** argv){
|
int main(int argc, const char** argv){
|
||||||
try {
|
try {
|
||||||
std::cout<<"initializing ResourceManager";
|
std::cout<<"Initializing Engine"<<std::endl;
|
||||||
resources::ResourceManager resourceManager;
|
|
||||||
|
|
||||||
std::cout<<"initializing Engine";
|
|
||||||
Engine engine;
|
Engine engine;
|
||||||
|
|
||||||
std::cout<<"initializing MainWindowSDL2"<<std::endl;
|
std::cout<<"Initializing ResourceManager"<<std::endl;
|
||||||
modules::MainWindowSDL2 mainWindow (engine, "ougge", resourceManager);
|
resources::ResourceManager resourceManager;
|
||||||
engine.addModule(&mainWindow);
|
|
||||||
|
|
||||||
std::cout<<"initializing MonoGameObjectSystem"<<std::endl;
|
engine.createModule<modules::MainWindowSDL2>("ougge", resourceManager);
|
||||||
modules::MonoGameObjectSystem monoSystem (engine, 64*1024);
|
engine.createModule<modules::MonoGameObjectSystem>(64*1024);
|
||||||
engine.addModule(&monoSystem);
|
createExampleObject(engine);
|
||||||
|
engine.createModule<TutelModule>(resourceManager);
|
||||||
std::cout<<"createing ExampleObject"<<std::endl;
|
|
||||||
game::GameObject& exampleObj = monoSystem.createGameObject();
|
|
||||||
std::string componentClassName = "Ougge.ExampleComponent";
|
|
||||||
if(!monoSystem.tryCreateComponent(exampleObj, componentClassName))
|
|
||||||
throw UsefulException(ougge_format("couldn't create component '%s'", componentClassName.c_str()));
|
|
||||||
|
|
||||||
std::cout<<"initializing TutelModule"<<std::endl;
|
|
||||||
TutelModule tutel (engine, resourceManager, mainWindow);
|
|
||||||
engine.addModule(&tutel);
|
|
||||||
|
|
||||||
std::cout<<"main loop start"<<std::endl;
|
std::cout<<"main loop start"<<std::endl;
|
||||||
engine.startLoop();
|
engine.startLoop();
|
||||||
|
|||||||
@ -10,6 +10,10 @@ using namespace ougge::gui;
|
|||||||
|
|
||||||
namespace ougge::modules {
|
namespace ougge::modules {
|
||||||
|
|
||||||
|
const std::string& MainWindowSDL2::getName() {
|
||||||
|
return ougge_type_name<MainWindowSDL2>();
|
||||||
|
}
|
||||||
|
|
||||||
f32 MainWindowSDL2::getDPI(){
|
f32 MainWindowSDL2::getDPI(){
|
||||||
i32 w=0, h=0;
|
i32 w=0, h=0;
|
||||||
SDL_GetRendererOutputSize(sdl_renderer, &w, &h);
|
SDL_GetRendererOutputSize(sdl_renderer, &w, &h);
|
||||||
@ -24,7 +28,7 @@ f32 MainWindowSDL2::getDPI(){
|
|||||||
MainWindowSDL2::MainWindowSDL2(Engine& engine,
|
MainWindowSDL2::MainWindowSDL2(Engine& engine,
|
||||||
const std::string& window_title,
|
const std::string& window_title,
|
||||||
resources::ResourceManager& resourceManager)
|
resources::ResourceManager& resourceManager)
|
||||||
: EngineModule(engine, nameof(MainWindowSDL2))
|
: IEngineModule(engine)
|
||||||
{
|
{
|
||||||
SDL_TRY(SDL_Init(SDL_INIT_EVERYTHING));
|
SDL_TRY(SDL_Init(SDL_INIT_EVERYTHING));
|
||||||
SDL_version v;
|
SDL_version v;
|
||||||
|
|||||||
@ -17,7 +17,7 @@ namespace ougge::modules {
|
|||||||
|
|
||||||
#define default_font_path "fonts/DroidSans.ttf"
|
#define default_font_path "fonts/DroidSans.ttf"
|
||||||
|
|
||||||
class MainWindowSDL2 : public EngineModule {
|
class MainWindowSDL2 : public IEngineModule {
|
||||||
public:
|
public:
|
||||||
f32 default_font_size = 14.0f;
|
f32 default_font_size = 14.0f;
|
||||||
ImVec4 clear_color = RGBAHexToF(35,35,50,255);
|
ImVec4 clear_color = RGBAHexToF(35,35,50,255);
|
||||||
@ -34,8 +34,9 @@ public:
|
|||||||
resources::ResourceManager& resourceManager);
|
resources::ResourceManager& resourceManager);
|
||||||
~MainWindowSDL2();
|
~MainWindowSDL2();
|
||||||
|
|
||||||
virtual void beginFrame();
|
const std::string& getName() override;
|
||||||
virtual void endFrame();
|
void beginFrame() override;
|
||||||
|
void endFrame() override;
|
||||||
|
|
||||||
f32 getDPI();
|
f32 getDPI();
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -2,8 +2,12 @@
|
|||||||
|
|
||||||
namespace ougge::modules {
|
namespace ougge::modules {
|
||||||
|
|
||||||
|
const std::string& MonoGameObjectSystem::getName() {
|
||||||
|
return ougge_type_name<MonoGameObjectSystem>();
|
||||||
|
}
|
||||||
|
|
||||||
MonoGameObjectSystem::MonoGameObjectSystem(Engine& engine, u32 max_game_objects) :
|
MonoGameObjectSystem::MonoGameObjectSystem(Engine& engine, u32 max_game_objects) :
|
||||||
EngineModule(engine, nameof(MonoGameObjectSystem)),
|
IEngineModule(engine),
|
||||||
gameObjectPool(max_game_objects)
|
gameObjectPool(max_game_objects)
|
||||||
{
|
{
|
||||||
engineManagedAssembly = mono.loadAssembly("Ougge.dll");
|
engineManagedAssembly = mono.loadAssembly("Ougge.dll");
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace ougge::modules {
|
namespace ougge::modules {
|
||||||
|
|
||||||
class MonoGameObjectSystem : public EngineModule {
|
class MonoGameObjectSystem : public IEngineModule {
|
||||||
Mono::RuntimeJIT mono;
|
Mono::RuntimeJIT mono;
|
||||||
game::GameObjectPool gameObjectPool;
|
game::GameObjectPool gameObjectPool;
|
||||||
u64 obj_id = 0;
|
u64 obj_id = 0;
|
||||||
@ -21,7 +21,8 @@ public:
|
|||||||
|
|
||||||
MonoGameObjectSystem(Engine& engine, u32 max_game_objects);
|
MonoGameObjectSystem(Engine& engine, u32 max_game_objects);
|
||||||
|
|
||||||
virtual void beginFrame();
|
const std::string& getName() override;
|
||||||
|
void beginFrame() override;
|
||||||
|
|
||||||
game::GameObject& createGameObject();
|
game::GameObject& createGameObject();
|
||||||
bool tryCreateComponent(game::GameObject& obj, const std::string& componentClassName);
|
bool tryCreateComponent(game::GameObject& obj, const std::string& componentClassName);
|
||||||
|
|||||||
@ -4,10 +4,10 @@ class MemoryStreamBuf : public std::streambuf {
|
|||||||
public:
|
public:
|
||||||
MemoryStreamBuf(void* p, const std::size_t n);
|
MemoryStreamBuf(void* p, const std::size_t n);
|
||||||
|
|
||||||
virtual std::istream::pos_type seekoff(
|
std::istream::pos_type seekoff(
|
||||||
std::istream::off_type off,
|
std::istream::off_type off,
|
||||||
std::ios_base::seekdir dir,
|
std::ios_base::seekdir dir,
|
||||||
std::ios_base::openmode which);
|
std::ios_base::openmode which) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
MemoryStreamBuf::MemoryStreamBuf(void* _p, const std::size_t n){
|
MemoryStreamBuf::MemoryStreamBuf(void* _p, const std::size_t n){
|
||||||
|
|||||||
@ -23,6 +23,7 @@ public:
|
|||||||
|
|
||||||
using ResourceMap = std::unordered_map<std::string, ResourceFactory>;
|
using ResourceMap = std::unordered_map<std::string, ResourceFactory>;
|
||||||
|
|
||||||
|
//TODO: rewrite ResourceManager as a module
|
||||||
class ResourceManager {
|
class ResourceManager {
|
||||||
std::list<std::shared_ptr<ResourceMap>> _resourceMaps;
|
std::list<std::shared_ptr<ResourceMap>> _resourceMaps;
|
||||||
static std::shared_ptr<ResourceMap> _embeddedResourcesMap;
|
static std::shared_ptr<ResourceMap> _embeddedResourcesMap;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user