diff options
Diffstat (limited to 'src/crepe/api')
| -rw-r--r-- | src/crepe/api/Asset.cpp | 54 | ||||
| -rw-r--r-- | src/crepe/api/Asset.h | 84 | ||||
| -rw-r--r-- | src/crepe/api/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/crepe/api/Config.h | 14 | ||||
| -rw-r--r-- | src/crepe/api/GameObject.cpp | 6 | ||||
| -rw-r--r-- | src/crepe/api/Script.h | 2 | ||||
| -rw-r--r-- | src/crepe/api/Script.hpp | 4 | ||||
| -rw-r--r-- | src/crepe/api/Texture.cpp | 2 | 
8 files changed, 160 insertions, 8 deletions
| diff --git a/src/crepe/api/Asset.cpp b/src/crepe/api/Asset.cpp new file mode 100644 index 0000000..e148367 --- /dev/null +++ b/src/crepe/api/Asset.cpp @@ -0,0 +1,54 @@ +#include <filesystem> +#include <stdexcept> +#include <whereami.h> + +#include "api/Config.h" + +#include "Asset.h" + +using namespace crepe; +using namespace std; + +Asset::Asset(const string & src) : src(find_asset(src)) {} +Asset::Asset(const char * src) : src(find_asset(src)) {} + +const string & Asset::get_path() const noexcept { return this->src; } + +string Asset::find_asset(const string & src) const { +	auto & cfg = Config::get_instance(); +	string & root_pattern = cfg.asset.root_pattern; + +	// if root_pattern is empty, find_asset must return all paths as-is +	if (root_pattern.empty()) return src; + +	// absolute paths do not need to be resolved, only canonicalized +	filesystem::path path = src; +	if (path.is_absolute()) return filesystem::canonical(path); + +	// find directory matching root_pattern +	filesystem::path root = this->whereami(); +	while (1) { +		if (filesystem::exists(root / root_pattern)) break; +		if (!root.has_parent_path()) +			throw runtime_error(format("Asset: Cannot find root pattern ({})", root_pattern)); +		root = root.parent_path(); +	} + +	// join path to root (base directory) and canonicalize +	return filesystem::canonical(root / path); +} + +string Asset::whereami() const noexcept { +	string path; +	size_t path_length = wai_getExecutablePath(NULL, 0, NULL); +	path.resize(path_length + 1); // wai writes null byte +	wai_getExecutablePath(path.data(), path_length, NULL); +	path.resize(path_length); +	return path; +} + +bool Asset::operator==(const Asset & other) const noexcept { return this->src == other.src; } + +size_t std::hash<const Asset>::operator()(const Asset & asset) const noexcept { +	return std::hash<string>{}(asset.get_path()); +}; diff --git a/src/crepe/api/Asset.h b/src/crepe/api/Asset.h new file mode 100644 index 0000000..bfd0ac7 --- /dev/null +++ b/src/crepe/api/Asset.h @@ -0,0 +1,84 @@ +#pragma once + +#include <string> + +namespace crepe { + +/** + * \brief Asset location helper + * + * This class is used to locate game asset files, and should *always* be used + * instead of reading file paths directly. + */ +class Asset { +public: +	/** +	 * \param src  Unique identifier to asset +	 */ +	Asset(const std::string & src); +	/** +	 * \param src  Unique identifier to asset +	 */ +	Asset(const char * src); + +public: +	/** +	 * \brief Get the path to this asset +	 * \return path to this asset +	 */ +	const std::string & get_path() const noexcept; + +	/** +	 * \brief Comparison operator +	 * \param other Possibly different instance of \c Asset to test equality against +	 * \return True if \c this and \c other are equal +	 */ +	bool operator==(const Asset & other) const noexcept; + +private: +	//! path to asset +	const std::string src; + +private: +	/** +	 * \brief Locate asset path, or throw exception if it cannot be found +	 * +	 * This function resolves asset locations relative to crepe::Config::root_pattern if it is +	 * set and \p src is a relative path. If \p src is an absolute path, it is canonicalized. +	 * This function only returns if the file can be found. +	 * +	 * \param src Arbitrary path to resource file +	 * +	 * \returns \p src if crepe::Config::root_pattern is empty +	 * \returns Canonical path to \p src +	 * +	 * \throws std::runtime_error if root_pattern cannot be found +	 * \throws std::filesystem::filesystem_error if the resolved path does not exist +	 * \throws std::filesystem::filesystem_error if the path cannot be canonicalized +	 */ +	std::string find_asset(const std::string & src) const; +	/** +	 * \returns The path to the current executable +	 */ +	std::string whereami() const noexcept; +}; + +} // namespace crepe + +namespace std { + +//! Hash helper struct +template <> +struct hash<const crepe::Asset> { +	/** +	 * \brief Hash operator for crepe::Asset +	 * +	 * This function hashes a crepe::Asset instance, allowing it to be used as a key in an \c +	 * std::unordered_map. +	 * +	 * \returns Hash value +	 */ +	size_t operator()(const crepe::Asset & asset) const noexcept; +}; + +} // namespace std diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index a63c5ff..602ab52 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -22,6 +22,7 @@ target_sources(crepe PUBLIC  	IMouseListener.cpp  	LoopManager.cpp  	LoopTimer.cpp +	Asset.cpp  	EventHandler.cpp  	Script.cpp  ) @@ -57,4 +58,5 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES  	IMouseListener.h  	LoopManager.h  	LoopTimer.h +	Asset.h  ) diff --git a/src/crepe/api/Config.h b/src/crepe/api/Config.h index 3ab877a..13eabd1 100644 --- a/src/crepe/api/Config.h +++ b/src/crepe/api/Config.h @@ -62,6 +62,20 @@ public:  		 */  		double gravity = 1;  	} physics; + +	//! Asset loading options +	struct { +		/** +		 * \brief Pattern to match for Asset base directory +		 * +		 * All non-absolute paths resolved using \c Asset will be made relative to +		 * the first parent directory relative to the calling executable where +		 * appending this pattern results in a path that exists. If this string is +		 * empty, path resolution is disabled, and Asset will return all paths +		 * as-is. +		 */ +		std::string root_pattern = ".crepe-root"; +	} asset;  };  } // namespace crepe diff --git a/src/crepe/api/GameObject.cpp b/src/crepe/api/GameObject.cpp index 287e81d..4874426 100644 --- a/src/crepe/api/GameObject.cpp +++ b/src/crepe/api/GameObject.cpp @@ -23,12 +23,10 @@ void GameObject::set_parent(const GameObject & parent) {  	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); +	RefVector<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); +	RefVector<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/Script.h b/src/crepe/api/Script.h index 8356fd2..43efd15 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -78,7 +78,7 @@ protected:  	 * \returns List of component references  	 */  	template <typename T> -	std::vector<std::reference_wrapper<T>> get_components() const; +	RefVector<T> get_components() const;  	/**  	 * \brief Log a message using Log::logf diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp index e60be07..e94278d 100644 --- a/src/crepe/api/Script.hpp +++ b/src/crepe/api/Script.hpp @@ -10,7 +10,7 @@ namespace crepe {  template <typename T>  T & Script::get_component() const {  	using namespace std; -	vector<reference_wrapper<T>> all_components = this->get_components<T>(); +	RefVector<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())); @@ -19,7 +19,7 @@ T & Script::get_component() const {  }  template <typename T> -std::vector<std::reference_wrapper<T>> Script::get_components() const { +RefVector<T> Script::get_components() const {  	ComponentManager & mgr = *this->component_manager_ref;  	return mgr.get_components_by_id<T>(*this->game_object_id_ref); diff --git a/src/crepe/api/Texture.cpp b/src/crepe/api/Texture.cpp index 734a5bb..9be9421 100644 --- a/src/crepe/api/Texture.cpp +++ b/src/crepe/api/Texture.cpp @@ -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->get_canonical())); +	this->texture = std::move(ctx.texture_from_path(res->get_path()));  }  int Texture::get_width() const { |