diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a32d57..ed3086f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,8 @@ add_executable(CodingGame src/IO/parser.cpp src/IO/file_manager.cpp + src/window/window.cpp + src/renderer/debug.cpp src/renderer/basics.cpp src/renderer/mesh.cpp @@ -38,9 +40,6 @@ add_executable(CodingGame src/renderer/wavefront.cpp src/renderer/engine.cpp - include/window/event.hpp - src/window/window.cpp - src/main.cpp ) diff --git a/include/app/app.h b/include/app/app.h new file mode 100644 index 0000000..5cdaa22 --- /dev/null +++ b/include/app/app.h @@ -0,0 +1,19 @@ +#ifndef APPLICATION_H_ +#define APPLICATION_H_ + +#include "window/event.h" + +class IApplication { +public: + virtual ~IApplication() = default; + + virtual void OnInit() {}; + virtual void OnUpdate() {}; + virtual void OnRender() {}; + virtual void OnShutdown() {}; + + virtual void OnEvent() {}; + virtual void OnWindowResized(const WindowResized& e) {}; +}; + +#endif // APPLICATION_H_ \ No newline at end of file diff --git a/include/renderer/engine.h b/include/renderer/engine.h index 60ecf77..e60e55a 100644 --- a/include/renderer/engine.h +++ b/include/renderer/engine.h @@ -7,23 +7,17 @@ #include "window/window.h" #include "window/events/window.h" +#include "app/app.h" + class Engine { -private: - std::unique_ptr m_window; - bool m_isRunning; -private: - glm::mat4 m_projection; public: - Engine(); - ~Engine(); -private: - void Stop(); - void Destroy() const; - [[nodiscard]] bool Running() const; + static void Run(std::unique_ptr app); private: void HandleWindowResized(const WindowResized& event); -public: - void Run(); +private: + static std::unique_ptr s_app; + static std::shared_ptr s_window; + static bool s_running; }; diff --git a/include/renderer/wavefront.h b/include/renderer/wavefront.h index 51f0896..23e3ad1 100644 --- a/include/renderer/wavefront.h +++ b/include/renderer/wavefront.h @@ -32,7 +32,9 @@ private: private: Object(); public: - static Object LoadFile(const std::string& filename); + ~Object() = default; +public: + static Object* LoadFile(const std::string& filename); private: void LoadMaterials(const std::filesystem::path& filename); diff --git a/include/window/event.hpp b/include/window/event.h similarity index 69% rename from include/window/event.hpp rename to include/window/event.h index 4f07ac4..afddfb6 100644 --- a/include/window/event.hpp +++ b/include/window/event.h @@ -3,11 +3,12 @@ #include #include +#include #include #include #include -class EventBus { +class EventDispatcher { using Type = std::type_index; using RawFn = std::function; @@ -24,7 +25,7 @@ public: }; template - Handle subscribe(F&& f) { + Handle Subscribe(F&& f) { auto& vec = subs_[Type(typeid(E))]; Handle h{ Type(typeid(E)), next_id_++ }; // Wrap strongly typed callback into type-erased RawFn @@ -36,7 +37,7 @@ public: } // Unsubscribe with handle - void unsubscribe(const Handle& h) { + void Unsubscribe(const Handle& h) { auto it = subs_.find(h.type); if (it == subs_.end()) return; auto& vec = it->second; @@ -47,26 +48,11 @@ public: // Publish immediately template - void publish(const E& e) const { + void Dispatch(const E& e) const { auto it = subs_.find(Type(typeid(E))); if (it == subs_.end()) return; for (auto& slot : it->second) slot.fn(&e); } }; -// Optional RAII helper -struct ScopedSub { - EventBus* bus{}; - EventBus::Handle h{}; - ScopedSub() = default; - ScopedSub(EventBus& b, EventBus::Handle hh) : bus(&b), h(hh) {} - ScopedSub(ScopedSub&& o) noexcept { *this = std::move(o); } - ScopedSub& operator=(ScopedSub&& o) noexcept { - if (this != &o) { reset(); bus = o.bus; h = o.h; o.bus = nullptr; } - return *this; - } - ~ScopedSub(){ reset(); } - void reset(){ if (bus && h) bus->unsubscribe(h); bus=nullptr; h={}; } -}; - #endif // EVENT_H_ \ No newline at end of file diff --git a/include/window/window.h b/include/window/window.h index 710d8da..7d562a4 100644 --- a/include/window/window.h +++ b/include/window/window.h @@ -1,8 +1,9 @@ #ifndef WINDOW_H_ #define WINDOW_H_ #include +#include -#include "event.hpp" +#include "event.h" #define ENGINE_GL_MAJOR_VERSION 4 #define ENGINE_GL_MINOR_VERSION 6 @@ -12,35 +13,39 @@ #define DEFAULT_WIDTH 1024 #define DEFAULT_HEIGHT 768 -class Window : public EventBus { +class Window : public EventDispatcher { + friend class Engine; private: - SDL_Window *m_handle; - SDL_GLContext m_context; - - int m_width; - int m_height; - - bool m_is_open; -public: Window(); Window(const char* title, int width, int height); ~Window(); + struct WindowDeleter { + void operator()(Window* w) const { delete w; }; + }; +public: + static std::shared_ptr GetInstance(); + Window(Window&& window) noexcept; Window& operator=(Window&& window) noexcept; Window(const Window& window) noexcept = delete; Window& operator=(const Window& window) noexcept = delete; public: - [[nodiscard]] inline int GetWidth() const { return m_width; } - [[nodiscard]] inline int GetHeight() const { return m_height; } - [[nodiscard]] inline bool IsOpen() const { return m_is_open; } -public: + [[nodiscard]] static inline int GetWidth() { return Window::GetInstance()->m_width; } + [[nodiscard]] static inline int GetHeight() { return Window::GetInstance()->m_height; } +private: void ProcessEvents(); -public: void SwapBuffers() const; -public: void Destroy() const; +private: + static std::shared_ptr s_instance; + + SDL_Window *m_handle; + SDL_GLContext m_context; + + int m_width; + int m_height; }; #endif //WINDOW_H_ \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 1dfcda1..a06f0f4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,12 +2,205 @@ #define GLEW_STATIC #endif +#include +#include + +#ifdef WIN32 +#include +#endif +#include +#include +#include +#include + +#include "renderer/shader.h" +#include "renderer/wavefront.h" #include "renderer/engine.h" +#include "IO/file_manager.h" + +class Game : public IApplication { +public: + Game() {} + ~Game() override {} + + void OnInit() override { + std::cout << "Game initialized" << std::endl; + + m_proj = glm::perspective( + static_cast(M_PI_2), + static_cast(Window::GetWidth()) / static_cast(Window::GetHeight()), + 0.01f, + 100.0f + ); + + m_shader.init( + FileManager::read("./src/shaders/simple.vs"), + FileManager::read("./src/shaders/simple.fs") + ); + + m_camPos = glm::vec3(0.f, 0.f, 2.f); + // glm::vec3 cameraViewDirection(0.f, 0.f, -1.f); + // glm::vec3 lightPosition(1.f, 3.5f, -2.f); + m_lightPos = glm::vec3(-5.f, 5.f, 5.f); + + m_model = glm::mat4(1.f); + + m_angle = 3.45f; + m_lastTicks = SDL_GetTicks(); + + // m_sun = Object::LoadFile("./assets/cube.obj"); + // m_target = Object::LoadFile("./assets/monkey.obj"); + + m_sun = std::unique_ptr(Object::LoadFile("./assets/cube.obj")); + m_target = std::unique_ptr(Object::LoadFile("./assets/monkey.obj")); + + m_paused = false; + + m_yaw = -90.0f; // looking along -Z initially + m_pitch = 0.0f; // no vertical tilt + + // FPS tracking + m_startTicks = SDL_GetTicks(); + m_frameCount = 0; + } + + void OnWindowResized(const WindowResized& event) override { + m_proj = glm::perspective( + static_cast(M_PI_2), + static_cast(event.w) / static_cast(event.h), + 0.01f, + 100.0f + ); + } + + void OnUpdate() override { + m_currentTicks = SDL_GetTicks(); + float deltaTime = static_cast(m_currentTicks - m_lastTicks) / 1000.0f; // seconds + + m_lastTicks = m_currentTicks; + + float mouseXRel, mouseYRel; + SDL_GetRelativeMouseState(&mouseXRel, &mouseYRel); + + float sensitivity = 0.1f; // tweak as needed + m_yaw += mouseXRel * sensitivity; + m_pitch -= mouseYRel * sensitivity; // invert Y for typical FPS control + + // clamp pitch to avoid flipping + // if (pitch > 89.0f) pitch = 89.0f; + // if (pitch < -89.0f) pitch = -89.0f; + m_pitch = glm::clamp(m_pitch, -89.0f, 89.0f); + + // convert to direction vector + glm::vec3 cameraViewDirection(0.f, 0.f, -1.f); + cameraViewDirection.x = cos(glm::radians(m_yaw)) * cos(glm::radians(m_pitch)); + cameraViewDirection.y = sin(glm::radians(m_pitch)); + cameraViewDirection.z = sin(glm::radians(m_yaw)) * cos(glm::radians(m_pitch)); + cameraViewDirection = glm::normalize(cameraViewDirection); + + glm::vec3 velocity(0.f); + + const bool* state = SDL_GetKeyboardState(nullptr); + + if (state[SDL_SCANCODE_P]) m_paused = !m_paused; + + glm::vec3 front = glm::normalize(glm::vec3(cameraViewDirection.x, 0.f, cameraViewDirection.z)); + glm::vec3 right = glm::normalize(glm::cross(front, glm::vec3(0.f, 1.f, 0.f))); + + if (state[SDL_SCANCODE_W]) velocity += front; + if (state[SDL_SCANCODE_S]) velocity -= front; + if (state[SDL_SCANCODE_A]) velocity -= right; + if (state[SDL_SCANCODE_D]) velocity += right; + if (state[SDL_SCANCODE_SPACE]) velocity.y += 1.f; + if (state[SDL_SCANCODE_LSHIFT]) velocity.y -= 1.f; + + m_camPos += velocity * deltaTime * 2.5f; // speed is e.g. 2.5f + + m_view = glm::lookAt( + m_camPos, + m_camPos + cameraViewDirection, + glm::vec3(0.f, 1.f, 0.f) + ); + + // update rotation + if (!m_paused) { + m_angle += glm::radians(45.0f) * deltaTime; // 72° per second + if (m_angle > glm::two_pi()) { + m_angle -= glm::two_pi(); // keep value small + } + } + } + + void OnRender() override { + m_shader.use(); + + m_shader.setMat4("u_view", m_view); + m_shader.setMat4("u_projection", m_proj); + + m_shader.setVec3("lightColor", glm::vec3(1.0f, 1.0f, 1.0f)); + m_shader.setVec3("lightPos", m_lightPos); + m_shader.setVec3("viewPos", m_camPos); + + m_model = glm::mat4(1.f); + m_model = glm::translate(m_model, m_lightPos); + + m_shader.setMat4("u_model", m_model); + + m_sun->Render(m_shader); + + // lightPosition -= glm::vec3(0.05f, 0.f, 0.f) * deltaTime; + + m_model = glm::rotate( + glm::mat4(1.f), + m_angle, + glm::vec3(0.f, -0.5f, 0.0f) + ) * 0.5f; + + m_shader.setMat4("u_model", m_model); + + m_target->Render(m_shader); + + m_frameCount++; + m_currentTicks = SDL_GetTicks(); + Uint64 elapsed = m_currentTicks - m_startTicks; + + if (elapsed >= 1000) { // one second passed + double fps = static_cast(m_frameCount) / (static_cast(elapsed) / 1000.0); + std::cout << "FPS: " << fps << std::endl; + m_frameCount = 0; + m_startTicks = m_currentTicks; + } + } +private: + Shader m_shader; + + glm::mat4 m_model; + glm::mat4 m_proj; + glm::mat4 m_view; + + glm::vec3 m_camPos; + glm::vec3 m_lightPos; + + float m_angle; + Uint64 m_lastTicks; + + std::unique_ptr m_sun = nullptr; + std::unique_ptr m_target = nullptr; + + bool m_paused = false; + + float m_yaw = -90.0f; // looking along -Z initially + float m_pitch = 0.0f; // no vertical tilt + + // FPS tracking + Uint64 m_startTicks; + int m_frameCount; + + Uint64 m_currentTicks; +}; + int main() { - Engine engine; - - engine.Run(); - + Engine::Run(std::make_unique()); return 0; } \ No newline at end of file diff --git a/src/renderer/engine.cpp b/src/renderer/engine.cpp index 4f44b45..b26dec4 100644 --- a/src/renderer/engine.cpp +++ b/src/renderer/engine.cpp @@ -1,195 +1,47 @@ -#include "renderer/engine.h" +#include -#ifdef WIN32 -#include -#endif -#include -#include -#include +#include "renderer/engine.h" +#include "window/event.h" #include "IO/file_manager.h" #include "renderer/shader.h" #include "renderer/wavefront.h" -Engine::Engine() { - m_window = std::make_unique(); - m_isRunning = true; - m_projection = glm::perspective( - static_cast(M_PI_2), - static_cast(m_window->GetWidth()) / static_cast(m_window->GetHeight()), - 0.01f, - 100.0f - ); +std::unique_ptr Engine::s_app = nullptr; +std::shared_ptr Engine::s_window = nullptr; +bool Engine::s_running = false; - m_window->subscribe([this](const WindowResized& e) { - HandleWindowResized(e); +void Engine::Run(std::unique_ptr app) { + s_app = std::move(app); + s_window = Window::GetInstance(); + s_running = true; + + s_app->OnInit(); + + s_window->Subscribe([](const WindowCloseRequested& e) { + Engine::s_running = false; }); - m_window->subscribe([this](const WindowCloseRequested& e) { - Stop(); + s_window->Subscribe([](const WindowResized& e) { + Engine::s_app->OnWindowResized(e); }); -} -bool Engine::Running() const { - return m_isRunning && m_window->IsOpen(); -} - -void Engine::Stop() { - m_isRunning = false; -} - -void Engine::HandleWindowResized(const WindowResized& event) { - m_projection = glm::perspective( - static_cast(M_PI_2), - static_cast(event.w) / static_cast(event.h), - 0.01f, - 100.0f - ); -} - - -void Engine::Run() { - Shader simpleShader; - simpleShader.init( - FileManager::read("./src/shaders/simple.vs"), - FileManager::read("./src/shaders/simple.fs") - ); - - glm::vec3 cameraPosition(0.f, 0.f, 2.f); - // glm::vec3 cameraViewDirection(0.f, 0.f, -1.f); - // glm::vec3 lightPosition(1.f, 3.5f, -2.f); - glm::vec3 lightPosition(-5.f, 5.f, 5.f); - - glm::mat4 model(1.f); - - float angle = 3.45f; - Uint64 lastTicks = SDL_GetTicks(); - - Object lightSource = Object::LoadFile("./assets/cube.obj"); - Object target = Object::LoadFile("./assets/monkey.obj"); - - bool paused = false; - - float yaw = -90.0f; // looking along -Z initially - float pitch = 0.0f; // no vertical tilt - - // FPS tracking - Uint64 startTicks = SDL_GetTicks(); - int frameCount = 0; - - while (m_isRunning) { - m_window->ProcessEvents(); - - Uint64 currentTicks = SDL_GetTicks(); - float deltaTime = static_cast(currentTicks - lastTicks) / 1000.0f; // seconds - - lastTicks = currentTicks; - - float mouseXRel, mouseYRel; - SDL_GetRelativeMouseState(&mouseXRel, &mouseYRel); - - float sensitivity = 0.1f; // tweak as needed - yaw += mouseXRel * sensitivity; - pitch -= mouseYRel * sensitivity; // invert Y for typical FPS control - - // clamp pitch to avoid flipping - // if (pitch > 89.0f) pitch = 89.0f; - // if (pitch < -89.0f) pitch = -89.0f; - pitch = glm::clamp(pitch, -89.0f, 89.0f); - - // convert to direction vector - glm::vec3 cameraViewDirection(0.f, 0.f, -1.f); - cameraViewDirection.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch)); - cameraViewDirection.y = sin(glm::radians(pitch)); - cameraViewDirection.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch)); - cameraViewDirection = glm::normalize(cameraViewDirection); - - glm::vec3 velocity(0.f); - - const bool* state = SDL_GetKeyboardState(nullptr); - - if (state[SDL_SCANCODE_P]) paused = !paused; - - glm::vec3 front = glm::normalize(glm::vec3(cameraViewDirection.x, 0.f, cameraViewDirection.z)); - glm::vec3 right = glm::normalize(glm::cross(front, glm::vec3(0.f, 1.f, 0.f))); - - if (state[SDL_SCANCODE_W]) velocity += front; - if (state[SDL_SCANCODE_S]) velocity -= front; - if (state[SDL_SCANCODE_A]) velocity -= right; - if (state[SDL_SCANCODE_D]) velocity += right; - if (state[SDL_SCANCODE_SPACE]) velocity.y += 1.f; - if (state[SDL_SCANCODE_LSHIFT]) velocity.y -= 1.f; - - cameraPosition += velocity * deltaTime * 2.5f; // speed is e.g. 2.5f - - glm::mat4 view = glm::lookAt( - cameraPosition, - cameraPosition + cameraViewDirection, - glm::vec3(0.f, 1.f, 0.f) - ); - - // update rotation - if (!paused) { - angle += glm::radians(45.0f) * deltaTime; // 72° per second - if (angle > glm::two_pi()) { - angle -= glm::two_pi(); // keep value small - } - } + while (s_running) { + s_window->ProcessEvents(); + s_app->OnUpdate(); + glClearColor(0x18/255.0f, 0x18/255.0f, 0x18/255.0f, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // Triangle render - { - simpleShader.use(); + s_app->OnRender(); - simpleShader.setMat4("u_view", view); - simpleShader.setMat4("u_projection", m_projection); - - simpleShader.setVec3("lightColor", glm::vec3(1.0f, 1.0f, 1.0f)); - simpleShader.setVec3("lightPos", lightPosition); - simpleShader.setVec3("viewPos", cameraPosition); - - model = glm::mat4(1.f); - model = glm::translate(model, lightPosition); - - simpleShader.setMat4("u_model", model); - - lightSource.Render(simpleShader); - - // lightPosition -= glm::vec3(0.05f, 0.f, 0.f) * deltaTime; - - model = glm::rotate( - glm::mat4(1.f), - angle, - glm::vec3(0.f, -0.5f, 0.0f) - ) * 0.5f; - - simpleShader.setMat4("u_model", model); - - target.Render(simpleShader); - } - - m_window->SwapBuffers(); - - frameCount++; - currentTicks = SDL_GetTicks(); - Uint64 elapsed = currentTicks - startTicks; - - if (elapsed >= 1000) { // one second passed - double fps = static_cast(frameCount) / (static_cast(elapsed) / 1000.0); - std::cout << "FPS: " << fps << std::endl; - frameCount = 0; - startTicks = currentTicks; - } + s_window->SwapBuffers(); } -} - -Engine::~Engine() { - Destroy(); -} - -void Engine::Destroy() const { - m_window->Destroy(); + + s_app->OnShutdown(); + + s_window->Destroy(); + s_app.reset(); } diff --git a/src/renderer/wavefront.cpp b/src/renderer/wavefront.cpp index 5612a17..601a978 100644 --- a/src/renderer/wavefront.cpp +++ b/src/renderer/wavefront.cpp @@ -259,14 +259,14 @@ Mesh& Object::GetLastMesh() return m_meshes.back(); } -Object Object::LoadFile(const std::string& filename) { +Object* Object::LoadFile(const std::string& filename) { std::ifstream file(filename); if (!file.is_open()) { std::cerr << "Failed to open OBJ file: " << filename << std::endl; return {}; } - Object obj; + Object* obj = new Object(); char line[1024]; // static buffer for each line (enough for OBJ lines) while (file.getline(line, sizeof(line))) { @@ -284,7 +284,7 @@ Object Object::LoadFile(const std::string& filename) { if (mtlFile) { std::filesystem::path fullPath = filename; std::filesystem::path mtlPath = fullPath.replace_filename(mtlFile); - obj.LoadMaterials(mtlPath); + obj->LoadMaterials(mtlPath); } break; } @@ -293,11 +293,11 @@ Object Object::LoadFile(const std::string& filename) { { char* materialName = p.TakeWord(); if (materialName) { - auto& mesh = obj.GetLastMesh(); + auto& mesh = obj->GetLastMesh(); if (mesh.materialName != materialName) { Mesh newMesh; newMesh.materialName = materialName; - obj.m_meshes.push_back(newMesh); + obj->m_meshes.push_back(newMesh); } } break; @@ -306,7 +306,7 @@ Object Object::LoadFile(const std::string& filename) { case ObjElement::O: // object name { char* name = p.TakeWord(); - if (name) obj.m_name = name; + if (name) obj->m_name = name; break; } @@ -320,7 +320,7 @@ Object Object::LoadFile(const std::string& filename) { if (w != 0.0f && w != 1.0f) { x /= w; y /= w; z /= w; } - obj.m_vertices.emplace_back(x, y, z); + obj->m_vertices.emplace_back(x, y, z); break; } @@ -329,7 +329,7 @@ Object Object::LoadFile(const std::string& filename) { float x = p.TakeFloat(); float y = p.TakeFloat(); float z = p.TakeFloat(); - obj.m_normals.emplace_back(x, y, z); + obj->m_normals.emplace_back(x, y, z); break; } @@ -337,32 +337,32 @@ Object Object::LoadFile(const std::string& filename) { { float u = p.TakeFloat(); float v = p.TakeFloat(); - obj.m_texCoords.emplace_back(u, 1.0f - v); + obj->m_texCoords.emplace_back(u, 1.0f - v); break; } case ObjElement::F: // face { - auto& mesh = obj.GetLastMesh(); + auto& mesh = obj->GetLastMesh(); int raw_vi, raw_ti, raw_ni; while (p.TakeFaceIndices(raw_vi, raw_ti, raw_ni)) { // Convert raw OBJ indices to 0-based / -1 sentinel - int vi = Object::NormalizeIndex(raw_vi, (int)obj.m_vertices.size()); - int ti = Object::NormalizeIndex(raw_ti, (int)obj.m_texCoords.size()); - int ni = Object::NormalizeIndex(raw_ni, (int)obj.m_normals.size()); + int vi = Object::NormalizeIndex(raw_vi, (int)obj->m_vertices.size()); + int ti = Object::NormalizeIndex(raw_ti, (int)obj->m_texCoords.size()); + int ni = Object::NormalizeIndex(raw_ni, (int)obj->m_normals.size()); if (vi < 0) { // malformed token (no vertex) — skip continue; } - glm::vec3 vert = obj.m_vertices[vi]; + glm::vec3 vert = obj->m_vertices[vi]; glm::vec3 norm(0.0f); glm::vec2 texCoord(0.0f); - if (ni >= 0) norm = obj.m_normals[ni]; - if (ti >= 0) texCoord = obj.m_texCoords[ti]; + if (ni >= 0) norm = obj->m_normals[ni]; + if (ti >= 0) texCoord = obj->m_texCoords[ti]; mesh.m_vertexBuffer.emplace_back(vert, norm, texCoord); mesh.m_indexBuffer.push_back(mesh.m_vertexBuffer.size() - 1); @@ -376,16 +376,16 @@ Object Object::LoadFile(const std::string& filename) { } } - std::cout << "Object name: " << obj.m_name << std::endl; - std::cout << "Vertices count: " << obj.m_vertices.size() << std::endl; - std::cout << "Normals count: " << obj.m_normals.size() << std::endl; - std::cout << "TexCoords count: " << obj.m_texCoords.size() << std::endl; - std::cout << "Meshes count: " << obj.m_meshes.size() << std::endl; - std::cout << "Materials count: " << obj.m_materials.size() << std::endl; + std::cout << "Object name: " << obj->m_name << std::endl; + std::cout << "Vertices count: " << obj->m_vertices.size() << std::endl; + std::cout << "Normals count: " << obj->m_normals.size() << std::endl; + std::cout << "TexCoords count: " << obj->m_texCoords.size() << std::endl; + std::cout << "Meshes count: " << obj->m_meshes.size() << std::endl; + std::cout << "Materials count: " << obj->m_materials.size() << std::endl; file.close(); - for (auto &mesh : obj.m_meshes) { + for (auto &mesh : obj->m_meshes) { mesh.Upload(); } diff --git a/src/window/window.cpp b/src/window/window.cpp index 33d028a..329fdb9 100644 --- a/src/window/window.cpp +++ b/src/window/window.cpp @@ -8,6 +8,8 @@ #include "renderer/debug.h" +std::shared_ptr Window::s_instance = nullptr; + Window::Window(const char* title, int width, int height) { SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS); @@ -55,20 +57,24 @@ Window::Window(const char* title, int width, int height) { glDebugMessageCallback(MessageCallback, nullptr); glViewport(0, 0, m_width, m_height); - - m_is_open = true; } Window::Window() : Window("OpenGL Test", DEFAULT_WIDTH, DEFAULT_HEIGHT) {} +std::shared_ptr Window::GetInstance() { + if (!s_instance) { + s_instance = std::shared_ptr(new Window(), WindowDeleter{}); + } + return s_instance; +} + Window::Window(Window&& window) noexcept - : m_handle(window.m_handle), m_context(window.m_context), m_width(window.m_width), m_height(window.m_height), m_is_open(window.m_is_open) + : m_handle(window.m_handle), m_context(window.m_context), m_width(window.m_width), m_height(window.m_height) { window.m_handle = nullptr; window.m_context = (SDL_GLContext)nullptr; window.m_width = 0; window.m_height = 0; - window.m_is_open = false; } Window& Window::operator=(Window&& window) noexcept @@ -81,7 +87,6 @@ Window& Window::operator=(Window&& window) noexcept this->m_context = window.m_context; this->m_width = window.m_width; this->m_height = window.m_height; - this->m_is_open = window.m_is_open; return *this; } @@ -92,11 +97,11 @@ void Window::ProcessEvents() { switch (event.type) { case SDL_EVENT_WINDOW_CLOSE_REQUESTED: case SDL_EVENT_QUIT: - publish(WindowCloseRequested()); + Dispatch(WindowCloseRequested()); break; case SDL_EVENT_KEY_DOWN: if (event.key.scancode == SDL_SCANCODE_ESCAPE) { - publish(WindowCloseRequested()); + Dispatch(WindowCloseRequested()); } break; case SDL_EVENT_WINDOW_RESIZED: @@ -109,7 +114,7 @@ void Window::ProcessEvents() { 0, width, height); - publish(WindowResized{ m_width, m_height }); + Dispatch(WindowResized{ m_width, m_height }); } break; default: break;