From 8d78727d6e7badca16ba7a1328643928a0039569 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Mon, 18 Nov 2024 18:02:09 +0100 Subject: move utilities from loek/audio --- src/crepe/api/Asset.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++ src/crepe/api/Asset.h | 60 ++++++++++++++++++++++++++++++++++++++++++++ src/crepe/api/CMakeLists.txt | 2 ++ src/crepe/api/Config.h | 14 +++++++++++ src/crepe/api/Texture.cpp | 2 +- 5 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 src/crepe/api/Asset.cpp create mode 100644 src/crepe/api/Asset.h (limited to 'src/crepe/api') diff --git a/src/crepe/api/Asset.cpp b/src/crepe/api/Asset.cpp new file mode 100644 index 0000000..5271cf7 --- /dev/null +++ b/src/crepe/api/Asset.cpp @@ -0,0 +1,58 @@ +#include +#include +#include + +#include "Asset.h" +#include "api/Config.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(); + auto & 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::operator()(const Asset & asset) const noexcept { + return std::hash{}(asset.get_path()); +}; + diff --git a/src/crepe/api/Asset.h b/src/crepe/api/Asset.h new file mode 100644 index 0000000..05dccba --- /dev/null +++ b/src/crepe/api/Asset.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include + +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: + 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 { + +template<> struct hash { + size_t operator()(const crepe::Asset & asset) const noexcept; +}; + +} + diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index f9b370f..6557656 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -19,6 +19,7 @@ target_sources(crepe PUBLIC Animator.cpp LoopManager.cpp LoopTimer.cpp + Asset.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -45,4 +46,5 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES Animator.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/Texture.cpp b/src/crepe/api/Texture.cpp index de0d0ea..6a1e4d8 100644 --- a/src/crepe/api/Texture.cpp +++ b/src/crepe/api/Texture.cpp @@ -26,7 +26,7 @@ Texture::~Texture() { void Texture::load(unique_ptr 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 { -- cgit v1.2.3 From 9770b548c5619821d7b6ea7a017df2b5a6898d0a Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Mon, 18 Nov 2024 18:10:31 +0100 Subject: add doxygen comments --- src/crepe/api/Asset.h | 10 +++++++++- src/crepe/util/OptionalRef.h | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 3 deletions(-) (limited to 'src/crepe/api') diff --git a/src/crepe/api/Asset.h b/src/crepe/api/Asset.h index 05dccba..685dd3a 100644 --- a/src/crepe/api/Asset.h +++ b/src/crepe/api/Asset.h @@ -1,7 +1,6 @@ #pragma once #include -#include namespace crepe { @@ -52,7 +51,16 @@ private: namespace std { +//! Hash helper struct template<> struct hash { + /** + * \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; }; diff --git a/src/crepe/util/OptionalRef.h b/src/crepe/util/OptionalRef.h index 1ad3a6d..8417a25 100644 --- a/src/crepe/util/OptionalRef.h +++ b/src/crepe/util/OptionalRef.h @@ -12,18 +12,51 @@ namespace crepe { template class OptionalRef { public: + //! Initialize empty (nonexistant) reference OptionalRef() = default; - OptionalRef(T &); - OptionalRef & operator=(T &); + //! Initialize reference with value + OptionalRef(T & ref); + /** + * \brief Assign new reference + * + * \param ref Reference to assign + * + * \return Reference to this (required for operator) + */ + OptionalRef & operator=(T & ref); + /** + * \brief Check if this reference is not empty + * + * \returns `true` if reference is set, or `false` if it is not + */ explicit operator bool() const noexcept; + /** + * \brief Assign new reference + * + * \param ref Reference to assign + */ void set(T &) noexcept; + /** + * \brief Retrieve this reference + * + * \returns Internal reference if it is set + * + * \throws std::runtime_error if this function is called while the reference it not set + */ T & get() const; + /** + * \brief Make this reference empty + */ void clear() noexcept; + //! Copy constructor OptionalRef(const OptionalRef &); + //! Move constructor OptionalRef(OptionalRef &&); + //! Copy assignment OptionalRef & operator=(const OptionalRef &); + //! Move assignment OptionalRef & operator=(OptionalRef &&); private: -- cgit v1.2.3