From 3496f6147b172aa721a984275c3b6871462c7c95 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 10:37:21 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20Add=20docstrings=20to=20`feat/as?= =?UTF-8?q?set-back`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docstrings generation was requested by @Thyodas. * https://github.com/NexoEngine/game-engine/pull/63#issuecomment-2757460087 The following files were modified: * `editor/main.cpp` * `editor/src/DocumentWindows/AssetManagerWindow.cpp` * `editor/src/Editor.cpp` * `editor/src/Editor.hpp` * `editor/src/backends/ImGuiBackend.cpp` * `engine/src/assets/Asset.hpp` * `engine/src/assets/AssetCatalog.cpp` * `engine/src/assets/AssetCatalog.hpp` * `engine/src/assets/AssetImporter.cpp` * `engine/src/assets/AssetImporter.hpp` * `engine/src/assets/AssetImporterBase.hpp` * `engine/src/assets/AssetImporterContext.cpp` * `engine/src/assets/AssetImporterContext.hpp` * `engine/src/assets/AssetLocation.cpp` * `engine/src/assets/AssetLocation.hpp` * `engine/src/assets/AssetRef.hpp` * `engine/src/assets/Assets/Model/Model.hpp` * `engine/src/assets/Assets/Model/ModelImporter.hpp` * `engine/src/assets/Assets/Texture/Texture.hpp` * `engine/src/assets/Assets/Texture/TextureImporter.hpp` * `engine/src/assets/FilenameValidator.hpp` * `engine/src/assets/ValidatedName.hpp` * `engine/src/renderer/Renderer2D.cpp` * `engine/src/renderer/Texture.cpp` * `engine/src/renderer/opengl/OpenGlBuffer.hpp` * `engine/src/renderer/opengl/OpenGlTexture2D.cpp` * `engine/src/renderer/opengl/OpenGlTexture2D.hpp` * `tests/test_main.cpp` --- editor/main.cpp | 9 + .../DocumentWindows/AssetManagerWindow.cpp | 75 ++++++++ editor/src/Editor.cpp | 12 ++ editor/src/Editor.hpp | 38 +++- editor/src/backends/ImGuiBackend.cpp | 10 + engine/src/assets/Asset.hpp | 116 +++++++++++- engine/src/assets/AssetCatalog.cpp | 55 ++++++ engine/src/assets/AssetCatalog.hpp | 46 ++++- engine/src/assets/AssetImporter.cpp | 71 ++++++++ engine/src/assets/AssetImporter.hpp | 68 ++++++- engine/src/assets/AssetImporterBase.hpp | 23 ++- engine/src/assets/AssetImporterContext.cpp | 42 +++++ engine/src/assets/AssetImporterContext.hpp | 43 ++++- engine/src/assets/AssetLocation.cpp | 9 + engine/src/assets/AssetLocation.hpp | 66 +++++-- engine/src/assets/AssetRef.hpp | 113 ++++++++++-- engine/src/assets/Assets/Model/Model.hpp | 16 +- .../src/assets/Assets/Model/ModelImporter.hpp | 36 +++- engine/src/assets/Assets/Texture/Texture.hpp | 14 +- .../assets/Assets/Texture/TextureImporter.hpp | 55 +++++- engine/src/assets/FilenameValidator.hpp | 11 ++ engine/src/assets/ValidatedName.hpp | 172 ++++++++++++++++-- engine/src/renderer/Renderer2D.cpp | 37 ++++ engine/src/renderer/Texture.cpp | 37 ++++ engine/src/renderer/opengl/OpenGlBuffer.hpp | 9 +- .../src/renderer/opengl/OpenGlTexture2D.cpp | 73 ++++++++ .../src/renderer/opengl/OpenGlTexture2D.hpp | 18 +- tests/test_main.cpp | 13 +- 28 files changed, 1206 insertions(+), 81 deletions(-) diff --git a/editor/main.cpp b/editor/main.cpp index 51228e882..37dbca758 100644 --- a/editor/main.cpp +++ b/editor/main.cpp @@ -23,6 +23,15 @@ #include #include +/** + * @brief Entry point for the Nexo Editor application. + * + * Initializes logging, registers editor windows (including the default scene, scene tree, inspector, console, material inspector, and asset manager), sets up the default scene if available, and starts the main loop that handles rendering and updating the editor at roughly 60 FPS. Upon exit or in case of an exception, the editor is properly shut down. + * + * @param argc Number of command-line arguments. + * @param argv Array of command-line argument strings. + * @return int Returns 0 if the application exits normally; returns 1 if an exception is caught. + */ int main(int argc, char **argv) { try { diff --git a/editor/src/DocumentWindows/AssetManagerWindow.cpp b/editor/src/DocumentWindows/AssetManagerWindow.cpp index 0035db50d..bf437e0e1 100644 --- a/editor/src/DocumentWindows/AssetManagerWindow.cpp +++ b/editor/src/DocumentWindows/AssetManagerWindow.cpp @@ -23,6 +23,13 @@ namespace nexo::editor { + /** + * @brief Initializes the asset manager by registering and importing default assets. + * + * Retrieves the global asset catalog, registers a default model asset, and imports additional + * assets from filesystem paths. Specifically, it imports a scene model from a GLTF file and a texture + * from a PNG file using an AssetImporter, associating them with predefined asset locations. + */ void AssetManagerWindow::setup() { auto& catalog = assets::AssetCatalog::getInstance(); @@ -46,9 +53,20 @@ namespace nexo::editor { } } + /** + * @brief Performs cleanup operations for the Asset Manager. + * + * This function is intended for releasing resources and performing any necessary cleanup + * when the Asset Manager is no longer needed. Currently, it does not contain any implementation. + */ void AssetManagerWindow::shutdown() { } + /** + * @brief Displays the Asset Manager window interface. + * + * Sets the initial window size on first use and opens the asset manager window. If the window is successfully opened, this function draws the menu bar, calculates layout parameters based on the current content region width, and renders the grid of assets. If the window fails to open, the function exits early. + */ void AssetManagerWindow::show() { ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver); if (!ImGui::Begin("Asset Manager", nullptr, ImGuiWindowFlags_MenuBar)) { @@ -66,10 +84,24 @@ namespace nexo::editor { ImGui::End(); } + /** + * @brief Performs per-frame update operations for the asset manager. + * + * Currently a placeholder, this function can be extended to implement any + * update logic required by the asset manager during runtime. + */ void AssetManagerWindow::update() { // Update logic if necessary } + /** + * @brief Computes layout parameters for displaying asset items. + * + * Calculates the number of columns, item dimensions, and spacing for the asset grid based on the available width. + * Also updates the UI color settings for thumbnails and titles using current ImGui theme colors. + * + * @param availWidth The available width for laying out the asset grid. + */ void AssetManagerWindow::calculateLayout(float availWidth) { // Sizes m_layout.size.columnCount = std::max(static_cast(availWidth / (m_layout.size.iconSize + m_layout.size.iconSpacing)), 1); @@ -92,6 +124,12 @@ namespace nexo::editor { m_layout.color.titleText = ImGui::GetColorU32(ImGuiCol_Text); } + /** + * @brief Renders the menu bar to adjust asset icon layout options. + * + * This method creates an ImGui menu bar with an "Options" menu that includes sliders for modifying + * the asset icon size (ranging from 32 to 128 pixels) and the spacing between icons (0 to 32 units). + */ void AssetManagerWindow::drawMenuBar() { if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenu("Options")) { @@ -103,6 +141,12 @@ namespace nexo::editor { } } + /** + * @brief Renders a grid of asset thumbnails. + * + * Retrieves all assets from the asset catalog and calculates each asset's on-screen position based on the current layout settings. + * Utilizes ImGui's list clipper to efficiently process only the visible range of assets, and calls drawAsset() to draw each asset. + */ void AssetManagerWindow::drawAssetsGrid() { ImVec2 startPos = ImGui::GetCursorScreenPos(); @@ -124,6 +168,17 @@ namespace nexo::editor { clipper.End(); } + /** + * @brief Renders an individual asset in the asset grid. + * + * This function displays an asset by drawing its background, selection border (if selected), thumbnail, type overlay, and title. + * It also sets up an invisible button to handle selection input and shows a tooltip with the asset's full location on hover. The asset is rendered only if it is valid. + * + * @param asset A reference to the asset to render. The asset is locked to verify its validity. + * @param index The asset's index in the grid, used to manage its unique identification and selection state. + * @param itemPos The screen coordinates corresponding to the top-left corner of the asset's drawing area. + * @param itemSize The dimensions of the asset's drawing area. + */ void AssetManagerWindow::drawAsset(const assets::GenericAssetRef& asset, int index, const ImVec2& itemPos, const ImVec2& itemSize) { auto assetData = asset.lock(); if (!assetData) @@ -187,6 +242,17 @@ namespace nexo::editor { } + /** + * @brief Updates the asset selection state based on user input modifiers. + * + * This function modifies the selection state for an asset by evaluating current keyboard modifiers: + * - **Ctrl**: Toggles the selection state of the asset at the specified index. + * - **Shift**: Selects a range of assets from the most recently selected asset to the specified index. + * - **No modifier**: Clears existing selections and selects only the asset at the specified index. + * + * @param index The index of the asset being modified. + * @param isSelected Indicates whether the asset is currently selected (true) or not (false). + */ void AssetManagerWindow::handleSelection(int index, bool isSelected) { LOG(NEXO_INFO, "Asset {} {}", index, isSelected ? "deselected" : "selected"); @@ -212,6 +278,15 @@ namespace nexo::editor { } } + /** + * @brief Returns the overlay color associated with a given asset type. + * + * This function maps asset types to specific overlay colors for UI visualization. + * It returns a red-tinted color for textures, a green-tinted color for models, and a fully transparent color for any other type. + * + * @param type The asset type for which the overlay color is determined. + * @return ImU32 The corresponding overlay color in ImGui's 32-bit unsigned integer format. + */ ImU32 AssetManagerWindow::getAssetTypeOverlayColor(assets::AssetType type) const { switch (type) { case assets::AssetType::TEXTURE: return IM_COL32(200, 70, 70, 255); diff --git a/editor/src/Editor.cpp b/editor/src/Editor.cpp index ff7634695..901658b77 100644 --- a/editor/src/Editor.cpp +++ b/editor/src/Editor.cpp @@ -197,6 +197,18 @@ namespace nexo::editor { } } + /** + * @brief Configures and renders the docking layout for the editor's UI. + * + * Constructs a dockspace layout using ImGui's DockBuilder API by partitioning the main viewport into designated regions + * for core editor windows such as "Default scene", "Console", "Scene Tree", "Inspector", "Material Inspector", and "Asset Manager". + * If the dockspace has not been built yet, the layout is created by splitting the viewport into subnodes with preset ratios, + * and docking each window into its corresponding node. On subsequent calls, if the registry has not been filled, the function + * updates the docking IDs from configuration. + * + * @note The layout is built only once per session and cached via an internal flag. It also sets a global docking ID for the + * Material Inspector used elsewhere in the application. + */ void Editor::buildDockspace() { const ImGuiViewport* viewport = ImGui::GetMainViewport(); diff --git a/editor/src/Editor.hpp b/editor/src/Editor.hpp index 69e7901f4..acd9c9da0 100644 --- a/editor/src/Editor.hpp +++ b/editor/src/Editor.hpp @@ -29,21 +29,49 @@ namespace nexo::editor { class Editor { private: - // Singleton: private constructor and destructor + /** + * @brief Private default constructor for the Editor singleton. + * + * This constructor is private and defaulted to enforce the Singleton design pattern, + * ensuring that only one instance of the Editor exists. + */ Editor() = default; - ~Editor() = default; + /** + * @brief Default destructor for the Editor class. + * + * Relies on the compiler-generated destructor to clean up the Editor instance. + */ +~Editor() = default; public: - // Singleton: Meyers' Singleton Pattern + /** + * @brief Retrieves the singleton instance of the Editor. + * + * Implements Meyers' Singleton pattern to ensure that only one instance of the + * Editor class is created and accessed throughout the application lifecycle. The + * instance is lazily initialized on first use. + * + * @return Editor& Reference to the singleton instance. + */ static Editor& getInstance() { static Editor s_instance; return s_instance; } - // Singleton: delete copy constructor and assignment operator + /** + * @brief Deleted copy constructor. + * + * Prevents copying of the Editor instance to enforce the singleton pattern. + */ Editor(Editor const&) = delete; - void operator=(Editor const&) = delete; + /** + * @brief Deleted copy assignment operator for the Editor singleton. + * + * The assignment operator is explicitly deleted to prevent copying or reassigning the Editor instance, + * thereby enforcing the singleton design pattern. + */ +void operator=(Editor const&) = delete; /** * @brief Initializes the editor. diff --git a/editor/src/backends/ImGuiBackend.cpp b/editor/src/backends/ImGuiBackend.cpp index 31ac39280..e08c066e0 100644 --- a/editor/src/backends/ImGuiBackend.cpp +++ b/editor/src/backends/ImGuiBackend.cpp @@ -65,6 +65,16 @@ namespace nexo::editor { THROW_EXCEPTION(BackendRendererApiNotSupported, "UNKNOWN"); } + /** + * @brief Sets the ImGui error callback for the specified window. + * + * Retrieves the error callback from the OpenGL backend and assigns it to the provided window. + * Throws a BackendRendererApiNotSupported exception if the underlying graphics API is not OpenGL. + * + * @param window A shared pointer to the window on which to set the error callback. + * + * @throws BackendRendererApiNotSupported if the graphics API is not supported. + */ void ImGuiBackend::setErrorCallback([[maybe_unused]] const std::shared_ptr &window) { #ifdef GRAPHICS_API_OPENGL diff --git a/engine/src/assets/Asset.hpp b/engine/src/assets/Asset.hpp index d9d4f35e0..6c8ef1e7c 100644 --- a/engine/src/assets/Asset.hpp +++ b/engine/src/assets/Asset.hpp @@ -141,16 +141,62 @@ namespace nexo::assets { friend class AssetCatalog; friend class AssetImporter; public: - //IAsset() = delete; + /** + * @brief Default virtual destructor for the IAsset interface. + * + * Ensures proper cleanup of derived asset objects. + */ virtual ~IAsset() = default; - [[nodiscard]] virtual const AssetMetadata& getMetadata() const { return m_metadata; } - [[nodiscard]] virtual AssetType getType() const { return getMetadata().type; } - [[nodiscard]] virtual AssetID getID() const { return getMetadata().id; } - [[nodiscard]] virtual AssetStatus getStatus() const { return getMetadata().status; } + /** + * @brief Retrieves the metadata associated with the asset. + * + * Returns a constant reference to the asset's metadata, which includes information such as its type, status, reference count, unique identifier, and location. + * + * @return const AssetMetadata& A constant reference to the asset metadata. + */ +[[nodiscard]] virtual const AssetMetadata& getMetadata() const { return m_metadata; } + /** + * @brief Retrieves the asset's type. + * + * This method returns the type of the asset as specified in its metadata. + * + * @return AssetType The type of the asset. + */ +[[nodiscard]] virtual AssetType getType() const { return getMetadata().type; } + /** + * @brief Retrieves the unique identifier of the asset. + * + * This function returns the asset's identifier from its metadata. + * + * @return AssetID The unique identifier associated with the asset. + */ +[[nodiscard]] virtual AssetID getID() const { return getMetadata().id; } + /** + * @brief Retrieves the current status of the asset. + * + * This function returns the asset's current status by extracting it from the asset's metadata. + * + * @return AssetStatus The current state of the asset. + */ +[[nodiscard]] virtual AssetStatus getStatus() const { return getMetadata().status; } - [[nodiscard]] virtual bool isLoaded() const { return getStatus() == AssetStatus::LOADED; } - [[nodiscard]] virtual bool isErrored() const { return getStatus() == AssetStatus::ERROR; } + /** + * @brief Checks if the asset is loaded. + * + * This method returns true if the asset's current status equals AssetStatus::LOADED, indicating that its data has been successfully loaded. + * + * @return true if the asset is loaded; false otherwise. + */ +[[nodiscard]] virtual bool isLoaded() const { return getStatus() == AssetStatus::LOADED; } + /** + * @brief Checks if the asset is in an error state. + * + * Compares the asset's current status to AssetStatus::ERROR to determine if an error has occurred. + * + * @return true if the asset's status is AssetStatus::ERROR, otherwise false. + */ +[[nodiscard]] virtual bool isErrored() const { return getStatus() == AssetStatus::ERROR; } /** * @brief Get the asset data pointer @@ -165,6 +211,16 @@ namespace nexo::assets { */ virtual IAsset& setRawData(void* rawData) = 0; protected: + /** + * @brief Constructs an IAsset with default metadata settings. + * + * Initializes the asset's metadata with predefined default values: + * - **type**: set to AssetType::UNKNOWN. + * - **status**: set to AssetStatus::UNLOADED. + * - **referenceCount**: initialized to 0. + * - **id**: set to a nil UUID. + * - **location**: set to "default". + */ explicit IAsset() : m_metadata({ .type = AssetType::UNKNOWN, @@ -209,11 +265,25 @@ namespace nexo::assets { TAssetData *data; - // Implementation of IAsset virtual methods + /** + * @brief Retrieves the raw asset data. + * + * Returns a pointer to the underlying memory storing the asset's data. + * + * @return void* A pointer to the raw asset data. + */ [[nodiscard]] void* getRawData() const override { return data; } + /** + * @brief Updates the asset's raw data pointer. + * + * This method deletes the current asset data before assigning a new raw data pointer. It casts the provided pointer to the asset's specific data type and updates the asset's status accordingly: if the pointer is null, the asset is marked as UNLOADED; otherwise, it is marked as LOADED. + * + * @param rawData Pointer to the new asset data. + * @return IAsset& Reference to the current asset instance. + */ IAsset& setRawData(void* rawData) override { delete data; // Clean up existing data if (rawData == nullptr) { @@ -226,10 +296,27 @@ namespace nexo::assets { return *this; } + /** + * @brief Retrieves the asset's raw data. + * + * Returns the pointer to the underlying asset data. This pointer can be used + * to access or update the asset's stored data. + * + * @return Pointer to the asset's data. + */ [[nodiscard]] TAssetData* getData() const { return data; } + /** + * @brief Replaces the asset's current data with new data. + * + * Deletes the existing data and assigns the provided pointer, transferring ownership. + * The asset's status is updated to UNLOADED if the new data pointer is null, or to LOADED otherwise. + * + * @param newData Pointer to the new asset data. + * @return Asset& Reference to the updated asset instance. + */ Asset& setData(TAssetData* newData) { delete data; if (newData == nullptr) { @@ -242,11 +329,24 @@ namespace nexo::assets { } protected: + /** + * @brief Constructs an asset with no initial data. + * + * Initializes the asset's data pointer to nullptr and sets the asset's metadata type to the + * value specified by the TAssetType template parameter. + */ explicit Asset() : data(nullptr) { m_metadata.type = TAssetType; } + /** + * @brief Constructs an asset with the specified raw data. + * + * Initializes the asset using the provided data pointer, sets its type based on the template parameter, and marks the asset as loaded. + * + * @param data Pointer to the raw asset data. + */ explicit Asset(TAssetData* data) : data(data) { m_metadata.type = TAssetType; diff --git a/engine/src/assets/AssetCatalog.cpp b/engine/src/assets/AssetCatalog.cpp index 62b861e6d..e67f96899 100644 --- a/engine/src/assets/AssetCatalog.cpp +++ b/engine/src/assets/AssetCatalog.cpp @@ -18,6 +18,14 @@ namespace nexo::assets { + /** + * @brief Removes an asset from the catalog by its identifier. + * + * If an asset with the specified AssetID exists, it is removed from the asset collection. + * If no such asset exists, the function does nothing. + * + * @param id The unique identifier of the asset to remove. + */ void AssetCatalog::deleteAsset(AssetID id) { if (!m_assets.contains(id)) @@ -25,6 +33,14 @@ namespace nexo::assets { m_assets.erase(id); } + /** + * @brief Deletes an asset using its generic reference. + * + * Attempts to lock the provided asset reference to access the underlying asset data. + * If successful, retrieves the asset's ID and deletes the asset by invoking the ID-based deletion method. + * + * @param asset A generic reference to the asset to be deleted. + */ void AssetCatalog::deleteAsset(const GenericAssetRef& asset) { if (const auto assetData = asset.lock()) { @@ -32,6 +48,15 @@ namespace nexo::assets { } } + /** + * @brief Retrieves an asset from the catalog by its ID. + * + * Checks if an asset with the specified ID exists in the catalog and returns a reference + * to it. If the asset is not found, a null reference is returned. + * + * @param id The unique identifier of the asset. + * @return GenericAssetRef A reference to the asset if found; otherwise, a null reference. + */ GenericAssetRef AssetCatalog::getAsset(AssetID id) const { if (!m_assets.contains(id)) @@ -39,6 +64,16 @@ namespace nexo::assets { return GenericAssetRef(m_assets.at(id)); } + /** + * @brief Retrieves an asset that matches the specified location. + * + * Iterates over the catalog's assets and returns a reference to the first asset whose metadata + * location is equal to the provided location. If no matching asset is found, a null asset reference + * is returned. + * + * @param location The location identifier to search for. + * @return GenericAssetRef A reference to the asset with the matching location, or a null reference if not found. + */ GenericAssetRef AssetCatalog::getAsset(const AssetLocation& location) const { // TODO: implement a tree for folders and assets instead of doing O(n) search @@ -49,6 +84,13 @@ namespace nexo::assets { return GenericAssetRef::null(); } + /** + * @brief Retrieves all asset references from the catalog. + * + * Iterates over the stored assets and compiles them into a vector, returning a reference to each asset. + * + * @return std::vector A vector containing references to all assets in the catalog. + */ std::vector AssetCatalog::getAssets() const { std::vector assets; @@ -58,6 +100,19 @@ namespace nexo::assets { return assets; } + /** + * @brief Registers an asset with the specified location. + * + * Associates an asset with a given location and ensures it has a unique identifier. If the asset's identifier is not set, + * the function generates a new UUID. The asset is then added to the internal catalog. If the asset pointer is null, + * this function returns a null asset reference. + * + * @param location The metadata location to assign to the asset. + * @param asset Pointer to the asset to register. + * @return GenericAssetRef A reference to the registered asset, or a null reference if the asset pointer is null. + * + * @note Duplicate asset handling is not implemented yet. + */ GenericAssetRef AssetCatalog::registerAsset(const AssetLocation& location, IAsset* asset) { if (!asset) diff --git a/engine/src/assets/AssetCatalog.hpp b/engine/src/assets/AssetCatalog.hpp index 1cb7424e7..4153c227f 100644 --- a/engine/src/assets/AssetCatalog.hpp +++ b/engine/src/assets/AssetCatalog.hpp @@ -49,16 +49,34 @@ namespace nexo::assets { ~AssetCatalog() = default; public: - // Singleton: Meyers' Singleton Pattern + /** + * @brief Retrieves the singleton instance of AssetCatalog. + * + * Implements Meyers' Singleton pattern to ensure only one instance of AssetCatalog exists, + * providing a global access point for asset management. + * + * @return AssetCatalog& A reference to the singleton AssetCatalog instance. + */ static AssetCatalog& getInstance() { static AssetCatalog s_instance; return s_instance; } - // Singleton: delete copy constructor and assignment operator + /** + * @brief Deleted copy constructor to enforce the singleton pattern. + * + * This constructor is explicitly deleted to prevent copying of the AssetCatalog instance, + * ensuring that only a single instance exists. + */ AssetCatalog(AssetCatalog const&) = delete; - void operator=(AssetCatalog const&) = delete; + /** + * @brief Deleted copy assignment operator. + * + * This operator is explicitly deleted to prevent assignment of the singleton instance, + * thereby ensuring that only one instance of AssetCatalog exists. + */ +void operator=(AssetCatalog const&) = delete; /** * @brief Removes the asset associated with the given ID from the catalog. @@ -156,6 +174,17 @@ namespace nexo::assets { template requires std::derived_from + /** + * @brief Retrieves all assets of a specified type. + * + * @tparam AssetType The asset type to filter by (must derive from IAsset). + * + * This function iterates over all assets registered in the catalog and collects those + * whose runtime type identifier matches AssetType::TYPE. Note that the type + * filtering logic is currently a placeholder and is not fully implemented. + * + * @return A vector of asset references cast to AssetType. + */ std::vector> AssetCatalog::getAssetsOfType() const { // TODO: AssetType::TYPE is not a thing, need to find a way to get the type of the asset @@ -169,6 +198,17 @@ namespace nexo::assets { } template requires std::derived_from + /** + * @brief Retrieves a view of assets filtered and cast to the specified asset type. + * + * This function returns a view over the catalog's assets, filtering them based on a type comparison + * with AssetType::TYPE and then transforming the asset pointers to std::shared_ptr. + * Note that the filtering mechanism is not fully implemented and is marked by a static assertion. + * + * @tparam AssetType The asset subtype to filter and cast to. Must be derived from IAsset. + * + * @return A view over assets as shared pointers of the specified type. + */ std::ranges::view auto AssetCatalog::getAssetsOfTypeView() const { // TODO: AssetType::TYPE is not a thing, need to find a way to get the type of the asset diff --git a/engine/src/assets/AssetImporter.cpp b/engine/src/assets/AssetImporter.cpp index 9c067d3bb..9046a17b3 100644 --- a/engine/src/assets/AssetImporter.cpp +++ b/engine/src/assets/AssetImporter.cpp @@ -20,12 +20,25 @@ #include "Assets/Texture/TextureImporter.hpp" namespace nexo::assets { + /** + * @brief Constructs an AssetImporter and registers default asset importers. + * + * This constructor registers a TextureImporter for Texture assets with a priority of 100 + * and a ModelImporter for Model assets with a priority of 90, ensuring that these asset types + * have dedicated importers available for asset processing. + */ AssetImporter::AssetImporter() { registerImporter(100); registerImporter(90); } + /** + * @brief Destroys the AssetImporter instance and cleans up all registered importers. + * + * Iterates over the registered importer collections and deletes each dynamically + * allocated asset importer to free memory. + */ AssetImporter::~AssetImporter() { for (auto& importers: m_importers | std::views::values) { @@ -35,6 +48,17 @@ namespace nexo::assets { } } + /** + * @brief Attempts to automatically import an asset using registered importers. + * + * This function iterates over all lists of importers registered in the internal registry. For each list, + * it calls the importAssetTryImporters method to try and import the asset using the provided location and input data. + * It returns the first successfully imported asset, or a null asset reference if no importer is able to perform the import. + * + * @param location The location information identifying the asset to be imported. + * @param inputVariant The input data required for asset import. + * @return GenericAssetRef A reference to the imported asset, or a null reference if the import fails. + */ GenericAssetRef AssetImporter::importAssetAuto(const AssetLocation& location, const ImporterInputVariant& inputVariant) { for (const auto& importers: m_importers | std::views::values) { @@ -46,6 +70,19 @@ namespace nexo::assets { return GenericAssetRef::null(); } + /** + * @brief Imports an asset using the specified importer. + * + * Sets up an asset importer context—using a custom context if available or a temporary one otherwise—and delegates + * the import operation to the given importer. If the import is successful, the asset's metadata is updated by assigning + * a new unique identifier if needed and replacing a default location with the provided one before the asset is registered + * in the asset catalog. + * + * @param location The location where the asset is expected to be found. + * @param inputVariant The input data variant used for importing the asset. + * @param importer The asset importer instance to perform the import operation. + * @return GenericAssetRef A reference to the registered asset, or a null reference if the import fails. + */ GenericAssetRef AssetImporter::importAssetUsingImporter(const AssetLocation& location, const ImporterInputVariant& inputVariant, AssetImporterBase* importer) const { @@ -70,6 +107,16 @@ namespace nexo::assets { return AssetCatalog::getInstance().registerAsset(location, asset); } + /** + * @brief Attempts to import an asset by trying a list of importers. + * + * This function first iterates over the provided importers and uses those that are compatible with the given input variant (i.e., their `canRead()` method returns true) to try importing the asset via `importAssetUsingImporter()`. If none of the compatible importers successfully import the asset, it retries with the remaining, originally incompatible importers. It returns the first successfully imported asset, or a null reference if all attempts fail. + * + * @param location The location descriptor of the asset to import. + * @param inputVariant The input data variant used by the importers to read the asset. + * @param importers A list of asset importers to attempt for the import. + * @return A reference to the successfully imported asset, or a null reference if the import fails. + */ GenericAssetRef AssetImporter::importAssetTryImporters(const AssetLocation& location, const ImporterInputVariant& inputVariant, const std::vector& importers) const { @@ -92,6 +139,15 @@ namespace nexo::assets { return GenericAssetRef::null(); } + /** + * @brief Retrieves the asset importers registered for a specific asset type. + * + * Returns a constant reference to a vector containing pointers to importers associated with the given type index. + * If no importers are registered for the specified type, an empty vector is returned. + * + * @param typeIdx The type index representing the asset type. + * @return const std::vector& A reference to the vector of importers for the given type. + */ const std::vector& AssetImporter:: getImportersForType(const std::type_index& typeIdx) const { @@ -102,12 +158,27 @@ namespace nexo::assets { return m_importers.at(typeIdx); } + /** + * @brief Determines if there are any registered importers for a given asset type. + * + * Searches the internal importer registry for the specified type index and checks that the associated importer list is not empty. + * + * @param typeIdx The type index identifying the asset type. + * @return true if at least one importer is registered for the specified asset type, false otherwise. + */ bool AssetImporter::hasImportersForType(const std::type_index& typeIdx) const { const auto it = m_importers.find(typeIdx); return (it != m_importers.end() && !it->second.empty()); } + /** + * @brief Unregisters all asset importers for the specified asset type. + * + * Removes both the importers and their associated details corresponding to the provided type index. + * + * @param typeIdx The type index identifying the asset type to unregister. + */ void AssetImporter::unregisterAllImportersForType(const std::type_index& typeIdx) { m_importers.erase(typeIdx); diff --git a/engine/src/assets/AssetImporter.hpp b/engine/src/assets/AssetImporter.hpp index 7d57b264c..95f2aef47 100644 --- a/engine/src/assets/AssetImporter.hpp +++ b/engine/src/assets/AssetImporter.hpp @@ -135,7 +135,15 @@ namespace nexo::assets { */ [[nodiscard]] bool hasImportersForType(const std::type_index& typeIdx) const; - void setCustomContext(AssetImporterContext *ctx) { m_customCtx = ctx; } + /** + * @brief Sets the custom asset importing context. + * + * This function assigns a custom context to the asset importer, which is subsequently + * used during asset import operations. + * + * @param ctx Pointer to the custom AssetImporterContext. + */ +void setCustomContext(AssetImporterContext *ctx) { m_customCtx = ctx; } /** * @brief Clears the custom context. @@ -237,6 +245,15 @@ namespace nexo::assets { template requires std::derived_from && std:: derived_from + /** + * @brief Registers an importer for a specified asset type. + * + * This template method instantiates a new importer of type ImporterType and registers it for the asset type + * AssetType with the given priority. The registration is delegated to the alternative overload that accepts + * an importer pointer. + * + * @param priority The priority level for registering the importer. + */ void AssetImporter::registerImporter(int priority) { auto importer = new ImporterType(); @@ -244,6 +261,17 @@ namespace nexo::assets { } template requires std::derived_from + /** + * @brief Registers an importer for a specific asset type. + * + * This method adds the provided importer instance to the registry for the asset type specified by the template parameter. + * The importer is inserted in a list that is maintained in descending order of priority, ensuring that importers with + * higher priorities are considered before those with lower ones. + * + * @tparam AssetType The asset type that the importer supports. + * @param importer Pointer to the importer instance to register. + * @param priority The priority of the importer; higher values indicate higher precedence. + */ void AssetImporter::registerImporter(AssetImporterBase *importer, const int priority) { const auto typeIdx = std::type_index(typeid(AssetType)); @@ -265,6 +293,18 @@ namespace nexo::assets { } template requires std::derived_from + /** + * @brief Imports an asset of the specified type from a given location. + * + * Retrieves all registered importers for the asset type and attempts to import the asset + * using a prioritized trial of these importers. If no importers are registered for the asset type, + * it logs an error and returns a null asset reference. + * + * @tparam AssetType The type of asset to import. + * @param location The asset's location information. + * @param inputVariant Supplementary data guiding the import process. + * @return An AssetRef referencing the imported asset, or a null reference if no suitable importer is found. + */ AssetRef AssetImporter::importAsset(const AssetLocation& location, const ImporterInputVariant& inputVariant) { @@ -277,6 +317,15 @@ namespace nexo::assets { } template requires std::derived_from + /** + * @brief Retrieves the importers registered for the specified asset type. + * + * This templated method computes the type index for AssetType and returns the corresponding vector + * of associated asset importer pointers by delegating to the overload that accepts a std::type_index. + * + * @tparam AssetType The asset type for which to obtain the registered importers. + * @return const std::vector& A reference to the vector containing pointers to importers for AssetType. + */ const std::vector& AssetImporter::getImportersForType() const { const auto typeIdx = std::type_index(typeid(AssetType)); @@ -285,6 +334,15 @@ namespace nexo::assets { } template requires std::derived_from + /** + * @brief Determines whether there are any registered importers for the specified asset type. + * + * This templated method creates a type index for the given @c AssetType and checks the internal importer + * registry to see if any importers are registered for that asset type. + * + * @tparam AssetType The type of asset to verify importers for. + * @return true if at least one importer is registered for @c AssetType, false otherwise. + */ bool AssetImporter::hasImportersForType() const { const auto typeIdx = std::type_index(typeid(AssetType)); @@ -292,6 +350,14 @@ namespace nexo::assets { } template requires std::derived_from + /** + * @brief Unregisters all importers for the specified asset type. + * + * This templated function determines the type index of the provided AssetType and delegates + * the unregistration of all associated importers to the corresponding overload. + * + * @tparam AssetType The asset type for which all importers are to be unregistered. + */ void AssetImporter::unregisterAllImportersForType() { const auto typeIdx = std::type_index(typeid(AssetType)); diff --git a/engine/src/assets/AssetImporterBase.hpp b/engine/src/assets/AssetImporterBase.hpp index 4177de4b7..0d18d7117 100644 --- a/engine/src/assets/AssetImporterBase.hpp +++ b/engine/src/assets/AssetImporterBase.hpp @@ -29,8 +29,18 @@ namespace nexo::assets { */ class AssetImporterBase { public: - AssetImporterBase() = default; - virtual ~AssetImporterBase() = default; + /** + * @brief Default constructor for AssetImporterBase. + * + * Constructs a new AssetImporterBase object. + */ +AssetImporterBase() = default; + /** + * @brief Virtual destructor for AssetImporterBase. + * + * Defined as default to ensure that derived asset importer classes are properly cleaned up. + */ +virtual ~AssetImporterBase() = default; /** * @brief Checks if the importer can read the file at the given path. @@ -52,12 +62,13 @@ namespace nexo::assets { virtual void importImpl(AssetImporterContext& ctx) = 0; /** - * @brief Imports an asset from a file. + * @brief Wraps the asset import operation with error handling. * - * This method is not intended to be overridden. Implement importImpl() to do the import. - * This method is a wrapper of importImpl() that for example catches exceptions thrown by importImpl(). + * This method calls the asset-specific import implementation (importImpl()) to perform the asset import and verifies + * that the main asset data is set in the provided context. It is not intended to be overridden. If importImpl() throws + * an exception or the main asset data remains unset after the import, an error is logged. * - * @param[in,out] ctx The context for the import. + * @param[in,out] ctx The asset importer context providing the asset location and storing the imported asset data. */ void import(AssetImporterContext& ctx) noexcept { diff --git a/engine/src/assets/AssetImporterContext.cpp b/engine/src/assets/AssetImporterContext.cpp index 7cfce359e..3eb731f7c 100644 --- a/engine/src/assets/AssetImporterContext.cpp +++ b/engine/src/assets/AssetImporterContext.cpp @@ -16,31 +16,73 @@ namespace nexo::assets { + /** + * @brief Sets the main asset for the importer context. + * + * Assigns the specified asset as the main asset used within the context. + * + * @param asset Pointer to the asset to be designated as the main asset. + */ void AssetImporterContext::setMainAsset(IAsset* asset) { m_mainAsset = asset; } + /** + * @brief Retrieves the main asset from the context. + * + * Returns a pointer to the main asset currently stored in the context. + * + * @return IAsset* Pointer to the main asset, or nullptr if not set. + */ IAsset* AssetImporterContext::getMainAsset() const { return m_mainAsset; } + /** + * @brief Adds an asset dependency to the context. + * + * Appends the provided asset dependency reference to the list of dependencies managed by the importer context. + * + * @param dependency The dependency to be added. + */ void AssetImporterContext::addDependency(const GenericAssetRef& dependency) { m_dependencies.push_back(dependency); } + /** + * @brief Retrieves the list of asset dependencies. + * + * Returns a constant reference to the vector containing the asset dependencies managed by the context. + * + * @return const std::vector& Reference to the vector of dependencies. + */ const std::vector& AssetImporterContext::getDependencies() const { return m_dependencies; } + /** + * @brief Sets the JSON parameters for the asset importer context. + * + * Assigns the provided JSON object to configure the parameters used for asset importing. + * + * @param params The JSON object containing the configuration parameters. + */ void AssetImporterContext::setParameters(const nlohmann::json& params) { m_jsonParameters = params; } + /** + * @brief Retrieves the JSON parameters for the asset importer context. + * + * Returns a JSON object representing the current configuration parameters. + * + * @return A JSON object containing the parameters. + */ nlohmann::json AssetImporterContext::getParameters() const { return m_jsonParameters; diff --git a/engine/src/assets/AssetImporterContext.hpp b/engine/src/assets/AssetImporterContext.hpp index a2ce7683f..830da7cfd 100644 --- a/engine/src/assets/AssetImporterContext.hpp +++ b/engine/src/assets/AssetImporterContext.hpp @@ -38,10 +38,20 @@ namespace nexo::assets { struct AssetImporterContext { public: ImporterInputVariant input; //< Input data for the importer - AssetLocation location = AssetLocation("default"); //< Future location of the asset in the catalog + AssetLocation location = AssetLocation("default"); /** + * @brief Default constructor for AssetImporterContext. + * + * Constructs an AssetImporterContext with all members initialized to their default states, + * including setting the asset location to its default future catalog placement. + */ AssetImporterContext() = default; - ~AssetImporterContext() = default; + /** + * @brief Default destructor for AssetImporterContext. + * + * Releases resources automatically. This defaulted destructor relies on the compiler-generated implementation. + */ +~AssetImporterContext() = default; /** * @brief Set the main asset for this context @@ -126,6 +136,17 @@ namespace nexo::assets { template requires std::derived_from + /** + * @brief Generates a unique asset location for a dependency. + * + * This method constructs a candidate asset location based on the current context's location + * by appending a unique identifier. It then checks the asset catalog to ensure the candidate + * does not already exist. If a conflict is found, the method continues incrementing the identifier + * until a unique location is obtained or the maximum allowed attempts is reached. In the latter case, + * an error is logged and the most recent candidate is returned. + * + * @return AssetLocation A unique location for the dependency. + */ AssetLocation AssetImporterContext::genUniqueDependencyLocation() { auto depLoc = AssetLocation(location.getFullLocation()); @@ -147,12 +168,30 @@ namespace nexo::assets { } template requires JSONSerializable + /** + * @brief Serializes and stores importer parameters. + * + * Converts the given parameters to JSON format and stores the result for later retrieval. + * The parameter type must be JSON serializable. + * + * @tparam ParamType JSON serializable type representing the asset parameters. + * @param params The parameters to serialize and store. + */ void AssetImporterContext::setParameters(const ParamType& params) { to_json(m_jsonParameters, params); } template requires JSONSerializable + /** + * @brief Retrieves the asset importer parameters. + * + * Deserializes the internally stored JSON parameters into an object of type ParamType. + * If no parameters were set, the function returns a default-constructed instance of ParamType. + * + * @tparam ParamType The type representing the parameters, which must be JSON serializable. + * @return The asset importer parameters deserialized from JSON. + */ ParamType AssetImporterContext::getParameters() const { ParamType params; diff --git a/engine/src/assets/AssetLocation.cpp b/engine/src/assets/AssetLocation.cpp index dd47173c7..49a2dc2b2 100644 --- a/engine/src/assets/AssetLocation.cpp +++ b/engine/src/assets/AssetLocation.cpp @@ -16,6 +16,15 @@ namespace nexo::assets { + /** + * @brief Sets the asset's location. + * + * Updates the asset's internal state by assigning the provided asset name, file path, and optional asset pack name. + * + * @param name The asset's name. + * @param path The path of the asset. + * @param packName Optional reference to the asset pack name. + */ void AssetLocation::setLocation( const AssetName& name, const std::string& path, diff --git a/engine/src/assets/AssetLocation.hpp b/engine/src/assets/AssetLocation.hpp index b33e5eb47..f2c473e03 100644 --- a/engine/src/assets/AssetLocation.hpp +++ b/engine/src/assets/AssetLocation.hpp @@ -26,6 +26,17 @@ namespace nexo::assets { class InvalidAssetLocation final : public Exception { public: + /** + * @brief Constructs an exception indicating an invalid asset location. + * + * This constructor builds an InvalidAssetLocation exception by formatting an error + * message that includes the provided asset location and an explanatory message. + * It optionally takes a source location to mark where the exception is generated. + * + * @param assetLocation The invalid asset location string. + * @param message Additional context describing why the asset location is invalid. + * @param loc The source location at which the exception is thrown (defaults to the current call site). + */ explicit InvalidAssetLocation( std::string_view assetLocation, std::string_view message, @@ -40,11 +51,30 @@ namespace nexo::assets { */ class AssetLocation { public: + /** + * @brief Constructs an AssetLocation by parsing the provided full location string. + * + * This explicit constructor initializes an AssetLocation object using the given fullLocation string, + * which should include the asset name, path, and optionally the asset pack name. The parsing is + * performed by calling setLocation(fullLocation), and an InvalidAssetLocation exception is thrown + * if the asset name is invalid. + * + * @param fullLocation The complete asset location string to be parsed. + */ explicit AssetLocation(const std::string& fullLocation) { setLocation(fullLocation); } + /** + * @brief Sets the asset's name. + * + * Updates the asset's name with the provided value and returns a reference + * to the current object to facilitate method chaining. + * + * @param name The new name for the asset. + * @return Reference to the modified AssetLocation instance. + */ AssetLocation& setName(const AssetName& name) { _name = name; @@ -101,9 +131,13 @@ namespace nexo::assets { [[nodiscard]] const AssetName& getName() const { return _name; } /** - * @brief Get the asset's pack name - * @return The asset's AssetPackName - */ + * @brief Retrieves the asset's pack name. + * + * Returns an optional reference wrapper to a constant AssetPackName. If the asset is not associated + * with any pack, this function returns an empty optional. + * + * @return An optional reference to the asset's pack name. + */ [[nodiscard]] std::optional> getPackName() const { return _packName; } /** @@ -113,8 +147,11 @@ namespace nexo::assets { [[nodiscard]] const std::string& getPath() const { return _path; } /** - * @brief Get the asset's full location - * @return The asset's full location as string (e.g.: packName::name@path/to/asset) + * @brief Constructs and returns the full asset location. + * + * The full location is formatted as "packName::name@path", where the "packName::" prefix is included only if a pack name is set and the "@path" suffix is appended only when the path is non-empty. + * + * @return A string representing the asset's complete location. */ [[nodiscard]] std::string getFullLocation() const { @@ -198,14 +235,17 @@ namespace nexo::assets { } /** - * @brief Parse a full asset location string into its components - * @param fullLocation The full location string to parse - * @param extractedAssetName The extracted asset name - * @param extractedPath The extracted path - * @param extractedPackName The extracted package name - * @note This function is static and can be used to parse a full location string into its components - * @warning Does not validate the extracted names - */ + * @brief Parses a full asset location string into its constituent components. + * + * This static function divides the provided location string into an asset name, an asset path, and an optional package name based on the "::" and "@" delimiters. If "::" is present, the substring before it is assigned as the package name and removed from the string. If "@" is found in the remaining string, the substring after it is used as the asset path, and the preceding part is considered the asset name. If a delimiter is absent, the corresponding output string is cleared. + * + * @param fullLocation The full asset location string to parse. + * @param extractedAssetName Output parameter for the parsed asset name. + * @param extractedPath Output parameter for the parsed asset path. + * @param extractedPackName Output parameter for the parsed package name. + * + * @warning No validation is performed on the extracted components. + */ static void parseFullLocation( std::string_view fullLocation, std::string& extractedAssetName, diff --git a/engine/src/assets/AssetRef.hpp b/engine/src/assets/AssetRef.hpp index 5ed27c32e..bb2f6c6cf 100644 --- a/engine/src/assets/AssetRef.hpp +++ b/engine/src/assets/AssetRef.hpp @@ -43,9 +43,13 @@ namespace nexo::assets { GenericAssetRef() = default; /** - * @brief Construct from a shared_ptr to an asset - * @param ptr The shared pointer to the asset - */ + * @brief Constructs a GenericAssetRef from a shared asset pointer. + * + * Initializes the asset reference by converting the provided shared pointer into a weak pointer. + * This allows the asset's lifetime to be monitored without owning it, enabling safe retrieval via lock(). + * + * @param ptr The shared pointer to the asset. + */ explicit GenericAssetRef(const std::shared_ptr& ptr) : m_weakPtr(ptr) {} /** @@ -60,7 +64,14 @@ namespace nexo::assets { * @brief Get a shared_ptr to the referenced asset * @return A shared_ptr to the asset, or nullptr if expired */ - // ReSharper disable once CppHiddenFunction + /** + * @brief Locks the asset reference and returns a shared pointer. + * + * This function attempts to lock the weak pointer to the asset, returning a shared pointer + * if the asset is still valid. If the asset reference has expired, it returns an empty shared pointer. + * + * @return A shared pointer to the asset, or an empty pointer if the asset is not valid. + */ [[nodiscard]] std::shared_ptr lock() const noexcept { return m_weakPtr.lock(); } @@ -90,7 +101,11 @@ namespace nexo::assets { } /** - * @brief Requests the AssetCatalog to load the asset + * @brief Requests the AssetCatalog to initiate loading of the asset. + * + * If the asset reference is valid (i.e., not expired), this function is intended to trigger + * a reload or load operation via the AssetCatalog. Currently, the loading functionality + * is not implemented, and a warning is logged instead. */ void load() { if (auto ptr = lock()) { @@ -101,7 +116,13 @@ namespace nexo::assets { } /** - * @brief Requests the AssetCatalog to unload the asset but maintain the reference + * @brief Requests the AssetCatalog to unload the referenced asset while retaining the reference. + * + * If the asset is valid, this method attempts to obtain the shared pointer (using lock()) and then issues + * an unload request through the AssetCatalog. Currently, the unload operation is not implemented, so a warning + * is logged instead. + * + * @note The actual unloading functionality via AssetCatalog is pending implementation. */ void unload() { if (auto ptr = lock()) { @@ -112,12 +133,45 @@ namespace nexo::assets { } - // Standard copy/move operations + /** + * @brief Copy constructs a GenericAssetRef. + * + * Constructs a new GenericAssetRef by copying the internal state from the provided instance. + */ GenericAssetRef(const GenericAssetRef&) = default; - GenericAssetRef& operator=(const GenericAssetRef&) = default; - GenericAssetRef(GenericAssetRef&&) noexcept = default; - GenericAssetRef& operator=(GenericAssetRef&&) noexcept = default; - virtual ~GenericAssetRef() = default; + /** + * @brief Default copy assignment operator. + * + * Copies the asset reference from another GenericAssetRef instance. + * + * @param other The GenericAssetRef to copy from. + * @return A reference to this GenericAssetRef. + */ +GenericAssetRef& operator=(const GenericAssetRef&) = default; + /** + * @brief Move constructs a GenericAssetRef by transferring ownership. + * + * Constructs a new GenericAssetRef from an rvalue reference by transferring the internal asset reference. + * The moved-from object remains in a valid but unspecified state. + */ +GenericAssetRef(GenericAssetRef&&) noexcept = default; + /** + * @brief Move assignment operator for GenericAssetRef. + * + * Transfers ownership of the internal reference from another GenericAssetRef to this instance. + * This operation is noexcept and leaves the moved-from object in a valid but unspecified state. + * + * @param other The GenericAssetRef to move from. + * @return A reference to this instance. + */ +GenericAssetRef& operator=(GenericAssetRef&&) noexcept = default; + /** + * @brief Virtual destructor for GenericAssetRef. + * + * Ensures that destructors for derived classes are called correctly when deleting through a pointer + * to GenericAssetRef. + */ +virtual ~GenericAssetRef() = default; protected: std::weak_ptr m_weakPtr; @@ -154,8 +208,13 @@ namespace nexo::assets { [[nodiscard]] std::shared_ptr lock() const noexcept; /** - * @brief Checks if the asset is fully loaded - * @return true if the asset is loaded, false otherwise + * @brief Determines if the asset is fully loaded. + * + * This method locks the underlying asset reference and checks its loaded status by invoking + * the asset's own isLoaded() method. If the asset reference has expired or is invalid, the method + * returns false. + * + * @return true if the asset is valid and reported as loaded; false otherwise. */ [[nodiscard]] bool isLoaded() const { if (auto ptr = lock()) { @@ -165,8 +224,12 @@ namespace nexo::assets { } /** - * @brief Creates a null asset reference - * @return An empty AssetRef instance + * @brief Returns a null asset reference. + * + * Creates and returns a type-specific AssetRef instance that does not reference any asset. + * This null asset reference is equivalent to a default-constructed instance and will evaluate as false. + * + * @return A null AssetRef instance. */ [[nodiscard]] static AssetRef null() { return AssetRef(); @@ -174,6 +237,17 @@ namespace nexo::assets { }; template + /** + * @brief Converts a GenericAssetRef into a type-safe AssetRef. + * + * This function attempts to lock the underlying weak pointer to obtain a shared pointer + * to the asset. If successful, it performs a dynamic cast to convert the asset pointer + * to type TAsset and returns an AssetRef encapsulating it. Otherwise, it returns + * a null AssetRef. + * + * @tparam TAsset The asset type to cast to. + * @return AssetRef A type-safe reference to the asset if available, or a null reference otherwise. + */ AssetRef GenericAssetRef::as() const { const auto ptr = m_weakPtr.lock(); if (!ptr) { @@ -183,6 +257,15 @@ namespace nexo::assets { } template + /** + * @brief Locks the asset reference and returns a type-safe shared pointer. + * + * This method attempts to obtain a shared pointer from the underlying generic asset reference + * and casts it to the specified asset type TAsset. If the asset reference is expired or invalid, + * the returned pointer will be nullptr. + * + * @return std::shared_ptr A shared pointer to the asset, or nullptr if the reference is not valid. + */ std::shared_ptr AssetRef::lock() const noexcept { return std::static_pointer_cast(GenericAssetRef::lock()); diff --git a/engine/src/assets/Assets/Model/Model.hpp b/engine/src/assets/Assets/Model/Model.hpp index 4a8db1b69..ba6369080 100644 --- a/engine/src/assets/Assets/Model/Model.hpp +++ b/engine/src/assets/Assets/Model/Model.hpp @@ -34,9 +34,19 @@ namespace nexo::assets { */ class Model final : public Asset { public: - Model() = default; - - ~Model() override = default; + /** + * @brief Constructs a new Model instance. + * + * This default constructor initializes a Model object with default settings. + */ +Model() = default; + + /** + * @brief Default destructor for the Model class. + * + * This destructor overrides the base class destructor and uses the default cleanup behavior. + */ +~Model() override = default; }; } diff --git a/engine/src/assets/Assets/Model/ModelImporter.hpp b/engine/src/assets/Assets/Model/ModelImporter.hpp index b4b26f4ed..bd7e5075a 100644 --- a/engine/src/assets/Assets/Model/ModelImporter.hpp +++ b/engine/src/assets/Assets/Model/ModelImporter.hpp @@ -27,9 +27,29 @@ namespace nexo::assets { class ModelImporter final : public AssetImporterBase { public: - ModelImporter() = default; - ~ModelImporter() override = default; + /** + * @brief Default constructor for ModelImporter. + * + * Initializes a ModelImporter instance with default member values. + */ +ModelImporter() = default; + /** + * @brief Default destructor for ModelImporter. + * + * Overrides the base class destructor. This defaulted destructor ensures that cleanup + * is correctly delegated to member objects and the base class. + */ +~ModelImporter() override = default; + /** + * @brief Determines if the input variant can be processed based on its file extension. + * + * Inspects the provided input to extract the file extension from either the file path (for file-based inputs) + * or the explicit extension (for memory inputs), and checks if this extension is supported by Assimp. + * + * @param inputVariant The variant containing either file-based or memory-based input. + * @return true if the file extension is supported by Assimp; false otherwise. + */ bool canRead(const ImporterInputVariant& inputVariant) override { std::string extension; @@ -44,6 +64,18 @@ namespace nexo::assets { return importer.IsExtensionSupported(extension); } + /** + * @brief Imports a 3D model asset using Assimp. + * + * This function creates a new model instance and initializes its data container. It retrieves + * import parameters from the provided context and sets up processing flags for Assimp, including + * triangulation, UV flipping, and normal generation. Depending on the input type (file or memory), + * it calls the appropriate Assimp method to read the scene. If the scene is incomplete or invalid, + * an error is logged with the corresponding file path. On success, the imported scene is assigned + * to the model's data and the model is set as the main asset within the context. + * + * @param ctx The asset importer context containing input data and import parameters. + */ void importImpl(AssetImporterContext& ctx) override { m_model = new Model(); diff --git a/engine/src/assets/Assets/Texture/Texture.hpp b/engine/src/assets/Assets/Texture/Texture.hpp index 731b0f7e3..7502fa7b6 100644 --- a/engine/src/assets/Assets/Texture/Texture.hpp +++ b/engine/src/assets/Assets/Texture/Texture.hpp @@ -31,9 +31,19 @@ namespace nexo::assets { */ class Texture final : public Asset { public: - Texture() = default; + /** + * @brief Default constructor for the Texture class. + * + * Initializes a Texture object with default settings. + */ +Texture() = default; - ~Texture() override = default; + /** + * @brief Default destructor for the Texture asset. + * + * Explicitly overrides the base class destructor, ensuring proper resource cleanup. + */ +~Texture() override = default; }; } diff --git a/engine/src/assets/Assets/Texture/TextureImporter.hpp b/engine/src/assets/Assets/Texture/TextureImporter.hpp index 4c94b5d4b..b8acf8b3b 100644 --- a/engine/src/assets/Assets/Texture/TextureImporter.hpp +++ b/engine/src/assets/Assets/Texture/TextureImporter.hpp @@ -24,9 +24,30 @@ namespace nexo::assets { class TextureImporter final : public AssetImporterBase { public: - TextureImporter() = default; - ~TextureImporter() override = default; + /** + * @brief Default constructor for TextureImporter. + * + * Constructs a TextureImporter object using default initialization. + */ +TextureImporter() = default; + /** + * @brief Default destructor for TextureImporter. + * + * Overrides the base class destructor to ensure proper cleanup of the TextureImporter instance. + */ +~TextureImporter() override = default; + /** + * @brief Determines if the importer can read the provided input variant. + * + * Evaluates the input variant to check whether it contains either a file or memory input for texture data. + * - If the variant holds a file input, the method delegates validation to the file-based checker. + * - If the variant holds a memory input, it delegates to the memory-based checker. + * Returns false if the input type is unsupported. + * + * @param inputVariant Variant containing texture input data, either as a file or from memory. + * @return true if the input can be read as a texture; false otherwise. + */ bool canRead(const ImporterInputVariant& inputVariant) override { if (std::holds_alternative(inputVariant)) @@ -37,6 +58,17 @@ namespace nexo::assets { return false; } + /** + * @brief Imports a texture asset based on the input type. + * + * This function creates a new Texture asset and loads texture data either from a file or from memory, + * depending on the type of input provided in the asset importer context. When the input is a file, it + * initializes the texture using the file path; if the input is memory-based, it uses the memory data. + * The texture is then wrapped in a TextureData object, assigned a unique identifier, and registered as + * the main asset in the context. + * + * @param ctx The asset importer context containing input data and methods for setting the main asset. + */ void importImpl(AssetImporterContext& ctx) override { auto asset = new Texture(); @@ -57,12 +89,31 @@ namespace nexo::assets { protected: + /** + * @brief Determines whether the provided memory data contains a valid image for texture import. + * + * This function checks if the memory data within the given input can be interpreted as a valid image by + * invoking stb_image's `stbi_info_from_memory`. It returns true if the image header information is recognized, + * indicating that the memory data represents a valid texture. + * + * @param input Memory input containing raw image data to be validated. + * @return true if the image data is valid; false otherwise. + */ bool canReadMemory(const ImporterMemoryInput& input) { const int ok = stbi_info_from_memory(input.memoryData.data(), input.memoryData.size(), nullptr, nullptr, nullptr); return ok; } + /** + * @brief Checks whether the file specified in the input can be read as a texture asset. + * + * This function uses stb_image's stbi_info function to validate that the file at the given path + * is accessible and in a supported image format. + * + * @param input The file input containing the path of the texture asset. + * @return True if the file is a valid and readable texture file; false otherwise. + */ bool canReadFile(const ImporterFileInput& input) { const int ok = stbi_info(input.filePath.string().c_str(), nullptr, nullptr, nullptr); diff --git a/engine/src/assets/FilenameValidator.hpp b/engine/src/assets/FilenameValidator.hpp index 30c021ea4..fe17e0ea1 100644 --- a/engine/src/assets/FilenameValidator.hpp +++ b/engine/src/assets/FilenameValidator.hpp @@ -32,6 +32,17 @@ namespace nexo::assets { "LPT8", "LPT9" }; + /** + * @brief Validates a filename against predefined criteria. + * + * The function checks that the filename is not empty, does not exceed 255 characters, + * contains only allowed characters (alphanumeric, '.', '_', and '-'), and is not a reserved keyword. + * It returns an error message describing the first encountered issue if the filename is invalid; + * otherwise, it returns std::nullopt. + * + * @param name The filename to be validated. + * @return std::optional An error message if the filename is invalid, or std::nullopt if valid. + */ [[nodiscard]] static std::optional validate(std::string_view name) { if (name.empty()) diff --git a/engine/src/assets/ValidatedName.hpp b/engine/src/assets/ValidatedName.hpp index 3d68217d4..153941df9 100644 --- a/engine/src/assets/ValidatedName.hpp +++ b/engine/src/assets/ValidatedName.hpp @@ -17,6 +17,16 @@ namespace nexo::assets { */ class InvalidName final : public Exception { public: + /** + * @brief Constructs an InvalidName exception. + * + * Formats an error message incorporating the invalid name and an explanatory message. + * An optional source location parameter can be provided to indicate where the exception was thrown. + * + * @param name The invalid name that triggered the exception. + * @param message A descriptive message explaining why the name is invalid. + * @param loc The source location where the exception was thrown (defaults to the current location). + */ explicit InvalidName( std::string_view name, std::string_view message, @@ -37,48 +47,135 @@ namespace nexo::assets { template class ValidatedName { public: - virtual ~ValidatedName() = default; + /** + * @brief Default virtual destructor for the ValidatedName class. + * + * Ensures proper cleanup of derived classes when deleting objects through a pointer to ValidatedName. + */ +virtual ~ValidatedName() = default; - // Constructors + /** + * @brief Constructs a ValidatedName object from a given name. + * + * Validates the input name using TValidator::validate. If the name is invalid, + * the stored value is reset to "Unnamed" and an InvalidName exception is thrown + * with the corresponding error message. + * + * @param name The name to be validated. + * + * @throws InvalidName if the name fails validation. + */ explicit ValidatedName(const std::string_view name) : _value(name) { if (auto errorMessage = TValidator::validate(name); errorMessage.has_value()) { _value = "Unnamed"; THROW_EXCEPTION(InvalidName, name, errorMessage.value()); } } - explicit(false) ValidatedName(const std::string& name) : ValidatedName(std::string_view(name)) {} - explicit(false) ValidatedName(const char* name) : ValidatedName(std::string_view(name)) {} + /** + * @brief Constructs a ValidatedName from a std::string. + * + * This convenience constructor converts the provided std::string to a std::string_view and forwards it + * to the primary constructor for validation using the associated Validator. If the name fails validation, + * "Unnamed" is assigned and an InvalidName exception is thrown. + * + * @param name The string containing the name to be validated. + * + * @throws InvalidName if the name does not meet the validation criteria. + */ +explicit(false) ValidatedName(const std::string& name) : ValidatedName(std::string_view(name)) {} + /** + * @brief Constructs a ValidatedName from a C-style string. + * + * Converts the provided null-terminated string to a std::string_view and validates it using the configured validator. + * If the name fails validation, the name is set to "Unnamed" and an InvalidName exception is thrown. + * + * @param name A pointer to a null-terminated C-string representing the name to validate. + * + * @throws nexo::assets::InvalidName if the name does not meet validation criteria. + */ +explicit(false) ValidatedName(const char* name) : ValidatedName(std::string_view(name)) {} /** - * @brief Returns the size of the name. - */ + * @brief Retrieves the length of the validated name. + * + * This method returns the number of characters in the name stored by the object. + * + * @return std::size_t The length of the validated name. + */ [[nodiscard]] std::size_t size() const { return _value.size(); } /** - * @brief Implicit conversions for convenience. - */ + * @brief Converts the validated name to a std::string. + * + * This operator returns the underlying validated name stored in the instance, + * allowing the object to be used as a std::string in contexts that require a string representation. + */ explicit operator std::string() const { return _value; } - explicit operator std::string_view() const { return _value; } - explicit operator const char*() const { return _value.c_str(); } + /** + * @brief Explicit conversion operator to std::string_view. + * + * Converts the ValidatedName instance into a std::string_view, providing a read-only view + * of the internally stored validated name. + * + * @return std::string_view A view of the validated name. + */ +explicit operator std::string_view() const { return _value; } + /** + * @brief Explicitly converts the validated name to a C-style string. + * + * Returns a pointer to the null-terminated character array of the underlying name. + * + * @return const char* Pointer to the C-string representation of the validated name. + */ +explicit operator const char*() const { return _value.c_str(); } /** * @brief Returns the underlying name as a string. */ [[nodiscard]] const std::string& data() const { return _value; } - [[nodiscard]] const char* c_str() const { return _value.c_str(); } + /** + * @brief Returns the validated name as a null-terminated C-style string. + * + * This function provides a pointer to the internal string's data, enabling compatibility + * with APIs that require a pointer to a null-terminated character array. + * + * @return const char* Pointer to the validated name. + */ +[[nodiscard]] const char* c_str() const { return _value.c_str(); } /** - * @brief Equality and inequality operators. - */ + * @brief Compares two ValidatedName instances for equality. + * + * Compares the underlying name stored in each object to determine if they are identical. + * + * @param other Another ValidatedName instance to compare against. + * @return true if both instances have the same name; false otherwise. + */ bool operator==(const ValidatedName& other) const { return _value == other._value; } - bool operator!=(const ValidatedName& other) const { return !(*this == other); } + /** + * @brief Compares two ValidatedName instances for inequality. + * + * This operator returns the negated result of the equality operator. + * + * @param other The ValidatedName instance to compare against. + * @return true if the current instance is not equal to other; false otherwise. + */ +bool operator!=(const ValidatedName& other) const { return !(*this == other); } - ValidatedName& operator=(const ValidatedName& other) = default; + /** + * @brief Default copy assignment operator. + * + * Copies the validated name from the given instance. + * + * @param other The instance to copy from. + * @return ValidatedName& A reference to the updated instance. + */ +ValidatedName& operator=(const ValidatedName& other) = default; ValidatedName& operator=(std::string_view name); ValidatedName& operator=(const std::string& name); @@ -102,6 +199,18 @@ namespace nexo::assets { }; template + /** + * @brief Assigns a new validated name to the object. + * + * Validates the provided name using the TValidator's static validate method. If validation fails, + * it throws an InvalidName exception containing the error message. Upon successful validation, + * the internal name value is updated and a reference to the current object is returned. + * + * @param name The new name to assign, as a std::string_view. + * @return ValidatedName& Reference to the updated object. + * + * @throws InvalidName if the name fails validation. + */ ValidatedName& ValidatedName::operator=(std::string_view name) { if (auto errorMessage = validate(name); errorMessage.has_value()) @@ -111,6 +220,18 @@ namespace nexo::assets { } template + /** + * @brief Assigns a new validated name from a std::string. + * + * Converts the given std::string to a std::string_view and delegates + * validation and assignment to the corresponding operator. If the new name + * is invalid, an InvalidName exception is thrown. + * + * @param name The new name to assign. + * @return Reference to the updated ValidatedName object. + * + * @throws InvalidName if the provided name does not pass validation. + */ ValidatedName& ValidatedName::operator=(const std::string& name) { *this = std::string_view(name); @@ -118,6 +239,17 @@ namespace nexo::assets { } template + /** + * @brief Assigns a new validated name from a null-terminated string. + * + * Converts the provided C-string into a std::string_view and delegates the assignment + * to the corresponding operator=. If the new name fails validation, an InvalidName + * exception is thrown. + * + * @param name The C-string representing the new name. + * @return Reference to the updated ValidatedName instance. + * @throws InvalidName If the provided name is invalid. + */ ValidatedName& ValidatedName::operator=(const char* name) { this->operator=(std::string_view(name)); @@ -125,6 +257,16 @@ namespace nexo::assets { } template + /** + * @brief Attempts to rename the asset by validating the new name. + * + * Validates the provided name using the associated validator. If validation fails, + * returns an error message describing the failure and leaves the current name unchanged. + * On successful validation, updates the internal name and returns std::nullopt. + * + * @param name The new name to be applied. + * @return std::optional An error message if the new name is invalid; otherwise, std::nullopt. + */ std::optional ValidatedName::rename(std::string_view name) { if (auto errorMessage = validate(name); errorMessage.has_value()) diff --git a/engine/src/renderer/Renderer2D.cpp b/engine/src/renderer/Renderer2D.cpp index ad6f5cf07..23e94e693 100644 --- a/engine/src/renderer/Renderer2D.cpp +++ b/engine/src/renderer/Renderer2D.cpp @@ -23,6 +23,13 @@ #include namespace nexo::renderer { + /** + * @brief Initializes the Renderer2D system. + * + * This function allocates internal storage and prepares all graphics resources required for 2D quad rendering. It sets up the vertex array, vertex and index buffers with their respective layouts, initializes a default white texture, configures texture sampler slots, and loads the texture shader with the appropriate uniform settings. Predefined quad vertex positions are also established for subsequent rendering calls. + * + * Any exceptions during shader creation or binding are logged. + */ void Renderer2D::init() { m_storage = std::make_shared(); @@ -106,6 +113,12 @@ namespace nexo::renderer { m_renderingScene = true; } + /** + * @brief Flushes the current rendering batch. + * + * Binds the active texture shader and all texture slots, issues an indexed draw call for the buffered vertices, + * increments the draw call count in the renderer statistics, and finally unbinds the vertex array and vertex buffer. + */ void Renderer2D::flush() const { m_storage->textureShader->bind(); @@ -146,6 +159,20 @@ namespace nexo::renderer { } + /** + * @brief Generates vertex and index data for a quad. + * + * This function computes the vertex attributes for a quad by applying the specified transformation matrix + * to predefined quad vertex positions. It assigns the provided color, texture coordinates, texture index, + * and entity ID to each vertex and generates corresponding indices. If adding the quad's data would exceed + * the current buffer capacities, the function automatically flushes and resets the buffers. + * + * @param transform Transformation matrix applied to the quad's vertex positions. + * @param color Color assigned to each vertex of the quad. + * @param textureIndex Index of the texture to be used for the quad. + * @param textureCoords Pointer to an array of texture coordinate vectors for each vertex. + * @param entityID Identifier for the quad, used for object picking or debugging. + */ void Renderer2D::generateQuadVertices(const glm::mat4 &transform, const glm::vec4 color, const float textureIndex, const glm::vec2 *textureCoords, int entityID) const { @@ -185,6 +212,16 @@ namespace nexo::renderer { } + /** + * @brief Retrieves the index of a texture within the renderer's texture slots. + * + * This function checks if the provided texture already exists in the current texture slots. + * If found, it returns the corresponding index. Otherwise, it adds the texture to the next available + * slot and returns the new index. + * + * @param texture The texture to locate or add. + * @return float The index of the texture as a floating-point value. + */ float Renderer2D::getTextureIndex(const std::shared_ptr &texture) const { float textureIndex = 0.0f; diff --git a/engine/src/renderer/Texture.cpp b/engine/src/renderer/Texture.cpp index 2c69e4137..ffaa24236 100644 --- a/engine/src/renderer/Texture.cpp +++ b/engine/src/renderer/Texture.cpp @@ -21,6 +21,19 @@ namespace nexo::renderer { + /** + * @brief Creates a Texture2D instance with the specified dimensions. + * + * This factory method instantiates a Texture2D object configured with the given width and height. + * When the OpenGL graphics API is enabled, it returns an instance of OpenGlTexture2D; otherwise, + * it throws an UnknownGraphicsApi exception. + * + * @param width The texture's width in pixels. + * @param height The texture's height in pixels. + * @return A shared pointer to the created Texture2D object. + * + * @throws UnknownGraphicsApi if the graphics API is not recognized. + */ std::shared_ptr Texture2D::create(unsigned int width, unsigned int height) { #ifdef GRAPHICS_API_OPENGL @@ -29,6 +42,19 @@ namespace nexo::renderer { THROW_EXCEPTION(UnknownGraphicsApi, "UNKNOWN"); } + /** + * @brief Creates a Texture2D object from raw pixel data. + * + * Constructs a Texture2D using a provided buffer of pixel data and its length. + * When compiled with the OpenGL graphics API (GRAPHICS_API_OPENGL defined), an OpenGlTexture2D is instantiated with the data. + * Otherwise, an UnknownGraphicsApi exception is thrown. + * + * @param buffer Pointer to the raw pixel data. + * @param len Length of the pixel data buffer in bytes. + * @return std::shared_ptr A shared pointer to the created Texture2D object. + * + * @throws UnknownGraphicsApi if the graphics API is not supported. + */ std::shared_ptr Texture2D::create(uint8_t* buffer, unsigned int len) { #ifdef GRAPHICS_API_OPENGL @@ -37,6 +63,17 @@ namespace nexo::renderer { THROW_EXCEPTION(UnknownGraphicsApi, "UNKNOWN"); } + /** + * @brief Creates a Texture2D instance from a file path. + * + * Constructs a Texture2D object by loading an image from the specified file path. + * When compiled with OpenGL support (i.e., GRAPHICS_API_OPENGL is defined), it returns + * an instance of OpenGlTexture2D. Otherwise, it throws an UnknownGraphicsApi exception. + * + * @param path The file path to the texture image. + * @return std::shared_ptr A shared pointer to the newly created Texture2D object. + * @throws UnknownGraphicsApi if the graphics API is not supported. + */ std::shared_ptr Texture2D::create(const std::string &path) { #ifdef GRAPHICS_API_OPENGL diff --git a/engine/src/renderer/opengl/OpenGlBuffer.hpp b/engine/src/renderer/opengl/OpenGlBuffer.hpp index f960bcdbe..92fbf2544 100644 --- a/engine/src/renderer/opengl/OpenGlBuffer.hpp +++ b/engine/src/renderer/opengl/OpenGlBuffer.hpp @@ -193,7 +193,14 @@ namespace nexo::renderer { */ [[nodiscard]] unsigned int getCount() const override; - [[nodiscard]] unsigned int getId() const override { return _id; }; + /** + * @brief Retrieves the unique OpenGL buffer identifier. + * + * This method returns the identifier assigned to this buffer by OpenGL, which is used for subsequent buffer operations. + * + * @return The OpenGL buffer identifier. + */ +[[nodiscard]] unsigned int getId() const override { return _id; }; private: unsigned int _id{}; unsigned int _count = 0; diff --git a/engine/src/renderer/opengl/OpenGlTexture2D.cpp b/engine/src/renderer/opengl/OpenGlTexture2D.cpp index a712c64df..07041d39f 100644 --- a/engine/src/renderer/opengl/OpenGlTexture2D.cpp +++ b/engine/src/renderer/opengl/OpenGlTexture2D.cpp @@ -40,6 +40,16 @@ namespace nexo::renderer { glBindTexture(GL_TEXTURE_2D, 0); } + /** + * @brief Constructs a 2D texture from an image file. + * + * Loads the image data using the STB image library from the specified file path and initializes the texture. + * The texture's properties, such as dimensions and formats, are configured by calling ingestDataFromStb. + * + * @param path The filesystem path to the image to load. + * + * @throws FileNotFoundException If the image cannot be loaded from the provided path. + */ OpenGlTexture2D::OpenGlTexture2D(const std::string &path) { int width = 0; @@ -53,11 +63,26 @@ namespace nexo::renderer { ingestDataFromStb(data, width, height, channels, path); } + /** + * @brief Releases the OpenGL texture resource. + * + * Deletes the texture object by calling glDeleteTextures, ensuring the GPU memory associated with the texture is freed. + */ OpenGlTexture2D::~OpenGlTexture2D() { glDeleteTextures(1, &m_id); } + /** + * @brief Constructs an OpenGlTexture2D from image data in a memory buffer. + * + * This constructor loads texture image data using stb_image's stbi_load_from_memory function. + * If loading fails, it throws a TextureUnsupportedFormat exception with a debug message indicating the source as "(buffer)". + * On success, it processes the loaded data via ingestDataFromStb to set up the texture. + * + * @param buffer Pointer to the memory buffer containing the image data. + * @param len Size in bytes of the memory buffer. + */ OpenGlTexture2D::OpenGlTexture2D(const uint8_t* buffer, unsigned int len) { int width = 0; @@ -71,6 +96,14 @@ namespace nexo::renderer { ingestDataFromStb(data, width, height, channels, "(buffer)"); } + /** + * @brief Retrieves the maximum texture size supported by the OpenGL implementation. + * + * This method calls glGetIntegerv with GL_MAX_TEXTURE_SIZE to obtain the maximum + * dimension (in pixels) that an OpenGL texture can have. + * + * @return unsigned int The maximum texture size available. + */ unsigned int OpenGlTexture2D::getMaxTextureSize() const { int maxTextureSize = 0; @@ -78,6 +111,18 @@ namespace nexo::renderer { return static_cast(maxTextureSize); } + /** + * @brief Updates the texture with new data. + * + * Validates that the provided data size matches the expected texture size, computed as m_width * m_height * + * (4 when m_dataFormat is GL_RGBA, otherwise 3). If the sizes do not match, a TextureSizeMismatch exception is thrown. + * Otherwise, the texture is bound, the full texture is updated with the new data using glTexSubImage2D, and then unbound. + * + * @param data Pointer to the new texture data. + * @param size Size in bytes of the supplied data; must equal the expected texture size. + * + * @throws TextureSizeMismatch if the supplied size does not match the expected texture size. + */ void OpenGlTexture2D::setData(void *data, const unsigned int size) { if (const unsigned int expectedSize = m_width * m_height * (m_dataFormat == GL_RGBA ? 4 : 3); size != expectedSize) @@ -88,6 +133,20 @@ namespace nexo::renderer { glBindTexture(GL_TEXTURE_2D, 0); } + /** + * @brief Configures the 2D texture using image data loaded by STB. + * + * Sets the texture's dimensions and chooses the appropriate internal and data formats based + * on the number of channels (3 for RGB, 4 for RGBA). Generates a new texture ID, uploads the + * image data to OpenGL, and applies common texture parameters for filtering and wrapping. + * If the number of channels is unsupported, frees the image data and throws a TextureUnsupportedFormat exception. + * + * @param data Pointer to the image data loaded by the STB library. + * @param width Image width in pixels. + * @param height Image height in pixels. + * @param channels Number of channels in the image (expected to be 3 or 4). + * @param debugPath Debug path or identifier for improved error reporting. + */ void OpenGlTexture2D::ingestDataFromStb(uint8_t* data, int width, int height, int channels, const std::string& debugPath) { @@ -124,12 +183,26 @@ namespace nexo::renderer { } + /** + * @brief Binds the texture to the specified texture unit. + * + * Activates the texture unit corresponding to (GL_TEXTURE0 + slot) and binds this texture to the GL_TEXTURE_2D target. + * + * @param slot The texture unit slot to bind the texture to. + */ void OpenGlTexture2D::bind(const unsigned int slot) const { glActiveTexture(GL_TEXTURE0 + slot); glBindTexture(GL_TEXTURE_2D, m_id); } + /** + * @brief Unbinds the texture from a specified texture unit. + * + * Sets the active texture unit to the given slot and unbinds any texture bound to the GL_TEXTURE_2D target. + * + * @param slot The texture unit index from which the texture will be unbound. + */ void OpenGlTexture2D::unbind(const unsigned int slot) const { glActiveTexture(GL_TEXTURE0 + slot); diff --git a/engine/src/renderer/opengl/OpenGlTexture2D.hpp b/engine/src/renderer/opengl/OpenGlTexture2D.hpp index 82919ec78..d09381bad 100644 --- a/engine/src/renderer/opengl/OpenGlTexture2D.hpp +++ b/engine/src/renderer/opengl/OpenGlTexture2D.hpp @@ -86,8 +86,22 @@ namespace nexo::renderer { */ OpenGlTexture2D(const uint8_t *buffer, unsigned int len); - [[nodiscard]] unsigned int getWidth() const override {return m_width;}; - [[nodiscard]] unsigned int getHeight() const override {return m_height;}; + /** + * @brief Retrieves the width of the texture. + * + * This method returns the width of the texture in pixels. + * + * @return The texture's width in pixels. + */ +[[nodiscard]] unsigned int getWidth() const override {return m_width;}; + /** + * @brief Returns the height of the texture. + * + * Retrieves the texture's height in pixels. + * + * @return The height of the texture. + */ +[[nodiscard]] unsigned int getHeight() const override {return m_height;}; /** * @brief Retrieves the maximum texture size supported by the OpenGL context. diff --git a/tests/test_main.cpp b/tests/test_main.cpp index d5b6e7b05..18da7b719 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -2,7 +2,18 @@ // Init tests // Use this main file instead of GTest::gtest_main in linking -// See: https://github.com/google/googletest/issues/2157 +/** + * @brief Initializes and runs Google Test unit tests. + * + * This function sets up the Google Test framework using the provided command-line arguments, + * executes all registered tests, and logs the total number of tests run. If no tests are executed, + * it logs a fatal error indicating a potential linking configuration issue and returns an error code. + * Otherwise, it returns the status code from the test run. + * + * @return int The exit code from running the tests, or 1 if no tests were executed. + * + * @see https://github.com/google/googletest/issues/2157 + */ int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); const int rv = RUN_ALL_TESTS();