diff options
Diffstat (limited to 'src')
51 files changed, 348 insertions, 311 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 0cb5834..cb413f4 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..52a781e 100644 --- a/src/crepe/CMakeLists.txt +++ b/src/crepe/CMakeLists.txt @@ -16,6 +16,7 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES  	ValueBroker.h  	ValueBroker.hpp  	Exception.h +	Exception.hpp  )  add_subdirectory(api) diff --git a/src/crepe/ComponentManager.cpp b/src/crepe/ComponentManager.cpp index 8f8437b..c6b658c 100644 --- a/src/crepe/ComponentManager.cpp +++ b/src/crepe/ComponentManager.cpp @@ -1,5 +1,5 @@  #include "api/GameObject.h" -#include "util/log.h" +#include "util/Log.h"  #include "ComponentManager.h" diff --git a/src/crepe/Exception.cpp b/src/crepe/Exception.cpp index dab8f2e..5a24e7e 100644 --- a/src/crepe/Exception.cpp +++ b/src/crepe/Exception.cpp @@ -1,16 +1,8 @@ -#include <cstdarg> -  #include "Exception.h" -#include "util/fmt.h" -using namespace std;  using namespace crepe; +using namespace std; -const char * Exception::what() { return error.c_str(); } +const char * Exception::what() const noexcept { 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); -} +Exception::Exception(const string & msg) { this->error = msg; } diff --git a/src/crepe/Exception.h b/src/crepe/Exception.h index 6473043..580fc16 100644 --- a/src/crepe/Exception.h +++ b/src/crepe/Exception.h @@ -1,22 +1,31 @@  #pragma once  #include <exception> +#include <format>  #include <string>  namespace crepe { -//! Exception class with printf-style constructor +//! Exception class  class Exception : public std::exception {  public: -	//! printf -	Exception(const char * fmt, ...); +	//! Exception with plain message +	Exception(const std::string & msg); + +	//! Exception with \c std::format message +	template <class... Args> +	Exception(std::format_string<Args...> fmt, Args &&... args); +  	//! Get formatted error message -	const char * what(); +	const char * what() const noexcept;  protected:  	Exception() = default; +  	//! Formatted error message  	std::string error;  };  } // namespace crepe + +#include "Exception.hpp" diff --git a/src/crepe/Exception.hpp b/src/crepe/Exception.hpp new file mode 100644 index 0000000..7c462a3 --- /dev/null +++ b/src/crepe/Exception.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "Exception.h" + +namespace crepe { + +template <class... Args> +Exception::Exception(std::format_string<Args...> fmt, Args &&... args) { +	this->error = std::format(fmt, std::forward<Args>(args)...); +} + +} // namespace crepe diff --git a/src/crepe/api/Animator.cpp b/src/crepe/api/Animator.cpp index fcc07ef..54b2ec3 100644 --- a/src/crepe/api/Animator.cpp +++ b/src/crepe/api/Animator.cpp @@ -1,7 +1,7 @@  #include <cstdint> -#include "util/log.h" +#include "util/Log.h"  #include "Animator.h"  #include "Component.h" 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.h b/src/crepe/api/BehaviorScript.h index a49fc96..2982358 100644 --- a/src/crepe/api/BehaviorScript.h +++ b/src/crepe/api/BehaviorScript.h @@ -11,6 +11,13 @@ 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:  	BehaviorScript(game_object_id_t id, ComponentManager & component_manager); @@ -18,7 +25,7 @@ protected:  	friend class ComponentManager;  public: -	virtual ~BehaviorScript() = default; +	~BehaviorScript() = default;  public:  	/** @@ -36,7 +43,9 @@ protected:  	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;  private: diff --git a/src/crepe/api/BehaviorScript.hpp b/src/crepe/api/BehaviorScript.hpp index 2bed1b7..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" diff --git a/src/crepe/api/Camera.cpp b/src/crepe/api/Camera.cpp index 232c922..5835bdd 100644 --- a/src/crepe/api/Camera.cpp +++ b/src/crepe/api/Camera.cpp @@ -1,4 +1,4 @@ -#include "util/log.h" +#include "util/Log.h"  #include "Camera.h"  #include "Color.h" diff --git a/src/crepe/api/Config.h b/src/crepe/api/Config.h index 8c9e643..e3f86bf 100644 --- a/src/crepe/api/Config.h +++ b/src/crepe/api/Config.h @@ -1,6 +1,6 @@  #pragma once -#include "../util/log.h" +#include "../util/Log.h"  namespace crepe { @@ -26,10 +26,10 @@ public:  		/**  		 * \brief Log level  		 * -		 * Only messages with equal or higher priority than this value will be +		 * Only messages with equal or higher severity 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/LoopTimer.cpp b/src/crepe/api/LoopTimer.cpp index 8f09e41..b3aec22 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/SaveManager.cpp b/src/crepe/api/SaveManager.cpp index 43276c5..2974b91 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/Script.h b/src/crepe/api/Script.h index 051ea00..68a46d7 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -3,20 +3,36 @@  #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 @@ -24,13 +40,28 @@ protected:  	// added event.  protected: -	//! Retrieve component from component manager (utility) +	/** +	 * \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; -	//! Retrieve components from component manager (utility) +	/** +	 * \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 diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp index ee8c380..aceb38b 100644 --- a/src/crepe/api/Script.hpp +++ b/src/crepe/api/Script.hpp @@ -1,6 +1,7 @@  #pragma once  #include "../ComponentManager.h" +#include "../Exception.h"  #include "BehaviorScript.h"  #include "Script.h" @@ -8,16 +9,18 @@  namespace crepe {  template <typename T> -T & Script::get_component() { +T & Script::get_component() const {  	std::vector<std::reference_wrapper<T>> all_components  		= this->get_components<T>(); -	if (all_components.size() < 1) throw nullptr; // TODO +	if (all_components.size() < 1) +		throw Exception("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() { +std::vector<std::reference_wrapper<T>> Script::get_components() const {  	auto & parent = *this->parent_ref;  	auto & mgr = *this->component_manager_ref; diff --git a/src/crepe/api/Sprite.cpp b/src/crepe/api/Sprite.cpp index 6f0433f..ac0079e 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/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 e401120..e9108c4 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/facade/DB.cpp b/src/crepe/facade/DB.cpp index 0a2f455..80047a6 100644 --- a/src/crepe/facade/DB.cpp +++ b/src/crepe/facade/DB.cpp @@ -1,7 +1,7 @@  #include <cstring>  #include "Exception.h" -#include "util/log.h" +#include "util/Log.h"  #include "DB.h" @@ -15,19 +15,18 @@ 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 Exception("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 Exception("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 Exception("db->cursor: {}", libdb::db_strerror(ret));  	this->cursor = {cursor, [](libdb::DBC * cursor) { cursor->close(cursor); }};  } @@ -45,7 +44,7 @@ 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)); +	if (ret != 0) throw Exception("cursor->get: {}", libdb::db_strerror(ret));  	return {static_cast<char *>(db_val.data), db_val.size};  } @@ -53,7 +52,7 @@ 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 Exception("cursor->get: {}", libdb::db_strerror(ret));  }  bool DB::has(const std::string & key) noexcept { diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index 236bf8c..a68d940 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -15,7 +15,7 @@  #include "../api/Sprite.h"  #include "../api/Texture.h"  #include "../api/Transform.h" -#include "../util/log.h" +#include "../util/Log.h"  #include "Exception.h"  #include "SDLContext.h" @@ -171,7 +171,7 @@ SDLContext::texture_from_path(const std::string & path) {  		this->game_renderer.get(), img_surface.get());  	if (tmp_texture == nullptr) { -		throw Exception("Texture cannot be load from %s", path.c_str()); +		throw Exception("Texture cannot be load from {}", path);  	}  	std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>> diff --git a/src/crepe/facade/Sound.cpp b/src/crepe/facade/Sound.cpp index 648ec81..a65b052 100644 --- a/src/crepe/facade/Sound.cpp +++ b/src/crepe/facade/Sound.cpp @@ -1,22 +1,23 @@ -#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() { diff --git a/src/crepe/facade/Sound.h b/src/crepe/facade/Sound.h index 183bd7c..402482f 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/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 3e6360c..0d37808 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -5,7 +5,7 @@  #include "../api/Sprite.h"  #include "../api/Transform.h"  #include "../facade/SDLContext.h" -#include "../util/log.h" +#include "../util/Log.h"  #include "RenderSystem.h" diff --git a/src/crepe/system/ScriptSystem.cpp b/src/crepe/system/ScriptSystem.cpp index 644e96e..7b22533 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" @@ -28,7 +27,7 @@ void ScriptSystem::update() {  	}  } -forward_list<reference_wrapper<Script>> ScriptSystem::get_scripts() { +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 @@ -44,3 +43,4 @@ forward_list<reference_wrapper<Script>> ScriptSystem::get_scripts() {  	return scripts;  } + diff --git a/src/crepe/system/ScriptSystem.h b/src/crepe/system/ScriptSystem.h index b0b4185..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:  	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: -	std::forward_list<std::reference_wrapper<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 index 201b9ad..937a423 100644 --- a/src/crepe/system/System.cpp +++ b/src/crepe/system/System.cpp @@ -1,4 +1,4 @@ -#include "../util/log.h" +#include "../util/Log.h"  #include "System.h" diff --git a/src/crepe/system/System.h b/src/crepe/system/System.h index 7970e72..28ea20e 100644 --- a/src/crepe/system/System.h +++ b/src/crepe/system/System.h @@ -4,8 +4,18 @@ 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: 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 index 4a8f8e8..e583734 100644 --- a/src/crepe/util/log.cpp +++ b/src/crepe/util/Log.cpp @@ -4,50 +4,35 @@  #include <string>  #include "../api/Config.h" -#include "fmt.h" -#include "log.h" +#include "Log.h"  using namespace crepe;  using namespace std; -string log_prefix(LogLevel level) { +string Log::prefix(const Level & level) {  	switch (level) { -		case LogLevel::TRACE: +		case Level::TRACE:  			return LogColor().fg_white().str("[TRACE]") + " "; -		case LogLevel::DEBUG: +		case Level::DEBUG:  			return LogColor().fg_magenta().str("[DEBUG]") + " "; -		case LogLevel::INFO: +		case Level::INFO:  			return LogColor().fg_blue().str("[INFO]") + " "; -		case LogLevel::WARNING: +		case Level::WARNING:  			return LogColor().fg_yellow().str("[WARN]") + " "; -		case LogLevel::ERROR: +		case Level::ERROR:  			return LogColor().fg_red().str("[ERROR]") + " ";  	}  	return "";  } -static void log(LogLevel level, const string msg) { +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; +	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 new file mode 100644 index 0000000..01452b2 --- /dev/null +++ b/src/crepe/util/Log.h @@ -0,0 +1,85 @@ +#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 +	 */ +	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 b5fe3ea..ae44d72 100644 --- a/src/crepe/util/LogColor.cpp +++ b/src/crepe/util/LogColor.cpp @@ -3,14 +3,12 @@  #include "../api/Config.h"  #include "LogColor.h" -#include "fmt.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 +17,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..4b65127 100644 --- a/src/crepe/util/LogColor.h +++ b/src/crepe/util/LogColor.h @@ -4,20 +4,19 @@  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; +	//! Get color code as stl string (or color content string) +	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: @@ -41,11 +40,19 @@ public:  	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.h b/src/crepe/util/log.h deleted file mode 100644 index 5a1cf00..0000000 --- a/src/crepe/util/log.h +++ /dev/null @@ -1,39 +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 diff --git a/src/example/audio_internal.cpp b/src/example/audio_internal.cpp index 1ea839d..ff55a59 100644 --- a/src/example/audio_internal.cpp +++ b/src/example/audio_internal.cpp @@ -5,7 +5,7 @@  #include <crepe/api/Config.h>  #include <crepe/facade/Sound.h> -#include <crepe/util/log.h> +#include <crepe/util/Log.h>  #include <thread> @@ -18,7 +18,7 @@ using std::make_unique;  int _ = []() {  	// Show dbg_trace() output  	auto & cfg = Config::get_instance(); -	cfg.log.level = LogLevel::TRACE; +	cfg.log.level = Log::Level::TRACE;  	return 0; // satisfy compiler  }(); diff --git a/src/example/components_internal.cpp b/src/example/components_internal.cpp index dd4c7df..7a8a08a 100644 --- a/src/example/components_internal.cpp +++ b/src/example/components_internal.cpp @@ -13,7 +13,7 @@  #include <crepe/api/Rigidbody.h>  #include <crepe/api/Sprite.h> -#include <crepe/util/log.h> +#include <crepe/util/Log.h>  using namespace crepe;  using namespace std; diff --git a/src/example/db.cpp b/src/example/db.cpp index 8c06a84..ee4e8fc 100644 --- a/src/example/db.cpp +++ b/src/example/db.cpp @@ -1,6 +1,6 @@  #include <crepe/api/Config.h>  #include <crepe/facade/DB.h> -#include <crepe/util/log.h> +#include <crepe/util/Log.h>  using namespace crepe;  using namespace std; @@ -8,7 +8,7 @@ using namespace std;  // run before main  static auto _ = []() {  	auto & cfg = Config::get_instance(); -	cfg.log.level = LogLevel::TRACE; +	cfg.log.level = Log::Level::TRACE;  	return 0;  }(); @@ -20,11 +20,11 @@ int main() {  	const char * test_key = "test-key";  	string test_data = "Hello world!"; -	dbg_logf("DB has key = %d", db.has(test_key)); +	dbg_logf("DB has key = {}", db.has(test_key));  	db.set(test_key, test_data); -	dbg_logf("key = \"%s\"", db.get(test_key).c_str()); +	dbg_logf("key = \"{}\"", db.get(test_key));  	return 0;  } diff --git a/src/example/log.cpp b/src/example/log.cpp index db8aa48..5baa021 100644 --- a/src/example/log.cpp +++ b/src/example/log.cpp @@ -4,7 +4,7 @@   */  #include <crepe/api/Config.h> -#include <crepe/util/log.h> +#include <crepe/util/Log.h>  using namespace crepe; @@ -12,17 +12,17 @@ using namespace crepe;  int _ = []() {  	// make sure all log messages get printed  	auto & cfg = Config::get_instance(); -	cfg.log.level = LogLevel::TRACE; +	cfg.log.level = Log::Level::TRACE;  	return 0; // satisfy compiler  }();  int main() {  	dbg_trace(); -	dbg_logf("test printf parameters: %d", 3); -	logf(LogLevel::INFO, "info message"); -	logf(LogLevel::WARNING, "warning"); -	logf(LogLevel::ERROR, "error"); +	dbg_log("debug message"); +	Log::logf("info message with variable: {}", 3); +	Log::logf(Log::Level::WARNING, "warning"); +	Log::logf(Log::Level::ERROR, "error");  	return 0;  } diff --git a/src/example/proxy.cpp b/src/example/proxy.cpp index 0afff41..69451f8 100644 --- a/src/example/proxy.cpp +++ b/src/example/proxy.cpp @@ -5,8 +5,8 @@  #include <crepe/ValueBroker.h>  #include <crepe/api/Config.h> +#include <crepe/util/Log.h>  #include <crepe/util/Proxy.h> -#include <crepe/util/log.h>  using namespace std;  using namespace crepe; @@ -17,18 +17,17 @@ void test_ro_val(int val) {}  int main() {  	auto & cfg = Config::get_instance(); -	cfg.log.level = LogLevel::DEBUG; +	cfg.log.level = Log::Level::DEBUG;  	int real_value = 0;  	ValueBroker<int> broker{  		[&real_value](const int & target) { -			dbg_logf("set %s to %s", to_string(real_value).c_str(), -					 to_string(target).c_str()); +			dbg_logf("set {} to {}", real_value, target);  			real_value = target;  		},  		[&real_value]() -> const int & { -			dbg_logf("get %s", to_string(real_value).c_str()); +			dbg_logf("get {}", real_value);  			return real_value;  		},  	}; diff --git a/src/example/rendering.cpp b/src/example/rendering.cpp index 95d5dac..74c00e2 100644 --- a/src/example/rendering.cpp +++ b/src/example/rendering.cpp @@ -2,7 +2,7 @@  #include <crepe/ComponentManager.h>  #include <crepe/api/GameObject.h>  #include <crepe/system/RenderSystem.h> -#include <crepe/util/log.h> +#include <crepe/util/Log.h>  #include <crepe/api/AssetManager.h>  #include <crepe/api/Color.h> diff --git a/src/example/savemgr.cpp b/src/example/savemgr.cpp index 436fb5a..65c4a34 100644 --- a/src/example/savemgr.cpp +++ b/src/example/savemgr.cpp @@ -6,8 +6,8 @@  #include <cassert>  #include <crepe/api/Config.h>  #include <crepe/api/SaveManager.h> +#include <crepe/util/Log.h>  #include <crepe/util/Proxy.h> -#include <crepe/util/log.h>  using namespace crepe; @@ -15,7 +15,7 @@ using namespace crepe;  int _ = []() {  	// make sure all log messages get printed  	auto & cfg = Config::get_instance(); -	cfg.log.level = LogLevel::TRACE; +	cfg.log.level = Log::Level::TRACE;  	return 0; // satisfy compiler  }(); @@ -25,19 +25,19 @@ int main() {  	SaveManager & mgr = SaveManager::get_instance(); -	dbg_logf("has key = %s", mgr.has(key) ? "true" : "false"); +	dbg_logf("has key = {}", mgr.has(key));  	ValueBroker<int> prop = mgr.get<int>(key, 0);  	Proxy<int> val = mgr.get<int>(key, 0); -	dbg_logf("val = %d", mgr.get<int>(key).get()); +	dbg_logf("val = {}", mgr.get<int>(key).get());  	prop.set(1); -	dbg_logf("val = %d", mgr.get<int>(key).get()); +	dbg_logf("val = {}", mgr.get<int>(key).get());  	val = 2; -	dbg_logf("val = %d", mgr.get<int>(key).get()); +	dbg_logf("val = {}", mgr.get<int>(key).get());  	mgr.set<int>(key, 3); -	dbg_logf("val = %d", mgr.get<int>(key).get()); +	dbg_logf("val = {}", mgr.get<int>(key).get()); -	dbg_logf("has key = %s", mgr.has(key) ? "true" : "false"); +	dbg_logf("has key = {}", mgr.has(key));  	assert(true == mgr.has(key));  	return 0; diff --git a/src/example/script.cpp b/src/example/script.cpp index 69d1ce1..c82764c 100644 --- a/src/example/script.cpp +++ b/src/example/script.cpp @@ -5,7 +5,7 @@  #include <crepe/ComponentManager.h>  #include <crepe/system/ScriptSystem.h> -#include <crepe/util/log.h> +#include <crepe/util/Log.h>  #include <crepe/api/BehaviorScript.h>  #include <crepe/api/Config.h> @@ -20,7 +20,7 @@ using namespace std;  int _ = []() {  	// Show dbg_trace() output  	auto & cfg = Config::get_instance(); -	cfg.log.level = LogLevel::TRACE; +	cfg.log.level = Log::Level::TRACE;  	return 0; // satisfy compiler  }(); @@ -30,7 +30,7 @@ class MyScript : public Script {  	void update() {  		// Retrieve component from the same GameObject this script is on  		Transform & test = get_component<Transform>(); -		dbg_logf("Transform(%.2f, %.2f)", test.position.x, test.position.y); +		dbg_logf("Transform({:.2f}, {:.2f})", test.position.x, test.position.y);  	}  }; diff --git a/src/test/main.cpp b/src/test/main.cpp index a54d239..241015d 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -9,7 +9,7 @@ int main(int argc, char ** argv) {  	InitGoogleTest(&argc, argv);  	auto & cfg = Config::get_instance(); -	cfg.log.level = LogLevel::ERROR; +	cfg.log.level = Log::Level::ERROR;  	return RUN_ALL_TESTS();  }  |