diff options
Diffstat (limited to 'src')
50 files changed, 338 insertions, 161 deletions
| diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e4922df..445a8b2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -38,6 +38,5 @@ install(  target_link_libraries(test_main  	PRIVATE gtest -	PRIVATE gtest_main  	PUBLIC crepe  ) diff --git a/src/crepe/Asset.cpp b/src/crepe/Asset.cpp index 8a2a11c..3d4df53 100644 --- a/src/crepe/Asset.cpp +++ b/src/crepe/Asset.cpp @@ -1,16 +1,20 @@  #include <filesystem>  #include "Asset.h" +#include "Exception.h"  using namespace crepe; +using namespace std; -Asset::Asset(const std::string & src) { -	// FIXME: restore this -	// this->src = std::filesystem::canonical(src); -	this->src = src; -	this->file = std::ifstream(this->src, std::ios::in | std::ios::binary); +Asset::Asset(const string & src) : src(src) { +	try { +		this->src = filesystem::canonical(src); +	} catch (filesystem::filesystem_error & e) { +		throw Exception("Asset error: %s", e.what()); +	} +	this->file = ifstream(this->src, ios::in | ios::binary);  } -const std::istream & Asset::read() { return this->file; } +const istream & Asset::read() { return this->file; } -const char * Asset::canonical() { return this->src.c_str(); } +const char * Asset::canonical() const { return this->src.c_str(); } diff --git a/src/crepe/Asset.h b/src/crepe/Asset.h index 0cb5834..d4e4ba1 100644 --- a/src/crepe/Asset.h +++ b/src/crepe/Asset.h @@ -23,7 +23,7 @@ public:  	//! Get an input stream to the contents of this resource  	const std::istream & read();  	//! Get the canonical path to this resource -	const char * canonical(); +	const char * canonical() const;  private:  	std::string src; diff --git a/src/crepe/Collider.cpp b/src/crepe/Collider.cpp index bbec488..b408609 100644 --- a/src/crepe/Collider.cpp +++ b/src/crepe/Collider.cpp @@ -2,4 +2,3 @@  using namespace crepe; -Collider::Collider(game_object_id_t id) : Component(id) {} diff --git a/src/crepe/Collider.h b/src/crepe/Collider.h index 827f83d..a1e9095 100644 --- a/src/crepe/Collider.h +++ b/src/crepe/Collider.h @@ -6,7 +6,7 @@ namespace crepe {  class Collider : public Component {  public: -	Collider(game_object_id_t id); +	using Component::Component;  	int size;  }; diff --git a/src/crepe/Component.cpp b/src/crepe/Component.cpp index 73c2d07..c133739 100644 --- a/src/crepe/Component.cpp +++ b/src/crepe/Component.cpp @@ -1,6 +1,6 @@  #include "Component.h" -#include "types.h"  using namespace crepe; -Component::Component(game_object_id_t id) : game_object_id(id) {} +Component::Component(const Data & data) : data(data) {} + diff --git a/src/crepe/Component.h b/src/crepe/Component.h index 0fe60b2..c6d72df 100644 --- a/src/crepe/Component.h +++ b/src/crepe/Component.h @@ -2,8 +2,6 @@  #include "types.h" -#include <cstdint> -  namespace crepe {  class ComponentManager; @@ -15,13 +13,21 @@ class ComponentManager;   * interface for all components.   */  class Component { +public: +	struct Data { +		//! The ID of the GameObject this component belongs to +		const game_object_id_t id; +		//! The manager of this component +		ComponentManager & component_manager; +	}; +  protected: -	//! Only the ComponentManager can create components -	friend class crepe::ComponentManager;  	/** -	 * \param id The id of the GameObject this component belongs to +	 * \param base Data  	 */ -	Component(game_object_id_t id); +	Component(const Data & base); +	//! Only the ComponentManager can create components +	friend class crepe::ComponentManager;  public:  	virtual ~Component() = default; @@ -37,8 +43,7 @@ public:  	virtual int get_instances_max() const { return -1; }  public: -	//! The id of the GameObject this component belongs to -	const game_object_id_t game_object_id; +	Data data;  	//! Whether the component is active  	bool active = true;  }; diff --git a/src/crepe/ComponentManager.cpp b/src/crepe/ComponentManager.cpp index 85149c8..f6acc1a 100644 --- a/src/crepe/ComponentManager.cpp +++ b/src/crepe/ComponentManager.cpp @@ -1,13 +1,10 @@ +#include "api/GameObject.h"  #include "util/log.h"  #include "ComponentManager.h"  using namespace crepe; - -ComponentManager & ComponentManager::get_instance() { -	static ComponentManager instance; -	return instance; -} +using namespace std;  void ComponentManager::delete_all_components_of_id(game_object_id_t id) {  	// Loop through all the types (in the unordered_map<>) @@ -26,5 +23,12 @@ void ComponentManager::delete_all_components() {  }  ComponentManager::ComponentManager() { dbg_trace(); } -  ComponentManager::~ComponentManager() { dbg_trace(); } + +GameObject & ComponentManager::new_object(const string & name, const string & tag, const Vector2 & position, double rotation, double scale) { +	GameObject * object = new GameObject(*this, this->next_id, name, tag, position, rotation, scale); +	this->objects.push_front(unique_ptr<GameObject>(object)); +	this->next_id++; +	return *object; +} + diff --git a/src/crepe/ComponentManager.h b/src/crepe/ComponentManager.h index c8c196c..e37bc4a 100644 --- a/src/crepe/ComponentManager.h +++ b/src/crepe/ComponentManager.h @@ -1,15 +1,18 @@  #pragma once -#include <cstdint>  #include <memory>  #include <typeindex>  #include <unordered_map>  #include <vector> +#include <forward_list>  #include "Component.h" +#include "api/Vector2.h"  namespace crepe { +class GameObject; +  /**   * \brief Manages all components   *  @@ -18,18 +21,10 @@ namespace crepe {   */  class ComponentManager {  public: -	/** -	 * \brief Get the instance of the ComponentManager -	 *  -	 * \return The instance of the ComponentManager -	 */ -	static ComponentManager & get_instance(); -	ComponentManager(const ComponentManager &) = delete; -	ComponentManager(ComponentManager &&) = delete; -	ComponentManager & operator=(const ComponentManager &) = delete; -	ComponentManager & operator=(ComponentManager &&) = delete; -	~ComponentManager(); +	ComponentManager(); // dbg_trace +	~ComponentManager(); // dbg_trace +public:  	/**  	 * \brief Add a component to the ComponentManager  	 *  @@ -100,8 +95,8 @@ public:  	template <typename T>  	std::vector<std::reference_wrapper<T>> get_components_by_type() const; -private: -	ComponentManager(); +	// TODO: doxygen +	GameObject & new_object(const std::string & name, const std::string & tag = "", const Vector2 & position = { 0, 0 }, double rotation = 0, double scale = 0);  private:  	/** @@ -118,6 +113,10 @@ private:  	std::unordered_map<std::type_index,  					   std::vector<std::vector<std::unique_ptr<Component>>>>  		components; + +	//! ID of next GameObject +	game_object_id_t next_id = 0; +	std::forward_list<std::unique_ptr<GameObject>> objects;  };  } // namespace crepe diff --git a/src/crepe/ComponentManager.hpp b/src/crepe/ComponentManager.hpp index 98efb49..89a8536 100644 --- a/src/crepe/ComponentManager.hpp +++ b/src/crepe/ComponentManager.hpp @@ -31,7 +31,10 @@ T & ComponentManager::add_component(game_object_id_t id, Args &&... args) {  	// Create a new component of type T (arguments directly forwarded). The  	// constructor must be called by ComponentManager. -	T * instance_ptr = new T(id, forward<Args>(args)...); +	T * instance_ptr = new T(Component::Data { +		.id = id, +		.component_manager = *this, +	}, forward<Args>(args)...);  	if (instance_ptr == nullptr) throw std::bad_alloc();  	T & instance_ref = *instance_ptr; diff --git a/src/crepe/Resource.h b/src/crepe/Resource.h new file mode 100644 index 0000000..dcf3dbd --- /dev/null +++ b/src/crepe/Resource.h @@ -0,0 +1,33 @@ +#pragma once + +#include <memory> + +namespace crepe { + +class ResourceManager; +class Asset; + +/** + * Resource is an interface class used to represent a (deserialized) game + * resource (e.g. textures, sounds). + */ +class Resource { +private: +	/** +	 * \brief Prototype pattern clone function. +	 * +	 * \param src Source file of new resource (abstraction for file saved on +	 * disk) +	 * +	 * \returns New instance of concrete resource +	 */ +	virtual std::unique_ptr<Resource> clone(const Asset & src) const = 0; +	/** +	 * The resource manager uses \c clone to create new instances of the concrete +	 * resource class. This may be used to inherit references to classes that +	 * would otherwise need to be implemented as singletons. +	 */ +	friend class ResourceManager; +}; + +} // namespace crepe diff --git a/src/crepe/api/Animator.cpp b/src/crepe/api/Animator.cpp index 58fee2a..ad60981 100644 --- a/src/crepe/api/Animator.cpp +++ b/src/crepe/api/Animator.cpp @@ -9,8 +9,8 @@  using namespace crepe; -Animator::Animator(uint32_t id, Sprite & ss, int row, int col, int col_animator) -	: Component(id), +Animator::Animator(const Component::Data & data, Sprite & ss, int row, int col, int col_animator) +	: Component(data),  	  spritesheet(ss),  	  row(row),  	  col(col) { diff --git a/src/crepe/api/Animator.h b/src/crepe/api/Animator.h index def0240..f66dc1a 100644 --- a/src/crepe/api/Animator.h +++ b/src/crepe/api/Animator.h @@ -6,6 +6,7 @@  #include "Sprite.h"  namespace crepe { +  class AnimatorSystem;  class SDLContext; @@ -35,7 +36,7 @@ public:  	 *  	 * This constructor sets up the Animator with the given parameters, and initializes the animation system.  	 */ -	Animator(uint32_t id, Sprite & spritesheet, int row, int col, +	Animator(const Component::Data & data, Sprite & spritesheet, int row, int col,  			 int col_animate);  	~Animator(); // dbg_trace diff --git a/src/crepe/api/BehaviorScript.cpp b/src/crepe/api/BehaviorScript.cpp index e69de29..ce1cfde 100644 --- a/src/crepe/api/BehaviorScript.cpp +++ b/src/crepe/api/BehaviorScript.cpp @@ -0,0 +1,4 @@ +#include "BehaviorScript.h" + +using namespace crepe; + diff --git a/src/crepe/api/BehaviorScript.h b/src/crepe/api/BehaviorScript.h index 6b1fec7..8d21a72 100644 --- a/src/crepe/api/BehaviorScript.h +++ b/src/crepe/api/BehaviorScript.h @@ -12,19 +12,35 @@ class Script;  class BehaviorScript : public Component {  protected: -	friend class crepe::ComponentManager;  	using Component::Component; +	//! Only ComponentManager is allowed to instantiate BehaviorScript +	friend class ComponentManager;  public:  	virtual ~BehaviorScript() = default;  public: +	/** +	 * \brief Set the concrete script of this component +	 * +	 * \tparam T Concrete script type (derived from \c crepe::Script) +	 * +	 * \returns Reference to BehaviorScript component (`*this`) +	 */  	template <class T>  	BehaviorScript & set_script();  protected: -	friend class crepe::ScriptSystem; +	//! ScriptSystem needs direct access to the script instance +	friend class ScriptSystem; +	//! Flag to indicate if script->init() has been called already +	bool initialized = false;  	std::unique_ptr<Script> script = nullptr; + +private: +	//! Script accesses the component manager directly via its parent +	// (BehaviorScript) reference +	friend class Script;  };  } // namespace crepe diff --git a/src/crepe/api/BehaviorScript.hpp b/src/crepe/api/BehaviorScript.hpp index 4751607..bb5d829 100644 --- a/src/crepe/api/BehaviorScript.hpp +++ b/src/crepe/api/BehaviorScript.hpp @@ -11,10 +11,10 @@ namespace crepe {  template <class T>  BehaviorScript & BehaviorScript::set_script() { -	static_assert(std::is_base_of<Script, T>::value);  	dbg_trace(); +	static_assert(std::is_base_of<Script, T>::value);  	Script * s = new T(); -	s->parent = this; +	s->parent_ref = this;  	this->script = std::unique_ptr<Script>(s);  	return *this;  } diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 85696c4..d9cda57 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -14,11 +14,11 @@ target_sources(crepe PUBLIC  	Config.cpp  	Metadata.cpp  	Scene.cpp -	SceneManager.cpp +	# SceneManager.cpp  	Vector2.cpp  	Camera.cpp  	Animator.cpp -	LoopManager.cpp +	# LoopManager.cpp  	LoopTimer.cpp  ) @@ -40,10 +40,10 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES  	SaveManager.h  	Scene.h  	Metadata.h -	SceneManager.h -	SceneManager.hpp +	# SceneManager.h +	# SceneManager.hpp  	Camera.h  	Animator.h -	LoopManager.h +	# LoopManager.h  	LoopTimer.h  ) diff --git a/src/crepe/api/Camera.cpp b/src/crepe/api/Camera.cpp index 6355a03..fece199 100644 --- a/src/crepe/api/Camera.cpp +++ b/src/crepe/api/Camera.cpp @@ -1,6 +1,3 @@ - -#include <cstdint> -  #include "util/log.h"  #include "Camera.h" @@ -9,8 +6,8 @@  using namespace crepe; -Camera::Camera(uint32_t id, const Color & bg_color) -	: Component(id), +Camera::Camera(const Component::Data & data, const Color & bg_color) +	: Component(data),  	  bg_color(bg_color) {  	dbg_trace();  } diff --git a/src/crepe/api/Camera.h b/src/crepe/api/Camera.h index ba3a9ef..a52f2f7 100644 --- a/src/crepe/api/Camera.h +++ b/src/crepe/api/Camera.h @@ -23,7 +23,7 @@ public:  	 * \param id Unique identifier for the camera component.  	 * \param bg_color Background color for the camera view.  	 */ -	Camera(uint32_t id, const Color & bg_color); +	Camera(const Component::Data & data, const Color & bg_color);  	~Camera(); // dbg_trace only  public: diff --git a/src/crepe/api/GameObject.cpp b/src/crepe/api/GameObject.cpp index d252e77..bba1f26 100644 --- a/src/crepe/api/GameObject.cpp +++ b/src/crepe/api/GameObject.cpp @@ -6,18 +6,19 @@  using namespace crepe;  using namespace std; -GameObject::GameObject(game_object_id_t id, const std::string & name, +GameObject::GameObject(ComponentManager & component_manager, game_object_id_t id, const std::string & name,  					   const std::string & tag, const Vector2 & position,  					   double rotation, double scale) -	: id(id) { +	: id(id), component_manager(component_manager) { +  	// Add Transform and Metadata components -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	mgr.add_component<Transform>(this->id, position, rotation, scale);  	mgr.add_component<Metadata>(this->id, name, tag);  }  void GameObject::set_parent(const GameObject & parent) { -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	// Set parent on own Metadata component  	vector<reference_wrapper<Metadata>> this_metadata diff --git a/src/crepe/api/GameObject.h b/src/crepe/api/GameObject.h index d703730..d09938a 100644 --- a/src/crepe/api/GameObject.h +++ b/src/crepe/api/GameObject.h @@ -3,10 +3,11 @@  #include <string>  #include "types.h" +#include "Vector2.h"  namespace crepe { -class Vector2; +class ComponentManager;  /**   * \brief Represents a GameObject @@ -16,11 +17,12 @@ class Vector2;   * done in the ComponentManager.   */  class GameObject { -public: +private:  	/**  	 * This constructor creates a new GameObject. It creates a new  	 * Transform and Metadata component and adds them to the ComponentManager.  	 *  +	 * \param component_manager Reference to component_manager  	 * \param id The id of the GameObject  	 * \param name The name of the GameObject  	 * \param tag The tag of the GameObject @@ -28,9 +30,11 @@ public:  	 * \param rotation The rotation of the GameObject  	 * \param scale The scale of the GameObject  	 */ -	GameObject(game_object_id_t id, const std::string & name, -			   const std::string & tag, const Vector2 & position, -			   double rotation, double scale); +	GameObject(ComponentManager & component_manager, game_object_id_t id, const std::string & name, const std::string & tag, const Vector2 & position, double rotation, double scale); +	//! ComponentManager instances GameObject +	friend class ComponentManager; + +public:  	/**  	 * \brief Set the parent of this GameObject  	 *  @@ -58,6 +62,9 @@ public:  public:  	//! The id of the GameObject  	const game_object_id_t id; + +protected: +	ComponentManager & component_manager;  };  } // namespace crepe diff --git a/src/crepe/api/GameObject.hpp b/src/crepe/api/GameObject.hpp index bfba7fe..17b17d7 100644 --- a/src/crepe/api/GameObject.hpp +++ b/src/crepe/api/GameObject.hpp @@ -8,7 +8,7 @@ namespace crepe {  template <typename T, typename... Args>  T & GameObject::add_component(Args &&... args) { -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	return mgr.add_component<T>(this->id, std::forward<Args>(args)...);  } diff --git a/src/crepe/api/Metadata.cpp b/src/crepe/api/Metadata.cpp index d421de5..6f0a280 100644 --- a/src/crepe/api/Metadata.cpp +++ b/src/crepe/api/Metadata.cpp @@ -3,7 +3,7 @@  using namespace crepe;  using namespace std; -Metadata::Metadata(game_object_id_t id, const string & name, const string & tag) -	: Component(id), +Metadata::Metadata(const Component::Data & data, const string & name, const string & tag) +	: Component(data),  	  name(name),  	  tag(tag) {} diff --git a/src/crepe/api/Metadata.h b/src/crepe/api/Metadata.h index c61e006..8c91797 100644 --- a/src/crepe/api/Metadata.h +++ b/src/crepe/api/Metadata.h @@ -20,7 +20,7 @@ public:  	 * \param name The name of the GameObject  	 * \param tag The tag of the GameObject  	 */ -	Metadata(game_object_id_t id, const std::string & name, +	Metadata(const Component::Data & data, const std::string & name,  			 const std::string & tag);  	/**  	 * \brief Get the maximum number of instances for this component diff --git a/src/crepe/api/ParticleEmitter.cpp b/src/crepe/api/ParticleEmitter.cpp index 0bc2197..ed4fec8 100644 --- a/src/crepe/api/ParticleEmitter.cpp +++ b/src/crepe/api/ParticleEmitter.cpp @@ -6,12 +6,12 @@  using namespace crepe; -ParticleEmitter::ParticleEmitter(game_object_id_t id, uint32_t max_particles, +ParticleEmitter::ParticleEmitter(const Component::Data & data, uint32_t max_particles,  								 uint32_t emission_rate, uint32_t speed,  								 uint32_t speed_offset, uint32_t angle,  								 uint32_t angleOffset, float begin_lifespan,  								 float end_lifespan) -	: Component(id), +	: Component(data),  	  max_particles(max_particles),  	  emission_rate(emission_rate),  	  speed(speed), diff --git a/src/crepe/api/ParticleEmitter.h b/src/crepe/api/ParticleEmitter.h index 5939723..ba89538 100644 --- a/src/crepe/api/ParticleEmitter.h +++ b/src/crepe/api/ParticleEmitter.h @@ -10,7 +10,7 @@ namespace crepe {  class ParticleEmitter : public Component {  public: -	ParticleEmitter(game_object_id_t id, uint32_t max_particles, +	ParticleEmitter(const Component::Data & data, uint32_t max_particles,  					uint32_t emission_rate, uint32_t speed,  					uint32_t speed_offset, uint32_t angle, uint32_t angleOffset,  					float begin_lifespan, float end_lifespan); diff --git a/src/crepe/api/Rigidbody.cpp b/src/crepe/api/Rigidbody.cpp index 3bf1c5b..be6bb93 100644 --- a/src/crepe/api/Rigidbody.cpp +++ b/src/crepe/api/Rigidbody.cpp @@ -2,8 +2,8 @@  using namespace crepe; -crepe::Rigidbody::Rigidbody(uint32_t game_object_id, const Data & data) -	: Component(game_object_id), +crepe::Rigidbody::Rigidbody(const Component::Data & component_data, const Data & data) +	: Component(component_data),  	  data(data) {}  void crepe::Rigidbody::add_force_linear(const Vector2 & force) { diff --git a/src/crepe/api/Rigidbody.h b/src/crepe/api/Rigidbody.h index 68481f4..99837a6 100644 --- a/src/crepe/api/Rigidbody.h +++ b/src/crepe/api/Rigidbody.h @@ -82,7 +82,7 @@ public:  	 * \param game_object_id id of the gameobject the rigibody is added to.  	 * \param data struct to configure the rigidbody.  	 */ -	Rigidbody(uint32_t game_object_id, const Data & data); +	Rigidbody(const Component::Data & component_data, const Data & data);  	//! struct to hold data of rigidbody  	Data data; diff --git a/src/crepe/api/Script.cpp b/src/crepe/api/Script.cpp index 390cec7..0423315 100644 --- a/src/crepe/api/Script.cpp +++ b/src/crepe/api/Script.cpp @@ -1,3 +1,4 @@  #include "Script.h"  using namespace crepe; + diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h index 49e625f..d543df8 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -11,6 +11,7 @@ namespace crepe {  class BehaviorScript;  class Script { +	//! ScriptSystem calls \c update()  	friend class crepe::ScriptSystem;  protected: @@ -22,17 +23,25 @@ protected:  	// added event.  protected: +	//! Retrieve component from component manager (utility)  	template <typename T>  	T & get_component(); +	//! Retrieve components from component manager (utility)  	template <typename T>  	std::vector<std::reference_wrapper<T>> get_components(); -private: -	friend class crepe::BehaviorScript; -	BehaviorScript * parent = nullptr; +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; +	BehaviorScript * parent_ref = nullptr;  };  } // namespace crepe  #include "Script.hpp" + diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp index d96c0e8..68bcc29 100644 --- a/src/crepe/api/Script.hpp +++ b/src/crepe/api/Script.hpp @@ -18,8 +18,10 @@ T & Script::get_component() {  template <typename T>  std::vector<std::reference_wrapper<T>> Script::get_components() { -	ComponentManager & mgr = ComponentManager::get_instance(); -	return mgr.get_components_by_id<T>(this->parent->game_object_id); +	auto & parent = *this->parent_ref; +	auto & mgr = parent.data.component_manager; + +	return mgr.get_components_by_id<T>(parent.data.id);  }  } // namespace crepe diff --git a/src/crepe/api/Sprite.cpp b/src/crepe/api/Sprite.cpp index 6f0433f..716609f 100644 --- a/src/crepe/api/Sprite.cpp +++ b/src/crepe/api/Sprite.cpp @@ -10,9 +10,9 @@  using namespace std;  using namespace crepe; -Sprite::Sprite(game_object_id_t id, const shared_ptr<Texture> image, +Sprite::Sprite(const Component::Data & data, const shared_ptr<Texture> image,  			   const Color & color, const FlipSettings & flip) -	: Component(id), +	: Component(data),  	  color(color),  	  flip(flip),  	  sprite_image(image) { diff --git a/src/crepe/api/Sprite.h b/src/crepe/api/Sprite.h index deb3f93..171dfeb 100644 --- a/src/crepe/api/Sprite.h +++ b/src/crepe/api/Sprite.h @@ -43,7 +43,7 @@ public:  	 * \param color Color tint applied to the sprite.  	 * \param flip Flip settings for horizontal and vertical orientation.  	 */ -	Sprite(game_object_id_t id, const std::shared_ptr<Texture> image, +	Sprite(const Component::Data & data, const std::shared_ptr<Texture> image,  		   const Color & color, const FlipSettings & flip);  	/** diff --git a/src/crepe/api/Transform.cpp b/src/crepe/api/Transform.cpp index e401120..9645d03 100644 --- a/src/crepe/api/Transform.cpp +++ b/src/crepe/api/Transform.cpp @@ -4,9 +4,9 @@  using namespace crepe; -Transform::Transform(game_object_id_t id, const Vector2 & point, +Transform::Transform(const Component::Data & data, const Vector2 & point,  					 double rotation, double scale) -	: Component(id), +	: Component(data),  	  position(point),  	  rotation(rotation),  	  scale(scale) { diff --git a/src/crepe/api/Transform.h b/src/crepe/api/Transform.h index 756e45b..a7bcd89 100644 --- a/src/crepe/api/Transform.h +++ b/src/crepe/api/Transform.h @@ -20,7 +20,7 @@ public:  	 * \param rotation The rotation of the GameObject  	 * \param scale The scale of the GameObject  	 */ -	Transform(game_object_id_t id, const Vector2 & point, double rotation, +	Transform(const Component::Data & data, const Vector2 & point, double rotation,  			  double scale);  	/**  	 * \brief Get the maximum number of instances for this component diff --git a/src/crepe/facade/Sound.cpp b/src/crepe/facade/Sound.cpp index 648ec81..3a6e1e1 100644 --- a/src/crepe/facade/Sound.cpp +++ b/src/crepe/facade/Sound.cpp @@ -1,26 +1,24 @@ +#include <memory> +  #include "../util/log.h" +#include "../Asset.h"  #include "Sound.h"  #include "SoundContext.h"  using namespace crepe; +using namespace std; -Sound::Sound(std::unique_ptr<Asset> res) { -	dbg_trace(); -	this->load(std::move(res)); -} +Sound::Sound(SoundContext & ctx) : context(ctx) { dbg_trace(); } -Sound::Sound(const char * src) { -	dbg_trace(); -	this->load(std::make_unique<Asset>(src)); -} - -void Sound::load(std::unique_ptr<Asset> res) { -	this->sample.load(res->canonical()); +unique_ptr<Resource> Sound::clone(const Asset & src) const { +	auto instance = make_unique<Sound>(*this); +	instance->sample.load(src.canonical()); +	return instance;  }  void Sound::play() { -	SoundContext & ctx = SoundContext::get_instance(); +	SoundContext & ctx = this->context;  	if (ctx.engine.getPause(this->handle)) {  		// resume if paused  		ctx.engine.setPause(this->handle, false); @@ -32,13 +30,13 @@ void Sound::play() {  }  void Sound::pause() { -	SoundContext & ctx = SoundContext::get_instance(); +	SoundContext & ctx = this->context;  	if (ctx.engine.getPause(this->handle)) return;  	ctx.engine.setPause(this->handle, true);  }  void Sound::rewind() { -	SoundContext & ctx = SoundContext::get_instance(); +	SoundContext & ctx = this->context;  	if (!ctx.engine.isValidVoiceHandle(this->handle)) return;  	ctx.engine.seek(this->handle, 0);  } @@ -46,7 +44,7 @@ void Sound::rewind() {  void Sound::set_volume(float volume) {  	this->volume = volume; -	SoundContext & ctx = SoundContext::get_instance(); +	SoundContext & ctx = this->context;  	if (!ctx.engine.isValidVoiceHandle(this->handle)) return;  	ctx.engine.setVolume(this->handle, this->volume);  } @@ -54,7 +52,8 @@ void Sound::set_volume(float volume) {  void Sound::set_looping(bool looping) {  	this->looping = looping; -	SoundContext & ctx = SoundContext::get_instance(); +	SoundContext & ctx = this->context;  	if (!ctx.engine.isValidVoiceHandle(this->handle)) return;  	ctx.engine.setLooping(this->handle, this->looping);  } + diff --git a/src/crepe/facade/Sound.h b/src/crepe/facade/Sound.h index 183bd7c..e5b2f19 100644 --- a/src/crepe/facade/Sound.h +++ b/src/crepe/facade/Sound.h @@ -4,11 +4,13 @@  #include <soloud/soloud.h>  #include <soloud/soloud_wav.h> -#include "../Asset.h" +#include "../Resource.h"  namespace crepe { -class Sound { +class SoundContext; + +class Sound : public Resource {  public:  	/**  	 * \brief Pause this sample @@ -64,15 +66,13 @@ public:  	bool get_looping() const { return this->looping; }  public: -	Sound(const char * src); -	Sound(std::unique_ptr<Asset> res); - -private: -	void load(std::unique_ptr<Asset> res); +	Sound(SoundContext & ctx); +	std::unique_ptr<Resource> clone(const Asset & src) const override;  private:  	SoLoud::Wav sample;  	SoLoud::handle handle; +	SoundContext & context;  	float volume = 1.0f;  	bool looping = false; diff --git a/src/crepe/facade/SoundContext.cpp b/src/crepe/facade/SoundContext.cpp index 5e5a3a9..c89fb03 100644 --- a/src/crepe/facade/SoundContext.cpp +++ b/src/crepe/facade/SoundContext.cpp @@ -4,11 +4,6 @@  using namespace crepe; -SoundContext & SoundContext::get_instance() { -	static SoundContext instance; -	return instance; -} -  SoundContext::SoundContext() {  	dbg_trace();  	engine.init(); @@ -18,3 +13,4 @@ SoundContext::~SoundContext() {  	dbg_trace();  	engine.deinit();  } + diff --git a/src/crepe/facade/SoundContext.h b/src/crepe/facade/SoundContext.h index d3123d2..c360fb8 100644 --- a/src/crepe/facade/SoundContext.h +++ b/src/crepe/facade/SoundContext.h @@ -7,19 +7,18 @@  namespace crepe {  class SoundContext { -private: +public:  	SoundContext();  	virtual ~SoundContext(); -	// singleton -	static SoundContext & get_instance(); -	SoundContext(const SoundContext &) = delete; -	SoundContext(SoundContext &&) = delete; -	SoundContext & operator=(const SoundContext &) = delete; -	SoundContext & operator=(SoundContext &&) = delete; +  SoundContext(const SoundContext &) = delete; +  SoundContext(SoundContext &&) = delete; +  SoundContext & operator=(const SoundContext &) = delete; +  SoundContext & operator=(SoundContext &&) = delete;  private:  	SoLoud::Soloud engine; +	//! Sound directly calls methods on \c engine  	friend class Sound;  }; diff --git a/src/crepe/system/CMakeLists.txt b/src/crepe/system/CMakeLists.txt index 4c18b87..9ee12f6 100644 --- a/src/crepe/system/CMakeLists.txt +++ b/src/crepe/system/CMakeLists.txt @@ -1,17 +1,18 @@  target_sources(crepe PUBLIC -	ParticleSystem.cpp +	System.cpp +	# ParticleSystem.cpp  	ScriptSystem.cpp -	PhysicsSystem.cpp -	CollisionSystem.cpp -	RenderSystem.cpp -	AnimatorSystem.cpp +	# PhysicsSystem.cpp +	# CollisionSystem.cpp +	# RenderSystem.cpp +	# AnimatorSystem.cpp  )  target_sources(crepe PUBLIC FILE_SET HEADERS FILES  	System.h  	ScriptSystem.h -	PhysicsSystem.h -	CollisionSystem.h -	RenderSystem.h -	AnimatorSystem.h +	# PhysicsSystem.h +	# CollisionSystem.h +	# RenderSystem.h +	# AnimatorSystem.h  ) diff --git a/src/crepe/system/ScriptSystem.cpp b/src/crepe/system/ScriptSystem.cpp index f2673e7..0a87fcc 100644 --- a/src/crepe/system/ScriptSystem.cpp +++ b/src/crepe/system/ScriptSystem.cpp @@ -13,16 +13,24 @@ using namespace std;  using namespace crepe;  void ScriptSystem::update() { -	using namespace std;  	dbg_trace(); -	forward_list<Script *> scripts = this->get_scripts(); -	for (Script * script : scripts) script->update(); +	forward_list<reference_wrapper<Script>> scripts = this->get_scripts(); + +	for (auto & script_ref : scripts) { +		Script & script = script_ref.get(); +		BehaviorScript & component = *script.parent_ref; +		if (!component.initialized) { +			script.init(); +			component.initialized = true; +		} +		script.update(); +	}  } -forward_list<Script *> ScriptSystem::get_scripts() { -	forward_list<Script *> scripts = {}; -	ComponentManager & mgr = ComponentManager::get_instance(); +forward_list<reference_wrapper<Script>> ScriptSystem::get_scripts() { +	forward_list<reference_wrapper<Script>> scripts = {}; +	ComponentManager & mgr = this->component_manager;  	vector<reference_wrapper<BehaviorScript>> behavior_scripts  		= mgr.get_components_by_type<BehaviorScript>(); @@ -31,8 +39,9 @@ forward_list<Script *> ScriptSystem::get_scripts() {  		if (!behavior_script.active) continue;  		Script * script = behavior_script.script.get();  		if (script == nullptr) continue; -		scripts.push_front(script); +		scripts.push_front(*script);  	}  	return scripts;  } + diff --git a/src/crepe/system/ScriptSystem.h b/src/crepe/system/ScriptSystem.h index 4fa6141..b52e825 100644 --- a/src/crepe/system/ScriptSystem.h +++ b/src/crepe/system/ScriptSystem.h @@ -7,14 +7,15 @@  namespace crepe {  class Script; +class BehaviorScript;  class ScriptSystem : public System {  public: +	using System::System;  	void update();  private: -	// TODO: to forward_list<reference_wrapper> -	std::forward_list<Script *> get_scripts(); +	std::forward_list<std::reference_wrapper<Script>> get_scripts();  };  } // namespace crepe diff --git a/src/crepe/system/System.cpp b/src/crepe/system/System.cpp new file mode 100644 index 0000000..296f1ed --- /dev/null +++ b/src/crepe/system/System.cpp @@ -0,0 +1,6 @@ +#include "System.h" + +using namespace crepe; + +System::System(ComponentManager & mgr) : component_manager(mgr) {} + diff --git a/src/crepe/system/System.h b/src/crepe/system/System.h index 3b81bef..7970e72 100644 --- a/src/crepe/system/System.h +++ b/src/crepe/system/System.h @@ -2,13 +2,18 @@  namespace crepe { +class ComponentManager; +  class System {  public:  	virtual void update() = 0;  public: -	System() = default; +	System(ComponentManager &);  	virtual ~System() = default; + +protected: +	ComponentManager & component_manager;  };  } // namespace crepe diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 0e4eaed..9d303bc 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -1,6 +1,6 @@  target_sources(test_main PUBLIC -	dummy.cpp -	# audio.cpp -	PhysicsTest.cpp +	main.cpp +	# PhysicsTest.cpp +	ScriptTest.cpp  ) diff --git a/src/test/PhysicsTest.cpp b/src/test/PhysicsTest.cpp index 5385962..538d244 100644 --- a/src/test/PhysicsTest.cpp +++ b/src/test/PhysicsTest.cpp @@ -11,9 +11,11 @@ using namespace std::chrono_literals;  using namespace crepe;  class PhysicsTest : public ::testing::Test { -protected: +public:  	GameObject * game_object; +	ComponentManager component_manager;  	PhysicsSystem physics_system; +  	void SetUp() override {  		ComponentManager & mgr = ComponentManager::get_instance();  		std::vector<std::reference_wrapper<Transform>> transforms diff --git a/src/test/ScriptTest.cpp b/src/test/ScriptTest.cpp new file mode 100644 index 0000000..ea49a35 --- /dev/null +++ b/src/test/ScriptTest.cpp @@ -0,0 +1,73 @@ +#include <gtest/gtest.h> + +// stupid hack to allow access to private/protected members under test +#define private public +#define protected public + +#include <crepe/ComponentManager.h> +#include <crepe/system/ScriptSystem.h> +#include <crepe/api/BehaviorScript.h> +#include <crepe/api/Script.h> +#include <crepe/api/GameObject.h> +#include <crepe/api/Vector2.h> + +using namespace std; +using namespace crepe; +using namespace testing; + +class ScriptTest : public Test { +public: +	ComponentManager component_manager {}; +	ScriptSystem system { component_manager }; + +	class MyScript : public Script { +		// NOTE: default (private) visibility of init and update shouldn't cause +		// issues! +		void init() { this->init_count++; } +		void update() { this->update_count++; } + +	public: +		unsigned init_count = 0; +		unsigned update_count = 0; +	}; + +	BehaviorScript * behaviorscript_ref = nullptr; +	MyScript * script_ref = nullptr; + +	void SetUp() override { +		auto & mgr = this->component_manager; +		GameObject & entity = mgr.new_object("name"); +		BehaviorScript & component = entity.add_component<BehaviorScript>(); + +		this->behaviorscript_ref = &component; +		EXPECT_EQ(this->behaviorscript_ref->script.get(), nullptr); +		component.set_script<MyScript>(); +		ASSERT_NE(this->behaviorscript_ref->script.get(), nullptr); + +		this->script_ref = (MyScript *) this->behaviorscript_ref->script.get(); +		ASSERT_NE(this->script_ref, nullptr); +	} +}; + +TEST_F(ScriptTest, Default) { +	EXPECT_EQ(0, this->script_ref->init_count); +	EXPECT_EQ(0, this->script_ref->update_count); +} + +TEST_F(ScriptTest, UpdateOnce) { +	EXPECT_EQ(0, this->script_ref->init_count); +	EXPECT_EQ(0, this->script_ref->update_count); + +	this->system.update(); +	EXPECT_EQ(1, this->script_ref->init_count); +	EXPECT_EQ(1, this->script_ref->update_count); +} + +TEST_F(ScriptTest, ListScripts) { +	size_t script_count = 0; +	for (auto & _ : this->system.get_scripts()) { +		script_count++; +	} +	ASSERT_EQ(1, script_count); +} + diff --git a/src/test/audio.cpp b/src/test/audio.cpp deleted file mode 100644 index d6ff689..0000000 --- a/src/test/audio.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include <gtest/gtest.h> - -using namespace std; -using namespace std::chrono_literals; - -// using namespace crepe; - -// TODO: mock internal audio class - -TEST(audio, play) { ASSERT_TRUE(true); } diff --git a/src/test/dummy.cpp b/src/test/dummy.cpp deleted file mode 100644 index a00a9c6..0000000 --- a/src/test/dummy.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include <gtest/gtest.h> - -TEST(dummy, foo) { ASSERT_TRUE(1); } diff --git a/src/test/main.cpp b/src/test/main.cpp new file mode 100644 index 0000000..6830a01 --- /dev/null +++ b/src/test/main.cpp @@ -0,0 +1,15 @@ +#include <crepe/api/Config.h> + +#include <gtest/gtest.h> + +using namespace crepe; +using namespace testing; + +int main(int argc, char **argv) { +  InitGoogleTest(&argc, argv); + +	auto & cfg = Config::get_instance(); +	cfg.log.level = LogLevel::ERROR; + +  return RUN_ALL_TESTS(); +} |