From 880a7b1fb233a67303ad5a4155dc459f79734762 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Mon, 11 Nov 2024 10:50:40 +0100 Subject: big cleanup events + events are now structs --- src/crepe/api/Event.h | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/crepe/api/Event.h (limited to 'src/crepe/api/Event.h') 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 +//#include "keyCodes.h" +#include +#include +#include +#include +#include +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: +}; -- cgit v1.2.3 From 48fb3f48831b1db187942592343eb4a2dc6662fc Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Tue, 12 Nov 2024 12:45:19 +0100 Subject: dispatch and queue working --- lib/sdl2 | 2 +- lib/sdl_image | 2 +- lib/sdl_ttf | 2 +- src/crepe/api/Event.h | 1 + src/crepe/api/EventHandler.h | 1 - src/crepe/api/EventManager.cpp | 96 ++++++++++++++-------------------------- src/crepe/api/EventManager.h | 21 ++++++--- src/crepe/api/IKeyListener.cpp | 16 +++---- src/crepe/api/IMouseListener.cpp | 8 ++-- src/example/events.cpp | 51 +++++++++++---------- 10 files changed, 89 insertions(+), 111 deletions(-) (limited to 'src/crepe/api/Event.h') diff --git a/lib/sdl2 b/lib/sdl2 index 9519b99..c98c4fb 160000 --- a/lib/sdl2 +++ b/lib/sdl2 @@ -1 +1 @@ -Subproject commit 9519b9916cd29a14587af0507292f2bd31dd5752 +Subproject commit c98c4fbff6d8f3016a3ce6685bf8f43433c3efcc diff --git a/lib/sdl_image b/lib/sdl_image index abcf63a..5656019 160000 --- a/lib/sdl_image +++ b/lib/sdl_image @@ -1 +1 @@ -Subproject commit abcf63aa71b4e3ac32120fa9870a6500ddcdcc89 +Subproject commit 56560190a6c5b5740e5afdce747e2a2bfbf16db1 diff --git a/lib/sdl_ttf b/lib/sdl_ttf index 4a318f8..a3d0895 160000 --- a/lib/sdl_ttf +++ b/lib/sdl_ttf @@ -1 +1 @@ -Subproject commit 4a318f8dfaa1bb6f10e0c5e54052e25d3c7f3440 +Subproject commit a3d0895c1b60c41ff9e85d9203ddd7485c014dae diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h index 8d9b241..c0de4fc 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -19,6 +19,7 @@ enum class MouseButton { }; class Event { public: +bool handled = false; }; class KeyPressEvent : public Event { diff --git a/src/crepe/api/EventHandler.h b/src/crepe/api/EventHandler.h index 0da6d7d..eea1c79 100644 --- a/src/crepe/api/EventHandler.h +++ b/src/crepe/api/EventHandler.h @@ -24,7 +24,6 @@ class EventHandlerWrapper : public IEventHandlerWrapper { public: explicit EventHandlerWrapper(const EventHandler & handler) : m_handler(handler), m_handler_type(m_handler.target_type().name()) { - std::cout << "subscribe name: " << m_handler_type << std::endl; } private: diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index 7a8be53..869ec74 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -1,69 +1,39 @@ #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>>>::iterator subscriber_list = subscribers_by_event_id.find(eventType); -// if (subscriber_list != subscribers_by_event_id.end()) { -// std::unordered_map< -// int, std::vector>> & -// handlers_map -// = subscriber_list->second; -// std::unordered_map< -// int, -// std::vector>>::iterator -// handlers -// = handlers_map.find(eventId); -// if (handlers != handlers_map.end()) { -// std::vector> & callbacks -// = handlers->second; -// for (std::vector< -// std::unique_ptr>::iterator it -// = callbacks.begin(); -// it != callbacks.end(); ++it) { -// if (it->get()->get_type() == handlerName) { -// it = callbacks.erase(it); -// return; -// } -// } -// } -// } -// } else { -// std::unordered_map< -// std::type_index, std::vector>>::iterator -// handlers_it -// = subscribers.find(eventType); -// if (handlers_it != subscribers.end()) { -// std::vector> & handlers -// = handlers_it->second; -// for (std::vector>::iterator it -// = handlers.begin(); -// it != handlers.end(); ++it) { -// if (it->get()->get_type() == handlerName) { -// it = handlers.erase(it); -// return; -// } -// } -// } -// } -// } -void EventManager::queue_event(std::unique_ptr && event_, int eventId) { - events_queue.emplace_back(std::move(event_), eventId); -} void EventManager::dispatch_events() { - for (std::vector, int>>::iterator event_it - = events_queue.begin(); - event_it != events_queue.end();) { - bool handled = false; - if (!handled) { - trigger_event(*event_it->first.get(), event_it->second); - event_it = events_queue.erase(event_it); - } else { - ++event_it; - } - } + for (auto event_it = events_queue.begin(); event_it != events_queue.end();) { + auto& event = std::get<0>(*event_it); + int channel = std::get<1>(*event_it); + std::type_index event_type = std::get<2>(*event_it); + if (channel) { + auto handlers_it = subscribers_by_event_id.find(event_type); + if (handlers_it != subscribers_by_event_id.end()) { + auto& handlers_map = handlers_it->second; + auto handlers = handlers_map.find(channel); + if (handlers != handlers_map.end()) { + auto& callbacks = handlers->second; + for (auto& handler : callbacks) { + handler->exec(*event); + } + } + } + } else { + auto handlers_it = subscribers.find(event_type); + if (handlers_it != subscribers.end()) { + auto& handlers = handlers_it->second; + for (auto& handler : handlers) { + handler->exec(*event); + } + } + } + + if (event->handled) { + event_it = events_queue.erase(event_it); + } else { + ++event_it; + } + } } + diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index 91120fd..be9a947 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -24,12 +24,13 @@ public: void unsubscribe(const EventHandler &, int eventId); template void trigger_event(const EventType & event, int channel); - void queue_event(std::unique_ptr && event, int channel); + template + void queue_event(EventType&& event, int channel); void dispatch_events(); private: EventManager() = default; - std::vector, int>> events_queue; + std::vector, int, std::type_index>> events_queue; std::unordered_map>> subscribers; std::unordered_map>>> subscribers_by_event_id; }; @@ -51,6 +52,19 @@ void EventManager::subscribe(EventHandler && callback, int channel){ subscribers[event_type].emplace_back(std::move(handler)); } } +template +void EventManager::queue_event(EventType&& event, int channel) { + std::type_index event_type = std::type_index(typeid(EventType)); + + std::unique_ptr event_ptr = std::make_unique(std::forward(event)); + + std::tuple, int, std::type_index> tuple( + std::move(event_ptr), + channel, + event_type + ); + events_queue.push_back(std::move(tuple)); +} template void EventManager::trigger_event(const EventType & event, int eventId) { @@ -79,7 +93,6 @@ template void EventManager::unsubscribe(const EventHandler & callback, int channel) { std::type_index event_type(typeid(EventType)); const std::string handler_name = callback.target_type().name(); - std::cout << "unsubcribe name: " << handler_name << std::endl; if (channel) { auto subscriber_list = subscribers_by_event_id.find(event_type); @@ -90,7 +103,6 @@ void EventManager::unsubscribe(const EventHandler & callback, int cha auto& callbacks = handlers->second; for (auto it = callbacks.begin(); it != callbacks.end(); ++it) { if ((*it)->get_type() == handler_name) { - std::cout << "successfully erased an event" << std::endl; it = callbacks.erase(it); return; } @@ -103,7 +115,6 @@ void EventManager::unsubscribe(const EventHandler & callback, int cha auto& handlers = handlers_it->second; for (auto it = handlers.begin(); it != handlers.end(); ++it) { if ((*it)->get_type() == handler_name) { - std::cout << "successfully erased an event" << std::endl; it = handlers.erase(it); return; } diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index f35dc20..663dbc7 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -5,27 +5,21 @@ IKeyListener::IKeyListener(){ subscribe_events(0); } IKeyListener::~IKeyListener() { - std::cout << "destructor call" << std::endl; unsubscribe_events(); - } +} void IKeyListener::subscribe_events(int listenerId) { - auto key_pressed_handler = [this](const KeyPressEvent & event) { + key_pressed_handler = [this](const KeyPressEvent & event) { return this->on_key_pressed(event); }; - auto key_released_handler = [this](const KeyReleaseEvent & event) { + key_released_handler = [this](const KeyReleaseEvent & event) { return this->on_key_released(event); }; - std::cout << "IKeyListener subscribe: " << std::endl; - EventManager::get_instance().subscribe(key_pressed_handler, listenerId); - EventManager::get_instance().subscribe(key_released_handler, listenerId); - std::cout << std::endl; + EventManager::get_instance().subscribe(std::move(key_pressed_handler), listenerId); + EventManager::get_instance().subscribe(std::move(key_released_handler), listenerId); } void IKeyListener::unsubscribe_events(int listenerId) { - std::cout << "IKeyListener unsubscribe: " << std::endl; - std::cout << "key_pressed_handler name: " << key_pressed_handler.target_type().name() << std::endl; - std::cout << "key_released_handler name: " << key_released_handler.target_type().name() << std::endl; EventManager::get_instance().unsubscribe(key_pressed_handler , listenerId); EventManager::get_instance().unsubscribe(key_released_handler , listenerId); std::cout << std::endl; diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index 515d801..bb59664 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -8,16 +8,16 @@ IMouseListener::~IMouseListener() { void IMouseListener::subscribe_events(int listenerId) { // Define handler lambdas and subscribe them - auto mouse_click_handler = [this](const MouseClickEvent& event) { + mouse_click_handler = [this](const MouseClickEvent& event) { return this->on_mouse_clicked(event); }; - auto mouse_press_handler = [this](const MousePressEvent& event) { + mouse_press_handler = [this](const MousePressEvent& event) { return this->on_mouse_pressed(event); }; - auto mouse_release_handler = [this](const MouseReleaseEvent& event) { + mouse_release_handler = [this](const MouseReleaseEvent& event) { return this->on_mouse_released(event); }; - auto mouse_move_handler = [this](const MouseMoveEvent& event) { + mouse_move_handler = [this](const MouseMoveEvent& event) { return this->on_mouse_moved(event); }; EventManager::get_instance().subscribe(std::move(mouse_click_handler), listenerId); diff --git a/src/example/events.cpp b/src/example/events.cpp index 53eb97f..1f757e1 100644 --- a/src/example/events.cpp +++ b/src/example/events.cpp @@ -31,19 +31,19 @@ class MyScript : public Script, public IKeyListener,public IMouseListener{ std::cout << "KeyRelease function" << std::endl; return false; } - bool on_mouse_clicked(const MouseClickEvent & event){ + bool on_mouse_clicked(const MouseClickEvent & event) override{ std::cout << "MouseClick function" << std::endl; return false; } - bool on_mouse_pressed(const MousePressEvent & event){ + bool on_mouse_pressed(const MousePressEvent & event) override { std::cout << "MousePress function" << std::endl; return false; } - bool on_mouse_released(const MouseReleaseEvent & event){ + bool on_mouse_released(const MouseReleaseEvent & event) override { std::cout << "MouseRelease function" << std::endl; return false; } - bool on_mouse_moved(const MouseMoveEvent & event){ + bool on_mouse_moved(const MouseMoveEvent & event) override { std::cout << "MouseMove function" << std::endl; return false; } @@ -61,6 +61,17 @@ public: } }; int main() { + // two events to trigger + KeyPressEvent key_press; + key_press.key = 1; + key_press.repeat = 0; + MouseClickEvent click_event; + click_event.button = MouseButton::LEFT_MOUSE; + click_event.mouse_x = 100; + click_event.mouse_y = 200; + // queue events to test queue + EventManager::get_instance().queue_event(std::move(key_press), 0); + EventManager::get_instance().queue_event(std::move(click_event), 0); { // Instantiate TestKeyListener, which subscribes to key events TestKeyListener testListener; @@ -73,32 +84,24 @@ int main() { ScriptSystem sys; sys.update(); - // Trigger some events - KeyPressEvent key_press; - key_press.key = 1; - key_press.repeat = 0; - - MouseClickEvent click_event; - click_event.button = MouseButton::LEFT_MOUSE; - click_event.mouse_x = 100; - click_event.mouse_y = 200; - std::cout << "testing custom listener:" << std::endl; // Trigger the events while `testListener` is in scope EventManager::get_instance().trigger_event(key_press, 0); EventManager::get_instance().trigger_event(click_event, 0); - } // End of scope - triggers destruction of obj, MyScript, and `testListener`, unsubscribing from events - // After `testListener` is destroyed, triggering events again should have no output if unsubscription worked - KeyPressEvent key_press; - key_press.key = 1; - key_press.repeat = 0; - EventManager::get_instance().trigger_event(key_press, 0); + } + // custom lambda event handler + EventHandler event_handler = [](const KeyPressEvent& e) { + std::cout << "lambda test" << std::endl; + return false; + }; + EventManager::get_instance().subscribe(std::move(event_handler),0); + // - MouseClickEvent click_event; - click_event.button = MouseButton::LEFT_MOUSE; - click_event.mouse_x = 100; - click_event.mouse_y = 200; + EventManager::get_instance().trigger_event(key_press, 0); + EventManager::get_instance().trigger_event(click_event, 0); + EventManager::get_instance().dispatch_events(); + EventManager::get_instance().unsubscribe(event_handler,0); return EXIT_SUCCESS; } -- cgit v1.2.3 From 408eb1fb5932a683a65db79afed6a300e18db5c6 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Wed, 13 Nov 2024 15:37:11 +0100 Subject: added keycodes --- .vscode/launch.json | 7 + .vscode/tasks.json | 28 ++++ mwe/events/include/event.h | 2 +- src/crepe/api/Event.h | 62 ++++----- src/crepe/api/EventHandler.h | 41 +++--- src/crepe/api/EventManager.cpp | 105 +++++++++------ src/crepe/api/EventManager.h | 274 +++++++++++++++++++++++---------------- src/crepe/api/IKeyListener.cpp | 51 ++++---- src/crepe/api/IKeyListener.h | 48 +++---- src/crepe/api/IMouseListener.cpp | 82 ++++++------ src/crepe/api/IMouseListener.h | 78 +++++------ src/crepe/api/KeyCodes.h | 147 +++++++++++++++++++++ src/example/events.cpp | 98 +++++++------- 13 files changed, 637 insertions(+), 386 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json create mode 100644 src/crepe/api/KeyCodes.h (limited to 'src/crepe/api/Event.h') diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..5c7247b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,7 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..05054c5 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,28 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: g++ build active file", + "command": "/usr/bin/g++", + "args": [ + "-fdiagnostics-color=always", + "-g", + "${file}", + "-o", + "${fileDirname}/${fileBasenameNoExtension}" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/mwe/events/include/event.h b/mwe/events/include/event.h index 16c75bf..3e70201 100644 --- a/mwe/events/include/event.h +++ b/mwe/events/include/event.h @@ -152,7 +152,7 @@ private: }; class ShutDownEvent : public Event { public: - ShutDownEvent() : Event("ShutDownEvent") {}; + ShutDownEvent() : Event("ShutDownEvent"){}; REGISTER_EVENT_TYPE(ShutDownEvent) diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h index c0de4fc..87c6068 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -1,68 +1,56 @@ #pragma once #include -//#include "keyCodes.h" -#include #include #include -#include -#include -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, -}; +#include "KeyCodes.h" + class Event { public: -bool handled = false; + bool handled = false; }; class KeyPressEvent : public Event { public: - int repeat = 0; - Keycode key = 0; + int repeat = 0; + Keycode key = Keycode::None; }; -class MouseClickEvent : public Event { -public: - int mouse_x = 0; - int mouse_y = 0; - MouseButton button; -}; class KeyReleaseEvent : public Event { public: - Keycode key = 0; + Keycode key = Keycode::None; }; class MousePressEvent : public Event { public: - int mouse_x = 0; - int mouse_y = 0; - MouseButton button; + int mouse_x = 0; + int mouse_y = 0; + MouseButton button; +}; + +class MouseClickEvent : 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; + int mouse_x = 0; + int mouse_y = 0; + MouseButton button = MouseButton::None; }; class MouseMoveEvent : public Event { public: - int mouse_x = 0; - int mouse_y = 0; + int mouse_x = 0; + int mouse_y = 0; }; -class CollisionEvent : public Event{ +class CollisionEvent : public Event { public: - //Collision collisionData; + //Collision collisionData; }; -class TextSubmitEvent : public Event{ +class TextSubmitEvent : public Event { public: - std::string text; + std::string text; }; class ShutDownEvent : public Event { public: diff --git a/src/crepe/api/EventHandler.h b/src/crepe/api/EventHandler.h index dc06806..46c6c7b 100644 --- a/src/crepe/api/EventHandler.h +++ b/src/crepe/api/EventHandler.h @@ -1,8 +1,8 @@ #pragma once +#include "Event.h" #include #include #include -#include "Event.h" /** * \brief A type alias for an event handler function. @@ -24,12 +24,12 @@ using EventHandler = std::function; */ class IEventHandlerWrapper { public: - /** + /** * \brief Virtual destructor for IEventHandlerWrapper. */ - virtual ~IEventHandlerWrapper() = default; + virtual ~IEventHandlerWrapper() = default; - /** + /** * \brief Executes the handler with the given event. * * This method calls the `call()` method of the derived class, passing the event to the handler. @@ -37,19 +37,19 @@ public: * \param e The event to be processed. * \return A boolean value indicating whether the event is handled. */ - bool exec(const Event & e); + bool exec(const Event & e); - /** + /** * \brief Get the type of the event handler. * * This method returns the type of the event handler as a string. * * \return A string representing the handler's type. */ - virtual std::string get_type() const = 0; + virtual std::string get_type() const = 0; private: - /** + /** * \brief The method responsible for handling the event. * * This method is implemented by derived classes to process the event. @@ -57,7 +57,7 @@ private: * \param e The event to be processed. * \return A boolean value indicating whether the event is handled. */ - virtual bool call(const Event & e) = 0; + virtual bool call(const Event & e) = 0; }; /** @@ -73,19 +73,18 @@ private: template class EventHandlerWrapper : public IEventHandlerWrapper { public: - /** + /** * \brief Constructs an EventHandlerWrapper with a given handler. * * The constructor takes an event handler function and stores it in the wrapper. * * \param handler The event handler function. */ - explicit EventHandlerWrapper(const EventHandler & handler) - : m_handler(handler), m_handler_type(m_handler.target_type().name()) { - } + explicit EventHandlerWrapper(const EventHandler & handler) + : m_handler(handler), m_handler_type(m_handler.target_type().name()) {} private: - /** + /** * \brief Calls the stored event handler with the event. * * This method casts the event to the appropriate type and calls the handler. @@ -93,20 +92,20 @@ private: * \param e The event to be handled. * \return A boolean value indicating whether the event is handled. */ - bool call(const Event & e) override { - return m_handler(static_cast(e)); - } + bool call(const Event & e) override { + return m_handler(static_cast(e)); + } - /** + /** * \brief Returns the type of the handler. * * This method returns a string representing the type of the event handler. * * \return The handler type as a string. */ - std::string get_type() const override { return m_handler_type; } + std::string get_type() const override { return m_handler_type; } //! The event handler function. - EventHandler m_handler; + EventHandler m_handler; //! The type name of the handler function. - const std::string m_handler_type; + const std::string m_handler_type; }; diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index 42bff12..72cfd74 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -6,46 +6,73 @@ EventManager & EventManager::get_instance() { } void EventManager::dispatch_events() { - for (std::vector, int, std::type_index>>::iterator event_it = this->events_queue.begin(); event_it != this->events_queue.end();) { - std::unique_ptr& event = std::get<0>(*event_it); - int channel = std::get<1>(*event_it); - std::type_index event_type = std::get<2>(*event_it); + for (std::vector, int, + std::type_index>>::iterator event_it + = this->events_queue.begin(); + event_it != this->events_queue.end();) { + std::unique_ptr & event = std::get<0>(*event_it); + int channel = std::get<1>(*event_it); + std::type_index event_type = std::get<2>(*event_it); - bool event_handled = false; + bool event_handled = false; - if (channel) { - std::unordered_map>>>::iterator handlers_it = subscribers_by_event_id.find(event_type); - if (handlers_it != subscribers_by_event_id.end()) { - std::unordered_map>>& handlers_map = handlers_it->second; - std::unordered_map>>::iterator handlers = handlers_map.find(channel); - if (handlers != handlers_map.end()) { - std::vector>& callbacks = handlers->second; - for (std::vector>::iterator handler_it = callbacks.begin(); handler_it != callbacks.end(); ++handler_it) { - if ((*handler_it)->exec(*event)) { - event_it = events_queue.erase(event_it); - event_handled = true; - break; - } - } - } - } - } else { - // Handle event for all channels - std::unordered_map>>::iterator handlers_it = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - std::vector>& handlers = handlers_it->second; - for (std::vector>::iterator handler_it = handlers.begin(); handler_it != handlers.end(); ++handler_it) { - if ((*handler_it)->exec(*event)) { - event_it = this->events_queue.erase(event_it); - event_handled = true; - break; - } - } - } - } + if (channel) { + std::unordered_map< + std::type_index, + std::unordered_map< + int, std::vector>>>:: + iterator handlers_it + = subscribers_by_event_id.find(event_type); + if (handlers_it != subscribers_by_event_id.end()) { + std::unordered_map< + int, std::vector>> & + handlers_map + = handlers_it->second; + std::unordered_map< + int, std::vector>>:: + iterator handlers + = handlers_map.find(channel); + if (handlers != handlers_map.end()) { + std::vector> & + callbacks + = handlers->second; + for (std::vector>:: + iterator handler_it + = callbacks.begin(); + handler_it != callbacks.end(); ++handler_it) { + if ((*handler_it)->exec(*event)) { + event_it = events_queue.erase(event_it); + event_handled = true; + break; + } + } + } + } + } else { + // Handle event for all channels + std::unordered_map< + std::type_index, + std::vector>>::iterator + handlers_it + = this->subscribers.find(event_type); + if (handlers_it != this->subscribers.end()) { + std::vector> & handlers + = handlers_it->second; + for (std::vector>:: + iterator handler_it + = handlers.begin(); + handler_it != handlers.end(); ++handler_it) { + if ((*handler_it)->exec(*event)) { + event_it = this->events_queue.erase(event_it); + event_handled = true; + break; + } + } + } + } - if (!event_handled) { - ++event_it; - } - } + if (!event_handled) { + ++event_it; + } + } } diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index b963ce3..26539ce 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -1,11 +1,11 @@ #pragma once +#include #include +#include +#include #include #include -#include -#include -#include #include "Event.h" #include "EventHandler.h" @@ -17,26 +17,26 @@ */ class EventManager { public: - /** + /** * \brief Deleted copy constructor to prevent copying of the EventManager instance. */ - EventManager(const EventManager &) = delete; + EventManager(const EventManager &) = delete; - /** + /** * \brief Deleted copy assignment operator to prevent assignment of the EventManager instance. */ - const EventManager & operator=(const EventManager &) = delete; + const EventManager & operator=(const EventManager &) = delete; - /** + /** * \brief Get the singleton instance of the EventManager. * * This method returns the unique instance of the EventManager, creating it on the first call. * * \return Reference to the EventManager instance. */ - static EventManager & get_instance(); + static EventManager & get_instance(); - /** + /** * \brief Subscribe to an event. * * This method allows the registration of a callback for a specific event type and channel. @@ -45,10 +45,10 @@ public: * \param callback The callback function to invoke when the event is triggered. * \param channel The channel number to subscribe to (default is 0). */ - template - void subscribe(EventHandler && callback, int channel = 0); + template + void subscribe(EventHandler && callback, int channel = 0); - /** + /** * \brief Unsubscribe from an event. * * This method removes a previously registered callback from an event. @@ -57,10 +57,10 @@ public: * \param callback The callback function to remove from the subscription list. * \param channel The event ID to unsubscribe from. */ - template - void unsubscribe(const EventHandler &, int channel); + template + void unsubscribe(const EventHandler &, int channel); - /** + /** * \brief Trigger an event. * * This method invokes the appropriate callback(s) for the specified event. @@ -69,10 +69,10 @@ public: * \param event The event data to pass to the callback. * \param channel The channel from which to trigger the event (default is 0). */ - template - void trigger_event(const EventType & event, int channel); + template + void trigger_event(const EventType & event, int channel); - /** + /** * \brief Queue an event for later processing. * * This method adds an event to the event queue, which will be processed in the @@ -82,128 +82,176 @@ public: * \param event The event to queue. * \param channel The channel number for the event (default is 0). */ - template - void queue_event(EventType&& event, int channel); + template + void queue_event(EventType && event, int channel); - /** + /** * \brief Dispatch all queued events. * * This method processes all events in the event queue and triggers the corresponding * callbacks for each event. */ - void dispatch_events(); + void dispatch_events(); private: - /** + /** * \brief Default constructor for the EventManager. * * This constructor is private to enforce the singleton pattern. */ - EventManager() = default; + EventManager() = default; - //! The queue of events to be processed. - std::vector, int, std::type_index>> events_queue; + //! The queue of events to be processed. + std::vector, int, std::type_index>> + events_queue; //! Registered event handlers. - std::unordered_map>> subscribers; + std::unordered_map>> + subscribers; //! Event handlers indexed by event ID. - std::unordered_map>>> subscribers_by_event_id; + std::unordered_map< + std::type_index, + std::unordered_map>>> + subscribers_by_event_id; }; - template void EventManager::subscribe(EventHandler && callback, int channel) { - std::type_index event_type = typeid(EventType); - std::unique_ptr> handler = std::make_unique>(callback); - - if (channel) { - std::unordered_map>>& handlers_map = this->subscribers_by_event_id[event_type]; - std::unordered_map>>::iterator 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 { - std::vector>& handlers = this->subscribers[event_type]; - handlers.emplace_back(std::move(handler)); - } + std::type_index event_type = typeid(EventType); + std::unique_ptr> handler + = std::make_unique>(callback); + + if (channel) { + std::unordered_map>> & + handlers_map + = this->subscribers_by_event_id[event_type]; + std::unordered_map< + int, std::vector>>::iterator + 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 { + std::vector> & handlers + = this->subscribers[event_type]; + handlers.emplace_back(std::move(handler)); + } } template -void EventManager::queue_event(EventType&& event, int channel) { - std::type_index event_type = std::type_index(typeid(EventType)); - - std::unique_ptr event_ptr = std::make_unique(std::forward(event)); - - std::tuple, int, std::type_index> tuple( - std::move(event_ptr), - channel, - event_type - ); - this->events_queue.push_back(std::move(tuple)); +void EventManager::queue_event(EventType && event, int channel) { + std::type_index event_type = std::type_index(typeid(EventType)); + + std::unique_ptr event_ptr + = std::make_unique(std::forward(event)); + + std::tuple, int, std::type_index> tuple( + std::move(event_ptr), channel, event_type); + this->events_queue.push_back(std::move(tuple)); } template void EventManager::trigger_event(const EventType & event, int channel) { - std::type_index event_type = std::type_index(typeid(EventType)); - - if (channel > 0) { - std::unordered_map>>& handlers_map = this->subscribers_by_event_id[event_type]; - std::unordered_map>>::iterator handlers_it = handlers_map.find(channel); - - if (handlers_it != handlers_map.end()) { - std::vector>& handlers = handlers_it->second; - for (std::vector>::iterator it = handlers.begin(); it != handlers.end();) { + std::type_index event_type = std::type_index(typeid(EventType)); + + if (channel > 0) { + std::unordered_map>> & + handlers_map + = this->subscribers_by_event_id[event_type]; + std::unordered_map< + int, std::vector>>::iterator + handlers_it + = handlers_map.find(channel); + + if (handlers_it != handlers_map.end()) { + std::vector> & handlers + = handlers_it->second; + for (std::vector>::iterator it + = handlers.begin(); + it != handlers.end();) { // erases callback if callback function returns true - if ((*it)->exec(event)) { - it = handlers.erase(it); - } else { - ++it; - } - } - } - } else { - std::vector>& handlers = this->subscribers[event_type]; - for (std::vector>::iterator it = handlers.begin(); it != handlers.end();) { + if ((*it)->exec(event)) { + it = handlers.erase(it); + } else { + ++it; + } + } + } + } else { + std::vector> & handlers + = this->subscribers[event_type]; + for (std::vector>::iterator it + = handlers.begin(); + it != handlers.end();) { // erases callback if callback function returns true - if ((*it)->exec(event)) { - it = handlers.erase(it); - } else { - ++it; - } - } - } + if ((*it)->exec(event)) { + it = handlers.erase(it); + } else { + ++it; + } + } + } } template -void EventManager::unsubscribe(const EventHandler & callback, int channel) { - std::type_index event_type(typeid(EventType)); - std::string handler_name = callback.target_type().name(); - - if (channel) { - std::unordered_map>>>::iterator subscriber_list = this->subscribers_by_event_id.find(event_type); - if (subscriber_list != this->subscribers_by_event_id.end()) { - std::unordered_map>>& handlers_map = subscriber_list->second; - std::unordered_map>>::iterator handlers = handlers_map.find(channel); - if (handlers != handlers_map.end()) { - std::vector>& callbacks = handlers->second; - for (std::vector>::iterator it = callbacks.begin(); it != callbacks.end(); ++it) { - if ((*it)->get_type() == handler_name) { - it = callbacks.erase(it); - return; - } - } - } - } - } else { - std::unordered_map>>::iterator handlers_it = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - std::vector>& handlers = handlers_it->second; - for (std::vector>::iterator it = handlers.begin(); it != handlers.end(); ++it) { - if ((*it)->get_type() == handler_name) { - it = handlers.erase(it); - return; - } - } - } - } +void EventManager::unsubscribe(const EventHandler & callback, + int channel) { + std::type_index event_type(typeid(EventType)); + std::string handler_name = callback.target_type().name(); + + if (channel) { + std::unordered_map< + std::type_index, + std::unordered_map< + int, std::vector>>>:: + iterator subscriber_list + = this->subscribers_by_event_id.find(event_type); + if (subscriber_list != this->subscribers_by_event_id.end()) { + std::unordered_map< + int, std::vector>> & + handlers_map + = subscriber_list->second; + std::unordered_map< + int, + std::vector>>::iterator + handlers + = handlers_map.find(channel); + if (handlers != handlers_map.end()) { + std::vector> & callbacks + = handlers->second; + for (std::vector< + std::unique_ptr>::iterator it + = callbacks.begin(); + it != callbacks.end(); ++it) { + if ((*it)->get_type() == handler_name) { + it = callbacks.erase(it); + return; + } + } + } + } + } else { + std::unordered_map>>:: + iterator handlers_it + = this->subscribers.find(event_type); + if (handlers_it != this->subscribers.end()) { + std::vector> & handlers + = handlers_it->second; + for (std::vector>::iterator it + = handlers.begin(); + it != handlers.end(); ++it) { + if ((*it)->get_type() == handler_name) { + it = handlers.erase(it); + return; + } + } + } + } } + diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index e759eca..eb8f9af 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -1,48 +1,49 @@ #include "IKeyListener.h" #include -IKeyListener::IKeyListener(){ +IKeyListener::IKeyListener() { this->channel = channel; this->subscribe_events(); } -IKeyListener::IKeyListener(int channel){ +IKeyListener::IKeyListener(int channel) { this->channel = channel; this->subscribe_events(); } -IKeyListener::~IKeyListener() { - this->unsubscribe_events(); -} +IKeyListener::~IKeyListener() { this->unsubscribe_events(); } void IKeyListener::subscribe_events() { - key_pressed_handler = [this](const KeyPressEvent & event) { - return this->on_key_pressed(event); - }; - key_released_handler = [this](const KeyReleaseEvent & event) { - return this->on_key_released(event); - }; - EventManager::get_instance().subscribe(std::move(this->key_pressed_handler), this->channel); - EventManager::get_instance().subscribe(std::move(this->key_released_handler), this->channel); + key_pressed_handler = [this](const KeyPressEvent & event) { + return this->on_key_pressed(event); + }; + key_released_handler = [this](const KeyReleaseEvent & event) { + return this->on_key_released(event); + }; + EventManager::get_instance().subscribe( + std::move(this->key_pressed_handler), this->channel); + EventManager::get_instance().subscribe( + std::move(this->key_released_handler), this->channel); } void IKeyListener::unsubscribe_events() { - EventManager::get_instance().unsubscribe(this->key_pressed_handler , channel); - EventManager::get_instance().unsubscribe(this->key_released_handler , channel); + EventManager::get_instance().unsubscribe( + this->key_pressed_handler, channel); + EventManager::get_instance().unsubscribe( + this->key_released_handler, channel); std::cout << std::endl; } -void IKeyListener::activate_keys() { - if(this->active){ +void IKeyListener::activate_keys() { + if (this->active) { return; } - this->subscribe_events(); + this->subscribe_events(); } -void IKeyListener::deactivate_keys() { - if(!this->active){ +void IKeyListener::deactivate_keys() { + if (!this->active) { return; } - this->unsubscribe_events(); + this->unsubscribe_events(); } -void IKeyListener::set_channel(int channel){ - this->unsubscribe_events(); +void IKeyListener::set_channel(int channel) { + this->unsubscribe_events(); this->channel = channel; - this->subscribe_events(); - + this->subscribe_events(); } diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index 6d7915d..839acbf 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -9,70 +9,70 @@ */ class IKeyListener { public: - /** + /** * \brief Constructs an IKeyListener with a specified channel. * \param channel The channel ID for event handling. */ - IKeyListener(int channel); + IKeyListener(int channel); - /** + /** * \brief Default constructor for IKeyListener. */ - IKeyListener(); + IKeyListener(); - /** + /** * \brief Destructor. */ - virtual ~IKeyListener(); + virtual ~IKeyListener(); - /** + /** * \brief Pure virtual function to handle key press events. * \param event The key press event to handle. * \return True if the event was handled, false otherwise. */ - virtual bool on_key_pressed(const KeyPressEvent& event) = 0; + virtual bool on_key_pressed(const KeyPressEvent & event) = 0; - /** + /** * \brief Pure virtual function to handle key release events. * \param event The key release event to handle. * \return True if the event was handled, false otherwise. */ - virtual bool on_key_released(const KeyReleaseEvent& event) = 0; + virtual bool on_key_released(const KeyReleaseEvent & event) = 0; - /** + /** * \brief Activates key listening. */ - void activate_keys(); + void activate_keys(); - /** + /** * \brief Deactivates key listening. */ - void deactivate_keys(); + void deactivate_keys(); - /** + /** * \brief Sets the channel ID for event handling. * \param channel The channel ID to set. */ - void set_channel(int channel); + void set_channel(int channel); protected: - /** + /** * \brief Subscribes to key events. */ - void subscribe_events(); + void subscribe_events(); - /** + /** * \brief Unsubscribes from key events. */ - void unsubscribe_events(); + void unsubscribe_events(); private: //! Indicates whether key listening is active. - bool active = true; + bool active = true; //! Channel ID for event handling. - int channel = 0; + int channel = 0; //! Key press event handler. - EventHandler key_pressed_handler; + EventHandler key_pressed_handler; //!< Key release event handler. - EventHandler key_released_handler; + EventHandler key_released_handler; }; diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index c6ea419..683632c 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -1,54 +1,56 @@ #include "IMouseListener.h" -IMouseListener::IMouseListener(int channel){ - this->channel = channel; -} -IMouseListener::IMouseListener(){ - this->subscribe_events(); -} -IMouseListener::~IMouseListener() { - this->unsubscribe_events(); -} +IMouseListener::IMouseListener(int channel) { this->channel = channel; } +IMouseListener::IMouseListener() { this->subscribe_events(); } +IMouseListener::~IMouseListener() { this->unsubscribe_events(); } void IMouseListener::subscribe_events() { - // Define handler lambdas and subscribe them - 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); - }; - EventManager::get_instance().subscribe(std::move(this->mouse_click_handler), this->channel); - EventManager::get_instance().subscribe(std::move(this->mouse_press_handler), this->channel); - EventManager::get_instance().subscribe(std::move(this->mouse_release_handler), this->channel); - EventManager::get_instance().subscribe(std::move(this->mouse_move_handler), this->channel); + // Define handler lambdas and subscribe them + 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); + }; + EventManager::get_instance().subscribe( + std::move(this->mouse_click_handler), this->channel); + EventManager::get_instance().subscribe( + std::move(this->mouse_press_handler), this->channel); + EventManager::get_instance().subscribe( + std::move(this->mouse_release_handler), this->channel); + EventManager::get_instance().subscribe( + std::move(this->mouse_move_handler), this->channel); } void IMouseListener::unsubscribe_events() { - EventManager::get_instance().unsubscribe(this->mouse_click_handler, this->channel); - EventManager::get_instance().unsubscribe(this->mouse_press_handler, this->channel); - EventManager::get_instance().unsubscribe(this->mouse_release_handler, this->channel); - EventManager::get_instance().unsubscribe(this->mouse_move_handler, this->channel); -} -void IMouseListener::activate_mouse() { - if(this->active){ + EventManager::get_instance().unsubscribe( + this->mouse_click_handler, this->channel); + EventManager::get_instance().unsubscribe( + this->mouse_press_handler, this->channel); + EventManager::get_instance().unsubscribe( + this->mouse_release_handler, this->channel); + EventManager::get_instance().unsubscribe( + this->mouse_move_handler, this->channel); +} +void IMouseListener::activate_mouse() { + if (this->active) { return; } - this->subscribe_events(); + this->subscribe_events(); } -void IMouseListener::deactivate_mouse() { - if(!this->active){ +void IMouseListener::deactivate_mouse() { + if (!this->active) { return; } - this->unsubscribe_events(); + this->unsubscribe_events(); } -void IMouseListener::set_channel(int channel){ - this->unsubscribe_events(); +void IMouseListener::set_channel(int channel) { + this->unsubscribe_events(); this->channel = channel; - this->subscribe_events(); + this->subscribe_events(); } diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index a7ad271..7e92956 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -10,108 +10,108 @@ */ class IMouseListener { public: - /** + /** * \brief Default constructor. */ - IMouseListener(); + IMouseListener(); - /** + /** * \brief Constructs an IMouseListener with a specified channel. * \param channel The channel ID for event handling. */ - IMouseListener(int channel); + IMouseListener(int channel); - /** + /** * \brief Destructor. */ - virtual ~IMouseListener(); + virtual ~IMouseListener(); - /** + /** * \brief Copy constructor (deleted). */ - IMouseListener(const IMouseListener&) = delete; + IMouseListener(const IMouseListener &) = delete; - /** + /** * \brief Copy assignment operator (deleted). */ - IMouseListener& operator=(const IMouseListener&) = delete; + IMouseListener & operator=(const IMouseListener &) = delete; - /** + /** * \brief Move constructor (deleted). */ - IMouseListener(IMouseListener&&) = delete; + IMouseListener(IMouseListener &&) = delete; - /** + /** * \brief Move assignment operator (deleted). */ - IMouseListener& operator=(IMouseListener&&) = delete; + IMouseListener & operator=(IMouseListener &&) = delete; - /** + /** * \brief Handles a mouse click event. * \param event The mouse click event to handle. * \return True if the event was handled, false otherwise. */ - virtual bool on_mouse_clicked(const MouseClickEvent& event) = 0; + virtual bool on_mouse_clicked(const MouseClickEvent & event) = 0; - /** + /** * \brief Handles a mouse press event. * \param event The mouse press event to handle. * \return True if the event was handled, false otherwise. */ - virtual bool on_mouse_pressed(const MousePressEvent& event) = 0; + virtual bool on_mouse_pressed(const MousePressEvent & event) = 0; - /** + /** * \brief Handles a mouse release event. * \param event The mouse release event to handle. * \return True if the event was handled, false otherwise. */ - virtual bool on_mouse_released(const MouseReleaseEvent& event) = 0; + virtual bool on_mouse_released(const MouseReleaseEvent & event) = 0; - /** + /** * \brief Handles a mouse move event. * \param event The mouse move event to handle. * \return True if the event was handled, false otherwise. */ - virtual bool on_mouse_moved(const MouseMoveEvent& event) = 0; + virtual bool on_mouse_moved(const MouseMoveEvent & event) = 0; - /** + /** * \brief Activates mouse listening. */ - void activate_mouse(); + void activate_mouse(); - /** + /** * \brief Deactivates mouse listening. */ - void deactivate_mouse(); + void deactivate_mouse(); - /** + /** * \brief Sets the channel ID for event handling. * \param channel The channel ID to set. */ - void set_channel(int channel); + void set_channel(int channel); protected: - /** + /** * \brief Subscribes to mouse events on the specified channel. */ - void subscribe_events(); + void subscribe_events(); - /** + /** * \brief Unsubscribes from mouse events on the specified channel. */ - void unsubscribe_events(); + void unsubscribe_events(); private: //! Indicates whether mouse listening is active. - bool active = true; - //! Channel ID for event handling. - int channel = 0; + bool active = true; + //! Channel ID for event handling. + int channel = 0; //! Mouse click event handler. - EventHandler mouse_click_handler; + EventHandler mouse_click_handler; //! Mouse press event handler. - EventHandler mouse_press_handler; + EventHandler mouse_press_handler; //! Mouse release event handler. - EventHandler mouse_release_handler; + EventHandler mouse_release_handler; //! Mouse move event handler. - EventHandler mouse_move_handler; + EventHandler mouse_move_handler; }; diff --git a/src/crepe/api/KeyCodes.h b/src/crepe/api/KeyCodes.h new file mode 100644 index 0000000..53be91b --- /dev/null +++ b/src/crepe/api/KeyCodes.h @@ -0,0 +1,147 @@ +#pragma once + +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 class Keycode : int{ + // From glfw3.h + None = 0, + 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 +}; diff --git a/src/example/events.cpp b/src/example/events.cpp index af6f294..210c42c 100644 --- a/src/example/events.cpp +++ b/src/example/events.cpp @@ -4,103 +4,107 @@ #include #include +#include +#include +#include +#include #include #include #include #include #include -#include "crepe/api/Event.h" -#include "crepe/api/EventManager.h" -#include "crepe/api/IKeyListener.h" -#include "crepe/api/IMouseListener.h" +#include using namespace crepe; using namespace std; -class MyScript : public Script, public IKeyListener,public IMouseListener{ +class MyScript : public Script, public IKeyListener, public IMouseListener { void update() { // Retrieve component from the same GameObject this script is on Transform & test = get_component(); dbg_logf("Transform(%.2f, %.2f)", test.position.x, test.position.y); } - bool on_key_pressed(const KeyPressEvent & event) override{ + bool on_key_pressed(const KeyPressEvent & event) override { std::cout << "KeyPressed function" << std::endl; this->deactivate_keys(); return false; } - bool on_key_released(const KeyReleaseEvent & event) override{ + bool on_key_released(const KeyReleaseEvent & event) override { std::cout << "KeyRelease function" << std::endl; return false; } - bool on_mouse_clicked(const MouseClickEvent & event) override{ + bool on_mouse_clicked(const MouseClickEvent & event) override { std::cout << "MouseClick function" << std::endl; return false; } - bool on_mouse_pressed(const MousePressEvent & event) override { + bool on_mouse_pressed(const MousePressEvent & event) override { std::cout << "MousePress function" << std::endl; return false; } - bool on_mouse_released(const MouseReleaseEvent & event) override { + bool on_mouse_released(const MouseReleaseEvent & event) override { std::cout << "MouseRelease function" << std::endl; return false; } - bool on_mouse_moved(const MouseMoveEvent & event) override { + bool on_mouse_moved(const MouseMoveEvent & event) override { std::cout << "MouseMove function" << std::endl; return false; } - }; class TestKeyListener : public IKeyListener { public: - bool on_key_pressed(const KeyPressEvent &event) override { - std::cout << "TestKeyListener: Key Pressed - Code: " << event.key << std::endl; - return true; // Return true if the listener should remain active - } - bool on_key_released(const KeyReleaseEvent &event) override { - std::cout << "TestKeyListener: Key Released - Code: " << event.key << std::endl; - return true; - } + bool on_key_pressed(const KeyPressEvent & event) override { + std::cout << "TestKeyListener: Key Pressed - Code: " << static_cast(event.key) + << std::endl; + return true; // Return true if the listener should remain active + } + bool on_key_released(const KeyReleaseEvent & event) override { + std::cout << "TestKeyListener: Key Released - Code: " << static_cast(event.key) + << std::endl; + return true; + } }; int main() { // two events to trigger KeyPressEvent key_press; - key_press.key = 1; - key_press.repeat = 0; + key_press.key = Keycode::A; + key_press.repeat = 0; MouseClickEvent click_event; - click_event.button = MouseButton::LEFT_MOUSE; - click_event.mouse_x = 100; - click_event.mouse_y = 200; + click_event.button = MouseButton::Left_Mouse; + click_event.mouse_x = 100; + click_event.mouse_y = 200; // queue events to test queue - EventManager::get_instance().queue_event(std::move(key_press), 0); - EventManager::get_instance().queue_event(std::move(click_event), 0); - { - TestKeyListener testListener; - testListener.set_channel(1); - auto obj = GameObject(0, "name", "tag", Vector2{1.2, 3.4}, 0, 1); - obj.add_component().set_script(); + EventManager::get_instance().queue_event( + std::move(key_press), 0); + EventManager::get_instance().queue_event( + std::move(click_event), 0); + { + TestKeyListener test_listener; + test_listener.set_channel(1); + auto obj = GameObject(0, "name", "tag", Vector2{1.2, 3.4}, 0, 1); + obj.add_component().set_script(); - ScriptSystem sys; - sys.update(); + ScriptSystem sys; + sys.update(); - // Trigger the events while `testListener` is in scope - EventManager::get_instance().trigger_event(key_press, 1); - EventManager::get_instance().trigger_event(click_event, 1); - } + // Trigger the events while `testListener` is in scope + EventManager::get_instance().trigger_event(key_press, 1); + EventManager::get_instance().trigger_event(click_event, + 1); + } // custom lambda event handler - EventHandler event_handler = [](const KeyPressEvent& e) { - std::cout << "lambda test" << std::endl; + EventHandler event_handler = [](const KeyPressEvent & e) { + std::cout << "lambda test" << std::endl; return false; }; - EventManager::get_instance().subscribe(std::move(event_handler),0); + EventManager::get_instance().subscribe( + std::move(event_handler), 0); // testing trigger with testListener not in scope (unsubscribed) - EventManager::get_instance().trigger_event(key_press, 0); - EventManager::get_instance().trigger_event(click_event, 0); + EventManager::get_instance().trigger_event(key_press, 0); + EventManager::get_instance().trigger_event(click_event, 0); // dispatching queued events EventManager::get_instance().dispatch_events(); - EventManager::get_instance().unsubscribe(event_handler,0); - return EXIT_SUCCESS; + EventManager::get_instance().unsubscribe(event_handler, 0); + return EXIT_SUCCESS; } - - -- cgit v1.2.3 From 9ce53b197953e66189febeaa434255b848647993 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Wed, 13 Nov 2024 15:40:52 +0100 Subject: make format --- src/crepe/api/Event.h | 4 +- src/crepe/api/EventManager.h | 1 - src/crepe/api/KeyCodes.h | 118 +++++++++++++++++++++---------------------- src/example/events.cpp | 16 +++--- 4 files changed, 69 insertions(+), 70 deletions(-) (limited to 'src/crepe/api/Event.h') diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h index 87c6068..cffa5da 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -1,8 +1,8 @@ #pragma once -#include +#include "KeyCodes.h" #include #include -#include "KeyCodes.h" +#include class Event { public: diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index 26539ce..e2665bd 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -254,4 +254,3 @@ void EventManager::unsubscribe(const EventHandler & callback, } } } - diff --git a/src/crepe/api/KeyCodes.h b/src/crepe/api/KeyCodes.h index 53be91b..1cb1a8a 100644 --- a/src/crepe/api/KeyCodes.h +++ b/src/crepe/api/KeyCodes.h @@ -1,25 +1,25 @@ #pragma once 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, + NONE = 0, + LEFT_MOUSE = 1, + RIGHT_MOUSE = 2, + MIDDLE_MOUSE = 3, + X1_MOUSE = 4, + X2_MOUSE = 5, + SCROLL_UP = 6, + SCROLL_DOWN = 7, }; -enum class Keycode : int{ +enum class Keycode : int { // From glfw3.h - None = 0, - Space = 32, - Apostrophe = 39, /* ' */ - Comma = 44, /* , */ - Minus = 45, /* - */ - Period = 46, /* . */ - Slash = 47, /* / */ + NONE = 0, + SPACE = 32, + APOSTROPHE = 39, /* ' */ + COMMA = 44, /* , */ + MINUS = 45, /* - */ + PERIOD = 46, /* . */ + SLASH = 47, /* / */ D0 = 48, /* 0 */ D1 = 49, /* 1 */ @@ -32,8 +32,8 @@ enum class Keycode : int{ D8 = 56, /* 8 */ D9 = 57, /* 9 */ - Semicolon = 59, /* ; */ - Equal = 61, /* = */ + SEMICOLON = 59, /* ; */ + EQUAL = 61, /* = */ A = 65, B = 66, @@ -62,34 +62,34 @@ enum class Keycode : int{ Y = 89, Z = 90, - LeftBracket = 91, /* [ */ - Backslash = 92, /* \ */ - RightBracket = 93, /* ] */ - GraveAccent = 96, /* ` */ + LEFT_BRACKET = 91, /* [ */ + BACKSLASH = 92, /* \ */ + RIGHT_BRACKET = 93, /* ] */ + GRAVE_ACCENT = 96, /* ` */ - World1 = 161, /* non-US #1 */ - World2 = 162, /* non-US #2 */ + 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, + ESCAPE = 256, + ENTER = 257, + TAB = 258, + BACKSPACE = 259, + INSERT = 260, + DELETE = 261, + RIGHT = 262, + LEFT = 263, + DOWN = 264, + UP = 265, + PAGE_UP = 266, + PAGE_DOWN = 267, + HOME = 268, + END = 269, + CAPS_LOCK = 280, + SCROLL_LOCK = 281, + NUM_LOCK = 282, + PRINT_SCREEN = 283, + PAUSE = 284, F1 = 290, F2 = 291, F3 = 292, @@ -127,21 +127,21 @@ enum class Keycode : int{ KP7 = 327, KP8 = 328, KP9 = 329, - KPDecimal = 330, - KPDivide = 331, - KPMultiply = 332, - KPSubtract = 333, - KPAdd = 334, - KPEnter = 335, - KPEqual = 336, + KP_DECIMAL = 330, + KP_DIVIDE = 331, + KP_MULTIPLY = 332, + KP_SUBTRACT = 333, + KP_ADD = 334, + KP_ENTER = 335, + KP_EQUAL = 336, - LeftShift = 340, - LeftControl = 341, - LeftAlt = 342, - LeftSuper = 343, - RightShift = 344, - RightControl = 345, - RightAlt = 346, - RightSuper = 347, - Menu = 348 + LEFT_SHIFT = 340, + LEFT_CONTROL = 341, + LEFT_ALT = 342, + LEFT_SUPER = 343, + RIGHT_SHIFT = 344, + RIGHT_CONTROL = 345, + RIGHT_ALT = 346, + RIGHT_SUPER = 347, + MENU = 348 }; diff --git a/src/example/events.cpp b/src/example/events.cpp index 210c42c..51c9a37 100644 --- a/src/example/events.cpp +++ b/src/example/events.cpp @@ -4,16 +4,16 @@ #include #include +#include +#include #include #include +#include #include #include -#include -#include -#include +#include #include #include -#include using namespace crepe; using namespace std; @@ -54,13 +54,13 @@ class MyScript : public Script, public IKeyListener, public IMouseListener { class TestKeyListener : public IKeyListener { public: bool on_key_pressed(const KeyPressEvent & event) override { - std::cout << "TestKeyListener: Key Pressed - Code: " << static_cast(event.key) - << std::endl; + std::cout << "TestKeyListener: Key Pressed - Code: " + << static_cast(event.key) << std::endl; return true; // Return true if the listener should remain active } bool on_key_released(const KeyReleaseEvent & event) override { - std::cout << "TestKeyListener: Key Released - Code: " << static_cast(event.key) - << std::endl; + std::cout << "TestKeyListener: Key Released - Code: " + << static_cast(event.key) << std::endl; return true; } }; -- cgit v1.2.3 From cab672ce6258aec563e7f0e0549281156c0c8d21 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Fri, 15 Nov 2024 12:43:38 +0100 Subject: feedback --- src/crepe/api/CMakeLists.txt | 14 ++++ src/crepe/api/Event.h | 13 ++-- src/crepe/api/EventHandler.h | 1 + src/crepe/api/EventManager.cpp | 3 + src/crepe/api/EventManager.h | 142 ++------------------------------------- src/crepe/api/EventManager.hpp | 140 ++++++++++++++++++++++++++++++++++++++ src/crepe/api/IKeyListener.cpp | 4 +- src/crepe/api/IMouseListener.cpp | 10 ++- src/crepe/api/KeyCodes.h | 1 - src/example/events.cpp | 10 ++- 10 files changed, 187 insertions(+), 151 deletions(-) create mode 100644 src/crepe/api/EventManager.hpp (limited to 'src/crepe/api/Event.h') diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 87cbb09..53b3041 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -18,6 +18,12 @@ target_sources(crepe PUBLIC Vector2.cpp Camera.cpp Animator.cpp + EventManager.cpp + EventHandler.cpp + IKeyListener.cpp + IMouseListener.cpp + LoopManager.cpp + LoopTimer.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -42,4 +48,12 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES SceneManager.hpp Camera.h Animator.h + EventManager.h + EventManager.hpp + EventHandler.h + Event.h + IKeyListener.h + IMouseListener.h + LoopManager.h + LoopTimer.h ) diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h index cffa5da..701ecdf 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -6,38 +6,37 @@ class Event { public: - bool handled = false; }; class KeyPressEvent : public Event { public: int repeat = 0; - Keycode key = Keycode::None; + Keycode key = Keycode::NONE; }; class KeyReleaseEvent : public Event { public: - Keycode key = Keycode::None; + Keycode key = Keycode::NONE; }; class MousePressEvent : public Event { public: int mouse_x = 0; int mouse_y = 0; - MouseButton button; + MouseButton button = MouseButton::NONE; }; class MouseClickEvent : public Event { public: int mouse_x = 0; int mouse_y = 0; - MouseButton button; + MouseButton button = MouseButton::NONE; }; class MouseReleaseEvent : public Event { public: int mouse_x = 0; int mouse_y = 0; - MouseButton button = MouseButton::None; + MouseButton button = MouseButton::NONE; }; class MouseMoveEvent : public Event { public: @@ -50,7 +49,7 @@ public: }; class TextSubmitEvent : public Event { public: - std::string text; + std::string text = ""; }; class ShutDownEvent : public Event { public: diff --git a/src/crepe/api/EventHandler.h b/src/crepe/api/EventHandler.h index 46c6c7b..0ab90de 100644 --- a/src/crepe/api/EventHandler.h +++ b/src/crepe/api/EventHandler.h @@ -12,6 +12,7 @@ * * \tparam EventType The type of event this handler will handle. */ +// TODO: typedef template using EventHandler = std::function; diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index 72cfd74..e881d49 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -1,5 +1,7 @@ #include "EventManager.h" +using namespace crepe; + EventManager & EventManager::get_instance() { static EventManager instance; return instance; @@ -62,6 +64,7 @@ void EventManager::dispatch_events() { iterator handler_it = handlers.begin(); handler_it != handlers.end(); ++handler_it) { + // remove event from queue since and continue when callback returns true if ((*handler_it)->exec(*event)) { event_it = this->events_queue.erase(event_it); event_handled = true; diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index e2665bd..38d2e64 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -10,6 +10,8 @@ #include "Event.h" #include "EventHandler.h" + +namespace crepe { /** * \class EventManager * \brief The EventManager class is responsible for managing the subscription, triggering, @@ -115,142 +117,6 @@ private: std::vector>>> subscribers_by_event_id; }; -template -void EventManager::subscribe(EventHandler && callback, int channel) { - std::type_index event_type = typeid(EventType); - std::unique_ptr> handler - = std::make_unique>(callback); - - if (channel) { - std::unordered_map>> & - handlers_map - = this->subscribers_by_event_id[event_type]; - std::unordered_map< - int, std::vector>>::iterator - 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 { - std::vector> & handlers - = this->subscribers[event_type]; - handlers.emplace_back(std::move(handler)); - } -} - -template -void EventManager::queue_event(EventType && event, int channel) { - std::type_index event_type = std::type_index(typeid(EventType)); - - std::unique_ptr event_ptr - = std::make_unique(std::forward(event)); - - std::tuple, int, std::type_index> tuple( - std::move(event_ptr), channel, event_type); - this->events_queue.push_back(std::move(tuple)); -} - -template -void EventManager::trigger_event(const EventType & event, int channel) { - std::type_index event_type = std::type_index(typeid(EventType)); - - if (channel > 0) { - std::unordered_map>> & - handlers_map - = this->subscribers_by_event_id[event_type]; - std::unordered_map< - int, std::vector>>::iterator - handlers_it - = handlers_map.find(channel); - - if (handlers_it != handlers_map.end()) { - std::vector> & handlers - = handlers_it->second; - for (std::vector>::iterator it - = handlers.begin(); - it != handlers.end();) { - // erases callback if callback function returns true - if ((*it)->exec(event)) { - it = handlers.erase(it); - } else { - ++it; - } - } - } - } else { - std::vector> & handlers - = this->subscribers[event_type]; - for (std::vector>::iterator it - = handlers.begin(); - it != handlers.end();) { - // erases callback if callback function returns true - if ((*it)->exec(event)) { - it = handlers.erase(it); - } else { - ++it; - } - } - } -} - -template -void EventManager::unsubscribe(const EventHandler & callback, - int channel) { - std::type_index event_type(typeid(EventType)); - std::string handler_name = callback.target_type().name(); - if (channel) { - std::unordered_map< - std::type_index, - std::unordered_map< - int, std::vector>>>:: - iterator subscriber_list - = this->subscribers_by_event_id.find(event_type); - if (subscriber_list != this->subscribers_by_event_id.end()) { - std::unordered_map< - int, std::vector>> & - handlers_map - = subscriber_list->second; - std::unordered_map< - int, - std::vector>>::iterator - handlers - = handlers_map.find(channel); - if (handlers != handlers_map.end()) { - std::vector> & callbacks - = handlers->second; - for (std::vector< - std::unique_ptr>::iterator it - = callbacks.begin(); - it != callbacks.end(); ++it) { - if ((*it)->get_type() == handler_name) { - it = callbacks.erase(it); - return; - } - } - } - } - } else { - std::unordered_map>>:: - iterator handlers_it - = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - std::vector> & handlers - = handlers_it->second; - for (std::vector>::iterator it - = handlers.begin(); - it != handlers.end(); ++it) { - if ((*it)->get_type() == handler_name) { - it = handlers.erase(it); - return; - } - } - } - } -} +} // namespace crepe +#include "EventManager.hpp" diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp new file mode 100644 index 0000000..b509097 --- /dev/null +++ b/src/crepe/api/EventManager.hpp @@ -0,0 +1,140 @@ +#include "EventManager.h" +namespace crepe { + +template +void EventManager::subscribe(EventHandler && callback, int channel) { + std::type_index event_type = typeid(EventType); + std::unique_ptr> handler + = std::make_unique>(callback); + + if (channel) { + std::unordered_map>> & + handlers_map + = this->subscribers_by_event_id[event_type]; + std::unordered_map< + int, std::vector>>::iterator + 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 { + std::vector> & handlers + = this->subscribers[event_type]; + handlers.emplace_back(std::move(handler)); + } +} + +template +void EventManager::queue_event(EventType && event, int channel) { + std::type_index event_type = std::type_index(typeid(EventType)); + + std::unique_ptr event_ptr + = std::make_unique(std::forward(event)); + + std::tuple, int, std::type_index> tuple( + std::move(event_ptr), channel, event_type); + this->events_queue.push_back(std::move(tuple)); +} + +template +void EventManager::trigger_event(const EventType & event, int channel) { + std::type_index event_type = std::type_index(typeid(EventType)); + + if (channel > 0) { + std::unordered_map>> & + handlers_map + = this->subscribers_by_event_id[event_type]; + std::unordered_map< + int, std::vector>>::iterator + handlers_it + = handlers_map.find(channel); + + if (handlers_it != handlers_map.end()) { + std::vector> & handlers + = handlers_it->second; + for (std::vector>::iterator it + = handlers.begin(); + it != handlers.end();++it) { + // stops when callback returns true + if((*it)->exec(event)){ + break; + } + } + } + } else { + std::vector> & handlers + = this->subscribers[event_type]; + for (std::vector>::iterator it + = handlers.begin(); + it != handlers.end();++it) { + // stops when callback returns true + if((*it)->exec(event)){ + break; + } + } + } +} + +template +void EventManager::unsubscribe(const EventHandler & callback, + int channel) { + std::type_index event_type(typeid(EventType)); + std::string handler_name = callback.target_type().name(); + + if (channel) { + std::unordered_map< + std::type_index, + std::unordered_map< + int, std::vector>>>:: + iterator subscriber_list + = this->subscribers_by_event_id.find(event_type); + if (subscriber_list != this->subscribers_by_event_id.end()) { + std::unordered_map< + int, std::vector>> & + handlers_map + = subscriber_list->second; + std::unordered_map< + int, + std::vector>>::iterator + handlers + = handlers_map.find(channel); + if (handlers != handlers_map.end()) { + std::vector> & callbacks + = handlers->second; + for (std::vector< + std::unique_ptr>::iterator it + = callbacks.begin(); + it != callbacks.end(); ++it) { + if ((*it)->get_type() == handler_name) { + it = callbacks.erase(it); + return; + } + } + } + } + } else { + std::unordered_map>>:: + iterator handlers_it + = this->subscribers.find(event_type); + if (handlers_it != this->subscribers.end()) { + std::vector> & handlers + = handlers_it->second; + for (std::vector>::iterator it + = handlers.begin(); + it != handlers.end(); ++it) { + if ((*it)->get_type() == handler_name) { + it = handlers.erase(it); + return; + } + } + } + } +} + +} diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index eb8f9af..4fd9855 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -1,5 +1,7 @@ #include "IKeyListener.h" -#include + +using namespace crepe; + IKeyListener::IKeyListener() { this->channel = channel; this->subscribe_events(); diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index 683632c..489e55b 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -1,6 +1,11 @@ #include "IMouseListener.h" + +using namespace crepe; + IMouseListener::IMouseListener(int channel) { this->channel = channel; } + IMouseListener::IMouseListener() { this->subscribe_events(); } + IMouseListener::~IMouseListener() { this->unsubscribe_events(); } void IMouseListener::subscribe_events() { @@ -26,7 +31,7 @@ void IMouseListener::subscribe_events() { EventManager::get_instance().subscribe( std::move(this->mouse_move_handler), this->channel); } - +// TODO: reference voor singleton void IMouseListener::unsubscribe_events() { EventManager::get_instance().unsubscribe( this->mouse_click_handler, this->channel); @@ -37,18 +42,21 @@ void IMouseListener::unsubscribe_events() { EventManager::get_instance().unsubscribe( this->mouse_move_handler, this->channel); } + void IMouseListener::activate_mouse() { if (this->active) { return; } this->subscribe_events(); } + void IMouseListener::deactivate_mouse() { if (!this->active) { return; } this->unsubscribe_events(); } + void IMouseListener::set_channel(int channel) { this->unsubscribe_events(); this->channel = channel; diff --git a/src/crepe/api/KeyCodes.h b/src/crepe/api/KeyCodes.h index 1cb1a8a..e5a91fc 100644 --- a/src/crepe/api/KeyCodes.h +++ b/src/crepe/api/KeyCodes.h @@ -12,7 +12,6 @@ enum class MouseButton { }; enum class Keycode : int { - // From glfw3.h NONE = 0, SPACE = 32, APOSTROPHE = 39, /* ' */ diff --git a/src/example/events.cpp b/src/example/events.cpp index 51c9a37..9c59bb7 100644 --- a/src/example/events.cpp +++ b/src/example/events.cpp @@ -70,7 +70,7 @@ int main() { key_press.key = Keycode::A; key_press.repeat = 0; MouseClickEvent click_event; - click_event.button = MouseButton::Left_Mouse; + click_event.button = MouseButton::LEFT_MOUSE; click_event.mouse_x = 100; click_event.mouse_y = 200; // queue events to test queue @@ -89,8 +89,12 @@ int main() { // Trigger the events while `testListener` is in scope EventManager::get_instance().trigger_event(key_press, 1); - EventManager::get_instance().trigger_event(click_event, - 1); + // EventManager::get_instance().trigger_event(MouseClickEvent{ + // .button = MouseButton::LEFT_MOUSE, + // .mouse_y = 100, + // .mouse_x = 100, + + // },1); } // custom lambda event handler EventHandler event_handler = [](const KeyPressEvent & e) { -- cgit v1.2.3 From 6e7003c73110cf9ad7e4c72de703dfdc2292d8ca Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Sat, 16 Nov 2024 13:55:47 +0100 Subject: added hpp files and auto --- src/crepe/api/CMakeLists.txt | 3 +- src/crepe/api/Event.h | 94 ++++++++++++++++++++++++++++++++++-------- src/crepe/api/EventHandler.cpp | 8 +++- src/crepe/api/EventHandler.h | 53 +++++++++++++----------- src/crepe/api/EventHandler.hpp | 25 +++++++++++ src/crepe/api/EventManager.hpp | 42 +++++-------------- src/crepe/api/IKeyListener.h | 3 ++ src/crepe/api/IMouseListener.h | 3 ++ 8 files changed, 155 insertions(+), 76 deletions(-) create mode 100644 src/crepe/api/EventHandler.hpp (limited to 'src/crepe/api/Event.h') diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 53b3041..edf4250 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -19,11 +19,11 @@ target_sources(crepe PUBLIC Camera.cpp Animator.cpp EventManager.cpp - EventHandler.cpp IKeyListener.cpp IMouseListener.cpp LoopManager.cpp LoopTimer.cpp + EventHandler.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -51,6 +51,7 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES EventManager.h EventManager.hpp EventHandler.h + EventHandler.hpp Event.h IKeyListener.h IMouseListener.h diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h index 701ecdf..e7cac25 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -1,56 +1,116 @@ #pragma once -#include "KeyCodes.h" + #include #include #include +#include "KeyCodes.h" +/** + * \brief Base class for all event types in the system. + */ class Event { public: }; +/** + * \brief Event triggered when a key is pressed. + */ class KeyPressEvent : public Event { public: - int repeat = 0; - Keycode key = Keycode::NONE; + //! Number of times the key press is repeated (e.g., for long presses). + int repeat = 0; + + //! The key that was pressed. + Keycode key = Keycode::NONE; }; +/** + * \brief Event triggered when a key is released. + */ class KeyReleaseEvent : public Event { public: - Keycode key = Keycode::NONE; + //! The key that was released. + Keycode key = Keycode::NONE; }; +/** + * \brief Event triggered when a mouse button is pressed. + */ class MousePressEvent : public Event { public: - int mouse_x = 0; - int mouse_y = 0; - MouseButton button = MouseButton::NONE; + //! X-coordinate of the mouse position at the time of the event. + int mouse_x = 0; + + //! Y-coordinate of the mouse position at the time of the event. + int mouse_y = 0; + + //! The mouse button that was pressed. + MouseButton button = MouseButton::NONE; }; +/** + * \brief Event triggered when a mouse button is clicked (press and release). + */ class MouseClickEvent : public Event { public: - int mouse_x = 0; - int mouse_y = 0; - MouseButton button = MouseButton::NONE; + //! X-coordinate of the mouse position at the time of the event. + int mouse_x = 0; + + //! Y-coordinate of the mouse position at the time of the event. + int mouse_y = 0; + + //! The mouse button that was clicked. + MouseButton button = MouseButton::NONE; }; + +/** + * \brief Event triggered when a mouse button is released. + */ class MouseReleaseEvent : public Event { public: - int mouse_x = 0; - int mouse_y = 0; - MouseButton button = MouseButton::NONE; + //! X-coordinate of the mouse position at the time of the event. + int mouse_x = 0; + + //! Y-coordinate of the mouse position at the time of the event. + int mouse_y = 0; + + //! The mouse button that was released. + MouseButton button = MouseButton::NONE; }; + +/** + * \brief Event triggered when the mouse is moved. + */ class MouseMoveEvent : public Event { public: - int mouse_x = 0; - int mouse_y = 0; + //! X-coordinate of the mouse position at the time of the event. + int mouse_x = 0; + + //! Y-coordinate of the mouse position at the time of the event. + int mouse_y = 0; }; + +/** + * \brief Event triggered during a collision between objects. + */ class CollisionEvent : public Event { public: - //Collision collisionData; + //! Data describing the collision (currently not implemented). + // Collision collisionData; }; + +/** + * \brief Event triggered when text is submitted, e.g., from a text input. + */ class TextSubmitEvent : public Event { public: - std::string text = ""; + //! The submitted text. + std::string text = ""; }; + +/** + * \brief Event triggered to indicate the application is shutting down. + */ class ShutDownEvent : public Event { public: }; diff --git a/src/crepe/api/EventHandler.cpp b/src/crepe/api/EventHandler.cpp index 93a116a..d90d765 100644 --- a/src/crepe/api/EventHandler.cpp +++ b/src/crepe/api/EventHandler.cpp @@ -1,2 +1,8 @@ #include "EventHandler.h" -bool IEventHandlerWrapper::exec(const Event & e) { return call(e); } + +using namespace crepe; + +// Implementation of IEventHandlerWrapper::exec +bool IEventHandlerWrapper::exec(const Event & e) { + return call(e); +} diff --git a/src/crepe/api/EventHandler.h b/src/crepe/api/EventHandler.h index 0ab90de..2a684c0 100644 --- a/src/crepe/api/EventHandler.h +++ b/src/crepe/api/EventHandler.h @@ -1,9 +1,11 @@ #pragma once -#include "Event.h" + #include -#include -#include +#include + +#include "Event.h" +namespace crepe { /** * \brief A type alias for an event handler function. * @@ -12,7 +14,6 @@ * * \tparam EventType The type of event this handler will handle. */ -// TODO: typedef template using EventHandler = std::function; @@ -25,12 +26,12 @@ using EventHandler = std::function; */ class IEventHandlerWrapper { public: - /** + /** * \brief Virtual destructor for IEventHandlerWrapper. */ - virtual ~IEventHandlerWrapper() = default; + virtual ~IEventHandlerWrapper() = default; - /** + /** * \brief Executes the handler with the given event. * * This method calls the `call()` method of the derived class, passing the event to the handler. @@ -38,19 +39,19 @@ public: * \param e The event to be processed. * \return A boolean value indicating whether the event is handled. */ - bool exec(const Event & e); + bool exec(const Event & e); - /** + /** * \brief Get the type of the event handler. * * This method returns the type of the event handler as a string. * * \return A string representing the handler's type. */ - virtual std::string get_type() const = 0; + virtual std::string get_type() const = 0; private: - /** + /** * \brief The method responsible for handling the event. * * This method is implemented by derived classes to process the event. @@ -58,7 +59,7 @@ private: * \param e The event to be processed. * \return A boolean value indicating whether the event is handled. */ - virtual bool call(const Event & e) = 0; + virtual bool call(const Event & e) = 0; }; /** @@ -74,18 +75,17 @@ private: template class EventHandlerWrapper : public IEventHandlerWrapper { public: - /** + /** * \brief Constructs an EventHandlerWrapper with a given handler. * * The constructor takes an event handler function and stores it in the wrapper. * * \param handler The event handler function. */ - explicit EventHandlerWrapper(const EventHandler & handler) - : m_handler(handler), m_handler_type(m_handler.target_type().name()) {} + explicit EventHandlerWrapper(const EventHandler & handler); private: - /** + /** * \brief Calls the stored event handler with the event. * * This method casts the event to the appropriate type and calls the handler. @@ -93,20 +93,23 @@ private: * \param e The event to be handled. * \return A boolean value indicating whether the event is handled. */ - bool call(const Event & e) override { - return m_handler(static_cast(e)); - } + bool call(const Event & e) override; - /** + /** * \brief Returns the type of the handler. * * This method returns a string representing the type of the event handler. * * \return The handler type as a string. */ - std::string get_type() const override { return m_handler_type; } - //! The event handler function. - EventHandler m_handler; - //! The type name of the handler function. - const std::string m_handler_type; + std::string get_type() const override; + + //! The event handler function. + EventHandler m_handler; + //! The type name of the handler function. + const std::string m_handler_type; }; + +} // namespace crepe + +#include "EventHandler.hpp" diff --git a/src/crepe/api/EventHandler.hpp b/src/crepe/api/EventHandler.hpp new file mode 100644 index 0000000..1b5702e --- /dev/null +++ b/src/crepe/api/EventHandler.hpp @@ -0,0 +1,25 @@ + +#include + +#include "EventHandler.h" + +namespace crepe { + +// Implementation of EventHandlerWrapper constructor +template +EventHandlerWrapper::EventHandlerWrapper(const EventHandler & handler) + : m_handler(handler), m_handler_type(m_handler.target_type().name()) {} + +// Implementation of EventHandlerWrapper::call +template +bool EventHandlerWrapper::call(const Event & e) { + return m_handler(static_cast(e)); +} + +// Implementation of EventHandlerWrapper::get_type +template +std::string EventHandlerWrapper::get_type() const { + return m_handler_type; +} + +} //namespace crepe diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp index b509097..70f0a31 100644 --- a/src/crepe/api/EventManager.hpp +++ b/src/crepe/api/EventManager.hpp @@ -12,10 +12,7 @@ void EventManager::subscribe(EventHandler && callback, int channel) { std::vector>> & handlers_map = this->subscribers_by_event_id[event_type]; - std::unordered_map< - int, std::vector>>::iterator - handlers - = handlers_map.find(channel); + auto handlers = handlers_map.find(channel); if (handlers != handlers_map.end()) { handlers->second.emplace_back(std::move(handler)); } else { @@ -49,16 +46,12 @@ void EventManager::trigger_event(const EventType & event, int channel) { std::vector>> & handlers_map = this->subscribers_by_event_id[event_type]; - std::unordered_map< - int, std::vector>>::iterator - handlers_it - = handlers_map.find(channel); + auto handlers_it = handlers_map.find(channel); if (handlers_it != handlers_map.end()) { std::vector> & handlers = handlers_it->second; - for (std::vector>::iterator it - = handlers.begin(); + for (auto it = handlers.begin(); it != handlers.end();++it) { // stops when callback returns true if((*it)->exec(event)){ @@ -69,7 +62,7 @@ void EventManager::trigger_event(const EventType & event, int channel) { } else { std::vector> & handlers = this->subscribers[event_type]; - for (std::vector>::iterator it + for (auto it = handlers.begin(); it != handlers.end();++it) { // stops when callback returns true @@ -87,28 +80,17 @@ void EventManager::unsubscribe(const EventHandler & callback, std::string handler_name = callback.target_type().name(); if (channel) { - std::unordered_map< - std::type_index, - std::unordered_map< - int, std::vector>>>:: - iterator subscriber_list - = this->subscribers_by_event_id.find(event_type); + auto subscriber_list = this->subscribers_by_event_id.find(event_type); if (subscriber_list != this->subscribers_by_event_id.end()) { std::unordered_map< int, std::vector>> & handlers_map = subscriber_list->second; - std::unordered_map< - int, - std::vector>>::iterator - handlers - = handlers_map.find(channel); + auto handlers = handlers_map.find(channel); if (handlers != handlers_map.end()) { std::vector> & callbacks = handlers->second; - for (std::vector< - std::unique_ptr>::iterator it - = callbacks.begin(); + for (auto it = callbacks.begin(); it != callbacks.end(); ++it) { if ((*it)->get_type() == handler_name) { it = callbacks.erase(it); @@ -118,15 +100,11 @@ void EventManager::unsubscribe(const EventHandler & callback, } } } else { - std::unordered_map>>:: - iterator handlers_it - = this->subscribers.find(event_type); + auto handlers_it = this->subscribers.find(event_type); if (handlers_it != this->subscribers.end()) { std::vector> & handlers = handlers_it->second; - for (std::vector>::iterator it - = handlers.begin(); + for (auto it = handlers.begin(); it != handlers.end(); ++it) { if ((*it)->get_type() == handler_name) { it = handlers.erase(it); @@ -137,4 +115,4 @@ void EventManager::unsubscribe(const EventHandler & callback, } } -} +} // namespace crepe diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index 839acbf..5a2cafa 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -3,6 +3,7 @@ #include "EventHandler.h" #include "EventManager.h" +namespace crepe { /** * \class IKeyListener * \brief Interface for keyboard event handling in the application. @@ -76,3 +77,5 @@ private: //!< Key release event handler. EventHandler key_released_handler; }; + +} // namespace crepe diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 7e92956..1df55af 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -4,6 +4,7 @@ #include "EventHandler.h" #include "EventManager.h" +namespace crepe { /** * \class IMouseListener * \brief Interface for mouse event handling in the application. @@ -115,3 +116,5 @@ private: //! Mouse move event handler. EventHandler mouse_move_handler; }; + +} //namespace crepe -- cgit v1.2.3 From 027e67b32a9cca3cac4a186e73fdcc42faeab8c4 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Sat, 16 Nov 2024 15:21:49 +0100 Subject: added eventManager reference to interfaces --- src/crepe/api/Event.h | 67 ++++----- src/crepe/api/EventHandler.cpp | 4 +- src/crepe/api/EventHandler.h | 36 ++--- src/crepe/api/EventHandler.hpp | 10 +- src/crepe/api/EventManager.cpp | 49 ++---- src/crepe/api/EventManager.h | 12 +- src/crepe/api/EventManager.hpp | 69 ++++----- src/crepe/api/IKeyListener.cpp | 81 ++++++---- src/crepe/api/IKeyListener.h | 3 + src/crepe/api/IMouseListener.cpp | 45 +++--- src/crepe/api/IMouseListener.h | 2 + src/crepe/api/KeyCodes.h | 318 ++++++++++++++++++++++----------------- src/example/events.cpp | 12 +- 13 files changed, 365 insertions(+), 343 deletions(-) (limited to 'src/crepe/api/Event.h') diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h index e7cac25..d5ddf0a 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -1,10 +1,9 @@ #pragma once -#include #include -#include #include "KeyCodes.h" + /** * \brief Base class for all event types in the system. */ @@ -17,11 +16,11 @@ public: */ class KeyPressEvent : public Event { public: - //! Number of times the key press is repeated (e.g., for long presses). - int repeat = 0; + //! Number of times the key press is repeated (e.g., for long presses). + int repeat = 0; - //! The key that was pressed. - Keycode key = Keycode::NONE; + //! The key that was pressed. + Keycode key = Keycode::NONE; }; /** @@ -29,8 +28,8 @@ public: */ class KeyReleaseEvent : public Event { public: - //! The key that was released. - Keycode key = Keycode::NONE; + //! The key that was released. + Keycode key = Keycode::NONE; }; /** @@ -38,14 +37,14 @@ public: */ class MousePressEvent : public Event { public: - //! X-coordinate of the mouse position at the time of the event. - int mouse_x = 0; + //! X-coordinate of the mouse position at the time of the event. + int mouse_x = 0; - //! Y-coordinate of the mouse position at the time of the event. - int mouse_y = 0; + //! Y-coordinate of the mouse position at the time of the event. + int mouse_y = 0; - //! The mouse button that was pressed. - MouseButton button = MouseButton::NONE; + //! The mouse button that was pressed. + MouseButton button = MouseButton::NONE; }; /** @@ -53,14 +52,14 @@ public: */ class MouseClickEvent : public Event { public: - //! X-coordinate of the mouse position at the time of the event. - int mouse_x = 0; + //! X-coordinate of the mouse position at the time of the event. + int mouse_x = 0; - //! Y-coordinate of the mouse position at the time of the event. - int mouse_y = 0; + //! Y-coordinate of the mouse position at the time of the event. + int mouse_y = 0; - //! The mouse button that was clicked. - MouseButton button = MouseButton::NONE; + //! The mouse button that was clicked. + MouseButton button = MouseButton::NONE; }; /** @@ -68,14 +67,14 @@ public: */ class MouseReleaseEvent : public Event { public: - //! X-coordinate of the mouse position at the time of the event. - int mouse_x = 0; + //! X-coordinate of the mouse position at the time of the event. + int mouse_x = 0; - //! Y-coordinate of the mouse position at the time of the event. - int mouse_y = 0; + //! Y-coordinate of the mouse position at the time of the event. + int mouse_y = 0; - //! The mouse button that was released. - MouseButton button = MouseButton::NONE; + //! The mouse button that was released. + MouseButton button = MouseButton::NONE; }; /** @@ -83,11 +82,11 @@ public: */ class MouseMoveEvent : public Event { public: - //! X-coordinate of the mouse position at the time of the event. - int mouse_x = 0; + //! X-coordinate of the mouse position at the time of the event. + int mouse_x = 0; - //! Y-coordinate of the mouse position at the time of the event. - int mouse_y = 0; + //! Y-coordinate of the mouse position at the time of the event. + int mouse_y = 0; }; /** @@ -95,8 +94,8 @@ public: */ class CollisionEvent : public Event { public: - //! Data describing the collision (currently not implemented). - // Collision collisionData; + //! Data describing the collision (currently not implemented). + // Collision collisionData; }; /** @@ -104,8 +103,8 @@ public: */ class TextSubmitEvent : public Event { public: - //! The submitted text. - std::string text = ""; + //! The submitted text. + std::string text = ""; }; /** diff --git a/src/crepe/api/EventHandler.cpp b/src/crepe/api/EventHandler.cpp index d90d765..186ec9c 100644 --- a/src/crepe/api/EventHandler.cpp +++ b/src/crepe/api/EventHandler.cpp @@ -3,6 +3,4 @@ using namespace crepe; // Implementation of IEventHandlerWrapper::exec -bool IEventHandlerWrapper::exec(const Event & e) { - return call(e); -} +bool IEventHandlerWrapper::exec(const Event & e) { return call(e); } diff --git a/src/crepe/api/EventHandler.h b/src/crepe/api/EventHandler.h index 2a684c0..db51d04 100644 --- a/src/crepe/api/EventHandler.h +++ b/src/crepe/api/EventHandler.h @@ -26,12 +26,12 @@ using EventHandler = std::function; */ class IEventHandlerWrapper { public: - /** + /** * \brief Virtual destructor for IEventHandlerWrapper. */ - virtual ~IEventHandlerWrapper() = default; + virtual ~IEventHandlerWrapper() = default; - /** + /** * \brief Executes the handler with the given event. * * This method calls the `call()` method of the derived class, passing the event to the handler. @@ -39,19 +39,19 @@ public: * \param e The event to be processed. * \return A boolean value indicating whether the event is handled. */ - bool exec(const Event & e); + bool exec(const Event & e); - /** + /** * \brief Get the type of the event handler. * * This method returns the type of the event handler as a string. * * \return A string representing the handler's type. */ - virtual std::string get_type() const = 0; + virtual std::string get_type() const = 0; private: - /** + /** * \brief The method responsible for handling the event. * * This method is implemented by derived classes to process the event. @@ -59,7 +59,7 @@ private: * \param e The event to be processed. * \return A boolean value indicating whether the event is handled. */ - virtual bool call(const Event & e) = 0; + virtual bool call(const Event & e) = 0; }; /** @@ -75,17 +75,17 @@ private: template class EventHandlerWrapper : public IEventHandlerWrapper { public: - /** + /** * \brief Constructs an EventHandlerWrapper with a given handler. * * The constructor takes an event handler function and stores it in the wrapper. * * \param handler The event handler function. */ - explicit EventHandlerWrapper(const EventHandler & handler); + explicit EventHandlerWrapper(const EventHandler & handler); private: - /** + /** * \brief Calls the stored event handler with the event. * * This method casts the event to the appropriate type and calls the handler. @@ -93,21 +93,21 @@ private: * \param e The event to be handled. * \return A boolean value indicating whether the event is handled. */ - bool call(const Event & e) override; + bool call(const Event & e) override; - /** + /** * \brief Returns the type of the handler. * * This method returns a string representing the type of the event handler. * * \return The handler type as a string. */ - std::string get_type() const override; + std::string get_type() const override; - //! The event handler function. - EventHandler m_handler; - //! The type name of the handler function. - const std::string m_handler_type; + //! The event handler function. + EventHandler m_handler; + //! The type name of the handler function. + const std::string m_handler_type; }; } // namespace crepe diff --git a/src/crepe/api/EventHandler.hpp b/src/crepe/api/EventHandler.hpp index 1b5702e..564d3d7 100644 --- a/src/crepe/api/EventHandler.hpp +++ b/src/crepe/api/EventHandler.hpp @@ -7,19 +7,21 @@ namespace crepe { // Implementation of EventHandlerWrapper constructor template -EventHandlerWrapper::EventHandlerWrapper(const EventHandler & handler) - : m_handler(handler), m_handler_type(m_handler.target_type().name()) {} +EventHandlerWrapper::EventHandlerWrapper( + const EventHandler & handler) + : m_handler(handler), + m_handler_type(m_handler.target_type().name()) {} // Implementation of EventHandlerWrapper::call template bool EventHandlerWrapper::call(const Event & e) { - return m_handler(static_cast(e)); + return m_handler(static_cast(e)); } // Implementation of EventHandlerWrapper::get_type template std::string EventHandlerWrapper::get_type() const { - return m_handler_type; + return m_handler_type; } } //namespace crepe diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index e881d49..a04f08b 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -8,10 +8,10 @@ EventManager & EventManager::get_instance() { } void EventManager::dispatch_events() { - for (std::vector, int, - std::type_index>>::iterator event_it - = this->events_queue.begin(); - event_it != this->events_queue.end();) { + using HandlersMap = std::unordered_map>>; + using HandlersVec = std::vector>; + + for (auto event_it = this->events_queue.begin(); event_it != this->events_queue.end();) { std::unique_ptr & event = std::get<0>(*event_it); int channel = std::get<1>(*event_it); std::type_index event_type = std::get<2>(*event_it); @@ -19,29 +19,13 @@ void EventManager::dispatch_events() { bool event_handled = false; if (channel) { - std::unordered_map< - std::type_index, - std::unordered_map< - int, std::vector>>>:: - iterator handlers_it - = subscribers_by_event_id.find(event_type); + auto handlers_it = subscribers_by_event_id.find(event_type); if (handlers_it != subscribers_by_event_id.end()) { - std::unordered_map< - int, std::vector>> & - handlers_map - = handlers_it->second; - std::unordered_map< - int, std::vector>>:: - iterator handlers - = handlers_map.find(channel); + HandlersMap & handlers_map = handlers_it->second; + auto handlers = handlers_map.find(channel); if (handlers != handlers_map.end()) { - std::vector> & - callbacks - = handlers->second; - for (std::vector>:: - iterator handler_it - = callbacks.begin(); - handler_it != callbacks.end(); ++handler_it) { + HandlersVec & callbacks = handlers->second; + for (auto handler_it = callbacks.begin(); handler_it != callbacks.end(); ++handler_it) { if ((*handler_it)->exec(*event)) { event_it = events_queue.erase(event_it); event_handled = true; @@ -52,18 +36,10 @@ void EventManager::dispatch_events() { } } else { // Handle event for all channels - std::unordered_map< - std::type_index, - std::vector>>::iterator - handlers_it - = this->subscribers.find(event_type); + auto handlers_it = this->subscribers.find(event_type); if (handlers_it != this->subscribers.end()) { - std::vector> & handlers - = handlers_it->second; - for (std::vector>:: - iterator handler_it - = handlers.begin(); - handler_it != handlers.end(); ++handler_it) { + HandlersVec & handlers = handlers_it->second; + for (auto handler_it = handlers.begin(); handler_it != handlers.end(); ++handler_it) { // remove event from queue since and continue when callback returns true if ((*handler_it)->exec(*event)) { event_it = this->events_queue.erase(event_it); @@ -79,3 +55,4 @@ void EventManager::dispatch_events() { } } } + diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index 38d2e64..1ff4031 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -10,8 +10,8 @@ #include "Event.h" #include "EventHandler.h" - namespace crepe { + /** * \class EventManager * \brief The EventManager class is responsible for managing the subscription, triggering, @@ -19,16 +19,6 @@ namespace crepe { */ class EventManager { public: - /** - * \brief Deleted copy constructor to prevent copying of the EventManager instance. - */ - EventManager(const EventManager &) = delete; - - /** - * \brief Deleted copy assignment operator to prevent assignment of the EventManager instance. - */ - const EventManager & operator=(const EventManager &) = delete; - /** * \brief Get the singleton instance of the EventManager. * diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp index 70f0a31..1e505f4 100644 --- a/src/crepe/api/EventManager.hpp +++ b/src/crepe/api/EventManager.hpp @@ -1,17 +1,18 @@ #include "EventManager.h" + namespace crepe { template void EventManager::subscribe(EventHandler && callback, int channel) { + using HandlersMap = std::unordered_map>>; + using HandlersVec = std::vector>; + std::type_index event_type = typeid(EventType); std::unique_ptr> handler = std::make_unique>(callback); if (channel) { - std::unordered_map>> & - handlers_map - = this->subscribers_by_event_id[event_type]; + HandlersMap & handlers_map = this->subscribers_by_event_id[event_type]; auto handlers = handlers_map.find(channel); if (handlers != handlers_map.end()) { handlers->second.emplace_back(std::move(handler)); @@ -19,8 +20,7 @@ void EventManager::subscribe(EventHandler && callback, int channel) { handlers_map[channel].emplace_back(std::move(handler)); } } else { - std::vector> & handlers - = this->subscribers[event_type]; + HandlersVec & handlers = this->subscribers[event_type]; handlers.emplace_back(std::move(handler)); } } @@ -29,8 +29,7 @@ template void EventManager::queue_event(EventType && event, int channel) { std::type_index event_type = std::type_index(typeid(EventType)); - std::unique_ptr event_ptr - = std::make_unique(std::forward(event)); + auto event_ptr = std::make_unique(std::forward(event)); std::tuple, int, std::type_index> tuple( std::move(event_ptr), channel, event_type); @@ -39,59 +38,51 @@ void EventManager::queue_event(EventType && event, int channel) { template void EventManager::trigger_event(const EventType & event, int channel) { + using HandlersMap = std::unordered_map>>; + using HandlersVec = std::vector>; + std::type_index event_type = std::type_index(typeid(EventType)); if (channel > 0) { - std::unordered_map>> & - handlers_map - = this->subscribers_by_event_id[event_type]; + HandlersMap & handlers_map = this->subscribers_by_event_id[event_type]; auto handlers_it = handlers_map.find(channel); if (handlers_it != handlers_map.end()) { - std::vector> & handlers - = handlers_it->second; - for (auto it = handlers.begin(); - it != handlers.end();++it) { + HandlersVec & handlers = handlers_it->second; + for (auto it = handlers.begin(); it != handlers.end(); ++it) { // stops when callback returns true - if((*it)->exec(event)){ + if ((*it)->exec(event)) { break; } } } } else { - std::vector> & handlers - = this->subscribers[event_type]; - for (auto it - = handlers.begin(); - it != handlers.end();++it) { + HandlersVec & handlers = this->subscribers[event_type]; + for (auto it = handlers.begin(); it != handlers.end(); ++it) { // stops when callback returns true - if((*it)->exec(event)){ - break; - } + if ((*it)->exec(event)) { + break; + } } } } template -void EventManager::unsubscribe(const EventHandler & callback, - int channel) { +void EventManager::unsubscribe(const EventHandler & callback, int channel) { + using HandlersMap = std::unordered_map>>; + using HandlersVec = std::vector>; + std::type_index event_type(typeid(EventType)); std::string handler_name = callback.target_type().name(); if (channel) { auto subscriber_list = this->subscribers_by_event_id.find(event_type); if (subscriber_list != this->subscribers_by_event_id.end()) { - std::unordered_map< - int, std::vector>> & - handlers_map - = subscriber_list->second; - auto handlers = handlers_map.find(channel); + HandlersMap & handlers_map = subscriber_list->second; + auto handlers = handlers_map.find(channel); if (handlers != handlers_map.end()) { - std::vector> & callbacks - = handlers->second; - for (auto it = callbacks.begin(); - it != callbacks.end(); ++it) { + HandlersVec & callbacks = handlers->second; + for (auto it = callbacks.begin(); it != callbacks.end(); ++it) { if ((*it)->get_type() == handler_name) { it = callbacks.erase(it); return; @@ -102,10 +93,8 @@ void EventManager::unsubscribe(const EventHandler & callback, } else { auto handlers_it = this->subscribers.find(event_type); if (handlers_it != this->subscribers.end()) { - std::vector> & handlers - = handlers_it->second; - for (auto it = handlers.begin(); - it != handlers.end(); ++it) { + HandlersVec & handlers = handlers_it->second; + for (auto it = handlers.begin(); it != handlers.end(); ++it) { if ((*it)->get_type() == handler_name) { it = handlers.erase(it); return; diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index 4fd9855..81d30b8 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -2,50 +2,65 @@ using namespace crepe; -IKeyListener::IKeyListener() { - this->channel = channel; - this->subscribe_events(); +// Constructor with default channel +IKeyListener::IKeyListener() : channel(0), active(true), event_manager(EventManager::get_instance()) { + this->subscribe_events(); } -IKeyListener::IKeyListener(int channel) { - this->channel = channel; - this->subscribe_events(); + +// Constructor with specified channel +IKeyListener::IKeyListener(int channel) : channel(channel), active(true), event_manager(EventManager::get_instance()) { + this->subscribe_events(); +} + +// Destructor, unsubscribe events +IKeyListener::~IKeyListener() { + this->unsubscribe_events(); } -IKeyListener::~IKeyListener() { this->unsubscribe_events(); } +// Subscribe to key events void IKeyListener::subscribe_events() { - key_pressed_handler = [this](const KeyPressEvent & event) { - return this->on_key_pressed(event); - }; - key_released_handler = [this](const KeyReleaseEvent & event) { - return this->on_key_released(event); - }; - EventManager::get_instance().subscribe( - std::move(this->key_pressed_handler), this->channel); - EventManager::get_instance().subscribe( - std::move(this->key_released_handler), this->channel); + key_pressed_handler = [this](const KeyPressEvent& event) { + return this->on_key_pressed(event); + }; + key_released_handler = [this](const KeyReleaseEvent& event) { + return this->on_key_released(event); + }; + + event_manager.subscribe( + std::move(this->key_pressed_handler), this->channel); + event_manager.subscribe( + std::move(this->key_released_handler), this->channel); } +// Unsubscribe from key events void IKeyListener::unsubscribe_events() { - EventManager::get_instance().unsubscribe( - this->key_pressed_handler, channel); - EventManager::get_instance().unsubscribe( - this->key_released_handler, channel); - std::cout << std::endl; + event_manager.unsubscribe( + this->key_pressed_handler, this->channel); + event_manager.unsubscribe( + this->key_released_handler, this->channel); } + +// Activate key listening void IKeyListener::activate_keys() { - if (this->active) { - return; - } - this->subscribe_events(); + if (this->active) { + return; + } + this->active = true; + this->subscribe_events(); } + +// Deactivate key listening void IKeyListener::deactivate_keys() { - if (!this->active) { - return; - } - this->unsubscribe_events(); + if (!this->active) { + return; + } + this->active = false; + this->unsubscribe_events(); } + +// Set a new channel for key events void IKeyListener::set_channel(int channel) { - this->unsubscribe_events(); - this->channel = channel; - this->subscribe_events(); + this->unsubscribe_events(); + this->channel = channel; + this->subscribe_events(); } diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index 5a2cafa..77fbf1e 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -1,9 +1,11 @@ #pragma once + #include "Event.h" #include "EventHandler.h" #include "EventManager.h" namespace crepe { + /** * \class IKeyListener * \brief Interface for keyboard event handling in the application. @@ -76,6 +78,7 @@ private: EventHandler key_pressed_handler; //!< Key release event handler. EventHandler key_released_handler; + EventManager& event_manager; }; } // namespace crepe diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index 489e55b..f49004a 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -2,11 +2,19 @@ using namespace crepe; -IMouseListener::IMouseListener(int channel) { this->channel = channel; } +IMouseListener::IMouseListener(int channel) + : event_manager(EventManager::get_instance()), channel(channel) { + this->subscribe_events(); +} -IMouseListener::IMouseListener() { this->subscribe_events(); } +IMouseListener::IMouseListener() + : event_manager(EventManager::get_instance()) { + this->subscribe_events(); +} -IMouseListener::~IMouseListener() { this->unsubscribe_events(); } +IMouseListener::~IMouseListener() { + this->unsubscribe_events(); +} void IMouseListener::subscribe_events() { // Define handler lambdas and subscribe them @@ -22,25 +30,20 @@ void IMouseListener::subscribe_events() { mouse_move_handler = [this](const MouseMoveEvent & event) { return this->on_mouse_moved(event); }; - EventManager::get_instance().subscribe( - std::move(this->mouse_click_handler), this->channel); - EventManager::get_instance().subscribe( - std::move(this->mouse_press_handler), this->channel); - EventManager::get_instance().subscribe( - std::move(this->mouse_release_handler), this->channel); - EventManager::get_instance().subscribe( - std::move(this->mouse_move_handler), this->channel); + + // Subscribe event handlers (no need for std::move) + event_manager.subscribe(std::move(mouse_click_handler), this->channel); + event_manager.subscribe(std::move(mouse_press_handler), this->channel); + event_manager.subscribe(std::move(mouse_release_handler), this->channel); + event_manager.subscribe(std::move(mouse_move_handler), this->channel); } -// TODO: reference voor singleton + void IMouseListener::unsubscribe_events() { - EventManager::get_instance().unsubscribe( - this->mouse_click_handler, this->channel); - EventManager::get_instance().unsubscribe( - this->mouse_press_handler, this->channel); - EventManager::get_instance().unsubscribe( - this->mouse_release_handler, this->channel); - EventManager::get_instance().unsubscribe( - this->mouse_move_handler, this->channel); + // Unsubscribe event handlers + event_manager.unsubscribe(mouse_click_handler, this->channel); + event_manager.unsubscribe(mouse_press_handler, this->channel); + event_manager.unsubscribe(mouse_release_handler, this->channel); + event_manager.unsubscribe(mouse_move_handler, this->channel); } void IMouseListener::activate_mouse() { @@ -48,6 +51,7 @@ void IMouseListener::activate_mouse() { return; } this->subscribe_events(); + this->active = true; } void IMouseListener::deactivate_mouse() { @@ -55,6 +59,7 @@ void IMouseListener::deactivate_mouse() { return; } this->unsubscribe_events(); + this->active = false; } void IMouseListener::set_channel(int channel) { diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 1df55af..3b9e317 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -5,6 +5,7 @@ #include "EventManager.h" namespace crepe { + /** * \class IMouseListener * \brief Interface for mouse event handling in the application. @@ -115,6 +116,7 @@ private: EventHandler mouse_release_handler; //! Mouse move event handler. EventHandler mouse_move_handler; + EventManager& event_manager; }; } //namespace crepe diff --git a/src/crepe/api/KeyCodes.h b/src/crepe/api/KeyCodes.h index e5a91fc..a326527 100644 --- a/src/crepe/api/KeyCodes.h +++ b/src/crepe/api/KeyCodes.h @@ -1,146 +1,186 @@ #pragma once +//! \file InputEnums.h +//! \brief Defines enums for mouse buttons and keyboard keycodes used in the application. + +//! \enum MouseButton +//! \brief Enumeration for mouse button inputs, including standard and extended buttons. 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, + //! No mouse button input. + NONE = 0, + //! Left mouse button. + LEFT_MOUSE = 1, + //! Right mouse button. + RIGHT_MOUSE = 2, + //! Middle mouse button (scroll wheel press). + MIDDLE_MOUSE = 3, + //! First extended mouse button. + X1_MOUSE = 4, + //! Second extended mouse button. + X2_MOUSE = 5, + //! Scroll wheel upward movement. + SCROLL_UP = 6, + //! Scroll wheel downward movement. + SCROLL_DOWN = 7 }; +//! \enum Keycode +//! \brief Enumeration for keyboard key inputs, including printable characters, function keys, and keypad keys. enum class Keycode : int { - NONE = 0, - 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, - - LEFT_BRACKET = 91, /* [ */ - BACKSLASH = 92, /* \ */ - RIGHT_BRACKET = 93, /* ] */ - GRAVE_ACCENT = 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, - PAGE_UP = 266, - PAGE_DOWN = 267, - HOME = 268, - END = 269, - CAPS_LOCK = 280, - SCROLL_LOCK = 281, - NUM_LOCK = 282, - PRINT_SCREEN = 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, - KP_DECIMAL = 330, - KP_DIVIDE = 331, - KP_MULTIPLY = 332, - KP_SUBTRACT = 333, - KP_ADD = 334, - KP_ENTER = 335, - KP_EQUAL = 336, - - LEFT_SHIFT = 340, - LEFT_CONTROL = 341, - LEFT_ALT = 342, - LEFT_SUPER = 343, - RIGHT_SHIFT = 344, - RIGHT_CONTROL = 345, - RIGHT_ALT = 346, - RIGHT_SUPER = 347, - MENU = 348 + //! No key input. + NONE = 0, + //! Spacebar. + SPACE = 32, + //! Apostrophe ('). + APOSTROPHE = 39, + //! Comma (,). + COMMA = 44, + //! Minus (-). + MINUS = 45, + //! Period (.). + PERIOD = 46, + //! Slash (/). + SLASH = 47, + //! Digit 0. + D0 = 48, + //! Digit 1. + D1 = 49, + //! Digit 2. + D2 = 50, + //! Digit 3. + D3 = 51, + //! Digit 4. + D4 = 52, + //! Digit 5. + D5 = 53, + //! Digit 6. + D6 = 54, + //! Digit 7. + D7 = 55, + //! Digit 8. + D8 = 56, + //! Digit 9. + D9 = 57, + //! Semicolon (;). + SEMICOLON = 59, + //! Equal sign (=). + EQUAL = 61, + //! Key 'A'. + A = 65, + //! Key 'B'. + B = 66, + //! Key 'C'. + C = 67, + //! Key 'D'. + D = 68, + //! Key 'E'. + E = 69, + //! Key 'F'. + F = 70, + //! Key 'G'. + G = 71, + //! Key 'H'. + H = 72, + //! Key 'I'. + I = 73, + //! Key 'J'. + J = 74, + //! Key 'K'. + K = 75, + //! Key 'L'. + L = 76, + //! Key 'M'. + M = 77, + //! Key 'N'. + N = 78, + //! Key 'O'. + O = 79, + //! Key 'P'. + P = 80, + //! Key 'Q'. + Q = 81, + //! Key 'R'. + R = 82, + //! Key 'S'. + S = 83, + //! Key 'T'. + T = 84, + //! Key 'U'. + U = 85, + //! Key 'V'. + V = 86, + //! Key 'W'. + W = 87, + //! Key 'X'. + X = 88, + //! Key 'Y'. + Y = 89, + //! Key 'Z'. + Z = 90, + //! Left bracket ([). + LEFT_BRACKET = 91, + //! Backslash (\). + BACKSLASH = 92, + //! Right bracket (]). + RIGHT_BRACKET = 93, + //! Grave accent (`). + GRAVE_ACCENT = 96, + //! Non-US key #1. + WORLD1 = 161, + //! Non-US key #2. + WORLD2 = 162, + //! Escape key. + ESCAPE = 256, + //! Enter key. + ENTER = 257, + //! Tab key. + TAB = 258, + //! Backspace key. + BACKSPACE = 259, + //! Insert key. + INSERT = 260, + //! Delete key. + DELETE = 261, + //! Right arrow key. + RIGHT = 262, + //! Left arrow key. + LEFT = 263, + //! Down arrow key. + DOWN = 264, + //! Up arrow key. + UP = 265, + //! Page Up key. + PAGE_UP = 266, + //! Page Down key. + PAGE_DOWN = 267, + //! Home key. + HOME = 268, + //! End key. + END = 269, + //! Caps Lock key. + CAPS_LOCK = 280, + //! Scroll Lock key. + SCROLL_LOCK = 281, + //! Num Lock key. + NUM_LOCK = 282, + //! Print Screen key. + PRINT_SCREEN = 283, + //! Pause key. + PAUSE = 284, + //! Function keys (F1-F25). + 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 digits and operators. + KP0 = 320, KP1 = 321, KP2 = 322, KP3 = 323, KP4 = 324, + KP5 = 325, KP6 = 326, KP7 = 327, KP8 = 328, KP9 = 329, + KP_DECIMAL = 330, KP_DIVIDE = 331, KP_MULTIPLY = 332, + KP_SUBTRACT = 333, KP_ADD = 334, KP_ENTER = 335, KP_EQUAL = 336, + //! Modifier keys. + LEFT_SHIFT = 340, LEFT_CONTROL = 341, LEFT_ALT = 342, LEFT_SUPER = 343, + RIGHT_SHIFT = 344, RIGHT_CONTROL = 345, RIGHT_ALT = 346, RIGHT_SUPER = 347, + //! Menu key. + MENU = 348 }; diff --git a/src/example/events.cpp b/src/example/events.cpp index ed519ff..5a0a748 100644 --- a/src/example/events.cpp +++ b/src/example/events.cpp @@ -89,11 +89,13 @@ int main() { // Trigger the events while `testListener` is in scope EventManager::get_instance().trigger_event(key_press, 1); - EventManager::get_instance().trigger_event(MouseClickEvent{ - .mouse_x = 100, - .mouse_y = 100, - .button = MouseButton::LEFT_MOUSE, - },1); + EventManager::get_instance().trigger_event( + MouseClickEvent{ + .mouse_x = 100, + .mouse_y = 100, + .button = MouseButton::LEFT_MOUSE, + }, + 1); } // custom lambda event handler EventHandler event_handler = [](const KeyPressEvent & e) { -- cgit v1.2.3 From ce14236bd08469737185962d0be11d72c442b60e Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Wed, 20 Nov 2024 15:39:27 +0100 Subject: most tests done --- src/crepe/api/Event.h | 12 +- src/crepe/api/EventHandler.cpp | 3 +- src/crepe/api/EventHandler.h | 6 +- src/crepe/api/EventHandler.hpp | 8 +- src/crepe/api/EventManager.cpp | 11 +- src/crepe/api/EventManager.h | 32 ++- src/crepe/api/EventManager.hpp | 24 +- src/crepe/api/IKeyListener.cpp | 35 +-- src/crepe/api/IKeyListener.h | 21 +- src/crepe/api/IMouseListener.cpp | 34 +-- src/crepe/api/IMouseListener.h | 22 +- src/crepe/facade/SDLContext.cpp | 1 - src/example/events.cpp | 74 +++--- src/test/CMakeLists.txt | 1 + src/test/EventTest.cpp | 470 +++++++++++++++++++++++++++++++++++++++ 15 files changed, 584 insertions(+), 170 deletions(-) create mode 100644 src/test/EventTest.cpp (limited to 'src/crepe/api/Event.h') diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h index d5ddf0a..33f3add 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -7,17 +7,15 @@ /** * \brief Base class for all event types in the system. */ -class Event { -public: -}; +class Event {}; /** * \brief Event triggered when a key is pressed. */ class KeyPressEvent : public Event { public: - //! Number of times the key press is repeated (e.g., for long presses). - int repeat = 0; + //! false if first time press, true if key is repeated + bool repeat = false; //! The key that was pressed. Keycode key = Keycode::NONE; @@ -110,6 +108,4 @@ public: /** * \brief Event triggered to indicate the application is shutting down. */ -class ShutDownEvent : public Event { -public: -}; +class ShutDownEvent : public Event {}; diff --git a/src/crepe/api/EventHandler.cpp b/src/crepe/api/EventHandler.cpp index 186ec9c..4dc232f 100644 --- a/src/crepe/api/EventHandler.cpp +++ b/src/crepe/api/EventHandler.cpp @@ -2,5 +2,4 @@ using namespace crepe; -// Implementation of IEventHandlerWrapper::exec -bool IEventHandlerWrapper::exec(const Event & e) { return call(e); } +bool IEventHandlerWrapper::exec(const Event & e) { return this->call(e); } diff --git a/src/crepe/api/EventHandler.h b/src/crepe/api/EventHandler.h index db51d04..90886aa 100644 --- a/src/crepe/api/EventHandler.h +++ b/src/crepe/api/EventHandler.h @@ -13,6 +13,8 @@ namespace crepe { * indicating whether the event is handled. * * \tparam EventType The type of event this handler will handle. + * + * Returning \c false from an event handler results in the event being propogated to other listeners for the same event type, while returning \c true stops propogation altogether. */ template using EventHandler = std::function; @@ -105,9 +107,9 @@ private: std::string get_type() const override; //! The event handler function. - EventHandler m_handler; + EventHandler handler; //! The type name of the handler function. - const std::string m_handler_type; + const std::string handler_type; }; } // namespace crepe diff --git a/src/crepe/api/EventHandler.hpp b/src/crepe/api/EventHandler.hpp index 9c47da2..a1e774d 100644 --- a/src/crepe/api/EventHandler.hpp +++ b/src/crepe/api/EventHandler.hpp @@ -8,19 +8,19 @@ namespace crepe { // Implementation of EventHandlerWrapper constructor template EventHandlerWrapper::EventHandlerWrapper(const EventHandler & handler) - : m_handler(handler), - m_handler_type(m_handler.target_type().name()) {} + : handler(handler), + handler_type(handler.target_type().name()) {} // Implementation of EventHandlerWrapper::call template bool EventHandlerWrapper::call(const Event & e) { - return m_handler(static_cast(e)); + return this->handler(static_cast(e)); } // Implementation of EventHandlerWrapper::get_type template std::string EventHandlerWrapper::get_type() const { - return m_handler_type; + return this->handler_type; } } //namespace crepe diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index b465e89..27a304f 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -13,9 +13,9 @@ void EventManager::dispatch_events() { using HandlersVec = std::vector>; for (auto event_it = this->events_queue.begin(); event_it != this->events_queue.end();) { - std::unique_ptr & event = std::get<0>(*event_it); - int channel = std::get<1>(*event_it); - std::type_index event_type = std::get<2>(*event_it); + std::unique_ptr & event = (*event_it).event; + int channel = (*event_it).channel; + std::type_index event_type = (*event_it).type; bool event_handled = false; @@ -58,3 +58,8 @@ void EventManager::dispatch_events() { } } } +void EventManager::clear(){ + this->subscribers.clear(); + this->events_queue.clear(); + this->subscribers_by_event_id.clear(); +} diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index 92273df..8fd22f4 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -11,7 +11,7 @@ #include "EventHandler.h" namespace crepe { - +static constexpr int CHANNEL_ALL = -1; /** * \class EventManager * \brief The EventManager class is responsible for managing the subscription, triggering, @@ -19,6 +19,7 @@ namespace crepe { */ class EventManager { public: + /** * \brief Get the singleton instance of the EventManager. * @@ -38,7 +39,7 @@ public: * \param channel The channel number to subscribe to (default is 0). */ template - void subscribe(EventHandler && callback, int channel = 0); + void subscribe(const EventHandler & callback, int channel = CHANNEL_ALL, int priority = 0); /** * \brief Unsubscribe from an event. @@ -50,7 +51,7 @@ public: * \param channel The event ID to unsubscribe from. */ template - void unsubscribe(const EventHandler &, int channel = 0); + void unsubscribe(const EventHandler &, int channel = CHANNEL_ALL); /** * \brief Trigger an event. @@ -62,7 +63,7 @@ public: * \param channel The channel from which to trigger the event (default is 0). */ template - void trigger_event(const EventType & event, int channel = 0); + void trigger_event(const EventType & event, int channel = CHANNEL_ALL); /** * \brief Queue an event for later processing. @@ -75,7 +76,7 @@ public: * \param channel The channel number for the event (default is 0). */ template - void queue_event(EventType && event, int channel = 0); + void queue_event(const EventType & event, int channel = CHANNEL_ALL,int priority = 0); /** * \brief Dispatch all queued events. @@ -84,8 +85,24 @@ public: * callbacks for each event. */ void dispatch_events(); - + /** + * \brief clears all subscribers + * + */ + void clear(); private: + struct QueueEntry { + std::unique_ptr event; + int channel = 0; + std::type_index type; + int priority = 0; + }; + struct CallbackEntry { + std::unique_ptr callback; + int channel = 0; + std::type_index type; + int priority = 0; + }; /** * \brief Default constructor for the EventManager. * @@ -94,7 +111,7 @@ private: EventManager() = default; //! The queue of events to be processed. - std::vector, int, std::type_index>> events_queue; + std::vector events_queue; //! Registered event handlers. std::unordered_map>> subscribers; @@ -103,6 +120,7 @@ private: std::type_index, std::unordered_map>>> subscribers_by_event_id; + }; } // namespace crepe diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp index b20b88f..9090a3f 100644 --- a/src/crepe/api/EventManager.hpp +++ b/src/crepe/api/EventManager.hpp @@ -3,7 +3,7 @@ namespace crepe { template -void EventManager::subscribe(EventHandler && callback, int channel) { +void EventManager::subscribe(const EventHandler & callback, int channel, int priority) { using HandlersMap = std::unordered_map>>; using HandlersVec = std::vector>; @@ -27,14 +27,20 @@ void EventManager::subscribe(EventHandler && callback, int channel) { } template -void EventManager::queue_event(EventType && event, int channel) { - std::type_index event_type = std::type_index(typeid(EventType)); +void EventManager::queue_event(const EventType & event, int channel,int priority) { + static_assert(std::is_base_of::value, "EventType must derive from Event"); + std::type_index event_type = typeid(EventType); - auto event_ptr = std::make_unique(std::forward(event)); + auto event_ptr = std::make_unique(event); - std::tuple, int, std::type_index> tuple(std::move(event_ptr), - channel, event_type); - this->events_queue.push_back(std::move(tuple)); + + this->events_queue.push_back( + QueueEntry{ + .event = std::move(event_ptr), + .channel = channel, + .type = event_type + } + ); } template @@ -43,7 +49,7 @@ void EventManager::trigger_event(const EventType & event, int channel) { = std::unordered_map>>; using HandlersVec = std::vector>; - std::type_index event_type = std::type_index(typeid(EventType)); + std::type_index event_type = typeid(EventType); if (channel > 0) { HandlersMap & handlers_map = this->subscribers_by_event_id[event_type]; @@ -75,7 +81,7 @@ void EventManager::unsubscribe(const EventHandler & callback, int cha = std::unordered_map>>; using HandlersVec = std::vector>; - std::type_index event_type(typeid(EventType)); + std::type_index event_type = typeid(EventType); std::string handler_name = callback.target_type().name(); if (channel) { diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index f5426be..5e7d9bb 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -2,13 +2,6 @@ using namespace crepe; -// Constructor with default channel -IKeyListener::IKeyListener() - : channel(0), - active(true), - event_manager(EventManager::get_instance()) { - this->subscribe_events(); -} // Constructor with specified channel IKeyListener::IKeyListener(int channel) @@ -28,9 +21,9 @@ void IKeyListener::subscribe_events() { key_released_handler = [this](const KeyReleaseEvent & event) { return this->on_key_released(event); }; - event_manager.subscribe(std::move(this->key_pressed_handler), + event_manager.subscribe(this->key_pressed_handler, this->channel); - event_manager.subscribe(std::move(this->key_released_handler), + event_manager.subscribe(this->key_released_handler, this->channel); } @@ -40,27 +33,3 @@ void IKeyListener::unsubscribe_events() { event_manager.unsubscribe(this->key_released_handler, this->channel); } -// Activate key listening -void IKeyListener::activate_keys() { - if (this->active) { - return; - } - this->active = true; - this->subscribe_events(); -} - -// Deactivate key listening -void IKeyListener::deactivate_keys() { - if (!this->active) { - return; - } - this->active = false; - this->unsubscribe_events(); -} - -// Set a new channel for key events -void IKeyListener::set_channel(int channel) { - this->unsubscribe_events(); - this->channel = channel; - this->subscribe_events(); -} diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index d492387..70243b4 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -16,11 +16,11 @@ public: * \brief Constructs an IKeyListener with a specified channel. * \param channel The channel ID for event handling. */ - IKeyListener(int channel); - IKeyListener(); + IKeyListener(int channel = CHANNEL_ALL); virtual ~IKeyListener(); IKeyListener(const IKeyListener &) = delete; IKeyListener & operator=(const IKeyListener &) = delete; + IKeyListener & operator=(IKeyListener &&) = delete; IKeyListener(IKeyListener &&) = delete; /** @@ -36,23 +36,6 @@ public: * \return True if the event was handled, false otherwise. */ virtual bool on_key_released(const KeyReleaseEvent & event) = 0; - - /** - * \brief Activates key listening. - */ - void activate_keys(); - - /** - * \brief Deactivates key listening. - */ - void deactivate_keys(); - - /** - * \brief Sets the channel ID for event handling. - * \param channel The channel ID to set. - */ - void set_channel(int channel); - protected: /** * \brief Subscribes to key events. diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index 5ee2814..6fd6c4b 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -8,10 +8,6 @@ IMouseListener::IMouseListener(int channel) this->subscribe_events(); } -IMouseListener::IMouseListener() : event_manager(EventManager::get_instance()) { - this->subscribe_events(); -} - IMouseListener::~IMouseListener() { this->unsubscribe_events(); } void IMouseListener::subscribe_events() { @@ -26,11 +22,11 @@ void IMouseListener::subscribe_events() { = [this](const MouseMoveEvent & event) { return this->on_mouse_moved(event); }; // Subscribe event handlers (no need for std::move) - event_manager.subscribe(std::move(mouse_click_handler), this->channel); - event_manager.subscribe(std::move(mouse_press_handler), this->channel); - event_manager.subscribe(std::move(mouse_release_handler), + event_manager.subscribe(mouse_click_handler, this->channel); + event_manager.subscribe(mouse_press_handler, this->channel); + event_manager.subscribe(mouse_release_handler, this->channel); - event_manager.subscribe(std::move(mouse_move_handler), this->channel); + event_manager.subscribe(mouse_move_handler, this->channel); } void IMouseListener::unsubscribe_events() { @@ -40,25 +36,3 @@ void IMouseListener::unsubscribe_events() { event_manager.unsubscribe(mouse_release_handler, this->channel); event_manager.unsubscribe(mouse_move_handler, this->channel); } - -void IMouseListener::activate_mouse() { - if (this->active) { - return; - } - this->subscribe_events(); - this->active = true; -} - -void IMouseListener::deactivate_mouse() { - if (!this->active) { - return; - } - this->unsubscribe_events(); - this->active = false; -} - -void IMouseListener::set_channel(int channel) { - this->unsubscribe_events(); - this->channel = channel; - this->subscribe_events(); -} diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 921a760..1195a4e 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -12,16 +12,15 @@ namespace crepe { */ class IMouseListener { public: - IMouseListener(); /** * \brief Constructs an IMouseListener with a specified channel. * \param channel The channel ID for event handling. */ - IMouseListener(int channel); + IMouseListener(int channel = CHANNEL_ALL); virtual ~IMouseListener(); IMouseListener & operator=(const IMouseListener &) = delete; IMouseListener(const IMouseListener &) = delete; - IMouseListener && operator=(const IMouseListener &&) = delete; + IMouseListener & operator=(const IMouseListener &&) = delete; IMouseListener(IMouseListener &&) = delete; /** @@ -56,23 +55,6 @@ public: * \return True if the event was handled, false otherwise. */ virtual bool on_mouse_moved(const MouseMoveEvent & event) = 0; - - /** - * \brief Activates mouse listening. - */ - void activate_mouse(); - - /** - * \brief Deactivates mouse listening. - */ - void deactivate_mouse(); - - /** - * \brief Sets the channel ID for event handling. - * \param channel The channel ID to set. - */ - void set_channel(int channel); - protected: /** * \brief Subscribes to mouse events on the specified channel. diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index 83e91f8..9464c31 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -78,7 +78,6 @@ SDLContext::~SDLContext() { IMG_Quit(); SDL_Quit(); } - void SDLContext::handle_events(bool & running) { //TODO: wouter i need events /* diff --git a/src/example/events.cpp b/src/example/events.cpp index 6431c67..402a857 100644 --- a/src/example/events.cpp +++ b/src/example/events.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -27,7 +26,6 @@ class MyScript : public Script, public IKeyListener, public IMouseListener { bool on_key_pressed(const KeyPressEvent & event) override { std::cout << "KeyPressed function" << std::endl; - this->deactivate_keys(); return false; } bool on_key_released(const KeyReleaseEvent & event) override { @@ -65,48 +63,60 @@ public: } }; int main() { - // two events to trigger - KeyPressEvent key_press; - key_press.key = Keycode::A; - key_press.repeat = 0; - MouseClickEvent click_event; - click_event.button = MouseButton::LEFT_MOUSE; - click_event.mouse_x = 100; - click_event.mouse_y = 200; - // queue events to test queue - EventManager::get_instance().queue_event(std::move(key_press), 0); - EventManager::get_instance().queue_event(std::move(click_event), 0); + { + // two events to trigger + KeyPressEvent key_press; + key_press.key = Keycode::A; + key_press.repeat = 0; + MouseClickEvent click_event; + click_event.button = MouseButton::LEFT_MOUSE; + click_event.mouse_x = 100; + click_event.mouse_y = 200; + // queue events to test queue + EventManager::get_instance().queue_event(key_press); + EventManager::get_instance().queue_event(click_event); TestKeyListener test_listener; - test_listener.set_channel(1); - auto obj = GameObject(0, "name", "tag", Vector2{1.2, 3.4}, 0, 1); - obj.add_component().set_script(); + //auto obj = GameObject(0, "name", "tag", Vector2{1.2, 3.4}, 0, 1); + //obj.add_component().set_script(); - ScriptSystem sys; - sys.update(); + //ScriptSystem sys; + //sys.update(); // Trigger the events while `testListener` is in scope - EventManager::get_instance().trigger_event(key_press, 1); - EventManager::get_instance().trigger_event( - MouseClickEvent{ - .mouse_x = 100, - .mouse_y = 100, - .button = MouseButton::LEFT_MOUSE, - }, - 1); + //EventManager::get_instance().trigger_event(key_press, 1); + // EventManager::get_instance().trigger_event( + // MouseClickEvent{ + // .mouse_x = 100, + // .mouse_y = 100, + // .button = MouseButton::LEFT_MOUSE, + // }, + // 1); + //EventManager::get_instance().trigger_event(click_event, 0); } // custom lambda event handler EventHandler event_handler = [](const KeyPressEvent & e) { - std::cout << "lambda test" << std::endl; + std::cout << "key lambda test" << std::endl; + return true; + }; + EventHandler event_handler2 = [](const MouseClickEvent & e) { + std::cout << "mouse lambda test" << std::endl; return false; }; - EventManager::get_instance().subscribe(std::move(event_handler), 0); + EventManager::get_instance().subscribe(event_handler, CHANNEL_ALL); + EventManager::get_instance().subscribe(event_handler, CHANNEL_ALL); + EventManager::get_instance().subscribe(event_handler2, CHANNEL_ALL); + EventManager::get_instance().trigger_event(KeyPressEvent{ + .repeat = false, + .key = Keycode::A + }); + //EventManager::get_instance().unsubscribe(event_handler, 0); // testing trigger with testListener not in scope (unsubscribed) - EventManager::get_instance().trigger_event(key_press, 0); - EventManager::get_instance().trigger_event(click_event, 0); + // EventManager::get_instance().trigger_event(key_press, 0); + // EventManager::get_instance().trigger_event(click_event, 0); // dispatching queued events - EventManager::get_instance().dispatch_events(); + //EventManager::get_instance().dispatch_events(); - EventManager::get_instance().unsubscribe(event_handler, 0); + EventManager::get_instance().unsubscribe(event_handler); return EXIT_SUCCESS; } diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 49c8151..6f6ad79 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -3,5 +3,6 @@ target_sources(test_main PUBLIC PhysicsTest.cpp ScriptTest.cpp ParticleTest.cpp + EventTest.cpp ) diff --git a/src/test/EventTest.cpp b/src/test/EventTest.cpp new file mode 100644 index 0000000..19f6d2e --- /dev/null +++ b/src/test/EventTest.cpp @@ -0,0 +1,470 @@ + +#include "api/EventManager.h" +#include "api/Event.h" +#include "api/IKeyListener.h" +#include "api/IMouseListener.h" +#include +#include +#include +using namespace std; +using namespace std::chrono_literals; +using namespace crepe; + + +class EventManagerTest : public ::testing::Test { +protected: + void SetUp() override { + // Clear any existing subscriptions or events before each test + EventManager::get_instance().clear(); + } + + void TearDown() override { + // Ensure cleanup after each test + EventManager::get_instance().clear(); + } +}; +class MockKeyListener : public IKeyListener { +public: + MOCK_METHOD(bool, on_key_pressed, (const KeyPressEvent& event), (override)); + MOCK_METHOD(bool, on_key_released, (const KeyReleaseEvent& event), (override)); +}; + +class MockMouseListener : public IMouseListener { +public: + MOCK_METHOD(bool, on_mouse_clicked, (const MouseClickEvent& event), (override)); + MOCK_METHOD(bool, on_mouse_pressed, (const MousePressEvent& event), (override)); + MOCK_METHOD(bool, on_mouse_released, (const MouseReleaseEvent& event), (override)); + MOCK_METHOD(bool, on_mouse_moved, (const MouseMoveEvent& event), (override)); +}; +TEST_F(EventManagerTest, EventSubscription) { + EventHandler key_handler = [](const KeyPressEvent& e) { + std::cout << "Key Event Triggered" << std::endl; + return true; + }; + + // Subscribe to KeyPressEvent + EventManager::get_instance().subscribe(key_handler, 1); + + // Verify subscription (not directly verifiable; test by triggering event) + + EventManager::get_instance().trigger_event(KeyPressEvent{ + .repeat = true, + .key = Keycode::A, + }, 1); + EventManager::get_instance().trigger_event(KeyPressEvent{ + .repeat = true, + .key = Keycode::A, + + }, CHANNEL_ALL); + +} +TEST_F(EventManagerTest, EventManagerTest_trigger_all_channels) { + bool triggered = false; + + EventHandler mouse_handler = [&](const MouseClickEvent& e) { + triggered = true; + std::cout << "mouse handled" <(mouse_handler, CHANNEL_ALL); + + MouseClickEvent click_event{ + .mouse_x = 100, + .mouse_y = 200, + .button = MouseButton::LEFT_MOUSE + }; + EventManager::get_instance().trigger_event(click_event, CHANNEL_ALL); + + EXPECT_TRUE(triggered); +} + +TEST_F(EventManagerTest, EventManagerTest_priority_order) { + EventManager& event_manager = EventManager::get_instance(); + + // Vector to track call order + std::vector call_order; + + // Handlers with different priorities + EventHandler handler_priority_3 = [&](const MouseClickEvent& e) { + call_order.push_back(3); + return false; // Allow propagation + }; + + EventHandler handler_priority_1 = [&](const MouseClickEvent& e) { + call_order.push_back(1); + return false; // Allow propagation + }; + + EventHandler handler_priority_2 = [&](const MouseClickEvent& e) { + call_order.push_back(2); + return false; // Allow propagation + }; + + // Subscribe handlers with different priorities + event_manager.subscribe(handler_priority_1, CHANNEL_ALL, 1); + event_manager.subscribe(handler_priority_2, CHANNEL_ALL, 2); + event_manager.subscribe(handler_priority_3, CHANNEL_ALL, 3); + + // Trigger the event + event_manager.trigger_event(MouseClickEvent{ + .mouse_x = 100, + .mouse_y = 200, + .button = MouseButton::LEFT_MOUSE + }, CHANNEL_ALL); + + // Check the call order matches the expected priority order + std::vector expected_order = {3, 2, 1}; + EXPECT_EQ(call_order, expected_order); + +} + +TEST_F(EventManagerTest, EventManagerTest_callback_propagation) { + EventManager& event_manager = EventManager::get_instance(); + + // Flags to track handler calls + bool triggered_true = false; + bool triggered_false = false; + + // Handlers + EventHandler mouse_handler_true = [&](const MouseClickEvent& e) { + triggered_true = true; + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return true; // Stops propagation + }; + + EventHandler mouse_handler_false = [&](const MouseClickEvent& e) { + triggered_false = true; + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; + + // Test event + MouseClickEvent click_event{ + .mouse_x = 100, + .mouse_y = 200, + .button = MouseButton::LEFT_MOUSE + }; + + // First Scenario: True handler has higher priority + event_manager.subscribe(mouse_handler_true, CHANNEL_ALL, 1); + event_manager.subscribe(mouse_handler_false, CHANNEL_ALL, 0); + + // Trigger event + event_manager.trigger_event(click_event, CHANNEL_ALL); + + // Check that only the true handler was triggered + EXPECT_TRUE(triggered_true); + EXPECT_FALSE(triggered_false); + + // Reset and clear + triggered_true = false; + triggered_false = false; + event_manager.clear(); + + // Second Scenario: False handler has higher priority + event_manager.subscribe(mouse_handler_true, CHANNEL_ALL, 0); + event_manager.subscribe(mouse_handler_false, CHANNEL_ALL, 1); + + // Trigger event again + event_manager.trigger_event(click_event, CHANNEL_ALL); + + // Check that both handlers were triggered + EXPECT_TRUE(triggered_true); + EXPECT_TRUE(triggered_false); +} + +TEST_F(EventManagerTest, EventManagerTest_queue_dispatch) { + EventManager& event_manager = EventManager::get_instance(); + bool triggered1 = false; + bool triggered2 = false; + int test_channel = 1; + EventHandler mouse_handler1 = [&](const MouseClickEvent& e) { + triggered1 = true; + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; + EventHandler mouse_handler2 = [&](const MouseClickEvent& e) { + triggered2 = true; + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; + event_manager.subscribe(mouse_handler1); + event_manager.subscribe(mouse_handler2,test_channel); + + event_manager.queue_event(MouseClickEvent{ + .mouse_x = 100, + .mouse_y = 200, + .button = MouseButton::LEFT_MOUSE + }); + event_manager.queue_event(MouseClickEvent{ + .mouse_x = 100, + .mouse_y = 200, + .button = MouseButton::LEFT_MOUSE + },test_channel); + event_manager.dispatch_events(); + EXPECT_TRUE(triggered1); + EXPECT_TRUE(triggered2); +} + +TEST_F(EventManagerTest, EventManagerTest_dispatch_priority) { + EventManager& event_manager = EventManager::get_instance(); + std::vector call_order; + int test_channel = 1; + EventHandler mouse_handler1 = [&](const MouseClickEvent& e) { + call_order.push_back(1); + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; + EventHandler mouse_handler2 = [&](const MouseClickEvent& e) { + call_order.push_back(2); + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; + EventHandler mouse_handler3 = [&](const MouseClickEvent& e) { + call_order.push_back(3); + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; + event_manager.subscribe(mouse_handler1,CHANNEL_ALL,1); + event_manager.subscribe(mouse_handler2,CHANNEL_ALL,2); + event_manager.subscribe(mouse_handler2,CHANNEL_ALL,3); + event_manager.queue_event(MouseClickEvent{ + .mouse_x = 100, + .mouse_y = 200, + .button = MouseButton::LEFT_MOUSE + }); + event_manager.dispatch_events(); + std::vector expected_order = {3, 2, 1}; + EXPECT_EQ(call_order, expected_order); +} + +TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { + EventManager& event_manager = EventManager::get_instance(); + + // Flags to track if handlers are triggered + bool triggered1 = false; + bool triggered2 = false; + + // Define EventHandlers + EventHandler mouse_handler1 = [&](const MouseClickEvent& e) { + triggered1 = true; + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; + + EventHandler mouse_handler2 = [&](const MouseClickEvent& e) { + triggered2 = true; + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; + + // Subscribe handlers + event_manager.subscribe(mouse_handler1); + event_manager.subscribe(mouse_handler2); + + // Queue events + event_manager.queue_event(MouseClickEvent{ + .mouse_x = 100, + .mouse_y = 200, + .button = MouseButton::LEFT_MOUSE + }); + + // Dispatch events - both handlers should be triggered + event_manager.dispatch_events(); + EXPECT_TRUE(triggered1); // Handler 1 should be triggered + EXPECT_TRUE(triggered2); // Handler 2 should be triggered + + // Reset flags + triggered1 = false; + triggered2 = false; + + // Unsubscribe handler1 + event_manager.unsubscribe(mouse_handler1); + + // Queue the same event again + event_manager.queue_event(MouseClickEvent{ + .mouse_x = 100, + .mouse_y = 200, + .button = MouseButton::LEFT_MOUSE + }); + + // Dispatch events - only handler 2 should be triggered, handler 1 should NOT + event_manager.dispatch_events(); + EXPECT_FALSE(triggered1); // Handler 1 should NOT be triggered + EXPECT_TRUE(triggered2); // Handler 2 should be triggered + + // Reset flags + triggered2 = false; + + // Unsubscribe handler2 + event_manager.unsubscribe(mouse_handler2); + + // Queue the event again + event_manager.queue_event(MouseClickEvent{ + .mouse_x = 100, + .mouse_y = 200, + .button = MouseButton::LEFT_MOUSE + }); + + // Dispatch events - no handler should be triggered + event_manager.dispatch_events(); + EXPECT_FALSE(triggered1); // Handler 1 should NOT be triggered + EXPECT_FALSE(triggered2); // Handler 2 should NOT be triggered +} + +// TEST_F(EventManagerTest, OnKeyPressedTest) { +// MockKeyListener mock_key_listener; +// EventManager& event_manager = EventManager::get_instance(); + +// // Create the KeyPressEvent object +// KeyPressEvent key_event = KeyPressEvent{ +// .key = Keycode::A, +// .repeat = false +// }; + +// // Set up the mock expectation with direct object passing +// EXPECT_CALL(mock_key_listener, on_key_pressed(key_event)) +// .Times(1) // Expect it to be called exactly once +// .WillOnce(::testing::Return(true)); // Return value (can be true/false) + + +// // Queue the event +// event_manager.queue_event(key_event); + +// // Dispatch the event to trigger the mock +// event_manager.dispatch_events(); // Trigger event dispatch + +// // The mock will ensure the on_key_pressed method is called +// } + + + +// TEST_F(EventManagerTest, OnKeyReleaseTest) { +// MockKeyListener mock_key_listener; +// EventManager& event_manager = EventManager::get_instance(); + +// // Create the KeyPressEvent object +// KeyReleaseEvent key_event = KeyReleaseEvent{ +// .key = Keycode::A, +// }; + +// // Set up the mock expectation with direct object passing +// EXPECT_CALL(mock_key_listener, on_key_released(key_event)) +// .Times(1) // Expect it to be called exactly once +// .WillOnce(::testing::Return(true)); // Return value (can be true/false) + + +// // Queue the event +// event_manager.queue_event(key_event); + +// // Dispatch the event to trigger the mock +// event_manager.dispatch_events(); // Trigger event dispatch + +// // The mock will ensure the on_key_pressed method is called +// } + +// TEST_F(EventManagerTest, UnsubscribeEventsTest) { +// EventManager& event_manager = EventManager::get_instance(); +// KeyPressEvent key_event{ +// .key = Keycode::A, +// .repeat = false +// }; + +// // Create the mock listener +// MockKeyListener mock_key_listener; + +// // Set up the mock expectation that on_key_pressed will be called once initially +// EXPECT_CALL(mock_key_listener, on_key_pressed(key_event)) +// .Times(1) // Expect it to be called exactly once +// .WillOnce(::testing::Return(true)); // Return value (can be true/false) + +// event_manager.queue_event(key_event); +// event_manager.dispatch_events(); // Should trigger on_key_pressed once + +// // Now unsubscribe the listener +// event_manager.unsubscribe(std::bind(&MockKeyListener::on_key_pressed, &mock_key_listener, std::placeholders::_1)); + +// // Set up the expectation that on_key_pressed will NOT be called after unsubscribing +// EXPECT_CALL(mock_key_listener, on_key_pressed(key_event)) +// .Times(0); // Should not be called after unsubscribe + +// // Queue and dispatch the event again (after unsubscribe) +// event_manager.queue_event(key_event); +// event_manager.dispatch_events(); // Should NOT trigger on_key_pressed after unsubscribe +// } + +// TEST_F(EventManagerTest, OnMouseButtonPressedTest) { +// MockMouseListener mock_mouse_listener; +// EventManager& event_manager = EventManager::get_instance(); + +// // Create the MouseButtonPressEvent object +// MousePressEvent mouse_event{ +// .mouse_x = 100, +// .mouse_y = 150, +// .button = MouseButton::LEFT_MOUSE +// }; + +// // Set up the mock expectation with direct object passing +// EXPECT_CALL(mock_mouse_listener, on_mouse_pressed(mouse_event)) +// .Times(1) // Expect it to be called exactly once +// .WillOnce(::testing::Return(true)); // Return value (can be true/false) + +// // Queue the event +// event_manager.queue_event(mouse_event); + +// // Dispatch the event to trigger the mock +// event_manager.dispatch_events(); // Should trigger on_mouse_button_pressed once +// } + +// TEST_F(EventManagerTest, UnsubscribeMouseEventsTest) { +// EventManager& event_manager = EventManager::get_instance(); +// MousePressEvent mouse_event{ +// .mouse_x = 100, +// .mouse_y = 150, +// .button = MouseButton::LEFT_MOUSE +// }; + +// // Create the mock listener +// MockMouseListener mock_mouse_listener; + +// // Set up the mock expectation that on_mouse_button_pressed will be called once initially +// EXPECT_CALL(mock_mouse_listener, on_mouse_pressed(mouse_event)) +// .Times(1) // Expect it to be called exactly once +// .WillOnce(::testing::Return(true)); // Return value (can be true/false) + +// // Queue and dispatch the event (should trigger on_mouse_button_pressed) +// event_manager.queue_event(mouse_event); +// event_manager.dispatch_events(); // Should trigger on_mouse_button_pressed once + +// // Now unsubscribe the listener +// event_manager.unsubscribe(std::bind(&MockMouseListener::on_mouse_pressed, &mock_mouse_listener, std::placeholders::_1)); + +// // Set up the expectation that on_mouse_button_pressed will NOT be called after unsubscribing +// EXPECT_CALL(mock_mouse_listener, on_mouse_pressed(mouse_event)) +// .Times(0); // Should not be called after unsubscribe + +// // Queue and dispatch the event again (after unsubscribe) +// event_manager.queue_event(mouse_event); +// event_manager.dispatch_events(); // Should NOT trigger on_mouse_button_pressed after unsubscribe +// } -- cgit v1.2.3 From 5f76ad1dde34fc0cf7b8ea63befa8917da94fe5c Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Wed, 20 Nov 2024 16:35:58 +0100 Subject: save before big refactor --- src/crepe/api/Event.h | 1 + src/crepe/api/EventManager.h | 27 ++++++++++----------------- src/crepe/api/EventManager.hpp | 29 ++++++++++------------------- 3 files changed, 21 insertions(+), 36 deletions(-) (limited to 'src/crepe/api/Event.h') diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h index 33f3add..06cf7f3 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -1,3 +1,4 @@ +// TODO discussing the location of these events #pragma once #include diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index 8fd22f4..eccb0bf 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -91,35 +91,28 @@ public: */ void clear(); private: + + /** + * \brief Default constructor for the EventManager. + * + * This constructor is private to enforce the singleton pattern. + */ + EventManager() = default; struct QueueEntry { std::unique_ptr event; - int channel = 0; + int channel = CHANNEL_ALL; std::type_index type; int priority = 0; }; struct CallbackEntry { std::unique_ptr callback; - int channel = 0; - std::type_index type; + int channel = CHANNEL_ALL; int priority = 0; }; - /** - * \brief Default constructor for the EventManager. - * - * This constructor is private to enforce the singleton pattern. - */ - EventManager() = default; - //! The queue of events to be processed. std::vector events_queue; //! Registered event handlers. - std::unordered_map>> - subscribers; - //! Event handlers indexed by event ID. - std::unordered_map< - std::type_index, - std::unordered_map>>> - subscribers_by_event_id; + std::unordered_map> subscribers; }; diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp index 9090a3f..3a40336 100644 --- a/src/crepe/api/EventManager.hpp +++ b/src/crepe/api/EventManager.hpp @@ -4,26 +4,17 @@ namespace crepe { template void EventManager::subscribe(const EventHandler & callback, int channel, int priority) { - using HandlersMap - = std::unordered_map>>; - using HandlersVec = std::vector>; + using HandlersVec = std::vector; std::type_index event_type = typeid(EventType); std::unique_ptr> handler = std::make_unique>(callback); - - if (channel) { - HandlersMap & handlers_map = this->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 { - HandlersVec & handlers = this->subscribers[event_type]; - handlers.emplace_back(std::move(handler)); - } + HandlersVec & handlers = this->subscribers[event_type]; + handlers.emplace_back(CallbackEntry{ + .callback = std::move(handler), + .channel = channel, + .priority = priority, + }); } template @@ -33,12 +24,12 @@ void EventManager::queue_event(const EventType & event, int channel,int priority auto event_ptr = std::make_unique(event); - this->events_queue.push_back( QueueEntry{ .event = std::move(event_ptr), .channel = channel, - .type = event_type + .type = event_type, + .priority = priority } ); } @@ -51,7 +42,7 @@ void EventManager::trigger_event(const EventType & event, int channel) { std::type_index event_type = typeid(EventType); - if (channel > 0) { + if (channel == CHANNEL_ALL) { HandlersMap & handlers_map = this->subscribers_by_event_id[event_type]; auto handlers_it = handlers_map.find(channel); -- cgit v1.2.3 From 502fb8e8d1dcfe10f55fdef2cdfb71afec806204 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Thu, 21 Nov 2024 09:43:13 +0100 Subject: pull script/event changes from `loek/collision-system` --- Doxyfile | 6 ++-- src/crepe/api/BehaviorScript.h | 7 +++-- src/crepe/api/BehaviorScript.hpp | 11 +++++--- src/crepe/api/Event.h | 12 ++++---- src/crepe/api/EventManager.h | 4 +-- src/crepe/api/Script.cpp | 6 ++++ src/crepe/api/Script.h | 60 +++++++++++++++++++++++++++++++++++----- src/crepe/api/Script.hpp | 20 ++++++++++++-- src/doc/layout.xml | 2 +- src/test/ScriptTest.cpp | 60 ++++++++++++++++++++++++++++++++++++++-- 10 files changed, 159 insertions(+), 29 deletions(-) (limited to 'src/crepe/api/Event.h') diff --git a/Doxyfile b/Doxyfile index e0a31df..f2714cd 100644 --- a/Doxyfile +++ b/Doxyfile @@ -19,15 +19,17 @@ TAB_SIZE = 2 HTML_INDEX_NUM_ENTRIES = 2 HTML_EXTRA_STYLESHEET = src/doc/style.css +SHOW_HEADERFILE = NO USE_MDFILE_AS_MAINPAGE = ./readme.md REPEAT_BRIEF = NO -INTERNAL_DOCS = YES -EXTRACT_PRIVATE = YES EXTRACT_STATIC = YES HIDE_UNDOC_NAMESPACES = YES HIDE_UNDOC_CLASSES = YES QUIET = YES +# set these to NO for user-only docs +INTERNAL_DOCS = YES +EXTRACT_PRIVATE = YES diff --git a/src/crepe/api/BehaviorScript.h b/src/crepe/api/BehaviorScript.h index 9d85d4c..d556fe5 100644 --- a/src/crepe/api/BehaviorScript.h +++ b/src/crepe/api/BehaviorScript.h @@ -39,11 +39,14 @@ public: * \brief Set the concrete script of this component * * \tparam T Concrete script type (derived from \c crepe::Script) + * \tparam Args Arguments for concrete script constructor + * + * \param args Arguments for concrete script constructor (forwarded using perfect forwarding) * * \returns Reference to BehaviorScript component (`*this`) */ - template - BehaviorScript & set_script(); + template + BehaviorScript & set_script(Args &&... args); protected: //! Script instance diff --git a/src/crepe/api/BehaviorScript.hpp b/src/crepe/api/BehaviorScript.hpp index dd1efd5..5b5a418 100644 --- a/src/crepe/api/BehaviorScript.hpp +++ b/src/crepe/api/BehaviorScript.hpp @@ -9,14 +9,17 @@ namespace crepe { -template -BehaviorScript & BehaviorScript::set_script() { +template +BehaviorScript & BehaviorScript::set_script(Args &&... args) { dbg_trace(); static_assert(std::is_base_of::value); - Script * s = new T(); - s->game_object_id = this->game_object_id; + Script * s = new T(std::forward(args)...); + + s->game_object_id_ref = &this->game_object_id; + s->active_ref = &this->active; s->component_manager_ref = &this->component_manager; s->event_manager_ref = &EventManager::get_instance(); + this->script = std::unique_ptr