diff --git a/engine/src/assets/Asset.hpp b/engine/src/assets/Asset.hpp index 0867ab157..d9d4f35e0 100644 --- a/engine/src/assets/Asset.hpp +++ b/engine/src/assets/Asset.hpp @@ -69,14 +69,41 @@ namespace nexo::assets { "AssetTypeNames array size must match AssetType enum size" ); + /** + * @brief Retrieves the name corresponding to the specified asset type. + * + * This function returns a string literal from the AssetTypeNames array that matches the provided asset type. + * + * @param type The asset type value. + * @return const char* The name of the asset type. + */ constexpr const char *getAssetTypeName(AssetType type) { return AssetTypeNames[static_cast(type)]; } + /** + * @brief Serializes an AssetType value to JSON. + * + * Converts the provided AssetType enum into its string representation using getAssetTypeName + * and assigns this string to the JSON object. + * + * @param j JSON object to receive the serialized asset type. + * @param type The AssetType enum value to convert. + */ inline void to_json(nlohmann::json& j, AssetType type) { j = getAssetTypeName(type); } + /** + * @brief Converts a JSON value to its corresponding AssetType. + * + * This function iterates over the predefined asset type names and, if the JSON value matches one, + * assigns the corresponding AssetType enum value to the output parameter. If no match is found, + * the AssetType is set to UNKNOWN. + * + * @param j JSON object containing the asset type as a string. + * @param type Output parameter to store the resulting AssetType. + */ inline void from_json(const nlohmann::json& j, AssetType& type) { for (int i = 0; i < static_cast(AssetType::_COUNT); ++i) { if (j == AssetTypeNames[i]) { @@ -170,6 +197,11 @@ namespace nexo::assets { public: static constexpr AssetType TYPE = TAssetType; + /** + * @brief Destructor that releases the allocated asset data. + * + * Deletes the dynamically allocated asset data to ensure proper memory cleanup when the asset is destroyed. + */ virtual ~Asset() override { delete data; diff --git a/engine/src/assets/AssetCatalog.hpp b/engine/src/assets/AssetCatalog.hpp index fb89ad187..1cb7424e7 100644 --- a/engine/src/assets/AssetCatalog.hpp +++ b/engine/src/assets/AssetCatalog.hpp @@ -30,8 +30,22 @@ namespace nexo::assets { */ class AssetCatalog { protected: - // Singleton: private constructor and destructor + // Singleton: protected constructor and destructor + /** + * @brief Default constructor for AssetCatalog. + * + * Constructs an AssetCatalog instance using the default initializer. + * The constructor is protected to allow instantiation by derived classes, + * while still supporting the singleton pattern. + */ AssetCatalog() = default; + + /** + * @brief Default destructor for AssetCatalog. + * + * The default destructor relies on compiler-generated behavior to clean up the instance, + * ensuring that all managed assets are properly released. + */ ~AssetCatalog() = default; public: @@ -47,8 +61,12 @@ namespace nexo::assets { void operator=(AssetCatalog const&) = delete; /** - * @brief Delete an asset from the catalog. - * @param id The ID of the asset to delete. + * @brief Removes the asset associated with the given ID from the catalog. + * + * Checks if an asset with the specified ID exists in the catalog and, if so, + * deletes it. + * + * @param id The unique identifier of the asset to be removed. */ void deleteAsset(AssetID id); @@ -73,14 +91,22 @@ namespace nexo::assets { [[nodiscard]] GenericAssetRef getAsset(const AssetLocation& location) const; /** - * @brief Get all assets in the catalog. - * @return A vector of all assets in the catalog. + * @brief Retrieves all asset references registered in the catalog. + * + * Iterates through the stored assets and collects them into a vector of GenericAssetRef objects. + * + * @return A vector containing a GenericAssetRef for each managed asset. */ [[nodiscard]] std::vector getAssets() const; /** - * @brief Get all assets in the catalog as a view. - * @return A view of all assets in the catalog. + * @brief Retrieves a view of all assets in the catalog. + * + * This function returns a view of the asset collection, where each asset is transformed into a + * GenericAssetRef using C++20 ranges. This lightweight view facilitates efficient iteration over + * the registered assets. + * + * @return A view of the assets with each element represented as a GenericAssetRef. */ [[nodiscard]] auto getAssetsView() const { @@ -109,6 +135,20 @@ namespace nexo::assets { requires std::derived_from [[nodiscard]] std::ranges::view auto getAssetsOfTypeView() const; + /** + * @brief Registers an asset in the catalog. + * + * This method verifies that the provided asset pointer is valid, then creates a shared pointer + * to the asset. It updates the asset's metadata by setting its location and assigning a new unique + * identifier if one is not already set. The asset is stored in the catalog and a reference to the + * asset is returned. + * + * @warning Once registered, the memory for the asset is managed by the catalog. Do not delete the asset. + * + * @param location The asset's location metadata. + * @param asset Pointer to the asset to be registered. + * @return GenericAssetRef A reference to the registered asset, or a null reference if the asset pointer was null. + */ GenericAssetRef registerAsset(const AssetLocation& location, IAsset *asset); private: std::unordered_map> m_assets; diff --git a/engine/src/assets/AssetImporter.hpp b/engine/src/assets/AssetImporter.hpp index 8e6cf9fba..7d57b264c 100644 --- a/engine/src/assets/AssetImporter.hpp +++ b/engine/src/assets/AssetImporter.hpp @@ -45,8 +45,50 @@ namespace nexo::assets { template requires std::derived_from AssetRef importAsset(const AssetLocation& location, const ImporterInputVariant& inputVariant); + + /** + * @brief Automatically imports an asset using available importers. + * + * Iterates through all registered importer groups, invoking each group's importer(s) + * to attempt importing an asset from the specified location and input data variant. + * Returns the first successfully imported asset, or a null reference if none succeed. + * + * @param location The location of the asset to be imported. + * @param inputVariant The input data variant providing information for asset import. + * @return GenericAssetRef A reference to the imported asset, or GenericAssetRef::null() if import fails. + */ GenericAssetRef importAssetAuto(const AssetLocation& location, const ImporterInputVariant& inputVariant); + + /** + * @brief Imports an asset using a specified importer and registers it. + * + * This function attempts to import an asset by invoking the given importer. It utilizes a custom import context if one + * is configured (see setCustomContext()); otherwise, it creates a temporary context initialized with the provided input data and location. + * After importing, if the asset is valid, the function ensures that the asset has a unique identifier and updates its location + * metadata if it is set to "default". The asset is then registered in the AssetCatalog. If the import fails, a null asset reference is returned. + * + * @param location The asset location used for input configuration and asset registration. + * @param inputVariant Input data required by the importer for the asset import operation. + * @param importer The importer instance responsible for performing the asset import. + * @return GenericAssetRef A reference to the imported and registered asset, or a null reference if the import fails. + */ GenericAssetRef importAssetUsingImporter(const AssetLocation& location, const ImporterInputVariant& inputVariant, AssetImporterBase *importer) const; + + /** + * @brief Attempts to import an asset using a prioritized list of importers. + * + * This function iterates over the provided importers in two phases: + * 1. In the first phase, it attempts to import the asset + * using importers that are capable of reading the given input variant. (checking with canRead()) + * 2. If none of these succeed, it then tries the remaining + * importers regardless of compatibility. The function returns immediately + * upon the first successful import, or a null asset reference if all attempts fail. + * + * @param location The asset's location information. + * @param inputVariant A variant that encapsulates the data and configuration for asset import. + * @param importers A list of asset importers to attempt the import operation with. + * @return GenericAssetRef A reference to the successfully imported asset, or a null reference if the import fails. + */ GenericAssetRef importAssetTryImporters(const AssetLocation& location, const ImporterInputVariant& inputVariant, const std::vector& importers) const; @@ -95,8 +137,21 @@ namespace nexo::assets { void setCustomContext(AssetImporterContext *ctx) { m_customCtx = ctx; } + /** + * @brief Clears the custom context. + * + * Resets the internal custom context pointer to indicate that no custom context is in use. + */ void clearCustomContext() { m_customCtx = nullptr; } + /** + * @brief Retrieves the current custom asset importer context. + * + * This function returns a pointer to the custom context associated with the asset importer. + * The returned context can provide custom configurations or behaviors if one has been set. + * + * @return A pointer to the current AssetImporterContext, or nullptr if no custom context is set. + */ [[nodiscard]] AssetImporterContext *getCustomContext() const { return m_customCtx; } void setParameters(const json& params); @@ -105,19 +160,27 @@ namespace nexo::assets { protected: /** - * @brief Protected constructor for custom importers - * @note Used currently by unit tests + * @brief Constructs an AssetImporter with a custom context. + * + * Initializes the AssetImporter using the provided custom context, allowing + * derived classes and unit tests to override the default importer context. + * + * @param ctx Pointer to the custom AssetImporterContext used for asset importing. */ explicit AssetImporter(AssetImporterContext *ctx) : m_customCtx(ctx) { } /** - * @brief Register an importer for a specific asset type + * @brief Instantiates and registers a new importer. * - * @tparam AssetType The type of asset the importer can handle - * @tparam ImporterType The type of importer to register - * @param priority Optional priority value (higher values = higher priority) + * This templated function creates a new importer instance of type ImporterType using default construction and + * registers it to handle assets of type AssetType with the provided priority. For equal priority values, + * the order of registration determines the processing sequence. + * + * @tparam AssetType The asset type associated with the importer. + * @tparam ImporterType The type of the importer to be registered. + * @param priority The registration priority. Importers with equal priorities retain the order in which they were added. */ template requires std::derived_from @@ -125,21 +188,28 @@ namespace nexo::assets { void registerImporter(int priority = 0); /** - * @brief Register an existing importer instance for a specific asset type - * @note Registered in order of priority and then insertion + * @brief Registers an importer instance for a specific asset type. + * + * This function inserts the provided importer for the asset type into the internal registry, + * maintaining a descending order based on the importers' priority. Importers with higher priority + * are placed before those with lower priority, and if equal priorities exist, the new importer is + * appended after previously registered ones. * - * @tparam AssetType The type of asset the importer can handle - * @param importer The importer instance to register - * @param priority Optional priority value (higher values = higher priority, if equal then insertion order) + * @tparam AssetType The asset type associated with the importer. + * @param importer Pointer to the importer instance. + * @param priority An integer representing the importer's priority; higher values denote higher precedence. If equal, insertion order. */ template requires std::derived_from void registerImporter(AssetImporterBase *importer, int priority = 0); /** - * @brief Unregister all importers for an asset type + * @brief Unregisters all importers associated with a specific asset type. * - * @tparam AssetType The type of asset + * Determines the runtime type index of the asset type using RTTI and delegates the unregistration + * to the overload that handles type index unregistration. + * + * @tparam AssetType The asset type for which all registered importers will be unregistered. */ template requires std::derived_from diff --git a/engine/src/assets/AssetImporterContext.hpp b/engine/src/assets/AssetImporterContext.hpp index 88fd75140..a2ce7683f 100644 --- a/engine/src/assets/AssetImporterContext.hpp +++ b/engine/src/assets/AssetImporterContext.hpp @@ -82,19 +82,41 @@ namespace nexo::assets { [[nodiscard]] json getParameters() const; + + /** + * @brief Generates a unique dependency asset location. + * + * This method creates a candidate asset location by using the current location as a base, then sets a unique name + * by incrementing an internal dependency counter and formatting the name with a dedicated formatting function. + * If the generated location already exists in the asset catalog, the method continues to update the candidate location + * until a unique one is found or the maximum allowed dependency count is exceeded. In the latter case, an error is logged, + * and the last candidate is returned. + * + * @tparam AssetType The type of the asset for which the location is being generated. + * @return AssetLocation A unique location for the dependency asset. + */ template requires std::derived_from AssetLocation genUniqueDependencyLocation(); + /** + * @brief Formats a unique asset name. + * + * Constructs a unique asset name by combining a base name, the asset type name, and a unique identifier. + * The resulting format is: `_`, where the asset type name is + * derived from the provided asset type. + * + * @param name The base name of the asset. + * @param type The type of the asset. + * @param id A unique identifier appended to ensure the name is distinct. + * @return AssetName The uniquely formatted asset name. + */ static AssetName formatUniqueName(const std::string& name, const AssetType type, unsigned int id) { return AssetName(std::format("{}_{}{}", name, getAssetTypeName(type), id)); } - private: - - IAsset *m_mainAsset = nullptr; //< Main asset being imported, resulting asset (MUST be set by importer) std::vector m_dependencies; //< Dependencies to import json m_jsonParameters; //< JSON parameters for the importer diff --git a/engine/src/assets/AssetLocation.hpp b/engine/src/assets/AssetLocation.hpp index 816debe79..b33e5eb47 100644 --- a/engine/src/assets/AssetLocation.hpp +++ b/engine/src/assets/AssetLocation.hpp @@ -51,18 +51,43 @@ namespace nexo::assets { return *this; } + /** + * @brief Sets the asset path. + * + * Assigns the given path string to the asset location. + * + * @param path The new asset path. + * @return A reference to this AssetLocation instance for chaining. + */ AssetLocation& setPath(const std::string& path) { _path = path; return *this; } + /** + * @brief Sets the asset's pack name. + * + * Assigns the provided pack name to the current asset location and returns a reference to + * the modified object, allowing for method chaining. + * + * @param packName The pack name to associate with the asset. + * @return AssetLocation& Reference to the updated AssetLocation. + */ AssetLocation& setPackName(const AssetPackName& packName) { _packName = packName; return *this; } + /** + * @brief Clears the pack name associated with the asset. + * + * Resets the pack name, effectively marking the asset as not belonging to any pack. + * Returns a reference to the current instance to facilitate method chaining. + * + * @return AssetLocation& A reference to the current AssetLocation instance. + */ AssetLocation& clearPackName() { _packName.reset(); @@ -108,6 +133,18 @@ namespace nexo::assets { const std::optional>& packName = std::nullopt ); + /** + * @brief Parses and sets the asset's location from a full location string. + * + * Extracts the asset name, path, and optional pack name from the provided string and updates + * the corresponding internal members. The expected format is "packName::name@path" or "name@path" if + * no pack name is included. If the extracted asset name is invalid, an InvalidAssetLocation + * exception is thrown. + * + * @param fullLocation Full asset location string. + * + * @throws InvalidAssetLocation if the asset name in the provided string is invalid. + */ void setLocation(const std::string& fullLocation) { std::string extractedPackName; @@ -126,11 +163,29 @@ namespace nexo::assets { _path = extractedPath; } + /** + * @brief Compares two AssetLocation objects for equality. + * + * Determines if this AssetLocation has the same name, pack name, and path as the given object. + * + * @param assetLocation The asset location to compare with. + * @return true if both asset locations contain equivalent values; false otherwise. + */ bool operator==(const AssetLocation& assetLocation) const { return _name == assetLocation._name && _packName == assetLocation._packName && _path == assetLocation._path; } + /** + * @brief Compares the current asset location with a full location string. + * + * Parses the provided full location string into its asset name, path, and pack name components and + * compares them with the object's corresponding values. Returns true if all components match, indicating + * that the asset location is equivalent to the provided string. + * + * @param fullLocation The full asset location string, expected to follow the format "packName::name@path". + * @return true if the extracted asset name, pack name, and path match those of this asset location; false otherwise. + */ bool operator==(const std::string& fullLocation) const { std::string extractedPackName;