diff options
-rw-r--r-- | src/crepe/api/EventHandler.h | 23 | ||||
-rw-r--r-- | src/crepe/api/EventHandler.hpp | 9 | ||||
-rw-r--r-- | src/crepe/api/EventManager.cpp | 42 | ||||
-rw-r--r-- | src/crepe/api/EventManager.h | 158 | ||||
-rw-r--r-- | src/crepe/api/EventManager.hpp | 38 | ||||
-rw-r--r-- | src/crepe/api/IKeyListener.cpp | 26 | ||||
-rw-r--r-- | src/crepe/api/IKeyListener.h | 26 | ||||
-rw-r--r-- | src/crepe/api/IMouseListener.cpp | 47 | ||||
-rw-r--r-- | src/crepe/api/IMouseListener.h | 34 | ||||
-rw-r--r-- | src/example/events.cpp | 120 | ||||
-rw-r--r-- | src/test/EventTest.cpp | 118 |
11 files changed, 198 insertions, 443 deletions
diff --git a/src/crepe/api/EventHandler.h b/src/crepe/api/EventHandler.h index 90886aa..ef659fd 100644 --- a/src/crepe/api/EventHandler.h +++ b/src/crepe/api/EventHandler.h @@ -24,7 +24,7 @@ using EventHandler = std::function<bool(const EventType & e)>; * \brief An abstract base class for event handler wrappers. * * This class provides the interface for handling events. Derived classes must implement the - * `call()` method to process events and the `get_type()` method to return the handler's type. + * `call()` method to process events */ class IEventHandlerWrapper { public: @@ -43,15 +43,6 @@ public: */ 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; - private: /** * \brief The method responsible for handling the event. @@ -96,20 +87,8 @@ private: * \return A boolean value indicating whether the event is handled. */ 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; - //! The event handler function. EventHandler<EventType> handler; - //! The type name of the handler function. - const std::string handler_type; }; } // namespace crepe diff --git a/src/crepe/api/EventHandler.hpp b/src/crepe/api/EventHandler.hpp index a1e774d..8d8136b 100644 --- a/src/crepe/api/EventHandler.hpp +++ b/src/crepe/api/EventHandler.hpp @@ -1,4 +1,3 @@ - #include <typeindex> #include "EventHandler.h" @@ -8,8 +7,7 @@ namespace crepe { // Implementation of EventHandlerWrapper constructor template <typename EventType> EventHandlerWrapper<EventType>::EventHandlerWrapper(const EventHandler<EventType> & handler) - : handler(handler), - handler_type(handler.target_type().name()) {} + : handler(handler){} // Implementation of EventHandlerWrapper::call template <typename EventType> @@ -17,10 +15,5 @@ bool EventHandlerWrapper<EventType>::call(const Event & e) { return this->handler(static_cast<const EventType &>(e)); } -// Implementation of EventHandlerWrapper::get_type -template <typename EventType> -std::string EventHandlerWrapper<EventType>::get_type() const { - return this->handler_type; -} } //namespace crepe diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index dbdb0c3..64d7c26 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -15,22 +15,18 @@ void EventManager::dispatch_events() { bool event_handled = false; auto handlers_it = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - std::vector<CallbackEntry> & handlers = handlers_it->second; - - std::sort(handlers.begin(), handlers.end(), - [](const CallbackEntry & a, const CallbackEntry & b) { - return a.priority > b.priority; - }); - - for (auto handler_it = handlers.begin(); handler_it != handlers.end(); - ++handler_it) { - // If callback is executed and returns true, remove the event from the queue - if ((*handler_it).callback->exec(*event)) { - event_it = this->events_queue.erase(event_it); - event_handled = true; - break; - } + if (handlers_it == this->subscribers.end()) { + continue; + } + std::vector<CallbackEntry> & handlers = handlers_it->second; + + for (auto handler_it = handlers.begin(); handler_it != handlers.end(); + ++handler_it) { + // If callback is executed and returns true, remove the event from the queue + if ((*handler_it).callback->exec(*event)) { + event_it = this->events_queue.erase(event_it); + event_handled = true; + break; } } @@ -44,3 +40,17 @@ void EventManager::clear() { this->subscribers.clear(); this->events_queue.clear(); } + +void EventManager::unsubscribe(subscription_t event_id) { + for (auto& [event_type, handlers] : this->subscribers) { + for (auto it = handlers.begin(); it != handlers.end();) { + if (it->id == event_id) { + it = handlers.erase(it); + return; + } else { + ++it; + } + } + } +} + diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index 133d72d..93e9ca2 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -11,109 +11,131 @@ #include "EventHandler.h" namespace crepe { -static constexpr int CHANNEL_ALL = -1; +//! typedef for subscription value +typedef int subscription_t; + /** * \class EventManager - * \brief The EventManager class is responsible for managing the subscription, triggering, - * and queueing of events. It handles events and dispatches them to appropriate subscribers. + * \brief Manages event subscriptions, triggers, and queues, enabling decoupled event handling. + * + * The `EventManager` acts as a centralized event system. It allows for registering callbacks + * for specific event types, triggering events synchronously, queueing events for later + * processing, and managing subscriptions via unique identifiers. */ class EventManager { public: + static constexpr int CHANNEL_ALL = -1; + /** - * \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. - */ + * \brief Get the singleton instance of the EventManager. + * + * This method returns the unique instance of the EventManager, creating it if it + * doesn't already exist. Ensures only one instance is active in the program. + * + * \return Reference to the singleton instance of the EventManager. + */ static EventManager & get_instance(); /** - * \brief Subscribe to an event. - * - * This method allows the registration of a callback for a specific event type and channel. - * - * \tparam EventType The type of the event to subscribe to. - * \param callback The callback function to invoke when the event is triggered. - * \param channel The channel number to subscribe to (default is 0). - */ + * \brief Subscribe to a specific event type. + * + * Registers a callback for a given event type and optional channel. Each callback + * is assigned a unique subscription ID that can be used for later unsubscription. + * + * \tparam EventType The type of the event to subscribe to. + * \param callback The callback function to be invoked when the event is triggered. + * \param channel The channel number to subscribe to (default is CHANNEL_ALL, which listens to all channels). + * \return A unique subscription ID associated with the registered callback. + */ template <typename EventType> - void subscribe(const EventHandler<EventType> & callback, int channel = CHANNEL_ALL, - int priority = 0); + subscription_t subscribe(const EventHandler<EventType> & callback, int channel = CHANNEL_ALL); /** - * \brief Unsubscribe from an event. - * - * This method removes a previously registered callback from an event. - * - * \tparam EventType The type of the event to unsubscribe from. - * \param callback The callback function to remove from the subscription list. - * \param channel The event ID to unsubscribe from. - */ - template <typename EventType> - void unsubscribe(const EventHandler<EventType> &, int channel = CHANNEL_ALL); + * \brief Unsubscribe a previously registered callback. + * + * Removes a callback from the subscription list based on its unique subscription ID. + * + * \param event_id The unique subscription ID of the callback to remove. + */ + void unsubscribe(subscription_t event_id); /** - * \brief Trigger an event. - * - * This method invokes the appropriate callback(s) for the specified event. - * - * \tparam EventType The type of the event to trigger. - * \param event The event data to pass to the callback. - * \param channel The channel from which to trigger the event (default is 0). - */ + * \brief Trigger an event immediately. + * + * Synchronously invokes all registered callbacks for the given event type on the specified channel. + * + * \tparam EventType The type of the event to trigger. + * \param event The event instance to pass to the callbacks. + * \param channel The channel to trigger the event on (default is CHANNEL_ALL, which triggers on all channels). + */ template <typename EventType> void trigger_event(const EventType & event, int channel = CHANNEL_ALL); /** - * \brief Queue an event for later processing. - * - * This method adds an event to the event queue, which will be processed in the - * dispatch_events function. - * - * \tparam EventType The type of the event to queue. - * \param event The event to queue. - * \param channel The channel number for the event (default is 0). - */ + * \brief Queue an event for later processing. + * + * Adds an event to the event queue to be processed during the next call to `dispatch_events`. + * + * \tparam EventType The type of the event to queue. + * \param event The event instance to queue. + * \param channel The channel to associate with the event (default is CHANNEL_ALL). + */ template <typename EventType> - void queue_event(const EventType & event, int channel = CHANNEL_ALL, int priority = 0); + void queue_event(const EventType & event, int channel = CHANNEL_ALL); /** - * \brief Dispatch all queued events. - * - * This method processes all events in the event queue and triggers the corresponding - * callbacks for each event. - */ + * \brief Process all queued events. + * + * Iterates through the event queue and triggers callbacks for each queued event. + * Events are removed from the queue once processed. + */ void dispatch_events(); + /** - * \brief clears all subscribers - * - */ + * \brief Clear all subscriptions. + * + * Removes all registered event handlers and clears the subscription list. + */ void clear(); private: /** - * \brief Default constructor for the EventManager. - * - * This constructor is private to enforce the singleton pattern. - */ + * \brief Default constructor for the EventManager. + * + * Constructor is private to enforce the singleton pattern. + */ EventManager() = default; + + /** + * \struct QueueEntry + * \brief Represents an entry in the event queue. + */ struct QueueEntry { - std::unique_ptr<Event> event; - int channel = CHANNEL_ALL; - std::type_index type; - int priority = 0; + std::unique_ptr<Event> event; ///< The event instance. + int channel = CHANNEL_ALL; ///< The channel associated with the event. + std::type_index type; ///< The type of the event. }; + + /** + * \struct CallbackEntry + * \brief Represents a registered event handler callback. + */ struct CallbackEntry { - std::unique_ptr<IEventHandlerWrapper> callback; - int channel = CHANNEL_ALL; - int priority = 0; + std::unique_ptr<IEventHandlerWrapper> callback; ///< The callback function wrapper. + int channel = CHANNEL_ALL; ///< The channel this callback listens to. + subscription_t id = -1; ///< Unique subscription ID. }; - //! The queue of events to be processed. + + //! The queue of events to be processed during dispatch. std::vector<QueueEntry> events_queue; - //! Registered event handlers. + + //! A map of event type to registered callbacks. std::unordered_map<std::type_index, std::vector<CallbackEntry>> subscribers; + + //! Counter to generate unique subscription IDs. + subscription_t subscription_counter = 0; }; } // namespace crepe + #include "EventManager.hpp" diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp index a04a43a..d7afa9f 100644 --- a/src/crepe/api/EventManager.hpp +++ b/src/crepe/api/EventManager.hpp @@ -3,9 +3,8 @@ namespace crepe { template <typename EventType> -void EventManager::subscribe(const EventHandler<EventType> & callback, int channel, - int priority) { - +subscription_t EventManager::subscribe(const EventHandler<EventType> & callback, int channel) { + subscription_counter++; std::type_index event_type = typeid(EventType); std::unique_ptr<EventHandlerWrapper<EventType>> handler = std::make_unique<EventHandlerWrapper<EventType>>(callback); @@ -13,17 +12,13 @@ void EventManager::subscribe(const EventHandler<EventType> & callback, int chann handlers.emplace_back(CallbackEntry{ .callback = std::move(handler), .channel = channel, - .priority = priority, + .id = subscription_counter }); - // Sort handlers by priority (highest first) - std::sort(handlers.begin(), handlers.end(), - [](const CallbackEntry & a, const CallbackEntry & b) { - return a.priority > b.priority; - }); + return subscription_counter; } template <typename EventType> -void EventManager::queue_event(const EventType & event, int channel, int priority) { +void EventManager::queue_event(const EventType & event, int channel) { static_assert(std::is_base_of<Event, EventType>::value, "EventType must derive from Event"); std::type_index event_type = typeid(EventType); @@ -32,8 +27,7 @@ void EventManager::queue_event(const EventType & event, int channel, int priorit this->events_queue.push_back(QueueEntry{.event = std::move(event_ptr), .channel = channel, - .type = event_type, - .priority = priority}); + .type = event_type}); } template <typename EventType> @@ -55,25 +49,5 @@ void EventManager::trigger_event(const EventType & event, int channel) { } } -template <typename EventType> -void EventManager::unsubscribe(const EventHandler<EventType> & callback, int channel) { - std::type_index event_type = typeid(EventType); - std::string handler_name = callback.target_type().name(); - - // Find the list of handlers for this event type - auto handlers_it = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - std::vector<CallbackEntry> & handlers = handlers_it->second; - - for (auto it = handlers.begin(); it != handlers.end();) { - // Match based on handler type and channel - if (it->callback->get_type() == handler_name && it->channel == channel) { - it = handlers.erase(it); - return; - } - ++it; - } - } -} } // namespace crepe diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index 6a522c1..ebbf486 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -3,29 +3,15 @@ using namespace crepe; // Constructor with specified channel -IKeyListener::IKeyListener(int channel) - : channel(channel), - active(true), +IKeyListener::IKeyListener(int channel) : event_manager(EventManager::get_instance()) { - this->subscribe_events(); + press_id = event_manager.subscribe<KeyPressEvent>([this](const KeyPressEvent & event) { return this->on_key_pressed(event); }, channel); + release_id = event_manager.subscribe<KeyReleaseEvent>([this](const KeyReleaseEvent & event) { return this->on_key_released(event); }, channel); } // Destructor, 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); }; - - event_manager.subscribe<KeyPressEvent>(this->key_pressed_handler, this->channel); - event_manager.subscribe<KeyReleaseEvent>(this->key_released_handler, this->channel); +IKeyListener::~IKeyListener() { + event_manager.unsubscribe(press_id); + event_manager.unsubscribe(release_id); } -// Unsubscribe from key events -void IKeyListener::unsubscribe_events() { - event_manager.unsubscribe<KeyPressEvent>(this->key_pressed_handler, this->channel); - event_manager.unsubscribe<KeyReleaseEvent>(this->key_released_handler, this->channel); -} diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index 9402cce..4726aa7 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -16,7 +16,7 @@ public: * \brief Constructs an IKeyListener with a specified channel. * \param channel The channel ID for event handling. */ - IKeyListener(int channel = CHANNEL_ALL); + IKeyListener(int channel = EventManager::CHANNEL_ALL); virtual ~IKeyListener(); IKeyListener(const IKeyListener &) = delete; IKeyListener & operator=(const IKeyListener &) = delete; @@ -36,27 +36,11 @@ public: * \return True if the event was handled, false otherwise. */ virtual bool on_key_released(const KeyReleaseEvent & event) = 0; - -protected: - /** - * \brief Subscribes to key events. - */ - void subscribe_events(); - - /** - * \brief Unsubscribes from key events. - */ - void unsubscribe_events(); - private: - //! Indicates whether key listening is active. - bool active = true; - //! Channel ID for event handling. - int channel = 0; - //! Key press event handler. - EventHandler<KeyPressEvent> key_pressed_handler; - //!< Key release event handler. - EventHandler<KeyReleaseEvent> key_released_handler; + //! Key press event id + subscription_t press_id = -1; + //!< Key release event id + subscription_t release_id = -1; EventManager & event_manager; }; diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index f3ceb84..a6cb163 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -3,35 +3,28 @@ using namespace crepe; IMouseListener::IMouseListener(int channel) - : event_manager(EventManager::get_instance()), - channel(channel) { - this->subscribe_events(); -} + : event_manager(EventManager::get_instance()) { + click_id = event_manager.subscribe<MouseClickEvent>( + [this](const MouseClickEvent & event) { return this->on_mouse_clicked(event); }, + channel); -IMouseListener::~IMouseListener() { this->unsubscribe_events(); } + press_id = event_manager.subscribe<MousePressEvent>( + [this](const MousePressEvent & event) { return this->on_mouse_pressed(event); }, + channel); -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); }; + release_id = event_manager.subscribe<MouseReleaseEvent>( + [this](const MouseReleaseEvent & event) { return this->on_mouse_released(event); }, + channel); - // Subscribe event handlers (no need for std::move) - event_manager.subscribe<MouseClickEvent>(mouse_click_handler, this->channel); - event_manager.subscribe<MousePressEvent>(mouse_press_handler, this->channel); - event_manager.subscribe<MouseReleaseEvent>(mouse_release_handler, this->channel); - event_manager.subscribe<MouseMoveEvent>(mouse_move_handler, this->channel); + move_id = event_manager.subscribe<MouseMoveEvent>( + [this](const MouseMoveEvent & event) { return this->on_mouse_moved(event); }, + channel); } -void IMouseListener::unsubscribe_events() { - // Unsubscribe event handlers - event_manager.unsubscribe<MouseClickEvent>(mouse_click_handler, this->channel); - event_manager.unsubscribe<MousePressEvent>(mouse_press_handler, this->channel); - event_manager.unsubscribe<MouseReleaseEvent>(mouse_release_handler, this->channel); - event_manager.unsubscribe<MouseMoveEvent>(mouse_move_handler, this->channel); -} +IMouseListener::~IMouseListener() { + // Unsubscribe event handlers + event_manager.unsubscribe(click_id); + event_manager.unsubscribe(press_id); + event_manager.unsubscribe(release_id); + event_manager.unsubscribe(move_id); + } diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 6bc5716..91b33e1 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -16,7 +16,7 @@ public: * \brief Constructs an IMouseListener with a specified channel. * \param channel The channel ID for event handling. */ - IMouseListener(int channel = CHANNEL_ALL); + IMouseListener(int channel = EventManager::CHANNEL_ALL); virtual ~IMouseListener(); IMouseListener & operator=(const IMouseListener &) = delete; IMouseListener(const IMouseListener &) = delete; @@ -56,30 +56,16 @@ public: */ virtual bool on_mouse_moved(const MouseMoveEvent & event) = 0; -protected: - /** - * \brief Subscribes to mouse events on the specified channel. - */ - void subscribe_events(); - - /** - * \brief Unsubscribes from mouse events on the specified channel. - */ - void unsubscribe_events(); - private: - //! Indicates whether mouse listening is active. - bool active = true; - //! Channel ID for event handling. - int channel = 0; - //! Mouse click event handler. - EventHandler<MouseClickEvent> mouse_click_handler; - //! Mouse press event handler. - EventHandler<MousePressEvent> mouse_press_handler; - //! Mouse release event handler. - EventHandler<MouseReleaseEvent> mouse_release_handler; - //! Mouse move event handler. - EventHandler<MouseMoveEvent> mouse_move_handler; + //! Mouse click event id + subscription_t click_id = -1; + //! Mouse press event id + subscription_t press_id = -1; + //! Mouse release event id + subscription_t release_id = -1; + //! Mouse move event id + subscription_t move_id = -1; + //! EventManager reference EventManager & event_manager; }; diff --git a/src/example/events.cpp b/src/example/events.cpp deleted file mode 100644 index 3dee9fa..0000000 --- a/src/example/events.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include <iostream> - -#include <crepe/ComponentManager.h> -#include <crepe/system/ScriptSystem.h> - -#include <crepe/api/BehaviorScript.h> -#include <crepe/api/Config.h> -#include <crepe/api/Event.h> -#include <crepe/api/EventManager.h> -#include <crepe/api/GameObject.h> -#include <crepe/api/IKeyListener.h> -#include <crepe/api/IMouseListener.h> -#include <crepe/api/KeyCodes.h> -#include <crepe/api/Script.h> -#include <crepe/api/Transform.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<Transform>(); - 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) override { - std::cout << "MouseClick function" << std::endl; - return false; - } - bool on_mouse_pressed(const MousePressEvent & event) override { - std::cout << "MousePress function" << std::endl; - return false; - } - bool on_mouse_released(const MouseReleaseEvent & event) override { - std::cout << "MouseRelease function" << std::endl; - return false; - } - 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: " << static_cast<int>(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<int>(event.key) - << std::endl; - return true; - } -}; -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<KeyPressEvent>(key_press); - EventManager::get_instance().queue_event<MouseClickEvent>(click_event); - TestKeyListener test_listener; - //auto obj = GameObject(0, "name", "tag", Vector2{1.2, 3.4}, 0, 1); - //obj.add_component<BehaviorScript>().set_script<MyScript>(); - - //ScriptSystem sys; - //sys.update(); - - // Trigger the events while `testListener` is in scope - //EventManager::get_instance().trigger_event<KeyPressEvent>(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>(click_event, 0); - } - // custom lambda event handler - EventHandler<KeyPressEvent> event_handler = [](const KeyPressEvent & e) { - std::cout << "key lambda test" << std::endl; - return true; - }; - EventHandler<MouseClickEvent> event_handler2 = [](const MouseClickEvent & e) { - std::cout << "mouse lambda test" << std::endl; - return false; - }; - EventManager::get_instance().subscribe<KeyPressEvent>(event_handler, CHANNEL_ALL); - EventManager::get_instance().subscribe<KeyPressEvent>(event_handler, CHANNEL_ALL); - EventManager::get_instance().subscribe<MouseClickEvent>(event_handler2, CHANNEL_ALL); - EventManager::get_instance().trigger_event<KeyPressEvent>( - KeyPressEvent{.repeat = false, .key = Keycode::A}); - //EventManager::get_instance().unsubscribe<KeyPressEvent>(event_handler, 0); - // testing trigger with testListener not in scope (unsubscribed) - // EventManager::get_instance().trigger_event<KeyPressEvent>(key_press, 0); - // EventManager::get_instance().trigger_event<MouseClickEvent>(click_event, 0); - // dispatching queued events - //EventManager::get_instance().dispatch_events(); - - EventManager::get_instance().unsubscribe<KeyPressEvent>(event_handler); - return EXIT_SUCCESS; -} diff --git a/src/test/EventTest.cpp b/src/test/EventTest.cpp index 9dc2360..d42e742 100644 --- a/src/test/EventTest.cpp +++ b/src/test/EventTest.cpp @@ -34,6 +34,7 @@ public: 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<KeyPressEvent> key_handler = [](const KeyPressEvent & e) { std::cout << "Key Event Triggered" << std::endl; @@ -57,65 +58,47 @@ TEST_F(EventManagerTest, EventSubscription) { .key = Keycode::A, }, - CHANNEL_ALL); + EventManager::CHANNEL_ALL); } TEST_F(EventManagerTest, EventManagerTest_trigger_all_channels) { bool triggered = false; EventHandler<MouseClickEvent> mouse_handler = [&](const MouseClickEvent & e) { triggered = true; - std::cout << "mouse handled" << std::endl; EXPECT_EQ(e.mouse_x, 100); EXPECT_EQ(e.mouse_y, 200); EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); return false; }; - EventManager::get_instance().subscribe<MouseClickEvent>(mouse_handler, CHANNEL_ALL); + EventManager::get_instance().subscribe<MouseClickEvent>(mouse_handler, EventManager::CHANNEL_ALL); MouseClickEvent click_event{ .mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}; - EventManager::get_instance().trigger_event<MouseClickEvent>(click_event, CHANNEL_ALL); + EventManager::get_instance().trigger_event<MouseClickEvent>(click_event, EventManager::CHANNEL_ALL); EXPECT_TRUE(triggered); } - -TEST_F(EventManagerTest, EventManagerTest_priority_order) { - EventManager & event_manager = EventManager::get_instance(); - - // Vector to track call order - std::vector<int> call_order; - - // Handlers with different priorities - EventHandler<MouseClickEvent> handler_priority_3 = [&](const MouseClickEvent & e) { - call_order.push_back(3); - return false; // Allow propagation - }; - - EventHandler<MouseClickEvent> handler_priority_1 = [&](const MouseClickEvent & e) { - call_order.push_back(1); - return false; // Allow propagation - }; - - EventHandler<MouseClickEvent> handler_priority_2 = [&](const MouseClickEvent & e) { - call_order.push_back(2); - return false; // Allow propagation +TEST_F(EventManagerTest, EventManagerTest_trigger_one_channel) { + bool triggered = false; + int test_channel = 1; + EventHandler<MouseClickEvent> mouse_handler = [&](const MouseClickEvent & e) { + triggered = true; + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; }; + EventManager::get_instance().subscribe<MouseClickEvent>(mouse_handler, test_channel); - // Subscribe handlers with different priorities - event_manager.subscribe<MouseClickEvent>(handler_priority_1, CHANNEL_ALL, 1); - event_manager.subscribe<MouseClickEvent>(handler_priority_3, CHANNEL_ALL, 3); - event_manager.subscribe<MouseClickEvent>(handler_priority_2, CHANNEL_ALL, 2); - - // Trigger the event - event_manager.trigger_event<MouseClickEvent>( - MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}, - CHANNEL_ALL); + MouseClickEvent click_event{ + .mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}; + EventManager::get_instance().trigger_event<MouseClickEvent>(click_event, EventManager::CHANNEL_ALL); - // Check the call order matches the expected priority order - std::vector<int> expected_order = {3, 2, 1}; - EXPECT_EQ(call_order, expected_order); + EXPECT_FALSE(triggered); + EventManager::get_instance().trigger_event<MouseClickEvent>(click_event, test_channel); } + TEST_F(EventManagerTest, EventManagerTest_callback_propagation) { EventManager & event_manager = EventManager::get_instance(); @@ -143,13 +126,13 @@ TEST_F(EventManagerTest, EventManagerTest_callback_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<MouseClickEvent>(mouse_handler_true, CHANNEL_ALL, 1); - event_manager.subscribe<MouseClickEvent>(mouse_handler_false, CHANNEL_ALL, 0); + event_manager.subscribe<MouseClickEvent>(mouse_handler_true, EventManager::CHANNEL_ALL); + event_manager.subscribe<MouseClickEvent>(mouse_handler_false, EventManager::CHANNEL_ALL); + + // Trigger event - event_manager.trigger_event<MouseClickEvent>(click_event, CHANNEL_ALL); + event_manager.trigger_event<MouseClickEvent>(click_event, EventManager::CHANNEL_ALL); // Check that only the true handler was triggered EXPECT_TRUE(triggered_true); @@ -159,13 +142,12 @@ TEST_F(EventManagerTest, EventManagerTest_callback_propagation) { triggered_true = false; triggered_false = false; event_manager.clear(); - - // Second Scenario: False handler has higher priority - event_manager.subscribe<MouseClickEvent>(mouse_handler_true, CHANNEL_ALL, 0); - event_manager.subscribe<MouseClickEvent>(mouse_handler_false, CHANNEL_ALL, 1); + event_manager.subscribe<MouseClickEvent>(mouse_handler_false, EventManager::CHANNEL_ALL); + event_manager.subscribe<MouseClickEvent>(mouse_handler_true, EventManager::CHANNEL_ALL); + // Trigger event again - event_manager.trigger_event<MouseClickEvent>(click_event, CHANNEL_ALL); + event_manager.trigger_event<MouseClickEvent>(click_event, EventManager::CHANNEL_ALL); // Check that both handlers were triggered EXPECT_TRUE(triggered_true); @@ -204,40 +186,6 @@ TEST_F(EventManagerTest, EventManagerTest_queue_dispatch) { EXPECT_TRUE(triggered2); } -TEST_F(EventManagerTest, EventManagerTest_dispatch_priority) { - EventManager & event_manager = EventManager::get_instance(); - std::vector<int> call_order; - int test_channel = 1; - EventHandler<MouseClickEvent> 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<MouseClickEvent> 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<MouseClickEvent> 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<MouseClickEvent>(mouse_handler2, CHANNEL_ALL, 2); - event_manager.subscribe<MouseClickEvent>(mouse_handler1, CHANNEL_ALL, 1); - event_manager.subscribe<MouseClickEvent>(mouse_handler3, CHANNEL_ALL, 3); - event_manager.queue_event<MouseClickEvent>( - MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}); - event_manager.dispatch_events(); - std::vector<int> expected_order = {3, 2, 1}; - EXPECT_EQ(call_order, expected_order); -} TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { EventManager & event_manager = EventManager::get_instance(); @@ -263,8 +211,8 @@ TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { return false; // Allows propagation }; // Subscribe handlers - event_manager.subscribe<MouseClickEvent>(mouse_handler1); - event_manager.subscribe<MouseClickEvent>(mouse_handler2); + subscription_t handler1_id = event_manager.subscribe<MouseClickEvent>(mouse_handler1); + subscription_t handler2_id = event_manager.subscribe<MouseClickEvent>(mouse_handler2); // Queue events event_manager.queue_event<MouseClickEvent>( @@ -280,7 +228,7 @@ TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { triggered2 = false; // Unsubscribe handler1 - event_manager.unsubscribe<MouseClickEvent>(mouse_handler1); + event_manager.unsubscribe(handler1_id); // Queue the same event again event_manager.queue_event<MouseClickEvent>( @@ -295,7 +243,7 @@ TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { triggered2 = false; // Unsubscribe handler2 - event_manager.unsubscribe<MouseClickEvent>(mouse_handler2); + event_manager.unsubscribe(handler2_id); // Queue the event again event_manager.queue_event<MouseClickEvent>( |