diff options
Diffstat (limited to 'src/crepe')
82 files changed, 693 insertions, 567 deletions
| diff --git a/src/crepe/Asset.cpp b/src/crepe/Asset.cpp index 8a2a11c..9c41ecb 100644 --- a/src/crepe/Asset.cpp +++ b/src/crepe/Asset.cpp @@ -3,14 +3,14 @@  #include "Asset.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; +// FIXME: restore this +// src(std::filesystem::canonical(src)) +Asset::Asset(const std::string & src) : src(src) {  	this->file = std::ifstream(this->src, std::ios::in | std::ios::binary);  } -const std::istream & Asset::read() { return this->file; } +istream & Asset::get_stream() { return this->file; } -const char * Asset::canonical() { return this->src.c_str(); } +const string & Asset::get_canonical() const { return this->src; } diff --git a/src/crepe/Asset.h b/src/crepe/Asset.h index ef20647..9051c5e 100644 --- a/src/crepe/Asset.h +++ b/src/crepe/Asset.h @@ -20,13 +20,21 @@ public:  	Asset(const std::string & src);  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(); +	/** +	 * \brief Get an input stream to the contents of this asset +	 * \return Input stream with file contents +	 */ +	std::istream & get_stream(); +	/** +	 * \brief Get the canonical path to this asset +	 * \return Canonical path to this asset +	 */ +	const std::string & get_canonical() const;  private: -	std::string src; +	//! Canonical path to asset +	const std::string src; +	//! File handle (stream)  	std::ifstream file;  }; diff --git a/src/crepe/CMakeLists.txt b/src/crepe/CMakeLists.txt index fc95bd3..3b05742 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -4,7 +4,6 @@ target_sources(crepe PUBLIC  	ComponentManager.cpp  	Component.cpp  	Collider.cpp -	Exception.cpp  )  target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -15,7 +14,6 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES  	Collider.h  	ValueBroker.h  	ValueBroker.hpp -	Exception.h  )  add_subdirectory(api) diff --git a/src/crepe/Collider.cpp b/src/crepe/Collider.cpp index bbec488..113ba61 100644 --- a/src/crepe/Collider.cpp +++ b/src/crepe/Collider.cpp @@ -1,5 +1,3 @@  #include "Collider.h"  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..acfd35c 100644 --- a/src/crepe/Component.cpp +++ b/src/crepe/Component.cpp @@ -1,5 +1,4 @@  #include "Component.h" -#include "types.h"  using namespace crepe; diff --git a/src/crepe/Component.h b/src/crepe/Component.h index 59570bc..68b28ef 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,16 +13,23 @@ class ComponentManager;   * components.   */  class Component { +public: +	//! Whether the component is active +	bool active = true; +	//! The id of the GameObject this component belongs to +	const game_object_id_t game_object_id; +  protected: -	//! Only the ComponentManager can create components -	friend class crepe::ComponentManager;  	/**  	 * \param id The id of the GameObject this component belongs to  	 */  	Component(game_object_id_t id); - +	//! Only the ComponentManager can create components +	friend class ComponentManager;  public:  	virtual ~Component() = default; + +public:  	/**  	 * \brief Get the maximum number of instances for this component  	 * @@ -34,12 +39,6 @@ public:  	 * \return The maximum number of instances for this component  	 */  	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; -	//! Whether the component is active -	bool active = true;  };  } // namespace crepe diff --git a/src/crepe/ComponentManager.cpp b/src/crepe/ComponentManager.cpp index 85149c8..67c6fc7 100644 --- a/src/crepe/ComponentManager.cpp +++ b/src/crepe/ComponentManager.cpp @@ -1,13 +1,13 @@ -#include "util/log.h" +#include "api/GameObject.h" +#include "util/Log.h"  #include "ComponentManager.h"  using namespace crepe; +using namespace std; -ComponentManager & ComponentManager::get_instance() { -	static ComponentManager instance; -	return instance; -} +ComponentManager::ComponentManager() { dbg_trace(); } +ComponentManager::~ComponentManager() { dbg_trace(); }  void ComponentManager::delete_all_components_of_id(game_object_id_t id) {  	// Loop through all the types (in the unordered_map<>) @@ -21,10 +21,14 @@ void ComponentManager::delete_all_components_of_id(game_object_id_t id) {  }  void ComponentManager::delete_all_components() { -	// Clear the whole unordered_map<>  	this->components.clear(); +	this->next_id = 0;  } -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{*this, this->next_id, name, tag, position, rotation, scale}; +	this->next_id++; +	return object; +} diff --git a/src/crepe/ComponentManager.h b/src/crepe/ComponentManager.h index 9a2aa1d..a14cb46 100644 --- a/src/crepe/ComponentManager.h +++ b/src/crepe/ComponentManager.h @@ -1,15 +1,19 @@  #pragma once -#include <cstdint> +#include <forward_list>  #include <memory>  #include <typeindex>  #include <unordered_map>  #include <vector> +#include "api/Vector2.h" +  #include "Component.h"  namespace crepe { +class GameObject; +  /**   * \brief Manages all components   *  @@ -17,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 +protected:  	/**  	 * \brief Add a component to the ComponentManager  	 *  @@ -43,6 +39,11 @@ public:  	 */  	template <typename T, typename... Args>  	T & add_component(game_object_id_t id, Args &&... args); +	//! GameObject is used as an interface to add components instead of the +	// component manager directly +	friend class GameObject; + +public:  	/**  	 * \brief Delete all components of a specific type and id  	 *  @@ -98,8 +99,11 @@ 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:  	/** @@ -114,6 +118,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 c537b03..be99cac 100644 --- a/src/crepe/ComponentManager.hpp +++ b/src/crepe/ComponentManager.hpp @@ -40,7 +40,6 @@ T & ComponentManager::add_component(game_object_id_t id, Args &&... args) {  	// Check if the vector size is not greater than get_instances_max  	int max_instances = instance->get_instances_max();  	if (max_instances != -1 && components[type][id].size() >= max_instances) { -		// TODO: Exception  		throw std::runtime_error(  			"Exceeded maximum number of instances for this component type");  	} diff --git a/src/crepe/Exception.cpp b/src/crepe/Exception.cpp deleted file mode 100644 index dab8f2e..0000000 --- a/src/crepe/Exception.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include <cstdarg> - -#include "Exception.h" -#include "util/fmt.h" - -using namespace std; -using namespace crepe; - -const char * Exception::what() { return error.c_str(); } - -Exception::Exception(const char * fmt, ...) { -	va_list args; -	va_start(args, fmt); -	this->error = va_stringf(args, fmt); -	va_end(args); -} diff --git a/src/crepe/Exception.h b/src/crepe/Exception.h deleted file mode 100644 index 6473043..0000000 --- a/src/crepe/Exception.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include <exception> -#include <string> - -namespace crepe { - -//! Exception class with printf-style constructor -class Exception : public std::exception { -public: -	//! printf -	Exception(const char * fmt, ...); -	//! Get formatted error message -	const char * what(); - -protected: -	Exception() = default; -	//! Formatted error message -	std::string error; -}; - -} // namespace crepe diff --git a/src/crepe/api/Animator.cpp b/src/crepe/api/Animator.cpp index 58fee2a..cccbc67 100644 --- a/src/crepe/api/Animator.cpp +++ b/src/crepe/api/Animator.cpp @@ -1,7 +1,5 @@ -#include <cstdint> - -#include "util/log.h" +#include "util/Log.h"  #include "Animator.h"  #include "Component.h" @@ -9,7 +7,8 @@  using namespace crepe; -Animator::Animator(uint32_t id, Sprite & ss, int row, int col, int col_animator) +Animator::Animator(game_object_id_t id, Sprite & ss, int row, int col, +				   int col_animator)  	: Component(id),  	  spritesheet(ss),  	  row(row), diff --git a/src/crepe/api/Animator.h b/src/crepe/api/Animator.h index b5bb4c9..53f4b91 100644 --- a/src/crepe/api/Animator.h +++ b/src/crepe/api/Animator.h @@ -1,11 +1,10 @@  #pragma once -#include <cstdint> -  #include "Component.h"  #include "Sprite.h"  namespace crepe { +  class AnimatorSystem;  class SDLContext; diff --git a/src/crepe/api/AssetManager.cpp b/src/crepe/api/AssetManager.cpp index b891760..3925758 100644 --- a/src/crepe/api/AssetManager.cpp +++ b/src/crepe/api/AssetManager.cpp @@ -1,4 +1,4 @@ -#include "util/log.h" +#include "util/Log.h"  #include "AssetManager.h" diff --git a/src/crepe/api/AudioSource.cpp b/src/crepe/api/AudioSource.cpp deleted file mode 100644 index 63fd0d7..0000000 --- a/src/crepe/api/AudioSource.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include <memory> - -#include "../facade/Sound.h" - -#include "AudioSource.h" - -using namespace crepe; - -AudioSource::AudioSource(std::unique_ptr<Asset> audio_clip) { -	this->sound = std::make_unique<crepe::Sound>(std::move(audio_clip)); -} - -void AudioSource::play() { return this->play(false); } - -void AudioSource::play(bool looping) { -	this->sound->set_looping(looping); -	this->sound->play(); -} - -void AudioSource::stop() { -	this->sound->pause(); -	this->sound->rewind(); -} diff --git a/src/crepe/api/AudioSource.h b/src/crepe/api/AudioSource.h deleted file mode 100644 index 1e24ae8..0000000 --- a/src/crepe/api/AudioSource.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include <memory> - -#include "../Asset.h" -#include "../Component.h" - -namespace crepe { - -class Sound; - -//! Audio source component -class AudioSource : public Component { -public: -	AudioSource(std::unique_ptr<Asset> audio_clip); -	virtual ~AudioSource() = default; - -public: -	//! Start or resume this audio source -	void play(); -	void play(bool looping); -	//! Stop this audio source -	void stop(); - -public: -	//! Sample file location -	std::unique_ptr<Asset> audio_clip; -	//! TODO: ????? -	bool play_on_awake; -	//! Repeat the current audio clip during playback -	bool loop; -	//! Normalized volume (0.0 - 1.0) -	float volume; - -private: -	std::unique_ptr<Sound> sound; -}; - -} // namespace crepe diff --git a/src/crepe/api/BehaviorScript.cpp b/src/crepe/api/BehaviorScript.cpp index e69de29..7bbace0 100644 --- a/src/crepe/api/BehaviorScript.cpp +++ b/src/crepe/api/BehaviorScript.cpp @@ -0,0 +1,15 @@ +#include "BehaviorScript.h" +#include "Component.h" +#include "GameObject.h" + +using namespace crepe; + +BehaviorScript::BehaviorScript(game_object_id_t id, ComponentManager & mgr) +	: Component(id), +	  component_manager(mgr) {} + +template <> +BehaviorScript & GameObject::add_component<BehaviorScript>() { +	ComponentManager & mgr = this->component_manager; +	return mgr.add_component<BehaviorScript>(this->id, mgr); +} diff --git a/src/crepe/api/BehaviorScript.h b/src/crepe/api/BehaviorScript.h index 6b1fec7..1a8910d 100644 --- a/src/crepe/api/BehaviorScript.h +++ b/src/crepe/api/BehaviorScript.h @@ -4,29 +4,67 @@  #include "../Component.h" +#include "GameObject.h" +  namespace crepe {  class ScriptSystem;  class ComponentManager;  class Script; +/** + * \brief Script component + * + * This class acts as a (component) wrapper around an instance of (a class + * derivatived from) \c Script. \c BehaviorScript is the only ECS component + * that stores member function implementations as data. + */  class BehaviorScript : public Component {  protected: -	friend class crepe::ComponentManager; -	using Component::Component; +	BehaviorScript(game_object_id_t id, ComponentManager & component_manager); +	//! Only ComponentManager is allowed to instantiate BehaviorScript +	friend class ComponentManager;  public: -	virtual ~BehaviorScript() = default; +	~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; +	//! Script instance  	std::unique_ptr<Script> script = nullptr; +	//! Reference to component manager +	ComponentManager & component_manager; +	//! Script accesses the component manager directly via its parent +	// (BehaviorScript) reference +	friend class Script;  }; +/** + * \brief Add a BehaviorScript component to this game object + * + * The \c BehaviorScript class is the only exception to the ECS harmony, and + * requires a reference to the component manager passed to its constructor in + * order to function normally. This is because the \c BehaviorScript (and \c + * Script) classes are the only component-related classes that store + * implemented member functions as data. + */ +template <> +BehaviorScript & GameObject::add_component<BehaviorScript>(); +  } // namespace crepe  #include "BehaviorScript.hpp" diff --git a/src/crepe/api/BehaviorScript.hpp b/src/crepe/api/BehaviorScript.hpp index 4751607..eec26da 100644 --- a/src/crepe/api/BehaviorScript.hpp +++ b/src/crepe/api/BehaviorScript.hpp @@ -2,7 +2,7 @@  #include <type_traits> -#include "../util/log.h" +#include "../util/Log.h"  #include "BehaviorScript.h"  #include "Script.h" @@ -11,10 +11,11 @@ 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; +	s->component_manager_ref = &this->component_manager;  	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..f9b370f 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -1,7 +1,6 @@  target_sources(crepe PUBLIC  	# AudioSource.cpp  	BehaviorScript.cpp -	Script.cpp  	GameObject.cpp  	Rigidbody.cpp  	ParticleEmitter.cpp diff --git a/src/crepe/api/Camera.cpp b/src/crepe/api/Camera.cpp index d5df196..eb99f7f 100644 --- a/src/crepe/api/Camera.cpp +++ b/src/crepe/api/Camera.cpp @@ -1,7 +1,4 @@ - -#include <cstdint> - -#include "util/log.h" +#include "util/Log.h"  #include "Camera.h"  #include "Color.h" @@ -9,7 +6,7 @@  using namespace crepe; -Camera::Camera(uint32_t id, const Color & bg_color) : Component(id), bg_color(bg_color) { +Camera::Camera(game_object_id_t id, const Color & bg_color) : Component(id), bg_color(bg_color) {  	dbg_trace();  } diff --git a/src/crepe/api/Camera.h b/src/crepe/api/Camera.h index c7f9af5..e0cda34 100644 --- a/src/crepe/api/Camera.h +++ b/src/crepe/api/Camera.h @@ -1,7 +1,5 @@  #pragma once -#include <cstdint> -  #include "Color.h"  #include "Component.h" @@ -22,7 +20,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(game_object_id_t id, const Color & bg_color);  	~Camera(); // dbg_trace only  public: diff --git a/src/crepe/api/Config.h b/src/crepe/api/Config.h index 1cee668..3ab877a 100644 --- a/src/crepe/api/Config.h +++ b/src/crepe/api/Config.h @@ -1,19 +1,24 @@  #pragma once -#include "../util/log.h" +#include "../util/Log.h"  namespace crepe { +/** + * \brief Global configuration interface + * + * This class stores engine default settings. Properties on this class are only supposed to be + * modified *before* execution is handed over from the game programmer to the engine (i.e. the + * main loop is started). + */  class Config { -private: -	Config() = default; - -public: -	~Config() = default; -  public:  	//! Retrieve handle to global Config instance  	static Config & get_instance(); + +private: +	Config() = default; +  	// singleton  	Config(const Config &) = delete;  	Config(Config &&) = delete; @@ -28,7 +33,7 @@ public:  		 *  		 * Only messages with equal or higher priority than this value will be logged.  		 */ -		LogLevel level = LogLevel::INFO; +		Log::Level level = Log::Level::INFO;  		/**  		 * \brief Colored log output  		 * diff --git a/src/crepe/api/GameObject.cpp b/src/crepe/api/GameObject.cpp index d470295..2b836e1 100644 --- a/src/crepe/api/GameObject.cpp +++ b/src/crepe/api/GameObject.cpp @@ -1,30 +1,28 @@  #include "api/Transform.h" +#include "BehaviorScript.h"  #include "GameObject.h"  #include "Metadata.h"  using namespace crepe;  using namespace std; -GameObject::GameObject(game_object_id_t id, const std::string & name, const std::string & tag, -					   const Vector2 & position, double rotation, double scale) -	: id(id) { +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), 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 -		= mgr.get_components_by_id<Metadata>(this->id); +	vector<reference_wrapper<Metadata>> this_metadata = mgr.get_components_by_id<Metadata>(this->id);  	this_metadata.at(0).get().parent = parent.id;  	// Add own id to children list of parent's Metadata component -	vector<reference_wrapper<Metadata>> parent_metadata -		= mgr.get_components_by_id<Metadata>(parent.id); +	vector<reference_wrapper<Metadata>> parent_metadata = mgr.get_components_by_id<Metadata>(parent.id);  	parent_metadata.at(0).get().children.push_back(this->id);  } diff --git a/src/crepe/api/GameObject.h b/src/crepe/api/GameObject.h index 75c164b..cf6765a 100644 --- a/src/crepe/api/GameObject.h +++ b/src/crepe/api/GameObject.h @@ -2,11 +2,12 @@  #include <string> +#include "Vector2.h"  #include "types.h"  namespace crepe { -class Vector2; +class ComponentManager;  /**   * \brief Represents a GameObject @@ -15,11 +16,12 @@ class Vector2;   * the game programmer. The actual implementation is 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 @@ -27,8 +29,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  	 *  @@ -56,6 +61,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/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 2e9823f..f0788ab 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -1,5 +1,9 @@ -  #include "../facade/SDLContext.h" + +#include "../system/AnimatorSystem.h" +#include "../system/CollisionSystem.h" +#include "../system/ParticleSystem.h" +#include "../system/PhysicsSystem.h"  #include "../system/RenderSystem.h"  #include "../system/ScriptSystem.h" @@ -7,11 +11,25 @@  #include "LoopTimer.h"  using namespace crepe; +using namespace std; + +LoopManager::LoopManager() { +	this->load_system<AnimatorSystem>(); +	this->load_system<CollisionSystem>(); +	this->load_system<ParticleSystem>(); +	this->load_system<PhysicsSystem>(); +	this->load_system<RenderSystem>(); +	this->load_system<ScriptSystem>(); +} + +ComponentManager & LoopManager::get_component_manager() { +	return this->component_manager; +} -LoopManager::LoopManager() {}  void LoopManager::process_input() {  	SDLContext::get_instance().handle_events(this->game_running);  } +  void LoopManager::start() {  	this->setup();  	this->loop(); @@ -48,7 +66,7 @@ void LoopManager::setup() {  void LoopManager::render() {  	if (this->game_running) { -		RenderSystem::get_instance().update(); +		this->get_system<RenderSystem>().update();  	}  } diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h index 2f03193..288dca2 100644 --- a/src/crepe/api/LoopManager.h +++ b/src/crepe/api/LoopManager.h @@ -2,15 +2,9 @@  #include <memory> -class RenderSystem; -class SDLContext; -class LoopTimer; -class ScriptSystem; -class SoundSystem; -class ParticleSystem; -class PhysicsSystem; -class AnimatorSystem; -class CollisionSystem; +#include "../ComponentManager.h" +#include "../system/System.h" +  namespace crepe {  class LoopManager { @@ -73,7 +67,21 @@ private:  	void render();  	bool game_running = false; -	//#TODO add system instances + +protected: +	ComponentManager & get_component_manager(); +	template <class T> +	T & get_system(); + +private: +	ComponentManager component_manager{}; +	std::unordered_map<std::type_index, std::unique_ptr<System>> systems; + +private: +	template <class T> +	void load_system();  };  } // namespace crepe + +#include "LoopManager.hpp" diff --git a/src/crepe/api/LoopManager.hpp b/src/crepe/api/LoopManager.hpp new file mode 100644 index 0000000..85a329b --- /dev/null +++ b/src/crepe/api/LoopManager.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include <cassert> +#include <memory> +#include <format> + +#include "../system/System.h" + +#include "LoopManager.h" + +namespace crepe { + +template <class T> +T & LoopManager::get_system() { +	using namespace std; +	static_assert(is_base_of<System, T>::value, +				  "get_system must recieve a derivative class of System"); + +	const type_info & type = typeid(T); +	if (!this->systems.contains(type)) +		throw runtime_error(format("LoopManager: {} is not initialized", type.name())); + +	System * system = this->systems.at(type).get(); +	T * concrete_system = dynamic_cast<T *>(system); +	assert(concrete_system != nullptr); + +	return *concrete_system; +} + +template <class T> +void LoopManager::load_system() { +	using namespace std; +	static_assert(is_base_of<System, T>::value, +				  "load_system must recieve a derivative class of System"); + +	System * system = new T(this->component_manager); +	this->systems[typeid(T)] = unique_ptr<System>(system); +} + +} // namespace crepe diff --git a/src/crepe/api/LoopTimer.cpp b/src/crepe/api/LoopTimer.cpp index 417da47..a9800b7 100644 --- a/src/crepe/api/LoopTimer.cpp +++ b/src/crepe/api/LoopTimer.cpp @@ -1,7 +1,7 @@  #include <chrono>  #include "../facade/SDLContext.h" -#include "../util/log.h" +#include "../util/Log.h"  #include "LoopTimer.h" diff --git a/src/crepe/api/LoopTimer.h b/src/crepe/api/LoopTimer.h index c3c5631..f277d7b 100644 --- a/src/crepe/api/LoopTimer.h +++ b/src/crepe/api/LoopTimer.h @@ -1,7 +1,6 @@  #pragma once  #include <chrono> -#include <cstdint>  namespace crepe { diff --git a/src/crepe/api/Rigidbody.cpp b/src/crepe/api/Rigidbody.cpp index 3bf1c5b..6b87695 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(game_object_id_t id, const Data & data) +	: Component(id),  	  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 c74fea8..3e5c7a3 100644 --- a/src/crepe/api/Rigidbody.h +++ b/src/crepe/api/Rigidbody.h @@ -1,7 +1,5 @@  #pragma once -#include <cstdint> -  #include "../Component.h"  #include "Vector2.h" @@ -82,7 +80,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(game_object_id_t id, const Data & data);  	//! struct to hold data of rigidbody  	Data data; diff --git a/src/crepe/api/SaveManager.cpp b/src/crepe/api/SaveManager.cpp index a71ad83..c5f43ea 100644 --- a/src/crepe/api/SaveManager.cpp +++ b/src/crepe/api/SaveManager.cpp @@ -1,5 +1,5 @@  #include "../facade/DB.h" -#include "../util/log.h" +#include "../util/Log.h"  #include "Config.h"  #include "SaveManager.h" diff --git a/src/crepe/api/Scene.cpp b/src/crepe/api/Scene.cpp index 933edf4..88aa82d 100644 --- a/src/crepe/api/Scene.cpp +++ b/src/crepe/api/Scene.cpp @@ -2,4 +2,6 @@  using namespace crepe; -Scene::Scene(const std::string & name) : name(name) {} +Scene::Scene(ComponentManager & mgr, const std::string & name) +	: component_manager(mgr), +	  name(name) {} diff --git a/src/crepe/api/Scene.h b/src/crepe/api/Scene.h index f8bcc3d..334f306 100644 --- a/src/crepe/api/Scene.h +++ b/src/crepe/api/Scene.h @@ -4,14 +4,20 @@  namespace crepe { +class ComponentManager; +  class Scene {  public: -	Scene(const std::string & name); +	Scene(ComponentManager & mgr, const std::string & name);  	virtual ~Scene() = default; +  	virtual void load_scene() = 0;  public: -	std::string name; +	const std::string name; + +protected: +	ComponentManager & component_manager;  };  } // namespace crepe diff --git a/src/crepe/api/SceneManager.cpp b/src/crepe/api/SceneManager.cpp index c0f8b23..7fb5cb0 100644 --- a/src/crepe/api/SceneManager.cpp +++ b/src/crepe/api/SceneManager.cpp @@ -8,10 +8,7 @@  using namespace crepe;  using namespace std; -SceneManager & SceneManager::get_instance() { -	static SceneManager instance; -	return instance; -} +SceneManager::SceneManager(ComponentManager & mgr) : component_manager(mgr) {}  void SceneManager::set_next_scene(const string & name) { next_scene = name; } @@ -29,7 +26,7 @@ void SceneManager::load_next_scene() {  	unique_ptr<Scene> & scene = *it;  	// Delete all components of the current scene -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	mgr.delete_all_components();  	// Load the new scene diff --git a/src/crepe/api/SceneManager.h b/src/crepe/api/SceneManager.h index 1e0e670..e854794 100644 --- a/src/crepe/api/SceneManager.h +++ b/src/crepe/api/SceneManager.h @@ -8,14 +8,11 @@  namespace crepe { +class ComponentManager; +  class SceneManager {  public: -	// Singleton -	static SceneManager & get_instance(); -	SceneManager(const SceneManager &) = delete; -	SceneManager(SceneManager &&) = delete; -	SceneManager & operator=(const SceneManager &) = delete; -	SceneManager & operator=(SceneManager &&) = delete; +	SceneManager(ComponentManager & mgr);  public:  	/** @@ -38,11 +35,9 @@ public:  	void load_next_scene();  private: -	SceneManager() = default; - -private:  	std::vector<std::unique_ptr<Scene>> scenes;  	std::string next_scene; +	ComponentManager & component_manager;  };  } // namespace crepe diff --git a/src/crepe/api/SceneManager.hpp b/src/crepe/api/SceneManager.hpp index 61c33bf..714f690 100644 --- a/src/crepe/api/SceneManager.hpp +++ b/src/crepe/api/SceneManager.hpp @@ -1,12 +1,16 @@ +#pragma once +  #include "SceneManager.h"  namespace crepe {  template <typename T>  void SceneManager::add_scene(const std::string & name) { -	static_assert(std::is_base_of<Scene, T>::value, "T must be derived from Scene"); +	using namespace std; +	static_assert(is_base_of<Scene, T>::value, "T must be derived from Scene"); -	scenes.emplace_back(make_unique<T>(name)); +	Scene * scene = new T(this->component_manager, name); +	this->scenes.emplace_back(unique_ptr<Scene>(scene));  	// The first scene added, is the one that will be loaded at the beginning  	if (next_scene.empty()) { diff --git a/src/crepe/api/Script.cpp b/src/crepe/api/Script.cpp deleted file mode 100644 index 390cec7..0000000 --- a/src/crepe/api/Script.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "Script.h" - -using namespace crepe; diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h index bf43a49..12ec7f1 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -3,33 +3,78 @@  #include <vector>  namespace crepe { -class ScriptSystem; -} - -namespace crepe { +class ScriptSystem;  class BehaviorScript; +class ComponentManager; +/** + * \brief Script interface + * + * This class is used as a base class for user-defined scripts that can be + * added to game objects using the \c BehaviorScript component. + */  class Script { +	//! ScriptSystem calls \c update()  	friend class crepe::ScriptSystem;  protected: +	/** +	 * \brief Script initialization function +	 * +	 * 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 holding this script instance is active. +	 */  	virtual void init() {} +	/** +	 * \brief Script update function +	 * +	 * This function is called during the ScriptSystem::update() routine if the +	 * \c BehaviorScript component holding this script instance is active. +	 */  	virtual void update() {}  	// NOTE: additional *events* (like unity's OnDisable and OnEnable) should be implemented as  	// member methods in derivative user script classes and registered in init(), otherwise this  	// class will balloon in size with each added event.  protected: +	/** +	 * \brief Get single component of type \c T on this game object (utility) +	 * +	 * \tparam T Type of component +	 * +	 * \returns Reference to component +	 * +	 * \throws nullptr if this game object does not have a component matching +	 * type \c T +	 */  	template <typename T> -	T & get_component(); +	T & get_component() const; +	/** +	 * \brief Get all components of type \c T on this game object (utility) +	 * +	 * \tparam T Type of component +	 * +	 * \returns List of component references +	 */  	template <typename T> -	std::vector<std::reference_wrapper<T>> get_components(); +	std::vector<std::reference_wrapper<T>> get_components() const; + +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;  private: -	friend class crepe::BehaviorScript; -	BehaviorScript * parent = nullptr; +	// These references are set by BehaviorScript immediately after calling the +	// constructor of Script. +	BehaviorScript * parent_ref = nullptr; +	ComponentManager * component_manager_ref = nullptr;  };  } // namespace crepe diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp index ce39331..13b8077 100644 --- a/src/crepe/api/Script.hpp +++ b/src/crepe/api/Script.hpp @@ -8,17 +8,21 @@  namespace crepe {  template <typename T> -T & Script::get_component() { -	std::vector<std::reference_wrapper<T>> all_components = this->get_components<T>(); -	if (all_components.size() < 1) throw nullptr; // TODO +T & Script::get_component() const { +	using namespace std; +	vector<reference_wrapper<T>> all_components = this->get_components<T>(); +	if (all_components.size() < 1) +		throw runtime_error(format("Script: no component found with type = {}", typeid(T).name()));  	return all_components.back().get();  }  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); +std::vector<std::reference_wrapper<T>> Script::get_components() const { +	auto & parent = *this->parent_ref; +	auto & mgr = *this->component_manager_ref; + +	return mgr.get_components_by_id<T>(parent.game_object_id);  }  } // namespace crepe diff --git a/src/crepe/api/Sprite.cpp b/src/crepe/api/Sprite.cpp index c4cd29e..bd2d5cf 100644 --- a/src/crepe/api/Sprite.cpp +++ b/src/crepe/api/Sprite.cpp @@ -1,6 +1,6 @@  #include <memory> -#include "../util/log.h" +#include "../util/Log.h"  #include "facade/SDLContext.h"  #include "Component.h" diff --git a/src/crepe/api/Sprite.h b/src/crepe/api/Sprite.h index 50ea88e..0192793 100644 --- a/src/crepe/api/Sprite.h +++ b/src/crepe/api/Sprite.h @@ -1,6 +1,5 @@  #pragma once -#include <cstdint>  #include <memory>  #include "Color.h" diff --git a/src/crepe/api/Texture.cpp b/src/crepe/api/Texture.cpp index 5ebd23d..de0d0ea 100644 --- a/src/crepe/api/Texture.cpp +++ b/src/crepe/api/Texture.cpp @@ -1,7 +1,7 @@  #include <SDL2/SDL_render.h>  #include "../facade/SDLContext.h" -#include "../util/log.h" +#include "../util/Log.h"  #include "Asset.h"  #include "Texture.h" @@ -26,7 +26,7 @@ Texture::~Texture() {  void Texture::load(unique_ptr<Asset> res) {  	SDLContext & ctx = SDLContext::get_instance(); -	this->texture = std::move(ctx.texture_from_path(res->canonical())); +	this->texture = std::move(ctx.texture_from_path(res->get_canonical()));  }  int Texture::get_width() const { diff --git a/src/crepe/api/Transform.cpp b/src/crepe/api/Transform.cpp index 8eeec41..cd944bd 100644 --- a/src/crepe/api/Transform.cpp +++ b/src/crepe/api/Transform.cpp @@ -1,4 +1,4 @@ -#include "util/log.h" +#include "../util/Log.h"  #include "Transform.h" diff --git a/src/crepe/api/Transform.h b/src/crepe/api/Transform.h index 51b0daa..18aa293 100644 --- a/src/crepe/api/Transform.h +++ b/src/crepe/api/Transform.h @@ -14,6 +14,14 @@ namespace crepe {   */  class Transform : public Component {  public: +	//! Translation (shift) +	Vector2 position = {0, 0}; +	//! Rotation, in degrees +	double rotation = 0; +	//! Multiplication factor +	double scale = 0; + +protected:  	/**  	 * \param id The id of the GameObject this component belongs to  	 * \param point The position of the GameObject @@ -22,19 +30,12 @@ public:  	 */  	Transform(game_object_id_t id, const Vector2 & point, double rotation, double scale);  	/** -	 * \brief Get the maximum number of instances for this component -	 * -	 * \return The maximum number of instances for this component +	 * There is always exactly one transform component per entity +	 * \return 1  	 */  	virtual int get_instances_max() const { return 1; } - -public: -	//! Translation (shift) -	Vector2 position; -	//! Rotation, in degrees -	double rotation; -	//! Multiplication factor -	double scale; +	//! ComponentManager instantiates all components +	friend class ComponentManager;  };  } // namespace crepe diff --git a/src/crepe/api/Vector2.cpp b/src/crepe/api/Vector2.cpp index 437d1d8..97b74ac 100644 --- a/src/crepe/api/Vector2.cpp +++ b/src/crepe/api/Vector2.cpp @@ -1,47 +1,43 @@  #include "Vector2.h" -namespace crepe { +using namespace crepe; -// Constructor with initial values -Vector2::Vector2(double x, double y) : x(x), y(y) {} - -// Subtracts another vector from this vector and returns the result. -Vector2 Vector2::operator-(const Vector2 & other) const { return {x - other.x, y - other.y}; } +Vector2 Vector2::operator-(const Vector2 & other) const { +	return {x - other.x, y - other.y}; +} -// Adds another vector to this vector and returns the result. -Vector2 Vector2::operator+(const Vector2 & other) const { return {x + other.x, y + other.y}; } +Vector2 Vector2::operator+(const Vector2 & other) const { +	return {x + other.x, y + other.y}; +} -// Multiplies this vector by a scalar and returns the result. -Vector2 Vector2::operator*(double scalar) const { return {x * scalar, y * scalar}; } +Vector2 Vector2::operator*(double scalar) const { +	return {x * scalar, y * scalar}; +} -// Multiplies this vector by another vector element-wise and updates this vector.  Vector2 & Vector2::operator*=(const Vector2 & other) {  	x *= other.x;  	y *= other.y;  	return *this;  } -// Adds another vector to this vector and updates this vector.  Vector2 & Vector2::operator+=(const Vector2 & other) {  	x += other.x;  	y += other.y;  	return *this;  } -// Adds a scalar value to both components of this vector and updates this vector.  Vector2 & Vector2::operator+=(double other) {  	x += other;  	y += other;  	return *this;  } -// Returns the negation of this vector.  Vector2 Vector2::operator-() const { return {-x, -y}; } -// Checks if this vector is equal to another vector. -bool Vector2::operator==(const Vector2 & other) const { return x == other.x && y == other.y; } - -// Checks if this vector is not equal to another vector. -bool Vector2::operator!=(const Vector2 & other) const { return !(*this == other); } +bool Vector2::operator==(const Vector2 & other) const { +	return x == other.x && y == other.y; +} -} // namespace crepe +bool Vector2::operator!=(const Vector2 & other) const { +	return !(*this == other); +} diff --git a/src/crepe/api/Vector2.h b/src/crepe/api/Vector2.h index 5a57484..2fb6136 100644 --- a/src/crepe/api/Vector2.h +++ b/src/crepe/api/Vector2.h @@ -2,19 +2,12 @@  namespace crepe { -//! Vector2 class -class Vector2 { -public: +//! 2D vector +struct Vector2 {  	//! X component of the vector -	double x; +	double x = 0;  	//! Y component of the vector -	double y; - -	//! Default constructor -	Vector2() = default; - -	//! Constructor with initial values -	Vector2(double x, double y); +	double y = 0;  	//! Subtracts another vector from this vector and returns the result.  	Vector2 operator-(const Vector2 & other) const; diff --git a/src/crepe/facade/DB.cpp b/src/crepe/facade/DB.cpp index bf877b5..00acf04 100644 --- a/src/crepe/facade/DB.cpp +++ b/src/crepe/facade/DB.cpp @@ -1,7 +1,6 @@  #include <cstring> -#include "Exception.h" -#include "util/log.h" +#include "util/Log.h"  #include "DB.h" @@ -15,19 +14,17 @@ DB::DB(const string & path) {  	// init database struct  	libdb::DB * db;  	if ((ret = libdb::db_create(&db, NULL, 0)) != 0) -		throw Exception("db_create: %s", libdb::db_strerror(ret)); +		throw runtime_error(format("db_create: {}", libdb::db_strerror(ret)));  	this->db = {db, [](libdb::DB * db) { db->close(db, 0); }};  	// load or create database file -	if ((ret = this->db->open(this->db.get(), NULL, path.c_str(), NULL, libdb::DB_BTREE, -							  DB_CREATE, 0)) -		!= 0) -		throw Exception("db->open: %s", libdb::db_strerror(ret)); +	ret = this->db->open(this->db.get(), NULL, path.c_str(), NULL, libdb::DB_BTREE, DB_CREATE, 0); +	if (ret != 0) throw runtime_error(format("db->open: {}", libdb::db_strerror(ret)));  	// create cursor  	libdb::DBC * cursor; -	if ((ret = this->db->cursor(this->db.get(), NULL, &cursor, 0)) != 0) -		throw Exception("db->cursor: %s", libdb::db_strerror(ret)); +	ret = this->db->cursor(this->db.get(), NULL, &cursor, 0); +	if (ret != 0) throw runtime_error(format("db->cursor: {}", libdb::db_strerror(ret)));  	this->cursor = {cursor, [](libdb::DBC * cursor) { cursor->close(cursor); }};  } @@ -45,21 +42,28 @@ string DB::get(const string & key) {  	memset(&db_val, 0, sizeof(libdb::DBT));  	int ret = this->cursor->get(this->cursor.get(), &db_key, &db_val, DB_FIRST); -	if (ret != 0) throw Exception("cursor->get: %s", libdb::db_strerror(ret)); -	return {static_cast<char *>(db_val.data), db_val.size}; +	if (ret == 0) +		return {static_cast<char *>(db_val.data), db_val.size}; + +	string err = format("cursor->get: {}", libdb::db_strerror(ret)); +	if (ret == DB_NOTFOUND) +		throw out_of_range(err); +	else +		throw runtime_error(err);  }  void DB::set(const string & key, const string & value) {  	libdb::DBT db_key = this->to_thing(key);  	libdb::DBT db_val = this->to_thing(value);  	int ret = this->db->put(this->db.get(), NULL, &db_key, &db_val, 0); -	if (ret != 0) throw Exception("cursor->get: %s", libdb::db_strerror(ret)); +	if (ret != 0) +		throw runtime_error(format("cursor->get: {}", libdb::db_strerror(ret)));  } -bool DB::has(const std::string & key) noexcept { +bool DB::has(const std::string & key) {  	try {  		this->get(key); -	} catch (...) { +	} catch (std::out_of_range &) {  		return false;  	}  	return true; diff --git a/src/crepe/facade/DB.h b/src/crepe/facade/DB.h index 5f8d939..629b0eb 100644 --- a/src/crepe/facade/DB.h +++ b/src/crepe/facade/DB.h @@ -34,7 +34,8 @@ public:  	 *  	 * \return The value  	 * -	 * \throws Exception if value is not found in DB or other error occurs +	 * \throws std::out_of_range if value is not found in DB +	 * \throws std::runtime_error if other error occurs  	 */  	std::string get(const std::string & key);  	/** @@ -43,7 +44,7 @@ public:  	 * \param key  The value key  	 * \param value  The value to store  	 * -	 * \throws Exception if an error occurs +	 * \throws std::runtime_error if an error occurs  	 */  	void set(const std::string & key, const std::string & value);  	/** @@ -53,7 +54,7 @@ public:  	 *  	 * \returns True if the key exists, or false if it does not  	 */ -	bool has(const std::string & key) noexcept; +	bool has(const std::string & key);  private:  	//! RAII wrapper around \c DB struct diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index e72b622..83e91f8 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -10,17 +10,16 @@  #include <iostream>  #include <memory>  #include <string> -#include <utility>  #include "../api/Sprite.h"  #include "../api/Texture.h"  #include "../api/Transform.h" -#include "../util/log.h" -#include "Exception.h" +#include "../util/Log.h"  #include "SDLContext.h"  using namespace crepe; +using namespace std;  SDLContext & SDLContext::get_instance() {  	static SDLContext instance; @@ -160,7 +159,7 @@ SDLContext::texture_from_path(const std::string & path) {  		= SDL_CreateTextureFromSurface(this->game_renderer.get(), img_surface.get());  	if (tmp_texture == nullptr) { -		throw Exception("Texture cannot be load from %s", path.c_str()); +		throw runtime_error(format("Texture cannot be load from {}", path));  	}  	std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>> img_texture; diff --git a/src/crepe/facade/Sound.cpp b/src/crepe/facade/Sound.cpp index a1aef17..a65b052 100644 --- a/src/crepe/facade/Sound.cpp +++ b/src/crepe/facade/Sound.cpp @@ -1,21 +1,24 @@ -#include "../util/log.h" +#include "../util/Log.h"  #include "Sound.h"  #include "SoundContext.h"  using namespace crepe; +using namespace std; -Sound::Sound(std::unique_ptr<Asset> res) { +Sound::Sound(unique_ptr<Asset> res) {  	dbg_trace();  	this->load(std::move(res));  }  Sound::Sound(const char * src) {  	dbg_trace(); -	this->load(std::make_unique<Asset>(src)); +	this->load(make_unique<Asset>(src));  } -void Sound::load(std::unique_ptr<Asset> res) { this->sample.load(res->canonical()); } +void Sound::load(unique_ptr<Asset> res) { +	this->sample.load(res->get_canonical().c_str()); +}  void Sound::play() {  	SoundContext & ctx = SoundContext::get_instance(); diff --git a/src/crepe/facade/Sound.h b/src/crepe/facade/Sound.h index adf1fef..32b6478 100644 --- a/src/crepe/facade/Sound.h +++ b/src/crepe/facade/Sound.h @@ -8,6 +8,12 @@  namespace crepe { +/** + * \brief Sound resource facade + * + * This class is a wrapper around a \c SoLoud::Wav instance, which holds a + * single sample. It is part of the sound facade. + */  class Sound {  public:  	/** diff --git a/src/crepe/facade/SoundContext.cpp b/src/crepe/facade/SoundContext.cpp index 5e5a3a9..deb2b62 100644 --- a/src/crepe/facade/SoundContext.cpp +++ b/src/crepe/facade/SoundContext.cpp @@ -1,4 +1,4 @@ -#include "../util/log.h" +#include "../util/Log.h"  #include "SoundContext.h" diff --git a/src/crepe/facade/SoundContext.h b/src/crepe/facade/SoundContext.h index d3123d2..d703c16 100644 --- a/src/crepe/facade/SoundContext.h +++ b/src/crepe/facade/SoundContext.h @@ -6,19 +6,24 @@  namespace crepe { +/** + * \brief Sound engine facade + * + * This class is a wrapper around a \c SoLoud::Soloud instance, which provides + * the methods for playing \c Sound instances. It is part of the sound facade. + */  class SoundContext {  private: +	// singleton  	SoundContext();  	virtual ~SoundContext(); - -	// singleton -	static SoundContext & get_instance();  	SoundContext(const SoundContext &) = delete;  	SoundContext(SoundContext &&) = delete;  	SoundContext & operator=(const SoundContext &) = delete;  	SoundContext & operator=(SoundContext &&) = delete;  private: +	static SoundContext & get_instance();  	SoLoud::Soloud engine;  	friend class Sound;  }; diff --git a/src/crepe/system/AnimatorSystem.cpp b/src/crepe/system/AnimatorSystem.cpp index bf45362..9d18873 100644 --- a/src/crepe/system/AnimatorSystem.cpp +++ b/src/crepe/system/AnimatorSystem.cpp @@ -1,27 +1,17 @@ -  #include <cstdint>  #include <functional>  #include <vector>  #include "api/Animator.h"  #include "facade/SDLContext.h" -#include "util/log.h"  #include "AnimatorSystem.h"  #include "ComponentManager.h"  using namespace crepe; -AnimatorSystem::AnimatorSystem() { dbg_trace(); } -AnimatorSystem::~AnimatorSystem() { dbg_trace(); } - -AnimatorSystem & AnimatorSystem::get_instance() { -	static AnimatorSystem instance; -	return instance; -} -  void AnimatorSystem::update() { -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	std::vector<std::reference_wrapper<Animator>> animations  		= mgr.get_components_by_type<Animator>(); diff --git a/src/crepe/system/AnimatorSystem.h b/src/crepe/system/AnimatorSystem.h index 29204d3..56cc7b3 100644 --- a/src/crepe/system/AnimatorSystem.h +++ b/src/crepe/system/AnimatorSystem.h @@ -17,16 +17,7 @@ namespace crepe {  class AnimatorSystem : public System {  public: -	/** -	 * \brief Retrieves the singleton instance of the AnimatorSystem. -	 * -	 * \return A reference to the single instance of the AnimatorSystem. -	 * -	 * This method ensures that there is only one instance of the AnimatorSystem, following the -	 * singleton design pattern. It can be used to access the system globally. -	 */ -	static AnimatorSystem & get_instance(); - +	using System::System;  	/**  	 * \brief Updates the Animator components.  	 * @@ -35,11 +26,7 @@ public:  	 * looping).  	 */  	void update() override; - -private: -	// private because singleton -	AnimatorSystem(); // dbg_trace -	~AnimatorSystem(); // dbg_trace +	// FIXME: never say "likely" in the documentation lmao  };  } // namespace crepe diff --git a/src/crepe/system/CMakeLists.txt b/src/crepe/system/CMakeLists.txt index 4c18b87..d658b25 100644 --- a/src/crepe/system/CMakeLists.txt +++ b/src/crepe/system/CMakeLists.txt @@ -1,4 +1,5 @@  target_sources(crepe PUBLIC +	System.cpp  	ParticleSystem.cpp  	ScriptSystem.cpp  	PhysicsSystem.cpp diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp index 55e0fdc..c74ca1d 100644 --- a/src/crepe/system/CollisionSystem.cpp +++ b/src/crepe/system/CollisionSystem.cpp @@ -2,6 +2,4 @@  using namespace crepe; -CollisionSystem::CollisionSystem() {} -  void CollisionSystem::update() {} diff --git a/src/crepe/system/CollisionSystem.h b/src/crepe/system/CollisionSystem.h index 1e9f1aa..c1a70d8 100644 --- a/src/crepe/system/CollisionSystem.h +++ b/src/crepe/system/CollisionSystem.h @@ -1,11 +1,13 @@  #pragma once +#include "System.h" +  namespace crepe { -class CollisionSystem { +class CollisionSystem : public System {  public: -	CollisionSystem(); -	void update(); +	using System::System; +	void update() override;  };  } // namespace crepe diff --git a/src/crepe/system/ParticleSystem.cpp b/src/crepe/system/ParticleSystem.cpp index 92e7d3f..7316309 100644 --- a/src/crepe/system/ParticleSystem.cpp +++ b/src/crepe/system/ParticleSystem.cpp @@ -13,7 +13,7 @@ using namespace crepe;  void ParticleSystem::update() {  	// Get all emitters -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	std::vector<std::reference_wrapper<ParticleEmitter>> emitters  		= mgr.get_components_by_type<ParticleEmitter>(); diff --git a/src/crepe/system/ParticleSystem.h b/src/crepe/system/ParticleSystem.h index 843261e..0a2dde1 100644 --- a/src/crepe/system/ParticleSystem.h +++ b/src/crepe/system/ParticleSystem.h @@ -4,6 +4,8 @@  #include "System.h" +#include "System.h" +  namespace crepe {  class ParticleEmitter; @@ -15,6 +17,7 @@ class Transform;   */  class ParticleSystem : public System {  public: +	using System::System;  	/**  	 * \brief Updates all particle emitters by emitting particles, updating particle states, and  	 * checking bounds. @@ -68,7 +71,8 @@ private:  	double generate_random_speed(double min_speed, double max_speed) const;  private: -	//! Counter to count updates to determine how many times emit_particle is called. +	//! Counter to count updates to determine how many times emit_particle is +	// called.  	unsigned int update_count = 0;  	//! Determines the lowest amount of emission rate (1000 = 0.001 = 1 particle per 1000  	// updates). diff --git a/src/crepe/system/PhysicsSystem.cpp b/src/crepe/system/PhysicsSystem.cpp index 402dfab..4a7dbfb 100644 --- a/src/crepe/system/PhysicsSystem.cpp +++ b/src/crepe/system/PhysicsSystem.cpp @@ -11,7 +11,7 @@  using namespace crepe;  void PhysicsSystem::update() { -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	std::vector<std::reference_wrapper<Rigidbody>> rigidbodies  		= mgr.get_components_by_type<Rigidbody>();  	std::vector<std::reference_wrapper<Transform>> transforms diff --git a/src/crepe/system/PhysicsSystem.h b/src/crepe/system/PhysicsSystem.h index b635693..227ab69 100644 --- a/src/crepe/system/PhysicsSystem.h +++ b/src/crepe/system/PhysicsSystem.h @@ -3,6 +3,7 @@  #include "System.h"  namespace crepe { +  /**   * \brief System that controls all physics   *  @@ -11,6 +12,7 @@ namespace crepe {   */  class PhysicsSystem : public System {  public: +	using System::System;  	/**  	 * \brief updates the physics system.  	 *  diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index a488370..19493f7 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -5,26 +5,19 @@  #include "../api/Sprite.h"  #include "../api/Transform.h"  #include "../facade/SDLContext.h" -#include "../util/log.h" +#include "../util/Log.h"  #include "RenderSystem.h"  using namespace crepe; -RenderSystem::RenderSystem() { dbg_trace(); } - -RenderSystem::~RenderSystem() { dbg_trace(); } - -RenderSystem & RenderSystem::get_instance() { -	static RenderSystem instance; -	return instance; +void RenderSystem::clear_screen() const { +	SDLContext::get_instance().clear_screen();  } -void RenderSystem::clear_screen() const { SDLContext::get_instance().clear_screen(); } -  void RenderSystem::present_screen() const { SDLContext::get_instance().present_screen(); }  void RenderSystem::update_camera() { -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	std::vector<std::reference_wrapper<Camera>> cameras = mgr.get_components_by_type<Camera>(); @@ -34,8 +27,7 @@ void RenderSystem::update_camera() {  	}  }  void RenderSystem::render_sprites() const { - -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	std::vector<std::reference_wrapper<Sprite>> sprites = mgr.get_components_by_type<Sprite>(); diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index b9bf94b..87ec494 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -15,14 +15,8 @@ namespace crepe {   * services for the application.   */  class RenderSystem : public System { -  public: -	/** -	 * \brief Gets the singleton instance of RenderSystem. -	 * \return Reference to the RenderSystem instance. -	 */ -	static RenderSystem & get_instance(); - +	using System::System;  	/**  	 * \brief Updates the RenderSystem for the current frame.  	 * This method is called to perform all rendering operations for the current game frame. @@ -30,10 +24,6 @@ public:  	void update() override;  private: -	// Private constructor to enforce singleton pattern. -	RenderSystem(); -	~RenderSystem(); -  	//! Clears the screen in preparation for rendering.  	void clear_screen() const; @@ -61,4 +51,5 @@ private:  	Camera * curr_cam = nullptr;  	// TODO: needs a better solution  }; +  } // namespace crepe diff --git a/src/crepe/system/ScriptSystem.cpp b/src/crepe/system/ScriptSystem.cpp index f2673e7..f4a826b 100644 --- a/src/crepe/system/ScriptSystem.cpp +++ b/src/crepe/system/ScriptSystem.cpp @@ -5,7 +5,6 @@  #include "../ComponentManager.h"  #include "../api/BehaviorScript.h"  #include "../api/Script.h" -#include "../util/log.h"  #include "ScriptSystem.h" @@ -13,16 +12,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() const { +	forward_list<reference_wrapper<Script>> scripts = {}; +	ComponentManager & mgr = this->component_manager;  	vector<reference_wrapper<BehaviorScript>> behavior_scripts  		= mgr.get_components_by_type<BehaviorScript>(); @@ -31,7 +38,7 @@ 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..deb89cb 100644 --- a/src/crepe/system/ScriptSystem.h +++ b/src/crepe/system/ScriptSystem.h @@ -8,13 +8,32 @@ namespace crepe {  class Script; +/** + * \brief Script system + *  + * The script system is responsible for all \c BehaviorScript components, and + * calls the methods on classes derived from \c Script. + */  class ScriptSystem : public System {  public: -	void update(); +	using System::System; +	/** +	 * \brief Call Script::update() on all active \c BehaviorScript instances +	 * +	 * This routine updates all scripts sequentially using the Script::update() +	 * method. It also calls Script::init() if this has not been done before on +	 * the \c BehaviorScript instance. +	 */ +	void update() override;  private: -	// TODO: to forward_list<reference_wrapper> -	std::forward_list<Script *> get_scripts(); +	/** +	 * \brief Aggregate all active \c BehaviorScript components and return a list +	 * of references to their \c Script instances (utility) +	 * +	 * \returns List of active \c Script instances +	 */ +	std::forward_list<std::reference_wrapper<Script>> get_scripts() const;  };  } // namespace crepe diff --git a/src/crepe/system/System.cpp b/src/crepe/system/System.cpp new file mode 100644 index 0000000..937a423 --- /dev/null +++ b/src/crepe/system/System.cpp @@ -0,0 +1,7 @@ +#include "../util/Log.h" + +#include "System.h" + +using namespace crepe; + +System::System(ComponentManager & mgr) : component_manager(mgr) { dbg_trace(); } diff --git a/src/crepe/system/System.h b/src/crepe/system/System.h index 3b81bef..28ea20e 100644 --- a/src/crepe/system/System.h +++ b/src/crepe/system/System.h @@ -2,13 +2,28 @@  namespace crepe { +class ComponentManager; + +/** + * \brief Base ECS system class + * + * This class is used as the base for all system classes. Classes derived from + * System must implement the System::update() method and copy Script::Script + * with the `using`-syntax. + */  class System {  public: +	/** +	 * \brief Process all components this system is responsible for. +	 */  	virtual void update() = 0;  public: -	System() = default; +	System(ComponentManager &);  	virtual ~System() = default; + +protected: +	ComponentManager & component_manager;  };  } // namespace crepe diff --git a/src/crepe/util/CMakeLists.txt b/src/crepe/util/CMakeLists.txt index 0fa4343..4be738a 100644 --- a/src/crepe/util/CMakeLists.txt +++ b/src/crepe/util/CMakeLists.txt @@ -1,13 +1,12 @@  target_sources(crepe PUBLIC  	LogColor.cpp -	log.cpp -	fmt.cpp +	Log.cpp  )  target_sources(crepe PUBLIC FILE_SET HEADERS FILES  	LogColor.h -	log.h -	fmt.h +	Log.h +	Log.hpp  	Proxy.h  	Proxy.hpp  ) diff --git a/src/crepe/util/Log.cpp b/src/crepe/util/Log.cpp new file mode 100644 index 0000000..84d80a8 --- /dev/null +++ b/src/crepe/util/Log.cpp @@ -0,0 +1,37 @@ +#include <iostream> +#include <string> + +#include "../api/Config.h" + +#include "Log.h" + +using namespace crepe; +using namespace std; + +string Log::prefix(const Level & level) { +	switch (level) { +		case Level::TRACE: +			return LogColor().fg_white().str("[TRACE]") + " "; +		case Level::DEBUG: +			return LogColor().fg_magenta().str("[DEBUG]") + " "; +		case Level::INFO: +			return LogColor().fg_blue().str("[INFO]") + " "; +		case Level::WARNING: +			return LogColor().fg_yellow().str("[WARN]") + " "; +		case Level::ERROR: +			return LogColor().fg_red().str("[ERROR]") + " "; +	} +	return ""; +} + +void Log::log(const Level & level, const string & msg) { +	auto & cfg = Config::get_instance(); +	if (level < cfg.log.level) return; + +	string out = Log::prefix(level) + msg; +	if (!out.ends_with("\n")) out += "\n"; + +	// TODO: also log to file or smth +	cout.write(out.data(), out.size()); +	cout.flush(); +} diff --git a/src/crepe/util/Log.h b/src/crepe/util/Log.h new file mode 100644 index 0000000..e0844ca --- /dev/null +++ b/src/crepe/util/Log.h @@ -0,0 +1,87 @@ +#pragma once + +#include <format> + +// allow user to disable debug macros +#ifndef CREPE_DISABLE_MACROS + +#include "LogColor.h" + +// utility macros +#define _crepe_logf_here(level, fmt, ...) \ +	crepe::Log::logf( \ +		level, "{}" fmt, \ +		crepe::LogColor().fg_white(false).str(std::format( \ +			"{} ({}:{})", __PRETTY_FUNCTION__, __FILE_NAME__, __LINE__)), \ +		__VA_ARGS__) + +// very illegal global function-style macros +// NOLINTBEGIN +#define dbg_logf(fmt, ...) \ +	_crepe_logf_here(crepe::Log::Level::DEBUG, ": " fmt, __VA_ARGS__) +#define dbg_log(str) _crepe_logf_here(crepe::Log::Level::DEBUG, ": {}", str) +#define dbg_trace() _crepe_logf_here(crepe::Log::Level::TRACE, "", "") +// NOLINTEND + +#endif + +namespace crepe { + +/** + * \brief Logging utility + * + * This class is used to output log messages to the console and/or log files. + */ +class Log { +public: +	//! Log message severity +	enum Level { +		TRACE, //< Include (internal) function calls +		DEBUG, //< Include dbg_logf output +		INFO, //< General-purpose messages +		WARNING, //< Non-fatal errors +		ERROR, //< Fatal errors +	}; + +	/** +	 * \brief Log a formatted message +	 * +	 * \param level Message severity +	 * \param msg Formatted message +	 */ +	static void log(const Level & level, const std::string & msg); + +	/** +	 * \brief Format a message and log it +	 * +	 * \param level Message severity +	 * \param fmt Message format +	 * \param args Format arguments +	 */ +	template <class... Args> +	static void logf(const Level & level, std::format_string<Args...> fmt, +					 Args &&... args); + +	/** +	 * \brief Format a message and log it (with default severity \c INFO) +	 * +	 * \param fmt Message format +	 * \param args Format arguments +	 */ +	template <class... Args> +	static void logf(std::format_string<Args...> fmt, Args &&... args); + +private: +	/** +	 * \brief Output a message prefix depending on the log level +	 * +	 * \param level Message severity +	 * +	 * \return Colored message severity prefix string +	 */ +	static std::string prefix(const Level & level); +}; + +} // namespace crepe + +#include "Log.hpp" diff --git a/src/crepe/util/Log.hpp b/src/crepe/util/Log.hpp new file mode 100644 index 0000000..651f076 --- /dev/null +++ b/src/crepe/util/Log.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "Log.h" + +namespace crepe { + +template <class... Args> +void Log::logf(std::format_string<Args...> fmt, Args &&... args) { +	Log::logf(Level::INFO, fmt, std::forward<Args>(args)...); +} + +template <class... Args> +void Log::logf(const Level & level, std::format_string<Args...> fmt, +			   Args &&... args) { +	Log::log(level, std::format(fmt, std::forward<Args>(args)...)); +} + +} // namespace crepe diff --git a/src/crepe/util/LogColor.cpp b/src/crepe/util/LogColor.cpp index c0c45a0..5411898 100644 --- a/src/crepe/util/LogColor.cpp +++ b/src/crepe/util/LogColor.cpp @@ -1,16 +1,15 @@  #include <cstdarg>  #include "../api/Config.h" -#include "LogColor.h" -#include "fmt.h" +#include "LogColor.h"  using namespace crepe;  using namespace std;  static constexpr const char * RESET_CODE = "\e[0m"; -const string LogColor::str(const string & content) { +const string LogColor::str(const string & content) const {  	auto & cfg = Config::get_instance();  	string out = content;  	if (cfg.log.color) out = this->code + out; @@ -19,21 +18,8 @@ const string LogColor::str(const string & content) {  	return out;  } -const char * LogColor::c_str(const char * content) { -	this->final = this->str(content == NULL ? "" : content); -	return this->final.c_str(); -} - -const char * LogColor::fmt(const char * fmt, ...) { -	va_list args; -	va_start(args, fmt); -	string content = va_stringf(args, fmt); -	va_end(args); -	return this->c_str(content.c_str()); -} -  LogColor & LogColor::add_code(unsigned int code) { -	this->code += stringf("\e[%dm", code); +	this->code += format("\e[{}m", code);  	return *this;  } diff --git a/src/crepe/util/LogColor.h b/src/crepe/util/LogColor.h index c1170cb..132fb94 100644 --- a/src/crepe/util/LogColor.h +++ b/src/crepe/util/LogColor.h @@ -4,23 +4,35 @@  namespace crepe { +/** + * \brief Utility class for coloring text using ANSI escape codes + * + * \note Most methods in this class return a reference to \c this, which may be + * used to chain multiple display attributes. + */  class LogColor {  public: -	LogColor() = default; +	/** +	 * \brief Get color code as STL string +	 * +	 * \param content If given, color this string and append a color reset escape sequence. +	 * +	 * \returns Color escape sequence +	 */ +	const std::string str(const std::string & content = "") const;  public: -	//! get color code as c-style string (or color content string) -	const char * c_str(const char * content = NULL); -	//! color printf-style format string -	const char * fmt(const char * fmt, ...); -	//! get color code as stl string (or color content string) -	const std::string str(const std::string & content = ""); - -public: -	//! reset color to default foreground and background color +	//! Reset color to default foreground and background color  	LogColor & reset();  public: +	/** +	 * \name Foreground colors +	 * +	 * These functions set the foreground (text) color. The \c bright parameter +	 * makes the color brighter, or bold on some terminals. +	 * \{ +	 */  	LogColor & fg_black(bool bright = false);  	LogColor & fg_red(bool bright = false);  	LogColor & fg_green(bool bright = false); @@ -29,8 +41,16 @@ public:  	LogColor & fg_magenta(bool bright = false);  	LogColor & fg_cyan(bool bright = false);  	LogColor & fg_white(bool bright = false); +	/// \}  public: +	/** +	 * \name Background colors +	 * +	 * These functions set the background color. The \c bright parameter makes +	 * the color brighter. +	 * \{ +	 */  	LogColor & bg_black(bool bright = false);  	LogColor & bg_red(bool bright = false);  	LogColor & bg_green(bool bright = false); @@ -39,13 +59,22 @@ public:  	LogColor & bg_magenta(bool bright = false);  	LogColor & bg_cyan(bool bright = false);  	LogColor & bg_white(bool bright = false); +	/// \}  private: +	/** +	 * \brief Append SGR escape sequence to \c this->code +	 * +	 * \param code SGR attribute number +	 * +	 * See <https://en.wikipedia.org/wiki/ANSI_escape_code> for magic number +	 * reference. +	 */  	LogColor & add_code(unsigned int code);  private: +	//! Color escape sequence  	std::string code = ""; -	std::string final = "";  };  } // namespace crepe diff --git a/src/crepe/util/fmt.cpp b/src/crepe/util/fmt.cpp deleted file mode 100644 index 4b50da8..0000000 --- a/src/crepe/util/fmt.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include <cstdarg> -#include <cstdio> -#include <string> - -#include "fmt.h" - -using namespace std; - -string crepe::va_stringf(va_list args, const char * fmt) { -	string out; - -	va_list args_copy; -	va_copy(args_copy, args); -	size_t length = vsnprintf(NULL, 0, fmt, args_copy); -	// resize to include terminating null byte -	out.resize(length + 1); -	va_end(args_copy); - -	// vsnprintf adds terminating null byte -	vsnprintf(out.data(), out.size(), fmt, args); -	// resize to actual length -	out.resize(length); - -	va_end(args); - -	return out; -} - -string crepe::stringf(const char * fmt, ...) { -	va_list args; -	va_start(args, fmt); -	string out = va_stringf(args, fmt); -	va_end(args); -	return out; -} diff --git a/src/crepe/util/fmt.h b/src/crepe/util/fmt.h deleted file mode 100644 index e319e6e..0000000 --- a/src/crepe/util/fmt.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include <string> - -namespace crepe { - -std::string va_stringf(va_list args, const char * fmt); -std::string stringf(const char * fmt, ...); - -} // namespace crepe diff --git a/src/crepe/util/log.cpp b/src/crepe/util/log.cpp deleted file mode 100644 index 4a8f8e8..0000000 --- a/src/crepe/util/log.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include <cstdarg> -#include <cstdio> -#include <cstdlib> -#include <string> - -#include "../api/Config.h" -#include "fmt.h" -#include "log.h" - -using namespace crepe; -using namespace std; - -string log_prefix(LogLevel level) { -	switch (level) { -		case LogLevel::TRACE: -			return LogColor().fg_white().str("[TRACE]") + " "; -		case LogLevel::DEBUG: -			return LogColor().fg_magenta().str("[DEBUG]") + " "; -		case LogLevel::INFO: -			return LogColor().fg_blue().str("[INFO]") + " "; -		case LogLevel::WARNING: -			return LogColor().fg_yellow().str("[WARN]") + " "; -		case LogLevel::ERROR: -			return LogColor().fg_red().str("[ERROR]") + " "; -	} -	return ""; -} - -static void log(LogLevel level, const string msg) { -	auto & cfg = Config::get_instance(); -	if (level < cfg.log.level) return; - -	string out = log_prefix(level) + msg; -	if (!out.ends_with("\n")) out += "\n"; - -	// TODO: also log to file or smth -	fwrite(out.c_str(), 1, out.size(), stdout); -	fflush(stdout); -} - -void crepe::logf(const char * fmt, ...) { -	va_list args; -	va_start(args, fmt); -	log(LogLevel::DEBUG, va_stringf(args, fmt)); -	va_end(args); -} - -void crepe::logf(LogLevel level, const char * fmt, ...) { -	va_list args; -	va_start(args, fmt); -	log(level, va_stringf(args, fmt)); -	va_end(args); -} diff --git a/src/crepe/util/log.h b/src/crepe/util/log.h deleted file mode 100644 index 00b5810..0000000 --- a/src/crepe/util/log.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -// allow user to disable debug macros -#ifndef CREPE_DISABLE_MACROS - -#include "LogColor.h" - -// utility macros -#define _crepe_logf_here(level, format, ...) \ -	crepe::logf(level, "%s" format, \ -				crepe::LogColor().fg_white(false).fmt("%s (%s:%d)", __PRETTY_FUNCTION__, \ -													  __FILE_NAME__, __LINE__), \ -				__VA_ARGS__) - -// very illegal global function-style macros -// NOLINTBEGIN -#define dbg_logf(fmt, ...) _crepe_logf_here(crepe::LogLevel::DEBUG, ": " fmt, __VA_ARGS__) -#define dbg_log(str) _crepe_logf_here(crepe::LogLevel::DEBUG, "%s: " str, "") -#define dbg_trace() _crepe_logf_here(crepe::LogLevel::TRACE, "%s", "") -// NOLINTEND - -#endif - -namespace crepe { - -enum LogLevel { -	TRACE, -	DEBUG, -	INFO, -	WARNING, -	ERROR, -}; - -void logf(const char * fmt, ...); -void logf(enum LogLevel level, const char * fmt, ...); - -} // namespace crepe |