aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/crepe/api')
-rw-r--r--src/crepe/api/BehaviorScript.hpp1
-rw-r--r--src/crepe/api/CMakeLists.txt4
-rw-r--r--src/crepe/api/Event.h78
-rw-r--r--src/crepe/api/EventHandler.cpp5
-rw-r--r--src/crepe/api/EventHandler.h46
-rw-r--r--src/crepe/api/EventHandler.hpp18
-rw-r--r--src/crepe/api/EventManager.cpp95
-rw-r--r--src/crepe/api/EventManager.h199
-rw-r--r--src/crepe/api/EventManager.hpp146
-rw-r--r--src/crepe/api/IKeyListener.cpp56
-rw-r--r--src/crepe/api/IKeyListener.h61
-rw-r--r--src/crepe/api/IMouseListener.cpp79
-rw-r--r--src/crepe/api/IMouseListener.h79
-rw-r--r--src/crepe/api/KeyCodes.h187
-rw-r--r--src/crepe/api/Script.cpp11
-rw-r--r--src/crepe/api/Script.h74
-rw-r--r--src/crepe/api/Script.hpp14
-rw-r--r--src/crepe/api/Texture.cpp2
18 files changed, 528 insertions, 627 deletions
diff --git a/src/crepe/api/BehaviorScript.hpp b/src/crepe/api/BehaviorScript.hpp
index 6bd123d..dd197b3 100644
--- a/src/crepe/api/BehaviorScript.hpp
+++ b/src/crepe/api/BehaviorScript.hpp
@@ -16,6 +16,7 @@ BehaviorScript & BehaviorScript::set_script(Args &&... args) {
Script * s = new T(std::forward<Args>(args)...);
s->game_object_id = this->game_object_id;
s->component_manager_ref = &this->component_manager;
+ s->event_manager_ref = &EventManager::get_instance();
this->script = std::unique_ptr<Script>(s);
return *this;
}
diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt
index 07b3a82..cc3e5e2 100644
--- a/src/crepe/api/CMakeLists.txt
+++ b/src/crepe/api/CMakeLists.txt
@@ -20,11 +20,12 @@ target_sources(crepe PUBLIC
BoxCollider.cpp
CircleCollider.cpp
EventManager.cpp
- EventHandler.cpp
IKeyListener.cpp
IMouseListener.cpp
LoopManager.cpp
LoopTimer.cpp
+ EventHandler.cpp
+ Script.cpp
)
target_sources(crepe PUBLIC FILE_SET HEADERS FILES
@@ -54,6 +55,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 bd6a541..9923a05 100644
--- a/src/crepe/api/Event.h
+++ b/src/crepe/api/Event.h
@@ -1,59 +1,115 @@
+// TODO discussing the location of these events
#pragma once
-#include "KeyCodes.h"
-#include <iostream>
+
#include <string>
-#include <typeindex>
-#include "system/CollisionSystem.h"
-class Event {
-public:
-};
+#include "../system/CollisionSystem.h"
+
+#include "KeyCodes.h"
+/**
+ * \brief Base class for all event types in the system.
+ */
+class Event {};
+
+/**
+ * \brief Event triggered when a key is pressed.
+ */
class KeyPressEvent : public Event {
public:
- 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;
};
+/**
+ * \brief Event triggered when a key is released.
+ */
class KeyReleaseEvent : public Event {
public:
+ //! The key that was released.
Keycode key = Keycode::NONE;
};
+/**
+ * \brief Event triggered when a mouse button is pressed.
+ */
class MousePressEvent : public Event {
public:
+ //! 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:
+ //! 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:
+ //! 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:
+ //! 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:
crepe::CollisionSystem::CollisionInfo info;
CollisionEvent(const crepe::CollisionSystem::CollisionInfo& collisionInfo)
: info(collisionInfo) {}
};
+
+/**
+ * \brief Event triggered when text is submitted, e.g., from a text input.
+ */
class TextSubmitEvent : public Event {
public:
+ //! The submitted text.
std::string text = "";
};
-class ShutDownEvent : public Event {
-public:
-};
+
+/**
+ * \brief Event triggered to indicate the application is shutting down.
+ */
+class ShutDownEvent : public Event {};
diff --git a/src/crepe/api/EventHandler.cpp b/src/crepe/api/EventHandler.cpp
index 93a116a..4dc232f 100644
--- a/src/crepe/api/EventHandler.cpp
+++ b/src/crepe/api/EventHandler.cpp
@@ -1,2 +1,5 @@
#include "EventHandler.h"
-bool IEventHandlerWrapper::exec(const Event & e) { return call(e); }
+
+using namespace crepe;
+
+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 0ab90de..ef659fd 100644
--- a/src/crepe/api/EventHandler.h
+++ b/src/crepe/api/EventHandler.h
@@ -1,9 +1,11 @@
#pragma once
-#include "Event.h"
+
#include <functional>
-#include <iostream>
-#include <typeindex>
+#include <string>
+#include "Event.h"
+
+namespace crepe {
/**
* \brief A type alias for an event handler function.
*
@@ -11,8 +13,9 @@
* 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.
*/
-// TODO: typedef
template <typename EventType>
using EventHandler = std::function<bool(const EventType & e)>;
@@ -21,7 +24,7 @@ using EventHandler = std::function<bool(const EventType & e)>;
* \brief An abstract base class for event handler wrappers.
*
* This class provides the interface for handling events. Derived classes must implement the
- * `call()` method to process events and the `get_type()` method to return the handler's type.
+ * `call()` method to process events
*/
class IEventHandlerWrapper {
public:
@@ -40,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.
@@ -81,8 +75,7 @@ public:
*
* \param handler The event handler function.
*/
- explicit EventHandlerWrapper(const EventHandler<EventType> & handler)
- : m_handler(handler), m_handler_type(m_handler.target_type().name()) {}
+ explicit EventHandlerWrapper(const EventHandler<EventType> & handler);
private:
/**
@@ -93,20 +86,11 @@ 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<const EventType &>(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; }
+ bool call(const Event & e) override;
//! The event handler function.
- EventHandler<EventType> m_handler;
- //! The type name of the handler function.
- const std::string m_handler_type;
+ EventHandler<EventType> handler;
};
+
+} // 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..391dcca
--- /dev/null
+++ b/src/crepe/api/EventHandler.hpp
@@ -0,0 +1,18 @@
+#include <typeindex>
+
+#include "EventHandler.h"
+
+namespace crepe {
+
+// Implementation of EventHandlerWrapper constructor
+template <typename EventType>
+EventHandlerWrapper<EventType>::EventHandlerWrapper(const EventHandler<EventType> & handler)
+ : handler(handler) {}
+
+// Implementation of EventHandlerWrapper::call
+template <typename EventType>
+bool EventHandlerWrapper<EventType>::call(const Event & e) {
+ return this->handler(static_cast<const EventType &>(e));
+}
+
+} //namespace crepe
diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp
index e881d49..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,74 +9,38 @@ EventManager & EventManager::get_instance() {
}
void EventManager::dispatch_events() {
- for (std::vector<std::tuple<std::unique_ptr<Event>, int,
- std::type_index>>::iterator event_it
- = this->events_queue.begin();
- event_it != this->events_queue.end();) {
- std::unique_ptr<Event> & event = std::get<0>(*event_it);
- int channel = std::get<1>(*event_it);
- std::type_index event_type = std::get<2>(*event_it);
+ for (auto & event : this->events_queue) {
+ this->handle_event(event.type, event.channel, *event.event.get());
+ }
+ this->events_queue.clear();
+}
- bool event_handled = false;
+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;
- if (channel) {
- std::unordered_map<
- std::type_index,
- std::unordered_map<
- int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>>::
- iterator handlers_it
- = subscribers_by_event_id.find(event_type);
- if (handlers_it != subscribers_by_event_id.end()) {
- std::unordered_map<
- int, std::vector<std::unique_ptr<IEventHandlerWrapper>>> &
- handlers_map
- = handlers_it->second;
- std::unordered_map<
- int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::
- iterator handlers
- = handlers_map.find(channel);
- if (handlers != handlers_map.end()) {
- std::vector<std::unique_ptr<IEventHandlerWrapper>> &
- callbacks
- = handlers->second;
- for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::
- 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<std::unique_ptr<IEventHandlerWrapper>>>::iterator
- handlers_it
- = this->subscribers.find(event_type);
- if (handlers_it != this->subscribers.end()) {
- std::vector<std::unique_ptr<IEventHandlerWrapper>> & handlers
- = handlers_it->second;
- for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::
- 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;
- break;
- }
- }
- }
- }
+ vector<CallbackEntry> & 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;
+ }
+}
+
+void EventManager::clear() {
+ this->subscribers.clear();
+ this->events_queue.clear();
+}
- if (!event_handled) {
- ++event_it;
+void EventManager::unsubscribe(subscription_t id) {
+ for (auto & [event_type, handlers] : this->subscribers) {
+ 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 38d2e64..348a04d 100644
--- a/src/crepe/api/EventManager.h
+++ b/src/crepe/api/EventManager.h
@@ -1,8 +1,6 @@
#pragma once
-#include <functional>
#include <memory>
-#include <type_traits>
#include <typeindex>
#include <unordered_map>
#include <vector>
@@ -10,113 +8,154 @@
#include "Event.h"
#include "EventHandler.h"
-
namespace crepe {
+
+//! 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
- * \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:
- /**
- * \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;
+ static constexpr const event_channel_t CHANNEL_ALL = -1;
/**
- * \brief Get the singleton instance of the EventManager.
- *
- * This method returns the unique instance of the EventManager, creating it on the first call.
- *
- * \return Reference to the EventManager instance.
- */
+ * \brief Get the singleton instance of the EventManager.
+ *
+ * This method returns the unique instance of the EventManager, creating it if it
+ * doesn't already exist. Ensures only one instance is active in the program.
+ *
+ * \return Reference to the singleton instance of the EventManager.
+ */
static EventManager & get_instance();
/**
- * \brief Subscribe to an event.
- *
- * This method allows the registration of a callback for a specific event type and channel.
- *
- * \tparam EventType The type of the event to subscribe to.
- * \param callback The callback function to invoke when the event is triggered.
- * \param channel The channel number to subscribe to (default is 0).
- */
+ * \brief Subscribe to a specific event type.
+ *
+ * Registers a callback for a given event type and optional channel. Each callback
+ * is assigned a unique subscription ID that can be used for later unsubscription.
+ *
+ * \tparam EventType The type of the event to subscribe to.
+ * \param callback The callback function to be invoked when the event is triggered.
+ * \param channel The channel number to subscribe to (default is CHANNEL_ALL, which listens to all channels).
+ * \return A unique subscription ID associated with the registered callback.
+ */
template <typename EventType>
- void subscribe(EventHandler<EventType> && callback, int channel = 0);
+ subscription_t subscribe(const EventHandler<EventType> & callback,
+ event_channel_t channel = CHANNEL_ALL);
/**
- * \brief Unsubscribe from an event.
- *
- * This method removes a previously registered callback from an event.
- *
- * \tparam EventType The type of the event to unsubscribe from.
- * \param callback The callback function to remove from the subscription list.
- * \param channel The event ID to unsubscribe from.
- */
- template <typename EventType>
- void unsubscribe(const EventHandler<EventType> &, int channel);
+ * \brief Unsubscribe a previously registered callback.
+ *
+ * Removes a callback from the subscription list based on its unique subscription ID.
+ *
+ * \param event_id The unique subscription ID of the callback to remove.
+ */
+ void unsubscribe(subscription_t event_id);
/**
- * \brief Trigger an event.
- *
- * This method invokes the appropriate callback(s) for the specified event.
- *
- * \tparam EventType The type of the event to trigger.
- * \param event The event data to pass to the callback.
- * \param channel The channel from which to trigger the event (default is 0).
- */
+ * \brief Trigger an event immediately.
+ *
+ * Synchronously invokes all registered callbacks for the given event type on the specified channel.
+ *
+ * \tparam EventType The type of the event to trigger.
+ * \param event The event instance to pass to the callbacks.
+ * \param channel The channel to trigger the event on (default is CHANNEL_ALL, which triggers on all channels).
+ */
template <typename EventType>
- void trigger_event(const EventType & event, int channel);
+ void trigger_event(const EventType & event, event_channel_t channel = CHANNEL_ALL);
/**
- * \brief Queue an event for later processing.
- *
- * This method adds an event to the event queue, which will be processed in the
- * dispatch_events function.
- *
- * \tparam EventType The type of the event to queue.
- * \param event The event to queue.
- * \param channel The channel number for the event (default is 0).
- */
+ * \brief Queue an event for later processing.
+ *
+ * Adds an event to the event queue to be processed during the next call to `dispatch_events`.
+ *
+ * \tparam EventType The type of the event to queue.
+ * \param event The event instance to queue.
+ * \param channel The channel to associate with the event (default is CHANNEL_ALL).
+ */
template <typename EventType>
- void queue_event(EventType && event, int channel);
+ void queue_event(const EventType & event, event_channel_t 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 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;
- //! The queue of events to be processed.
- std::vector<std::tuple<std::unique_ptr<Event>, int, std::type_index>>
- events_queue;
- //! Registered event handlers.
- std::unordered_map<std::type_index,
- std::vector<std::unique_ptr<IEventHandlerWrapper>>>
- subscribers;
- //! Event handlers indexed by event ID.
- std::unordered_map<
- std::type_index,
- std::unordered_map<int,
- std::vector<std::unique_ptr<IEventHandlerWrapper>>>>
- subscribers_by_event_id;
+ /**
+ * \struct QueueEntry
+ * \brief Represents an entry in the event queue.
+ */
+ struct QueueEntry {
+ std::unique_ptr<Event> event; ///< The event instance.
+ 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<IEventHandlerWrapper> callback; ///< The callback function wrapper.
+ event_channel_t 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.
+ std::vector<QueueEntry> events_queue;
+
+ //! A map of event type to registered callbacks.
+ std::unordered_map<std::type_index, std::vector<CallbackEntry>> subscribers;
+
+ //! Counter to generate unique subscription IDs.
+ subscription_t subscription_counter = 0;
};
} // namespace crepe
+
#include "EventManager.hpp"
diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp
index b509097..a5f4556 100644
--- a/src/crepe/api/EventManager.hpp
+++ b/src/crepe/api/EventManager.hpp
@@ -1,140 +1,36 @@
+#pragma once
+
#include "EventManager.h"
+
namespace crepe {
template <typename EventType>
-void EventManager::subscribe(EventHandler<EventType> && callback, int channel) {
+subscription_t EventManager::subscribe(const EventHandler<EventType> & callback,
+ event_channel_t channel) {
+ subscription_counter++;
std::type_index event_type = typeid(EventType);
std::unique_ptr<EventHandlerWrapper<EventType>> handler
= std::make_unique<EventHandlerWrapper<EventType>>(callback);
-
- if (channel) {
- std::unordered_map<int,
- std::vector<std::unique_ptr<IEventHandlerWrapper>>> &
- handlers_map
- = this->subscribers_by_event_id[event_type];
- std::unordered_map<
- int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::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<std::unique_ptr<IEventHandlerWrapper>> & handlers
- = this->subscribers[event_type];
- handlers.emplace_back(std::move(handler));
- }
-}
-
-template <typename EventType>
-void EventManager::queue_event(EventType && event, int channel) {
- std::type_index event_type = std::type_index(typeid(EventType));
-
- std::unique_ptr<EventType> event_ptr
- = std::make_unique<EventType>(std::forward<EventType>(event));
-
- std::tuple<std::unique_ptr<Event>, int, std::type_index> tuple(
- std::move(event_ptr), channel, event_type);
- this->events_queue.push_back(std::move(tuple));
+ std::vector<CallbackEntry> & handlers = this->subscribers[event_type];
+ handlers.emplace_back(CallbackEntry{
+ .callback = std::move(handler), .channel = channel, .id = subscription_counter});
+ return subscription_counter;
}
template <typename EventType>
-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<int,
- std::vector<std::unique_ptr<IEventHandlerWrapper>>> &
- handlers_map
- = this->subscribers_by_event_id[event_type];
- std::unordered_map<
- int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator
- handlers_it
- = handlers_map.find(channel);
-
- if (handlers_it != handlers_map.end()) {
- std::vector<std::unique_ptr<IEventHandlerWrapper>> & handlers
- = handlers_it->second;
- for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it
- = handlers.begin();
- it != handlers.end();++it) {
- // stops when callback returns true
- if((*it)->exec(event)){
- break;
- }
- }
- }
- } else {
- std::vector<std::unique_ptr<IEventHandlerWrapper>> & handlers
- = this->subscribers[event_type];
- for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it
- = handlers.begin();
- it != handlers.end();++it) {
- // stops when callback returns true
- if((*it)->exec(event)){
- break;
- }
- }
- }
+void EventManager::queue_event(const EventType & event, event_channel_t channel) {
+ static_assert(std::is_base_of<Event, EventType>::value,
+ "EventType must derive from Event");
+ this->events_queue.push_back(QueueEntry{
+ .event = std::make_unique<EventType>(event),
+ .channel = channel,
+ .type = typeid(EventType),
+ });
}
template <typename EventType>
-void EventManager::unsubscribe(const EventHandler<EventType> & callback,
- int channel) {
- std::type_index event_type(typeid(EventType));
- std::string handler_name = callback.target_type().name();
-
- if (channel) {
- std::unordered_map<
- std::type_index,
- std::unordered_map<
- int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>>::
- 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<std::unique_ptr<IEventHandlerWrapper>>> &
- handlers_map
- = subscriber_list->second;
- std::unordered_map<
- int,
- std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator
- handlers
- = handlers_map.find(channel);
- if (handlers != handlers_map.end()) {
- std::vector<std::unique_ptr<IEventHandlerWrapper>> & callbacks
- = handlers->second;
- for (std::vector<
- std::unique_ptr<IEventHandlerWrapper>>::iterator it
- = callbacks.begin();
- it != callbacks.end(); ++it) {
- if ((*it)->get_type() == handler_name) {
- it = callbacks.erase(it);
- return;
- }
- }
- }
- }
- } else {
- std::unordered_map<std::type_index,
- std::vector<std::unique_ptr<IEventHandlerWrapper>>>::
- iterator handlers_it
- = this->subscribers.find(event_type);
- if (handlers_it != this->subscribers.end()) {
- std::vector<std::unique_ptr<IEventHandlerWrapper>> & handlers
- = handlers_it->second;
- for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it
- = handlers.begin();
- it != handlers.end(); ++it) {
- if ((*it)->get_type() == handler_name) {
- it = handlers.erase(it);
- return;
- }
- }
- }
- }
+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 4fd9855..8642655 100644
--- a/src/crepe/api/IKeyListener.cpp
+++ b/src/crepe/api/IKeyListener.cpp
@@ -2,50 +2,18 @@
using namespace crepe;
-IKeyListener::IKeyListener() {
- this->channel = channel;
- this->subscribe_events();
-}
-IKeyListener::IKeyListener(int channel) {
- this->channel = channel;
- this->subscribe_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<KeyPressEvent>(
- std::move(this->key_pressed_handler), this->channel);
- EventManager::get_instance().subscribe<KeyReleaseEvent>(
- std::move(this->key_released_handler), this->channel);
+// Constructor with specified channel
+IKeyListener::IKeyListener(event_channel_t channel)
+ : event_manager(EventManager::get_instance()) {
+ this->press_id = event_manager.subscribe<KeyPressEvent>(
+ [this](const KeyPressEvent & event) { return this->on_key_pressed(event); }, channel);
+ this->release_id = event_manager.subscribe<KeyReleaseEvent>(
+ [this](const KeyReleaseEvent & event) { return this->on_key_released(event); },
+ channel);
}
-void IKeyListener::unsubscribe_events() {
- EventManager::get_instance().unsubscribe<KeyPressEvent>(
- this->key_pressed_handler, channel);
- EventManager::get_instance().unsubscribe<KeyReleaseEvent>(
- this->key_released_handler, channel);
- std::cout << std::endl;
-}
-void IKeyListener::activate_keys() {
- if (this->active) {
- return;
- }
- this->subscribe_events();
-}
-void IKeyListener::deactivate_keys() {
- if (!this->active) {
- return;
- }
- this->unsubscribe_events();
-}
-void IKeyListener::set_channel(int channel) {
- this->unsubscribe_events();
- this->channel = channel;
- this->subscribe_events();
+// Destructor, unsubscribe events
+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 839acbf..328a4c2 100644
--- a/src/crepe/api/IKeyListener.h
+++ b/src/crepe/api/IKeyListener.h
@@ -1,8 +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.
@@ -13,17 +16,12 @@ public:
* \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.
- */
+ IKeyListener(event_channel_t channel = EventManager::CHANNEL_ALL);
virtual ~IKeyListener();
+ IKeyListener(const IKeyListener &) = delete;
+ IKeyListener & operator=(const IKeyListener &) = delete;
+ IKeyListener & operator=(IKeyListener &&) = delete;
+ IKeyListener(IKeyListener &&) = delete;
/**
* \brief Pure virtual function to handle key press events.
@@ -39,40 +37,13 @@ public:
*/
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.
- */
- void subscribe_events();
-
- /**
- * \brief Unsubscribes from key events.
- */
- void unsubscribe_events();
-
private:
- //! Indicates whether key listening is active.
- bool active = true;
- //! Channel ID for event handling.
- int channel = 0;
- //! Key press event handler.
- EventHandler<KeyPressEvent> key_pressed_handler;
- //!< Key release event handler.
- EventHandler<KeyReleaseEvent> key_released_handler;
+ //! Key press event id
+ subscription_t press_id = -1;
+ //! Key release event id
+ subscription_t release_id = -1;
+ //! EventManager reference
+ EventManager & event_manager;
};
+
+} // namespace crepe
diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp
index 489e55b..989aeb3 100644
--- a/src/crepe/api/IMouseListener.cpp
+++ b/src/crepe/api/IMouseListener.cpp
@@ -2,63 +2,28 @@
using namespace crepe;
-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<MouseClickEvent>(
- std::move(this->mouse_click_handler), this->channel);
- EventManager::get_instance().subscribe<MousePressEvent>(
- std::move(this->mouse_press_handler), this->channel);
- EventManager::get_instance().subscribe<MouseReleaseEvent>(
- std::move(this->mouse_release_handler), this->channel);
- EventManager::get_instance().subscribe<MouseMoveEvent>(
- std::move(this->mouse_move_handler), this->channel);
-}
-// TODO: reference voor singleton
-void IMouseListener::unsubscribe_events() {
- EventManager::get_instance().unsubscribe<MouseClickEvent>(
- this->mouse_click_handler, this->channel);
- EventManager::get_instance().unsubscribe<MousePressEvent>(
- this->mouse_press_handler, this->channel);
- EventManager::get_instance().unsubscribe<MouseReleaseEvent>(
- this->mouse_release_handler, this->channel);
- EventManager::get_instance().unsubscribe<MouseMoveEvent>(
- 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();
+IMouseListener::IMouseListener(event_channel_t channel)
+ : event_manager(EventManager::get_instance()) {
+ this->click_id = event_manager.subscribe<MouseClickEvent>(
+ [this](const MouseClickEvent & event) { return this->on_mouse_clicked(event); },
+ channel);
+
+ this->press_id = event_manager.subscribe<MousePressEvent>(
+ [this](const MousePressEvent & event) { return this->on_mouse_pressed(event); },
+ channel);
+
+ this->release_id = event_manager.subscribe<MouseReleaseEvent>(
+ [this](const MouseReleaseEvent & event) { return this->on_mouse_released(event); },
+ channel);
+
+ this->move_id = event_manager.subscribe<MouseMoveEvent>(
+ [this](const MouseMoveEvent & event) { return this->on_mouse_moved(event); }, channel);
}
-void IMouseListener::set_channel(int channel) {
- this->unsubscribe_events();
- this->channel = channel;
- this->subscribe_events();
+IMouseListener::~IMouseListener() {
+ // 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/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h
index 7e92956..15e1619 100644
--- a/src/crepe/api/IMouseListener.h
+++ b/src/crepe/api/IMouseListener.h
@@ -4,6 +4,8 @@
#include "EventHandler.h"
#include "EventManager.h"
+namespace crepe {
+
/**
* \class IMouseListener
* \brief Interface for mouse event handling in the application.
@@ -11,34 +13,14 @@
class IMouseListener {
public:
/**
- * \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.
- */
+ IMouseListener(event_channel_t channel = EventManager::CHANNEL_ALL);
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(const IMouseListener &) = delete;
+ IMouseListener & operator=(const IMouseListener &&) = delete;
IMouseListener(IMouseListener &&) = delete;
/**
@@ -74,44 +56,17 @@ public:
*/
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.
- */
- void subscribe_events();
-
- /**
- * \brief Unsubscribes from mouse events on the specified channel.
- */
- void unsubscribe_events();
-
private:
- //! Indicates whether mouse listening is active.
- bool active = true;
- //! Channel ID for event handling.
- int channel = 0;
- //! Mouse click event handler.
- EventHandler<MouseClickEvent> mouse_click_handler;
- //! Mouse press event handler.
- EventHandler<MousePressEvent> mouse_press_handler;
- //! Mouse release event handler.
- EventHandler<MouseReleaseEvent> mouse_release_handler;
- //! Mouse move event handler.
- EventHandler<MouseMoveEvent> mouse_move_handler;
+ //! Mouse click event id
+ subscription_t click_id = -1;
+ //! Mouse press event id
+ subscription_t press_id = -1;
+ //! Mouse release event id
+ subscription_t release_id = -1;
+ //! Mouse move event id
+ subscription_t move_id = -1;
+ //! EventManager reference
+ EventManager & event_manager;
};
+
+} //namespace crepe
diff --git a/src/crepe/api/KeyCodes.h b/src/crepe/api/KeyCodes.h
index e5a91fc..9e173e0 100644
--- a/src/crepe/api/KeyCodes.h
+++ b/src/crepe/api/KeyCodes.h
@@ -1,94 +1,93 @@
#pragma once
+//! 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,
+ 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.
};
-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,
+//! Enumeration for keyboard key inputs, including printable characters, function keys, and keypad keys.
+enum class Keycode {
+ 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).
+ * \{
+ */
F1 = 290,
F2 = 291,
F3 = 292,
@@ -114,8 +113,11 @@ enum class Keycode : int {
F23 = 312,
F24 = 313,
F25 = 314,
-
- /* Keypad */
+ /// \}
+ /**
+ * \name Keypad digits and operators.
+ * \{
+ */
KP0 = 320,
KP1 = 321,
KP2 = 322,
@@ -133,7 +135,11 @@ enum class Keycode : int {
KP_ADD = 334,
KP_ENTER = 335,
KP_EQUAL = 336,
-
+ /// \}
+ /**
+ * \name Modifier keys.
+ * \{
+ */
LEFT_SHIFT = 340,
LEFT_CONTROL = 341,
LEFT_ALT = 342,
@@ -142,5 +148,6 @@ enum class Keycode : int {
RIGHT_CONTROL = 345,
RIGHT_ALT = 346,
RIGHT_SUPER = 347,
- MENU = 348
+ /// \}
+ MENU = 348, //!< Menu key.
};
diff --git a/src/crepe/api/Script.cpp b/src/crepe/api/Script.cpp
new file mode 100644
index 0000000..9ebb074
--- /dev/null
+++ b/src/crepe/api/Script.cpp
@@ -0,0 +1,11 @@
+#include "Script.h"
+
+using namespace crepe;
+
+Script::~Script() {
+ EventManager & evmgr = *this->event_manager_ref;
+ for (auto id : this->listeners) {
+ evmgr.unsubscribe(id);
+ }
+}
+
diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h
index 939d142..4d98e4d 100644
--- a/src/crepe/api/Script.h
+++ b/src/crepe/api/Script.h
@@ -4,6 +4,8 @@
#include "../types.h"
+#include "EventManager.h"
+
namespace crepe {
class ScriptSystem;
@@ -22,7 +24,11 @@ class ComponentManager;
class Script {
protected:
/**
- * \brief Script initialization function
+ * \name Interface functions
+ * \{
+ */
+ /**
+ * \brief Script initialization function (empty by default)
*
* This function is called during the ScriptSystem::update() routine *before*
* Script::update() if it (a) has not yet been called and (b) the \c BehaviorScript component
@@ -30,24 +36,32 @@ protected:
*/
virtual void init() {}
/**
- * \brief Script update function
+ * \brief Script update function (empty by default)
*
* This function is called during the ScriptSystem::update() routine if the \c BehaviorScript
* component holding this script instance is active.
*/
virtual void update() {}
+ //! \}
+
//! ScriptSystem calls \c init() and \c update()
friend class crepe::ScriptSystem;
protected:
/**
- * \brief Get single component of type \c T on this game object (utility)
+ * \name Utility functions
+ * \{
+ */
+
+ /**
+ * \brief Get single component of type \c T on this game object
*
* \tparam T Type of component
*
* \returns Reference to component
*
- * \throws nullptr if this game object does not have a component matching type \c T
+ * \throws std::runtime_error if this game object does not have a component matching type \c
+ * T
*/
template <typename T>
T & get_component() const;
@@ -55,7 +69,7 @@ protected:
// cause compile-time errors
/**
- * \brief Get all components of type \c T on this game object (utility)
+ * \brief Get all components of type \c T on this game object
*
* \tparam T Type of component
*
@@ -63,31 +77,65 @@ protected:
*/
template <typename T>
std::vector<std::reference_wrapper<T>> get_components() const;
-
+
+ /**
+ * \brief Log a message using Log::logf
+ *
+ * \tparam Args Log::logf parameters
+ * \param args Log::logf parameters
+ */
+ template <typename... Args>
+ void logf(Args &&... args);
+
+ game_object_id_t get_game_object_id() const { return this->game_object_id; };
+
/**
- * \brief Gets game object id this script is attached to
+ * \brief Subscribe to an event
*
- * \returns game object id
+ * \see EventManager::subscribe
*/
- game_object_id_t get_game_object_id() const {return this->game_object_id;};
-
+ template <typename EventType>
+ void subscribe(const EventHandler<EventType> & callback, event_channel_t channel = EventManager::CHANNEL_ALL);
+
+ //! \}
+
protected:
// NOTE: Script must have a constructor without arguments so the game programmer doesn't need
// to manually add `using Script::Script` to their concrete script class.
Script() = default;
//! Only \c BehaviorScript instantiates Script
friend class BehaviorScript;
+public:
+ // std::unique_ptr destroys script
+ virtual ~Script();
+
+ Script(const Script &) = delete;
+ Script(Script &&) = delete;
+ Script & operator=(const Script &) = delete;
+ Script & operator=(Script &&) = delete;
private:
- // These references are set by BehaviorScript immediately after calling the constructor of
- // Script.
+ /**
+ * \name Late references
+ *
+ * These references are set by BehaviorScript immediately after calling the constructor of
+ * Script.
+ *
+ * \{
+ */
+ //! Game object ID of game object parent BehaviorScript is attached to
game_object_id_t game_object_id = -1;
+ //! Reference to component manager instance
ComponentManager * component_manager_ref = nullptr;
- // TODO: use OptionalRef instead of pointer
+ //! Reference to event manager instance
+ EventManager * event_manager_ref = nullptr;
+ //! \}
private:
//! Flag to indicate if \c init() has been called already
bool initialized = false;
+ //! List of subscribed events
+ std::vector<subscription_t> listeners;
};
} // namespace crepe
diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp
index a064a90..42c8f0b 100644
--- a/src/crepe/api/Script.hpp
+++ b/src/crepe/api/Script.hpp
@@ -20,9 +20,21 @@ T & Script::get_component() const {
template <typename T>
std::vector<std::reference_wrapper<T>> Script::get_components() const {
- auto & mgr = *this->component_manager_ref;
+ ComponentManager & mgr = *this->component_manager_ref;
return mgr.get_components_by_id<T>(this->game_object_id);
}
+template <typename... Args>
+void Script::logf(Args &&... args) {
+ Log::logf(std::forward<Args>(args)...);
+}
+
+template <typename EventType>
+void Script::subscribe(const EventHandler<EventType> & callback, event_channel_t channel) {
+ EventManager & mgr = *this->event_manager_ref;
+ subscription_t listener = mgr.subscribe<EventType>(callback, channel);
+ this->listeners.push_back(listener);
+}
+
} // namespace crepe
diff --git a/src/crepe/api/Texture.cpp b/src/crepe/api/Texture.cpp
index de0d0ea..734a5bb 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);
}