split engine code into modules

This commit is contained in:
Timerix 2025-06-18 16:06:54 +05:00
parent 8fd6cee223
commit a288d0961f
10 changed files with 273 additions and 180 deletions

View File

@ -1,23 +1,27 @@
#include "Engine.hpp" #include "Engine.hpp"
#include "gui/gui.hpp" #include "common/UsefulException.hpp"
#include "common/ougge_format.hpp"
#include "common/time.hpp"
#include <SDL2/SDL.h>
#include <iostream>
namespace ougge { namespace ougge {
Engine::Engine(u32 game_object_pool_size) EngineModule::EngineModule(Engine& engine, const std::string& name)
: gameObjectPool(game_object_pool_size), textures(&resourceManager) : engine(engine), name(name)
{}
void EngineModule::beginFrame() {}
void EngineModule::endFrame() {}
void Engine::addModule(EngineModule* m){
modules.push_back(m);
}
void Engine::startLoop()
{ {
engineManagedAssembly = mono.loadAssembly("Ougge.dll");
gameObjectClass = engineManagedAssembly->getClass("Ougge", "GameObject");
gameObjectCtor = Mono::Method<void(u64, u32)>(gameObjectClass, ".ctor");
gameObjectInvokeUpdate = Mono::Method<void(f64)>(gameObjectClass, "InvokeUpdate");
gameObjectTryCreateComponent = Mono::Method<Mono::Bool(Mono::String)>(gameObjectClass, "TryCreateComponent_internal");
}
void Engine::openMainWindow(const std::string& window_title){
mainWindow.open(window_title, resourceManager);
}
void Engine::startLoop(){
if(loop_running) if(loop_running)
throw UsefulException("loop is running already"); throw UsefulException("loop is running already");
@ -25,87 +29,83 @@ void Engine::startLoop(){
loop_running=true; loop_running=true;
// main loop // main loop
while(loop_running){ while(loop_running){
mainWindow.pollEvents(&loop_running);
if(!loop_running)
break;
nsec_t update_time_ns = getMonotonicTimeNsec(); nsec_t update_time_ns = getMonotonicTimeNsec();
if(update_time_ns < prev_update_time_ns) if(update_time_ns < prev_update_time_ns)
throw UsefulException("monotonic clock returned unexpected value"); throw UsefulException("monotonic clock returned unexpected value");
f64 delta_time_s = (f64)(update_time_ns - prev_update_time_ns) / 1e9; f64 delta_time_s = (f64)(update_time_ns - prev_update_time_ns) / 1e9;
prev_update_time_ns = update_time_ns; prev_update_time_ns = update_time_ns;
deltaTime = delta_time_s;
tryDrawFrame(delta_time_s); tryDrawFrame();
nsec_t after_update_time_ns = getMonotonicTimeNsec(); nsec_t after_update_time_ns = getMonotonicTimeNsec();
nsec_t frame_delay_ns = (nsec_t)1e9 / mainWindow.fps_max - (after_update_time_ns - update_time_ns); nsec_t frame_delay_ns = (nsec_t)1e9 / fps_max - (after_update_time_ns - update_time_ns);
if(frame_delay_ns > 0){ if(frame_delay_ns > 0){
SDL_Delay(frame_delay_ns / 1e6); SDL_Delay(frame_delay_ns / 1e6);
} }
} }
mainWindow.close();
} }
void Engine::stopLoop(){ void Engine::stopLoop(){
loop_running = false; loop_running = false;
} }
void Engine::tryDrawFrame(f64 deltaTime){ void Engine::handleModuleError(EngineModule* module, const char* type, const char* method, const char* error){
static std::string error_message; std::string error_message = ougge_format(
static bool draw_error_window = false; "Catched %s at %s.%s(): %s",
try { type, module->name.c_str(), method, error);
mainWindow.beginFrame(); std::cerr<<error_message<<std::endl;
error_messages.push_back(error_message);
if(draw_error_window)
gui::drawErrorWindow(error_message, &draw_error_window);
else {
updateGameObjects(deltaTime);
if(!updateCallback.isNull())
updateCallback(deltaTime);
} }
mainWindow.endFrame();
void Engine::tryDrawFrame(){
auto it = modules.begin();
while(it != modules.end())
{
EngineModule* module = *it;
it++;
try {
module->beginFrame();
} }
catch(const std::exception& e){ catch(const std::exception& e){
error_message = "Catched exception: " + std::string(e.what()); handleModuleError(module, "exception", "beginFrame", e.what());
draw_error_window = true;
std::cerr<<error_message<<std::endl;
} }
catch(const char* cstr){ catch(const char* cstr){
error_message = "Catched error message (const char*): " + std::string(cstr); handleModuleError(module, "error message (const char*)", "beginFrame", cstr);
draw_error_window = true;
std::cerr<<error_message<<std::endl;
} }
catch(const std::string& str){ catch(const std::string& str){
error_message = "Catched error message (std::string): " + str; handleModuleError(module, "error message (std::string)", "beginFrame", str.c_str());
draw_error_window = true;
std::cerr<<error_message<<std::endl;
} }
catch(...){ catch(...){
error_message = "Catched unknown error"; handleModuleError(module, "unknown", "beginFrame", "unknown");
draw_error_window = true;
std::cerr<<error_message<<std::endl;
} }
} }
//TODO: frame expeption display
// if(draw_error_window)
// gui::drawErrorWindow(error_message, &draw_error_window);
void Engine::updateGameObjects(f64 deltaTime){ it = modules.end();
for(auto pair : gameObjectPool){ while(it != modules.begin())
gameObjectInvokeUpdate(pair.second.getObjectHandle().getObject(), deltaTime); {
it--;
EngineModule* module = *it;
try {
module->endFrame();
}
catch(const std::exception& e){
handleModuleError(module, "exception", "endFrame", e.what());
}
catch(const char* cstr){
handleModuleError(module, "error message (const char*)", "endFrame", cstr);
}
catch(const std::string& str){
handleModuleError(module, "error message (std::string)", "endFrame", str.c_str());
}
catch(...){
handleModuleError(module, "unknown", "endFrame", "unknown");
}
} }
} }
game::GameObject& Engine::createGameObject(){
auto pair = gameObjectPool.emplace(game::GameObject(mono.createObject(gameObjectClass)));
game::GameObject& obj = pair.second;
gameObjectCtor(obj.getObjectHandle().getObject(), ++obj_id, pair.first);
return obj;
}
bool Engine::tryCreateComponent(game::GameObject& obj, const std::string& componentClassName){
Mono::String componentClassNameManaged = mono.createString(componentClassName);
Mono::Bool created = gameObjectTryCreateComponent(obj.getObjectHandle().getObject(), componentClassNameManaged);
return created.wide_bool;
}
} }

View File

@ -1,49 +1,56 @@
#pragma once #pragma once
#include "common/function_shared_ptr.hpp" #include <vector>
#include "mono/mono.hpp" #include "common/std.hpp"
#include "game/GameObjectPool.hpp" #include "common/UsefulException.hpp"
#include "gui/MainWindow.hpp" #include "common/ougge_format.hpp"
#include "resources/textures.hpp"
namespace ougge { namespace ougge {
using UpdateFunc_t = function_shared_ptr<void(f64)>; class Engine;
class EngineModule {
public:
EngineModule() = delete;
EngineModule(const EngineModule&) = delete;
EngineModule& operator=(const EngineModule&) = delete;
EngineModule(EngineModule&&) = delete;
EngineModule& operator=(EngineModule&&) = delete;
Engine& engine;
const std::string name;
virtual void beginFrame();
virtual void endFrame();
protected:
EngineModule(Engine& engine, const std::string& name);
};
class Engine { class Engine {
std::vector<EngineModule*> modules;
bool loop_running = false; bool loop_running = false;
game::GameObjectPool gameObjectPool;
u64 obj_id = 0;
MonoClass* gameObjectClass;
Mono::Method<void(u64, u32)> gameObjectCtor;
Mono::Method<void(f64)> gameObjectInvokeUpdate;
Mono::Method<Mono::Bool(Mono::String)> gameObjectTryCreateComponent;
public: public:
gui::MainWindow mainWindow; u32 fps_max = 60;
UpdateFunc_t updateCallback; f64 deltaTime;
std::vector<std::string> error_messages;
Mono::RuntimeJIT mono; Engine() = default;
std::shared_ptr<Mono::Assembly> engineManagedAssembly; Engine(const Engine&) = delete;
Engine& operator=(const Engine&) = delete;
Engine(Engine&&) = delete;
Engine& operator=(Engine&&) = delete;
resources::ResourceManager resourceManager; void addModule(EngineModule* m);
resources::CacheStorage<resources::Texture> textures;
Engine(u32 game_object_pool_size = 64*1024);
void openMainWindow(const std::string& window_title);
// start game loop on the current thread // start game loop on the current thread
void startLoop(); void startLoop();
void stopLoop(); void stopLoop();
game::GameObject& createGameObject();
bool tryCreateComponent(game::GameObject& obj, const std::string& componentClassName);
private: private:
void tryDrawFrame(f64 deltaTime); void tryDrawFrame();
void updateGameObjects(f64 deltaTime); void handleModuleError(EngineModule *module, const char *type, const char *method, const char *error);
}; };
} }

View File

@ -30,8 +30,6 @@ public:
bool isNull() const { return func_ptr == nullptr; } bool isNull() const { return func_ptr == nullptr; }
//TODO: make inline
// ReturnT is not void // ReturnT is not void
template<typename RT = ReturnT> template<typename RT = ReturnT>
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){

View File

@ -1,11 +0,0 @@
#include "gui.hpp"
namespace ougge::gui {
void drawErrorWindow(const std::string& msg, bool* draw_error_window){
ImGui::Begin("ERROR", draw_error_window);
ImGui::Text("%s", msg.c_str());
ImGui::End();
}
}

View File

@ -1,11 +0,0 @@
#pragma once
#include <SDL.h>
#include <imgui.h>
#include "gui_exceptions.hpp"
namespace ougge::gui {
void drawErrorWindow(const std::string& msg, bool* draw_error_window);
}

View File

@ -1,46 +1,67 @@
#define SDL_MAIN_HANDLED #define SDL_MAIN_HANDLED
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include "common/UsefulException.hpp"
#include "common/ougge_format.hpp"
#include "Engine.hpp" #include "Engine.hpp"
#include "gui/gui.hpp" #include "modules/MainWindowSDL2.hpp"
#include "modules/MonoGameObjectSystem.hpp"
#include "resources/textures.hpp"
using namespace ougge; using namespace ougge;
void drawTutel(Engine& engine){ class TutelModule : public EngineModule {
resources::Texture* tutel = engine.textures.tryGetOrCreate("tutel.png", engine.mainWindow.sdl_renderer); resources::CacheStorage<resources::Texture> textures;
modules::MainWindowSDL2& mainWindow;
public:
TutelModule(Engine& engine, resources::ResourceManager& resourceManager, modules::MainWindowSDL2& mainWindow) :
EngineModule(engine, nameof(TutelModule)),
textures(&resourceManager),
mainWindow(mainWindow)
{
}
virtual void beginFrame(){
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'");
} }
resources::SDL_RenderCopyExF_Params params; resources::SDL_RenderCopyExF_Params params;
params.target_section = SDL_FRectConstruct(100, 100, 400, 400); params.target_section = SDL_FRectConstruct(100, 100, 400, 400);
static i32 si = 1; static i32 si = 1;
params.rotation_angle = M_PI_4 * (si++ / engine.mainWindow.fps_max); params.rotation_angle = M_PI_4 * (si++ / engine.fps_max);
tutel->render(params); tutel->render(params);
} }
int main(int argc, const char** argv){
try {
std::cout<<"initializing game engine... ";
Engine engine;
std::cout<<"done"<<std::endl;
game::GameObject& exampleObj = engine.createGameObject();
std::string componentClassName = "Ougge.ExampleComponent";
if(!engine.tryCreateComponent(exampleObj, componentClassName))
throw UsefulException(ougge_format("couldn't create component '%s'", componentClassName.c_str()));
std::cout<<"created ExampleObject"<<std::endl;
engine.updateCallback = [&engine](f64 deltaTime) -> void {
drawTutel(engine);
}; };
engine.openMainWindow("ougge"); int main(int argc, const char** argv){
std::cout<<"created sdl window"<<std::endl; try {
std::cout<<"initializing ResourceManager";
resources::ResourceManager resourceManager;
std::cout<<"initializing Engine";
Engine engine;
std::cout<<"initializing MainWindowSDL2"<<std::endl;
modules::MainWindowSDL2 mainWindow (engine, "ougge", resourceManager);
engine.addModule(&mainWindow);
std::cout<<"initializing MonoGameObjectSystem"<<std::endl;
modules::MonoGameObjectSystem monoSystem (engine, 64*1024);
engine.addModule(&monoSystem);
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;
engine.startLoop(); engine.startLoop();
std::cout<<"sdl window has been cosed"<<std::endl; std::cout<<"main loop stop"<<std::endl;
} }
catch(const std::exception& e){ catch(const std::exception& e){
std::cerr<<"Catched exception: "<<e.what()<<std::endl; std::cerr<<"Catched exception: "<<e.what()<<std::endl;

View File

@ -1,14 +1,16 @@
#include <backends/imgui_impl_sdl2.h> #include <backends/imgui_impl_sdl2.h>
#include <backends/imgui_impl_sdlrenderer2.h> #include <backends/imgui_impl_sdlrenderer2.h>
#include <iostream> #include <iostream>
#include "MainWindow.hpp" #include "MainWindowSDL2.hpp"
#include "gui_exceptions.hpp" #include "../gui/gui_exceptions.hpp"
#include "../common/ougge_format.hpp" #include "../common/ougge_format.hpp"
#include "../common/math.hpp" #include "../common/math.hpp"
namespace ougge::gui { using namespace ougge::gui;
f32 MainWindow::getDPI(){ namespace ougge::modules {
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);
i32 sim_w=0, sim_h=0; i32 sim_w=0, sim_h=0;
@ -19,7 +21,11 @@ f32 MainWindow::getDPI(){
return dpi; return dpi;
} }
void MainWindow::open(const std::string& window_title, resources::ResourceManager& resourceManager){ MainWindowSDL2::MainWindowSDL2(Engine& engine,
const std::string& window_title,
resources::ResourceManager& resourceManager)
: EngineModule(engine, nameof(MainWindowSDL2))
{
SDL_TRY(SDL_Init(SDL_INIT_EVERYTHING)); SDL_TRY(SDL_Init(SDL_INIT_EVERYTHING));
SDL_version v; SDL_version v;
SDL_GetVersion(&v); SDL_GetVersion(&v);
@ -78,7 +84,7 @@ void MainWindow::open(const std::string& window_title, resources::ResourceManage
io.FontDefault = resources::ImFont_LoadFromResource(font_res, default_font_size, dpi); io.FontDefault = resources::ImFont_LoadFromResource(font_res, default_font_size, dpi);
} }
void MainWindow::close(){ MainWindowSDL2::~MainWindowSDL2(){
ImGui_ImplSDLRenderer2_Shutdown(); ImGui_ImplSDLRenderer2_Shutdown();
ImGui_ImplSDL2_Shutdown(); ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext(); ImGui::DestroyContext();
@ -87,20 +93,22 @@ void MainWindow::close(){
SDL_Quit(); SDL_Quit();
} }
void MainWindow::pollEvents(bool* loopRunning){ void MainWindowSDL2::pollEvents(){
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
ImGui_ImplSDL2_ProcessEvent(&event); ImGui_ImplSDL2_ProcessEvent(&event);
switch(event.type){ switch(event.type){
case SDL_QUIT: { case SDL_QUIT: {
*loopRunning = false; //TODO: log SDL_QUIT event
engine.stopLoop();
break; break;
} }
case SDL_WINDOWEVENT: { case SDL_WINDOWEVENT: {
if(event.window.event == SDL_WINDOWEVENT_CLOSE if(event.window.event == SDL_WINDOWEVENT_CLOSE
&& event.window.windowID == SDL_GetWindowID(sdl_window)) && event.window.windowID == SDL_GetWindowID(sdl_window))
{ {
*loopRunning = false; //TODO: log SDL_WINDOWEVENT event
engine.stopLoop();
} }
break; break;
} }
@ -108,8 +116,10 @@ void MainWindow::pollEvents(bool* loopRunning){
} }
} }
void MainWindowSDL2::beginFrame(){
// process events happend since previous frame
pollEvents();
void MainWindow::beginFrame(){
// Start the Dear ImGui frame // Start the Dear ImGui frame
ImGui_ImplSDLRenderer2_NewFrame(); ImGui_ImplSDLRenderer2_NewFrame();
ImGui_ImplSDL2_NewFrame(); ImGui_ImplSDL2_NewFrame();
@ -126,16 +136,17 @@ void MainWindow::beginFrame(){
draw_bg_window(); draw_bg_window();
draw_debug_window(); draw_debug_window();
drawErrorWindow();
} }
void MainWindow::endFrame(){ void MainWindowSDL2::endFrame(){
ImGui::Render(); ImGui::Render();
ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData(), sdl_renderer); ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData(), sdl_renderer);
// Swap buffers // Swap buffers
SDL_RenderPresent(sdl_renderer); SDL_RenderPresent(sdl_renderer);
} }
void MainWindow::draw_bg_window(){ void MainWindowSDL2::draw_bg_window(){
const ImGuiDockNodeFlags dockspace_flags = const ImGuiDockNodeFlags dockspace_flags =
ImGuiDockNodeFlags_PassthruCentralNode; ImGuiDockNodeFlags_PassthruCentralNode;
const ImGuiWindowFlags window_flags = const ImGuiWindowFlags window_flags =
@ -199,11 +210,11 @@ void MainWindow::draw_bg_window(){
ImGui::End(); ImGui::End();
} }
void MainWindow::draw_debug_window(){ void MainWindowSDL2::draw_debug_window(){
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
if(ImGui::Begin("Debug Options", &show_debug_window)){ if(ImGui::Begin("Debug Options", &show_debug_window)){
ImGui::ColorEdit3("clear_color", (float*)&clear_color); ImGui::ColorEdit3("clear_color", (float*)&clear_color);
ImGui::InputInt("fps_max", &fps_max); ImGui::InputInt("fps_max", (int*)&engine.fps_max);
ImGui::Text("Application average %.3f ms/frame (%.2f FPS)", 1000.0f / io.Framerate, io.Framerate); ImGui::Text("Application average %.3f ms/frame (%.2f FPS)", 1000.0f / io.Framerate, io.Framerate);
ImGui::Checkbox("Demo Window", &show_demo_window); ImGui::Checkbox("Demo Window", &show_demo_window);
ImGui::Checkbox("Metrics/Debug Window", &show_metrics_window); ImGui::Checkbox("Metrics/Debug Window", &show_metrics_window);
@ -217,4 +228,16 @@ void MainWindow::draw_debug_window(){
ImGui::ShowMetricsWindow(&show_metrics_window); ImGui::ShowMetricsWindow(&show_metrics_window);
} }
void MainWindowSDL2::drawErrorWindow(){
if(engine.error_messages.size() < 1)
return;
ImGui::Begin("ERRORS");
if(ImGui::Button("Clear"))
engine.error_messages.clear();
for(auto& msg : engine.error_messages){
ImGui::TextWrapped("%s", msg.c_str());
}
ImGui::End();
}
} }

View File

@ -2,23 +2,23 @@
#include <SDL.h> #include <SDL.h>
#include <imgui.h> #include <imgui.h>
#include <vector>
#include "../common/std.hpp" #include "../common/std.hpp"
#include "../common/time.hpp"
#include "../resources/resources.hpp" #include "../resources/resources.hpp"
#include "../resources/fonts.hpp" #include "../resources/fonts.hpp"
#include "../Engine.hpp"
namespace ougge::modules {
/// converts hex color to float vector /// 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) #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 /// 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)} #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" #define default_font_path "fonts/DroidSans.ttf"
class MainWindow { class MainWindowSDL2 : public EngineModule {
public: public:
i32 fps_max = 60;
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);
SDL_Window* sdl_window = nullptr; SDL_Window* sdl_window = nullptr;
@ -30,18 +30,19 @@ private:
bool show_metrics_window = false; bool show_metrics_window = false;
public: public:
void open(const std::string& window_title, resources::ResourceManager& resourceManager); MainWindowSDL2(Engine& engine, const std::string& window_title,
void close(); resources::ResourceManager& resourceManager);
~MainWindowSDL2();
/// process io events happened since previous frame virtual void beginFrame();
void pollEvents(bool* loopRunning); virtual void endFrame();
void beginFrame();
void endFrame();
f32 getDPI(); f32 getDPI();
private: private:
void pollEvents();
void draw_debug_window(); void draw_debug_window();
void draw_bg_window(); void draw_bg_window();
void drawErrorWindow();
}; };
} }

View File

@ -0,0 +1,35 @@
#include "MonoGameObjectSystem.hpp"
namespace ougge::modules {
MonoGameObjectSystem::MonoGameObjectSystem(Engine& engine, u32 max_game_objects) :
EngineModule(engine, nameof(MonoGameObjectSystem)),
gameObjectPool(max_game_objects)
{
engineManagedAssembly = mono.loadAssembly("Ougge.dll");
gameObjectClass = engineManagedAssembly->getClass("Ougge", "GameObject");
gameObjectCtor = Mono::Method<void(u64, u32)>(gameObjectClass, ".ctor");
gameObjectInvokeUpdate = Mono::Method<void(f64)>(gameObjectClass, "InvokeUpdate");
gameObjectTryCreateComponent = Mono::Method<Mono::Bool(Mono::String)>(gameObjectClass, "TryCreateComponent_internal");
}
void MonoGameObjectSystem::beginFrame(){
for(auto pair : gameObjectPool){
gameObjectInvokeUpdate(pair.second.getObjectHandle().getObject(), engine.deltaTime);
}
}
game::GameObject& MonoGameObjectSystem::createGameObject(){
auto pair = gameObjectPool.emplace(game::GameObject(mono.createObject(gameObjectClass)));
game::GameObject& obj = pair.second;
gameObjectCtor(obj.getObjectHandle().getObject(), ++obj_id, pair.first);
return obj;
}
bool MonoGameObjectSystem::tryCreateComponent(game::GameObject& obj, const std::string& componentClassName){
Mono::String componentClassNameManaged = mono.createString(componentClassName);
Mono::Bool created = gameObjectTryCreateComponent(obj.getObjectHandle().getObject(), componentClassNameManaged);
return created.wide_bool;
}
}

View File

@ -0,0 +1,30 @@
#pragma once
#include "../Engine.hpp"
#include "../common/function_shared_ptr.hpp"
#include "../mono/mono.hpp"
#include "../game/GameObjectPool.hpp"
namespace ougge::modules {
class MonoGameObjectSystem : public EngineModule {
Mono::RuntimeJIT mono;
game::GameObjectPool gameObjectPool;
u64 obj_id = 0;
MonoClass* gameObjectClass;
Mono::Method<void(u64, u32)> gameObjectCtor;
Mono::Method<void(f64)> gameObjectInvokeUpdate;
Mono::Method<Mono::Bool(Mono::String)> gameObjectTryCreateComponent;
public:
std::shared_ptr<Mono::Assembly> engineManagedAssembly;
MonoGameObjectSystem(Engine& engine, u32 max_game_objects);
virtual void beginFrame();
game::GameObject& createGameObject();
bool tryCreateComponent(game::GameObject& obj, const std::string& componentClassName);
};
}