aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/crepe/api')
-rw-r--r--src/crepe/api/BehaviorScript.hpp5
-rw-r--r--src/crepe/api/Event.h6
-rw-r--r--src/crepe/api/EventManager.h4
-rw-r--r--src/crepe/api/Script.cpp4
-rw-r--r--src/crepe/api/Script.h47
-rw-r--r--src/crepe/api/Script.hpp8
6 files changed, 61 insertions, 13 deletions
diff --git a/src/crepe/api/BehaviorScript.hpp b/src/crepe/api/BehaviorScript.hpp
index dd197b3..5b5a418 100644
--- a/src/crepe/api/BehaviorScript.hpp
+++ b/src/crepe/api/BehaviorScript.hpp
@@ -14,9 +14,12 @@ BehaviorScript & BehaviorScript::set_script(Args &&... args) {
dbg_trace();
static_assert(std::is_base_of<Script, T>::value);
Script * s = new T(std::forward<Args>(args)...);
- s->game_object_id = this->game_object_id;
+
+ s->game_object_id_ref = &this->game_object_id;
+ s->active_ref = &this->active;
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/Event.h b/src/crepe/api/Event.h
index 9923a05..c1432e1 100644
--- a/src/crepe/api/Event.h
+++ b/src/crepe/api/Event.h
@@ -1,5 +1,5 @@
-// TODO discussing the location of these events
#pragma once
+// TODO discussing the location of these events
#include <string>
@@ -7,6 +7,8 @@
#include "KeyCodes.h"
+namespace crepe {
+
/**
* \brief Base class for all event types in the system.
*/
@@ -113,3 +115,5 @@ public:
* \brief Event triggered to indicate the application is shutting down.
*/
class ShutDownEvent : public Event {};
+
+}
diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h
index 348a04d..1a33023 100644
--- a/src/crepe/api/EventManager.h
+++ b/src/crepe/api/EventManager.h
@@ -77,7 +77,7 @@ public:
* \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, event_channel_t channel = CHANNEL_ALL);
+ void trigger_event(const EventType & event = {}, event_channel_t channel = CHANNEL_ALL);
/**
* \brief Queue an event for later processing.
@@ -89,7 +89,7 @@ public:
* \param channel The channel to associate with the event (default is CHANNEL_ALL).
*/
template <typename EventType>
- void queue_event(const EventType & event, event_channel_t channel = CHANNEL_ALL);
+ void queue_event(const EventType & event = {}, event_channel_t channel = CHANNEL_ALL);
/**
* \brief Process all queued events.
diff --git a/src/crepe/api/Script.cpp b/src/crepe/api/Script.cpp
index bac5ab2..d3fae07 100644
--- a/src/crepe/api/Script.cpp
+++ b/src/crepe/api/Script.cpp
@@ -11,5 +11,7 @@ Script::~Script() {
template <>
void Script::subscribe(const EventHandler<CollisionEvent> & callback) {
- this->subscribe_internal(callback, this->game_object_id);
+ const game_object_id_t & game_object_id = *this->game_object_id_ref;
+ this->subscribe_internal(callback, game_object_id);
}
+
diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h
index 2d5e7a6..373b253 100644
--- a/src/crepe/api/Script.h
+++ b/src/crepe/api/Script.h
@@ -18,8 +18,10 @@ class ComponentManager;
* This class is used as a base class for user-defined scripts that can be added to game
* objects using the \c BehaviorScript component.
*
- * \note Additional *events* (like Unity's OnDisable and OnEnable) should be implemented as
+ * \info Additional *events* (like Unity's OnDisable and OnEnable) should be implemented as
* member or lambda methods in derivative user script classes and registered in \c init().
+ *
+ * \see feature_script
*/
class Script {
protected:
@@ -88,24 +90,40 @@ protected:
void logf(Args &&... args);
/**
- * \brief Subscribe to an event
- *
+ * \brief Subscribe to an event with an explicit channel
* \see EventManager::subscribe
*/
template <typename EventType>
void subscribe(const EventHandler<EventType> & callback, event_channel_t channel);
+ /**
+ * \brief Subscribe to an event on EventManager::CHANNEL_ALL
+ * \see EventManager::subscribe
+ */
template <typename EventType>
void subscribe(const EventHandler<EventType> & callback);
//! \}
private:
+ /**
+ * \brief Internal subscribe function
+ *
+ * This function exists so certain template specializations of Script::subscribe can be
+ * explicitly deleted, and does the following:
+ * - Wrap the user-provided callback in a check that tests if the parent BehaviorScript
+ * component is still active
+ * - Store the subscriber handle returned by the event manager so this listener is
+ * automatically unsubscribed at the end of this Script instance's life
+ *
+ * \tparam EventType concrete Event class
+ * \param callback User-provided callback function
+ * \param channel Event channel (may have been overridden by template specializations)
+ */
template <typename EventType>
void subscribe_internal(const EventHandler<EventType> & callback, event_channel_t channel);
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.
+ // NOTE: This must be the only constructor on Script, see "Late references" below
Script() = default;
//! Only \c BehaviorScript instantiates Script
friend class BehaviorScript;
@@ -113,6 +131,7 @@ public:
// std::unique_ptr destroys script
virtual ~Script();
+private:
Script(const Script &) = delete;
Script(Script &&) = delete;
Script & operator=(const Script &) = delete;
@@ -125,10 +144,19 @@ private:
* These references are set by BehaviorScript immediately after calling the constructor of
* Script.
*
+ * \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 if they want to
+ * implement a non-default constructor (e.g. for passing references to their own concrete
+ * Script classes).
+ *
+ * \todo These should be converted to OptionalRef<> once `loek/util` is merged
+ *
* \{
*/
//! Game object ID of game object parent BehaviorScript is attached to
- game_object_id_t game_object_id = -1;
+ const game_object_id_t * game_object_id_ref = nullptr;
+ //! Reference to parent component
+ bool * active_ref = nullptr;
//! Reference to component manager instance
ComponentManager * component_manager_ref = nullptr;
//! Reference to event manager instance
@@ -142,6 +170,13 @@ private:
std::vector<subscription_t> listeners;
};
+/**
+ * \brief Subscribe to CollisionEvent for the current GameObject
+ *
+ * This is a template specialization for Script::subscribe which automatically sets the event
+ * channel so the callback handler is only called for CollisionEvent events that apply to the
+ * current GameObject the parent BehaviorScript is attached to.
+ */
template <>
void Script::subscribe(const EventHandler<CollisionEvent> & callback);
template <>
diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp
index 96e4a36..8186bd4 100644
--- a/src/crepe/api/Script.hpp
+++ b/src/crepe/api/Script.hpp
@@ -22,7 +22,7 @@ template <typename T>
std::vector<std::reference_wrapper<T>> Script::get_components() const {
ComponentManager & mgr = *this->component_manager_ref;
- return mgr.get_components_by_id<T>(this->game_object_id);
+ return mgr.get_components_by_id<T>(*this->game_object_id_ref);
}
template <typename... Args>
@@ -33,7 +33,11 @@ void Script::logf(Args &&... args) {
template <typename EventType>
void Script::subscribe_internal(const EventHandler<EventType> & callback, event_channel_t channel) {
EventManager & mgr = *this->event_manager_ref;
- subscription_t listener = mgr.subscribe<EventType>(callback, channel);
+ subscription_t listener = mgr.subscribe<EventType>([this, callback](const EventType & data) -> bool {
+ bool & active = *this->active_ref;
+ if (!active) return false;
+ return callback(data);
+ }, channel);
this->listeners.push_back(listener);
}