aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/api/Script.h
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-11-21 09:43:13 +0100
committerLoek Le Blansch <loek@pipeframe.xyz>2024-11-21 09:43:13 +0100
commit502fb8e8d1dcfe10f55fdef2cdfb71afec806204 (patch)
tree8b967076cf0212f00d811e57264e3e0878c059c4 /src/crepe/api/Script.h
parentda379a58033c0ef3c9c854326a3fca25d6e54319 (diff)
pull script/event changes from `loek/collision-system`
Diffstat (limited to 'src/crepe/api/Script.h')
-rw-r--r--src/crepe/api/Script.h60
1 files changed, 53 insertions, 7 deletions
diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h
index c9eb211..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,18 +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, event_channel_t channel = EventManager::CHANNEL_ALL);
+ 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;
@@ -107,6 +131,7 @@ public:
// std::unique_ptr destroys script
virtual ~Script();
+private:
Script(const Script &) = delete;
Script(Script &&) = delete;
Script & operator=(const Script &) = delete;
@@ -119,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
@@ -136,6 +170,18 @@ 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 <>
+void Script::subscribe(const EventHandler<CollisionEvent> & callback, event_channel_t) = delete;
+
} // namespace crepe
#include "Script.hpp"