diff options
Diffstat (limited to 'src/crepe')
| -rw-r--r-- | src/crepe/api/BehaviorScript.h | 7 | ||||
| -rw-r--r-- | src/crepe/api/BehaviorScript.hpp | 11 | ||||
| -rw-r--r-- | src/crepe/api/Event.h | 12 | ||||
| -rw-r--r-- | src/crepe/api/EventManager.h | 4 | ||||
| -rw-r--r-- | src/crepe/api/Script.cpp | 6 | ||||
| -rw-r--r-- | src/crepe/api/Script.h | 60 | ||||
| -rw-r--r-- | src/crepe/api/Script.hpp | 20 | 
7 files changed, 96 insertions, 24 deletions
| diff --git a/src/crepe/api/BehaviorScript.h b/src/crepe/api/BehaviorScript.h index 9d85d4c..d556fe5 100644 --- a/src/crepe/api/BehaviorScript.h +++ b/src/crepe/api/BehaviorScript.h @@ -39,11 +39,14 @@ public:  	 * \brief Set the concrete script of this component  	 *  	 * \tparam T Concrete script type (derived from \c crepe::Script) +	 * \tparam Args Arguments for concrete script constructor +	 * +	 * \param args Arguments for concrete script constructor (forwarded using perfect forwarding)  	 *  	 * \returns Reference to BehaviorScript component (`*this`)  	 */ -	template <class T> -	BehaviorScript & set_script(); +	template <class T, typename... Args> +	BehaviorScript & set_script(Args &&... args);  protected:  	//! Script instance diff --git a/src/crepe/api/BehaviorScript.hpp b/src/crepe/api/BehaviorScript.hpp index dd1efd5..5b5a418 100644 --- a/src/crepe/api/BehaviorScript.hpp +++ b/src/crepe/api/BehaviorScript.hpp @@ -9,14 +9,17 @@  namespace crepe { -template <class T> -BehaviorScript & BehaviorScript::set_script() { +template <class T, typename... Args> +BehaviorScript & BehaviorScript::set_script(Args &&... args) {  	dbg_trace();  	static_assert(std::is_base_of<Script, T>::value); -	Script * s = new T(); -	s->game_object_id = this->game_object_id; +	Script * s = new T(std::forward<Args>(args)...); + +	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 06cf7f3..ab4be2b 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -1,10 +1,12 @@ -// TODO discussing the location of these events  #pragma once +// TODO discussing the location of these events  #include <string>  #include "KeyCodes.h" +namespace crepe { +  /**   * \brief Base class for all event types in the system.   */ @@ -91,11 +93,7 @@ public:  /**   * \brief Event triggered during a collision between objects.   */ -class CollisionEvent : public Event { -public: -	//! Data describing the collision (currently not implemented). -	// Collision collisionData; -}; +class CollisionEvent : public Event { };  /**   * \brief Event triggered when text is submitted, e.g., from a text input. @@ -110,3 +108,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 9ebb074..d3fae07 100644 --- a/src/crepe/api/Script.cpp +++ b/src/crepe/api/Script.cpp @@ -9,3 +9,9 @@ Script::~Script() {  	}  } +template <> +void Script::subscribe(const EventHandler<CollisionEvent> & callback) { +	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 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" diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp index 42c8f0b..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> @@ -31,10 +31,24 @@ void Script::logf(Args &&... args) {  }  template <typename EventType> -void Script::subscribe(const EventHandler<EventType> & callback, event_channel_t channel) { +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);  } +template <typename EventType> +void Script::subscribe(const EventHandler<EventType> & callback, event_channel_t channel) { +	this->subscribe_internal(callback, channel); +} + +template <typename EventType> +void Script::subscribe(const EventHandler<EventType> & callback) { +	this->subscribe_internal(callback, EventManager::CHANNEL_ALL); +} +  } // namespace crepe |