diff options
Diffstat (limited to 'mwe/events/include')
-rw-r--r-- | mwe/events/include/customTypes.h | 35 | ||||
-rw-r--r-- | mwe/events/include/event.h | 167 | ||||
-rw-r--r-- | mwe/events/include/eventHandler.h | 46 | ||||
-rw-r--r-- | mwe/events/include/eventManager.h | 60 | ||||
-rw-r--r-- | mwe/events/include/gameObject.h | 20 | ||||
-rw-r--r-- | mwe/events/include/iKeyListener.h | 20 | ||||
-rw-r--r-- | mwe/events/include/iMouseListener.h | 24 | ||||
-rw-r--r-- | mwe/events/include/inputSystem.h | 23 | ||||
-rw-r--r-- | mwe/events/include/keyCodes.h | 154 | ||||
-rw-r--r-- | mwe/events/include/keyListenerTest.h | 12 | ||||
-rw-r--r-- | mwe/events/include/loopManager.h | 36 | ||||
-rw-r--r-- | mwe/events/include/mouseListenerTest.h | 14 | ||||
-rw-r--r-- | mwe/events/include/timer.h | 31 | ||||
-rw-r--r-- | mwe/events/include/uiObject.h | 68 | ||||
-rw-r--r-- | mwe/events/include/uiRenderer.h | 21 | ||||
-rw-r--r-- | mwe/events/include/userevent.h | 0 | ||||
-rw-r--r-- | mwe/events/include/window.h | 27 |
17 files changed, 758 insertions, 0 deletions
diff --git a/mwe/events/include/customTypes.h b/mwe/events/include/customTypes.h new file mode 100644 index 0000000..5a7851b --- /dev/null +++ b/mwe/events/include/customTypes.h @@ -0,0 +1,35 @@ +#pragma once +#include <cmath> +struct Vector2 { + float x; // X component of the vector + float y; // Y component of the vector + + // Vector subtraction + Vector2 operator-(const Vector2 & other) const { return {x - other.x, y - other.y}; } + + // Vector addition + Vector2 operator+(const Vector2 & other) const { return {x + other.x, y + other.y}; } + + // Scalar multiplication + Vector2 operator*(float scalar) const { return {x * scalar, y * scalar}; } + + // Normalize the vector + Vector2 normalize() const { + float length = std::sqrt(x * x + y * y); + if (length == 0) return {0, 0}; // Prevent division by zero + return {x / length, y / length}; + } +}; +struct Collision { + int objectIdA; // ID of the first object + int objectIdB; // ID of the second object + Vector2 contactPoint; // Point of contact + Vector2 contactNormal; // Normal vector at the contact point + + // Constructor to initialize a Collision + Collision(int idA, int idB, const Vector2 & point, const Vector2 & normal, float depth) + : objectIdA(idA), + objectIdB(idB), + contactPoint(point), + contactNormal(normal) {} +}; diff --git a/mwe/events/include/event.h b/mwe/events/include/event.h new file mode 100644 index 0000000..ee1bf52 --- /dev/null +++ b/mwe/events/include/event.h @@ -0,0 +1,167 @@ +#pragma once +#include "customTypes.h" +#include "keyCodes.h" +#include <cstdint> +#include <iostream> +#include <string> +#include <unordered_map> +#include <variant> +class UUIDGenerator { +public: + static std::uint32_t getUniqueID() { + static std::uint32_t id = 0; + return ++id; + } +}; +#define REGISTER_EVENT_TYPE(ClassName) \ +\ +public: \ + static std::uint32_t getStaticEventType() { \ + static std::uint32_t typeID = UUIDGenerator::getUniqueID(); \ + return typeID; \ + } \ + virtual std::uint32_t getEventType() const override { return getStaticEventType(); } +class Event { +public: + Event(std::string eventType); + virtual ~Event() = default; + virtual std::uint32_t getEventType() const = 0; + virtual std::string toString() const; + void addArgument(const std::string & key, + const std::variant<int, std::string, float> & value); + + std::variant<int, std::string, float> getArgument(const std::string & key) const; + + std::string getType() const; + bool getHandled() const; + void markHandled(); + +private: + std::unordered_map<std::string, std::variant<int, std::string, float>> eventData; + bool isHandled = false; +}; + +// KeyPressedEvent class +class KeyPressedEvent : public Event { +public: + KeyPressedEvent(int keyCode); + + REGISTER_EVENT_TYPE("KeyPressedEvent"); + + Keycode getKeyCode() const; + int getRepeatCount() const; + +private: + Keycode keycode; + +public: + Keycode key = 0; + int repeatCount = 0; +}; +class MouseClickEvent : public Event { +public: + MouseClickEvent(int x, int y, MouseButton button); + + REGISTER_EVENT_TYPE("KeyClickedEvent"); + std::pair<int, int> getMousePosition() const; + MouseButton getButton() const { return button; } + +private: + int mouseX = 0; + int mouseY = 0; + MouseButton button; +}; +// KeyReleasedEvent class +class KeyReleasedEvent : public Event { +public: + KeyReleasedEvent(int keyCode); + + REGISTER_EVENT_TYPE(KeyReleasedEvent); + + Keycode getKeyCode() const; + +private: + Keycode key = 0; +}; + +// MousePressedEvent class +class MousePressedEvent : public Event { +public: + MousePressedEvent(int mouseX, int mouseY); + + REGISTER_EVENT_TYPE(MousePressedEvent) + + std::pair<int, int> getMousePosition() const; + +private: + int mouseX = 0; + int mouseY = 0; + MouseButton button; +}; +class MouseReleasedEvent : public Event { +public: + MouseReleasedEvent(int mouseX, int mouseY, MouseButton button); + + REGISTER_EVENT_TYPE(MouseReleasedEvent) + + std::pair<int, int> getMousePosition() const; + MouseButton getMouseButton() const; + +private: + int mouseX = 0; + int mouseY = 0; + MouseButton button; +}; +class MouseMovedEvent : public Event { +public: + MouseMovedEvent(int mouseX, int mouseY); + + REGISTER_EVENT_TYPE(MouseMovedEvent) + + std::pair<int, int> getMousePosition() const; + +private: + int mouseX = 0; + int mouseY = 0; +}; +class CollisionEvent : public Event { +public: + CollisionEvent(Collision); + + REGISTER_EVENT_TYPE(CollisionEvent) + + Collision getCollisionData() const; + +private: + Collision collisionData; +}; +class TextSubmitEvent : public Event { +public: + TextSubmitEvent(std::string submittedText); + + REGISTER_EVENT_TYPE(TextSubmitEvent) + + std::string getText() const; + +private: + std::string text; +}; +class ShutDownEvent : public Event { +public: + ShutDownEvent() : Event("ShutDownEvent") {}; + + REGISTER_EVENT_TYPE(ShutDownEvent) + +private: +}; +// class ButtonClickEvent : public Event { +// public: +// ButtonClickEvent(int x,int y,int width,int height); + +// REGISTER_EVENT_TYPE(TextSubmitEvent) + +// std::string getText() const; + +// private: +// std::string text; +// }; diff --git a/mwe/events/include/eventHandler.h b/mwe/events/include/eventHandler.h new file mode 100644 index 0000000..3a83b15 --- /dev/null +++ b/mwe/events/include/eventHandler.h @@ -0,0 +1,46 @@ +#pragma once +#include "event.h" +#include <functional> +#include <iostream> + +template <typename EventType> +using EventHandler = std::function<void(const EventType & e)>; + +class IEventHandlerWrapper { +public: + virtual ~IEventHandlerWrapper() = default; + + void exec(const Event & e); + + virtual std::string getType() const = 0; + virtual bool isDestroyOnSuccess() const = 0; + +private: + virtual void call(const Event & e) = 0; +}; + +template <typename EventType> +class EventHandlerWrapper : public IEventHandlerWrapper { +public: + explicit EventHandlerWrapper(const EventHandler<EventType> & handler, + const bool destroyOnSuccess = false) + : m_handler(handler), + m_handlerType(m_handler.target_type().name()), + m_destroyOnSuccess(destroyOnSuccess) { + // std::cout << m_handlerType << std::endl; + } + +private: + void call(const Event & e) override { + if (e.getEventType() == EventType::getStaticEventType()) { + m_handler(static_cast<const EventType &>(e)); + } + } + + std::string getType() const override { return m_handlerType; } + bool isDestroyOnSuccess() const { return m_destroyOnSuccess; } + + EventHandler<EventType> m_handler; + const std::string m_handlerType; + bool m_destroyOnSuccess{false}; +}; diff --git a/mwe/events/include/eventManager.h b/mwe/events/include/eventManager.h new file mode 100644 index 0000000..30e927f --- /dev/null +++ b/mwe/events/include/eventManager.h @@ -0,0 +1,60 @@ +#pragma once +#include "event.h" +#include "eventHandler.h" +#include "keyCodes.h" +#include <memory> +#include <unordered_map> +#include <vector> +// using EventType = std::uint32_t; +// using EventId = std::uint64_t; + +class EventManager { +public: + EventManager(const EventManager &) = delete; + const EventManager & operator=(const EventManager &) = delete; + static EventManager & getInstance() { + static EventManager instance; + return instance; + } + + void shutdown(); + void subscribe(int eventType, std::unique_ptr<IEventHandlerWrapper> && handler, + int eventId); + void unsubscribe(int eventType, const std::string & handlerName, int eventId); + void triggerEvent(const Event & event_, int eventId); + void queueEvent(std::unique_ptr<Event> && event_, int eventId); + void dispatchEvents(); + +private: + EventManager() = default; + std::vector<std::pair<std::unique_ptr<Event>, int>> eventsQueue; + std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>> subscribers; + std::unordered_map< + int, std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>> + subscribersByEventId; +}; + +template <typename EventType> +inline void subscribe(const EventHandler<EventType> & callback, int eventId = 0, + const bool unsubscribeOnSuccess = false) { + std::unique_ptr<IEventHandlerWrapper> handler + = std::make_unique<EventHandlerWrapper<EventType>>(callback, unsubscribeOnSuccess); + EventManager::getInstance().subscribe(EventType::getStaticEventType(), std::move(handler), + eventId); +} + +template <typename EventType> +inline void unsubscribe(const EventHandler<EventType> & callback, int eventId = 0) { + const std::string handlerName = callback.target_type().name(); + EventManager::getInstance().unsubscribe(EventType::getStaticEventType(), handlerName, + eventId); +} + +inline void triggerEvent(const Event & triggeredEvent, int eventId = 0) { + EventManager::getInstance().triggerEvent(triggeredEvent, eventId); +} + +inline void queueEvent(std::unique_ptr<Event> && queuedEvent, int eventId = 0) { + EventManager::getInstance().queueEvent(std::forward<std::unique_ptr<Event>>(queuedEvent), + eventId); +} diff --git a/mwe/events/include/gameObject.h b/mwe/events/include/gameObject.h new file mode 100644 index 0000000..48e239b --- /dev/null +++ b/mwe/events/include/gameObject.h @@ -0,0 +1,20 @@ +#pragma once +#include <cstdint> +#include <string> +class GameObject { +public: + GameObject() {} + + // template <typename... Args> + // void addSpriteComponent(Args &&... args); + // template <typename... Args> + // void addRigidbodyComponent(Args &&... args); + // template <typename... Args> + // void addColiderComponent(Args &&... args); + + std::uint32_t mId; + std::string mName; + std::string mTag; + bool mActive; + int mLayer; +}; diff --git a/mwe/events/include/iKeyListener.h b/mwe/events/include/iKeyListener.h new file mode 100644 index 0000000..5fee2eb --- /dev/null +++ b/mwe/events/include/iKeyListener.h @@ -0,0 +1,20 @@ +#pragma once +#include "event.h" +#include "eventHandler.h" +#include "eventManager.h" +class IKeyListener { +public: + virtual ~IKeyListener(); + virtual void onKeyPressed(const KeyPressedEvent & event) = 0; + virtual void onKeyReleased(const KeyReleasedEvent & event) = 0; + +protected: + void subscribeEvents(int listenerId = 0); + void unsubscribeEvents(int listenerId = 0); + void activate(int listenerId = 0) { subscribeEvents(listenerId); } + void deactivate(int listenerId = 0) { unsubscribeEvents(listenerId); } + +private: + EventHandler<KeyPressedEvent> keyPressedHandler; + EventHandler<KeyReleasedEvent> keyReleasedHandler; +}; diff --git a/mwe/events/include/iMouseListener.h b/mwe/events/include/iMouseListener.h new file mode 100644 index 0000000..5b1181c --- /dev/null +++ b/mwe/events/include/iMouseListener.h @@ -0,0 +1,24 @@ +#pragma once +#include "event.h" +#include "eventHandler.h" +#include "eventManager.h" + +class IMouseListener { +public: + virtual ~IMouseListener(); + + virtual void onMouseClicked(const MouseClickEvent & event) = 0; + virtual void onMousePressed(const MousePressedEvent & event) = 0; + virtual void onMouseReleased(const MouseReleasedEvent & event) = 0; + virtual void onMouseMoved(const MouseMovedEvent & event) = 0; + +protected: + void subscribeEvents(int listenerId = 0); + void unsubscribeEvents(int listenerId = 0); + +private: + EventHandler<MouseClickEvent> mouseClickHandler; + EventHandler<MousePressedEvent> mousePressHandler; + EventHandler<MouseReleasedEvent> mouseReleaseHandler; + EventHandler<MouseMovedEvent> mouseMoveHandler; +}; diff --git a/mwe/events/include/inputSystem.h b/mwe/events/include/inputSystem.h new file mode 100644 index 0000000..3e53b7c --- /dev/null +++ b/mwe/events/include/inputSystem.h @@ -0,0 +1,23 @@ +#pragma once +#include "event.h" +#include "eventManager.h" +#include "keyCodes.h" +#include "uiObject.h" +#include <vector> +class InputSystem { +public: + InputSystem(); + void registerButton(Button * button); + void registerText(Text * label); + void registerTextInput(TextInput * input); + void processInput(); + +private: + std::vector<Button *> buttons; + std::vector<TextInput *> textInputs; + std::vector<Text *> texts; + void processMouseClick(int mouseX, int mouseY); + void processInputField(int mouseX, int mouseY); + void processKeyPress(Keycode); + void processTextInput(const std::string & text); +}; diff --git a/mwe/events/include/keyCodes.h b/mwe/events/include/keyCodes.h new file mode 100644 index 0000000..73ba1cd --- /dev/null +++ b/mwe/events/include/keyCodes.h @@ -0,0 +1,154 @@ +#pragma once +#include <SDL2/SDL.h> +#include <cstdint> +#include <unordered_map> +using Keycode = uint16_t; +enum class MouseButton { + None = 0, + Left_Mouse = 1, + Right_Mouse = 2, + Middle_Mouse = 3, + X1_Mouse = 4, + X2_Mouse = 5, + Scroll_Up = 6, + Scroll_Down = 7, +}; +enum : Keycode { + // From glfw3.h + Space = 32, + Apostrophe = 39, /* ' */ + Comma = 44, /* , */ + Minus = 45, /* - */ + Period = 46, /* . */ + Slash = 47, /* / */ + + D0 = 48, /* 0 */ + D1 = 49, /* 1 */ + D2 = 50, /* 2 */ + D3 = 51, /* 3 */ + D4 = 52, /* 4 */ + D5 = 53, /* 5 */ + D6 = 54, /* 6 */ + D7 = 55, /* 7 */ + D8 = 56, /* 8 */ + D9 = 57, /* 9 */ + + Semicolon = 59, /* ; */ + Equal = 61, /* = */ + + A = 65, + B = 66, + C = 67, + D = 68, + E = 69, + F = 70, + G = 71, + H = 72, + I = 73, + J = 74, + K = 75, + L = 76, + M = 77, + N = 78, + O = 79, + P = 80, + Q = 81, + R = 82, + S = 83, + T = 84, + U = 85, + V = 86, + W = 87, + X = 88, + Y = 89, + Z = 90, + + LeftBracket = 91, /* [ */ + Backslash = 92, /* \ */ + RightBracket = 93, /* ] */ + GraveAccent = 96, /* ` */ + + World1 = 161, /* non-US #1 */ + World2 = 162, /* non-US #2 */ + + /* Function keys */ + Escape = 256, + Enter = 257, + Tab = 258, + Backspace = 259, + Insert = 260, + Delete = 261, + Right = 262, + Left = 263, + Down = 264, + Up = 265, + PageUp = 266, + PageDown = 267, + Home = 268, + End = 269, + CapsLock = 280, + ScrollLock = 281, + NumLock = 282, + PrintScreen = 283, + Pause = 284, + F1 = 290, + F2 = 291, + F3 = 292, + F4 = 293, + F5 = 294, + F6 = 295, + F7 = 296, + F8 = 297, + F9 = 298, + F10 = 299, + F11 = 300, + F12 = 301, + F13 = 302, + F14 = 303, + F15 = 304, + F16 = 305, + F17 = 306, + F18 = 307, + F19 = 308, + F20 = 309, + F21 = 310, + F22 = 311, + F23 = 312, + F24 = 313, + F25 = 314, + + /* Keypad */ + KP0 = 320, + KP1 = 321, + KP2 = 322, + KP3 = 323, + KP4 = 324, + KP5 = 325, + KP6 = 326, + KP7 = 327, + KP8 = 328, + KP9 = 329, + KPDecimal = 330, + KPDivide = 331, + KPMultiply = 332, + KPSubtract = 333, + KPAdd = 334, + KPEnter = 335, + KPEqual = 336, + + LeftShift = 340, + LeftControl = 341, + LeftAlt = 342, + LeftSuper = 343, + RightShift = 344, + RightControl = 345, + RightAlt = 346, + RightSuper = 347, + Menu = 348 +}; + +// Define the mapping +extern const std::unordered_map<SDL_Keycode, Keycode> sdlToCustom; + +// Function to map SDL_Keycode to custom Keycode +Keycode getCustomKey(SDL_Keycode sdlKey); diff --git a/mwe/events/include/keyListenerTest.h b/mwe/events/include/keyListenerTest.h new file mode 100644 index 0000000..08f3feb --- /dev/null +++ b/mwe/events/include/keyListenerTest.h @@ -0,0 +1,12 @@ +#pragma once +#include "iKeyListener.h" +#include <iostream> + +class KeyListenerTest : public IKeyListener { +public: + KeyListenerTest(int listenerId); + ~KeyListenerTest(); + + void onKeyPressed(const KeyPressedEvent & event) override; + void onKeyReleased(const KeyReleasedEvent & event) override; +}; diff --git a/mwe/events/include/loopManager.h b/mwe/events/include/loopManager.h new file mode 100644 index 0000000..9959c94 --- /dev/null +++ b/mwe/events/include/loopManager.h @@ -0,0 +1,36 @@ +#pragma once +#include "timer.h" +#include "window.h" +#include <SDL2/SDL.h> +//#include "combinedEvent.h" +#include "eventHandler.h" +#include "eventManager.h" +#include "inputSystem.h" +#include "loopManager.h" +#include "uiObject.h" +#include "uiRenderer.h" +#include <memory> +class LoopManager { +public: + LoopManager(); + void setup(); + void loop(); + void setRunning(bool running); + +private: + void processInput(); + void update(); + void lateUpdate(); + void fixedUpdate(); + void render(); + void onShutdown(const ShutDownEvent & e); + bool gameRunning = false; + WindowManager window; + int timeScale = 1; + float accumulator = 0.0; + double currentTime; + double t = 0.0; + double dt = 0.01; + std::unique_ptr<InputSystem> inputSystem; + EventHandler<ShutDownEvent> shutdownHandler; +}; diff --git a/mwe/events/include/mouseListenerTest.h b/mwe/events/include/mouseListenerTest.h new file mode 100644 index 0000000..ca9afc5 --- /dev/null +++ b/mwe/events/include/mouseListenerTest.h @@ -0,0 +1,14 @@ +#pragma once +#include "iMouseListener.h" +#include <iostream> + +class MouseListenerTest : public IMouseListener { +public: + MouseListenerTest(int listenerId); + ~MouseListenerTest(); + + void onMouseClicked(const MouseClickEvent & event) override; + void onMousePressed(const MousePressedEvent & event) override; + void onMouseReleased(const MouseReleasedEvent & event) override; + void onMouseMoved(const MouseMovedEvent & event) override; +}; diff --git a/mwe/events/include/timer.h b/mwe/events/include/timer.h new file mode 100644 index 0000000..22383b2 --- /dev/null +++ b/mwe/events/include/timer.h @@ -0,0 +1,31 @@ +#pragma once + +#include <SDL2/SDL.h> + +class LoopTimer { +public: + static LoopTimer & getInstance(); + void start(); + void update(); + double getDeltaTime() const; + int getCurrentTime() const; + void advanceFixedUpdate(); + double getFixedDeltaTime() const; + void setFPS(int FPS); + int getFPS() const; + void enforceFrameRate(); + double getLag() const; + +private: + LoopTimer(); + int FPS = 50; + double gameScale = 1; + double maximumDeltaTime = 0.25; + double deltaTime; + double frameTargetTime = FPS / 1000; + double fixedDeltaTime = 0.01; + double elapsedTime; + double elapsedFixedTime; + double time; + uint64_t lastFrameTime; +}; diff --git a/mwe/events/include/uiObject.h b/mwe/events/include/uiObject.h new file mode 100644 index 0000000..23efe44 --- /dev/null +++ b/mwe/events/include/uiObject.h @@ -0,0 +1,68 @@ +#pragma once +#include "event.h" +#include "eventHandler.h" +#include "gameObject.h" +#include <SDL2/SDL.h> +#include <SDL_ttf.h> +#include <functional> +struct Alignment { + enum class Horizontal { LEFT, CENTER, RIGHT }; + enum class Vertical { TOP, MIDDLE, BOTTOM }; + enum class PositioningMode { RELATIVE, STATIC, ABSOLUTE }; + + Horizontal horizontal = Horizontal::CENTER; + Vertical vertical = Vertical::MIDDLE; + PositioningMode mode = PositioningMode::RELATIVE; + + int staticX = 0; + int staticY = 0; + + int marginTop = 0; + int marginBottom = 0; + int marginLeft = 0; + int marginRight = 0; +}; +struct RGBColor { + int red; + int green; + int blue; +}; +class UIObject : public GameObject { +public: + UIObject(int width, int height); + virtual ~UIObject() {} + int width; + int height; + int x; + int y; +}; +class Button : public UIObject { +public: + Button(int width, int height); + RGBColor color; + std::function<void()> onClick; +}; +class Text : public UIObject { +public: + Text(int width, int height); + std::string text; + int size; + Alignment alignment; + //font resource + TTF_Font * font; + RGBColor color; +}; +class TextInput : public UIObject { +public: + TextInput(int width, int height); + std::string textBuffer; + std::string placeholder; + bool isActive = false; + RGBColor textColor; + RGBColor backgroundColor; + size_t maxLength = 100; + Alignment alignment; + TTF_Font * font = nullptr; + std::function<void()> onSubmit; + std::function<void()> onFocus; +}; diff --git a/mwe/events/include/uiRenderer.h b/mwe/events/include/uiRenderer.h new file mode 100644 index 0000000..8f22fdf --- /dev/null +++ b/mwe/events/include/uiRenderer.h @@ -0,0 +1,21 @@ +#pragma once +#include "uiObject.h" +#include <SDL2/SDL.h> +#include <SDL2/SDL_ttf.h> +#include <string> + +class UIRenderer { +public: + UIRenderer(SDL_Renderer * renderer); + ~UIRenderer(); + + void render(UIObject * uiObject); + +private: + SDL_Renderer * renderer; + TTF_Font * font; + + void renderButton(Button * button); + void renderText(Text * text); + void renderTextInput(TextInput * textInput); +}; diff --git a/mwe/events/include/userevent.h b/mwe/events/include/userevent.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/mwe/events/include/userevent.h diff --git a/mwe/events/include/window.h b/mwe/events/include/window.h new file mode 100644 index 0000000..bd75c4a --- /dev/null +++ b/mwe/events/include/window.h @@ -0,0 +1,27 @@ +#pragma once +#include "uiObject.h" +#include "uiRenderer.h" +#include <SDL2/SDL.h> +#include <vector> + +class WindowManager { +public: + WindowManager(); + virtual ~WindowManager(); + + bool initWindow(); + void destroyWindow(); + SDL_Renderer * getRenderer(); + + void addUIObject(UIObject * uiObject); + void renderUIObjects(); + +private: + const int SCREEN_WIDTH = 800; + const int SCREEN_HEIGHT = 600; + SDL_Window * window = nullptr; + SDL_Renderer * renderer = nullptr; + + UIRenderer * uiRenderer; + std::vector<UIObject *> uiObjects; +}; |