diff options
| -rw-r--r-- | src/crepe/api/CMakeLists.txt | 9 | ||||
| -rw-r--r-- | src/crepe/api/EventHandler.h | 1 | ||||
| -rw-r--r-- | src/crepe/api/EventManager.cpp | 120 | ||||
| -rw-r--r-- | src/crepe/api/EventManager.h | 39 | ||||
| -rw-r--r-- | src/crepe/api/IKeyListener.cpp | 26 | ||||
| -rw-r--r-- | src/crepe/api/IKeyListener.h | 1 | ||||
| -rw-r--r-- | src/crepe/api/IMouseListener.cpp | 25 | ||||
| -rw-r--r-- | src/crepe/api/IMouseListener.h | 1 | ||||
| -rw-r--r-- | src/example/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/example/events.cpp | 105 | 
10 files changed, 247 insertions, 82 deletions
| 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<EventType> & 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<std::unique_ptr<IEventHandlerWrapper>>>>::iterator subscriber_list = subscribers_by_event_id.find(eventType); -	// 	if (subscriber_list != subscribers_by_event_id.end()) { -	// 		std::unordered_map< -	// 			int, std::vector<std::unique_ptr<IEventHandlerWrapper>>> & -	// 			handlers_map -	// 			= subscriber_list->second; -	// 		std::unordered_map< -	// 			int, -	// 			std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator -	// 			handlers -	// 			= handlers_map.find(eventId); -	// 		if (handlers != handlers_map.end()) { -	// 			std::vector<std::unique_ptr<IEventHandlerWrapper>> & callbacks -	// 				= handlers->second; -	// 			for (std::vector< -	// 					 std::unique_ptr<IEventHandlerWrapper>>::iterator it -	// 				 = callbacks.begin(); -	// 				 it != callbacks.end(); ++it) { -	// 				if (it->get()->getType() == handlerName) { -	// 					it = callbacks.erase(it); -	// 					return; -	// 				} -	// 			} -	// 		} -	// 	} -	// } else { -	// 	std::unordered_map< -	// 		std::type_index, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator -	// 		handlers_it -	// 		= subscribers.find(eventType); -	// 	if (handlers_it != subscribers.end()) { -	// 		std::vector<std::unique_ptr<IEventHandlerWrapper>> & handlers -	// 			= handlers_it->second; -	// 		for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it -	// 			 = handlers.begin(); -	// 			 it != handlers.end(); ++it) { -	// 			if (it->get()->getType() == handlerName) { -	// 				it = handlers.erase(it); -	// 				return; -	// 			} -	// 		} -	// 	} -	// } -} +// void EventManager::unsubscribe(std::type_index eventType, const std::string & handlerName, +// 							   int eventId) { +// 	if (eventId) { +// 		std::unordered_map< +// 			std::type_index, std::unordered_map< +// 					 int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>>::iterator subscriber_list = subscribers_by_event_id.find(eventType); +// 		if (subscriber_list != subscribers_by_event_id.end()) { +// 			std::unordered_map< +// 				int, std::vector<std::unique_ptr<IEventHandlerWrapper>>> & +// 				handlers_map +// 				= subscriber_list->second; +// 			std::unordered_map< +// 				int, +// 				std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator +// 				handlers +// 				= handlers_map.find(eventId); +// 			if (handlers != handlers_map.end()) { +// 				std::vector<std::unique_ptr<IEventHandlerWrapper>> & callbacks +// 					= handlers->second; +// 				for (std::vector< +// 						 std::unique_ptr<IEventHandlerWrapper>>::iterator it +// 					 = callbacks.begin(); +// 					 it != callbacks.end(); ++it) { +// 					if (it->get()->get_type() == handlerName) { +// 						it = callbacks.erase(it); +// 						return; +// 					} +// 				} +// 			} +// 		} +// 	} else { +// 		std::unordered_map< +// 			std::type_index, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator +// 			handlers_it +// 			= subscribers.find(eventType); +// 		if (handlers_it != subscribers.end()) { +// 			std::vector<std::unique_ptr<IEventHandlerWrapper>> & handlers +// 				= handlers_it->second; +// 			for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it +// 				 = handlers.begin(); +// 				 it != handlers.end(); ++it) { +// 				if (it->get()->get_type() == handlerName) { +// 					it = handlers.erase(it); +// 					return; +// 				} +// 			} +// 		} +// 	} +// }  void EventManager::queue_event(std::unique_ptr<Event> && event_, int eventId) {  	events_queue.emplace_back(std::move(event_), eventId);  }  void EventManager::dispatch_events() { -	// for (std::vector<std::pair<std::unique_ptr<Event>, int>>::iterator eventIt -	// 	 = eventsQueue.begin(); -	// 	 eventIt != eventsQueue.end();) { -	// 	bool handled = false; -	// 	if (!handled) { -	// 		triggerEvent(*eventIt->first.get(), eventIt->second); -	// 		eventIt = eventsQueue.erase(eventIt); -	// 	} else { -	// 		++eventIt; -	// 	} -	// } +	for (std::vector<std::pair<std::unique_ptr<Event>, int>>::iterator event_it +		 = events_queue.begin(); +		 event_it != events_queue.end();) { +		bool handled = false; +		if (!handled) { +			trigger_event<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 <typename EventType>  	void subscribe(EventHandler<EventType> && callback, int channel = 0); -	void unsubscribe(std::type_index eventType, const std::string & handlerName,int channel); +	template <typename EventType> +	void unsubscribe(const EventHandler<EventType> &, int eventId);  	template <typename EventType>  	void trigger_event(const EventType & event, int channel);  	void queue_event(std::unique_ptr<Event> && event, int channel); @@ -74,3 +75,39 @@ void EventManager::trigger_event(const EventType & event, int eventId) {          }      }  } +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()); +	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 <iostream> +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<KeyPressEvent>(std::move(key_pressed_handler), listenerId); -    EventManager::get_instance().subscribe<KeyReleaseEvent>(std::move(key_released_handler), listenerId); +	std::cout << "IKeyListener subscribe: " << std::endl; +    EventManager::get_instance().subscribe<KeyPressEvent>(key_pressed_handler, listenerId); +    EventManager::get_instance().subscribe<KeyReleaseEvent>(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<KeyPressEvent>(key_pressed_handler , listenerId); +    EventManager::get_instance().unsubscribe<KeyReleaseEvent>(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<MouseClickEvent>(std::move(mouse_click_handler), listenerId);      EventManager::get_instance().subscribe<MousePressEvent>(std::move(mouse_press_handler), listenerId);      EventManager::get_instance().subscribe<MouseReleaseEvent>(std::move(mouse_release_handler), listenerId); @@ -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<MouseClickEvent>(mouse_click_handler, listenerId); +    EventManager::get_instance().unsubscribe<MousePressEvent>(mouse_press_handler, listenerId); +    EventManager::get_instance().unsubscribe<MouseReleaseEvent>(mouse_release_handler, listenerId); +    EventManager::get_instance().unsubscribe<MouseMoveEvent>(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 <iostream> + +#include <crepe/ComponentManager.h> +#include <crepe/system/ScriptSystem.h> +#include <crepe/util/log.h> + +#include <crepe/api/BehaviorScript.h> +#include <crepe/api/Config.h> +#include <crepe/api/GameObject.h> +#include <crepe/api/Script.h> +#include <crepe/api/Transform.h> + +#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<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){ +		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<BehaviorScript>().set_script<MyScript>(); + +        // 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<KeyPressEvent>(key_press, 0); +        EventManager::get_instance().trigger_event<MouseClickEvent>(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<KeyPressEvent>(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<MouseClickEvent>(click_event, 0); + +    return EXIT_SUCCESS; +} + + |