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 +++++++++++++++++++++++++++++++++++ src/crepe/api/EventHandler.cpp | 2 ++ src/crepe/api/EventHandler.h | 38 ++++++++++++++++++++ src/crepe/api/EventManager.cpp | 69 ++++++++++++++++++++++++++++++++++++ src/crepe/api/EventManager.h | 76 ++++++++++++++++++++++++++++++++++++++++ src/crepe/api/IKeyListener.cpp | 20 +++++++++++ src/crepe/api/IKeyListener.h | 20 +++++++++++ src/crepe/api/IMouseListener.cpp | 35 ++++++++++++++++++ src/crepe/api/IMouseListener.h | 24 +++++++++++++ src/makefile | 12 +++++-- 10 files changed, 362 insertions(+), 2 deletions(-) create mode 100644 src/crepe/api/Event.h create mode 100644 src/crepe/api/EventHandler.cpp create mode 100644 src/crepe/api/EventHandler.h create mode 100644 src/crepe/api/EventManager.cpp create mode 100644 src/crepe/api/EventManager.h create mode 100644 src/crepe/api/IKeyListener.cpp create mode 100644 src/crepe/api/IKeyListener.h create mode 100644 src/crepe/api/IMouseListener.cpp create mode 100644 src/crepe/api/IMouseListener.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: +}; diff --git a/src/crepe/api/EventHandler.cpp b/src/crepe/api/EventHandler.cpp new file mode 100644 index 0000000..93a116a --- /dev/null +++ b/src/crepe/api/EventHandler.cpp @@ -0,0 +1,2 @@ +#include "EventHandler.h" +bool IEventHandlerWrapper::exec(const Event & e) { return call(e); } diff --git a/src/crepe/api/EventHandler.h b/src/crepe/api/EventHandler.h new file mode 100644 index 0000000..eea1c79 --- /dev/null +++ b/src/crepe/api/EventHandler.h @@ -0,0 +1,38 @@ +#pragma once +#include +#include +#include +#include "Event.h" + +template +using EventHandler = std::function; + +class IEventHandlerWrapper { +public: + virtual ~IEventHandlerWrapper() = default; + + bool exec(const Event & e); + + virtual std::string get_type() const = 0; + +private: + virtual bool call(const Event & e) = 0; +}; + +template +class EventHandlerWrapper : public IEventHandlerWrapper { +public: + explicit EventHandlerWrapper(const EventHandler & handler) + : m_handler(handler), m_handler_type(m_handler.target_type().name()) { + } + +private: + bool call(const Event & e) override { + return m_handler(static_cast(e)); + } + + std::string get_type() const override { return m_handler_type; } + + EventHandler m_handler; + const std::string m_handler_type; +}; diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp new file mode 100644 index 0000000..07ef1f7 --- /dev/null +++ b/src/crepe/api/EventManager.cpp @@ -0,0 +1,69 @@ +#include "EventManager.h" + +void EventManager::unsubscribe(std::type_index eventType, const std::string & handlerName, + int eventId) { + // if (eventId) { + // std::unordered_map< + // std::type_index, std::unordered_map< + // int, std::vector>>>::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::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; + // } + // } +} diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h new file mode 100644 index 0000000..8c0685a --- /dev/null +++ b/src/crepe/api/EventManager.h @@ -0,0 +1,76 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include "Event.h" +#include "EventHandler.h" +//#include "keyCodes.h" + +class EventManager { +public: + EventManager(const EventManager &) = delete; + const EventManager & operator=(const EventManager &) = delete; + static EventManager & get_instance() { + static EventManager instance; + return instance; + } + template + void subscribe(EventHandler && callback, int channel = 0); + void unsubscribe(std::type_index eventType, const std::string & handlerName,int channel); + template + void trigger_event(const EventType & event, int channel); + void queue_event(std::unique_ptr && event, int channel); + void dispatch_events(); + +private: + EventManager() = default; + std::vector, int>> events_queue; + std::unordered_map>> subscribers; + std::unordered_map>>> subscribers_by_event_id; +}; + +template +void EventManager::subscribe(EventHandler && callback, int channel){ + std::type_index event_type = typeid(EventType); + auto handler = std::make_unique>(callback); + + if (channel) { + auto & handlers_map = subscribers_by_event_id[event_type]; + auto handlers = handlers_map.find(channel); + if (handlers != handlers_map.end()) { + handlers->second.emplace_back(std::move(handler)); + } else { + handlers_map[channel].emplace_back(std::move(handler)); + } + } else { + subscribers[event_type].emplace_back(std::move(handler)); + } +} + +template +void EventManager::trigger_event(const EventType & event, int eventId) { + std::type_index event_type = std::type_index(typeid(EventType)); + + if (eventId > 0) { + auto handlers_it = subscribers_by_event_id[event_type].find(eventId); + if (handlers_it != subscribers_by_event_id[event_type].end()) { + auto & callbacks = handlers_it->second; + for (auto it = callbacks.begin(); it != callbacks.end();) { + if ((*it)->exec(event)) { + it = callbacks.erase(it); + } else { + ++it; + } + } + } + } else { + auto & handlers = subscribers[event_type]; + for (auto & handler : handlers) { + handler->exec(event); + } + } +} diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp new file mode 100644 index 0000000..b1ad5e5 --- /dev/null +++ b/src/crepe/api/IKeyListener.cpp @@ -0,0 +1,20 @@ +#include "IKeyListener.h" + +IKeyListener::~IKeyListener() { unsubscribe_events(); } + +void IKeyListener::subscribe_events(int listenerId) { + auto key_pressed_handler = [this](const KeyPressEvent & event) { + return this->on_key_pressed(event); + }; + auto key_released_handler = [this](const KeyReleaseEvent & event) { + return this->on_key_released(event); + }; + + EventManager::get_instance().subscribe(std::move(key_pressed_handler), listenerId); + EventManager::get_instance().subscribe(std::move(key_released_handler), listenerId); +} + +void IKeyListener::unsubscribe_events(int listenerId) { + EventManager::get_instance().unsubscribe(std::type_index(typeid(KeyPressEvent)), "on_key_pressed", listenerId); + EventManager::get_instance().unsubscribe(std::type_index(typeid(KeyReleaseEvent)), "on_key_released", listenerId); +} diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h new file mode 100644 index 0000000..4fd2238 --- /dev/null +++ b/src/crepe/api/IKeyListener.h @@ -0,0 +1,20 @@ +#pragma once +#include "Event.h" +#include "EventHandler.h" +#include "EventManager.h" +class IKeyListener { +public: + virtual ~IKeyListener(); + virtual bool on_key_pressed(const KeyPressEvent & event) = 0; + virtual bool on_key_released(const KeyReleaseEvent & event) = 0; + +protected: + void subscribe_events(int listenerId = 0); + void unsubscribe_events(int listenerId = 0); + void activate(int listenerId = 0) { subscribe_events(listenerId); } + void deactivate(int listenerId = 0) { unsubscribe_events(listenerId); } + +private: + EventHandler key_pressed_handler; + EventHandler key_released_handler; +}; diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp new file mode 100644 index 0000000..043188c --- /dev/null +++ b/src/crepe/api/IMouseListener.cpp @@ -0,0 +1,35 @@ +#include "IMouseListener.h" + +IMouseListener::~IMouseListener() { + unsubscribe_events(); +} + +void IMouseListener::subscribe_events(int listenerId) { + // Wrap member functions in lambdas to ensure correct function signatures + mouse_click_handler = [this](const MouseClickEvent & event) { + return this->on_mouse_clicked(event); + }; + mouse_press_handler = [this](const MousePressEvent & event) { + return this->on_mouse_pressed(event); + }; + mouse_release_handler = [this](const MouseReleaseEvent & event) { + return this->on_mouse_released(event); + }; + mouse_move_handler = [this](const MouseMoveEvent & event) { + return this->on_mouse_moved(event); + }; + + // Use EventManager for subscribing + EventManager::get_instance().subscribe(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); + EventManager::get_instance().subscribe(std::move(mouse_move_handler), listenerId); +} + +void IMouseListener::unsubscribe_events(int listenerId) { + // Use EventManager for unsubscribing with correct event type names + EventManager::get_instance().unsubscribe(std::type_index(typeid(MouseClickEvent)), "onMouseClicked", listenerId); + EventManager::get_instance().unsubscribe(std::type_index(typeid(MousePressEvent)), "onMousePressed", listenerId); + EventManager::get_instance().unsubscribe(std::type_index(typeid(MouseReleaseEvent)), "onMouseReleased", listenerId); + EventManager::get_instance().unsubscribe(std::type_index(typeid(MouseMoveEvent)), "onMouseMoved", listenerId); +} diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h new file mode 100644 index 0000000..9222905 --- /dev/null +++ b/src/crepe/api/IMouseListener.h @@ -0,0 +1,24 @@ +#pragma once +#include "Event.h" +#include "EventHandler.h" +#include "EventManager.h" + +class IMouseListener { +public: + virtual ~IMouseListener(); + + virtual bool on_mouse_clicked(const MouseClickEvent & event) = 0; + virtual bool on_mouse_pressed(const MousePressEvent & event) = 0; + virtual bool on_mouse_released(const MouseReleaseEvent & event) = 0; + virtual bool on_mouse_moved(const MouseMoveEvent & event) = 0; + +protected: + void subscribe_events(int listenerId = 0); + void unsubscribe_events(int listenerId = 0); + +private: + EventHandler mouse_click_handler; + EventHandler mouse_press_handler; + EventHandler mouse_release_handler; + EventHandler mouse_move_handler; +}; diff --git a/src/makefile b/src/makefile index b9c44c8..03a2c0e 100644 --- a/src/makefile +++ b/src/makefile @@ -94,8 +94,16 @@ LOEK += example/script.cpp LOEK += test/audio.cpp LOEK += test/dummy.cpp JARO += test/PhysicsTest.cpp - -FMT := $(JARO) #<<< CHANGE THIS TO YOUR NAME FOR STEP 2 +WOUTER += crepe/api/Event.h +WOUTER += crepe/api/EventHandler.cpp +WOUTER += crepe/api/EventHandler.h +WOUTER += crepe/api/EventManager.cpp +WOUTER += crepe/api/EventManager.h +WOUTER += crepe/api/IKeyListener.cpp +WOUTER += crepe/api/IKeyListener.h +WOUTER += crepe/api/IMouseListener.cpp +WOUTER += crepe/api/IMouseListener.h +FMT := $(WOUTER) #<<< CHANGE THIS TO YOUR NAME FOR STEP 2 format: FORCE clang-tidy -p build/compile_commands.json --fix-errors $(FMT) -- cgit v1.2.3 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 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 From 9ee280d8149f84f4240902c3363a6881bf425137 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Mon, 11 Nov 2024 18:41:52 +0100 Subject: backup --- src/crepe/api/EventManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index 88a386a..91120fd 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -78,7 +78,7 @@ 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()); + const std::string handler_name = callback.target_type().name(); std::cout << "unsubcribe name: " << handler_name << std::endl; if (channel) { -- cgit v1.2.3 From ca878336da5cdd120a929e6ce84f565ce5365248 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Mon, 11 Nov 2024 19:43:03 +0100 Subject: adjusted render a little and added a error img of the chosen img did not load. this prevents exceptions --- asset/texture/ERROR.png | Bin 0 -> 3581 bytes src/crepe/system/RenderSystem.cpp | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 asset/texture/ERROR.png diff --git a/asset/texture/ERROR.png b/asset/texture/ERROR.png new file mode 100644 index 0000000..2af3548 Binary files /dev/null and b/asset/texture/ERROR.png differ diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 10211a3..3a1def5 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -6,6 +6,7 @@ #include "../api/Transform.h" #include "../facade/SDLContext.h" #include "../util/log.h" +#include "api/ParticleEmitter.h" #include "RenderSystem.h" @@ -42,8 +43,7 @@ void RenderSystem::render_sprites() const { ComponentManager & mgr = ComponentManager::get_instance(); - std::vector> sprites - = mgr.get_components_by_type(); + auto sprites = mgr.get_components_by_type(); SDLContext & render = SDLContext::get_instance(); for (const Sprite & sprite : sprites) { -- cgit v1.2.3 From 3d97f7c60536bf14f314cc703883f74345aacd21 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Mon, 11 Nov 2024 20:49:49 +0100 Subject: rendering particle --- src/crepe/api/Texture.cpp | 2 +- src/crepe/facade/SDLContext.cpp | 4 +-- src/crepe/facade/SDLContext.h | 7 +++-- src/crepe/system/RenderSystem.cpp | 28 +++++++++++++---- src/crepe/system/RenderSystem.h | 6 +++- src/example/CMakeLists.txt | 1 + src/example/rendering_particle.cpp | 61 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 98 insertions(+), 11 deletions(-) create mode 100644 src/example/rendering_particle.cpp diff --git a/src/crepe/api/Texture.cpp b/src/crepe/api/Texture.cpp index 5ebd23d..8ce65c2 100644 --- a/src/crepe/api/Texture.cpp +++ b/src/crepe/api/Texture.cpp @@ -35,5 +35,5 @@ int Texture::get_width() const { } int Texture::get_height() const { if (this->texture == nullptr) return 0; - return SDLContext::get_instance().get_width(*this); + return SDLContext::get_instance().get_height(*this); } diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index e87a2c5..cc2e2f8 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -181,12 +181,12 @@ SDLContext::texture_from_path(const std::string & path) { return img_texture; } -int SDLContext::get_width(const Texture & ctx) const { +int SDLContext::get_width(const Texture & ctx) { int w; SDL_QueryTexture(ctx.texture.get(), NULL, NULL, &w, NULL); return w; } -int SDLContext::get_height(const Texture & ctx) const { +int SDLContext::get_height(const Texture & ctx) { int h; SDL_QueryTexture(ctx.texture.get(), NULL, NULL, NULL, &h); return h; diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index e358c21..7329b74 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -10,6 +10,7 @@ #include "../api/Sprite.h" #include "../api/Transform.h" #include "api/Camera.h" +#include "api/Vector2.h" // FIXME: this needs to be removed const int SCREEN_WIDTH = 640; @@ -97,14 +98,14 @@ private: * \param texture Reference to the Texture object. * \return Width of the texture as an integer. */ - int get_width(const Texture &) const; + int get_width(const Texture &) ; /** * \brief Gets the height of a texture. * \param texture Reference to the Texture object. * \return Height of the texture as an integer. */ - int get_height(const Texture &) const; + int get_height(const Texture &) ; private: //! Will use draw,clear_screen, present_screen, camera. @@ -119,6 +120,8 @@ private: void draw(const Sprite & sprite, const Transform & transform, const Camera & camera); + void draw_particle(const Vector2 & pos, const Camera & camera); + //! Clears the screen, preparing for a new frame. void clear_screen(); diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 3a1def5..3de8330 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -6,7 +7,9 @@ #include "../api/Transform.h" #include "../facade/SDLContext.h" #include "../util/log.h" +#include "Particle.h" #include "api/ParticleEmitter.h" +#include "api/Vector2.h" #include "RenderSystem.h" @@ -39,17 +42,32 @@ void RenderSystem::update_camera() { this->curr_cam = &cam; } } -void RenderSystem::render_sprites() const { + + +void RenderSystem::render_particle(const ParticleEmitter& em, Transform & tm){ + if (!em.active) return; + + SDLContext & render = SDLContext::get_instance(); + for (const Particle& p : em.data.particles) { + tm.position = p.position; + render.draw(em.data.sprite, tm , *curr_cam); + } +} +void RenderSystem::render_sprites() { ComponentManager & mgr = ComponentManager::get_instance(); - auto sprites = mgr.get_components_by_type(); + auto emitter = mgr.get_components_by_type(); SDLContext & render = SDLContext::get_instance(); - for (const Sprite & sprite : sprites) { + Transform test(1, Vector2{0,0},0,0); + + for (const ParticleEmitter & em : emitter) { auto transforms - = mgr.get_components_by_id(sprite.game_object_id); - render.draw(sprite, transforms[0], *curr_cam); + = mgr.get_components_by_id(em.game_object_id); + test.scale = transforms[0].get().scale; + test.rotation = transforms[0].get().rotation; + this->render_particle(em, test); } } diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 70db21a..8dd8b7e 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -3,6 +3,8 @@ #include "api/Camera.h" #include "System.h" +#include "api/ParticleEmitter.h" +#include "api/Transform.h" namespace crepe { @@ -44,7 +46,9 @@ private: void update_camera(); //! Renders all active sprites to the screen. - void render_sprites() const; + void render_sprites() ; + + void render_particle(const ParticleEmitter& em, Transform & tm); /** * \todo Include color handling for sprites. diff --git a/src/example/CMakeLists.txt b/src/example/CMakeLists.txt index 722ffea..72dc172 100644 --- a/src/example/CMakeLists.txt +++ b/src/example/CMakeLists.txt @@ -29,4 +29,5 @@ add_example(db) add_example(ecs) add_example(scene_manager) add_example(particles) +add_example(rendering_particle) diff --git a/src/example/rendering_particle.cpp b/src/example/rendering_particle.cpp new file mode 100644 index 0000000..54a9c23 --- /dev/null +++ b/src/example/rendering_particle.cpp @@ -0,0 +1,61 @@ +#include "api/Camera.h" +#include "system/ParticleSystem.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace crepe; +using namespace std; + +int main(int argc, char * argv[]) { + GameObject game_object(0, "", "", Vector2{0, 0}, 0, 0.1); + Color color(0, 0, 0, 0); + Sprite test_sprite = game_object.add_component( + make_shared("../asset/texture/img.png"), color, + FlipSettings{false, false}); + game_object.add_component(ParticleEmitter::Data{ + .position = {0, 0}, + .max_particles = 100, + .emission_rate = 0.5, + .min_speed = 1, + .max_speed = 1, + .min_angle = 0, + .max_angle = 0, + .begin_lifespan = 0, + .end_lifespan = 60, + .force_over_time = Vector2{0, 0}, + .boundary{ + .width = 1000, + .height = 1000, + .offset = Vector2{0, 0}, + .reset_on_exit = false, + }, + .sprite = test_sprite, + }); + game_object.add_component(Color::get_white()); + + auto & sys = crepe::RenderSystem::get_instance(); + auto sys_part = crepe::ParticleSystem(); + auto start = std::chrono::steady_clock::now(); + while (std::chrono::steady_clock::now() - start < std::chrono::seconds(5)) { + sys_part.update(); + sys.update(); + SDL_Delay(10 ); + } + + return 0; +} + -- cgit v1.2.3 From cf96d9639dbd18df6451a07fd7b623616e842c4a Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Mon, 11 Nov 2024 21:27:54 +0100 Subject: adjusted rendering and example --- src/crepe/system/RenderSystem.cpp | 1 + src/example/rendering_particle.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 3de8330..3fbd175 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -49,6 +49,7 @@ void RenderSystem::render_particle(const ParticleEmitter& em, Transform & tm){ SDLContext & render = SDLContext::get_instance(); for (const Particle& p : em.data.particles) { + if (!p.active) continue; tm.position = p.position; render.draw(em.data.sprite, tm , *curr_cam); } diff --git a/src/example/rendering_particle.cpp b/src/example/rendering_particle.cpp index 54a9c23..bd4ceb4 100644 --- a/src/example/rendering_particle.cpp +++ b/src/example/rendering_particle.cpp @@ -21,17 +21,17 @@ using namespace crepe; using namespace std; int main(int argc, char * argv[]) { - GameObject game_object(0, "", "", Vector2{0, 0}, 0, 0.1); + GameObject game_object(0, "", "", Vector2{100, 0}, 0, 0.1); Color color(0, 0, 0, 0); Sprite test_sprite = game_object.add_component( make_shared("../asset/texture/img.png"), color, FlipSettings{false, false}); game_object.add_component(ParticleEmitter::Data{ .position = {0, 0}, - .max_particles = 100, - .emission_rate = 0.5, - .min_speed = 1, - .max_speed = 1, + .max_particles = 10, + .emission_rate = 0.1, + .min_speed = 10, + .max_speed = 10, .min_angle = 0, .max_angle = 0, .begin_lifespan = 0, -- cgit v1.2.3 From 0d88ba90c55c0df97e418ce36c435955481b2850 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Mon, 11 Nov 2024 21:37:08 +0100 Subject: adjusted renderingsystem --- src/crepe/system/RenderSystem.cpp | 2 +- src/example/rendering_particle.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 3fbd175..8bbf441 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -51,6 +51,7 @@ void RenderSystem::render_particle(const ParticleEmitter& em, Transform & tm){ for (const Particle& p : em.data.particles) { if (!p.active) continue; tm.position = p.position; + tm.rotation = p.angle; render.draw(em.data.sprite, tm , *curr_cam); } } @@ -67,7 +68,6 @@ void RenderSystem::render_sprites() { auto transforms = mgr.get_components_by_id(em.game_object_id); test.scale = transforms[0].get().scale; - test.rotation = transforms[0].get().rotation; this->render_particle(em, test); } } diff --git a/src/example/rendering_particle.cpp b/src/example/rendering_particle.cpp index bd4ceb4..dd08354 100644 --- a/src/example/rendering_particle.cpp +++ b/src/example/rendering_particle.cpp @@ -21,7 +21,7 @@ using namespace crepe; using namespace std; int main(int argc, char * argv[]) { - GameObject game_object(0, "", "", Vector2{100, 0}, 0, 0.1); + GameObject game_object(0, "", "", Vector2{100, 100}, 0, 0.1); Color color(0, 0, 0, 0); Sprite test_sprite = game_object.add_component( make_shared("../asset/texture/img.png"), color, @@ -29,11 +29,11 @@ int main(int argc, char * argv[]) { game_object.add_component(ParticleEmitter::Data{ .position = {0, 0}, .max_particles = 10, - .emission_rate = 0.1, - .min_speed = 10, - .max_speed = 10, - .min_angle = 0, - .max_angle = 0, + .emission_rate = 0.5, + .min_speed = 6, + .max_speed = 20, + .min_angle = -20, + .max_angle = 20, .begin_lifespan = 0, .end_lifespan = 60, .force_over_time = Vector2{0, 0}, -- 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(-) 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 80e4e1eb78898879eed11648808ca6b65eecb304 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Tue, 12 Nov 2024 15:08:37 +0100 Subject: removed auto from code --- src/crepe/api/EventHandler.h | 80 +++++++++++++++++++- src/crepe/api/EventManager.cpp | 21 ++++-- src/crepe/api/EventManager.h | 162 +++++++++++++++++++++++++++++++---------- src/crepe/api/IKeyListener.cpp | 20 ++++- src/crepe/api/IKeyListener.h | 8 +- src/makefile | 3 +- 6 files changed, 240 insertions(+), 54 deletions(-) diff --git a/src/crepe/api/EventHandler.h b/src/crepe/api/EventHandler.h index eea1c79..5b9ac0d 100644 --- a/src/crepe/api/EventHandler.h +++ b/src/crepe/api/EventHandler.h @@ -4,35 +4,109 @@ #include #include "Event.h" +/** + * \brief A type alias for an event handler function. + * + * The EventHandler is a std::function that takes an EventType reference and returns a boolean value + * indicating whether the event was successfully handled. + * + * \tparam EventType The type of event this handler will handle. + */ template using EventHandler = std::function; +/** + * \class IEventHandlerWrapper + * \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. + */ class IEventHandlerWrapper { public: + /** + * \brief Virtual destructor for IEventHandlerWrapper. + */ 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. + * + * \param e The event to be processed. + * \return A boolean value indicating whether the event is handled. + */ 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. + * + * This method is implemented by derived classes to process the event. + * + * \param e The event to be processed. + * \return A boolean value indicating whether the event is handled. + */ virtual bool call(const Event & e) = 0; }; +/** + * \class EventHandlerWrapper + * \brief A wrapper for event handler functions. + * + * This class wraps an event handler function of a specific event type. It implements the + * `call()` and `get_type()` methods to allow the handler to be executed and its type to be + * queried. + * + * \tparam EventType The type of event this handler will handle. + */ 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()) { } private: + /** + * \brief Calls the stored event handler with the event. + * + * This method casts the event to the appropriate type and calls the handler. + * + * \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)); } + /** + * \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; } - - EventHandler m_handler; - 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; }; diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index 869ec74..3d8558b 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -7,6 +7,9 @@ void EventManager::dispatch_events() { auto& 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; + if (channel) { auto handlers_it = subscribers_by_event_id.find(event_type); if (handlers_it != subscribers_by_event_id.end()) { @@ -15,25 +18,33 @@ void EventManager::dispatch_events() { if (handlers != handlers_map.end()) { auto& callbacks = handlers->second; for (auto& handler : callbacks) { - handler->exec(*event); + if (handler->exec(*event)) { + event_it = events_queue.erase(event_it); + event_handled = true; + break; + } } } } } else { + // Handle event for all channels 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 (handler->exec(*event)) { + event_it = events_queue.erase(event_it); + event_handled = true; + break; + } } } } - if (event->handled) { - event_it = events_queue.erase(event_it); - } else { + if (!event_handled) { ++event_it; } } } + diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index be9a947..9b69b29 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -10,48 +10,127 @@ #include "EventHandler.h" //#include "keyCodes.h" +/** + * @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. + */ class EventManager { public: - EventManager(const EventManager &) = delete; - const EventManager & operator=(const EventManager &) = delete; - static EventManager & get_instance() { - static EventManager instance; - return instance; - } - template - void subscribe(EventHandler && callback, int channel = 0); - template - void unsubscribe(const EventHandler &, int eventId); - template - void trigger_event(const EventType & event, int channel); - template - void queue_event(EventType&& event, int channel); - void dispatch_events(); + /** + * \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. + * + * 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 instance; + return 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). + */ + template + void subscribe(EventHandler && callback, int channel = 0); + + /** + * @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 eventId The event ID to unsubscribe from. + */ + template + void unsubscribe(const EventHandler &, int eventId); + + /** + * @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). + */ + 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 + * 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). + */ + 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(); private: - EventManager() = default; - std::vector, int, std::type_index>> events_queue; - std::unordered_map>> subscribers; - std::unordered_map>>> subscribers_by_event_id; + /** + * @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, int, std::type_index>> events_queue; + //! Registered event handlers. + std::unordered_map>> subscribers; + //! Event handlers indexed by event ID. + std::unordered_map>>> subscribers_by_event_id; }; template -void EventManager::subscribe(EventHandler && callback, int channel){ +void EventManager::subscribe(EventHandler && callback, int channel) { std::type_index event_type = typeid(EventType); - auto handler = std::make_unique>(callback); + std::unique_ptr> handler = std::make_unique>(callback); if (channel) { - auto & handlers_map = subscribers_by_event_id[event_type]; - auto handlers = handlers_map.find(channel); + std::unordered_map>>& handlers_map = 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 { - subscribers[event_type].emplace_back(std::move(handler)); + std::vector>& handlers = 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)); @@ -71,10 +150,12 @@ void EventManager::trigger_event(const EventType & event, int eventId) { std::type_index event_type = std::type_index(typeid(EventType)); if (eventId > 0) { - auto handlers_it = subscribers_by_event_id[event_type].find(eventId); - if (handlers_it != subscribers_by_event_id[event_type].end()) { - auto & callbacks = handlers_it->second; - for (auto it = callbacks.begin(); it != callbacks.end();) { + std::unordered_map>>& handlers_map = subscribers_by_event_id[event_type]; + std::unordered_map>>::iterator handlers_it = handlers_map.find(eventId); + + if (handlers_it != handlers_map.end()) { + std::vector>& callbacks = handlers_it->second; + for (std::vector>::iterator it = callbacks.begin(); it != callbacks.end();) { if ((*it)->exec(event)) { it = callbacks.erase(it); } else { @@ -83,25 +164,26 @@ void EventManager::trigger_event(const EventType & event, int eventId) { } } } else { - auto & handlers = subscribers[event_type]; - for (auto & handler : handlers) { - handler->exec(event); + std::vector>& handlers = subscribers[event_type]; + for (std::vector>::iterator it = handlers.begin(); it != handlers.end(); ++it) { + (*it)->exec(event); } } } + 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::string handler_name = callback.target_type().name(); if (channel) { - auto subscriber_list = subscribers_by_event_id.find(event_type); + std::unordered_map>>>::iterator 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); + std::unordered_map>>& handlers_map = subscriber_list->second; + std::unordered_map>>::iterator handlers = handlers_map.find(channel); if (handlers != handlers_map.end()) { - auto& callbacks = handlers->second; - for (auto it = callbacks.begin(); it != callbacks.end(); ++it) { + 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; @@ -110,10 +192,10 @@ void EventManager::unsubscribe(const EventHandler & callback, int cha } } } else { - auto handlers_it = subscribers.find(event_type); + std::unordered_map>>::iterator 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) { + 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 663dbc7..3a06f77 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -1,8 +1,12 @@ #include "IKeyListener.h" #include IKeyListener::IKeyListener(){ - - subscribe_events(0); + this->channel = channel; + subscribe_events(); +} +IKeyListener::IKeyListener(int channel){ + this->channel = channel; + subscribe_events(channel); } IKeyListener::~IKeyListener() { unsubscribe_events(); @@ -24,3 +28,15 @@ void IKeyListener::unsubscribe_events(int listenerId) { EventManager::get_instance().unsubscribe(key_released_handler , listenerId); std::cout << std::endl; } +void IKeyListener::activate_keys(int listenerId) { + if(this->active){ + return; + } + subscribe_events(listenerId); +} +void IKeyListener::deactivate_keys() { + if(!this->active){ + return; + } + unsubscribe_events(); +} diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index fc8de16..83949bf 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -4,18 +4,22 @@ #include "EventManager.h" class IKeyListener { public: + IKeyListener(int channel); IKeyListener(); virtual ~IKeyListener(); virtual bool on_key_pressed(const KeyPressEvent & event) = 0; virtual bool on_key_released(const KeyReleaseEvent & event) = 0; + void activate_keys(int listenerId = 0); + void deactivate_keys(); protected: void subscribe_events(int listenerId = 0); void unsubscribe_events(int listenerId = 0); - void activate(int listenerId = 0) { subscribe_events(listenerId); } - void deactivate(int listenerId = 0) { unsubscribe_events(listenerId); } + private: + bool active = true; + int channel = 0; EventHandler key_pressed_handler; EventHandler key_released_handler; }; diff --git a/src/makefile b/src/makefile index 03a2c0e..f6907f6 100644 --- a/src/makefile +++ b/src/makefile @@ -103,10 +103,9 @@ WOUTER += crepe/api/IKeyListener.cpp WOUTER += crepe/api/IKeyListener.h WOUTER += crepe/api/IMouseListener.cpp WOUTER += crepe/api/IMouseListener.h -FMT := $(WOUTER) #<<< CHANGE THIS TO YOUR NAME FOR STEP 2 +FMT := $(shell git ls-files '*.c' '*.cpp' '*.h' '*.hpp') format: FORCE clang-tidy -p build/compile_commands.json --fix-errors $(FMT) -# FMT += $(shell git ls-files '*.c' '*.cpp' '*.h' '*.hpp') # TODO: re-enable linter after all corrections -- cgit v1.2.3 From fabdc6e27bdb41042d7a530c5f2440ca5a330118 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Tue, 12 Nov 2024 19:52:11 +0100 Subject: Adjusted rendering so that now a gameobject can have multiple sprites with particles and another texture --- src/crepe/system/RenderSystem.cpp | 65 ++++++++++++++++++++++++++------------- src/crepe/system/RenderSystem.h | 22 ++++++++----- src/example/rendering.cpp | 1 + 3 files changed, 60 insertions(+), 28 deletions(-) diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 8bbf441..17a2337 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -7,10 +7,10 @@ #include "../api/Transform.h" #include "../facade/SDLContext.h" #include "../util/log.h" -#include "Particle.h" -#include "api/ParticleEmitter.h" -#include "api/Vector2.h" +#include "../api/ParticleEmitter.h" +#include "../api/Vector2.h" +#include "Particle.h" #include "RenderSystem.h" using namespace crepe; @@ -43,38 +43,61 @@ void RenderSystem::update_camera() { } } +bool RenderSystem::render_particle(const Sprite & sprite, + const Transform & tm) { -void RenderSystem::render_particle(const ParticleEmitter& em, Transform & tm){ - if (!em.active) return; - + ComponentManager & mgr = ComponentManager::get_instance(); SDLContext & render = SDLContext::get_instance(); - for (const Particle& p : em.data.particles) { - if (!p.active) continue; - tm.position = p.position; - tm.rotation = p.angle; - render.draw(em.data.sprite, tm , *curr_cam); + + auto emitters = mgr.get_components_by_id(sprite.game_object_id); + + bool rendering_particles = false; + + Transform tmp(0, Vector2{0, 0}, 0, 0); + tmp.scale = tm.scale; + for (const ParticleEmitter & em : emitters) { + if (!em.active) continue; + if (!(em.data.sprite.game_object_id == sprite.game_object_id)) continue; + + rendering_particles = true; + + for (const Particle & p : em.data.particles) { + if (!p.active) continue; + tmp.position = p.position; + tmp.rotation = p.angle; + render.draw(em.data.sprite, tmp, *curr_cam); + } } + return rendering_particles; } -void RenderSystem::render_sprites() { +void RenderSystem::render_normal(const Sprite & sprite, const Transform & tm) { ComponentManager & mgr = ComponentManager::get_instance(); + SDLContext & render = SDLContext::get_instance(); + + render.draw(sprite, tm, *curr_cam); +} - auto emitter = mgr.get_components_by_type(); +void RenderSystem::render() { - SDLContext & render = SDLContext::get_instance(); - Transform test(1, Vector2{0,0},0,0); + ComponentManager & mgr = ComponentManager::get_instance(); + + auto sprites = mgr.get_components_by_type(); + for (const Sprite & sprite : sprites) { + if (!sprite.active) continue; + auto transform = mgr.get_components_by_id(sprite.game_object_id); + + bool rendered_particles = this->render_particle(sprite, transform[0].get()); + + if (rendered_particles) continue; - for (const ParticleEmitter & em : emitter) { - auto transforms - = mgr.get_components_by_id(em.game_object_id); - test.scale = transforms[0].get().scale; - this->render_particle(em, test); + this->render_normal(sprite, transform[0].get()); } } void RenderSystem::update() { this->clear_screen(); this->update_camera(); - this->render_sprites(); + this->render(); this->present_screen(); } diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 8dd8b7e..468f79b 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -1,10 +1,10 @@ #pragma once #include "api/Camera.h" +#include "api/Sprite.h" +#include "api/Transform.h" #include "System.h" -#include "api/ParticleEmitter.h" -#include "api/Transform.h" namespace crepe { @@ -45,14 +45,22 @@ private: //! Updates the active camera used for rendering. void update_camera(); - //! Renders all active sprites to the screen. - void render_sprites() ; - - void render_particle(const ParticleEmitter& em, Transform & tm); + //! Renders the whole screen + void render(); + + /** + * \brief Renders all the particles on the screen from a given sprite. + * + * \param sprite renders the particles with given texture + * \param tm the Transform component for scale + * \return true if particles have been rendered + */ + bool render_particle(const Sprite &, const Transform & tm); + + void render_normal(const Sprite &, const Transform & tm); /** * \todo Include color handling for sprites. - * \todo Implement particle emitter rendering with sprites. * \todo Add text rendering using SDL_ttf for text components. * \todo Implement a text component and a button component. * \todo Ensure each sprite is checked for active status before rendering. diff --git a/src/example/rendering.cpp b/src/example/rendering.cpp index e02f6a3..a7cb5d6 100644 --- a/src/example/rendering.cpp +++ b/src/example/rendering.cpp @@ -35,6 +35,7 @@ int main() { { Color color(0, 0, 0, 0); obj1.add_component(make_shared("../asset/texture/second.png"), color, FlipSettings{true, true}); + obj1.add_component(make_shared("../asset/texture/second.png"), color, FlipSettings{true, true}); } /* -- cgit v1.2.3 From 8524865e9a62974f77f63d70929000fc63c679d7 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Tue, 12 Nov 2024 19:55:11 +0100 Subject: makefile --- src/makefile | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/makefile b/src/makefile index 356179e..21903a7 100644 --- a/src/makefile +++ b/src/makefile @@ -28,18 +28,18 @@ MAX += crepe/api/Metadata.cpp MAX += crepe/api/Metadata.h JARO += crepe/Particle.cpp JARO += crepe/Particle.h -TODO += crepe/Position.h -TODO += crepe/api/AssetManager.cpp -TODO += crepe/api/AssetManager.h -TODO += crepe/api/AssetManager.hpp +NIELS += crepe/Position.h +NIELS += crepe/api/AssetManager.cpp +NIELS += crepe/api/AssetManager.h +NIELS += crepe/api/AssetManager.hpp LOEK += crepe/api/AudioSource.cpp LOEK += crepe/api/AudioSource.h LOEK += crepe/api/BehaviorScript.cpp LOEK += crepe/api/BehaviorScript.h LOEK += crepe/api/BehaviorScript.hpp TODO += crepe/api/CircleCollider.h -TODO += crepe/api/Color.cpp -TODO += crepe/api/Color.h +NIELS += crepe/api/Color.cpp +NIELS += crepe/api/Color.h LOEK += crepe/api/Config.h MAX += crepe/api/GameObject.cpp MAX += crepe/api/GameObject.h @@ -53,14 +53,14 @@ JARO += crepe/api/Rigidbody.h LOEK += crepe/api/Script.cpp LOEK += crepe/api/Script.h LOEK += crepe/api/Script.hpp -TODO += crepe/api/Sprite.cpp -TODO += crepe/api/Sprite.h -TODO += crepe/api/Texture.cpp -TODO += crepe/api/Texture.h +NIELS += crepe/api/Sprite.cpp +NIELS += crepe/api/Sprite.h +NIELS += crepe/api/Texture.cpp +NIELS += crepe/api/Texture.h MAX += crepe/api/Transform.cpp MAX += crepe/api/Transform.h -TODO += crepe/facade/SDLContext.cpp -TODO += crepe/facade/SDLContext.h +NIELS += crepe/facade/SDLContext.cpp +NIELS += crepe/facade/SDLContext.h LOEK += crepe/facade/Sound.cpp LOEK += crepe/facade/Sound.h LOEK += crepe/facade/SoundContext.cpp @@ -71,8 +71,8 @@ JARO += crepe/system/ParticleSystem.cpp JARO += crepe/system/ParticleSystem.h JARO += crepe/system/PhysicsSystem.cpp JARO += crepe/system/PhysicsSystem.h -TODO += crepe/system/RenderSystem.cpp -TODO += crepe/system/RenderSystem.h +NIELS += crepe/system/RenderSystem.cpp +NIELS += crepe/system/RenderSystem.h LOEK += crepe/system/ScriptSystem.cpp LOEK += crepe/system/ScriptSystem.h LOEK += crepe/system/System.h @@ -82,21 +82,21 @@ LOEK += crepe/util/fmt.cpp LOEK += crepe/util/fmt.h LOEK += crepe/util/log.cpp LOEK += crepe/util/log.h -TODO += example/asset_manager.cpp +NIELS += example/asset_manager.cpp LOEK += example/audio_internal.cpp TODO += example/components_internal.cpp MAX += example/ecs.cpp LOEK += example/log.cpp JARO += example/particles.cpp JARO += example/physics.cpp -TODO += example/rendering.cpp +NIELS += example/rendering.cpp LOEK += example/script.cpp LOEK += test/audio.cpp LOEK += test/dummy.cpp JARO += test/PhysicsTest.cpp JARO += test/ParticleTest.cpp -FMT := $(JARO) #<<< CHANGE THIS TO YOUR NAME FOR STEP 2 +FMT := $(NIELS) #<<< CHANGE THIS TO YOUR NAME FOR STEP 2 format: FORCE clang-tidy -p build/compile_commands.json --fix-errors $(FMT) -- cgit v1.2.3 From ab0c50d5b719863ab9e9821e6720bba450e174ce Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Wed, 13 Nov 2024 12:19:58 +0100 Subject: added activate/deactive to listeners and doxygen comments --- src/crepe/api/EventManager.cpp | 36 ++++++------- src/crepe/api/EventManager.h | 88 ++++++++++++++++-------------- src/crepe/api/IKeyListener.cpp | 27 +++++----- src/crepe/api/IKeyListener.h | 77 +++++++++++++++++++++----- src/crepe/api/IMouseListener.cpp | 42 ++++++++++----- src/crepe/api/IMouseListener.h | 114 +++++++++++++++++++++++++++++++++++---- src/example/events.cpp | 3 -- 7 files changed, 276 insertions(+), 111 deletions(-) diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index 3d8558b..872c6eb 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -1,24 +1,22 @@ #include "EventManager.h" - - void EventManager::dispatch_events() { - 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); + 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; if (channel) { - auto handlers_it = subscribers_by_event_id.find(event_type); + std::unordered_map>>>::iterator 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); + std::unordered_map>>& handlers_map = handlers_it->second; + std::unordered_map>>::iterator handlers = handlers_map.find(channel); if (handlers != handlers_map.end()) { - auto& callbacks = handlers->second; - for (auto& handler : callbacks) { - if (handler->exec(*event)) { + 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; @@ -28,12 +26,12 @@ void EventManager::dispatch_events() { } } else { // Handle event for all channels - auto handlers_it = subscribers.find(event_type); - if (handlers_it != subscribers.end()) { - auto& handlers = handlers_it->second; - for (auto& handler : handlers) { - if (handler->exec(*event)) { - event_it = events_queue.erase(event_it); + 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; } @@ -46,5 +44,3 @@ void EventManager::dispatch_events() { } } } - - diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index 9b69b29..d3a14da 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -1,18 +1,18 @@ #pragma once + #include #include #include #include -#include #include #include + #include "Event.h" #include "EventHandler.h" -//#include "keyCodes.h" /** - * @class EventManager - * @brief The EventManager class is responsible for managing the subscription, triggering, + * \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. */ class EventManager { @@ -23,16 +23,16 @@ public: EventManager(const EventManager &) = delete; /** - * @brief Deleted copy assignment operator to prevent assignment of the EventManager instance. + * \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. + * \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. + * \return Reference to the EventManager instance. */ static EventManager & get_instance() { static EventManager instance; @@ -40,56 +40,56 @@ public: } /** - * @brief Subscribe to an event. + * \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). + * \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). */ template void subscribe(EventHandler && callback, int channel = 0); /** - * @brief Unsubscribe from an event. + * \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 eventId The event ID to unsubscribe from. + * \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 - void unsubscribe(const EventHandler &, int eventId); + void unsubscribe(const EventHandler &, int channel); /** - * @brief Trigger an event. + * \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). + * \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). */ template void trigger_event(const EventType & event, int channel); /** - * @brief Queue an event for later processing. + * \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). + * \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). */ template void queue_event(EventType&& event, int channel); /** - * @brief Dispatch all queued events. + * \brief Dispatch all queued events. * * This method processes all events in the event queue and triggers the corresponding * callbacks for each event. @@ -98,7 +98,7 @@ public: private: /** - * @brief Default constructor for the EventManager. + * \brief Default constructor for the EventManager. * * This constructor is private to enforce the singleton pattern. */ @@ -118,7 +118,7 @@ void EventManager::subscribe(EventHandler && callback, int channel) { std::unique_ptr> handler = std::make_unique>(callback); if (channel) { - std::unordered_map>>& handlers_map = subscribers_by_event_id[event_type]; + 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)); @@ -126,7 +126,7 @@ void EventManager::subscribe(EventHandler && callback, int channel) { handlers_map[channel].emplace_back(std::move(handler)); } } else { - std::vector>& handlers = subscribers[event_type]; + std::vector>& handlers = this->subscribers[event_type]; handlers.emplace_back(std::move(handler)); } } @@ -142,22 +142,23 @@ void EventManager::queue_event(EventType&& event, int channel) { channel, event_type ); - events_queue.push_back(std::move(tuple)); + this->events_queue.push_back(std::move(tuple)); } template -void EventManager::trigger_event(const EventType & event, int eventId) { +void EventManager::trigger_event(const EventType & event, int channel) { std::type_index event_type = std::type_index(typeid(EventType)); - if (eventId > 0) { + if (channel > 0) { std::unordered_map>>& handlers_map = subscribers_by_event_id[event_type]; - std::unordered_map>>::iterator handlers_it = handlers_map.find(eventId); + std::unordered_map>>::iterator handlers_it = handlers_map.find(channel); if (handlers_it != handlers_map.end()) { - std::vector>& callbacks = handlers_it->second; - for (std::vector>::iterator it = callbacks.begin(); it != callbacks.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 = callbacks.erase(it); + it = handlers.erase(it); } else { ++it; } @@ -165,8 +166,13 @@ void EventManager::trigger_event(const EventType & event, int eventId) { } } else { std::vector>& handlers = subscribers[event_type]; - for (std::vector>::iterator it = handlers.begin(); it != handlers.end(); ++it) { - (*it)->exec(event); + 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; + } } } } @@ -177,8 +183,8 @@ void EventManager::unsubscribe(const EventHandler & callback, int cha std::string handler_name = callback.target_type().name(); if (channel) { - std::unordered_map>>>::iterator subscriber_list = subscribers_by_event_id.find(event_type); - if (subscriber_list != subscribers_by_event_id.end()) { + 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()) { @@ -192,8 +198,8 @@ void EventManager::unsubscribe(const EventHandler & callback, int cha } } } else { - std::unordered_map>>::iterator handlers_it = subscribers.find(event_type); - if (handlers_it != subscribers.end()) { + 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) { diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index 3a06f77..17d8735 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -2,41 +2,44 @@ #include IKeyListener::IKeyListener(){ this->channel = channel; - subscribe_events(); + this->subscribe_events(); } IKeyListener::IKeyListener(int channel){ this->channel = channel; - subscribe_events(channel); + this->subscribe_events(); } IKeyListener::~IKeyListener() { - unsubscribe_events(); + this->unsubscribe_events(); } -void IKeyListener::subscribe_events(int listenerId) { +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(key_pressed_handler), listenerId); - EventManager::get_instance().subscribe(std::move(key_released_handler), listenerId); + 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(int listenerId) { - EventManager::get_instance().unsubscribe(key_pressed_handler , listenerId); - EventManager::get_instance().unsubscribe(key_released_handler , listenerId); +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; } -void IKeyListener::activate_keys(int listenerId) { +void IKeyListener::activate_keys() { if(this->active){ return; } - subscribe_events(listenerId); + this->subscribe_events(); } void IKeyListener::deactivate_keys() { if(!this->active){ return; } - unsubscribe_events(); + this->unsubscribe_events(); +} +void IKeyListener::set_channel(int channel){ + this->channel = channel; } diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index 83949bf..6d7915d 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -2,24 +2,77 @@ #include "Event.h" #include "EventHandler.h" #include "EventManager.h" + +/** + * \class IKeyListener + * \brief Interface for keyboard event handling in the application. + */ class IKeyListener { public: - IKeyListener(int channel); - IKeyListener(); + /** + * \brief Constructs an IKeyListener with a specified channel. + * \param channel The channel ID for event handling. + */ + IKeyListener(int channel); + + /** + * \brief Default constructor for IKeyListener. + */ + IKeyListener(); + + /** + * \brief Destructor. + */ virtual ~IKeyListener(); - virtual bool on_key_pressed(const KeyPressEvent & event) = 0; - virtual bool on_key_released(const KeyReleaseEvent & event) = 0; - void activate_keys(int listenerId = 0); + + /** + * \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; + + /** + * \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; + + /** + * \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: - void subscribe_events(int listenerId = 0); - void unsubscribe_events(int listenerId = 0); - + /** + * \brief Subscribes to key events. + */ + void subscribe_events(); + + /** + * \brief Unsubscribes from key events. + */ + void unsubscribe_events(); private: - bool active = true; - int channel = 0; - EventHandler key_pressed_handler; - EventHandler key_released_handler; + //! Indicates whether key listening is active. + bool active = true; + //! Channel ID for event handling. + int channel = 0; + //! Key press event handler. + EventHandler key_pressed_handler; + //!< Key release event handler. + EventHandler key_released_handler; }; diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index bb59664..68061be 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -1,12 +1,15 @@ #include "IMouseListener.h" +IMouseListener::IMouseListener(int channel){ + this->channel = channel; +} IMouseListener::IMouseListener(){ - subscribe_events(); + this->subscribe_events(); } IMouseListener::~IMouseListener() { - unsubscribe_events(); + this->unsubscribe_events(); } -void IMouseListener::subscribe_events(int listenerId) { +void IMouseListener::subscribe_events() { // Define handler lambdas and subscribe them mouse_click_handler = [this](const MouseClickEvent& event) { return this->on_mouse_clicked(event); @@ -20,15 +23,30 @@ void IMouseListener::subscribe_events(int listenerId) { mouse_move_handler = [this](const MouseMoveEvent& event) { return this->on_mouse_moved(event); }; - 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); - EventManager::get_instance().subscribe(std::move(mouse_move_handler), listenerId); + 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(int 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); +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_keys() { + if(this->active){ + return; + } + this->subscribe_events(); +} +void IMouseListener::deactivate_keys() { + if(!this->active){ + return; + } + this->unsubscribe_events(); +} +void IMouseListener::set_channel(int channel){ + this->channel = channel; } diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 1078257..4493e7f 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -1,25 +1,117 @@ #pragma once + #include "Event.h" #include "EventHandler.h" #include "EventManager.h" +/** + * \class IMouseListener + * \brief Interface for mouse event handling in the application. + */ class IMouseListener { public: - IMouseListener(); + /** + * \brief Default constructor. + */ + IMouseListener(); + + /** + * \brief Constructs an IMouseListener with a specified channel. + * \param channel The channel ID for event handling. + */ + IMouseListener(int channel); + + /** + * \brief Destructor. + */ virtual ~IMouseListener(); - virtual bool on_mouse_clicked(const MouseClickEvent & event) = 0; - virtual bool on_mouse_pressed(const MousePressEvent & event) = 0; - virtual bool on_mouse_released(const MouseReleaseEvent & event) = 0; - virtual bool on_mouse_moved(const MouseMoveEvent & event) = 0; + /** + * \brief Copy constructor (deleted). + */ + IMouseListener(const IMouseListener&) = delete; + + /** + * \brief Copy assignment operator (deleted). + */ + IMouseListener& operator=(const IMouseListener&) = delete; + + /** + * \brief Move constructor (deleted). + */ + IMouseListener(IMouseListener&&) = delete; + + /** + * \brief Move assignment operator (deleted). + */ + 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; + + /** + * \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; + + /** + * \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; + + /** + * \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; + + /** + * \brief Activates mouse listening. + */ + void activate_keys(); + + /** + * \brief Deactivates mouse 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: - void subscribe_events(int listenerId = 0); - void unsubscribe_events(int listenerId = 0); + /** + * \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: - EventHandler mouse_click_handler; - EventHandler mouse_press_handler; - EventHandler mouse_release_handler; - EventHandler mouse_move_handler; + //! Indicates whether mouse listening is active. + bool active = true; + //! Channel ID for event handling. + int channel = 0; + //! Mouse click event handler. + EventHandler mouse_click_handler; + //! Mouse press event handler. + EventHandler mouse_press_handler; + //! Mouse release event handler. + EventHandler mouse_release_handler; + //! Mouse move event handler. + EventHandler mouse_move_handler; }; diff --git a/src/example/events.cpp b/src/example/events.cpp index 1f757e1..1a29d80 100644 --- a/src/example/events.cpp +++ b/src/example/events.cpp @@ -73,14 +73,11 @@ int main() { 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; - // 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(); -- cgit v1.2.3 From ab69e41cabd6f5a84ebb2e2629d194b49b7039de Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Wed, 13 Nov 2024 12:22:17 +0100 Subject: added some extra comments --- src/crepe/api/EventHandler.h | 2 +- src/example/events.cpp | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/crepe/api/EventHandler.h b/src/crepe/api/EventHandler.h index 5b9ac0d..dc06806 100644 --- a/src/crepe/api/EventHandler.h +++ b/src/crepe/api/EventHandler.h @@ -8,7 +8,7 @@ * \brief A type alias for an event handler function. * * The EventHandler is a std::function that takes an EventType reference and returns a boolean value - * indicating whether the event was successfully handled. + * indicating whether the event is handled. * * \tparam EventType The type of event this handler will handle. */ diff --git a/src/example/events.cpp b/src/example/events.cpp index 1a29d80..af5f747 100644 --- a/src/example/events.cpp +++ b/src/example/events.cpp @@ -91,13 +91,12 @@ int main() { return false; }; 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); + // dispatching queued events EventManager::get_instance().dispatch_events(); - + EventManager::get_instance().unsubscribe(event_handler,0); return EXIT_SUCCESS; } -- cgit v1.2.3 From f1ba2a5607f23ed0b23d74240ea66cb1f8d2c1ad Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Wed, 13 Nov 2024 12:28:04 +0100 Subject: tested channel and deactivating in function --- src/crepe/api/IKeyListener.cpp | 3 +++ src/crepe/api/IMouseListener.cpp | 6 ++++-- src/crepe/api/IMouseListener.h | 4 ++-- src/example/events.cpp | 9 +++++---- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index 17d8735..e759eca 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -41,5 +41,8 @@ void IKeyListener::deactivate_keys() { this->unsubscribe_events(); } void IKeyListener::set_channel(int channel){ + this->unsubscribe_events(); this->channel = channel; + this->subscribe_events(); + } diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index 68061be..c6ea419 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -35,18 +35,20 @@ void IMouseListener::unsubscribe_events() { EventManager::get_instance().unsubscribe(this->mouse_release_handler, this->channel); EventManager::get_instance().unsubscribe(this->mouse_move_handler, this->channel); } -void IMouseListener::activate_keys() { +void IMouseListener::activate_mouse() { if(this->active){ return; } this->subscribe_events(); } -void IMouseListener::deactivate_keys() { +void IMouseListener::deactivate_mouse() { if(!this->active){ return; } this->unsubscribe_events(); } 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 4493e7f..a7ad271 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -77,12 +77,12 @@ public: /** * \brief Activates mouse listening. */ - void activate_keys(); + void activate_mouse(); /** * \brief Deactivates mouse listening. */ - void deactivate_keys(); + void deactivate_mouse(); /** * \brief Sets the channel ID for event handling. diff --git a/src/example/events.cpp b/src/example/events.cpp index af5f747..ff97cf1 100644 --- a/src/example/events.cpp +++ b/src/example/events.cpp @@ -25,6 +25,7 @@ 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{ @@ -74,7 +75,7 @@ int main() { 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(); @@ -82,8 +83,8 @@ int main() { sys.update(); // Trigger the events while `testListener` is in scope - EventManager::get_instance().trigger_event(key_press, 0); - EventManager::get_instance().trigger_event(click_event, 0); + 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) { @@ -96,7 +97,7 @@ int main() { 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; } -- cgit v1.2.3 From e4b3162d28a635af37dd7ca1f71db16e0d196864 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Wed, 13 Nov 2024 12:33:16 +0100 Subject: moved get_instance --- src/crepe/api/EventManager.cpp | 5 +++++ src/crepe/api/EventManager.h | 9 +++------ src/example/events.cpp | 3 ++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index 872c6eb..42bff12 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -1,5 +1,10 @@ #include "EventManager.h" +EventManager & EventManager::get_instance() { + static EventManager instance; + return 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); diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index d3a14da..b963ce3 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -34,10 +34,7 @@ public: * * \return Reference to the EventManager instance. */ - static EventManager & get_instance() { - static EventManager instance; - return instance; - } + static EventManager & get_instance(); /** * \brief Subscribe to an event. @@ -150,7 +147,7 @@ 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 = subscribers_by_event_id[event_type]; + 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()) { @@ -165,7 +162,7 @@ void EventManager::trigger_event(const EventType & event, int channel) { } } } else { - std::vector>& handlers = subscribers[event_type]; + 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)) { diff --git a/src/example/events.cpp b/src/example/events.cpp index ff97cf1..af6f294 100644 --- a/src/example/events.cpp +++ b/src/example/events.cpp @@ -9,13 +9,14 @@ #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 -- 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 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(-) 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 032f8560b91b76cad5f32a6a9ebfc0ac845ed69a Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Thu, 14 Nov 2024 10:37:57 +0100 Subject: forget a doxygen docs on a function --- src/crepe/system/RenderSystem.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 468f79b..6a87eec 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -57,6 +57,12 @@ private: */ bool render_particle(const Sprite &, const Transform & tm); + /** + * \brief renders a sprite with a Transform component on the screen + * + * \param sprite the sprite component that holds all the data + * \param tm the Transform component that holds the position,rotation and scale + */ void render_normal(const Sprite &, const Transform & tm); /** -- cgit v1.2.3 From d6c48b5b955336f7e2832bae7b7eca4afdb02cc4 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Thu, 14 Nov 2024 13:42:35 +0100 Subject: removed unwanted files --- .vscode/launch.json | 7 ------- .vscode/tasks.json | 28 ---------------------------- 2 files changed, 35 deletions(-) delete mode 100644 .vscode/launch.json delete mode 100644 .vscode/tasks.json diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 5c7247b..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - // 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 deleted file mode 100644 index 05054c5..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "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 -- cgit v1.2.3 From 21f5b66d0bcc13d903800adf3bb614e380ff8591 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Thu, 14 Nov 2024 15:01:26 +0100 Subject: first part sorted still needing testing --- src/crepe/system/RenderSystem.cpp | 35 ++++++++++++++++++++++++++++++----- src/crepe/system/RenderSystem.h | 8 +++++++- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 10211a3..718036c 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include @@ -6,6 +8,7 @@ #include "../api/Transform.h" #include "../facade/SDLContext.h" #include "../util/log.h" +#include "Asset.h" #include "RenderSystem.h" @@ -29,7 +32,6 @@ void RenderSystem::present_screen() const { } void RenderSystem::update_camera() { ComponentManager & mgr = ComponentManager::get_instance(); - std::vector> cameras = mgr.get_components_by_type(); @@ -38,15 +40,38 @@ void RenderSystem::update_camera() { this->curr_cam = &cam; } } -void RenderSystem::render_sprites() const { + +std::vector> +RenderSystem::sort(std::vector> & objs) { + if (objs.empty()) return {}; + + std::vector> sorted_objs; + sorted_objs.insert(sorted_objs.end(), objs.begin(), objs.end()); + assert(sorted_objs.size() != objs.size()); + + std::sort(sorted_objs.begin(), sorted_objs.end(), + [](const std::reference_wrapper & a, + const std::reference_wrapper & b) { + const Sprite & sprite_a = a.get(); + const Sprite & sprite_b = b.get(); + if (sprite_a.sorting_in_layer == sprite_b.sorting_in_layer) { + return sprite_a.order_in_layer < sprite_b.order_in_layer; + } + return sprite_a.sorting_in_layer < sprite_b.sorting_in_layer; + }); + return sorted_objs; +} + +void RenderSystem::render_sprites() { ComponentManager & mgr = ComponentManager::get_instance(); - std::vector> sprites - = mgr.get_components_by_type(); + auto sprites = mgr.get_components_by_type(); + auto sorted_sprites = this->sort(sprites); + SDLContext & render = SDLContext::get_instance(); - for (const Sprite & sprite : sprites) { + for (const Sprite & sprite : sorted_sprites) { auto transforms = mgr.get_components_by_id(sprite.game_object_id); render.draw(sprite, transforms[0], *curr_cam); diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 70db21a..a83633a 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -3,6 +3,9 @@ #include "api/Camera.h" #include "System.h" +#include "api/Sprite.h" +#include +#include namespace crepe { @@ -44,7 +47,10 @@ private: void update_camera(); //! Renders all active sprites to the screen. - void render_sprites() const; + void render_sprites() ; + + std::vector> + sort(std::vector> & objs); /** * \todo Include color handling for sprites. -- cgit v1.2.3 From e25aa67c4263b3a940ae9e92f2fcd31a4486f407 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Thu, 14 Nov 2024 20:18:19 +0100 Subject: adjusted based on feedback of PR#31 --- src/crepe/facade/SDLContext.cpp | 33 +++++++++++---------------------- src/crepe/facade/SDLContext.h | 9 ++------- src/crepe/system/RenderSystem.cpp | 6 +++--- src/crepe/system/RenderSystem.h | 6 ++++++ 4 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index cacf238..febbe4b 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -7,10 +7,9 @@ #include #include #include -#include #include +#include #include -#include #include "../api/Sprite.h" #include "../api/Texture.h" @@ -32,31 +31,23 @@ SDLContext::SDLContext() { // FIXME: read window defaults from config manager if (SDL_Init(SDL_INIT_VIDEO) < 0) { - // FIXME: throw exception - std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() - << std::endl; - return; + throw std::runtime_error("SDL could not initialize!"); } + SDL_Window * tmp_window = SDL_CreateWindow( "Crepe Game Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, this->viewport.w, this->viewport.h, 0); if (!tmp_window) { - // FIXME: throw exception - std::cerr << "Window could not be created! SDL_Error: " - << SDL_GetError() << std::endl; - return; + throw std::runtime_error("Window could not be created!"); } + this->game_window = {tmp_window, [](SDL_Window * window) { SDL_DestroyWindow(window); }}; SDL_Renderer * tmp_renderer = SDL_CreateRenderer( this->game_window.get(), -1, SDL_RENDERER_ACCELERATED); if (!tmp_renderer) { - // FIXME: throw exception - std::cerr << "Renderer could not be created! SDL_Error: " - << SDL_GetError() << std::endl; - SDL_DestroyWindow(this->game_window.get()); - return; + throw std::runtime_error("Renderer could not be created!"); } this->game_renderer = {tmp_renderer, [](SDL_Renderer * renderer) { @@ -65,9 +56,7 @@ SDLContext::SDLContext() { int img_flags = IMG_INIT_PNG; if (!(IMG_Init(img_flags) & img_flags)) { - // FIXME: throw exception - std::cout << "SDL_image could not initialize! SDL_image Error: " - << IMG_GetError() << std::endl; + throw std::runtime_error("SDL_image could not initialize!"); } } @@ -145,8 +134,8 @@ void SDLContext::draw(const Sprite & sprite, const Transform & transform, void SDLContext::camera(const Camera & cam) { this->viewport.w = static_cast(cam.aspect_width); this->viewport.h = static_cast(cam.aspect_height); - this->viewport.x = static_cast(cam.x) - (SCREEN_WIDTH / 2); - this->viewport.y = static_cast(cam.y) - (SCREEN_HEIGHT / 2); + this->viewport.x = static_cast(cam.x) - (this->viewport.w / 2); + this->viewport.y = static_cast(cam.y) - (this->viewport.h / 2); SDL_SetRenderDrawColor(this->game_renderer.get(), cam.bg_color.r, cam.bg_color.g, cam.bg_color.b, cam.bg_color.a); @@ -181,12 +170,12 @@ SDLContext::texture_from_path(const std::string & path) { return img_texture; } -int SDLContext::get_width(const Texture & ctx) { +int SDLContext::get_width(const Texture & ctx) const { int w; SDL_QueryTexture(ctx.texture.get(), NULL, NULL, &w, NULL); return w; } -int SDLContext::get_height(const Texture & ctx) { +int SDLContext::get_height(const Texture & ctx) const { int h; SDL_QueryTexture(ctx.texture.get(), NULL, NULL, NULL, &h); return h; diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index c4392bd..0614036 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -10,11 +10,6 @@ #include "../api/Sprite.h" #include "../api/Transform.h" #include "api/Camera.h" -#include "api/Vector2.h" - -// FIXME: this needs to be removed -const int SCREEN_WIDTH = 640; -const int SCREEN_HEIGHT = 480; namespace crepe { @@ -109,14 +104,14 @@ private: * \param texture Reference to the Texture object. * \return Width of the texture as an integer. */ - int get_width(const Texture &) ; + int get_width(const Texture &) const; /** * \brief Gets the height of a texture. * \param texture Reference to the Texture object. * \return Height of the texture as an integer. */ - int get_height(const Texture &) ; + int get_height(const Texture &) const; private: //! Will use draw,clear_screen, present_screen, camera. diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 17a2337..6ecd604 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -85,13 +85,13 @@ void RenderSystem::render() { auto sprites = mgr.get_components_by_type(); for (const Sprite & sprite : sprites) { if (!sprite.active) continue; - auto transform = mgr.get_components_by_id(sprite.game_object_id); + auto transform = mgr.get_components_by_id(sprite.game_object_id).front().get(); - bool rendered_particles = this->render_particle(sprite, transform[0].get()); + bool rendered_particles = this->render_particle(sprite, transform); if (rendered_particles) continue; - this->render_normal(sprite, transform[0].get()); + this->render_normal(sprite, transform); } } diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 6a87eec..3d6286f 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -31,6 +31,12 @@ public: */ void update() override; + + RenderSystem(const RenderSystem &) = delete; + RenderSystem(RenderSystem &&) = delete; + RenderSystem & operator=(const RenderSystem &) = delete; + RenderSystem & operator=(RenderSystem &&) = delete; + private: // Private constructor to enforce singleton pattern. RenderSystem(); -- cgit v1.2.3 From ed1403aea4412bd479244eae8e2940190e71cd28 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Fri, 15 Nov 2024 09:48:04 +0100 Subject: example --- src/example/rendering_particle.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/example/rendering_particle.cpp b/src/example/rendering_particle.cpp index dd08354..33013ef 100644 --- a/src/example/rendering_particle.cpp +++ b/src/example/rendering_particle.cpp @@ -22,14 +22,14 @@ using namespace std; int main(int argc, char * argv[]) { GameObject game_object(0, "", "", Vector2{100, 100}, 0, 0.1); - Color color(0, 0, 0, 0); + Color color(255, 255, 255, 255); Sprite test_sprite = game_object.add_component( make_shared("../asset/texture/img.png"), color, FlipSettings{false, false}); game_object.add_component(ParticleEmitter::Data{ .position = {0, 0}, .max_particles = 10, - .emission_rate = 0.5, + .emission_rate = 0.1, .min_speed = 6, .max_speed = 20, .min_angle = -20, -- 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 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 337a957a9e605f16287506b6afda56950e562db3 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Fri, 15 Nov 2024 12:50:30 +0100 Subject: events example working --- src/example/events.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/example/events.cpp b/src/example/events.cpp index 9c59bb7..ed519ff 100644 --- a/src/example/events.cpp +++ b/src/example/events.cpp @@ -89,12 +89,11 @@ int main() { // Trigger the events while `testListener` is in scope EventManager::get_instance().trigger_event(key_press, 1); - // EventManager::get_instance().trigger_event(MouseClickEvent{ - // .button = MouseButton::LEFT_MOUSE, - // .mouse_y = 100, - // .mouse_x = 100, - - // },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 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 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(-) 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 8209678e20605936b2ce58331c1a65d8f23fee91 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Sat, 16 Nov 2024 15:26:48 +0100 Subject: make format --- src/crepe/api/EventManager.cpp | 13 +- src/crepe/api/EventManager.h | 2 +- src/crepe/api/EventManager.hpp | 15 +- src/crepe/api/IKeyListener.cpp | 72 ++++---- src/crepe/api/IKeyListener.h | 4 +- src/crepe/api/IMouseListener.cpp | 40 ++-- src/crepe/api/IMouseListener.h | 4 +- src/crepe/api/KeyCodes.h | 386 +++++++++++++++++++++------------------ 8 files changed, 295 insertions(+), 241 deletions(-) diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index a04f08b..7f47938 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -8,10 +8,12 @@ EventManager & EventManager::get_instance() { } void EventManager::dispatch_events() { - using HandlersMap = std::unordered_map>>; + using HandlersMap = std::unordered_map< + int, std::vector>>; using HandlersVec = std::vector>; - for (auto event_it = this->events_queue.begin(); event_it != this->events_queue.end();) { + 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); @@ -25,7 +27,8 @@ void EventManager::dispatch_events() { auto handlers = handlers_map.find(channel); if (handlers != handlers_map.end()) { HandlersVec & callbacks = handlers->second; - for (auto handler_it = callbacks.begin(); handler_it != callbacks.end(); ++handler_it) { + 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; @@ -39,7 +42,8 @@ void EventManager::dispatch_events() { auto handlers_it = this->subscribers.find(event_type); if (handlers_it != this->subscribers.end()) { HandlersVec & handlers = handlers_it->second; - for (auto handler_it = handlers.begin(); handler_it != handlers.end(); ++handler_it) { + 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); @@ -55,4 +59,3 @@ void EventManager::dispatch_events() { } } } - diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index 1ff4031..783db62 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -11,7 +11,7 @@ #include "EventHandler.h" namespace crepe { - + /** * \class EventManager * \brief The EventManager class is responsible for managing the subscription, triggering, diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp index 1e505f4..d901492 100644 --- a/src/crepe/api/EventManager.hpp +++ b/src/crepe/api/EventManager.hpp @@ -4,7 +4,8 @@ namespace crepe { template void EventManager::subscribe(EventHandler && callback, int channel) { - using HandlersMap = std::unordered_map>>; + using HandlersMap = std::unordered_map< + int, std::vector>>; using HandlersVec = std::vector>; std::type_index event_type = typeid(EventType); @@ -29,7 +30,8 @@ template void EventManager::queue_event(EventType && event, int channel) { std::type_index event_type = std::type_index(typeid(EventType)); - auto 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); @@ -38,7 +40,8 @@ void EventManager::queue_event(EventType && event, int channel) { template void EventManager::trigger_event(const EventType & event, int channel) { - using HandlersMap = std::unordered_map>>; + using HandlersMap = std::unordered_map< + int, std::vector>>; using HandlersVec = std::vector>; std::type_index event_type = std::type_index(typeid(EventType)); @@ -68,8 +71,10 @@ void EventManager::trigger_event(const EventType & event, int channel) { } template -void EventManager::unsubscribe(const EventHandler & callback, int channel) { - using HandlersMap = std::unordered_map>>; +void EventManager::unsubscribe(const EventHandler & callback, + int channel) { + using HandlersMap = std::unordered_map< + int, std::vector>>; using HandlersVec = std::vector>; std::type_index event_type(typeid(EventType)); diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index 81d30b8..cd255df 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -3,64 +3,68 @@ using namespace crepe; // Constructor with default channel -IKeyListener::IKeyListener() : channel(0), active(true), event_manager(EventManager::get_instance()) { - this->subscribe_events(); +IKeyListener::IKeyListener() + : channel(0), + active(true), + event_manager(EventManager::get_instance()) { + this->subscribe_events(); } // Constructor with specified channel -IKeyListener::IKeyListener(int channel) : channel(channel), active(true), event_manager(EventManager::get_instance()) { - this->subscribe_events(); +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); - }; + 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); + 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() { - event_manager.unsubscribe( - this->key_pressed_handler, this->channel); - event_manager.unsubscribe( - this->key_released_handler, this->channel); + 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->active = true; - 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->active = false; - 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 77fbf1e..e170120 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -5,7 +5,7 @@ #include "EventManager.h" namespace crepe { - + /** * \class IKeyListener * \brief Interface for keyboard event handling in the application. @@ -78,7 +78,7 @@ private: EventHandler key_pressed_handler; //!< Key release event handler. EventHandler key_released_handler; - EventManager& event_manager; + EventManager & event_manager; }; } // namespace crepe diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index f49004a..bfa49f8 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -2,19 +2,17 @@ using namespace crepe; -IMouseListener::IMouseListener(int channel) - : event_manager(EventManager::get_instance()), channel(channel) { - this->subscribe_events(); +IMouseListener::IMouseListener(int channel) + : event_manager(EventManager::get_instance()), + channel(channel) { + this->subscribe_events(); } -IMouseListener::IMouseListener() - : event_manager(EventManager::get_instance()) { - 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 @@ -32,18 +30,26 @@ void IMouseListener::subscribe_events() { }; // 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); + 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); } void IMouseListener::unsubscribe_events() { // 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); + 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() { diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 3b9e317..37d2f00 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -5,7 +5,7 @@ #include "EventManager.h" namespace crepe { - + /** * \class IMouseListener * \brief Interface for mouse event handling in the application. @@ -116,7 +116,7 @@ private: EventHandler mouse_release_handler; //! Mouse move event handler. EventHandler mouse_move_handler; - EventManager& event_manager; + EventManager & event_manager; }; } //namespace crepe diff --git a/src/crepe/api/KeyCodes.h b/src/crepe/api/KeyCodes.h index a326527..feed0b2 100644 --- a/src/crepe/api/KeyCodes.h +++ b/src/crepe/api/KeyCodes.h @@ -1,186 +1,222 @@ #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 { - //! 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 + //! 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 { - //! 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 + //! 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 }; -- cgit v1.2.3 From c9aac3ea385213b7b9a9a4e7e48e45e6a1268902 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Mon, 18 Nov 2024 15:03:39 +0100 Subject: working sorting --- src/crepe/system/RenderSystem.cpp | 37 +++++++++++++++++++------------------ src/example/rendering.cpp | 25 +++++++++++++++++++++---- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index aa9910b..ba804d4 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -1,13 +1,13 @@ #include #include #include +#include #include #include "../ComponentManager.h" #include "../api/Sprite.h" #include "../api/Transform.h" #include "../facade/SDLContext.h" -#include "../util/Log.h" #include "RenderSystem.h" @@ -27,38 +27,39 @@ void RenderSystem::update_camera() { } } +bool sorting_comparison(const Sprite & a, const Sprite & b) { + if (a.sorting_in_layer > b.sorting_in_layer) return true; + if (a.sorting_in_layer == b.sorting_in_layer) return a.order_in_layer > b.order_in_layer; + + return false; +} + std::vector> RenderSystem::sort(std::vector> & objs) { if (objs.empty()) return {}; - std::vector> sorted_objs; - sorted_objs.insert(sorted_objs.end(), objs.begin(), objs.end()); - assert(sorted_objs.size() != objs.size()); - - std::sort(sorted_objs.begin(), sorted_objs.end(), - [](const std::reference_wrapper & a, - const std::reference_wrapper & b) { - const Sprite & sprite_a = a.get(); - const Sprite & sprite_b = b.get(); - if (sprite_a.sorting_in_layer == sprite_b.sorting_in_layer) { - return sprite_a.order_in_layer < sprite_b.order_in_layer; - } - return sprite_a.sorting_in_layer < sprite_b.sorting_in_layer; - }); + std::vector> sorted_objs(objs); + std::sort(sorted_objs.begin(), sorted_objs.end(), sorting_comparison); + return sorted_objs; } void RenderSystem::render_sprites() { ComponentManager & mgr = this->component_manager; - ComponentManager & mgr = ComponentManager::get_instance(); - auto sprites = mgr.get_components_by_type(); + for (const Sprite & s : sprites) { + std::cout << s.game_object_id << " " << unsigned(s.sorting_in_layer) << " " + << unsigned(s.order_in_layer) << std::endl; + } + auto sorted_sprites = this->sort(sprites); - + SDLContext & render = SDLContext::get_instance(); for (const Sprite & sprite : sorted_sprites) { + std::cout << sprite.game_object_id << " " << unsigned(sprite.sorting_in_layer) << " " + << unsigned(sprite.order_in_layer) << std::endl; auto transforms = mgr.get_components_by_id(sprite.game_object_id); render.draw(sprite, transforms[0], *curr_cam); } diff --git a/src/example/rendering.cpp b/src/example/rendering.cpp index c9e62f1..ecd3f6a 100644 --- a/src/example/rendering.cpp +++ b/src/example/rendering.cpp @@ -30,14 +30,27 @@ int main() { // Normal adding components { Color color(0, 0, 0, 0); - obj.add_component(make_shared("../asset/texture/img.png"), color, - FlipSettings{false, false}); + Sprite & sprite + = obj.add_component(make_shared("../asset/texture/img.png"), + color, FlipSettings{false, false}); + sprite.sorting_in_layer = 2; + sprite.order_in_layer = 1; obj.add_component(Color::get_red()); } { Color color(0, 0, 0, 0); - obj1.add_component(make_shared("../asset/texture/second.png"), color, - FlipSettings{true, true}); + Sprite & sprite = obj1.add_component( + make_shared("../asset/texture/img.png"), color, FlipSettings{true, true}); + sprite.sorting_in_layer = 2; + sprite.order_in_layer = 2; + } + + { + Color color(0, 0, 0, 0); + Sprite & sprite = obj2.add_component( + make_shared("../asset/texture/img.png"), color, FlipSettings{true, true}); + sprite.sorting_in_layer = 1; + sprite.order_in_layer = 2; } /* @@ -48,8 +61,12 @@ int main() { } */ + sys.update(); + /* + auto start = std::chrono::steady_clock::now(); while (std::chrono::steady_clock::now() - start < std::chrono::seconds(5)) { sys.update(); } + */ } -- cgit v1.2.3 From bae2501c9e2604497db152d5e3df6a018cdd6858 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Mon, 18 Nov 2024 15:04:36 +0100 Subject: removed iostream & printing --- src/crepe/system/RenderSystem.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index ba804d4..bf5dade 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include "../ComponentManager.h" @@ -48,18 +47,10 @@ void RenderSystem::render_sprites() { ComponentManager & mgr = this->component_manager; auto sprites = mgr.get_components_by_type(); - - for (const Sprite & s : sprites) { - std::cout << s.game_object_id << " " << unsigned(s.sorting_in_layer) << " " - << unsigned(s.order_in_layer) << std::endl; - } - auto sorted_sprites = this->sort(sprites); SDLContext & render = SDLContext::get_instance(); for (const Sprite & sprite : sorted_sprites) { - std::cout << sprite.game_object_id << " " << unsigned(sprite.sorting_in_layer) << " " - << unsigned(sprite.order_in_layer) << std::endl; auto transforms = mgr.get_components_by_id(sprite.game_object_id); render.draw(sprite, transforms[0], *curr_cam); } -- cgit v1.2.3 From 74fcf733c2bcdcbcbfc64d88270b12a39e9d91e0 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Mon, 18 Nov 2024 15:18:20 +0100 Subject: merged master --- src/crepe/system/RenderSystem.cpp | 18 +++++++----------- src/crepe/system/RenderSystem.h | 2 +- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 23ab738..37320ed 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -6,11 +6,9 @@ #include "../api/Sprite.h" #include "../api/Transform.h" #include "../facade/SDLContext.h" -#include "../util/log.h" #include "../api/ParticleEmitter.h" #include "../api/Vector2.h" -#include "Particle.h" #include "RenderSystem.h" using namespace crepe; @@ -30,17 +28,15 @@ void RenderSystem::update_camera() { } bool RenderSystem::render_particle(const Sprite & sprite, - const Transform & tm) { + Transform tm) { - ComponentManager & mgr = ComponentManager::get_instance(); + ComponentManager & mgr = this->component_manager; SDLContext & render = SDLContext::get_instance(); auto emitters = mgr.get_components_by_id(sprite.game_object_id); bool rendering_particles = false; - Transform tmp(0, Vector2{0, 0}, 0, 0); - tmp.scale = tm.scale; for (const ParticleEmitter & em : emitters) { if (!em.active) continue; if (!(em.data.sprite.game_object_id == sprite.game_object_id)) continue; @@ -49,16 +45,16 @@ bool RenderSystem::render_particle(const Sprite & sprite, for (const Particle & p : em.data.particles) { if (!p.active) continue; - tmp.position = p.position; - tmp.rotation = p.angle; - render.draw(em.data.sprite, tmp, *curr_cam); + tm.position = p.position; + tm.rotation = p.angle; + render.draw(em.data.sprite, tm, *curr_cam); } } return rendering_particles; } void RenderSystem::render_normal(const Sprite & sprite, const Transform & tm) { - ComponentManager & mgr = ComponentManager::get_instance(); + ComponentManager & mgr = this->component_manager; SDLContext & render = SDLContext::get_instance(); render.draw(sprite, tm, *curr_cam); @@ -66,7 +62,7 @@ void RenderSystem::render_normal(const Sprite & sprite, const Transform & tm) { void RenderSystem::render() { - ComponentManager & mgr = ComponentManager::get_instance(); + ComponentManager & mgr = this->component_manager; auto sprites = mgr.get_components_by_type(); for (const Sprite & sprite : sprites) { diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index ad44716..c18b80b 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -51,7 +51,7 @@ private: * \param tm the Transform component for scale * \return true if particles have been rendered */ - bool render_particle(const Sprite &, const Transform & tm); + bool render_particle(const Sprite &, Transform tm); /** * \brief renders a sprite with a Transform component on the screen -- cgit v1.2.3 From c323cc9026e787fae2e5303b0632b626ddc3daba Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Mon, 18 Nov 2024 15:32:44 +0100 Subject: removed some comments --- src/crepe/api/IKeyListener.h | 13 ++++--------- src/crepe/api/IMouseListener.h | 21 +-------------------- 2 files changed, 5 insertions(+), 29 deletions(-) diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index e170120..3e0e2cb 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -17,17 +17,12 @@ public: * \param channel The channel ID for event handling. */ IKeyListener(int channel); - - /** - * \brief Default constructor for IKeyListener. - */ IKeyListener(); - - /** - * \brief Destructor. - */ virtual ~IKeyListener(); - + IKeyListener(const IKeyListener &) = delete; + IKeyListener & operator=(const IKeyListener &) = delete; + IKeyListener(IKeyListener &&) = delete; + /** * \brief Pure virtual function to handle key press events. * \param event The key press event to handle. diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 37d2f00..2ec156f 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -12,35 +12,16 @@ namespace crepe { */ 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); - - /** - * \brief Destructor. - */ virtual ~IMouseListener(); - - /** - * \brief Copy constructor (deleted). - */ IMouseListener(const IMouseListener &) = delete; - - /** - * \brief Copy assignment operator (deleted). - */ IMouseListener & operator=(const IMouseListener &) = delete; - - /** - * \brief Move constructor (deleted). - */ IMouseListener(IMouseListener &&) = delete; /** -- cgit v1.2.3 From 8b449e764b5c91cd3cb0c4fa404a290ab295a7ef Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Mon, 18 Nov 2024 15:33:48 +0100 Subject: restored mwe/events to master --- mwe/events/include/event.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mwe/events/include/event.h b/mwe/events/include/event.h index e1b220b..16c75bf 100644 --- a/mwe/events/include/event.h +++ b/mwe/events/include/event.h @@ -20,7 +20,9 @@ public: \ static std::uint32_t typeID = UUIDGenerator::getUniqueID(); \ return typeID; \ } \ - virtual std::uint32_t getEventType() const override { return getStaticEventType(); } + virtual std::uint32_t getEventType() const override { \ + return getStaticEventType(); \ + } class Event { public: Event(std::string eventType); @@ -30,14 +32,16 @@ public: void addArgument(const std::string & key, const std::variant & value); - std::variant getArgument(const std::string & key) const; + std::variant + getArgument(const std::string & key) const; std::string getType() const; bool getHandled() const; void markHandled(); private: - std::unordered_map> eventData; + std::unordered_map> + eventData; bool isHandled = false; }; @@ -148,7 +152,7 @@ private: }; class ShutDownEvent : public Event { public: - ShutDownEvent() : Event("ShutDownEvent"){}; + ShutDownEvent() : Event("ShutDownEvent") {}; REGISTER_EVENT_TYPE(ShutDownEvent) -- cgit v1.2.3 From 71a614e1f87141c4d062a2a466377322fc3d9ff0 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Mon, 18 Nov 2024 15:40:11 +0100 Subject: make format --- mwe/events/include/event.h | 12 ++++-------- src/crepe/api/EventHandler.hpp | 3 +-- src/crepe/api/EventManager.cpp | 15 +++++++-------- src/crepe/api/EventManager.h | 9 +++------ src/crepe/api/EventManager.hpp | 22 ++++++++++----------- src/crepe/api/IKeyListener.cpp | 20 ++++++++------------ src/crepe/api/IKeyListener.h | 2 +- src/crepe/api/IMouseListener.cpp | 41 +++++++++++++++------------------------- src/crepe/api/IMouseListener.h | 1 - src/example/events.cpp | 17 +++++++---------- 10 files changed, 56 insertions(+), 86 deletions(-) diff --git a/mwe/events/include/event.h b/mwe/events/include/event.h index 16c75bf..e1b220b 100644 --- a/mwe/events/include/event.h +++ b/mwe/events/include/event.h @@ -20,9 +20,7 @@ public: \ static std::uint32_t typeID = UUIDGenerator::getUniqueID(); \ return typeID; \ } \ - virtual std::uint32_t getEventType() const override { \ - return getStaticEventType(); \ - } + virtual std::uint32_t getEventType() const override { return getStaticEventType(); } class Event { public: Event(std::string eventType); @@ -32,16 +30,14 @@ public: void addArgument(const std::string & key, const std::variant & value); - std::variant - getArgument(const std::string & key) const; + std::variant getArgument(const std::string & key) const; std::string getType() const; bool getHandled() const; void markHandled(); private: - std::unordered_map> - eventData; + std::unordered_map> eventData; bool isHandled = false; }; @@ -152,7 +148,7 @@ private: }; class ShutDownEvent : public Event { public: - ShutDownEvent() : Event("ShutDownEvent") {}; + ShutDownEvent() : Event("ShutDownEvent"){}; REGISTER_EVENT_TYPE(ShutDownEvent) diff --git a/src/crepe/api/EventHandler.hpp b/src/crepe/api/EventHandler.hpp index 564d3d7..9c47da2 100644 --- a/src/crepe/api/EventHandler.hpp +++ b/src/crepe/api/EventHandler.hpp @@ -7,8 +7,7 @@ namespace crepe { // Implementation of EventHandlerWrapper constructor template -EventHandlerWrapper::EventHandlerWrapper( - const EventHandler & handler) +EventHandlerWrapper::EventHandlerWrapper(const EventHandler & handler) : m_handler(handler), m_handler_type(m_handler.target_type().name()) {} diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index 7f47938..b465e89 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -8,12 +8,11 @@ EventManager & EventManager::get_instance() { } void EventManager::dispatch_events() { - using HandlersMap = std::unordered_map< - int, std::vector>>; + using HandlersMap + = std::unordered_map>>; using HandlersVec = std::vector>; - for (auto event_it = this->events_queue.begin(); - event_it != this->events_queue.end();) { + 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); @@ -27,8 +26,8 @@ void EventManager::dispatch_events() { auto handlers = handlers_map.find(channel); if (handlers != handlers_map.end()) { HandlersVec & callbacks = handlers->second; - for (auto handler_it = callbacks.begin(); - handler_it != callbacks.end(); ++handler_it) { + 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; @@ -42,8 +41,8 @@ void EventManager::dispatch_events() { auto handlers_it = this->subscribers.find(event_type); if (handlers_it != this->subscribers.end()) { HandlersVec & handlers = handlers_it->second; - for (auto handler_it = handlers.begin(); - handler_it != handlers.end(); ++handler_it) { + 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); diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index 783db62..c7c4744 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -94,17 +94,14 @@ private: EventManager() = default; //! The queue of events to be processed. - std::vector, int, std::type_index>> - events_queue; + std::vector, int, std::type_index>> events_queue; //! Registered event handlers. - std::unordered_map>> + std::unordered_map>> subscribers; //! Event handlers indexed by event ID. std::unordered_map< std::type_index, - std::unordered_map>>> + std::unordered_map>>> subscribers_by_event_id; }; diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp index d901492..b20b88f 100644 --- a/src/crepe/api/EventManager.hpp +++ b/src/crepe/api/EventManager.hpp @@ -4,8 +4,8 @@ namespace crepe { template void EventManager::subscribe(EventHandler && callback, int channel) { - using HandlersMap = std::unordered_map< - int, std::vector>>; + using HandlersMap + = std::unordered_map>>; using HandlersVec = std::vector>; std::type_index event_type = typeid(EventType); @@ -30,18 +30,17 @@ template void EventManager::queue_event(EventType && event, int channel) { std::type_index event_type = std::type_index(typeid(EventType)); - auto 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); + 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) { - using HandlersMap = std::unordered_map< - int, std::vector>>; + using HandlersMap + = std::unordered_map>>; using HandlersVec = std::vector>; std::type_index event_type = std::type_index(typeid(EventType)); @@ -71,10 +70,9 @@ void EventManager::trigger_event(const EventType & event, int channel) { } template -void EventManager::unsubscribe(const EventHandler & callback, - int channel) { - using HandlersMap = std::unordered_map< - int, std::vector>>; +void EventManager::unsubscribe(const EventHandler & callback, int channel) { + using HandlersMap + = std::unordered_map>>; using HandlersVec = std::vector>; std::type_index event_type(typeid(EventType)); diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index cd255df..f5426be 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -23,25 +23,21 @@ 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); - }; + 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); + event_manager.subscribe(std::move(this->key_released_handler), + this->channel); } // Unsubscribe from key events void IKeyListener::unsubscribe_events() { - event_manager.unsubscribe(this->key_pressed_handler, - this->channel); - event_manager.unsubscribe(this->key_released_handler, - this->channel); + event_manager.unsubscribe(this->key_pressed_handler, this->channel); + event_manager.unsubscribe(this->key_released_handler, this->channel); } // Activate key listening diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index 3e0e2cb..d492387 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -22,7 +22,7 @@ public: IKeyListener(const IKeyListener &) = delete; IKeyListener & operator=(const IKeyListener &) = delete; IKeyListener(IKeyListener &&) = delete; - + /** * \brief Pure virtual function to handle key press events. * \param event The key press event to handle. diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index bfa49f8..5ee2814 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -16,40 +16,29 @@ 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); - }; + 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); }; // 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_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); + event_manager.subscribe(std::move(mouse_move_handler), this->channel); } void IMouseListener::unsubscribe_events() { // 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); + 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() { diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 2ec156f..c315c35 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -12,7 +12,6 @@ namespace crepe { */ class IMouseListener { public: - IMouseListener(); /** * \brief Constructs an IMouseListener with a specified channel. diff --git a/src/example/events.cpp b/src/example/events.cpp index 5a0a748..6431c67 100644 --- a/src/example/events.cpp +++ b/src/example/events.cpp @@ -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; } }; @@ -74,10 +74,8 @@ int main() { 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); + 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); @@ -102,8 +100,7 @@ int main() { 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); -- cgit v1.2.3 From ad5a0e04aec5e9e9cbbd54a665eff748e31bc1dc Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Mon, 18 Nov 2024 15:42:12 +0100 Subject: remove event.h change --- mwe/events/include/event.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mwe/events/include/event.h b/mwe/events/include/event.h index e1b220b..ee1bf52 100644 --- a/mwe/events/include/event.h +++ b/mwe/events/include/event.h @@ -148,7 +148,7 @@ private: }; class ShutDownEvent : public Event { public: - ShutDownEvent() : Event("ShutDownEvent"){}; + ShutDownEvent() : Event("ShutDownEvent") {}; REGISTER_EVENT_TYPE(ShutDownEvent) -- cgit v1.2.3 From ccc56c987dc69e2bdb20e58634d29c3bf89c44ad Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Mon, 18 Nov 2024 16:13:08 +0100 Subject: added default parameters of channel --- src/crepe/api/EventManager.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index c7c4744..92273df 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -50,7 +50,7 @@ public: * \param channel The event ID to unsubscribe from. */ template - void unsubscribe(const EventHandler &, int channel); + void unsubscribe(const EventHandler &, int channel = 0); /** * \brief Trigger an event. @@ -62,7 +62,7 @@ public: * \param channel The channel from which to trigger the event (default is 0). */ template - void trigger_event(const EventType & event, int channel); + void trigger_event(const EventType & event, int channel = 0); /** * \brief Queue an event for later processing. @@ -75,7 +75,7 @@ public: * \param channel The channel number for the event (default is 0). */ template - void queue_event(EventType && event, int channel); + void queue_event(EventType && event, int channel = 0); /** * \brief Dispatch all queued events. -- cgit v1.2.3 From 193e837fce92dcc169f995f670c9261f853ea1c3 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Mon, 18 Nov 2024 20:25:31 +0100 Subject: adjusted so that all gets are auto --- src/crepe/system/RenderSystem.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 37320ed..39e0e3f 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -1,5 +1,4 @@ #include -#include #include #include "../ComponentManager.h" @@ -19,7 +18,7 @@ void RenderSystem::present_screen() const { SDLContext::get_instance().present_s void RenderSystem::update_camera() { ComponentManager & mgr = this->component_manager; - std::vector> cameras = mgr.get_components_by_type(); + auto cameras = mgr.get_components_by_type(); for (Camera & cam : cameras) { SDLContext::get_instance().camera(cam); -- cgit v1.2.3 From 66bbea079bf1ae84c355349d337db468c18eac32 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Mon, 18 Nov 2024 21:07:26 +0100 Subject: feedback from PR#38 implemented --- src/crepe/facade/SDLContext.h | 5 ----- src/crepe/system/RenderSystem.cpp | 5 ++--- src/crepe/system/RenderSystem.h | 10 ++++++---- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index 007092b..d437bc4 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -21,8 +21,6 @@ namespace crepe { // typedef is unusable when crepe is packaged. Wouter will fix this later. typedef SDL_Keycode CREPE_KEYCODES; -class Texture; -class LoopManager; /** * \class SDLContext @@ -91,9 +89,6 @@ private: //! Will use the funtions: texture_from_path, get_width,get_height. friend class Texture; - //! Will use the funtions: texture_from_path, get_width,get_height. - friend class Animator; - /** * \brief Loads a texture from a file path. * \param path Path to the image file. diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index bf5dade..11c20f5 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -22,7 +22,7 @@ void RenderSystem::update_camera() { for (Camera & cam : cameras) { SDLContext::get_instance().camera(cam); - this->curr_cam = &cam; + this->curr_cam_ref = &cam; } } @@ -35,7 +35,6 @@ bool sorting_comparison(const Sprite & a, const Sprite & b) { std::vector> RenderSystem::sort(std::vector> & objs) { - if (objs.empty()) return {}; std::vector> sorted_objs(objs); std::sort(sorted_objs.begin(), sorted_objs.end(), sorting_comparison); @@ -52,7 +51,7 @@ void RenderSystem::render_sprites() { SDLContext & render = SDLContext::get_instance(); for (const Sprite & sprite : sorted_sprites) { auto transforms = mgr.get_components_by_id(sprite.game_object_id); - render.draw(sprite, transforms[0], *curr_cam); + render.draw(sprite, transforms[0], *this->curr_cam_ref); } } diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 7661cbd..1176b06 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -1,12 +1,14 @@ #pragma once -#include "api/Camera.h" -#include "System.h" -#include "api/Sprite.h" #include #include +#include "api/Sprite.h" +#include "api/Camera.h" + +#include "System.h" + namespace crepe { /** @@ -54,7 +56,7 @@ private: private: //! Pointer to the current active camera for rendering - Camera * curr_cam = nullptr; + Camera * curr_cam_ref = nullptr; // TODO: needs a better solution }; -- cgit v1.2.3 From 9fb2e3a1d697f4961379980651e5434395e372bd Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Tue, 19 Nov 2024 11:48:07 +0100 Subject: unit tests --- src/crepe/api/Color.h | 4 +- src/crepe/system/RenderSystem.cpp | 7 +- src/test/CMakeLists.txt | 1 + src/test/rendering.cpp | 174 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 src/test/rendering.cpp diff --git a/src/crepe/api/Color.h b/src/crepe/api/Color.h index aa47bf4..c207ba7 100644 --- a/src/crepe/api/Color.h +++ b/src/crepe/api/Color.h @@ -21,13 +21,13 @@ public: static const Color & get_yellow(); static const Color & get_black(); -private: - // TODO: why are these private!? +public: uint8_t r; uint8_t g; uint8_t b; uint8_t a; +private: static Color white; static Color red; static Color green; diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 11c20f5..82257c4 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include "../ComponentManager.h" @@ -20,6 +21,8 @@ void RenderSystem::update_camera() { std::vector> cameras = mgr.get_components_by_type(); + if (cameras.size() == 0) throw std::runtime_error("No cameras in current scene"); + for (Camera & cam : cameras) { SDLContext::get_instance().camera(cam); this->curr_cam_ref = &cam; @@ -27,8 +30,8 @@ void RenderSystem::update_camera() { } bool sorting_comparison(const Sprite & a, const Sprite & b) { - if (a.sorting_in_layer > b.sorting_in_layer) return true; - if (a.sorting_in_layer == b.sorting_in_layer) return a.order_in_layer > b.order_in_layer; + if (a.sorting_in_layer < b.sorting_in_layer) return true; + if (a.sorting_in_layer == b.sorting_in_layer) return a.order_in_layer < b.order_in_layer; return false; } diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 49c8151..0969a52 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 + rendering.cpp ) diff --git a/src/test/rendering.cpp b/src/test/rendering.cpp new file mode 100644 index 0000000..4c5fb1d --- /dev/null +++ b/src/test/rendering.cpp @@ -0,0 +1,174 @@ +#include "api/Camera.h" +#include +#include +#include +#include + +#define private public +#define protected public + +#include +#include +#include +#include +#include + +#include + +using namespace std; +using namespace crepe; +using namespace testing; + +class RenderSystemTest : public Test { +public: + ComponentManager mgr{}; + RenderSystem sys{mgr}; + GameObject entity1 = this->mgr.new_object("name"); + GameObject entity2 = this->mgr.new_object("name"); + GameObject entity3 = this->mgr.new_object("name"); + GameObject entity4 = this->mgr.new_object("name"); + + void SetUp() override { + auto & sprite1 + = entity1.add_component(make_shared("../asset/texture/img.png"), + Color(0, 0, 0, 0), FlipSettings{false, false}); + ASSERT_NE(sprite1.sprite_image.get(), nullptr); + sprite1.order_in_layer = 5; + sprite1.sorting_in_layer = 5; + EXPECT_EQ(sprite1.order_in_layer, 5); + EXPECT_EQ(sprite1.sorting_in_layer, 5); + auto & sprite2 + = entity2.add_component(make_shared("../asset/texture/img.png"), + Color(0, 0, 0, 0), FlipSettings{false, false}); + ASSERT_NE(sprite2.sprite_image.get(), nullptr); + sprite2.sorting_in_layer = 2; + sprite2.order_in_layer = 1; + + EXPECT_EQ(sprite2.sorting_in_layer, 2); + EXPECT_EQ(sprite2.order_in_layer, 1); + + auto & sprite3 + = entity3.add_component(make_shared("../asset/texture/img.png"), + Color(0, 0, 0, 0), FlipSettings{false, false}); + ASSERT_NE(sprite3.sprite_image.get(), nullptr); + sprite3.sorting_in_layer = 1; + sprite3.order_in_layer = 2; + + EXPECT_EQ(sprite3.sorting_in_layer, 1); + EXPECT_EQ(sprite3.order_in_layer, 2); + + auto & sprite4 + = entity4.add_component(make_shared("../asset/texture/img.png"), + Color(0, 0, 0, 0), FlipSettings{false, false}); + ASSERT_NE(sprite4.sprite_image.get(), nullptr); + sprite4.sorting_in_layer = 1; + sprite4.order_in_layer = 1; + EXPECT_EQ(sprite4.sorting_in_layer, 1); + EXPECT_EQ(sprite4.order_in_layer, 1); + } +}; + +TEST_F(RenderSystemTest, expected_throws) { + GameObject entity1 = this->mgr.new_object("NAME"); + + // no texture img + EXPECT_ANY_THROW({ + entity1.add_component(make_shared("NO_IMAGE"), Color(0, 0, 0, 0), + FlipSettings{false, false}); + }); + + // No camera + EXPECT_ANY_THROW({ this->sys.update(); }); +} + +TEST_F(RenderSystemTest, make_sprites) {} + +TEST_F(RenderSystemTest, sorting_sprites) { + vector> sprites = this->mgr.get_components_by_type(); + ASSERT_EQ(sprites.size(), 4); + + vector> sorted_sprites = this->sys.sort(sprites); + ASSERT_EQ(sorted_sprites.size(), 4); + + // Expected order after sorting: + // 1. sorting_in_layer: 1, order_in_layer: 1 (entity4) + // 2. sorting_in_layer: 1, order_in_layer: 2 (entity3) + // 3. sorting_in_layer: 2, order_in_layer: 1 (entity2) + // 4. sorting_in_layer: 5, order_in_layer: 5 (entity1) + + EXPECT_EQ(sorted_sprites[0].get().sorting_in_layer, 1); + EXPECT_EQ(sorted_sprites[0].get().order_in_layer, 1); + + EXPECT_EQ(sorted_sprites[1].get().sorting_in_layer, 1); + EXPECT_EQ(sorted_sprites[1].get().order_in_layer, 2); + + EXPECT_EQ(sorted_sprites[2].get().sorting_in_layer, 2); + EXPECT_EQ(sorted_sprites[2].get().order_in_layer, 1); + + EXPECT_EQ(sorted_sprites[3].get().sorting_in_layer, 5); + EXPECT_EQ(sorted_sprites[3].get().order_in_layer, 5); + + for (size_t i = 1; i < sorted_sprites.size(); ++i) { + const Sprite & prev = sorted_sprites[i - 1].get(); + const Sprite & curr = sorted_sprites[i].get(); + + if (prev.sorting_in_layer == curr.sorting_in_layer) { + EXPECT_LE(prev.order_in_layer, curr.order_in_layer); + } else { + EXPECT_LE(prev.sorting_in_layer, curr.sorting_in_layer); + } + } +} + +TEST_F(RenderSystemTest, Update) { + entity1.add_component(Color::get_white()); + { + vector> sprites = this->mgr.get_components_by_type(); + ASSERT_EQ(sprites.size(), 4); + + EXPECT_EQ(sprites[0].get().game_object_id, 0); + EXPECT_EQ(sprites[1].get().game_object_id, 1); + EXPECT_EQ(sprites[2].get().game_object_id, 2); + EXPECT_EQ(sprites[3].get().game_object_id, 3); + } + this->sys.update(); + { + vector> sprites = this->mgr.get_components_by_type(); + ASSERT_EQ(sprites.size(), 4); + + EXPECT_EQ(sprites[0].get().game_object_id, 0); + EXPECT_EQ(sprites[1].get().game_object_id, 1); + EXPECT_EQ(sprites[2].get().game_object_id, 2); + EXPECT_EQ(sprites[3].get().game_object_id, 3); + } +} + +TEST_F(RenderSystemTest, Camera) { + { + auto cameras = this->mgr.get_components_by_type(); + EXPECT_NE(cameras.size(), 1); + } + { + entity1.add_component(Color::get_white()); + auto cameras = this->mgr.get_components_by_type(); + EXPECT_EQ(cameras.size(), 1); + } + + //TODO improve with newer version +} +TEST_F(RenderSystemTest, Color) { + entity1.add_component(Color::get_white()); + auto & sprite = this->mgr.get_components_by_id(entity1.id).front().get(); + ASSERT_NE(sprite.sprite_image.get(), nullptr); + + sprite.color = Color::get_green(); + EXPECT_EQ(sprite.color.r, Color::get_green().r); + EXPECT_EQ(sprite.color.g, Color::get_green().g); + EXPECT_EQ(sprite.color.b, Color::get_green().b); + EXPECT_EQ(sprite.color.a, Color::get_green().a); + this->sys.update(); + EXPECT_EQ(sprite.color.r, Color::get_green().r); + EXPECT_EQ(sprite.color.g, Color::get_green().g); + EXPECT_EQ(sprite.color.b, Color::get_green().b); + EXPECT_EQ(sprite.color.a, Color::get_green().a); +} -- cgit v1.2.3 From 881e8f286a553f393af7c698652521b5c125b1f7 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Tue, 19 Nov 2024 15:17:20 +0100 Subject: added operator --- src/crepe/api/IMouseListener.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index c315c35..921a760 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -19,8 +19,9 @@ public: */ IMouseListener(int channel); virtual ~IMouseListener(); - IMouseListener(const IMouseListener &) = delete; IMouseListener & operator=(const IMouseListener &) = delete; + IMouseListener(const IMouseListener &) = delete; + IMouseListener && operator=(const IMouseListener &&) = delete; IMouseListener(IMouseListener &&) = delete; /** -- cgit v1.2.3 From 85a15e4f43941b5d47fc4be2fee754f0a3d88d15 Mon Sep 17 00:00:00 2001 From: max-001 Date: Wed, 20 Nov 2024 10:41:01 +0100 Subject: Added ECS tests --- src/example/CMakeLists.txt | 2 - src/example/components_internal.cpp | 51 -------- src/example/ecs.cpp | 53 -------- src/test/CMakeLists.txt | 1 + src/test/ECSTest.cpp | 236 ++++++++++++++++++++++++++++++++++++ 5 files changed, 237 insertions(+), 106 deletions(-) delete mode 100644 src/example/components_internal.cpp delete mode 100644 src/example/ecs.cpp create mode 100644 src/test/ECSTest.cpp diff --git a/src/example/CMakeLists.txt b/src/example/CMakeLists.txt index 3a5b543..bbeec09 100644 --- a/src/example/CMakeLists.txt +++ b/src/example/CMakeLists.txt @@ -17,7 +17,6 @@ function(add_example target_name) endfunction() add_example(audio_internal) -# add_example(components_internal) add_example(script) add_example(log) add_example(rendering) @@ -26,7 +25,6 @@ add_example(physics) add_example(savemgr) add_example(proxy) add_example(db) -add_example(ecs) add_example(scene_manager) add_example(particles) add_example(gameloop) diff --git a/src/example/components_internal.cpp b/src/example/components_internal.cpp deleted file mode 100644 index 2a232a9..0000000 --- a/src/example/components_internal.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/** \file - * - * Standalone example for usage of the internal ECS - */ - -#include -#include - -#include -#include - -#include -#include -#include - -#include - -using namespace crepe; -using namespace std; - -#define OBJ_COUNT 100000 - -int main() { - dbg_trace(); - - ComponentManager mgr{}; - - auto start_adding = chrono::high_resolution_clock::now(); - - for (int i = 0; i < OBJ_COUNT; ++i) { - GameObject obj = mgr.new_object("Name", "Tag"); - obj.add_component("test"); - obj.add_component(0, 0, i); - } - - auto stop_adding = chrono::high_resolution_clock::now(); - - auto sprites = mgr.get_components_by_type(); - for (auto sprite : sprites) { - assert(true); - } - - auto stop_looping = chrono::high_resolution_clock::now(); - - auto add_time = chrono::duration_cast(stop_adding - start_adding); - auto loop_time = chrono::duration_cast(stop_looping - stop_adding); - printf("add time: %ldus\n", add_time.count()); - printf("loop time: %ldus\n", loop_time.count()); - - return 0; -} diff --git a/src/example/ecs.cpp b/src/example/ecs.cpp deleted file mode 100644 index d5ba51b..0000000 --- a/src/example/ecs.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include - -#include -#include -#include -#include - -using namespace crepe; -using namespace std; - -int main() { - ComponentManager mgr{}; - - // Create a few GameObjects - try { - GameObject body = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1); - GameObject right_leg = mgr.new_object("rightLeg", "person", Vector2{1, 1}, 0, 1); - GameObject left_leg = mgr.new_object("leftLeg", "person", Vector2{1, 1}, 0, 1); - GameObject right_foot = mgr.new_object("rightFoot", "person", Vector2{2, 2}, 0, 1); - GameObject left_foot = mgr.new_object("leftFoot", "person", Vector2{2, 2}, 0, 1); - - // Set the parent of each GameObject - right_foot.set_parent(right_leg); - left_foot.set_parent(left_leg); - right_leg.set_parent(body); - left_leg.set_parent(body); - - // Adding a second Transform component is not allowed and will invoke an exception - body.add_component(Vector2{10, 10}, 0, 1); - } catch (const exception & e) { - cerr << e.what() << endl; - } - - // Get the Metadata and Transform components of each GameObject - vector> metadata = mgr.get_components_by_type(); - vector> transform = mgr.get_components_by_type(); - - // Print the Metadata and Transform components - for (auto & m : metadata) { - cout << "Id: " << m.get().game_object_id << " Name: " << m.get().name - << " Tag: " << m.get().tag << " Parent: " << m.get().parent << " Children: "; - for (auto & c : m.get().children) { - cout << c << " "; - } - cout << endl; - } - for (auto & t : transform) { - cout << "Id: " << t.get().game_object_id << " Position: [" << t.get().position.x - << ", " << t.get().position.y << "]" << endl; - } - - return 0; -} diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 49c8151..0849b98 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 + ECSTest.cpp ) diff --git a/src/test/ECSTest.cpp b/src/test/ECSTest.cpp new file mode 100644 index 0000000..a245879 --- /dev/null +++ b/src/test/ECSTest.cpp @@ -0,0 +1,236 @@ +#include +#include +#define protected public + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace crepe; + +class ECSTest : public ::testing::Test { +public: + ComponentManager mgr{}; +}; + +TEST_F(ECSTest, createGameObject) { + GameObject obj = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1); + + vector> metadata = mgr.get_components_by_type(); + vector> transform = mgr.get_components_by_type(); + + EXPECT_EQ(metadata.size(), 1); + EXPECT_EQ(transform.size(), 1); + + EXPECT_EQ(metadata[0].get().name, "body"); + EXPECT_EQ(metadata[0].get().tag, "person"); + EXPECT_EQ(metadata[0].get().parent, -1); + EXPECT_EQ(metadata[0].get().children.size(), 0); + + EXPECT_EQ(transform[0].get().position.x, 0); + EXPECT_EQ(transform[0].get().position.y, 0); + EXPECT_EQ(transform[0].get().rotation, 0); + EXPECT_EQ(transform[0].get().scale, 1); +} + +TEST_F(ECSTest, deleteAllGameObjects) { + GameObject obj0 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1); + GameObject obj1 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1); + + mgr.delete_all_components(); + + vector> metadata = mgr.get_components_by_type(); + vector> transform = mgr.get_components_by_type(); + + EXPECT_EQ(metadata.size(), 0); + EXPECT_EQ(transform.size(), 0); + + GameObject obj2 = mgr.new_object("body2", "person2", Vector2{1, 0}, 5, 1); + + metadata = mgr.get_components_by_type(); + transform = mgr.get_components_by_type(); + + EXPECT_EQ(metadata.size(), 1); + EXPECT_EQ(transform.size(), 1); + + EXPECT_EQ(metadata[0].get().game_object_id, 0); + EXPECT_EQ(metadata[0].get().name, "body2"); + EXPECT_EQ(metadata[0].get().tag, "person2"); + EXPECT_EQ(metadata[0].get().parent, -1); + EXPECT_EQ(metadata[0].get().children.size(), 0); + + EXPECT_EQ(transform[0].get().game_object_id, 0); + EXPECT_EQ(transform[0].get().position.x, 1); + EXPECT_EQ(transform[0].get().position.y, 0); + EXPECT_EQ(transform[0].get().rotation, 5); + EXPECT_EQ(transform[0].get().scale, 1); +} + +TEST_F(ECSTest, deleteGameObject) { + GameObject obj0 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1); + GameObject obj1 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1); + + mgr.delete_all_components_of_id(0); + + vector> metadata = mgr.get_components_by_type(); + vector> transform = mgr.get_components_by_type(); + + EXPECT_EQ(metadata.size(), 1); + EXPECT_EQ(transform.size(), 1); + + EXPECT_EQ(metadata[0].get().game_object_id, 1); + EXPECT_EQ(metadata[0].get().name, "body"); + EXPECT_EQ(metadata[0].get().tag, "person"); + EXPECT_EQ(metadata[0].get().parent, -1); + EXPECT_EQ(metadata[0].get().children.size(), 0); + + EXPECT_EQ(transform[0].get().game_object_id, 1); + EXPECT_EQ(transform[0].get().position.x, 0); + EXPECT_EQ(transform[0].get().position.y, 0); + EXPECT_EQ(transform[0].get().rotation, 0); + EXPECT_EQ(transform[0].get().scale, 1); +} + +TEST_F(ECSTest, manyGameObjects) { + for(int i = 0; i < 5000; i++) { + GameObject obj = mgr.new_object("body", "person", Vector2{0, 0}, 0, i); + } + + vector> metadata = mgr.get_components_by_type(); + vector> transform = mgr.get_components_by_type(); + + EXPECT_EQ(metadata.size(), 5000); + EXPECT_EQ(transform.size(), 5000); + for(int i = 0; i < 5000; i++) { + EXPECT_EQ(metadata[i].get().game_object_id, i); + EXPECT_EQ(metadata[i].get().name, "body"); + EXPECT_EQ(metadata[i].get().tag, "person"); + EXPECT_EQ(metadata[i].get().parent, -1); + EXPECT_EQ(metadata[i].get().children.size(), 0); + + EXPECT_EQ(transform[i].get().game_object_id, i); + EXPECT_EQ(transform[i].get().position.x, 0); + EXPECT_EQ(transform[i].get().position.y, 0); + EXPECT_EQ(transform[i].get().rotation, 0); + EXPECT_EQ(transform[i].get().scale, i); + } + + mgr.delete_components(); + + metadata = mgr.get_components_by_type(); + transform = mgr.get_components_by_type(); + + EXPECT_EQ(metadata.size(), 0); + EXPECT_EQ(transform.size(), 5000); + + for(int i = 0; i < 10000 - 5000; i++) { + string tag = "person" + to_string(i); + GameObject obj = mgr.new_object("body", tag, Vector2{0, 0}, i, 0); + } + + metadata = mgr.get_components_by_type(); + transform = mgr.get_components_by_type(); + + EXPECT_EQ(metadata.size(), 10000 - 5000); + EXPECT_EQ(transform.size(), 10000); +} + +TEST_F(ECSTest, getComponentsByID) { + GameObject obj0 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1); + GameObject obj1 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1); + + vector> metadata = mgr.get_components_by_id(0); + vector> transform = mgr.get_components_by_id(1); + + EXPECT_EQ(metadata.size(), 1); + EXPECT_EQ(transform.size(), 1); + + EXPECT_EQ(metadata[0].get().game_object_id, 0); + EXPECT_EQ(metadata[0].get().name, "body"); + EXPECT_EQ(metadata[0].get().tag, "person"); + EXPECT_EQ(metadata[0].get().parent, -1); + EXPECT_EQ(metadata[0].get().children.size(), 0); + + EXPECT_EQ(transform[0].get().game_object_id, 1); + EXPECT_EQ(transform[0].get().position.x, 0); + EXPECT_EQ(transform[0].get().position.y, 0); + EXPECT_EQ(transform[0].get().rotation, 0); + EXPECT_EQ(transform[0].get().scale, 1); +} + +TEST_F(ECSTest, tooMuchComponents) { + try { + GameObject obj0 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1); + obj0.add_component(Vector2{10, 10}, 0, 1); + } catch (const exception & e) { + EXPECT_EQ(e.what(), string("Exceeded maximum number of instances for this component type")); + } + + try { + GameObject obj1 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1); + obj1.add_component("body", "person"); + } catch (const exception & e) { + EXPECT_EQ(e.what(), string("Exceeded maximum number of instances for this component type")); + } + + vector> metadata = mgr.get_components_by_type(); + + EXPECT_EQ(metadata.size(), 2); + EXPECT_EQ(metadata[0].get().name, "body"); + EXPECT_EQ(metadata[1].get().name, "body"); +} + +TEST_F(ECSTest, partentChild) { + { + GameObject body = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1); + GameObject right_leg = mgr.new_object("rightLeg", "person", Vector2{1, 1}, 0, 1); + GameObject left_leg = mgr.new_object("leftLeg", "person", Vector2{1, 1}, 0, 1); + GameObject right_foot = mgr.new_object("rightFoot", "person", Vector2{2, 2}, 0, 1); + GameObject left_foot = mgr.new_object("leftFoot", "person", Vector2{2, 2}, 0, 1); + + // Set the parent of each GameObject + right_foot.set_parent(right_leg); + left_foot.set_parent(left_leg); + right_leg.set_parent(body); + left_leg.set_parent(body); + } + + // Get the Metadata and Transform components of each GameObject + vector> metadata = mgr.get_components_by_type(); + + // Check IDs + EXPECT_EQ(metadata[0].get().game_object_id, 0); + EXPECT_EQ(metadata[1].get().game_object_id, 1); + EXPECT_EQ(metadata[2].get().game_object_id, 2); + EXPECT_EQ(metadata[3].get().game_object_id, 3); + EXPECT_EQ(metadata[4].get().game_object_id, 4); + + // Check the parent-child relationships + EXPECT_EQ(metadata[0].get().name, "body"); + EXPECT_EQ(metadata[1].get().name, "rightLeg"); + EXPECT_EQ(metadata[2].get().name, "leftLeg"); + EXPECT_EQ(metadata[3].get().name, "rightFoot"); + EXPECT_EQ(metadata[4].get().name, "leftFoot"); + + EXPECT_EQ(metadata[0].get().parent, -1); + EXPECT_EQ(metadata[1].get().parent, 0); + EXPECT_EQ(metadata[2].get().parent, 0); + EXPECT_EQ(metadata[3].get().parent, 1); + EXPECT_EQ(metadata[4].get().parent, 2); + + EXPECT_EQ(metadata[0].get().children.size(), 2); + EXPECT_EQ(metadata[1].get().children.size(), 1); + EXPECT_EQ(metadata[2].get().children.size(), 1); + EXPECT_EQ(metadata[3].get().children.size(), 0); + EXPECT_EQ(metadata[4].get().children.size(), 0); + + EXPECT_EQ(metadata[0].get().children[0], 1); + EXPECT_EQ(metadata[0].get().children[1], 2); + EXPECT_EQ(metadata[1].get().children[0], 3); + EXPECT_EQ(metadata[2].get().children[0], 4); +} -- cgit v1.2.3 From e714303c486fb81851116710ba5d68e1b469df02 Mon Sep 17 00:00:00 2001 From: max-001 Date: Wed, 20 Nov 2024 10:59:34 +0100 Subject: Added SceneManager tests --- src/example/CMakeLists.txt | 1 - src/example/scene_manager.cpp | 79 --------------------------- src/test/CMakeLists.txt | 1 + src/test/ECSTest.cpp | 3 -- src/test/SceneManagerTest.cpp | 120 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 121 insertions(+), 83 deletions(-) delete mode 100644 src/example/scene_manager.cpp create mode 100644 src/test/SceneManagerTest.cpp diff --git a/src/example/CMakeLists.txt b/src/example/CMakeLists.txt index bbeec09..30432e5 100644 --- a/src/example/CMakeLists.txt +++ b/src/example/CMakeLists.txt @@ -25,7 +25,6 @@ add_example(physics) add_example(savemgr) add_example(proxy) add_example(db) -add_example(scene_manager) add_example(particles) add_example(gameloop) diff --git a/src/example/scene_manager.cpp b/src/example/scene_manager.cpp deleted file mode 100644 index accec7d..0000000 --- a/src/example/scene_manager.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include - -using namespace crepe; -using namespace std; - -class ConcreteScene1 : public Scene { -public: - using Scene::Scene; - - void load_scene() { - auto & mgr = this->component_manager; - GameObject object1 = mgr.new_object("scene_1", "tag_scene_1", Vector2{0, 0}, 0, 1); - GameObject object2 = mgr.new_object("scene_1", "tag_scene_1", Vector2{1, 0}, 0, 1); - GameObject object3 = mgr.new_object("scene_1", "tag_scene_1", Vector2{2, 0}, 0, 1); - } -}; - -class ConcreteScene2 : public Scene { -public: - using Scene::Scene; - - void load_scene() { - auto & mgr = this->component_manager; - GameObject object1 = mgr.new_object("scene_2", "tag_scene_2", Vector2{0, 0}, 0, 1); - GameObject object2 = mgr.new_object("scene_2", "tag_scene_2", Vector2{0, 1}, 0, 1); - GameObject object3 = mgr.new_object("scene_2", "tag_scene_2", Vector2{0, 2}, 0, 1); - GameObject object4 = mgr.new_object("scene_2", "tag_scene_2", Vector2{0, 3}, 0, 1); - } -}; - -int main() { - ComponentManager component_mgr{}; - SceneManager scene_mgr{component_mgr}; - - // Add the scenes to the scene manager - scene_mgr.add_scene("scene1"); - scene_mgr.add_scene("scene2"); - - // There is no need to call set_next_scene() at the beginnen, because the first scene will be - // automatically set as the next scene - - // Load scene1 (the first scene added) - scene_mgr.load_next_scene(); - - // Get the Metadata components of each GameObject of Scene1 - vector> metadata - = component_mgr.get_components_by_type(); - - cout << "Metadata components of Scene1:" << endl; - // Print the Metadata - for (auto & m : metadata) { - cout << "Id: " << m.get().game_object_id << " Name: " << m.get().name - << " Tag: " << m.get().tag << endl; - } - - // Set scene2 as the next scene - scene_mgr.set_next_scene("scene2"); - // Load scene2 - scene_mgr.load_next_scene(); - - // Get the Metadata components of each GameObject of Scene2 - metadata = component_mgr.get_components_by_type(); - - cout << "Metadata components of Scene2:" << endl; - // Print the Metadata - for (auto & m : metadata) { - cout << "Id: " << m.get().game_object_id << " Name: " << m.get().name - << " Tag: " << m.get().tag << endl; - } - - return 0; -} diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 0849b98..d56d80f 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -4,5 +4,6 @@ target_sources(test_main PUBLIC ScriptTest.cpp ParticleTest.cpp ECSTest.cpp + SceneManagerTest.cpp ) diff --git a/src/test/ECSTest.cpp b/src/test/ECSTest.cpp index a245879..eaa2dbc 100644 --- a/src/test/ECSTest.cpp +++ b/src/test/ECSTest.cpp @@ -1,5 +1,3 @@ -#include -#include #define protected public #include @@ -7,7 +5,6 @@ #include #include #include -#include #include using namespace std; diff --git a/src/test/SceneManagerTest.cpp b/src/test/SceneManagerTest.cpp new file mode 100644 index 0000000..98b2a23 --- /dev/null +++ b/src/test/SceneManagerTest.cpp @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace crepe; + +class ConcreteScene1 : public Scene { +public: + using Scene::Scene; + + void load_scene() { + auto & mgr = this->component_manager; + GameObject object1 = mgr.new_object("scene_1", "tag_scene_1", Vector2{0, 0}, 0, 1); + GameObject object2 = mgr.new_object("scene_1", "tag_scene_1", Vector2{1, 0}, 0, 1); + GameObject object3 = mgr.new_object("scene_1", "tag_scene_1", Vector2{2, 0}, 0, 1); + } +}; + +class ConcreteScene2 : public Scene { +public: + using Scene::Scene; + + void load_scene() { + auto & mgr = this->component_manager; + GameObject object1 = mgr.new_object("scene_2", "tag_scene_2", Vector2{0, 0}, 0, 1); + GameObject object2 = mgr.new_object("scene_2", "tag_scene_2", Vector2{0, 1}, 0, 1); + GameObject object3 = mgr.new_object("scene_2", "tag_scene_2", Vector2{0, 2}, 0, 1); + GameObject object4 = mgr.new_object("scene_2", "tag_scene_2", Vector2{0, 3}, 0, 1); + } +}; + +class SceneManagerTest : public ::testing::Test { +public: + ComponentManager component_mgr{}; + SceneManager scene_mgr{component_mgr}; +}; + +TEST_F(SceneManagerTest, loadScene) { + scene_mgr.add_scene("scene1"); + scene_mgr.add_scene("scene2"); + + scene_mgr.load_next_scene(); + + vector> metadata = component_mgr.get_components_by_type(); + vector> transform = component_mgr.get_components_by_type(); + + EXPECT_EQ(metadata.size(), 3); + EXPECT_EQ(transform.size(), 3); + + EXPECT_EQ(metadata[0].get().game_object_id, 0); + EXPECT_EQ(metadata[0].get().name, "scene_1"); + EXPECT_EQ(metadata[0].get().tag, "tag_scene_1"); + EXPECT_EQ(metadata[0].get().parent, -1); + EXPECT_EQ(metadata[0].get().children.size(), 0); + EXPECT_EQ(transform[0].get().position.x, 0); + EXPECT_EQ(transform[0].get().position.y, 0); + + EXPECT_EQ(metadata[1].get().game_object_id, 1); + EXPECT_EQ(metadata[1].get().name, "scene_1"); + EXPECT_EQ(metadata[1].get().tag, "tag_scene_1"); + EXPECT_EQ(metadata[1].get().parent, -1); + EXPECT_EQ(metadata[1].get().children.size(), 0); + EXPECT_EQ(transform[1].get().position.x, 1); + EXPECT_EQ(transform[1].get().position.y, 0); + + EXPECT_EQ(metadata[2].get().game_object_id, 2); + EXPECT_EQ(metadata[2].get().name, "scene_1"); + EXPECT_EQ(metadata[2].get().tag, "tag_scene_1"); + EXPECT_EQ(metadata[2].get().parent, -1); + EXPECT_EQ(metadata[2].get().children.size(), 0); + EXPECT_EQ(transform[2].get().position.x, 2); + EXPECT_EQ(transform[2].get().position.y, 0); + + scene_mgr.set_next_scene("scene2"); + scene_mgr.load_next_scene(); + + metadata = component_mgr.get_components_by_type(); + transform = component_mgr.get_components_by_type(); + + EXPECT_EQ(metadata.size(), 4); + EXPECT_EQ(transform.size(), 4); + + EXPECT_EQ(metadata[0].get().game_object_id, 0); + EXPECT_EQ(metadata[0].get().name, "scene_2"); + EXPECT_EQ(metadata[0].get().tag, "tag_scene_2"); + EXPECT_EQ(metadata[0].get().parent, -1); + EXPECT_EQ(metadata[0].get().children.size(), 0); + EXPECT_EQ(transform[0].get().position.x, 0); + EXPECT_EQ(transform[0].get().position.y, 0); + + EXPECT_EQ(metadata[1].get().game_object_id, 1); + EXPECT_EQ(metadata[1].get().name, "scene_2"); + EXPECT_EQ(metadata[1].get().tag, "tag_scene_2"); + EXPECT_EQ(metadata[1].get().parent, -1); + EXPECT_EQ(metadata[1].get().children.size(), 0); + EXPECT_EQ(transform[1].get().position.x, 0); + EXPECT_EQ(transform[1].get().position.y, 1); + + EXPECT_EQ(metadata[2].get().game_object_id, 2); + EXPECT_EQ(metadata[2].get().name, "scene_2"); + EXPECT_EQ(metadata[2].get().tag, "tag_scene_2"); + EXPECT_EQ(metadata[2].get().parent, -1); + EXPECT_EQ(metadata[2].get().children.size(), 0); + EXPECT_EQ(transform[2].get().position.x, 0); + EXPECT_EQ(transform[2].get().position.y, 2); + + EXPECT_EQ(metadata[3].get().game_object_id, 3); + EXPECT_EQ(metadata[3].get().name, "scene_2"); + EXPECT_EQ(metadata[3].get().tag, "tag_scene_2"); + EXPECT_EQ(metadata[3].get().parent, -1); + EXPECT_EQ(metadata[3].get().children.size(), 0); + EXPECT_EQ(transform[3].get().position.x, 0); + EXPECT_EQ(transform[3].get().position.y, 3); +} -- cgit v1.2.3 From 52e84ca0a81210cd1dc61e096c228586649c9bfc Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Wed, 20 Nov 2024 11:35:25 +0100 Subject: updated adjsuted rendering based on feedback --- src/crepe/facade/SDLContext.cpp | 51 +++++++++++++++++++++++++++++--------- src/crepe/facade/SDLContext.h | 26 +++++++++++++++++-- src/crepe/system/RenderSystem.cpp | 8 +++--- src/crepe/system/RenderSystem.h | 3 ++- src/example/rendering_particle.cpp | 11 ++++---- 5 files changed, 74 insertions(+), 25 deletions(-) diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index 40189f6..8131df2 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -15,6 +16,8 @@ #include "../api/Texture.h" #include "../api/Transform.h" #include "../util/Log.h" +#include "api/Camera.h" +#include "api/Vector2.h" #include "SDLContext.h" @@ -93,30 +96,54 @@ void SDLContext::handle_events(bool & running) { void SDLContext::clear_screen() { SDL_RenderClear(this->game_renderer.get()); } void SDLContext::present_screen() { SDL_RenderPresent(this->game_renderer.get()); } -void SDLContext::draw(const Sprite & sprite, const Transform & transform, const Camera & cam) { - - SDL_RendererFlip render_flip - = (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * sprite.flip.flip_x) - | (SDL_FLIP_VERTICAL * sprite.flip.flip_y)); - - double adjusted_x = (transform.position.x - cam.x) * cam.zoom; - double adjusted_y = (transform.position.y - cam.y) * cam.zoom; - double adjusted_w = sprite.sprite_rect.w * transform.scale * cam.zoom; - double adjusted_h = sprite.sprite_rect.h * transform.scale * cam.zoom; - SDL_Rect srcrect = { +SDL_Rect SDLContext::get_src_rect(const Sprite & sprite) { + return SDL_Rect{ .x = sprite.sprite_rect.x, .y = sprite.sprite_rect.y, .w = sprite.sprite_rect.w, .h = sprite.sprite_rect.h, }; +} +SDL_Rect SDLContext::get_dst_rect(const Sprite & sprite, const Vector2 & pos, + const double & scale, const Camera & cam) { + + double adjusted_x = (pos.x - cam.x) * cam.zoom; + double adjusted_y = (pos.y - cam.y) * cam.zoom; + double adjusted_w = sprite.sprite_rect.w * scale * cam.zoom; + double adjusted_h = sprite.sprite_rect.h * scale * cam.zoom; - SDL_Rect dstrect = { + return SDL_Rect{ .x = static_cast(adjusted_x), .y = static_cast(adjusted_y), .w = static_cast(adjusted_w), .h = static_cast(adjusted_h), }; +} + +void SDLContext::draw_particle(const Sprite & sprite, const Vector2 & pos, + const double & angle, const double & scale, + const Camera & camera) { + + SDL_RendererFlip render_flip + = (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * sprite.flip.flip_x) + | (SDL_FLIP_VERTICAL * sprite.flip.flip_y)); + + SDL_Rect srcrect = this->get_src_rect(sprite); + SDL_Rect dstrect = this->get_dst_rect(sprite, pos, scale, camera); + + SDL_RenderCopyEx(this->game_renderer.get(), sprite.sprite_image->texture.get(), &srcrect, + &dstrect, angle, NULL, render_flip); +} + +void SDLContext::draw(const Sprite & sprite, const Transform & transform, const Camera & cam) { + + SDL_RendererFlip render_flip + = (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * sprite.flip.flip_x) + | (SDL_FLIP_VERTICAL * sprite.flip.flip_y)); + + SDL_Rect srcrect = this->get_src_rect(sprite); + SDL_Rect dstrect = this->get_dst_rect(sprite, transform.position, transform.scale, cam); SDL_RenderCopyEx(this->game_renderer.get(), sprite.sprite_image->texture.get(), &srcrect, &dstrect, transform.rotation, NULL, render_flip); diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index 78ac56b..fb09015 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -1,8 +1,10 @@ #pragma once #include +#include #include #include +#include #include #include #include @@ -10,6 +12,7 @@ #include "../api/Sprite.h" #include "../api/Transform.h" #include "api/Camera.h" +#include "api/Vector2.h" namespace crepe { @@ -122,8 +125,7 @@ private: * \param camera Reference to the Camera for view adjustments. */ void draw(const Sprite & sprite, const Transform & transform, const Camera & camera); - - void draw_particle(const Vector2 & pos, const Camera & camera); + void draw_particle(const Sprite & sprite, const Vector2 & pos, const double & angle, const double & scale, const Camera & camera); //! Clears the screen, preparing for a new frame. void clear_screen(); @@ -137,6 +139,26 @@ private: */ void camera(const Camera & camera); +private: + /** + * \brief calculates the sqaure size of the image + * + * \param sprite Reference to the sprite to calculate the rectangle + * \return sdl rectangle to draw a src image + */ + SDL_Rect get_src_rect(const Sprite & sprite); + /** + * \brief calculates the sqaure size of the image for an destination + * + * \param sprite Reference to the sprite to calculate the rectangle + * \param pos the pos in pixel positions + * \param scale the multiplier to increase of decrease for the specified sprite + * \param cam Reference to the current camera in the scene to calculate the position based + * on the camera + * \return sdl rectangle to draw a dst image to draw on the screen + */ + SDL_Rect get_dst_rect(const Sprite & sprite, const Vector2 & pos, const double & scale, const Camera & cam); + private: //! sdl Window std::unique_ptr> game_window; diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 39e0e3f..1ae5ca7 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -27,7 +27,7 @@ void RenderSystem::update_camera() { } bool RenderSystem::render_particle(const Sprite & sprite, - Transform tm) { + const double & scale) { ComponentManager & mgr = this->component_manager; SDLContext & render = SDLContext::get_instance(); @@ -44,9 +44,7 @@ bool RenderSystem::render_particle(const Sprite & sprite, for (const Particle & p : em.data.particles) { if (!p.active) continue; - tm.position = p.position; - tm.rotation = p.angle; - render.draw(em.data.sprite, tm, *curr_cam); + render.draw_particle(sprite, p.position, p.angle, scale, *this->curr_cam); } } return rendering_particles; @@ -68,7 +66,7 @@ void RenderSystem::render() { if (!sprite.active) continue; auto transform = mgr.get_components_by_id(sprite.game_object_id).front().get(); - bool rendered_particles = this->render_particle(sprite, transform); + bool rendered_particles = this->render_particle(sprite, transform.scale); if (rendered_particles) continue; diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index c18b80b..6643084 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -5,6 +5,7 @@ #include "api/Transform.h" #include "System.h" +#include namespace crepe { @@ -51,7 +52,7 @@ private: * \param tm the Transform component for scale * \return true if particles have been rendered */ - bool render_particle(const Sprite &, Transform tm); + bool render_particle(const Sprite &, const double & scale); /** * \brief renders a sprite with a Transform component on the screen diff --git a/src/example/rendering_particle.cpp b/src/example/rendering_particle.cpp index 33013ef..71b50ba 100644 --- a/src/example/rendering_particle.cpp +++ b/src/example/rendering_particle.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -21,7 +20,11 @@ using namespace crepe; using namespace std; int main(int argc, char * argv[]) { - GameObject game_object(0, "", "", Vector2{100, 100}, 0, 0.1); + ComponentManager mgr; + GameObject game_object = mgr.new_object("", "", Vector2{100, 100}, 0, 0.1); + RenderSystem sys{mgr}; + ParticleSystem psys{mgr}; + Color color(255, 255, 255, 255); Sprite test_sprite = game_object.add_component( make_shared("../asset/texture/img.png"), color, @@ -47,11 +50,9 @@ int main(int argc, char * argv[]) { }); game_object.add_component(Color::get_white()); - auto & sys = crepe::RenderSystem::get_instance(); - auto sys_part = crepe::ParticleSystem(); auto start = std::chrono::steady_clock::now(); while (std::chrono::steady_clock::now() - start < std::chrono::seconds(5)) { - sys_part.update(); + psys.update(); sys.update(); SDL_Delay(10 ); } -- cgit v1.2.3 From 5121e95e5ba98ca5cadfb63b7603731dfb41a322 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Wed, 20 Nov 2024 11:53:17 +0100 Subject: implemented feedback --- makefile | 2 +- mwe/events/include/event.h | 2 +- src/crepe/api/Sprite.h | 3 ++- src/crepe/facade/SDLContext.h | 1 - src/crepe/system/RenderSystem.cpp | 15 +++++++-------- src/crepe/system/RenderSystem.h | 20 +++++++++++--------- 6 files changed, 22 insertions(+), 21 deletions(-) diff --git a/makefile b/makefile index dd7c587..32e68c0 100644 --- a/makefile +++ b/makefile @@ -6,5 +6,5 @@ doxygen: Doxyfile FORCE FMT += $(shell git ls-files '*.c' '*.cpp' '*.h' '*.hpp') format: FORCE clang-format -i $(FMT) - $(MAKE) -C src $@ + #$(MAKE) -C src $@ diff --git a/mwe/events/include/event.h b/mwe/events/include/event.h index ee1bf52..e1b220b 100644 --- a/mwe/events/include/event.h +++ b/mwe/events/include/event.h @@ -148,7 +148,7 @@ private: }; class ShutDownEvent : public Event { public: - ShutDownEvent() : Event("ShutDownEvent") {}; + ShutDownEvent() : Event("ShutDownEvent"){}; REGISTER_EVENT_TYPE(ShutDownEvent) diff --git a/src/crepe/api/Sprite.h b/src/crepe/api/Sprite.h index 0192793..74a55d4 100644 --- a/src/crepe/api/Sprite.h +++ b/src/crepe/api/Sprite.h @@ -2,8 +2,9 @@ #include +#include "../Component.h" + #include "Color.h" -#include "Component.h" #include "Texture.h" namespace crepe { diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index d437bc4..652a83e 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -21,7 +21,6 @@ namespace crepe { // typedef is unusable when crepe is packaged. Wouter will fix this later. typedef SDL_Keycode CREPE_KEYCODES; - /** * \class SDLContext * \brief Facade for the SDL library diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 82257c4..96c5f27 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -12,10 +12,11 @@ #include "RenderSystem.h" using namespace crepe; +using namespace std; -void RenderSystem::clear_screen() const { SDLContext::get_instance().clear_screen(); } +void RenderSystem::clear_screen() { this->context.clear_screen(); } -void RenderSystem::present_screen() const { SDLContext::get_instance().present_screen(); } +void RenderSystem::present_screen() { this->context.present_screen(); } void RenderSystem::update_camera() { ComponentManager & mgr = this->component_manager; @@ -24,7 +25,7 @@ void RenderSystem::update_camera() { if (cameras.size() == 0) throw std::runtime_error("No cameras in current scene"); for (Camera & cam : cameras) { - SDLContext::get_instance().camera(cam); + this->context.camera(cam); this->curr_cam_ref = &cam; } } @@ -47,14 +48,12 @@ RenderSystem::sort(std::vector> & objs) { void RenderSystem::render_sprites() { ComponentManager & mgr = this->component_manager; + vector> sprites = mgr.get_components_by_type(); + vector> sorted_sprites = this->sort(sprites); - auto sprites = mgr.get_components_by_type(); - auto sorted_sprites = this->sort(sprites); - - SDLContext & render = SDLContext::get_instance(); for (const Sprite & sprite : sorted_sprites) { auto transforms = mgr.get_components_by_id(sprite.game_object_id); - render.draw(sprite, transforms[0], *this->curr_cam_ref); + this->context.draw(sprite, transforms[0], *this->curr_cam_ref); } } diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 1176b06..8914b96 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -1,23 +1,23 @@ #pragma once - #include #include -#include "api/Sprite.h" -#include "api/Camera.h" +#include "facade/SDLContext.h" #include "System.h" namespace crepe { +class Camera; +class Sprite; + /** * \class RenderSystem * \brief Manages rendering operations for all game objects. * - * RenderSystem is responsible for rendering sprites, clearing and presenting the screen, and - * managing the active camera. It functions as a singleton, providing centralized rendering - * services for the application. + * RenderSystem is responsible for rendering, clearing and presenting the screen, and + * managing the active camera. */ class RenderSystem : public System { public: @@ -30,16 +30,16 @@ public: private: //! Clears the screen in preparation for rendering. - void clear_screen() const; + void clear_screen(); //! Presents the rendered frame to the display. - void present_screen() const; + void present_screen(); //! Updates the active camera used for rendering. void update_camera(); //! Renders all active sprites to the screen. - void render_sprites() ; + void render_sprites(); std::vector> sort(std::vector> & objs); @@ -58,6 +58,8 @@ private: //! Pointer to the current active camera for rendering Camera * curr_cam_ref = nullptr; // TODO: needs a better solution + + SDLContext & context = SDLContext::get_instance(); }; } // namespace crepe -- cgit v1.2.3 From d4dd3ceab2b95c26f3b07092a5c80f47eab18110 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 20 Nov 2024 13:02:08 +0100 Subject: split format/lint --- makefile | 3 ++- src/makefile | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index dd7c587..c46e8a5 100644 --- a/makefile +++ b/makefile @@ -6,5 +6,6 @@ doxygen: Doxyfile FORCE FMT += $(shell git ls-files '*.c' '*.cpp' '*.h' '*.hpp') format: FORCE clang-format -i $(FMT) - $(MAKE) -C src $@ +lint: FORCE + $(MAKE) -C src $@ diff --git a/src/makefile b/src/makefile index 5f80204..a0e8f02 100644 --- a/src/makefile +++ b/src/makefile @@ -1,6 +1,9 @@ .PHONY: FORCE -FMT := $(shell git ls-files '*.c' '*.cpp' '*.h' '*.hpp') format: FORCE - clang-tidy -p build/compile_commands.json --fix-errors $(FMT) + $(MAKE) -C .. $@ + +LINT := $(shell git ls-files '*.c' '*.cpp' '*.h' '*.hpp') +lint: FORCE + clang-tidy -p build/compile_commands.json --fix-errors $(LINT) -- cgit v1.2.3 From 158022890cb9abd308a6a445588cc2fca8d84e67 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Wed, 20 Nov 2024 13:25:44 +0100 Subject: implementing feedback --- src/crepe/facade/SDLContext.cpp | 3 ++- src/crepe/facade/SDLContext.h | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index 8131df2..eacb10a 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -149,7 +149,7 @@ void SDLContext::draw(const Sprite & sprite, const Transform & transform, const &dstrect, transform.rotation, NULL, render_flip); } -void SDLContext::camera(const Camera & cam) { +void SDLContext::set_camera(const Camera & cam) { this->viewport.w = static_cast(cam.aspect_width); this->viewport.h = static_cast(cam.aspect_height); this->viewport.x = static_cast(cam.x) - (this->viewport.w / 2); @@ -167,6 +167,7 @@ SDLContext::texture_from_path(const std::string & path) { SDL_Surface * tmp = IMG_Load(path.c_str()); if (tmp == nullptr) { tmp = IMG_Load("../asset/texture/ERROR.png"); + if (tmp == nullptr) throw runtime_error("cannot load image"); } std::unique_ptr> img_surface; diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index fb09015..287ad5d 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -125,6 +125,7 @@ private: * \param camera Reference to the Camera for view adjustments. */ void draw(const Sprite & sprite, const Transform & transform, const Camera & camera); + void draw_particle(const Sprite & sprite, const Vector2 & pos, const double & angle, const double & scale, const Camera & camera); //! Clears the screen, preparing for a new frame. @@ -134,10 +135,10 @@ private: void present_screen(); /** - * \brief Sets the current camera for rendering. + * \brief sets the background of the camera (will be adjusted in future PR) * \param camera Reference to the Camera object. */ - void camera(const Camera & camera); + void set_camera(const Camera & camera); private: /** -- cgit v1.2.3 From 26ddec125cd93e9613331872f8e22c79c6f3a720 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 20 Nov 2024 13:30:33 +0100 Subject: update contributing.md --- contributing.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/contributing.md b/contributing.md index 5b0c79d..9c95851 100644 --- a/contributing.md +++ b/contributing.md @@ -20,7 +20,7 @@ that you can click on to open them. # Code style - Formatting nitty-gritty is handled by clang-format/clang-tidy (run `make - format` in the root folder of this repository to format all sources files) + format` or `make lint`) -
ASCII only
GoodBad
@@ -798,6 +798,27 @@ that you can click on to open them. resolving merge conflicts when multiple sources were added by different people to the same CMakeLists.txt easier. +## GoogleTest-specific + +- Unit tests are not *required* to follow all code standards +-
+ Private/protected members may be accessed using preprocessor tricks + + + ```cpp + // include unrelated headers before + + #define private public + #define protected public + + // headers included after *will* be affected + ``` +
+- Each test source file defines tests within a single test suite (first + parameter of `TEST()` / `TEST_F()` macro) +- Test source files match their suite name (or test fixture name in the case of + tests that use a fixture) + # Structure - Files are placed in the appropriate directory: -- cgit v1.2.3 From c6d7623cc0bc17aa171bc5078f2f36c15be28683 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Wed, 20 Nov 2024 13:39:44 +0100 Subject: implemented feedback from @lonkaars --- src/crepe/api/Color.cpp | 37 ++------- src/crepe/api/Color.h | 49 ++++------- src/crepe/system/RenderSystem.h | 6 ++ src/test/CMakeLists.txt | 2 +- src/test/RenderSystemTest.cpp | 174 ++++++++++++++++++++++++++++++++++++++++ src/test/rendering.cpp | 174 ---------------------------------------- 6 files changed, 203 insertions(+), 239 deletions(-) create mode 100644 src/test/RenderSystemTest.cpp delete mode 100644 src/test/rendering.cpp diff --git a/src/crepe/api/Color.cpp b/src/crepe/api/Color.cpp index 9e5f187..29bd77a 100644 --- a/src/crepe/api/Color.cpp +++ b/src/crepe/api/Color.cpp @@ -2,32 +2,11 @@ using namespace crepe; -Color Color::white = Color(255, 255, 255, 0); -Color Color::red = Color(255, 0, 0, 0); -Color Color::green = Color(0, 255, 0, 0); -Color Color::blue = Color(0, 0, 255, 0); -Color Color::black = Color(0, 0, 0, 0); -Color Color::cyan = Color(0, 255, 255, 0); -Color Color::yellow = Color(255, 255, 0, 0); -Color Color::magenta = Color(255, 0, 255, 0); - -Color::Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) { - this->a = alpha; - this->r = red; - this->g = green; - this->b = blue; -}; - -const Color & Color::get_white() { return Color::white; }; - -const Color & Color::get_red() { return Color::red; }; -const Color & Color::get_green() { return Color::green; }; -const Color & Color::get_blue() { return Color::blue; }; - -const Color & Color::get_black() { return Color::black; }; - -const Color & Color::get_cyan() { return Color::cyan; }; - -const Color & Color::get_yellow() { return Color::yellow; }; - -const Color & Color::get_magenta() { return Color::magenta; }; +const Color Color::WHITE{0xff, 0xff, 0xff}; +const Color Color::RED{0xff, 0x00, 0x00}; +const Color Color::GREEN{0x00, 0xff, 0x00}; +const Color Color::BLUE{0x00, 0x00, 0xff}; +const Color Color::BLACK{0x00, 0x00, 0x00}; +const Color Color::CYAN{0x00, 0xff, 0xff}; +const Color Color::YELLOW{0xff, 0xff, 0x00}; +const Color Color::MAGENTA{0xff, 0x00, 0xff}; diff --git a/src/crepe/api/Color.h b/src/crepe/api/Color.h index c207ba7..84edb5c 100644 --- a/src/crepe/api/Color.h +++ b/src/crepe/api/Color.h @@ -4,41 +4,20 @@ namespace crepe { -// TODO: make Color a struct w/o constructors/destructors -class Color { - - // FIXME: can't these colors be defined as a `static constexpr const Color` - // instead? - -public: - Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha); - static const Color & get_white(); - static const Color & get_red(); - static const Color & get_green(); - static const Color & get_blue(); - static const Color & get_cyan(); - static const Color & get_magenta(); - static const Color & get_yellow(); - static const Color & get_black(); - -public: - uint8_t r; - uint8_t g; - uint8_t b; - uint8_t a; - -private: - static Color white; - static Color red; - static Color green; - static Color blue; - static Color cyan; - static Color magenta; - static Color yellow; - static Color black; - -private: - friend class SDLContext; +struct Color { + uint8_t r = 0x00; + uint8_t g = 0x00; + uint8_t b = 0x00; + uint8_t a = 0xff; + + static const Color WHITE; + static const Color RED; + static const Color GREEN; + static const Color BLUE; + static const Color CYAN; + static const Color MAGENTA; + static const Color YELLOW; + static const Color BLACK; }; } // namespace crepe diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 8914b96..57b9c73 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -41,6 +41,12 @@ private: //! Renders all active sprites to the screen. void render_sprites(); + /** + * \brief sort a vector sprite objects with + * + * \param objs the vector that will do a sorting algorithm on + * \return returns a sorted reference vector + */ std::vector> sort(std::vector> & objs); diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 0969a52..1c93220 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -3,6 +3,6 @@ target_sources(test_main PUBLIC PhysicsTest.cpp ScriptTest.cpp ParticleTest.cpp - rendering.cpp + RenderSystemTest.cpp ) diff --git a/src/test/RenderSystemTest.cpp b/src/test/RenderSystemTest.cpp new file mode 100644 index 0000000..ac479d3 --- /dev/null +++ b/src/test/RenderSystemTest.cpp @@ -0,0 +1,174 @@ +#include "api/Camera.h" +#include +#include +#include +#include + +#define private public +#define protected public + +#include +#include +#include +#include +#include + +#include + +using namespace std; +using namespace crepe; +using namespace testing; + +class RenderSystemTest : public Test { +public: + ComponentManager mgr{}; + RenderSystem sys{mgr}; + GameObject entity1 = this->mgr.new_object("name"); + GameObject entity2 = this->mgr.new_object("name"); + GameObject entity3 = this->mgr.new_object("name"); + GameObject entity4 = this->mgr.new_object("name"); + + void SetUp() override { + auto & sprite1 + = entity1.add_component(make_shared("../asset/texture/img.png"), + Color(0, 0, 0, 0), FlipSettings{false, false}); + ASSERT_NE(sprite1.sprite_image.get(), nullptr); + sprite1.order_in_layer = 5; + sprite1.sorting_in_layer = 5; + EXPECT_EQ(sprite1.order_in_layer, 5); + EXPECT_EQ(sprite1.sorting_in_layer, 5); + auto & sprite2 + = entity2.add_component(make_shared("../asset/texture/img.png"), + Color(0, 0, 0, 0), FlipSettings{false, false}); + ASSERT_NE(sprite2.sprite_image.get(), nullptr); + sprite2.sorting_in_layer = 2; + sprite2.order_in_layer = 1; + + EXPECT_EQ(sprite2.sorting_in_layer, 2); + EXPECT_EQ(sprite2.order_in_layer, 1); + + auto & sprite3 + = entity3.add_component(make_shared("../asset/texture/img.png"), + Color(0, 0, 0, 0), FlipSettings{false, false}); + ASSERT_NE(sprite3.sprite_image.get(), nullptr); + sprite3.sorting_in_layer = 1; + sprite3.order_in_layer = 2; + + EXPECT_EQ(sprite3.sorting_in_layer, 1); + EXPECT_EQ(sprite3.order_in_layer, 2); + + auto & sprite4 + = entity4.add_component(make_shared("../asset/texture/img.png"), + Color(0, 0, 0, 0), FlipSettings{false, false}); + ASSERT_NE(sprite4.sprite_image.get(), nullptr); + sprite4.sorting_in_layer = 1; + sprite4.order_in_layer = 1; + EXPECT_EQ(sprite4.sorting_in_layer, 1); + EXPECT_EQ(sprite4.order_in_layer, 1); + } +}; + +TEST_F(RenderSystemTest, expected_throws) { + GameObject entity1 = this->mgr.new_object("NAME"); + + // no texture img + EXPECT_ANY_THROW({ + entity1.add_component(make_shared("NO_IMAGE"), Color(0, 0, 0, 0), + FlipSettings{false, false}); + }); + + // No camera + EXPECT_ANY_THROW({ this->sys.update(); }); +} + +TEST_F(RenderSystemTest, make_sprites) {} + +TEST_F(RenderSystemTest, sorting_sprites) { + vector> sprites = this->mgr.get_components_by_type(); + ASSERT_EQ(sprites.size(), 4); + + vector> sorted_sprites = this->sys.sort(sprites); + ASSERT_EQ(sorted_sprites.size(), 4); + + // Expected order after sorting: + // 1. sorting_in_layer: 1, order_in_layer: 1 (entity4) + // 2. sorting_in_layer: 1, order_in_layer: 2 (entity3) + // 3. sorting_in_layer: 2, order_in_layer: 1 (entity2) + // 4. sorting_in_layer: 5, order_in_layer: 5 (entity1) + + EXPECT_EQ(sorted_sprites[0].get().sorting_in_layer, 1); + EXPECT_EQ(sorted_sprites[0].get().order_in_layer, 1); + + EXPECT_EQ(sorted_sprites[1].get().sorting_in_layer, 1); + EXPECT_EQ(sorted_sprites[1].get().order_in_layer, 2); + + EXPECT_EQ(sorted_sprites[2].get().sorting_in_layer, 2); + EXPECT_EQ(sorted_sprites[2].get().order_in_layer, 1); + + EXPECT_EQ(sorted_sprites[3].get().sorting_in_layer, 5); + EXPECT_EQ(sorted_sprites[3].get().order_in_layer, 5); + + for (size_t i = 1; i < sorted_sprites.size(); ++i) { + const Sprite & prev = sorted_sprites[i - 1].get(); + const Sprite & curr = sorted_sprites[i].get(); + + if (prev.sorting_in_layer == curr.sorting_in_layer) { + EXPECT_LE(prev.order_in_layer, curr.order_in_layer); + } else { + EXPECT_LE(prev.sorting_in_layer, curr.sorting_in_layer); + } + } +} + +TEST_F(RenderSystemTest, Update) { + entity1.add_component(Color::WHITE); + { + vector> sprites = this->mgr.get_components_by_type(); + ASSERT_EQ(sprites.size(), 4); + + EXPECT_EQ(sprites[0].get().game_object_id, 0); + EXPECT_EQ(sprites[1].get().game_object_id, 1); + EXPECT_EQ(sprites[2].get().game_object_id, 2); + EXPECT_EQ(sprites[3].get().game_object_id, 3); + } + this->sys.update(); + { + vector> sprites = this->mgr.get_components_by_type(); + ASSERT_EQ(sprites.size(), 4); + + EXPECT_EQ(sprites[0].get().game_object_id, 0); + EXPECT_EQ(sprites[1].get().game_object_id, 1); + EXPECT_EQ(sprites[2].get().game_object_id, 2); + EXPECT_EQ(sprites[3].get().game_object_id, 3); + } +} + +TEST_F(RenderSystemTest, Camera) { + { + auto cameras = this->mgr.get_components_by_type(); + EXPECT_NE(cameras.size(), 1); + } + { + entity1.add_component(Color::WHITE); + auto cameras = this->mgr.get_components_by_type(); + EXPECT_EQ(cameras.size(), 1); + } + + //TODO improve with newer version +} +TEST_F(RenderSystemTest, Color) { + entity1.add_component(Color::WHITE); + auto & sprite = this->mgr.get_components_by_id(entity1.id).front().get(); + ASSERT_NE(sprite.sprite_image.get(), nullptr); + + sprite.color = Color::GREEN; + EXPECT_EQ(sprite.color.r, Color::GREEN.r); + EXPECT_EQ(sprite.color.g, Color::GREEN.g); + EXPECT_EQ(sprite.color.b, Color::GREEN.b); + EXPECT_EQ(sprite.color.a, Color::GREEN.a); + this->sys.update(); + EXPECT_EQ(sprite.color.r, Color::GREEN.r); + EXPECT_EQ(sprite.color.g, Color::GREEN.g); + EXPECT_EQ(sprite.color.b, Color::GREEN.b); + EXPECT_EQ(sprite.color.a, Color::GREEN.a); +} diff --git a/src/test/rendering.cpp b/src/test/rendering.cpp deleted file mode 100644 index 4c5fb1d..0000000 --- a/src/test/rendering.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include "api/Camera.h" -#include -#include -#include -#include - -#define private public -#define protected public - -#include -#include -#include -#include -#include - -#include - -using namespace std; -using namespace crepe; -using namespace testing; - -class RenderSystemTest : public Test { -public: - ComponentManager mgr{}; - RenderSystem sys{mgr}; - GameObject entity1 = this->mgr.new_object("name"); - GameObject entity2 = this->mgr.new_object("name"); - GameObject entity3 = this->mgr.new_object("name"); - GameObject entity4 = this->mgr.new_object("name"); - - void SetUp() override { - auto & sprite1 - = entity1.add_component(make_shared("../asset/texture/img.png"), - Color(0, 0, 0, 0), FlipSettings{false, false}); - ASSERT_NE(sprite1.sprite_image.get(), nullptr); - sprite1.order_in_layer = 5; - sprite1.sorting_in_layer = 5; - EXPECT_EQ(sprite1.order_in_layer, 5); - EXPECT_EQ(sprite1.sorting_in_layer, 5); - auto & sprite2 - = entity2.add_component(make_shared("../asset/texture/img.png"), - Color(0, 0, 0, 0), FlipSettings{false, false}); - ASSERT_NE(sprite2.sprite_image.get(), nullptr); - sprite2.sorting_in_layer = 2; - sprite2.order_in_layer = 1; - - EXPECT_EQ(sprite2.sorting_in_layer, 2); - EXPECT_EQ(sprite2.order_in_layer, 1); - - auto & sprite3 - = entity3.add_component(make_shared("../asset/texture/img.png"), - Color(0, 0, 0, 0), FlipSettings{false, false}); - ASSERT_NE(sprite3.sprite_image.get(), nullptr); - sprite3.sorting_in_layer = 1; - sprite3.order_in_layer = 2; - - EXPECT_EQ(sprite3.sorting_in_layer, 1); - EXPECT_EQ(sprite3.order_in_layer, 2); - - auto & sprite4 - = entity4.add_component(make_shared("../asset/texture/img.png"), - Color(0, 0, 0, 0), FlipSettings{false, false}); - ASSERT_NE(sprite4.sprite_image.get(), nullptr); - sprite4.sorting_in_layer = 1; - sprite4.order_in_layer = 1; - EXPECT_EQ(sprite4.sorting_in_layer, 1); - EXPECT_EQ(sprite4.order_in_layer, 1); - } -}; - -TEST_F(RenderSystemTest, expected_throws) { - GameObject entity1 = this->mgr.new_object("NAME"); - - // no texture img - EXPECT_ANY_THROW({ - entity1.add_component(make_shared("NO_IMAGE"), Color(0, 0, 0, 0), - FlipSettings{false, false}); - }); - - // No camera - EXPECT_ANY_THROW({ this->sys.update(); }); -} - -TEST_F(RenderSystemTest, make_sprites) {} - -TEST_F(RenderSystemTest, sorting_sprites) { - vector> sprites = this->mgr.get_components_by_type(); - ASSERT_EQ(sprites.size(), 4); - - vector> sorted_sprites = this->sys.sort(sprites); - ASSERT_EQ(sorted_sprites.size(), 4); - - // Expected order after sorting: - // 1. sorting_in_layer: 1, order_in_layer: 1 (entity4) - // 2. sorting_in_layer: 1, order_in_layer: 2 (entity3) - // 3. sorting_in_layer: 2, order_in_layer: 1 (entity2) - // 4. sorting_in_layer: 5, order_in_layer: 5 (entity1) - - EXPECT_EQ(sorted_sprites[0].get().sorting_in_layer, 1); - EXPECT_EQ(sorted_sprites[0].get().order_in_layer, 1); - - EXPECT_EQ(sorted_sprites[1].get().sorting_in_layer, 1); - EXPECT_EQ(sorted_sprites[1].get().order_in_layer, 2); - - EXPECT_EQ(sorted_sprites[2].get().sorting_in_layer, 2); - EXPECT_EQ(sorted_sprites[2].get().order_in_layer, 1); - - EXPECT_EQ(sorted_sprites[3].get().sorting_in_layer, 5); - EXPECT_EQ(sorted_sprites[3].get().order_in_layer, 5); - - for (size_t i = 1; i < sorted_sprites.size(); ++i) { - const Sprite & prev = sorted_sprites[i - 1].get(); - const Sprite & curr = sorted_sprites[i].get(); - - if (prev.sorting_in_layer == curr.sorting_in_layer) { - EXPECT_LE(prev.order_in_layer, curr.order_in_layer); - } else { - EXPECT_LE(prev.sorting_in_layer, curr.sorting_in_layer); - } - } -} - -TEST_F(RenderSystemTest, Update) { - entity1.add_component(Color::get_white()); - { - vector> sprites = this->mgr.get_components_by_type(); - ASSERT_EQ(sprites.size(), 4); - - EXPECT_EQ(sprites[0].get().game_object_id, 0); - EXPECT_EQ(sprites[1].get().game_object_id, 1); - EXPECT_EQ(sprites[2].get().game_object_id, 2); - EXPECT_EQ(sprites[3].get().game_object_id, 3); - } - this->sys.update(); - { - vector> sprites = this->mgr.get_components_by_type(); - ASSERT_EQ(sprites.size(), 4); - - EXPECT_EQ(sprites[0].get().game_object_id, 0); - EXPECT_EQ(sprites[1].get().game_object_id, 1); - EXPECT_EQ(sprites[2].get().game_object_id, 2); - EXPECT_EQ(sprites[3].get().game_object_id, 3); - } -} - -TEST_F(RenderSystemTest, Camera) { - { - auto cameras = this->mgr.get_components_by_type(); - EXPECT_NE(cameras.size(), 1); - } - { - entity1.add_component(Color::get_white()); - auto cameras = this->mgr.get_components_by_type(); - EXPECT_EQ(cameras.size(), 1); - } - - //TODO improve with newer version -} -TEST_F(RenderSystemTest, Color) { - entity1.add_component(Color::get_white()); - auto & sprite = this->mgr.get_components_by_id(entity1.id).front().get(); - ASSERT_NE(sprite.sprite_image.get(), nullptr); - - sprite.color = Color::get_green(); - EXPECT_EQ(sprite.color.r, Color::get_green().r); - EXPECT_EQ(sprite.color.g, Color::get_green().g); - EXPECT_EQ(sprite.color.b, Color::get_green().b); - EXPECT_EQ(sprite.color.a, Color::get_green().a); - this->sys.update(); - EXPECT_EQ(sprite.color.r, Color::get_green().r); - EXPECT_EQ(sprite.color.g, Color::get_green().g); - EXPECT_EQ(sprite.color.b, Color::get_green().b); - EXPECT_EQ(sprite.color.a, Color::get_green().a); -} -- cgit v1.2.3 From e25547c26c8d852ba7cc9fa3981aa75daf0f2287 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 20 Nov 2024 13:57:23 +0100 Subject: show private members in doxygen --- Doxyfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Doxyfile b/Doxyfile index 9328b24..e0a31df 100644 --- a/Doxyfile +++ b/Doxyfile @@ -24,6 +24,7 @@ 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 -- cgit v1.2.3 From 22741a7adc6ff5ce53324d6ef8ef36acf666a46c Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 20 Nov 2024 13:57:28 +0100 Subject: `make format` --- mwe/events/include/event.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mwe/events/include/event.h b/mwe/events/include/event.h index e1b220b..ee1bf52 100644 --- a/mwe/events/include/event.h +++ b/mwe/events/include/event.h @@ -148,7 +148,7 @@ private: }; class ShutDownEvent : public Event { public: - ShutDownEvent() : Event("ShutDownEvent"){}; + ShutDownEvent() : Event("ShutDownEvent") {}; REGISTER_EVENT_TYPE(ShutDownEvent) -- cgit v1.2.3 From 3344e0df01435be903e38ccbd3b9cee608d574e7 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Wed, 20 Nov 2024 14:06:54 +0100 Subject: implemented feedback --- src/crepe/facade/SDLContext.cpp | 18 +++++++++--------- src/crepe/facade/SDLContext.h | 10 ++++++---- src/crepe/system/RenderSystem.cpp | 18 +++++++++--------- src/crepe/system/RenderSystem.h | 14 ++++---------- src/example/rendering_particle.cpp | 14 ++++++-------- 5 files changed, 34 insertions(+), 40 deletions(-) diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index eacb10a..daf0050 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -12,12 +12,12 @@ #include #include +#include "../api/Camera.h" #include "../api/Sprite.h" #include "../api/Texture.h" #include "../api/Transform.h" +#include "../api/Vector2.h" #include "../util/Log.h" -#include "api/Camera.h" -#include "api/Vector2.h" #include "SDLContext.h" @@ -96,8 +96,7 @@ void SDLContext::handle_events(bool & running) { void SDLContext::clear_screen() { SDL_RenderClear(this->game_renderer.get()); } void SDLContext::present_screen() { SDL_RenderPresent(this->game_renderer.get()); } - -SDL_Rect SDLContext::get_src_rect(const Sprite & sprite) { +SDL_Rect SDLContext::get_src_rect(const Sprite & sprite) const { return SDL_Rect{ .x = sprite.sprite_rect.x, .y = sprite.sprite_rect.y, @@ -106,7 +105,7 @@ SDL_Rect SDLContext::get_src_rect(const Sprite & sprite) { }; } SDL_Rect SDLContext::get_dst_rect(const Sprite & sprite, const Vector2 & pos, - const double & scale, const Camera & cam) { + const double & scale, const Camera & cam) const { double adjusted_x = (pos.x - cam.x) * cam.zoom; double adjusted_y = (pos.y - cam.y) * cam.zoom; @@ -123,20 +122,21 @@ SDL_Rect SDLContext::get_dst_rect(const Sprite & sprite, const Vector2 & pos, void SDLContext::draw_particle(const Sprite & sprite, const Vector2 & pos, const double & angle, const double & scale, - const Camera & camera) { + const Camera & camera) const { SDL_RendererFlip render_flip = (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * sprite.flip.flip_x) - | (SDL_FLIP_VERTICAL * sprite.flip.flip_y)); + | (SDL_FLIP_VERTICAL * sprite.flip.flip_y)); SDL_Rect srcrect = this->get_src_rect(sprite); SDL_Rect dstrect = this->get_dst_rect(sprite, pos, scale, camera); SDL_RenderCopyEx(this->game_renderer.get(), sprite.sprite_image->texture.get(), &srcrect, - &dstrect, angle, NULL, render_flip); + &dstrect, angle, NULL, render_flip); } -void SDLContext::draw(const Sprite & sprite, const Transform & transform, const Camera & cam) { +void SDLContext::draw(const Sprite & sprite, const Transform & transform, + const Camera & cam) const { SDL_RendererFlip render_flip = (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * sprite.flip.flip_x) diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index 287ad5d..718c40f 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -124,9 +124,10 @@ private: * \param transform Reference to the Transform for positioning. * \param camera Reference to the Camera for view adjustments. */ - void draw(const Sprite & sprite, const Transform & transform, const Camera & camera); + void draw(const Sprite & sprite, const Transform & transform, const Camera & camera) const; - void draw_particle(const Sprite & sprite, const Vector2 & pos, const double & angle, const double & scale, const Camera & camera); + void draw_particle(const Sprite & sprite, const Vector2 & pos, const double & angle, + const double & scale, const Camera & camera) const; //! Clears the screen, preparing for a new frame. void clear_screen(); @@ -147,7 +148,7 @@ private: * \param sprite Reference to the sprite to calculate the rectangle * \return sdl rectangle to draw a src image */ - SDL_Rect get_src_rect(const Sprite & sprite); + SDL_Rect get_src_rect(const Sprite & sprite) const; /** * \brief calculates the sqaure size of the image for an destination * @@ -158,7 +159,8 @@ private: * on the camera * \return sdl rectangle to draw a dst image to draw on the screen */ - SDL_Rect get_dst_rect(const Sprite & sprite, const Vector2 & pos, const double & scale, const Camera & cam); + SDL_Rect get_dst_rect(const Sprite & sprite, const Vector2 & pos, const double & scale, + const Camera & cam) const; private: //! sdl Window diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 1ae5ca7..28bcf56 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -2,11 +2,11 @@ #include #include "../ComponentManager.h" +#include "../api/ParticleEmitter.h" #include "../api/Sprite.h" #include "../api/Transform.h" -#include "../facade/SDLContext.h" -#include "../api/ParticleEmitter.h" #include "../api/Vector2.h" +#include "../facade/SDLContext.h" #include "RenderSystem.h" @@ -21,13 +21,12 @@ void RenderSystem::update_camera() { auto cameras = mgr.get_components_by_type(); for (Camera & cam : cameras) { - SDLContext::get_instance().camera(cam); + SDLContext::get_instance().set_camera(cam); this->curr_cam = &cam; } } -bool RenderSystem::render_particle(const Sprite & sprite, - const double & scale) { +bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) const { ComponentManager & mgr = this->component_manager; SDLContext & render = SDLContext::get_instance(); @@ -49,22 +48,23 @@ bool RenderSystem::render_particle(const Sprite & sprite, } return rendering_particles; } -void RenderSystem::render_normal(const Sprite & sprite, const Transform & tm) { +void RenderSystem::render_normal(const Sprite & sprite, const Transform & tm) const { ComponentManager & mgr = this->component_manager; SDLContext & render = SDLContext::get_instance(); - + render.draw(sprite, tm, *curr_cam); } -void RenderSystem::render() { +void RenderSystem::render() const { ComponentManager & mgr = this->component_manager; auto sprites = mgr.get_components_by_type(); for (const Sprite & sprite : sprites) { if (!sprite.active) continue; - auto transform = mgr.get_components_by_id(sprite.game_object_id).front().get(); + const Transform & transform + = mgr.get_components_by_id(sprite.game_object_id).front().get(); bool rendered_particles = this->render_particle(sprite, transform.scale); diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 6643084..8841f72 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -25,13 +25,7 @@ public: * This method is called to perform all rendering operations for the current game frame. */ void update() override; - - - RenderSystem(const RenderSystem &) = delete; - RenderSystem(RenderSystem &&) = delete; - RenderSystem & operator=(const RenderSystem &) = delete; - RenderSystem & operator=(RenderSystem &&) = delete; - + private: //! Clears the screen in preparation for rendering. void clear_screen() const; @@ -43,7 +37,7 @@ private: void update_camera(); //! Renders the whole screen - void render(); + void render() const; /** * \brief Renders all the particles on the screen from a given sprite. @@ -52,7 +46,7 @@ private: * \param tm the Transform component for scale * \return true if particles have been rendered */ - bool render_particle(const Sprite &, const double & scale); + bool render_particle(const Sprite & sprite, const double & scale) const; /** * \brief renders a sprite with a Transform component on the screen @@ -60,7 +54,7 @@ private: * \param sprite the sprite component that holds all the data * \param tm the Transform component that holds the position,rotation and scale */ - void render_normal(const Sprite &, const Transform & tm); + void render_normal(const Sprite & sprite, const Transform & tm) const; /** * \todo Include color handling for sprites. diff --git a/src/example/rendering_particle.cpp b/src/example/rendering_particle.cpp index 71b50ba..3f71750 100644 --- a/src/example/rendering_particle.cpp +++ b/src/example/rendering_particle.cpp @@ -4,15 +4,15 @@ #include #include +#include #include #include #include +#include #include #include -#include -#include -#include #include +#include #include @@ -20,15 +20,14 @@ using namespace crepe; using namespace std; int main(int argc, char * argv[]) { - ComponentManager mgr; + ComponentManager mgr; GameObject game_object = mgr.new_object("", "", Vector2{100, 100}, 0, 0.1); RenderSystem sys{mgr}; ParticleSystem psys{mgr}; Color color(255, 255, 255, 255); Sprite test_sprite = game_object.add_component( - make_shared("../asset/texture/img.png"), color, - FlipSettings{false, false}); + make_shared("../asset/texture/img.png"), color, FlipSettings{false, false}); game_object.add_component(ParticleEmitter::Data{ .position = {0, 0}, .max_particles = 10, @@ -54,9 +53,8 @@ int main(int argc, char * argv[]) { while (std::chrono::steady_clock::now() - start < std::chrono::seconds(5)) { psys.update(); sys.update(); - SDL_Delay(10 ); + SDL_Delay(10); } return 0; } - -- cgit v1.2.3 From d623b13dab63408cf5e99dbc453636f174bc6fe8 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Wed, 20 Nov 2024 14:33:08 +0100 Subject: fixxed bug with particleemiiter and sprite in single component --- src/crepe/system/RenderSystem.cpp | 4 ++-- src/example/rendering_particle.cpp | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 28bcf56..c137de1 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -36,10 +36,10 @@ bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) bool rendering_particles = false; for (const ParticleEmitter & em : emitters) { + if (!(&em.data.sprite == &sprite)) continue; + rendering_particles = true; if (!em.active) continue; - if (!(em.data.sprite.game_object_id == sprite.game_object_id)) continue; - rendering_particles = true; for (const Particle & p : em.data.particles) { if (!p.active) continue; diff --git a/src/example/rendering_particle.cpp b/src/example/rendering_particle.cpp index 3f71750..bcf95b8 100644 --- a/src/example/rendering_particle.cpp +++ b/src/example/rendering_particle.cpp @@ -15,6 +15,7 @@ #include #include +#include using namespace crepe; using namespace std; @@ -26,10 +27,12 @@ int main(int argc, char * argv[]) { ParticleSystem psys{mgr}; Color color(255, 255, 255, 255); + game_object.add_component(make_shared("../asset/texture/img.png"), color, FlipSettings{false,false}); + Sprite test_sprite = game_object.add_component( make_shared("../asset/texture/img.png"), color, FlipSettings{false, false}); game_object.add_component(ParticleEmitter::Data{ - .position = {0, 0}, + .position = {100, 0}, .max_particles = 10, .emission_rate = 0.1, .min_speed = 6, @@ -46,9 +49,10 @@ int main(int argc, char * argv[]) { .reset_on_exit = false, }, .sprite = test_sprite, - }); + }).active = false; game_object.add_component(Color::get_white()); + auto start = std::chrono::steady_clock::now(); while (std::chrono::steady_clock::now() - start < std::chrono::seconds(5)) { psys.update(); -- cgit v1.2.3 From fb35ca64eee9afdd72f2cf8d279c4e745444baf9 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 20 Nov 2024 14:51:26 +0100 Subject: `make format` --- src/test/ECSTest.cpp | 15 +++++++++------ src/test/SceneManagerTest.cpp | 10 ++++++---- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/test/ECSTest.cpp b/src/test/ECSTest.cpp index eaa2dbc..d5a5826 100644 --- a/src/test/ECSTest.cpp +++ b/src/test/ECSTest.cpp @@ -1,3 +1,5 @@ +#include + #define protected public #include @@ -5,7 +7,6 @@ #include #include #include -#include using namespace std; using namespace crepe; @@ -94,7 +95,7 @@ TEST_F(ECSTest, deleteGameObject) { } TEST_F(ECSTest, manyGameObjects) { - for(int i = 0; i < 5000; i++) { + for (int i = 0; i < 5000; i++) { GameObject obj = mgr.new_object("body", "person", Vector2{0, 0}, 0, i); } @@ -103,7 +104,7 @@ TEST_F(ECSTest, manyGameObjects) { EXPECT_EQ(metadata.size(), 5000); EXPECT_EQ(transform.size(), 5000); - for(int i = 0; i < 5000; i++) { + for (int i = 0; i < 5000; i++) { EXPECT_EQ(metadata[i].get().game_object_id, i); EXPECT_EQ(metadata[i].get().name, "body"); EXPECT_EQ(metadata[i].get().tag, "person"); @@ -125,7 +126,7 @@ TEST_F(ECSTest, manyGameObjects) { EXPECT_EQ(metadata.size(), 0); EXPECT_EQ(transform.size(), 5000); - for(int i = 0; i < 10000 - 5000; i++) { + for (int i = 0; i < 10000 - 5000; i++) { string tag = "person" + to_string(i); GameObject obj = mgr.new_object("body", tag, Vector2{0, 0}, i, 0); } @@ -165,14 +166,16 @@ TEST_F(ECSTest, tooMuchComponents) { GameObject obj0 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1); obj0.add_component(Vector2{10, 10}, 0, 1); } catch (const exception & e) { - EXPECT_EQ(e.what(), string("Exceeded maximum number of instances for this component type")); + EXPECT_EQ(e.what(), + string("Exceeded maximum number of instances for this component type")); } try { GameObject obj1 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1); obj1.add_component("body", "person"); } catch (const exception & e) { - EXPECT_EQ(e.what(), string("Exceeded maximum number of instances for this component type")); + EXPECT_EQ(e.what(), + string("Exceeded maximum number of instances for this component type")); } vector> metadata = mgr.get_components_by_type(); diff --git a/src/test/SceneManagerTest.cpp b/src/test/SceneManagerTest.cpp index 98b2a23..69e1171 100644 --- a/src/test/SceneManagerTest.cpp +++ b/src/test/SceneManagerTest.cpp @@ -1,10 +1,10 @@ #include #include #include -#include -#include #include #include +#include +#include #include using namespace std; @@ -47,8 +47,10 @@ TEST_F(SceneManagerTest, loadScene) { scene_mgr.load_next_scene(); - vector> metadata = component_mgr.get_components_by_type(); - vector> transform = component_mgr.get_components_by_type(); + vector> metadata + = component_mgr.get_components_by_type(); + vector> transform + = component_mgr.get_components_by_type(); EXPECT_EQ(metadata.size(), 3); EXPECT_EQ(transform.size(), 3); -- cgit v1.2.3 From a0f39be4510665614d25d23d88fe1d0f0b5cc740 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Wed, 20 Nov 2024 15:16:06 +0100 Subject: rendering system bug --- src/crepe/system/RenderSystem.cpp | 29 ++++++++++++++--------------- src/crepe/system/RenderSystem.h | 12 ++++++------ src/example/rendering_particle.cpp | 8 ++++---- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index bc5422d..c599729 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include #include @@ -48,8 +50,6 @@ RenderSystem::sort(std::vector> & objs) { return sorted_objs; } - - void RenderSystem::update() { this->clear_screen(); this->update_camera(); @@ -57,43 +57,42 @@ void RenderSystem::update() { this->present_screen(); } -bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) const { +bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) { ComponentManager & mgr = this->component_manager; - auto emitters = mgr.get_components_by_id(sprite.game_object_id); + vector> emitters + = mgr.get_components_by_id(sprite.game_object_id); bool rendering_particles = false; for (const ParticleEmitter & em : emitters) { + cout << &em.data.sprite << " " << &sprite << endl; if (!(&em.data.sprite == &sprite)) continue; rendering_particles = true; if (!em.active) continue; - for (const Particle & p : em.data.particles) { if (!p.active) continue; - this->context.draw_particle(sprite, p.position, p.angle, scale, *this->curr_cam); + this->context.draw_particle(sprite, p.position, p.angle, scale, + *this->curr_cam_ref); } } return rendering_particles; } -void RenderSystem::render_normal(const Sprite & sprite, const Transform & tm) const { - - ComponentManager & mgr = this->component_manager; - - this->context.draw(sprite, tm, *this->curr_cam); +void RenderSystem::render_normal(const Sprite & sprite, const Transform & tm) { + this->context.draw(sprite, tm, *this->curr_cam_ref); } -void RenderSystem::render() const { +void RenderSystem::render() { ComponentManager & mgr = this->component_manager; vector> sprites = mgr.get_components_by_type(); - vector> sorted_sprites = this->sort(sprites); + //vector> sorted_sprites = this->sort(sprites); - for (const Sprite & sprite : sorted_sprites) { + for (const Sprite & sprite : sprites) { if (!sprite.active) continue; - const Transform & transform + Transform & transform = mgr.get_components_by_id(sprite.game_object_id).front().get(); bool rendered_particles = this->render_particle(sprite, transform.scale); diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index b9033fb..0393f2f 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -31,16 +31,16 @@ public: private: //! Clears the screen in preparation for rendering. - void clear_screen(); + void clear_screen() ; //! Presents the rendered frame to the display. - void present_screen(); + void present_screen() ; //! Updates the active camera used for rendering. void update_camera(); //! Renders the whole screen - void render() const; + void render() ; /** * \brief Renders all the particles on the screen from a given sprite. @@ -49,7 +49,7 @@ private: * \param tm the Transform component for scale * \return true if particles have been rendered */ - bool render_particle(const Sprite & sprite, const double & scale) const; + bool render_particle(const Sprite & sprite, const double & scale) ; /** * \brief renders a sprite with a Transform component on the screen @@ -57,7 +57,7 @@ private: * \param sprite the sprite component that holds all the data * \param tm the Transform component that holds the position,rotation and scale */ - void render_normal(const Sprite & sprite, const Transform & tm); + void render_normal(const Sprite & sprite, const Transform & tm) ; /** * \brief sort a vector sprite objects with @@ -66,7 +66,7 @@ private: * \return returns a sorted reference vector */ std::vector> - sort(std::vector> & objs); + sort(std::vector> & objs) ; /** * \todo Include color handling for sprites. diff --git a/src/example/rendering_particle.cpp b/src/example/rendering_particle.cpp index bcf95b8..062f11f 100644 --- a/src/example/rendering_particle.cpp +++ b/src/example/rendering_particle.cpp @@ -27,12 +27,12 @@ int main(int argc, char * argv[]) { ParticleSystem psys{mgr}; Color color(255, 255, 255, 255); - game_object.add_component(make_shared("../asset/texture/img.png"), color, FlipSettings{false,false}); + //game_object.add_component(make_shared("../asset/texture/img.png"), color, FlipSettings{false,false}); Sprite test_sprite = game_object.add_component( make_shared("../asset/texture/img.png"), color, FlipSettings{false, false}); game_object.add_component(ParticleEmitter::Data{ - .position = {100, 0}, + .position = {0, 0}, .max_particles = 10, .emission_rate = 0.1, .min_speed = 6, @@ -49,8 +49,8 @@ int main(int argc, char * argv[]) { .reset_on_exit = false, }, .sprite = test_sprite, - }).active = false; - game_object.add_component(Color::get_white()); + }); + game_object.add_component(Color::WHITE); auto start = std::chrono::steady_clock::now(); -- 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 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 ccb9dd63c6fc172fed9acaea31a6d67c457b37fe Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Wed, 20 Nov 2024 15:42:55 +0100 Subject: fixed the reference bug in render particle, it was in the example problem --- mwe/events/include/event.h | 2 +- src/crepe/system/RenderSystem.cpp | 19 +++++++++---------- src/crepe/system/RenderSystem.h | 14 +++++++------- src/example/rendering_particle.cpp | 12 +++++++++--- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/mwe/events/include/event.h b/mwe/events/include/event.h index ee1bf52..e1b220b 100644 --- a/mwe/events/include/event.h +++ b/mwe/events/include/event.h @@ -148,7 +148,7 @@ private: }; class ShutDownEvent : public Event { public: - ShutDownEvent() : Event("ShutDownEvent") {}; + ShutDownEvent() : Event("ShutDownEvent"){}; REGISTER_EVENT_TYPE(ShutDownEvent) diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index c599729..05b7337 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -18,9 +18,9 @@ using namespace crepe; using namespace std; -void RenderSystem::clear_screen() { this->context.clear_screen(); } +void RenderSystem::clear_screen() const { this->context.clear_screen(); } -void RenderSystem::present_screen() { this->context.present_screen(); } +void RenderSystem::present_screen() const { this->context.present_screen(); } void RenderSystem::update_camera() { ComponentManager & mgr = this->component_manager; @@ -42,7 +42,7 @@ bool sorting_comparison(const Sprite & a, const Sprite & b) { } std::vector> -RenderSystem::sort(std::vector> & objs) { +RenderSystem::sort(std::vector> & objs) const { std::vector> sorted_objs(objs); std::sort(sorted_objs.begin(), sorted_objs.end(), sorting_comparison); @@ -57,7 +57,7 @@ void RenderSystem::update() { this->present_screen(); } -bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) { +bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) const { ComponentManager & mgr = this->component_manager; @@ -67,7 +67,6 @@ bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) bool rendering_particles = false; for (const ParticleEmitter & em : emitters) { - cout << &em.data.sprite << " " << &sprite << endl; if (!(&em.data.sprite == &sprite)) continue; rendering_particles = true; if (!em.active) continue; @@ -80,19 +79,19 @@ bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) } return rendering_particles; } -void RenderSystem::render_normal(const Sprite & sprite, const Transform & tm) { +void RenderSystem::render_normal(const Sprite & sprite, const Transform & tm) const { this->context.draw(sprite, tm, *this->curr_cam_ref); } -void RenderSystem::render() { +void RenderSystem::render() const { ComponentManager & mgr = this->component_manager; vector> sprites = mgr.get_components_by_type(); - //vector> sorted_sprites = this->sort(sprites); + vector> sorted_sprites = this->sort(sprites); - for (const Sprite & sprite : sprites) { + for (const Sprite & sprite : sorted_sprites) { if (!sprite.active) continue; - Transform & transform + const Transform & transform = mgr.get_components_by_id(sprite.game_object_id).front().get(); bool rendered_particles = this->render_particle(sprite, transform.scale); diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 0393f2f..1a11d5b 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -28,19 +28,19 @@ public: * This method is called to perform all rendering operations for the current game frame. */ void update() override; - + private: //! Clears the screen in preparation for rendering. - void clear_screen() ; + void clear_screen() const; //! Presents the rendered frame to the display. - void present_screen() ; + void present_screen() const; //! Updates the active camera used for rendering. void update_camera(); //! Renders the whole screen - void render() ; + void render() const; /** * \brief Renders all the particles on the screen from a given sprite. @@ -49,7 +49,7 @@ private: * \param tm the Transform component for scale * \return true if particles have been rendered */ - bool render_particle(const Sprite & sprite, const double & scale) ; + bool render_particle(const Sprite & sprite, const double & scale) const; /** * \brief renders a sprite with a Transform component on the screen @@ -57,7 +57,7 @@ private: * \param sprite the sprite component that holds all the data * \param tm the Transform component that holds the position,rotation and scale */ - void render_normal(const Sprite & sprite, const Transform & tm) ; + void render_normal(const Sprite & sprite, const Transform & tm) const; /** * \brief sort a vector sprite objects with @@ -66,7 +66,7 @@ private: * \return returns a sorted reference vector */ std::vector> - sort(std::vector> & objs) ; + sort(std::vector> & objs) const; /** * \todo Include color handling for sprites. diff --git a/src/example/rendering_particle.cpp b/src/example/rendering_particle.cpp index 062f11f..5030bc6 100644 --- a/src/example/rendering_particle.cpp +++ b/src/example/rendering_particle.cpp @@ -15,6 +15,7 @@ #include #include +#include #include using namespace crepe; @@ -27,11 +28,11 @@ int main(int argc, char * argv[]) { ParticleSystem psys{mgr}; Color color(255, 255, 255, 255); - //game_object.add_component(make_shared("../asset/texture/img.png"), color, FlipSettings{false,false}); - Sprite test_sprite = game_object.add_component( + Sprite & test_sprite = game_object.add_component( make_shared("../asset/texture/img.png"), color, FlipSettings{false, false}); - game_object.add_component(ParticleEmitter::Data{ + test_sprite.order_in_layer = 5; + auto test = game_object.add_component(ParticleEmitter::Data{ .position = {0, 0}, .max_particles = 10, .emission_rate = 0.1, @@ -52,6 +53,11 @@ int main(int argc, char * argv[]) { }); game_object.add_component(Color::WHITE); + game_object + .add_component(make_shared("../asset/texture/img.png"), color, + FlipSettings{false, false}) + .order_in_layer + = 6; auto start = std::chrono::steady_clock::now(); while (std::chrono::steady_clock::now() - start < std::chrono::seconds(5)) { -- cgit v1.2.3 From d9a51069366650051e644453f5d3ac90f2ab29b5 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 20 Nov 2024 16:29:48 +0100 Subject: turn examples into unit tests --- src/crepe/util/Proxy.h | 2 ++ src/crepe/util/Proxy.hpp | 6 +++++ src/example/CMakeLists.txt | 3 --- src/example/log.cpp | 28 ------------------- src/example/proxy.cpp | 45 ------------------------------- src/example/script.cpp | 49 --------------------------------- src/test/CMakeLists.txt | 1 + src/test/ValueBrokerTest.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 73 insertions(+), 125 deletions(-) delete mode 100644 src/example/log.cpp delete mode 100644 src/example/proxy.cpp delete mode 100644 src/example/script.cpp create mode 100644 src/test/ValueBrokerTest.cpp diff --git a/src/crepe/util/Proxy.h b/src/crepe/util/Proxy.h index b34f7c6..789144a 100644 --- a/src/crepe/util/Proxy.h +++ b/src/crepe/util/Proxy.h @@ -15,6 +15,8 @@ namespace crepe { template class Proxy { public: + //! Set operator + Proxy & operator=(Proxy &); //! Set operator Proxy & operator=(const T &); //! Get operator diff --git a/src/crepe/util/Proxy.hpp b/src/crepe/util/Proxy.hpp index b9923db..ef2b69f 100644 --- a/src/crepe/util/Proxy.hpp +++ b/src/crepe/util/Proxy.hpp @@ -13,6 +13,12 @@ Proxy & Proxy::operator=(const T & val) { return *this; } +template +Proxy & Proxy::operator=(Proxy & proxy) { + this->broker.set(T(proxy)); + return *this; +} + template Proxy::operator const T &() { return this->broker.get(); diff --git a/src/example/CMakeLists.txt b/src/example/CMakeLists.txt index 30432e5..f21bd24 100644 --- a/src/example/CMakeLists.txt +++ b/src/example/CMakeLists.txt @@ -17,13 +17,10 @@ function(add_example target_name) endfunction() add_example(audio_internal) -add_example(script) -add_example(log) add_example(rendering) add_example(asset_manager) add_example(physics) add_example(savemgr) -add_example(proxy) add_example(db) add_example(particles) add_example(gameloop) diff --git a/src/example/log.cpp b/src/example/log.cpp deleted file mode 100644 index 5baa021..0000000 --- a/src/example/log.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/** \file - * - * Standalone example for usage of the logging functions - */ - -#include -#include - -using namespace crepe; - -// unrelated setup code -int _ = []() { - // make sure all log messages get printed - auto & cfg = Config::get_instance(); - cfg.log.level = Log::Level::TRACE; - - return 0; // satisfy compiler -}(); - -int main() { - dbg_trace(); - dbg_log("debug message"); - Log::logf("info message with variable: {}", 3); - Log::logf(Log::Level::WARNING, "warning"); - Log::logf(Log::Level::ERROR, "error"); - - return 0; -} diff --git a/src/example/proxy.cpp b/src/example/proxy.cpp deleted file mode 100644 index 69451f8..0000000 --- a/src/example/proxy.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/** \file - * - * Standalone example for usage of the proxy type - */ - -#include -#include -#include -#include - -using namespace std; -using namespace crepe; - -void test_ro_ref(const int & val) {} -void test_rw_ref(int & val) {} -void test_ro_val(int val) {} - -int main() { - auto & cfg = Config::get_instance(); - cfg.log.level = Log::Level::DEBUG; - - int real_value = 0; - - ValueBroker broker{ - [&real_value](const int & target) { - dbg_logf("set {} to {}", real_value, target); - real_value = target; - }, - [&real_value]() -> const int & { - dbg_logf("get {}", real_value); - return real_value; - }, - }; - - Proxy proxy{broker}; - - broker.set(54); - proxy = 84; - - test_ro_ref(proxy); // this is allowed - // test_rw_ref(proxy); // this should throw a compile error - test_ro_val(proxy); - - return 0; -} diff --git a/src/example/script.cpp b/src/example/script.cpp deleted file mode 100644 index a23295b..0000000 --- a/src/example/script.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/** \file - * - * Standalone example for usage of the script component and system - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -using namespace crepe; -using namespace std; - -// Unrelated stuff that is not part of this POC -int _ = []() { - // Show dbg_trace() output - auto & cfg = Config::get_instance(); - cfg.log.level = Log::Level::TRACE; - - return 0; // satisfy compiler -}(); - -// User-defined script: -class MyScript : public Script { - 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); - } -}; - -int main() { - ComponentManager component_manager{}; - ScriptSystem system{component_manager}; - - // Create game object with Transform and BehaviorScript components - GameObject obj = component_manager.new_object("name"); - obj.add_component().set_script(); - - // Update all scripts. This should result in MyScript::update being called - system.update(); - - return EXIT_SUCCESS; -} diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index d56d80f..c1f935d 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -5,5 +5,6 @@ target_sources(test_main PUBLIC ParticleTest.cpp ECSTest.cpp SceneManagerTest.cpp + ValueBrokerTest.cpp ) diff --git a/src/test/ValueBrokerTest.cpp b/src/test/ValueBrokerTest.cpp new file mode 100644 index 0000000..10a4654 --- /dev/null +++ b/src/test/ValueBrokerTest.cpp @@ -0,0 +1,64 @@ +#include + +#include +#include + +using namespace std; +using namespace crepe; +using namespace testing; + +class ValueBrokerTest : public Test { +public: + int read_count = 0; + int write_count = 0; + int value = 0; + + ValueBroker broker { + [this](const int & target) -> void { + this->write_count++; + this->value = target; + }, + [this]() -> const int & { + this->read_count++; + return this->value; + }, + }; + Proxy proxy{broker}; + + void SetUp() override { + ASSERT_EQ(read_count, 0); + ASSERT_EQ(write_count, 0); + } +}; + +TEST_F(ValueBrokerTest, BrokerWrite) { + broker.set(0); + EXPECT_EQ(read_count, 0); + EXPECT_EQ(write_count, 1); +} + +TEST_F(ValueBrokerTest, BrokerRead) { + broker.get(); + EXPECT_EQ(read_count, 1); + EXPECT_EQ(write_count, 0); +} + +TEST_F(ValueBrokerTest, ProxyWrite) { + proxy = 0; + EXPECT_EQ(read_count, 0); + EXPECT_EQ(write_count, 1); +} + +void dummy(int) { } +TEST_F(ValueBrokerTest, ProxyRead) { + dummy(proxy); + EXPECT_EQ(read_count, 1); + EXPECT_EQ(write_count, 0); +} + +TEST_F(ValueBrokerTest, ProxyReadWrite) { + proxy = proxy; + ASSERT_EQ(read_count, 1); + ASSERT_EQ(write_count, 1); +} + -- 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(-) 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 fdf91122ddc1fa9942c8790d2c8c845f877df11d Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 20 Nov 2024 16:46:00 +0100 Subject: convert more examples to unit tests --- src/crepe/facade/DB.cpp | 4 +-- src/crepe/facade/DB.h | 4 ++- src/example/CMakeLists.txt | 5 --- src/example/audio_internal.cpp | 56 -------------------------------- src/example/db.cpp | 30 ------------------ src/example/particles.cpp | 43 ------------------------- src/example/physics.cpp | 24 -------------- src/example/rendering.cpp | 72 ------------------------------------------ src/test/CMakeLists.txt | 1 + src/test/DBTest.cpp | 29 +++++++++++++++++ 10 files changed, 35 insertions(+), 233 deletions(-) delete mode 100644 src/example/audio_internal.cpp delete mode 100644 src/example/db.cpp delete mode 100644 src/example/particles.cpp delete mode 100644 src/example/physics.cpp delete mode 100644 src/example/rendering.cpp create mode 100644 src/test/DBTest.cpp diff --git a/src/crepe/facade/DB.cpp b/src/crepe/facade/DB.cpp index d5d19dc..95cf606 100644 --- a/src/crepe/facade/DB.cpp +++ b/src/crepe/facade/DB.cpp @@ -18,8 +18,8 @@ DB::DB(const string & path) { this->db = {db, [](libdb::DB * db) { db->close(db, 0); }}; // load or create database file - ret = this->db->open(this->db.get(), NULL, path.c_str(), NULL, libdb::DB_BTREE, DB_CREATE, - 0); + const char * file = path.empty() ? NULL : path.c_str(); + ret = this->db->open(this->db.get(), NULL, file, NULL, libdb::DB_BTREE, DB_CREATE, 0); if (ret != 0) throw runtime_error(format("db->open: {}", libdb::db_strerror(ret))); // create cursor diff --git a/src/crepe/facade/DB.h b/src/crepe/facade/DB.h index 629b0eb..115c0f1 100644 --- a/src/crepe/facade/DB.h +++ b/src/crepe/facade/DB.h @@ -22,8 +22,10 @@ class DB { public: /** * \param path The path of the database (created if nonexistant) + * + * \note If \p path is empty, the database is entirely in-memory */ - DB(const std::string & path); + DB(const std::string & path = ""); virtual ~DB() = default; public: diff --git a/src/example/CMakeLists.txt b/src/example/CMakeLists.txt index f21bd24..c75a4b5 100644 --- a/src/example/CMakeLists.txt +++ b/src/example/CMakeLists.txt @@ -16,12 +16,7 @@ function(add_example target_name) add_dependencies(examples ${target_name}) endfunction() -add_example(audio_internal) -add_example(rendering) add_example(asset_manager) -add_example(physics) add_example(savemgr) -add_example(db) -add_example(particles) add_example(gameloop) diff --git a/src/example/audio_internal.cpp b/src/example/audio_internal.cpp deleted file mode 100644 index 661161a..0000000 --- a/src/example/audio_internal.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/** \file - * - * Standalone example for usage of the internal \c Sound class. - */ - -#include -#include -#include - -#include - -using namespace crepe; -using namespace std; -using namespace std::chrono_literals; -using std::make_unique; - -// Unrelated stuff that is not part of this POC -int _ = []() { - // Show dbg_trace() output - auto & cfg = Config::get_instance(); - cfg.log.level = Log::Level::TRACE; - - return 0; // satisfy compiler -}(); - -int main() { - // Load a background track (Ogg Vorbis) - auto bgm = Sound("../mwe/audio/bgm.ogg"); - // Load three short samples (WAV) - auto sfx1 = Sound("../mwe/audio/sfx1.wav"); - auto sfx2 = Sound("../mwe/audio/sfx2.wav"); - auto sfx3 = Sound("../mwe/audio/sfx3.wav"); - - // Start the background track - bgm.play(); - - // Play each sample sequentially while pausing and resuming the background track - this_thread::sleep_for(500ms); - sfx1.play(); - this_thread::sleep_for(500ms); - sfx2.play(); - bgm.pause(); - this_thread::sleep_for(500ms); - sfx3.play(); - bgm.play(); - this_thread::sleep_for(500ms); - - // Play all samples simultaniously - sfx1.play(); - sfx2.play(); - sfx3.play(); - this_thread::sleep_for(1000ms); - - // Stop all audio and exit - return EXIT_SUCCESS; -} diff --git a/src/example/db.cpp b/src/example/db.cpp deleted file mode 100644 index ee4e8fc..0000000 --- a/src/example/db.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include - -using namespace crepe; -using namespace std; - -// run before main -static auto _ = []() { - auto & cfg = Config::get_instance(); - cfg.log.level = Log::Level::TRACE; - return 0; -}(); - -int main() { - dbg_trace(); - - DB db("file.db"); - - const char * test_key = "test-key"; - string test_data = "Hello world!"; - - dbg_logf("DB has key = {}", db.has(test_key)); - - db.set(test_key, test_data); - - dbg_logf("key = \"{}\"", db.get(test_key)); - - return 0; -} diff --git a/src/example/particles.cpp b/src/example/particles.cpp deleted file mode 100644 index 3d5f676..0000000 --- a/src/example/particles.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace crepe; -using namespace std; - -int main(int argc, char * argv[]) { - ComponentManager mgr{}; - GameObject game_object = mgr.new_object("", "", Vector2{0, 0}, 0, 0); - Color color(0, 0, 0, 0); - Sprite test_sprite = game_object.add_component( - make_shared("../asset/texture/img.png"), color, FlipSettings{true, true}); - game_object.add_component(ParticleEmitter::Data{ - .position = {0, 0}, - .max_particles = 100, - .emission_rate = 0, - .min_speed = 0, - .max_speed = 0, - .min_angle = 0, - .max_angle = 0, - .begin_lifespan = 0, - .end_lifespan = 0, - .force_over_time = Vector2{0, 0}, - .boundary{ - .width = 0, - .height = 0, - .offset = Vector2{0, 0}, - .reset_on_exit = false, - }, - .sprite = test_sprite, - }); - - return 0; -} diff --git a/src/example/physics.cpp b/src/example/physics.cpp deleted file mode 100644 index ad663a0..0000000 --- a/src/example/physics.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include -#include -#include - -using namespace crepe; -using namespace std; - -int main(int argc, char * argv[]) { - ComponentManager mgr{}; - - GameObject game_object = mgr.new_object("Name", "Tag", Vector2{0, 0}, 0, 0); - game_object.add_component(Rigidbody::Data{ - .mass = 1, - .gravity_scale = 1, - .body_type = Rigidbody::BodyType::DYNAMIC, - .constraints = {0, 0, 0}, - .use_gravity = true, - .bounce = false, - }); - return 0; -} diff --git a/src/example/rendering.cpp b/src/example/rendering.cpp deleted file mode 100644 index ecd3f6a..0000000 --- a/src/example/rendering.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "api/Camera.h" -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -using namespace std; -using namespace crepe; - -int main() { - dbg_trace(); - - ComponentManager mgr{}; - RenderSystem sys{mgr}; - - GameObject obj = mgr.new_object("name", "tag", Vector2{0, 0}, 1, 1); - GameObject obj1 = mgr.new_object("name", "tag", Vector2{500, 0}, 1, 0.1); - GameObject obj2 = mgr.new_object("name", "tag", Vector2{800, 0}, 1, 0.1); - - // Normal adding components - { - Color color(0, 0, 0, 0); - Sprite & sprite - = obj.add_component(make_shared("../asset/texture/img.png"), - color, FlipSettings{false, false}); - sprite.sorting_in_layer = 2; - sprite.order_in_layer = 1; - obj.add_component(Color::get_red()); - } - { - Color color(0, 0, 0, 0); - Sprite & sprite = obj1.add_component( - make_shared("../asset/texture/img.png"), color, FlipSettings{true, true}); - sprite.sorting_in_layer = 2; - sprite.order_in_layer = 2; - } - - { - Color color(0, 0, 0, 0); - Sprite & sprite = obj2.add_component( - make_shared("../asset/texture/img.png"), color, FlipSettings{true, true}); - sprite.sorting_in_layer = 1; - sprite.order_in_layer = 2; - } - - /* - { - Color color(0, 0, 0, 0); - auto img = mgr.cache("../asset/texture/second.png"); - obj2.add_component(img, color, FlipSettings{true, true}); - } - */ - - sys.update(); - /* - - auto start = std::chrono::steady_clock::now(); - while (std::chrono::steady_clock::now() - start < std::chrono::seconds(5)) { - sys.update(); - } - */ -} diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index c1f935d..61dd2d9 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -6,5 +6,6 @@ target_sources(test_main PUBLIC ECSTest.cpp SceneManagerTest.cpp ValueBrokerTest.cpp + DBTest.cpp ) diff --git a/src/test/DBTest.cpp b/src/test/DBTest.cpp new file mode 100644 index 0000000..b57eba9 --- /dev/null +++ b/src/test/DBTest.cpp @@ -0,0 +1,29 @@ +#include +#include + +using namespace std; +using namespace crepe; +using namespace testing; + +class DBTest : public Test { +public: + DB db; +}; + +TEST_F(DBTest, ReadWrite) { + db.set("foo", "bar"); + EXPECT_EQ(db.get("foo"), "bar"); +} + +TEST_F(DBTest, Nonexistant) { + EXPECT_THROW(db.get("foo"), std::out_of_range); + db.set("foo", "bar"); + EXPECT_NO_THROW(db.get("foo")); +} + +TEST_F(DBTest, Has) { + EXPECT_EQ(db.has("foo"), false); + db.set("foo", "bar"); + EXPECT_EQ(db.has("foo"), true); +} + -- cgit v1.2.3 From 9a46acde813e00e574e70439795dedcdc9a8192a Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Wed, 20 Nov 2024 18:41:50 +0100 Subject: dispatch fixed and priority added --- src/crepe/api/EventManager.cpp | 73 ++++++++------------- src/crepe/api/EventManager.hpp | 95 ++++++++++----------------- src/crepe/api/KeyCodes.h | 29 ++++++--- src/test/EventTest.cpp | 142 +---------------------------------------- 4 files changed, 84 insertions(+), 255 deletions(-) diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index 27a304f..4f88e97 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -8,58 +8,37 @@ EventManager & EventManager::get_instance() { } void EventManager::dispatch_events() { - 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 = (*event_it).event; + int channel = (*event_it).channel; + std::type_index event_type = (*event_it).type; - for (auto event_it = this->events_queue.begin(); event_it != this->events_queue.end();) { - std::unique_ptr & event = (*event_it).event; - int channel = (*event_it).channel; - std::type_index event_type = (*event_it).type; + bool event_handled = false; + auto handlers_it = this->subscribers.find(event_type); + if (handlers_it != this->subscribers.end()) { + std::vector& handlers = handlers_it->second; + + std::sort(handlers.begin(), handlers.end(), [](const CallbackEntry& a, const CallbackEntry& b) { + return a.priority > b.priority; + }); - bool event_handled = false; + 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 (channel) { - auto handlers_it = subscribers_by_event_id.find(event_type); - if (handlers_it != subscribers_by_event_id.end()) { - HandlersMap & handlers_map = handlers_it->second; - auto handlers = handlers_map.find(channel); - if (handlers != handlers_map.end()) { - 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; - break; - } - } - } - } - } else { - // Handle event for all channels - auto handlers_it = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - 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); - event_handled = true; - break; - } - } - } - } - - if (!event_handled) { - ++event_it; - } - } + if (!event_handled) { + ++event_it; + } + } } + void EventManager::clear(){ this->subscribers.clear(); this->events_queue.clear(); - this->subscribers_by_event_id.clear(); } diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp index 3a40336..481017d 100644 --- a/src/crepe/api/EventManager.hpp +++ b/src/crepe/api/EventManager.hpp @@ -4,17 +4,20 @@ namespace crepe { template void EventManager::subscribe(const EventHandler & callback, int channel, int priority) { - using HandlersVec = std::vector; std::type_index event_type = typeid(EventType); std::unique_ptr> handler = std::make_unique>(callback); - HandlersVec & handlers = this->subscribers[event_type]; + std::vector & handlers = this->subscribers[event_type]; handlers.emplace_back(CallbackEntry{ .callback = std::move(handler), .channel = channel, .priority = priority, }); + // Sort handlers by priority (highest first) + std::sort(handlers.begin(), handlers.end(), [](const CallbackEntry &a, const CallbackEntry &b) { + return a.priority > b.priority; + }); } template @@ -36,72 +39,44 @@ void EventManager::queue_event(const EventType & event, int channel,int priority template void EventManager::trigger_event(const EventType & event, int channel) { - using HandlersMap - = std::unordered_map>>; - using HandlersVec = std::vector>; + std::type_index event_type = typeid(EventType); - std::type_index event_type = typeid(EventType); - - if (channel == CHANNEL_ALL) { - HandlersMap & handlers_map = this->subscribers_by_event_id[event_type]; - auto handlers_it = handlers_map.find(channel); + auto handlers_it = this->subscribers.find(event_type); + if (handlers_it != this->subscribers.end()) { + const std::vector &handlers = handlers_it->second; - if (handlers_it != handlers_map.end()) { - HandlersVec & handlers = handlers_it->second; - for (auto it = handlers.begin(); it != handlers.end(); ++it) { - // stops when callback returns true - if ((*it)->exec(event)) { - break; - } - } - } - } else { - 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; - } - } - } + for (const CallbackEntry &handler : handlers) { + if (handler.channel != channel && handler.channel != CHANNEL_ALL) { + continue; + } + if (handler.callback->exec(event)) { + break; + } + } + } } + template 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(); - 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 & handlers = handlers_it->second; - if (channel) { - auto subscriber_list = this->subscribers_by_event_id.find(event_type); - if (subscriber_list != this->subscribers_by_event_id.end()) { - HandlersMap & handlers_map = subscriber_list->second; - auto handlers = handlers_map.find(channel); - if (handlers != handlers_map.end()) { - HandlersVec & callbacks = handlers->second; - for (auto it = callbacks.begin(); it != callbacks.end(); ++it) { - if ((*it)->get_type() == handler_name) { - it = callbacks.erase(it); - return; - } - } - } - } - } else { - auto handlers_it = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - 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; - } - } - } - } + 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/KeyCodes.h b/src/crepe/api/KeyCodes.h index feed0b2..16c2108 100644 --- a/src/crepe/api/KeyCodes.h +++ b/src/crepe/api/KeyCodes.h @@ -1,7 +1,6 @@ #pragma once -//! \enum MouseButton -//! \brief Enumeration for mouse button inputs, including standard and extended buttons. +//! Enumeration for mouse button inputs, including standard and extended buttons. enum class MouseButton { //! No mouse button input. NONE = 0, @@ -18,12 +17,11 @@ enum class MouseButton { //! Scroll wheel upward movement. SCROLL_UP = 6, //! Scroll wheel downward movement. - SCROLL_DOWN = 7 + SCROLL_DOWN = 7, }; -//! \enum Keycode -//! \brief Enumeration for keyboard key inputs, including printable characters, function keys, and keypad keys. -enum class Keycode : int { +//! Enumeration for keyboard key inputs, including printable characters, function keys, and keypad keys. +enum class Keycode { //! No key input. NONE = 0, //! Spacebar. @@ -164,7 +162,10 @@ enum class Keycode : int { PRINT_SCREEN = 283, //! Pause key. PAUSE = 284, - //! Function keys (F1-F25). + /** + * \name Function keys (F1-F25). + * \{ + */ F1 = 290, F2 = 291, F3 = 292, @@ -190,7 +191,11 @@ enum class Keycode : int { F23 = 312, F24 = 313, F25 = 314, - //! Keypad digits and operators. + /// \} + /** + * \name Keypad digits and operators. + * \{ + */ KP0 = 320, KP1 = 321, KP2 = 322, @@ -208,6 +213,11 @@ enum class Keycode : int { KP_ADD = 334, KP_ENTER = 335, KP_EQUAL = 336, + /// \} + /** + * \name Modifier keys. + * \{ + */ //! Modifier keys. LEFT_SHIFT = 340, LEFT_CONTROL = 341, @@ -217,6 +227,7 @@ enum class Keycode : int { RIGHT_CONTROL = 345, RIGHT_ALT = 346, RIGHT_SUPER = 347, + /// \} //! Menu key. - MENU = 348 + MENU = 348, }; diff --git a/src/test/EventTest.cpp b/src/test/EventTest.cpp index 19f6d2e..3a78590 100644 --- a/src/test/EventTest.cpp +++ b/src/test/EventTest.cpp @@ -105,8 +105,8 @@ TEST_F(EventManagerTest, EventManagerTest_priority_order) { // 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); + event_manager.subscribe(handler_priority_2, CHANNEL_ALL, 2); // Trigger the event event_manager.trigger_event(MouseClickEvent{ @@ -242,9 +242,9 @@ TEST_F(EventManagerTest, EventManagerTest_dispatch_priority) { 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.subscribe(mouse_handler1,CHANNEL_ALL,1); + event_manager.subscribe(mouse_handler3,CHANNEL_ALL,3); event_manager.queue_event(MouseClickEvent{ .mouse_x = 100, .mouse_y = 200, @@ -278,7 +278,6 @@ TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); return false; // Allows propagation }; - // Subscribe handlers event_manager.subscribe(mouse_handler1); event_manager.subscribe(mouse_handler2); @@ -333,138 +332,3 @@ TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { 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 9f882131f09410113d757d96e5aa0322aa5584bd Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Wed, 20 Nov 2024 18:48:18 +0100 Subject: git remake --- mwe/events/include/event.h | 2 +- src/crepe/api/EventManager.cpp | 60 ++--- src/crepe/api/EventManager.h | 19 +- src/crepe/api/EventManager.hpp | 87 ++++--- src/crepe/api/IKeyListener.cpp | 8 +- src/crepe/api/IKeyListener.h | 1 + src/crepe/api/IMouseListener.cpp | 3 +- src/crepe/api/IMouseListener.h | 1 + src/example/events.cpp | 10 +- src/test/EventTest.cpp | 530 +++++++++++++++++++-------------------- 10 files changed, 344 insertions(+), 377 deletions(-) diff --git a/mwe/events/include/event.h b/mwe/events/include/event.h index ee1bf52..e1b220b 100644 --- a/mwe/events/include/event.h +++ b/mwe/events/include/event.h @@ -148,7 +148,7 @@ private: }; class ShutDownEvent : public Event { public: - ShutDownEvent() : Event("ShutDownEvent") {}; + ShutDownEvent() : Event("ShutDownEvent"){}; REGISTER_EVENT_TYPE(ShutDownEvent) diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index 4f88e97..dbdb0c3 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -8,37 +8,39 @@ EventManager & EventManager::get_instance() { } void EventManager::dispatch_events() { - for (auto event_it = this->events_queue.begin(); event_it != this->events_queue.end();) { - std::unique_ptr& event = (*event_it).event; - int channel = (*event_it).channel; - std::type_index event_type = (*event_it).type; - - bool event_handled = false; - auto handlers_it = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - std::vector& 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 (!event_handled) { - ++event_it; - } - } + for (auto event_it = this->events_queue.begin(); event_it != this->events_queue.end();) { + std::unique_ptr & event = (*event_it).event; + int channel = (*event_it).channel; + std::type_index event_type = (*event_it).type; + + bool event_handled = false; + auto handlers_it = this->subscribers.find(event_type); + if (handlers_it != this->subscribers.end()) { + std::vector & 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 (!event_handled) { + ++event_it; + } + } } -void EventManager::clear(){ +void EventManager::clear() { this->subscribers.clear(); this->events_queue.clear(); } diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index eccb0bf..133d72d 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -19,7 +19,6 @@ static constexpr int CHANNEL_ALL = -1; */ class EventManager { public: - /** * \brief Get the singleton instance of the EventManager. * @@ -39,7 +38,8 @@ public: * \param channel The channel number to subscribe to (default is 0). */ template - void subscribe(const EventHandler & callback, int channel = CHANNEL_ALL, int priority = 0); + void subscribe(const EventHandler & callback, int channel = CHANNEL_ALL, + int priority = 0); /** * \brief Unsubscribe from an event. @@ -76,7 +76,7 @@ public: * \param channel The channel number for the event (default is 0). */ template - void queue_event(const EventType & event, int channel = CHANNEL_ALL,int priority = 0); + void queue_event(const EventType & event, int channel = CHANNEL_ALL, int priority = 0); /** * \brief Dispatch all queued events. @@ -90,8 +90,8 @@ public: * */ void clear(); + private: - /** * \brief Default constructor for the EventManager. * @@ -99,21 +99,20 @@ private: */ EventManager() = default; struct QueueEntry { - std::unique_ptr event; + std::unique_ptr event; int channel = CHANNEL_ALL; std::type_index type; int priority = 0; - }; + }; struct CallbackEntry { - std::unique_ptr callback; + std::unique_ptr callback; int channel = CHANNEL_ALL; int priority = 0; - }; + }; //! The queue of events to be processed. std::vector events_queue; //! Registered event handlers. - std::unordered_map> subscribers; - + std::unordered_map> subscribers; }; } // namespace crepe diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp index 481017d..a04a43a 100644 --- a/src/crepe/api/EventManager.hpp +++ b/src/crepe/api/EventManager.hpp @@ -3,7 +3,8 @@ namespace crepe { template -void EventManager::subscribe(const EventHandler & callback, int channel, int priority) { +void EventManager::subscribe(const EventHandler & callback, int channel, + int priority) { std::type_index event_type = typeid(EventType); std::unique_ptr> handler @@ -14,69 +15,65 @@ void EventManager::subscribe(const EventHandler & callback, int chann .channel = channel, .priority = priority, }); - // Sort handlers by priority (highest first) - std::sort(handlers.begin(), handlers.end(), [](const CallbackEntry &a, const CallbackEntry &b) { - return a.priority > b.priority; - }); + // Sort handlers by priority (highest first) + std::sort(handlers.begin(), handlers.end(), + [](const CallbackEntry & a, const CallbackEntry & b) { + return a.priority > b.priority; + }); } template -void EventManager::queue_event(const EventType & event, int channel,int priority) { - static_assert(std::is_base_of::value, "EventType must derive from Event"); +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(event); - this->events_queue.push_back( - QueueEntry{ - .event = std::move(event_ptr), - .channel = channel, - .type = event_type, - .priority = priority - } - ); + this->events_queue.push_back(QueueEntry{.event = std::move(event_ptr), + .channel = channel, + .type = event_type, + .priority = priority}); } template void EventManager::trigger_event(const EventType & event, int channel) { - std::type_index event_type = typeid(EventType); + std::type_index event_type = typeid(EventType); - auto handlers_it = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - const std::vector &handlers = handlers_it->second; + auto handlers_it = this->subscribers.find(event_type); + if (handlers_it != this->subscribers.end()) { + const std::vector & handlers = handlers_it->second; - for (const CallbackEntry &handler : handlers) { - if (handler.channel != channel && handler.channel != CHANNEL_ALL) { - continue; - } - if (handler.callback->exec(event)) { - break; - } - } - } + for (const CallbackEntry & handler : handlers) { + if (handler.channel != channel && handler.channel != CHANNEL_ALL) { + continue; + } + if (handler.callback->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(); + 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 & handlers = handlers_it->second; + // 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 & 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; - } - } + 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 5e7d9bb..6a522c1 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -2,7 +2,6 @@ using namespace crepe; - // Constructor with specified channel IKeyListener::IKeyListener(int channel) : channel(channel), @@ -21,10 +20,8 @@ void IKeyListener::subscribe_events() { key_released_handler = [this](const KeyReleaseEvent & event) { return this->on_key_released(event); }; - event_manager.subscribe(this->key_pressed_handler, - this->channel); - event_manager.subscribe(this->key_released_handler, - this->channel); + event_manager.subscribe(this->key_pressed_handler, this->channel); + event_manager.subscribe(this->key_released_handler, this->channel); } // Unsubscribe from key events @@ -32,4 +29,3 @@ void IKeyListener::unsubscribe_events() { event_manager.unsubscribe(this->key_pressed_handler, this->channel); event_manager.unsubscribe(this->key_released_handler, this->channel); } - diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index 70243b4..9402cce 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -36,6 +36,7 @@ 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. diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index 6fd6c4b..f3ceb84 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -24,8 +24,7 @@ void IMouseListener::subscribe_events() { // Subscribe event handlers (no need for std::move) 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(mouse_release_handler, this->channel); event_manager.subscribe(mouse_move_handler, this->channel); } diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 1195a4e..6bc5716 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -55,6 +55,7 @@ public: * \return True if the event was handled, false otherwise. */ virtual bool on_mouse_moved(const MouseMoveEvent & event) = 0; + protected: /** * \brief Subscribes to mouse events on the specified channel. diff --git a/src/example/events.cpp b/src/example/events.cpp index 402a857..3dee9fa 100644 --- a/src/example/events.cpp +++ b/src/example/events.cpp @@ -63,9 +63,9 @@ public: } }; int main() { - + { - // two events to trigger + // two events to trigger KeyPressEvent key_press; key_press.key = Keycode::A; key_press.repeat = 0; @@ -106,10 +106,8 @@ int main() { 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().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); diff --git a/src/test/EventTest.cpp b/src/test/EventTest.cpp index 3a78590..9dc2360 100644 --- a/src/test/EventTest.cpp +++ b/src/test/EventTest.cpp @@ -1,334 +1,308 @@ -#include "api/EventManager.h" #include "api/Event.h" +#include "api/EventManager.h" #include "api/IKeyListener.h" #include "api/IMouseListener.h" -#include -#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(); - } + 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)); + 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)); + 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); - + 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 + bool triggered = false; + + EventHandler 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(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); + 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_3, CHANNEL_ALL, 3); - event_manager.subscribe(handler_priority_2, CHANNEL_ALL, 2); + 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 + }; - // Trigger the event - event_manager.trigger_event(MouseClickEvent{ - .mouse_x = 100, - .mouse_y = 200, - .button = MouseButton::LEFT_MOUSE - }, CHANNEL_ALL); + 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_3, CHANNEL_ALL, 3); + event_manager.subscribe(handler_priority_2, CHANNEL_ALL, 2); - // Check the call order matches the expected priority order - std::vector expected_order = {3, 2, 1}; - EXPECT_EQ(call_order, expected_order); + // 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); + 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(); + 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 - }; + 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.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(); + EventManager & event_manager = EventManager::get_instance(); std::vector call_order; int test_channel = 1; - EventHandler mouse_handler1 = [&](const MouseClickEvent& e) { + 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_handler2,CHANNEL_ALL,2); - event_manager.subscribe(mouse_handler1,CHANNEL_ALL,1); - event_manager.subscribe(mouse_handler3,CHANNEL_ALL,3); - event_manager.queue_event(MouseClickEvent{ - .mouse_x = 100, - .mouse_y = 200, - .button = MouseButton::LEFT_MOUSE - }); + 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_handler2, CHANNEL_ALL, 2); + event_manager.subscribe(mouse_handler1, CHANNEL_ALL, 1); + event_manager.subscribe(mouse_handler3, 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); + 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 -} + 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 +} -- cgit v1.2.3 From 80712f111e5b703f4f91b9bd55f4dbb14cb14829 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 20 Nov 2024 19:00:36 +0100 Subject: remove copy/move constructors/operators on all components --- src/crepe/Component.h | 5 +++++ src/test/ParticleTest.cpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/crepe/Component.h b/src/crepe/Component.h index 5279fb3..6d405c7 100644 --- a/src/crepe/Component.h +++ b/src/crepe/Component.h @@ -27,6 +27,11 @@ protected: //! Only the ComponentManager can create components friend class ComponentManager; + Component(const Component &) = delete; + Component(Component &&) = delete; + virtual Component & operator=(const Component &) = delete; + virtual Component & operator=(Component &&) = delete; + public: virtual ~Component() = default; diff --git a/src/test/ParticleTest.cpp b/src/test/ParticleTest.cpp index 4e655a9..d9bbba0 100644 --- a/src/test/ParticleTest.cpp +++ b/src/test/ParticleTest.cpp @@ -28,7 +28,7 @@ public: GameObject game_object = mgr.new_object("", "", Vector2{0, 0}, 0, 0); Color color(0, 0, 0, 0); - Sprite test_sprite = game_object.add_component( + Sprite & test_sprite = game_object.add_component( make_shared("../asset/texture/img.png"), color, FlipSettings{true, true}); -- cgit v1.2.3 From 700892e9a2801902da31835c0069ae27da54cf4c Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Wed, 20 Nov 2024 19:21:46 +0100 Subject: implemented feedback --- src/crepe/facade/SDLContext.h | 4 ++-- src/crepe/system/RenderSystem.cpp | 11 ++++++----- src/crepe/system/RenderSystem.h | 10 +++++----- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index 9a514cb..3b17c0b 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -118,10 +118,10 @@ private: * \param transform Reference to the Transform for positioning. * \param camera Reference to the Camera for view adjustments. */ - void draw(const Sprite & sprite, const Transform & transform, const Camera & camera) const; + void draw(const Sprite & sprite, const Transform & transform, const Camera & camera) ; void draw_particle(const Sprite & sprite, const Vector2 & pos, const double & angle, - const double & scale, const Camera & camera) const; + const double & scale, const Camera & camera) ; //! Clears the screen, preparing for a new frame. void clear_screen(); diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 05b7337..e379771 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -18,9 +18,9 @@ using namespace crepe; using namespace std; -void RenderSystem::clear_screen() const { this->context.clear_screen(); } +void RenderSystem::clear_screen() { this->context.clear_screen(); } -void RenderSystem::present_screen() const { this->context.present_screen(); } +void RenderSystem::present_screen() { this->context.present_screen(); } void RenderSystem::update_camera() { ComponentManager & mgr = this->component_manager; @@ -29,6 +29,7 @@ void RenderSystem::update_camera() { if (cameras.size() == 0) throw std::runtime_error("No cameras in current scene"); for (Camera & cam : cameras) { + if (!cam.active) continue; this->context.set_camera(cam); this->curr_cam_ref = &cam; } @@ -57,7 +58,7 @@ void RenderSystem::update() { this->present_screen(); } -bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) const { +bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) { ComponentManager & mgr = this->component_manager; @@ -79,11 +80,11 @@ bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) } return rendering_particles; } -void RenderSystem::render_normal(const Sprite & sprite, const Transform & tm) const { +void RenderSystem::render_normal(const Sprite & sprite, const Transform & tm) { this->context.draw(sprite, tm, *this->curr_cam_ref); } -void RenderSystem::render() const { +void RenderSystem::render() { ComponentManager & mgr = this->component_manager; vector> sprites = mgr.get_components_by_type(); diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 1a11d5b..5a2af17 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -31,16 +31,16 @@ public: private: //! Clears the screen in preparation for rendering. - void clear_screen() const; + void clear_screen() ; //! Presents the rendered frame to the display. - void present_screen() const; + void present_screen() ; //! Updates the active camera used for rendering. void update_camera(); //! Renders the whole screen - void render() const; + void render(); /** * \brief Renders all the particles on the screen from a given sprite. @@ -49,7 +49,7 @@ private: * \param tm the Transform component for scale * \return true if particles have been rendered */ - bool render_particle(const Sprite & sprite, const double & scale) const; + bool render_particle(const Sprite & sprite, const double & scale); /** * \brief renders a sprite with a Transform component on the screen @@ -57,7 +57,7 @@ private: * \param sprite the sprite component that holds all the data * \param tm the Transform component that holds the position,rotation and scale */ - void render_normal(const Sprite & sprite, const Transform & tm) const; + void render_normal(const Sprite & sprite, const Transform & tm); /** * \brief sort a vector sprite objects with -- cgit v1.2.3 From c23c7d03522456ac580cb7acd93fbfd95d5b846d Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Wed, 20 Nov 2024 19:27:30 +0100 Subject: fixed compile warning and tested the prerequisite that user needs to set explicity and reference --- src/crepe/facade/SDLContext.cpp | 4 ++-- src/example/rendering_particle.cpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index daf0050..f78ec8f 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -122,7 +122,7 @@ SDL_Rect SDLContext::get_dst_rect(const Sprite & sprite, const Vector2 & pos, void SDLContext::draw_particle(const Sprite & sprite, const Vector2 & pos, const double & angle, const double & scale, - const Camera & camera) const { + const Camera & camera) { SDL_RendererFlip render_flip = (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * sprite.flip.flip_x) @@ -136,7 +136,7 @@ void SDLContext::draw_particle(const Sprite & sprite, const Vector2 & pos, } void SDLContext::draw(const Sprite & sprite, const Transform & transform, - const Camera & cam) const { + const Camera & cam) { SDL_RendererFlip render_flip = (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * sprite.flip.flip_x) diff --git a/src/example/rendering_particle.cpp b/src/example/rendering_particle.cpp index 5030bc6..4571afb 100644 --- a/src/example/rendering_particle.cpp +++ b/src/example/rendering_particle.cpp @@ -32,7 +32,8 @@ int main(int argc, char * argv[]) { Sprite & test_sprite = game_object.add_component( make_shared("../asset/texture/img.png"), color, FlipSettings{false, false}); test_sprite.order_in_layer = 5; - auto test = game_object.add_component(ParticleEmitter::Data{ + + auto & test = game_object.add_component(ParticleEmitter::Data{ .position = {0, 0}, .max_particles = 10, .emission_rate = 0.1, -- cgit v1.2.3 From 30492d9eee7ee47a42e2471dd0716044f59df705 Mon Sep 17 00:00:00 2001 From: heavydemon21 Date: Wed, 20 Nov 2024 19:30:34 +0100 Subject: make format --- src/crepe/Component.h | 8 ++++---- src/crepe/facade/SDLContext.cpp | 3 +-- src/crepe/facade/SDLContext.h | 4 ++-- src/crepe/system/RenderSystem.h | 4 ++-- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/crepe/Component.h b/src/crepe/Component.h index 6d405c7..dc17721 100644 --- a/src/crepe/Component.h +++ b/src/crepe/Component.h @@ -27,10 +27,10 @@ protected: //! Only the ComponentManager can create components friend class ComponentManager; - Component(const Component &) = delete; - Component(Component &&) = delete; - virtual Component & operator=(const Component &) = delete; - virtual Component & operator=(Component &&) = delete; + Component(const Component &) = delete; + Component(Component &&) = delete; + virtual Component & operator=(const Component &) = delete; + virtual Component & operator=(Component &&) = delete; public: virtual ~Component() = default; diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index f78ec8f..26a1bdc 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -135,8 +135,7 @@ void SDLContext::draw_particle(const Sprite & sprite, const Vector2 & pos, &dstrect, angle, NULL, render_flip); } -void SDLContext::draw(const Sprite & sprite, const Transform & transform, - const Camera & cam) { +void SDLContext::draw(const Sprite & sprite, const Transform & transform, const Camera & cam) { SDL_RendererFlip render_flip = (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * sprite.flip.flip_x) diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index 3b17c0b..841ffc9 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -118,10 +118,10 @@ private: * \param transform Reference to the Transform for positioning. * \param camera Reference to the Camera for view adjustments. */ - void draw(const Sprite & sprite, const Transform & transform, const Camera & camera) ; + void draw(const Sprite & sprite, const Transform & transform, const Camera & camera); void draw_particle(const Sprite & sprite, const Vector2 & pos, const double & angle, - const double & scale, const Camera & camera) ; + const double & scale, const Camera & camera); //! Clears the screen, preparing for a new frame. void clear_screen(); diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 5a2af17..d25a6e3 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -31,10 +31,10 @@ public: private: //! Clears the screen in preparation for rendering. - void clear_screen() ; + void clear_screen(); //! Presents the rendered frame to the display. - void present_screen() ; + void present_screen(); //! Updates the active camera used for rendering. void update_camera(); -- cgit v1.2.3 From b6aea9de9c9c8d86856bcd6c3b521e385bc00a69 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 20 Nov 2024 20:19:10 +0100 Subject: nitpick #31 --- src/crepe/facade/SDLContext.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index 26a1bdc..d352ea6 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -33,21 +33,21 @@ SDLContext::SDLContext() { dbg_trace(); // FIXME: read window defaults from config manager - if (SDL_Init(SDL_INIT_VIDEO) < 0) { - throw std::runtime_error("SDL could not initialize!"); + if (SDL_Init(SDL_INIT_VIDEO) != 0) { + throw runtime_error(format("SDLContext: SDL_Init error: {}", SDL_GetError())); } SDL_Window * tmp_window = SDL_CreateWindow("Crepe Game Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, this->viewport.w, this->viewport.h, 0); if (!tmp_window) { - throw std::runtime_error("Window could not be created!"); + throw runtime_error(format("SDLContext: SDL_Window error: {}", SDL_GetError())); } this->game_window = {tmp_window, [](SDL_Window * window) { SDL_DestroyWindow(window); }}; SDL_Renderer * tmp_renderer = SDL_CreateRenderer(this->game_window.get(), -1, SDL_RENDERER_ACCELERATED); if (!tmp_renderer) { - throw std::runtime_error("Renderer could not be created!"); + throw runtime_error(format("SDLContext: SDL_CreateRenderer error: {}", SDL_GetError())); } this->game_renderer @@ -55,7 +55,7 @@ SDLContext::SDLContext() { int img_flags = IMG_INIT_PNG; if (!(IMG_Init(img_flags) & img_flags)) { - throw std::runtime_error("SDL_image could not initialize!"); + throw runtime_error("SDLContext: SDL_image could not initialize!"); } } @@ -164,10 +164,8 @@ std::unique_ptr> SDLContext::texture_from_path(const std::string & path) { SDL_Surface * tmp = IMG_Load(path.c_str()); - if (tmp == nullptr) { - tmp = IMG_Load("../asset/texture/ERROR.png"); - if (tmp == nullptr) throw runtime_error("cannot load image"); - } + if (tmp == nullptr) + throw runtime_error(format("SDLContext: IMG_Load error: {}", SDL_GetError())); std::unique_ptr> img_surface; img_surface = {tmp, [](SDL_Surface * surface) { SDL_FreeSurface(surface); }}; @@ -176,7 +174,7 @@ SDLContext::texture_from_path(const std::string & path) { = SDL_CreateTextureFromSurface(this->game_renderer.get(), img_surface.get()); if (tmp_texture == nullptr) { - throw runtime_error(format("Texture cannot be load from {}", path)); + throw runtime_error(format("SDLContext: Texture cannot be load from {}", path)); } std::unique_ptr> img_texture; -- cgit v1.2.3 From 397da65e03ec681922aeea3881918026d36068a7 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Wed, 20 Nov 2024 20:24:17 +0100 Subject: result of loeks temper tantrum --- src/crepe/api/EventHandler.h | 23 +----- src/crepe/api/EventHandler.hpp | 9 +-- src/crepe/api/EventManager.cpp | 42 +++++++---- src/crepe/api/EventManager.h | 158 ++++++++++++++++++++++----------------- src/crepe/api/EventManager.hpp | 38 ++-------- src/crepe/api/IKeyListener.cpp | 26 ++----- src/crepe/api/IKeyListener.h | 26 ++----- src/crepe/api/IMouseListener.cpp | 47 +++++------- src/crepe/api/IMouseListener.h | 34 +++------ src/example/events.cpp | 120 ----------------------------- src/test/EventTest.cpp | 118 ++++++++--------------------- 11 files changed, 198 insertions(+), 443 deletions(-) delete mode 100644 src/example/events.cpp 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; * \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 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 #include "EventHandler.h" @@ -8,8 +7,7 @@ namespace crepe { // Implementation of EventHandlerWrapper constructor template EventHandlerWrapper::EventHandlerWrapper(const EventHandler & handler) - : handler(handler), - handler_type(handler.target_type().name()) {} + : handler(handler){} // Implementation of EventHandlerWrapper::call template @@ -17,10 +15,5 @@ bool EventHandlerWrapper::call(const Event & e) { return this->handler(static_cast(e)); } -// Implementation of EventHandlerWrapper::get_type -template -std::string EventHandlerWrapper::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 & 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 & 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 - void subscribe(const EventHandler & callback, int channel = CHANNEL_ALL, - int priority = 0); + subscription_t subscribe(const EventHandler & 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 - void unsubscribe(const EventHandler &, 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 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 - 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; - int channel = CHANNEL_ALL; - std::type_index type; - int priority = 0; + std::unique_ptr 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 callback; - int channel = CHANNEL_ALL; - int priority = 0; + std::unique_ptr 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 events_queue; - //! Registered event handlers. + + //! A map of event type to registered callbacks. std::unordered_map> 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 -void EventManager::subscribe(const EventHandler & callback, int channel, - int priority) { - +subscription_t EventManager::subscribe(const EventHandler & callback, int channel) { + subscription_counter++; std::type_index event_type = typeid(EventType); std::unique_ptr> handler = std::make_unique>(callback); @@ -13,17 +12,13 @@ void EventManager::subscribe(const EventHandler & 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 -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::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 @@ -55,25 +49,5 @@ void EventManager::trigger_event(const EventType & event, int channel) { } } -template -void EventManager::unsubscribe(const EventHandler & 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 & 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([this](const KeyPressEvent & event) { return this->on_key_pressed(event); }, channel); + release_id = event_manager.subscribe([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(this->key_pressed_handler, this->channel); - event_manager.subscribe(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(this->key_pressed_handler, this->channel); - event_manager.unsubscribe(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 key_pressed_handler; - //!< Key release event handler. - EventHandler 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( + [this](const MouseClickEvent & event) { return this->on_mouse_clicked(event); }, + channel); -IMouseListener::~IMouseListener() { this->unsubscribe_events(); } + press_id = event_manager.subscribe( + [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( + [this](const MouseReleaseEvent & event) { return this->on_mouse_released(event); }, + channel); - // Subscribe event handlers (no need for std::move) - 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(mouse_move_handler, this->channel); + move_id = event_manager.subscribe( + [this](const MouseMoveEvent & event) { return this->on_mouse_moved(event); }, + channel); } -void IMouseListener::unsubscribe_events() { - // 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); -} +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 mouse_click_handler; - //! Mouse press event handler. - EventHandler mouse_press_handler; - //! Mouse release event handler. - EventHandler mouse_release_handler; - //! Mouse move event handler. - EventHandler 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 - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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) 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(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 = 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; - //auto obj = GameObject(0, "name", "tag", Vector2{1.2, 3.4}, 0, 1); - //obj.add_component().set_script(); - - //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(click_event, 0); - } - // custom lambda event handler - EventHandler event_handler = [](const KeyPressEvent & e) { - 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(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); - // dispatching queued events - //EventManager::get_instance().dispatch_events(); - - EventManager::get_instance().unsubscribe(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 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 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(mouse_handler, CHANNEL_ALL); + EventManager::get_instance().subscribe(mouse_handler, EventManager::CHANNEL_ALL); MouseClickEvent click_event{ .mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}; - EventManager::get_instance().trigger_event(click_event, CHANNEL_ALL); + EventManager::get_instance().trigger_event(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 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 +TEST_F(EventManagerTest, EventManagerTest_trigger_one_channel) { + bool triggered = false; + int test_channel = 1; + EventHandler 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(mouse_handler, test_channel); - // Subscribe handlers with different priorities - event_manager.subscribe(handler_priority_1, CHANNEL_ALL, 1); - event_manager.subscribe(handler_priority_3, CHANNEL_ALL, 3); - event_manager.subscribe(handler_priority_2, CHANNEL_ALL, 2); - - // Trigger the event - event_manager.trigger_event( - 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(click_event, EventManager::CHANNEL_ALL); - // Check the call order matches the expected priority order - std::vector expected_order = {3, 2, 1}; - EXPECT_EQ(call_order, expected_order); + EXPECT_FALSE(triggered); + EventManager::get_instance().trigger_event(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(mouse_handler_true, CHANNEL_ALL, 1); - event_manager.subscribe(mouse_handler_false, CHANNEL_ALL, 0); + event_manager.subscribe(mouse_handler_true, EventManager::CHANNEL_ALL); + event_manager.subscribe(mouse_handler_false, EventManager::CHANNEL_ALL); + + // Trigger event - event_manager.trigger_event(click_event, CHANNEL_ALL); + event_manager.trigger_event(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(mouse_handler_true, CHANNEL_ALL, 0); - event_manager.subscribe(mouse_handler_false, CHANNEL_ALL, 1); + event_manager.subscribe(mouse_handler_false, EventManager::CHANNEL_ALL); + event_manager.subscribe(mouse_handler_true, EventManager::CHANNEL_ALL); + // Trigger event again - event_manager.trigger_event(click_event, CHANNEL_ALL); + event_manager.trigger_event(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 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_handler2, CHANNEL_ALL, 2); - event_manager.subscribe(mouse_handler1, CHANNEL_ALL, 1); - event_manager.subscribe(mouse_handler3, 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(); @@ -263,8 +211,8 @@ TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { return false; // Allows propagation }; // Subscribe handlers - event_manager.subscribe(mouse_handler1); - event_manager.subscribe(mouse_handler2); + subscription_t handler1_id = event_manager.subscribe(mouse_handler1); + subscription_t handler2_id = event_manager.subscribe(mouse_handler2); // Queue events event_manager.queue_event( @@ -280,7 +228,7 @@ TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { triggered2 = false; // Unsubscribe handler1 - event_manager.unsubscribe(mouse_handler1); + event_manager.unsubscribe(handler1_id); // Queue the same event again event_manager.queue_event( @@ -295,7 +243,7 @@ TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { triggered2 = false; // Unsubscribe handler2 - event_manager.unsubscribe(mouse_handler2); + event_manager.unsubscribe(handler2_id); // Queue the event again event_manager.queue_event( -- cgit v1.2.3 From 5ec30d8915debef409f6db6f8ee9b822fb24d46b Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Wed, 20 Nov 2024 20:30:33 +0100 Subject: make format --- src/crepe/api/EventHandler.hpp | 3 +-- src/crepe/api/EventManager.cpp | 24 +++++++++++------------- src/crepe/api/EventManager.h | 11 ++++++----- src/crepe/api/EventManager.hpp | 11 +++-------- src/crepe/api/IKeyListener.cpp | 17 +++++++++-------- src/crepe/api/IKeyListener.h | 6 ++++-- src/crepe/api/IMouseListener.cpp | 26 ++++++++++++-------------- src/test/EventTest.cpp | 14 ++++++-------- 8 files changed, 52 insertions(+), 60 deletions(-) diff --git a/src/crepe/api/EventHandler.hpp b/src/crepe/api/EventHandler.hpp index 8d8136b..391dcca 100644 --- a/src/crepe/api/EventHandler.hpp +++ b/src/crepe/api/EventHandler.hpp @@ -7,7 +7,7 @@ namespace crepe { // Implementation of EventHandlerWrapper constructor template EventHandlerWrapper::EventHandlerWrapper(const EventHandler & handler) - : handler(handler){} + : handler(handler) {} // Implementation of EventHandlerWrapper::call template @@ -15,5 +15,4 @@ bool EventHandlerWrapper::call(const Event & e) { return this->handler(static_cast(e)); } - } //namespace crepe diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index 64d7c26..993db86 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -20,8 +20,7 @@ void EventManager::dispatch_events() { } std::vector & handlers = handlers_it->second; - for (auto handler_it = handlers.begin(); handler_it != handlers.end(); - ++handler_it) { + 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); @@ -42,15 +41,14 @@ void EventManager::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; - } - } - } + 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 93e9ca2..bd9772a 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -48,7 +48,8 @@ public: * \return A unique subscription ID associated with the registered callback. */ template - subscription_t subscribe(const EventHandler & callback, int channel = CHANNEL_ALL); + subscription_t subscribe(const EventHandler & callback, + int channel = CHANNEL_ALL); /** * \brief Unsubscribe a previously registered callback. @@ -112,8 +113,8 @@ private: */ struct QueueEntry { std::unique_ptr event; ///< The event instance. - int channel = CHANNEL_ALL; ///< The channel associated with the event. - std::type_index type; ///< The type of the event. + int channel = CHANNEL_ALL; ///< The channel associated with the event. + std::type_index type; ///< The type of the event. }; /** @@ -122,8 +123,8 @@ private: */ struct CallbackEntry { std::unique_ptr callback; ///< The callback function wrapper. - int channel = CHANNEL_ALL; ///< The channel this callback listens to. - subscription_t id = -1; ///< Unique subscription ID. + int channel = CHANNEL_ALL; ///< The channel this callback listens to. + subscription_t id = -1; ///< Unique subscription ID. }; //! The queue of events to be processed during dispatch. diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp index d7afa9f..b2a94bd 100644 --- a/src/crepe/api/EventManager.hpp +++ b/src/crepe/api/EventManager.hpp @@ -10,10 +10,7 @@ subscription_t EventManager::subscribe(const EventHandler & callback, = std::make_unique>(callback); std::vector & handlers = this->subscribers[event_type]; handlers.emplace_back(CallbackEntry{ - .callback = std::move(handler), - .channel = channel, - .id = subscription_counter - }); + .callback = std::move(handler), .channel = channel, .id = subscription_counter}); return subscription_counter; } @@ -25,9 +22,8 @@ void EventManager::queue_event(const EventType & event, int channel) { auto event_ptr = std::make_unique(event); - this->events_queue.push_back(QueueEntry{.event = std::move(event_ptr), - .channel = channel, - .type = event_type}); + this->events_queue.push_back( + QueueEntry{.event = std::move(event_ptr), .channel = channel, .type = event_type}); } template @@ -49,5 +45,4 @@ void EventManager::trigger_event(const EventType & event, int channel) { } } - } // namespace crepe diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index ebbf486..7aefaf7 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -3,15 +3,16 @@ using namespace crepe; // Constructor with specified channel -IKeyListener::IKeyListener(int channel) : - event_manager(EventManager::get_instance()) { - press_id = event_manager.subscribe([this](const KeyPressEvent & event) { return this->on_key_pressed(event); }, channel); - release_id = event_manager.subscribe([this](const KeyReleaseEvent & event) { return this->on_key_released(event); }, channel); +IKeyListener::IKeyListener(int channel) : event_manager(EventManager::get_instance()) { + this->press_id = event_manager.subscribe( + [this](const KeyPressEvent & event) { return this->on_key_pressed(event); }, channel); + this->release_id = event_manager.subscribe( + [this](const KeyReleaseEvent & event) { return this->on_key_released(event); }, + channel); } // Destructor, unsubscribe events -IKeyListener::~IKeyListener() { - event_manager.unsubscribe(press_id); - event_manager.unsubscribe(release_id); +IKeyListener::~IKeyListener() { + event_manager.unsubscribe(this->press_id); + event_manager.unsubscribe(this->release_id); } - diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index 4726aa7..2a89cbc 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -36,12 +36,14 @@ public: * \return True if the event was handled, false otherwise. */ virtual bool on_key_released(const KeyReleaseEvent & event) = 0; + private: //! Key press event id subscription_t press_id = -1; - //!< Key release event id + //! Key release event id subscription_t release_id = -1; - EventManager & event_manager; + //! EventManager reference + EventManager & event_manager;; }; } // namespace crepe diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index a6cb163..7d38280 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -2,29 +2,27 @@ using namespace crepe; -IMouseListener::IMouseListener(int channel) - : event_manager(EventManager::get_instance()) { - click_id = event_manager.subscribe( +IMouseListener::IMouseListener(int channel) : event_manager(EventManager::get_instance()) { + this->click_id = event_manager.subscribe( [this](const MouseClickEvent & event) { return this->on_mouse_clicked(event); }, channel); - press_id = event_manager.subscribe( + this->press_id = event_manager.subscribe( [this](const MousePressEvent & event) { return this->on_mouse_pressed(event); }, channel); - release_id = event_manager.subscribe( + this->release_id = event_manager.subscribe( [this](const MouseReleaseEvent & event) { return this->on_mouse_released(event); }, channel); - move_id = event_manager.subscribe( - [this](const MouseMoveEvent & event) { return this->on_mouse_moved(event); }, - channel); + this->move_id = event_manager.subscribe( + [this](const MouseMoveEvent & event) { return this->on_mouse_moved(event); }, 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); - } + // Unsubscribe event handlers + event_manager.unsubscribe(this->click_id); + event_manager.unsubscribe(this->press_id); + event_manager.unsubscribe(this->release_id); + event_manager.unsubscribe(this->move_id); +} diff --git a/src/test/EventTest.cpp b/src/test/EventTest.cpp index d42e742..b0e6c9c 100644 --- a/src/test/EventTest.cpp +++ b/src/test/EventTest.cpp @@ -70,11 +70,13 @@ TEST_F(EventManagerTest, EventManagerTest_trigger_all_channels) { EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); return false; }; - EventManager::get_instance().subscribe(mouse_handler, EventManager::CHANNEL_ALL); + EventManager::get_instance().subscribe(mouse_handler, + EventManager::CHANNEL_ALL); MouseClickEvent click_event{ .mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}; - EventManager::get_instance().trigger_event(click_event, EventManager::CHANNEL_ALL); + EventManager::get_instance().trigger_event(click_event, + EventManager::CHANNEL_ALL); EXPECT_TRUE(triggered); } @@ -92,13 +94,13 @@ TEST_F(EventManagerTest, EventManagerTest_trigger_one_channel) { MouseClickEvent click_event{ .mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}; - EventManager::get_instance().trigger_event(click_event, EventManager::CHANNEL_ALL); + EventManager::get_instance().trigger_event(click_event, + EventManager::CHANNEL_ALL); EXPECT_FALSE(triggered); EventManager::get_instance().trigger_event(click_event, test_channel); } - TEST_F(EventManagerTest, EventManagerTest_callback_propagation) { EventManager & event_manager = EventManager::get_instance(); @@ -128,8 +130,6 @@ TEST_F(EventManagerTest, EventManagerTest_callback_propagation) { .mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}; event_manager.subscribe(mouse_handler_true, EventManager::CHANNEL_ALL); event_manager.subscribe(mouse_handler_false, EventManager::CHANNEL_ALL); - - // Trigger event event_manager.trigger_event(click_event, EventManager::CHANNEL_ALL); @@ -144,7 +144,6 @@ TEST_F(EventManagerTest, EventManagerTest_callback_propagation) { event_manager.clear(); event_manager.subscribe(mouse_handler_false, EventManager::CHANNEL_ALL); event_manager.subscribe(mouse_handler_true, EventManager::CHANNEL_ALL); - // Trigger event again event_manager.trigger_event(click_event, EventManager::CHANNEL_ALL); @@ -186,7 +185,6 @@ TEST_F(EventManagerTest, EventManagerTest_queue_dispatch) { EXPECT_TRUE(triggered2); } - TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { EventManager & event_manager = EventManager::get_instance(); -- cgit v1.2.3 From 8e72968e294cbc4ac6e9ff09bd94cde1775d735b Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 20 Nov 2024 21:51:30 +0100 Subject: nitpick #34 --- mwe/events/include/event.h | 2 +- src/crepe/api/EventManager.cpp | 54 +++++++++++++++++----------------------- src/crepe/api/EventManager.h | 39 +++++++++++++++++++++-------- src/crepe/api/EventManager.hpp | 36 +++++++++------------------ src/crepe/api/IKeyListener.cpp | 3 ++- src/crepe/api/IKeyListener.h | 4 +-- src/crepe/api/IMouseListener.cpp | 3 ++- src/crepe/api/IMouseListener.h | 2 +- src/crepe/facade/SDLContext.cpp | 3 ++- src/example/CMakeLists.txt | 6 ----- src/test/DBTest.cpp | 3 +-- src/test/ValueBrokerTest.cpp | 5 ++-- 12 files changed, 77 insertions(+), 83 deletions(-) diff --git a/mwe/events/include/event.h b/mwe/events/include/event.h index e1b220b..ee1bf52 100644 --- a/mwe/events/include/event.h +++ b/mwe/events/include/event.h @@ -148,7 +148,7 @@ private: }; class ShutDownEvent : public Event { public: - ShutDownEvent() : Event("ShutDownEvent"){}; + ShutDownEvent() : Event("ShutDownEvent") {}; REGISTER_EVENT_TYPE(ShutDownEvent) diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index 993db86..20f0dd3 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -1,6 +1,7 @@ #include "EventManager.h" using namespace crepe; +using namespace std; EventManager & EventManager::get_instance() { static EventManager instance; @@ -8,30 +9,23 @@ EventManager & EventManager::get_instance() { } void EventManager::dispatch_events() { - for (auto event_it = this->events_queue.begin(); event_it != this->events_queue.end();) { - std::unique_ptr & event = (*event_it).event; - int channel = (*event_it).channel; - std::type_index event_type = (*event_it).type; - - bool event_handled = false; - auto handlers_it = this->subscribers.find(event_type); - if (handlers_it == this->subscribers.end()) { - continue; - } - std::vector & 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; - } - } + for (auto & event : this->events_queue) { + this->handle_event(event.type, event.channel, *event.event.get()); + } + this->events_queue.clear(); +} - if (!event_handled) { - ++event_it; - } +void EventManager::handle_event(type_index type, event_channel_t channel, const Event & data) { + auto handlers_it = this->subscribers.find(type); + if (handlers_it == this->subscribers.end()) return; + + vector & handlers = handlers_it->second; + for (auto & handler : handlers) { + bool check_channel = handler.channel != CHANNEL_ALL || channel != CHANNEL_ALL; + if (check_channel && handler.channel != channel) continue; + + bool handled = handler.callback->exec(data); + if (handled) return; } } @@ -40,15 +34,13 @@ void EventManager::clear() { this->events_queue.clear(); } -void EventManager::unsubscribe(subscription_t event_id) { +void EventManager::unsubscribe(subscription_t 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; - } + for (auto it = handlers.begin(); it != handlers.end(); it++) { + // find listener with subscription id + if ((*it).id != id) continue; + it = handlers.erase(it); + return; } } } diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index bd9772a..348a04d 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -1,8 +1,6 @@ #pragma once -#include #include -#include #include #include #include @@ -11,8 +9,17 @@ #include "EventHandler.h" namespace crepe { -//! typedef for subscription value -typedef int subscription_t; + +//! Event listener unique ID +typedef size_t subscription_t; + +/** + * \brief Event channel + * + * Events can be sent to a specific channel, which prevents listeners on other channels from + * being called. The default channel is EventManager::CHANNEL_ALL, which calls all listeners. + */ +typedef size_t event_channel_t; /** * \class EventManager @@ -24,7 +31,7 @@ typedef int subscription_t; */ class EventManager { public: - static constexpr int CHANNEL_ALL = -1; + static constexpr const event_channel_t CHANNEL_ALL = -1; /** * \brief Get the singleton instance of the EventManager. @@ -49,7 +56,7 @@ public: */ template subscription_t subscribe(const EventHandler & callback, - int channel = CHANNEL_ALL); + event_channel_t channel = CHANNEL_ALL); /** * \brief Unsubscribe a previously registered callback. @@ -70,7 +77,7 @@ public: * \param channel The channel to trigger the event on (default is CHANNEL_ALL, which triggers on all channels). */ template - void trigger_event(const EventType & event, int channel = CHANNEL_ALL); + void trigger_event(const EventType & event, event_channel_t channel = CHANNEL_ALL); /** * \brief Queue an event for later processing. @@ -82,7 +89,7 @@ public: * \param channel The channel to associate with the event (default is CHANNEL_ALL). */ template - void queue_event(const EventType & event, int channel = CHANNEL_ALL); + void queue_event(const EventType & event, event_channel_t channel = CHANNEL_ALL); /** * \brief Process all queued events. @@ -113,17 +120,29 @@ private: */ struct QueueEntry { std::unique_ptr event; ///< The event instance. - int channel = CHANNEL_ALL; ///< The channel associated with the event. + event_channel_t channel = CHANNEL_ALL; ///< The channel associated with the event. std::type_index type; ///< The type of the event. }; + /** + * \brief Internal event handler + * + * This function processes a single event, and is used to process events both during + * EventManager::dispatch_events and inside EventManager::trigger_event + * + * \param type \c typeid of concrete Event class + * \param channel Event channel + * \param data Event data + */ + void handle_event(std::type_index type, event_channel_t channel, const Event & data); + /** * \struct CallbackEntry * \brief Represents a registered event handler callback. */ struct CallbackEntry { std::unique_ptr callback; ///< The callback function wrapper. - int channel = CHANNEL_ALL; ///< The channel this callback listens to. + event_channel_t channel = CHANNEL_ALL; ///< The channel this callback listens to. subscription_t id = -1; ///< Unique subscription ID. }; diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp index b2a94bd..a5f4556 100644 --- a/src/crepe/api/EventManager.hpp +++ b/src/crepe/api/EventManager.hpp @@ -1,9 +1,12 @@ +#pragma once + #include "EventManager.h" namespace crepe { template -subscription_t EventManager::subscribe(const EventHandler & callback, int channel) { +subscription_t EventManager::subscribe(const EventHandler & callback, + event_channel_t channel) { subscription_counter++; std::type_index event_type = typeid(EventType); std::unique_ptr> handler @@ -15,34 +18,19 @@ subscription_t EventManager::subscribe(const EventHandler & callback, } template -void EventManager::queue_event(const EventType & event, int channel) { +void EventManager::queue_event(const EventType & event, event_channel_t channel) { 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(event); - - this->events_queue.push_back( - QueueEntry{.event = std::move(event_ptr), .channel = channel, .type = event_type}); + this->events_queue.push_back(QueueEntry{ + .event = std::make_unique(event), + .channel = channel, + .type = typeid(EventType), + }); } template -void EventManager::trigger_event(const EventType & event, int channel) { - std::type_index event_type = typeid(EventType); - - auto handlers_it = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - const std::vector & handlers = handlers_it->second; - - for (const CallbackEntry & handler : handlers) { - if (handler.channel != channel && handler.channel != CHANNEL_ALL) { - continue; - } - if (handler.callback->exec(event)) { - break; - } - } - } +void EventManager::trigger_event(const EventType & event, event_channel_t channel) { + this->handle_event(typeid(EventType), channel, event); } } // namespace crepe diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index 7aefaf7..8642655 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -3,7 +3,8 @@ using namespace crepe; // Constructor with specified channel -IKeyListener::IKeyListener(int channel) : event_manager(EventManager::get_instance()) { +IKeyListener::IKeyListener(event_channel_t channel) + : event_manager(EventManager::get_instance()) { this->press_id = event_manager.subscribe( [this](const KeyPressEvent & event) { return this->on_key_pressed(event); }, channel); this->release_id = event_manager.subscribe( diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index 2a89cbc..328a4c2 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 = EventManager::CHANNEL_ALL); + IKeyListener(event_channel_t channel = EventManager::CHANNEL_ALL); virtual ~IKeyListener(); IKeyListener(const IKeyListener &) = delete; IKeyListener & operator=(const IKeyListener &) = delete; @@ -43,7 +43,7 @@ private: //! Key release event id subscription_t release_id = -1; //! EventManager reference - EventManager & event_manager;; + EventManager & event_manager; }; } // namespace crepe diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index 7d38280..989aeb3 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -2,7 +2,8 @@ using namespace crepe; -IMouseListener::IMouseListener(int channel) : event_manager(EventManager::get_instance()) { +IMouseListener::IMouseListener(event_channel_t channel) + : event_manager(EventManager::get_instance()) { this->click_id = event_manager.subscribe( [this](const MouseClickEvent & event) { return this->on_mouse_clicked(event); }, channel); diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 91b33e1..15e1619 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 = EventManager::CHANNEL_ALL); + IMouseListener(event_channel_t channel = EventManager::CHANNEL_ALL); virtual ~IMouseListener(); IMouseListener & operator=(const IMouseListener &) = delete; IMouseListener(const IMouseListener &) = delete; diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index b8b2bda..00523a6 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -47,7 +47,8 @@ SDLContext::SDLContext() { SDL_Renderer * tmp_renderer = SDL_CreateRenderer(this->game_window.get(), -1, SDL_RENDERER_ACCELERATED); if (!tmp_renderer) { - throw runtime_error(format("SDLContext: SDL_CreateRenderer error: {}", SDL_GetError())); + throw runtime_error( + format("SDLContext: SDL_CreateRenderer error: {}", SDL_GetError())); } this->game_renderer diff --git a/src/example/CMakeLists.txt b/src/example/CMakeLists.txt index 7b4cc43..560e2bc 100644 --- a/src/example/CMakeLists.txt +++ b/src/example/CMakeLists.txt @@ -18,12 +18,6 @@ endfunction() add_example(asset_manager) add_example(savemgr) -add_example(proxy) -add_example(db) -add_example(ecs) -add_example(scene_manager) -add_example(events) -add_example(particles) add_example(rendering_particle) add_example(gameloop) diff --git a/src/test/DBTest.cpp b/src/test/DBTest.cpp index b57eba9..e80814c 100644 --- a/src/test/DBTest.cpp +++ b/src/test/DBTest.cpp @@ -1,5 +1,5 @@ -#include #include +#include using namespace std; using namespace crepe; @@ -26,4 +26,3 @@ TEST_F(DBTest, Has) { db.set("foo", "bar"); EXPECT_EQ(db.has("foo"), true); } - diff --git a/src/test/ValueBrokerTest.cpp b/src/test/ValueBrokerTest.cpp index 10a4654..e6bb058 100644 --- a/src/test/ValueBrokerTest.cpp +++ b/src/test/ValueBrokerTest.cpp @@ -13,7 +13,7 @@ public: int write_count = 0; int value = 0; - ValueBroker broker { + ValueBroker broker{ [this](const int & target) -> void { this->write_count++; this->value = target; @@ -49,7 +49,7 @@ TEST_F(ValueBrokerTest, ProxyWrite) { EXPECT_EQ(write_count, 1); } -void dummy(int) { } +void dummy(int) {} TEST_F(ValueBrokerTest, ProxyRead) { dummy(proxy); EXPECT_EQ(read_count, 1); @@ -61,4 +61,3 @@ TEST_F(ValueBrokerTest, ProxyReadWrite) { ASSERT_EQ(read_count, 1); ASSERT_EQ(write_count, 1); } - -- cgit v1.2.3 From 1cc120a0031cfc19c35240da8390d9129b4d75a3 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 20 Nov 2024 21:55:19 +0100 Subject: fix doxygen comments on keycodes --- src/crepe/api/KeyCodes.h | 238 ++++++++++++++++------------------------------- 1 file changed, 79 insertions(+), 159 deletions(-) diff --git a/src/crepe/api/KeyCodes.h b/src/crepe/api/KeyCodes.h index 16c2108..9e173e0 100644 --- a/src/crepe/api/KeyCodes.h +++ b/src/crepe/api/KeyCodes.h @@ -2,166 +2,88 @@ //! Enumeration for mouse button inputs, including standard and extended buttons. enum class MouseButton { - //! 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, + NONE = 0, //!< No mouse button input. + LEFT_MOUSE = 1, //!< Left mouse button. + RIGHT_MOUSE = 2, //!< Right mouse button. + MIDDLE_MOUSE = 3, //!< Middle mouse button (scroll wheel press). + X1_MOUSE = 4, //!< First extended mouse button. + X2_MOUSE = 5, //!< Second extended mouse button. + SCROLL_UP = 6, //!< Scroll wheel upward movement. + SCROLL_DOWN = 7, //!< Scroll wheel downward movement. }; //! Enumeration for keyboard key inputs, including printable characters, function keys, and keypad keys. enum class Keycode { - //! 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, + NONE = 0, //!< No key input. + SPACE = 32, //!< Spacebar. + APOSTROPHE = 39, //!< Apostrophe ('). + COMMA = 44, //!< Comma (,). + MINUS = 45, //!< Minus (-). + PERIOD = 46, //!< Period (.). + SLASH = 47, //!< Slash (/). + D0 = 48, //!< Digit 0. + D1 = 49, //!< Digit 1. + D2 = 50, //!< Digit 2. + D3 = 51, //!< Digit 3. + D4 = 52, //!< Digit 4. + D5 = 53, //!< Digit 5. + D6 = 54, //!< Digit 6. + D7 = 55, //!< Digit 7. + D8 = 56, //!< Digit 8. + D9 = 57, //!< Digit 9. + SEMICOLON = 59, //!< Semicolon (;). + EQUAL = 61, //!< Equal sign (=). + A = 65, //!< Key 'A'. + B = 66, //!< Key 'B'. + C = 67, //!< Key 'C'. + D = 68, //!< Key 'D'. + E = 69, //!< Key 'E'. + F = 70, //!< Key 'F'. + G = 71, //!< Key 'G'. + H = 72, //!< Key 'H'. + I = 73, //!< Key 'I'. + J = 74, //!< Key 'J'. + K = 75, //!< Key 'K'. + L = 76, //!< Key 'L'. + M = 77, //!< Key 'M'. + N = 78, //!< Key 'N'. + O = 79, //!< Key 'O'. + P = 80, //!< Key 'P'. + Q = 81, //!< Key 'Q'. + R = 82, //!< Key 'R'. + S = 83, //!< Key 'S'. + T = 84, //!< Key 'T'. + U = 85, //!< Key 'U'. + V = 86, //!< Key 'V'. + W = 87, //!< Key 'W'. + X = 88, //!< Key 'X'. + Y = 89, //!< Key 'Y'. + Z = 90, //!< Key 'Z'. + LEFT_BRACKET = 91, //!< Left bracket ([). + BACKSLASH = 92, //!< Backslash (\). + RIGHT_BRACKET = 93, //!< Right bracket (]). + GRAVE_ACCENT = 96, //!< Grave accent (`). + WORLD1 = 161, //!< Non-US key #1. + WORLD2 = 162, //!< Non-US key #2. + ESCAPE = 256, //!< Escape key. + ENTER = 257, //!< Enter key. + TAB = 258, //!< Tab key. + BACKSPACE = 259, //!< Backspace key. + INSERT = 260, //!< Insert key. + DELETE = 261, //!< Delete key. + RIGHT = 262, //!< Right arrow key. + LEFT = 263, //!< Left arrow key. + DOWN = 264, //!< Down arrow key. + UP = 265, //!< Up arrow key. + PAGE_UP = 266, //!< Page Up key. + PAGE_DOWN = 267, //!< Page Down key. + HOME = 268, //!< Home key. + END = 269, //!< End key. + CAPS_LOCK = 280, //!< Caps Lock key. + SCROLL_LOCK = 281, //!< Scroll Lock key. + NUM_LOCK = 282, //!< Num Lock key. + PRINT_SCREEN = 283, //!< Print Screen key. + PAUSE = 284, //!< Pause key. /** * \name Function keys (F1-F25). * \{ @@ -218,7 +140,6 @@ enum class Keycode { * \name Modifier keys. * \{ */ - //! Modifier keys. LEFT_SHIFT = 340, LEFT_CONTROL = 341, LEFT_ALT = 342, @@ -228,6 +149,5 @@ enum class Keycode { RIGHT_ALT = 346, RIGHT_SUPER = 347, /// \} - //! Menu key. - MENU = 348, + MENU = 348, //!< Menu key. }; -- cgit v1.2.3