diff options
author | WBoerenkamps <wrj.boerenkamps@student.avans.nl> | 2024-11-11 10:50:40 +0100 |
---|---|---|
committer | WBoerenkamps <wrj.boerenkamps@student.avans.nl> | 2024-11-11 10:50:40 +0100 |
commit | 880a7b1fb233a67303ad5a4155dc459f79734762 (patch) | |
tree | 955faa9c02480f17cb4a674ae9a1b82dab741a63 | |
parent | 3a690f7d0c91b92b9cdfe62f44dba8db90142abc (diff) |
big cleanup events + events are now structs
-rw-r--r-- | src/crepe/api/Event.h | 68 | ||||
-rw-r--r-- | src/crepe/api/EventHandler.cpp | 2 | ||||
-rw-r--r-- | src/crepe/api/EventHandler.h | 38 | ||||
-rw-r--r-- | src/crepe/api/EventManager.cpp | 69 | ||||
-rw-r--r-- | src/crepe/api/EventManager.h | 76 | ||||
-rw-r--r-- | src/crepe/api/IKeyListener.cpp | 20 | ||||
-rw-r--r-- | src/crepe/api/IKeyListener.h | 20 | ||||
-rw-r--r-- | src/crepe/api/IMouseListener.cpp | 35 | ||||
-rw-r--r-- | src/crepe/api/IMouseListener.h | 24 | ||||
-rw-r--r-- | src/makefile | 12 |
10 files changed, 362 insertions, 2 deletions
diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h new file mode 100644 index 0000000..8d9b241 --- /dev/null +++ b/src/crepe/api/Event.h @@ -0,0 +1,68 @@ +#pragma once +#include <typeindex> +//#include "keyCodes.h" +#include <cstdint> +#include <iostream> +#include <string> +#include <unordered_map> +#include <variant> +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, +}; +class Event { +public: +}; + +class KeyPressEvent : public Event { +public: + int repeat = 0; + Keycode key = 0; +}; + +class MouseClickEvent : public Event { +public: + int mouse_x = 0; + int mouse_y = 0; + MouseButton button; +}; +class KeyReleaseEvent : public Event { +public: + Keycode key = 0; +}; + +class MousePressEvent : public Event { +public: + int mouse_x = 0; + int mouse_y = 0; + MouseButton button; +}; +class MouseReleaseEvent : public Event { +public: + int mouse_x = 0; + int mouse_y = 0; + MouseButton button; +}; +class MouseMoveEvent : public Event { +public: + int mouse_x = 0; + int mouse_y = 0; +}; +class CollisionEvent : public Event{ +public: + //Collision collisionData; +}; +class TextSubmitEvent : public Event{ +public: + std::string text; +}; +class ShutDownEvent : public Event { +public: +}; diff --git a/src/crepe/api/EventHandler.cpp b/src/crepe/api/EventHandler.cpp new file mode 100644 index 0000000..93a116a --- /dev/null +++ b/src/crepe/api/EventHandler.cpp @@ -0,0 +1,2 @@ +#include "EventHandler.h" +bool IEventHandlerWrapper::exec(const Event & e) { return call(e); } diff --git a/src/crepe/api/EventHandler.h b/src/crepe/api/EventHandler.h new file mode 100644 index 0000000..eea1c79 --- /dev/null +++ b/src/crepe/api/EventHandler.h @@ -0,0 +1,38 @@ +#pragma once +#include <functional> +#include <iostream> +#include <typeindex> +#include "Event.h" + +template <typename EventType> +using EventHandler = std::function<bool(const EventType & e)>; + +class IEventHandlerWrapper { +public: + virtual ~IEventHandlerWrapper() = default; + + bool exec(const Event & e); + + virtual std::string get_type() const = 0; + +private: + virtual bool call(const Event & e) = 0; +}; + +template <typename EventType> +class EventHandlerWrapper : public IEventHandlerWrapper { +public: + explicit EventHandlerWrapper(const EventHandler<EventType> & handler) + : m_handler(handler), m_handler_type(m_handler.target_type().name()) { + } + +private: + bool call(const Event & e) override { + return m_handler(static_cast<const EventType &>(e)); + } + + std::string get_type() const override { return m_handler_type; } + + EventHandler<EventType> m_handler; + const std::string m_handler_type; +}; diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp new file mode 100644 index 0000000..07ef1f7 --- /dev/null +++ b/src/crepe/api/EventManager.cpp @@ -0,0 +1,69 @@ +#include "EventManager.h" + +void EventManager::unsubscribe(std::type_index eventType, const std::string & handlerName, + int eventId) { + // if (eventId) { + // std::unordered_map< + // std::type_index, std::unordered_map< + // int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>>::iterator subscriber_list = subscribers_by_event_id.find(eventType); + // if (subscriber_list != subscribers_by_event_id.end()) { + // std::unordered_map< + // int, std::vector<std::unique_ptr<IEventHandlerWrapper>>> & + // handlers_map + // = subscriber_list->second; + // std::unordered_map< + // int, + // std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator + // handlers + // = handlers_map.find(eventId); + // if (handlers != handlers_map.end()) { + // std::vector<std::unique_ptr<IEventHandlerWrapper>> & callbacks + // = handlers->second; + // for (std::vector< + // std::unique_ptr<IEventHandlerWrapper>>::iterator it + // = callbacks.begin(); + // it != callbacks.end(); ++it) { + // if (it->get()->getType() == handlerName) { + // it = callbacks.erase(it); + // return; + // } + // } + // } + // } + // } else { + // std::unordered_map< + // std::type_index, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator + // handlers_it + // = subscribers.find(eventType); + // if (handlers_it != subscribers.end()) { + // std::vector<std::unique_ptr<IEventHandlerWrapper>> & handlers + // = handlers_it->second; + // for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it + // = handlers.begin(); + // it != handlers.end(); ++it) { + // if (it->get()->getType() == handlerName) { + // it = handlers.erase(it); + // return; + // } + // } + // } + // } +} + +void EventManager::queue_event(std::unique_ptr<Event> && event_, int eventId) { + events_queue.emplace_back(std::move(event_), eventId); +} + +void EventManager::dispatch_events() { + // for (std::vector<std::pair<std::unique_ptr<Event>, int>>::iterator eventIt + // = eventsQueue.begin(); + // eventIt != eventsQueue.end();) { + // bool handled = false; + // if (!handled) { + // triggerEvent(*eventIt->first.get(), eventIt->second); + // eventIt = eventsQueue.erase(eventIt); + // } else { + // ++eventIt; + // } + // } +} diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h new file mode 100644 index 0000000..8c0685a --- /dev/null +++ b/src/crepe/api/EventManager.h @@ -0,0 +1,76 @@ +#pragma once +#include <memory> +#include <unordered_map> +#include <vector> +#include <functional> +#include <iostream> +#include <typeindex> +#include <type_traits> +#include "Event.h" +#include "EventHandler.h" +//#include "keyCodes.h" + +class EventManager { +public: + EventManager(const EventManager &) = delete; + const EventManager & operator=(const EventManager &) = delete; + static EventManager & get_instance() { + static EventManager instance; + return instance; + } + template <typename EventType> + void subscribe(EventHandler<EventType> && callback, int channel = 0); + void unsubscribe(std::type_index eventType, const std::string & handlerName,int channel); + template <typename EventType> + void trigger_event(const EventType & event, int channel); + void queue_event(std::unique_ptr<Event> && event, int channel); + void dispatch_events(); + +private: + EventManager() = default; + std::vector<std::pair<std::unique_ptr<Event>, int>> events_queue; + std::unordered_map<std::type_index, std::vector<std::unique_ptr<IEventHandlerWrapper>>> subscribers; + std::unordered_map<std::type_index, std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>> subscribers_by_event_id; +}; + +template <typename EventType> +void EventManager::subscribe(EventHandler<EventType> && callback, int channel){ + std::type_index event_type = typeid(EventType); + auto handler = std::make_unique<EventHandlerWrapper<EventType>>(callback); + + if (channel) { + auto & handlers_map = subscribers_by_event_id[event_type]; + auto handlers = handlers_map.find(channel); + if (handlers != handlers_map.end()) { + handlers->second.emplace_back(std::move(handler)); + } else { + handlers_map[channel].emplace_back(std::move(handler)); + } + } else { + subscribers[event_type].emplace_back(std::move(handler)); + } +} + +template <typename EventType> +void EventManager::trigger_event(const EventType & event, int eventId) { + std::type_index event_type = std::type_index(typeid(EventType)); + + if (eventId > 0) { + auto handlers_it = subscribers_by_event_id[event_type].find(eventId); + if (handlers_it != subscribers_by_event_id[event_type].end()) { + auto & callbacks = handlers_it->second; + for (auto it = callbacks.begin(); it != callbacks.end();) { + if ((*it)->exec(event)) { + it = callbacks.erase(it); + } else { + ++it; + } + } + } + } else { + auto & handlers = subscribers[event_type]; + for (auto & handler : handlers) { + handler->exec(event); + } + } +} diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp new file mode 100644 index 0000000..b1ad5e5 --- /dev/null +++ b/src/crepe/api/IKeyListener.cpp @@ -0,0 +1,20 @@ +#include "IKeyListener.h" + +IKeyListener::~IKeyListener() { unsubscribe_events(); } + +void IKeyListener::subscribe_events(int listenerId) { + auto key_pressed_handler = [this](const KeyPressEvent & event) { + return this->on_key_pressed(event); + }; + auto key_released_handler = [this](const KeyReleaseEvent & event) { + return this->on_key_released(event); + }; + + EventManager::get_instance().subscribe<KeyPressEvent>(std::move(key_pressed_handler), listenerId); + EventManager::get_instance().subscribe<KeyReleaseEvent>(std::move(key_released_handler), listenerId); +} + +void IKeyListener::unsubscribe_events(int listenerId) { + EventManager::get_instance().unsubscribe(std::type_index(typeid(KeyPressEvent)), "on_key_pressed", listenerId); + EventManager::get_instance().unsubscribe(std::type_index(typeid(KeyReleaseEvent)), "on_key_released", listenerId); +} diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h new file mode 100644 index 0000000..4fd2238 --- /dev/null +++ b/src/crepe/api/IKeyListener.h @@ -0,0 +1,20 @@ +#pragma once +#include "Event.h" +#include "EventHandler.h" +#include "EventManager.h" +class IKeyListener { +public: + virtual ~IKeyListener(); + virtual bool on_key_pressed(const KeyPressEvent & event) = 0; + virtual bool on_key_released(const KeyReleaseEvent & event) = 0; + +protected: + void subscribe_events(int listenerId = 0); + void unsubscribe_events(int listenerId = 0); + void activate(int listenerId = 0) { subscribe_events(listenerId); } + void deactivate(int listenerId = 0) { unsubscribe_events(listenerId); } + +private: + EventHandler<KeyPressEvent> key_pressed_handler; + EventHandler<KeyReleaseEvent> key_released_handler; +}; diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp new file mode 100644 index 0000000..043188c --- /dev/null +++ b/src/crepe/api/IMouseListener.cpp @@ -0,0 +1,35 @@ +#include "IMouseListener.h" + +IMouseListener::~IMouseListener() { + unsubscribe_events(); +} + +void IMouseListener::subscribe_events(int listenerId) { + // Wrap member functions in lambdas to ensure correct function signatures + mouse_click_handler = [this](const MouseClickEvent & event) { + return this->on_mouse_clicked(event); + }; + mouse_press_handler = [this](const MousePressEvent & event) { + return this->on_mouse_pressed(event); + }; + mouse_release_handler = [this](const MouseReleaseEvent & event) { + return this->on_mouse_released(event); + }; + mouse_move_handler = [this](const MouseMoveEvent & event) { + return this->on_mouse_moved(event); + }; + + // Use EventManager for subscribing + EventManager::get_instance().subscribe<MouseClickEvent>(std::move(mouse_click_handler), listenerId); + EventManager::get_instance().subscribe<MousePressEvent>(std::move(mouse_press_handler), listenerId); + EventManager::get_instance().subscribe<MouseReleaseEvent>(std::move(mouse_release_handler), listenerId); + EventManager::get_instance().subscribe<MouseMoveEvent>(std::move(mouse_move_handler), listenerId); +} + +void IMouseListener::unsubscribe_events(int listenerId) { + // Use EventManager for unsubscribing with correct event type names + EventManager::get_instance().unsubscribe(std::type_index(typeid(MouseClickEvent)), "onMouseClicked", listenerId); + EventManager::get_instance().unsubscribe(std::type_index(typeid(MousePressEvent)), "onMousePressed", listenerId); + EventManager::get_instance().unsubscribe(std::type_index(typeid(MouseReleaseEvent)), "onMouseReleased", listenerId); + EventManager::get_instance().unsubscribe(std::type_index(typeid(MouseMoveEvent)), "onMouseMoved", listenerId); +} diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h new file mode 100644 index 0000000..9222905 --- /dev/null +++ b/src/crepe/api/IMouseListener.h @@ -0,0 +1,24 @@ +#pragma once +#include "Event.h" +#include "EventHandler.h" +#include "EventManager.h" + +class IMouseListener { +public: + virtual ~IMouseListener(); + + virtual bool on_mouse_clicked(const MouseClickEvent & event) = 0; + virtual bool on_mouse_pressed(const MousePressEvent & event) = 0; + virtual bool on_mouse_released(const MouseReleaseEvent & event) = 0; + virtual bool on_mouse_moved(const MouseMoveEvent & event) = 0; + +protected: + void subscribe_events(int listenerId = 0); + void unsubscribe_events(int listenerId = 0); + +private: + EventHandler<MouseClickEvent> mouse_click_handler; + EventHandler<MousePressEvent> mouse_press_handler; + EventHandler<MouseReleaseEvent> mouse_release_handler; + EventHandler<MouseMoveEvent> mouse_move_handler; +}; diff --git a/src/makefile b/src/makefile index b9c44c8..03a2c0e 100644 --- a/src/makefile +++ b/src/makefile @@ -94,8 +94,16 @@ LOEK += example/script.cpp LOEK += test/audio.cpp LOEK += test/dummy.cpp JARO += test/PhysicsTest.cpp - -FMT := $(JARO) #<<< CHANGE THIS TO YOUR NAME FOR STEP 2 +WOUTER += crepe/api/Event.h +WOUTER += crepe/api/EventHandler.cpp +WOUTER += crepe/api/EventHandler.h +WOUTER += crepe/api/EventManager.cpp +WOUTER += crepe/api/EventManager.h +WOUTER += crepe/api/IKeyListener.cpp +WOUTER += crepe/api/IKeyListener.h +WOUTER += crepe/api/IMouseListener.cpp +WOUTER += crepe/api/IMouseListener.h +FMT := $(WOUTER) #<<< CHANGE THIS TO YOUR NAME FOR STEP 2 format: FORCE clang-tidy -p build/compile_commands.json --fix-errors $(FMT) |