From b6464c714c8194f8216bacd445448a6ab143e574 Mon Sep 17 00:00:00 2001 From: Light3039 Date: Sun, 23 May 2021 18:10:11 +0430 Subject: [PATCH] Dispatcher & Layers --- Engine/src/Engine/Base.h | 4 +- Engine/src/Engine/Core/Application.cpp | 15 +++++- Engine/src/Engine/Core/Application.h | 9 +++- Engine/src/Engine/Core/Window.h | 4 +- Engine/src/Engine/Events/Dispatcher.h | 42 +++++++++++++++++ Engine/src/Engine/Events/Event.h | 13 ++--- Engine/src/Engine/Events/Events.cpp | 3 ++ .../{KeyboardEvent.h => KeyboardEvents.h} | 4 +- Engine/src/Engine/Events/MouseEvents.h | 3 +- Engine/src/Engine/Layer/Layer.h | 47 +++++++++++++++++++ Engine/src/Engine/Layer/LayerStack.cpp | 23 +++++++++ Engine/src/Engine/Layer/LayerStack.h | 26 ++++++++++ .../Engine/Platforms/OS/Windows/wWindow.cpp | 43 +++++++++++++++-- .../src/Engine/Platforms/OS/Windows/wWindow.h | 8 +++- Engine/src/LightEngine.h | 4 ++ 15 files changed, 229 insertions(+), 19 deletions(-) create mode 100644 Engine/src/Engine/Events/Dispatcher.h create mode 100644 Engine/src/Engine/Events/Events.cpp rename Engine/src/Engine/Events/{KeyboardEvent.h => KeyboardEvents.h} (91%) create mode 100644 Engine/src/Engine/Layer/Layer.h create mode 100644 Engine/src/Engine/Layer/LayerStack.cpp create mode 100644 Engine/src/Engine/Layer/LayerStack.h diff --git a/Engine/src/Engine/Base.h b/Engine/src/Engine/Base.h index 2fa27df..b74be19 100644 --- a/Engine/src/Engine/Base.h +++ b/Engine/src/Engine/Base.h @@ -6,4 +6,6 @@ #error "Unsupported platform: UNIX" #else #error "Unsupported platform: Unknown" -#endif \ No newline at end of file +#endif + +#include "Core/Logger.h" \ No newline at end of file diff --git a/Engine/src/Engine/Core/Application.cpp b/Engine/src/Engine/Core/Application.cpp index b3ca33e..3bb3ce8 100644 --- a/Engine/src/Engine/Core/Application.cpp +++ b/Engine/src/Engine/Core/Application.cpp @@ -3,13 +3,21 @@ #include "Logger.h" #include "Window.h" +#include "Events/MouseEvents.h" + +#include +#include + namespace Light { Application::Application() { Logger::Initialize(); - m_Window = std::unique_ptr(Window::Create({ "Title", 800u, 600u, false })); + m_Window = std::unique_ptr(Window::Create({ "Title", 800u, 600u, false }, std::bind(&Application::OnEvent, this , std::placeholders::_1))); + + TestLayer* layer = new TestLayer("Test Layer"); + m_LayerStack.PushLayer(layer); LT_ENGINE_INFO("Initialized Logger"); } @@ -23,4 +31,9 @@ namespace Light { while (true) { m_Window->OnUpdate(); } } + void Application::OnEvent(Event& event) + { + m_Dispatcher.Dispatch(event, m_LayerStack.begin(), m_LayerStack.end()); + } + } \ No newline at end of file diff --git a/Engine/src/Engine/Core/Application.h b/Engine/src/Engine/Core/Application.h index e6171c2..42495d0 100644 --- a/Engine/src/Engine/Core/Application.h +++ b/Engine/src/Engine/Core/Application.h @@ -2,6 +2,11 @@ #include "Base.h" +#include "Events/Event.h" +#include "Events/Dispatcher.h" + +#include "Layer/LayerStack.h" + #include namespace Light { @@ -12,11 +17,13 @@ namespace Light { { private: std::unique_ptr m_Window = nullptr; - + LayerStack m_LayerStack; + Dispatcher m_Dispatcher; public: virtual ~Application(); void GameLoop(); + void OnEvent(Event& event); // To be defined in client project friend Application* CreateApplication(); diff --git a/Engine/src/Engine/Core/Window.h b/Engine/src/Engine/Core/Window.h index 3d2659f..9112b8b 100644 --- a/Engine/src/Engine/Core/Window.h +++ b/Engine/src/Engine/Core/Window.h @@ -2,6 +2,8 @@ #include "Base.h" +#include "Events/Event.h" + #include namespace Light { @@ -25,7 +27,7 @@ namespace Light { virtual inline void* GetNativeHandle() = 0; - static Window* Create(const WindowProperties& properties); + static Window* Create(const WindowProperties& properties, std::function callback); }; } \ No newline at end of file diff --git a/Engine/src/Engine/Events/Dispatcher.h b/Engine/src/Engine/Events/Dispatcher.h new file mode 100644 index 0000000..b8062e5 --- /dev/null +++ b/Engine/src/Engine/Events/Dispatcher.h @@ -0,0 +1,42 @@ +#pragma once + +#include "Base.h" + +#include "Event.h" + +#include "Layer/Layer.h" + +namespace Light { + + class Dispatcher + { + public: + void Dispatch(Event& event, std::vector::iterator begin, std::vector::iterator end) + { + switch (event.GetEventType()) + { + case EventType::MouseMoved: + for (auto it = begin; it != end; it++) + if ((*it)->OnMouseMoved((MouseMovedEvent&)event)) return; + return; + case EventType::ButtonPressed: + for (auto it = begin; it != end; it++) + if ((*it)->OnButtonPressed((ButtonPressedEvent&)event)) return; + return; + case EventType::ButtonReleased: + for (auto it = begin; it != end; it++) + if ((*it)->OnButtonReleased((ButtonReleasedEvent&)event)) return; + return; + case EventType::KeyPressed: + for (auto it = begin; it != end; it++) + if ((*it)->OnKeyPressed((KeyPressedEvent&)event)) return; + return; + case EventType::KeyReleased: + for (auto it = begin; it != end; it++) + if ((*it)->OnKeyReleased((KeyReleasedEvent&)event)) return; + return; + } + } + }; + +} \ No newline at end of file diff --git a/Engine/src/Engine/Events/Event.h b/Engine/src/Engine/Events/Event.h index 9a0ecba..7f4ae5f 100644 --- a/Engine/src/Engine/Events/Event.h +++ b/Engine/src/Engine/Events/Event.h @@ -4,9 +4,11 @@ #include +#include + namespace Light { - enum EventType + enum class EventType { None = 0, @@ -18,19 +20,14 @@ namespace Light { WindowMoved, WindowResized, WindowClosed, }; -#define EVENT_TYPE(x) virtual EventType GetType() override { return x; } +#define EVENT_TYPE(type) EventType GetEventType() const override { return EventType::##type; } class Event { - private: - bool b_Handled; - public: - virtual EventType GetType() = 0; + virtual EventType GetEventType() const = 0; virtual std::string GetInfoLog() const = 0; - inline bool IsHandled() const { return b_Handled; } - friend std::ostream & operator<<(std::ostream & os, const Event& e) { return os << e.GetInfoLog(); diff --git a/Engine/src/Engine/Events/Events.cpp b/Engine/src/Engine/Events/Events.cpp new file mode 100644 index 0000000..2689c97 --- /dev/null +++ b/Engine/src/Engine/Events/Events.cpp @@ -0,0 +1,3 @@ +#include "Event.h" +#include "KeyboardEvents.h" +#include "MouseEvents.h" \ No newline at end of file diff --git a/Engine/src/Engine/Events/KeyboardEvent.h b/Engine/src/Engine/Events/KeyboardEvents.h similarity index 91% rename from Engine/src/Engine/Events/KeyboardEvent.h rename to Engine/src/Engine/Events/KeyboardEvents.h index 393ddac..a556efd 100644 --- a/Engine/src/Engine/Events/KeyboardEvent.h +++ b/Engine/src/Engine/Events/KeyboardEvents.h @@ -2,7 +2,7 @@ #include "Base.h" -#include "Event.h" +#include "Events/Event.h" #include @@ -22,6 +22,7 @@ namespace Light { { std::stringstream ss; ss << "KeyPressed: " << m_Key; + return ss.str(); } EVENT_TYPE(KeyPressed) }; @@ -40,6 +41,7 @@ namespace Light { { std::stringstream ss; ss << "KeyReleased: " << m_Key; + return ss.str(); } EVENT_TYPE(KeyReleased) }; diff --git a/Engine/src/Engine/Events/MouseEvents.h b/Engine/src/Engine/Events/MouseEvents.h index b9030e0..42c8b21 100644 --- a/Engine/src/Engine/Events/MouseEvents.h +++ b/Engine/src/Engine/Events/MouseEvents.h @@ -63,7 +63,8 @@ namespace Light { ss << "ButtonReleased: " << m_Button; return ss.str(); } - EVENT_TYPE(ButtonReleased) + + EVENT_TYPE(ButtonReleased); }; } \ No newline at end of file diff --git a/Engine/src/Engine/Layer/Layer.h b/Engine/src/Engine/Layer/Layer.h new file mode 100644 index 0000000..c406683 --- /dev/null +++ b/Engine/src/Engine/Layer/Layer.h @@ -0,0 +1,47 @@ +#pragma once + +#include "Base.h" + +#include "Events/MouseEvents.h" +#include "Events/KeyboardEvents.h" + +#include + +namespace Light { + + class Layer + { + private: + std::string m_Name; + public: + Layer(const std::string& name): m_Name(name) {} + virtual ~Layer() = default; + + inline const std::string& GetName() const { return m_Name; } + + // Mouse events + virtual bool OnMouseMoved(const MouseMovedEvent& event) { return false; } + virtual bool OnButtonPressed(const ButtonPressedEvent& event) { return false; } + virtual bool OnButtonReleased(const ButtonReleasedEvent& event) { return false; } + + // Keyboard events + virtual bool OnKeyPressed(const KeyPressedEvent& event) { return false; } + virtual bool OnKeyReleased(const KeyReleasedEvent& event) { return false; } + }; + + class TestLayer : public Layer + { + public: + TestLayer(const std::string& name): Layer(name) {} + + // Mouse events + virtual bool OnMouseMoved(const MouseMovedEvent& event) { LT_ENGINE_TRACE("{}", event.GetInfoLog()); return false; } + virtual bool OnButtonPressed(const ButtonPressedEvent& event) { LT_ENGINE_TRACE(event.GetInfoLog()); return false; } + virtual bool OnButtonReleased(const ButtonReleasedEvent& event) { LT_ENGINE_TRACE(event.GetInfoLog()); return false; } + + // Keyboard events + virtual bool OnKeyPressed(const KeyPressedEvent& event) { LT_ENGINE_TRACE(event.GetInfoLog()); return false; } + virtual bool OnKeyReleased(const KeyReleasedEvent& event) { LT_ENGINE_TRACE(event.GetInfoLog()); return false; } + }; + +} \ No newline at end of file diff --git a/Engine/src/Engine/Layer/LayerStack.cpp b/Engine/src/Engine/Layer/LayerStack.cpp new file mode 100644 index 0000000..17010a9 --- /dev/null +++ b/Engine/src/Engine/Layer/LayerStack.cpp @@ -0,0 +1,23 @@ +#include "LayerStack.h" + +namespace Light { + + LayerStack::~LayerStack() + { + for (Layer* layer : m_Layers) + delete layer; + } + + void LayerStack::PushLayer(Layer* layer) + { + m_Layers.push_back(layer); + LT_ENGINE_TRACE("LayerStack::PushLayer: Attached [{}]", layer->GetName()); + } + + void LayerStack::PopLayer(Layer* layer) + { + m_Layers.erase(std::find(m_Layers.begin(), m_Layers.end(), layer)); + LT_ENGINE_TRACE("LayerStack::PushLayer: Detatched[{}]", layer->GetName()); + } + +} \ No newline at end of file diff --git a/Engine/src/Engine/Layer/LayerStack.h b/Engine/src/Engine/Layer/LayerStack.h new file mode 100644 index 0000000..2b13640 --- /dev/null +++ b/Engine/src/Engine/Layer/LayerStack.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Base.h" + +#include "Layer.h" + +#include + +namespace Light { + + class LayerStack + { + private: + std::vector m_Layers; + + public: + ~LayerStack(); + + void PushLayer(Layer* layer); + void PopLayer(Layer* layer); + + std::vector::iterator begin() { return m_Layers.begin(); } + std::vector::iterator end() { return m_Layers.end(); } + }; + +} \ No newline at end of file diff --git a/Engine/src/Engine/Platforms/OS/Windows/wWindow.cpp b/Engine/src/Engine/Platforms/OS/Windows/wWindow.cpp index b1def44..cc485ff 100644 --- a/Engine/src/Engine/Platforms/OS/Windows/wWindow.cpp +++ b/Engine/src/Engine/Platforms/OS/Windows/wWindow.cpp @@ -1,20 +1,26 @@ #include "wWindow.h" +#include "Events/KeyboardEvents.h" +#include "Events/MouseEvents.h" + namespace Light { - Window* Window::Create(const WindowProperties& properties) + Window* Window::Create(const WindowProperties& properties, std::function callback) { - return new wWindow(properties); + return new wWindow(properties, callback); } - wWindow::wWindow(const WindowProperties& properties) - : m_Properties(properties) + wWindow::wWindow(const WindowProperties& properties, std::function callback) + : m_Properties(properties), m_EventCallback(callback) { if (!glfwInit()) __debugbreak(); m_Handle = glfwCreateWindow(properties.width, properties.height, properties.title.c_str(), nullptr, nullptr); glfwMakeContextCurrent(m_Handle); + glfwSetWindowUserPointer(m_Handle, &m_EventCallback); + + BindGlfwEvents(); } wWindow::~wWindow() @@ -38,4 +44,33 @@ namespace Light { return m_Properties.height; } + void wWindow::BindGlfwEvents() + { + glfwSetCursorPosCallback(m_Handle, [](GLFWwindow* window, double xpos, double ypos) + { + std::function callback = *(std::function*)glfwGetWindowUserPointer(window); + callback(MouseMovedEvent(xpos, ypos)); + }); + + glfwSetMouseButtonCallback(m_Handle, [](GLFWwindow* window, int button, int action, int mods) + { + std::function callback = *(std::function*)glfwGetWindowUserPointer(window); + + if (action == GLFW_PRESS) + callback(ButtonPressedEvent(button)); + else + callback(ButtonReleasedEvent(button)); + }); + + glfwSetKeyCallback(m_Handle, [](GLFWwindow* window, int key, int scancode, int action, int mods) + { + std::function callback = *(std::function*)glfwGetWindowUserPointer(window); + + if (action == GLFW_PRESS) + callback(KeyPressedEvent(key)); + else + callback(KeyReleasedEvent(key)); + }); + } + } \ No newline at end of file diff --git a/Engine/src/Engine/Platforms/OS/Windows/wWindow.h b/Engine/src/Engine/Platforms/OS/Windows/wWindow.h index 286e9b7..7a11a2d 100644 --- a/Engine/src/Engine/Platforms/OS/Windows/wWindow.h +++ b/Engine/src/Engine/Platforms/OS/Windows/wWindow.h @@ -4,6 +4,8 @@ #include "Core/Window.h" +#include "Events/Event.h" + #include #include @@ -15,8 +17,10 @@ namespace Light { private: GLFWwindow* m_Handle = nullptr; WindowProperties m_Properties; + + std::function m_EventCallback; public: - wWindow(const WindowProperties& properties); + wWindow(const WindowProperties& properties, std::function callback); ~wWindow(); @@ -26,6 +30,8 @@ namespace Light { virtual unsigned int GetHeight() override; virtual inline void* GetNativeHandle() override { return m_Handle; } + private: + void BindGlfwEvents(); }; } \ No newline at end of file diff --git a/Engine/src/LightEngine.h b/Engine/src/LightEngine.h index 4bcbdd7..0bbce6f 100644 --- a/Engine/src/LightEngine.h +++ b/Engine/src/LightEngine.h @@ -1,5 +1,9 @@ #pragma once +#include "Engine/Events/Event.h" +#include "Engine/Events/KeyboardEvents.h" +#include "Engine/Events/MouseEvents.h" + #include "Engine/Core/Application.h" #include "Engine/Core/Logger.h"