From 80c74b90a3e44e25a4fa9fdd25bf0aa9efbaf6fd Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Mon, 11 Nov 2024 16:12:09 +0100 Subject: interfaces working but unsubscribe broken --- src/crepe/api/CMakeLists.txt | 9 +++ src/crepe/api/EventHandler.h | 1 + src/crepe/api/EventManager.cpp | 120 +++++++++++++++++++-------------------- src/crepe/api/EventManager.h | 39 ++++++++++++- src/crepe/api/IKeyListener.cpp | 26 ++++++--- src/crepe/api/IKeyListener.h | 1 + src/crepe/api/IMouseListener.cpp | 25 ++++---- src/crepe/api/IMouseListener.h | 1 + src/example/CMakeLists.txt | 2 +- src/example/events.cpp | 105 ++++++++++++++++++++++++++++++++++ 10 files changed, 247 insertions(+), 82 deletions(-) create mode 100644 src/example/events.cpp (limited to 'src') diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 87cbb09..4e8f8a0 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -18,6 +18,10 @@ target_sources(crepe PUBLIC Vector2.cpp Camera.cpp Animator.cpp + EventManager.cpp + EventHandler.cpp + IKeyListener.cpp + IMouseListener.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -42,4 +46,9 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES SceneManager.hpp Camera.h Animator.h + EventManager.h + EventHandler.h + Event.h + IKeyListener.h + IMouseListener.h ) diff --git a/src/crepe/api/EventHandler.h b/src/crepe/api/EventHandler.h index eea1c79..0da6d7d 100644 --- a/src/crepe/api/EventHandler.h +++ b/src/crepe/api/EventHandler.h @@ -24,6 +24,7 @@ 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 07ef1f7..7a8be53 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -1,69 +1,69 @@ #include "EventManager.h" -void EventManager::unsubscribe(std::type_index eventType, const std::string & handlerName, - int eventId) { - // if (eventId) { - // std::unordered_map< - // std::type_index, std::unordered_map< - // int, std::vector>>>::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()->getType() == 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()->getType() == handlerName) { - // it = handlers.erase(it); - // return; - // } - // } - // } - // } -} +// 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 eventIt - // = eventsQueue.begin(); - // eventIt != eventsQueue.end();) { - // bool handled = false; - // if (!handled) { - // triggerEvent(*eventIt->first.get(), eventIt->second); - // eventIt = eventsQueue.erase(eventIt); - // } else { - // ++eventIt; - // } - // } + 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; + } + } } diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index 8c0685a..88a386a 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -20,7 +20,8 @@ public: } template void subscribe(EventHandler && callback, int channel = 0); - void unsubscribe(std::type_index eventType, const std::string & handlerName,int channel); + template + void unsubscribe(const EventHandler &, int eventId); template void trigger_event(const EventType & event, int channel); void queue_event(std::unique_ptr && event, int channel); @@ -74,3 +75,39 @@ void EventManager::trigger_event(const EventType & event, int eventId) { } } } +template +void EventManager::unsubscribe(const EventHandler & callback, int channel) { + std::type_index event_type(typeid(EventType)); + 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); + if (subscriber_list != subscribers_by_event_id.end()) { + auto& handlers_map = subscriber_list->second; + auto handlers = handlers_map.find(channel); + if (handlers != handlers_map.end()) { + 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; + } + } + } + } + } else { + auto handlers_it = subscribers.find(event_type); + if (handlers_it != subscribers.end()) { + 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 b1ad5e5..f35dc20 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -1,6 +1,13 @@ #include "IKeyListener.h" - -IKeyListener::~IKeyListener() { unsubscribe_events(); } +#include +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) { @@ -9,12 +16,17 @@ void IKeyListener::subscribe_events(int listenerId) { auto key_released_handler = [this](const KeyReleaseEvent & event) { return this->on_key_released(event); }; - - EventManager::get_instance().subscribe(std::move(key_pressed_handler), listenerId); - EventManager::get_instance().subscribe(std::move(key_released_handler), listenerId); + 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; } void IKeyListener::unsubscribe_events(int listenerId) { - EventManager::get_instance().unsubscribe(std::type_index(typeid(KeyPressEvent)), "on_key_pressed", listenerId); - EventManager::get_instance().unsubscribe(std::type_index(typeid(KeyReleaseEvent)), "on_key_released", listenerId); + 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/IKeyListener.h b/src/crepe/api/IKeyListener.h index 4fd2238..fc8de16 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -4,6 +4,7 @@ #include "EventManager.h" class IKeyListener { public: + IKeyListener(); virtual ~IKeyListener(); virtual bool on_key_pressed(const KeyPressEvent & event) = 0; virtual bool on_key_released(const KeyReleaseEvent & event) = 0; diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index 043188c..515d801 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -1,25 +1,25 @@ #include "IMouseListener.h" - +IMouseListener::IMouseListener(){ + subscribe_events(); +} IMouseListener::~IMouseListener() { unsubscribe_events(); } void IMouseListener::subscribe_events(int listenerId) { - // Wrap member functions in lambdas to ensure correct function signatures - mouse_click_handler = [this](const MouseClickEvent & event) { + // Define handler lambdas and subscribe them + auto mouse_click_handler = [this](const MouseClickEvent& event) { return this->on_mouse_clicked(event); }; - mouse_press_handler = [this](const MousePressEvent & event) { + auto mouse_press_handler = [this](const MousePressEvent& event) { return this->on_mouse_pressed(event); }; - mouse_release_handler = [this](const MouseReleaseEvent & event) { + auto mouse_release_handler = [this](const MouseReleaseEvent& event) { return this->on_mouse_released(event); }; - mouse_move_handler = [this](const MouseMoveEvent & event) { + auto mouse_move_handler = [this](const MouseMoveEvent& event) { return this->on_mouse_moved(event); }; - - // Use EventManager for subscribing EventManager::get_instance().subscribe(std::move(mouse_click_handler), listenerId); EventManager::get_instance().subscribe(std::move(mouse_press_handler), listenerId); EventManager::get_instance().subscribe(std::move(mouse_release_handler), listenerId); @@ -27,9 +27,8 @@ void IMouseListener::subscribe_events(int listenerId) { } void IMouseListener::unsubscribe_events(int listenerId) { - // Use EventManager for unsubscribing with correct event type names - EventManager::get_instance().unsubscribe(std::type_index(typeid(MouseClickEvent)), "onMouseClicked", listenerId); - EventManager::get_instance().unsubscribe(std::type_index(typeid(MousePressEvent)), "onMousePressed", listenerId); - EventManager::get_instance().unsubscribe(std::type_index(typeid(MouseReleaseEvent)), "onMouseReleased", listenerId); - EventManager::get_instance().unsubscribe(std::type_index(typeid(MouseMoveEvent)), "onMouseMoved", listenerId); + EventManager::get_instance().unsubscribe(mouse_click_handler, listenerId); + EventManager::get_instance().unsubscribe(mouse_press_handler, listenerId); + EventManager::get_instance().unsubscribe(mouse_release_handler, listenerId); + EventManager::get_instance().unsubscribe(mouse_move_handler, listenerId); } diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 9222905..1078257 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -5,6 +5,7 @@ class IMouseListener { public: + IMouseListener(); virtual ~IMouseListener(); virtual bool on_mouse_clicked(const MouseClickEvent & event) = 0; diff --git a/src/example/CMakeLists.txt b/src/example/CMakeLists.txt index 36f9d4d..da6ceba 100644 --- a/src/example/CMakeLists.txt +++ b/src/example/CMakeLists.txt @@ -28,4 +28,4 @@ add_example(proxy) add_example(db) add_example(ecs) add_example(scene_manager) - +add_example(events) diff --git a/src/example/events.cpp b/src/example/events.cpp new file mode 100644 index 0000000..53eb97f --- /dev/null +++ b/src/example/events.cpp @@ -0,0 +1,105 @@ +#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" +using namespace crepe; +using namespace std; +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{ + std::cout << "KeyPressed function" << std::endl; + return false; + } + bool on_key_released(const KeyReleaseEvent & event) override{ + std::cout << "KeyRelease function" << std::endl; + return false; + } + bool on_mouse_clicked(const MouseClickEvent & event){ + std::cout << "MouseClick function" << std::endl; + return false; + } + bool on_mouse_pressed(const MousePressEvent & event){ + std::cout << "MousePress function" << std::endl; + return false; + } + bool on_mouse_released(const MouseReleaseEvent & event){ + std::cout << "MouseRelease function" << std::endl; + return false; + } + bool on_mouse_moved(const MouseMoveEvent & event){ + 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; + } +}; +int main() { + { + // Instantiate TestKeyListener, which subscribes to key events + TestKeyListener testListener; + + // Create game object with Transform and BehaviorScript components + auto obj = GameObject(0, "name", "tag", Vector2{1.2, 3.4}, 0, 1); + obj.add_component().set_script(); + + // Get ScriptSystem singleton instance (this would normally be done from the game loop) + 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); + + MouseClickEvent click_event; + click_event.button = MouseButton::LEFT_MOUSE; + click_event.mouse_x = 100; + click_event.mouse_y = 200; + EventManager::get_instance().trigger_event(click_event, 0); + + return EXIT_SUCCESS; +} + + -- cgit v1.2.3