diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index f1d656ee..41326174 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -1,4 +1,4 @@ -#include "SBpch.h" + #include "SBpch.h" #include "SBTestScene.h" #include "ECS_Base/Managers/SHSystemManager.h" @@ -14,6 +14,7 @@ #include "Physics/Components/SHColliderComponent.h" #include "Assets/SHAssetManager.h" +#include "Resource/SHResourceManager.h" using namespace SHADE; @@ -40,34 +41,22 @@ namespace Sandbox const auto CUBE_MESH = SHADE::SHPrimitiveGenerator::Cube(*graphicsSystem); //Test Racoon mesh - auto meshes = SHADE::SHAssetManager::GetAllMeshes(); std::vector> handles; - for (auto const& mesh : meshes) + std::vector> texHandles; + for (const auto& asset : SHAssetManager::GetAllAssets()) { - if (mesh.header.meshName == "Cube.012") + switch (asset.type) { - handles.push_back(graphicsSystem->AddMesh( - mesh.header.vertexCount, - mesh.vertexPosition.data(), - mesh.texCoords.data(), - mesh.vertexTangent.data(), - mesh.vertexNormal.data(), - mesh.header.indexCount, - mesh.indices.data() - )); + case AssetType::MESH: + if (asset.name == "Cube.012") + handles.emplace_back(SHResourceManager::LoadOrGet(asset.id)); + break; + case AssetType::TEXTURE: + texHandles.emplace_back(SHResourceManager::LoadOrGet(asset.id)); + break; } } - graphicsSystem->BuildMeshBuffers(); - - // Load Textures - auto textures = SHADE::SHAssetManager::GetAllTextures(); - std::vector> texHandles; - for (const auto& tex : textures) - { - auto texture = graphicsSystem->Add(tex); - texHandles.push_back(texture); - } - graphicsSystem->BuildTextures(); + SHResourceManager::FinaliseChanges(); // Create Materials auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance(); @@ -78,8 +67,8 @@ namespace Sandbox // Create Stress Test Objects static const SHVec3 TEST_OBJ_SCALE = SHVec3::One * 0.5f; - constexpr int NUM_ROWS = 10; - constexpr int NUM_COLS = 10; + constexpr int NUM_ROWS = 0; + constexpr int NUM_COLS = 0; static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f }; static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f }; diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index aa9772dd..956d52e8 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -62,7 +62,12 @@ namespace SHADE } } - AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept + void SHAssetManager::Unload(AssetID assetId) noexcept + { + // TODO + } + + AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept { if (!IsRecognised(path.extension().string().c_str())) { diff --git a/SHADE_Engine/src/Assets/SHAssetManager.h b/SHADE_Engine/src/Assets/SHAssetManager.h index 50549e01..2469165a 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.h +++ b/SHADE_Engine/src/Assets/SHAssetManager.h @@ -32,6 +32,7 @@ namespace SHADE * \brief Deallocate all memory used by resource data ****************************************************************************/ static void Unload() noexcept; + static void Unload(AssetID assetId) noexcept; /**************************************************************************** * \brief Load all resources that are in the folder diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 06762db8..44404bc7 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -585,19 +585,19 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Texture Registration Functions */ /*---------------------------------------------------------------------------------*/ - Handle SHGraphicsSystem::Add(const SHTextureAsset& texAsset) + Handle SHGraphicsSystem::AddTexture(const SHTextureAsset& texAsset) { auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams { .maxLod = static_cast(texAsset.mipOffsets.size()) }); return texLibrary.Add(texAsset, sampler); } - SHADE::Handle SHGraphicsSystem::Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector mipOffsets) + SHADE::Handle SHGraphicsSystem::AddTexture(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector mipOffsets) { auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams{ .maxLod = static_cast(mipOffsets.size()) }); return texLibrary.Add(pixelCount, pixelData, width, height, format, mipOffsets, sampler); } - void SHGraphicsSystem::Remove(Handle tex) + void SHGraphicsSystem::RemoveTexture(Handle tex) { texLibrary.Remove(tex); } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index 29429703..870325ac 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -231,8 +231,8 @@ namespace SHADE */ /*******************************************************************************/ - Handle Add(const SHTextureAsset& texAsset); - Handle Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector mipOffsets); + Handle AddTexture(const SHTextureAsset& texAsset); + Handle AddTexture(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector mipOffsets); /*******************************************************************************/ /*! @@ -246,7 +246,7 @@ namespace SHADE */ /*******************************************************************************/ - void Remove(Handle tex); + void RemoveTexture(Handle tex); /***************************************************************************/ /*! diff --git a/SHADE_Engine/src/Resource/SHHandle.h b/SHADE_Engine/src/Resource/SHHandle.h index ffc8ae6b..6acc85ed 100644 --- a/SHADE_Engine/src/Resource/SHHandle.h +++ b/SHADE_Engine/src/Resource/SHHandle.h @@ -8,6 +8,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Forward Declarations */ /*---------------------------------------------------------------------------------*/ + class SHResourceLibraryBase; template class SHResourceLibrary; @@ -25,6 +26,20 @@ namespace SHADE using std::runtime_error::runtime_error; }; + /// + /// Exception thrown when a generic Handle is being casted to the wrong type. + /// + class BadHandleCastException : std::runtime_error + { + public: + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + BadHandleCastException() + : std::runtime_error("Attempted to cast a generic Handle to the wrong type. ") + {} + }; + /// /// Base implementation of the Handle that is not templated to allow for holding /// generic non-type-specific Handles. @@ -80,7 +95,7 @@ namespace SHADE /// Generic implementation of a Handle object /// /// Type of the handle. - template + template class Handle : public HandleBase { public: @@ -88,6 +103,16 @@ namespace SHADE /* Constructors */ /*-----------------------------------------------------------------------------*/ Handle() = default; + /// + /// Converts a generic/void Handle to a specific type. + /// Runtime type checking is enabled to ensure that Handles are only being casted + /// to the correct type. + /// + /// Generic handle to convert. + /// + /// Thrown if an invalid conversion is made. + /// + explicit Handle(const Handle& genericHandle); ~Handle() = default; /*-----------------------------------------------------------------------------*/ @@ -146,7 +171,42 @@ namespace SHADE /* Friend Declarations */ /*-----------------------------------------------------------------------------*/ friend class SHResourceLibrary; - }; + friend class Handle; + }; + + /// + /// Template Specialization for Handle that represents a type-less Handle. + /// + template<> + class Handle : public HandleBase + { + public: + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + Handle() = default; + template + explicit Handle(const Handle& handle); + ~Handle() = default; + + /*-----------------------------------------------------------------------------*/ + /* Overloaded Operators */ + /*-----------------------------------------------------------------------------*/ + template + inline bool operator==(const Handle& rhs) const noexcept; + + protected: + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + SHResourceLibraryBase* library = nullptr; + + /*-----------------------------------------------------------------------------*/ + /* Friend Declarations */ + /*-----------------------------------------------------------------------------*/ + template + friend class Handle; + }; /// /// Interface that needs to be implemented by classes that want to store a Handle to @@ -155,7 +215,7 @@ namespace SHADE template class ISelfHandle { - public: + public: /*-----------------------------------------------------------------------------*/ /* Constructors */ /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Resource/SHHandle.hpp b/SHADE_Engine/src/Resource/SHHandle.hpp index 6f6ea31f..53061ac7 100644 --- a/SHADE_Engine/src/Resource/SHHandle.hpp +++ b/SHADE_Engine/src/Resource/SHHandle.hpp @@ -20,7 +20,21 @@ namespace SHADE { return id.Raw != INVALID_ID.Raw; } - + + /*---------------------------------------------------------------------------------*/ + /* Handle - Constructors */ + /*---------------------------------------------------------------------------------*/ + template + Handle::Handle(const Handle& genericHandle) + : library { reinterpret_cast*>(genericHandle.library) } + { + id = genericHandle.id; + + // Check if valid + if (library != nullptr && library->GetType() != typeid(T)) + throw BadHandleCastException(); + } + /*---------------------------------------------------------------------------------*/ /* Handle - Usage Functions */ /*---------------------------------------------------------------------------------*/ @@ -63,6 +77,28 @@ namespace SHADE return &library->Get(*this); } + /*---------------------------------------------------------------------------------*/ + /* Handle - Constructors */ + /*---------------------------------------------------------------------------------*/ + template + Handle::Handle(const Handle& handle) + : library{ static_cast(handle.library) } + { + id = handle.id; + } + + /*---------------------------------------------------------------------------------*/ + /* Handle - Overloaded Operators */ + /*---------------------------------------------------------------------------------*/ + template + bool SHADE::Handle::operator==(const Handle& rhs) const noexcept + { + return id.Raw == rhs.id.Raw && library == static_cast(rhs.library); + } + + /*---------------------------------------------------------------------------------*/ + /* ISelfHandle - Constructors */ + /*---------------------------------------------------------------------------------*/ template inline ISelfHandle::ISelfHandle(const ISelfHandle& rhs) : handle { rhs.handle } @@ -73,6 +109,9 @@ namespace SHADE : handle { rhs.handle } {} + /*---------------------------------------------------------------------------------*/ + /* ISelfHandle - Overloaded Operators */ + /*---------------------------------------------------------------------------------*/ template inline ISelfHandle& ISelfHandle::operator=(const ISelfHandle& rhs) { diff --git a/SHADE_Engine/src/Resource/SHResourceLibrary.h b/SHADE_Engine/src/Resource/SHResourceLibrary.h index c83cf321..46ae4572 100644 --- a/SHADE_Engine/src/Resource/SHResourceLibrary.h +++ b/SHADE_Engine/src/Resource/SHResourceLibrary.h @@ -11,13 +11,31 @@ namespace SHADE { + /// + /// Base class for SHResourceLibrary that holds information about the library type. + /// + class SHResourceLibraryBase + { + public: + /*-----------------------------------------------------------------------------*/ + /* Getter Functions */ + /*-----------------------------------------------------------------------------*/ + inline std::type_index GetType() { return libraryType; } + + protected: + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + std::type_index libraryType = typeid(void); + }; + /// /// Generic Resource Library for a specified type of Resource. This object will own /// any resources created using it. /// /// Type of resources that this library stores. template - class SHResourceLibrary + class SHResourceLibrary : public SHResourceLibraryBase { public: /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Resource/SHResourceLibrary.hpp b/SHADE_Engine/src/Resource/SHResourceLibrary.hpp index 54120a94..411f6bf5 100644 --- a/SHADE_Engine/src/Resource/SHResourceLibrary.hpp +++ b/SHADE_Engine/src/Resource/SHResourceLibrary.hpp @@ -13,10 +13,11 @@ namespace SHADE SHResourceLibrary::SHResourceLibrary() { // Type Checking - //static_assert(std::is_copy_assignable_v, "Resource Library's resources must be copy assignable."); - //static_assert(std::is_copy_constructible_v, "Resource Library's resources must be copy constructible."); static_assert(std::is_move_assignable_v, "Resource Library's resources must be move assignable."); static_assert(std::is_move_constructible_v, "Resource Library's resources must be move constructible."); + + // Keep track of the type for conversions + libraryType = typeid(T); } /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Resource/SHResourceManager.cpp b/SHADE_Engine/src/Resource/SHResourceManager.cpp new file mode 100644 index 00000000..156c31c7 --- /dev/null +++ b/SHADE_Engine/src/Resource/SHResourceManager.cpp @@ -0,0 +1,95 @@ +/************************************************************************************//*! +\file SHResourceManager.cpp +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 21, 2022 +\brief Contains the definition of the functions of the SHResourceManager static + class. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#include "SHpch.h" +// Primary Include +#include "SHResourceManager.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Static Data Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + SHResourceHub SHResourceManager::resourceHub; + std::unordered_map>> SHResourceManager::handlesMap; + std::unordered_map SHResourceManager::assetIdMap; + std::unordered_map> SHResourceManager::typedFreeFuncMap; + std::vector SHResourceManager::loadedAssetData; + + /*-----------------------------------------------------------------------------------*/ + /* Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + void SHResourceManager::Unload(AssetID assetId) + { + // Search each library for the asset ID and try to free it + Handle handle; + for (auto& typedHandleMap : handlesMap) + { + if (typedHandleMap.second.contains(assetId)) + { + // Save handle for later + handle = typedHandleMap.second[assetId]; + // Dispose + typedFreeFuncMap[typedHandleMap.first](assetId); + typedHandleMap.second.erase(assetId); + } + } + + // No handles were found + if (!handle) + return; + + for (auto& typedAssetIdsMap : assetIdMap) + { + if (typedAssetIdsMap.second.contains(handle)) + { + // Dispose + typedAssetIdsMap.second.erase(handle); + } + } + } + + void SHResourceManager::FinaliseChanges() + { + SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem(); + if (gfxSystem == nullptr) + throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed."); + gfxSystem->BuildMeshBuffers(); + gfxSystem->BuildTextures(); + + // Free CPU Resources + for (auto assetId : loadedAssetData) + { + SHAssetManager::Unload(assetId); + } + loadedAssetData.clear(); + } + + /*-----------------------------------------------------------------------------------*/ + /* Query Functions */ + /*-----------------------------------------------------------------------------------*/ + std::optional SHResourceManager::GetAssetID(Handle handle) + { + const Handle GENERIC_HANDLE = Handle(handle); + + // Search each library for the asset ID and try to free it + for (auto& typedAssetIdsMap : assetIdMap) + { + if (typedAssetIdsMap.second.contains(GENERIC_HANDLE)) + { + return typedAssetIdsMap.second[GENERIC_HANDLE]; + } + } + + return {}; + } +} diff --git a/SHADE_Engine/src/Resource/SHResourceManager.h b/SHADE_Engine/src/Resource/SHResourceManager.h new file mode 100644 index 00000000..84f93b10 --- /dev/null +++ b/SHADE_Engine/src/Resource/SHResourceManager.h @@ -0,0 +1,130 @@ +/************************************************************************************//*! +\file SHResourceManager.h +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 21, 2022 +\brief Contains the definition of the SHResourceManager static class. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +// STL Includes +#include +// Project Includes +#include "SH_API.h" +#include "SHResourceLibrary.h" +#include "Assets/SHAssetMacros.h" + +namespace SHADE +{ + /// + /// Static class responsible for loading and caching runtime resources from their + /// serialised Asset IDs. + /// + class SH_API SHResourceManager + { + public: + /*---------------------------------------------------------------------------------*/ + /* Loading Functions */ + /*---------------------------------------------------------------------------------*/ + /// + /// Loads or retrieves an existing loaded object of the specified type with the + /// specified asset ID. + /// Note that for specific types, the retrieved Handle may not be valid until after + /// FinaliseChanges() is called. + /// + /// + /// Type of resource to load. + /// + /// Asset ID of the resource to load. + /// Handle to a loaded runtime asset. + template + static Handle LoadOrGet(AssetID assetId); + /// + /// Unloads an existing loaded asset. Attempting to unload an invalid Handle will + /// simply do nothing except emit a warning. + /// Faster than the untemplated version. + /// + /// Type of resource to unload. + /// Handle to the resource to unload. + template + static void Unload(Handle assetId); + /// + /// Unloads an existing loaded asset. Attempting to unload an invalid Handle will + /// simply do nothing except emit a warning. + /// Compared to the templated version, this function is slower as it requires + /// searching through the storage of all resource types. + /// + /// Handle to the resource to unload. + static void Unload(AssetID assetId); + /// + /// Needs to be called to finalise all changes to loads. + /// + static void FinaliseChanges(); + + /*---------------------------------------------------------------------------------*/ + /* Query Functions */ + /*---------------------------------------------------------------------------------*/ + /// + /// Retrieves the AssetID associated with a specified Handle. + /// Faster than the untemplated version. + /// + /// Type of resource to get the ID of. + /// Handle to get the AssetID of. + /// + /// AssetID for the specified Handle. If the Handle is invalid, there will be no + /// value. + /// + template + static std::optional GetAssetID(Handle handle); + /// + /// Retrieves the AssetID associated with a specified Handle. + /// Compared to the templated version, this function is slower as it requires + /// searching through the storage of all resource types. + /// + /// Handle to get the AssetID of. + /// + /// AssetID for the specified Handle. If the Handle is invalid, there will be no + /// value. + /// + static std::optional GetAssetID(Handle handle); + + private: + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + using AssetHandleMap = std::unordered_map>; + using HandleAssetMap = std::unordered_map, AssetID>; + using AssetHandleMapRef = std::reference_wrapper; + using HandleAssetMapRef = std::reference_wrapper; + + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + // Handles + static SHResourceHub resourceHub; + static std::unordered_map handlesMap; + static std::unordered_map assetIdMap; + static std::unordered_map> typedFreeFuncMap; + // Pointers to temp CPU resources + static std::vector loadedAssetData; + + /*---------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*---------------------------------------------------------------------------------*/ + /// + /// Retrieves or creates the AssetHandleMap for the specific type if it doesn't exist + /// + /// + /// The type of AssetHandleMap to retrieve. + /// + /// Reference to the AssetHandleMap of the specified type. + template + static std::pair getAssetHandleMap(); + }; +} + +#include "SHResourceManager.hpp" diff --git a/SHADE_Engine/src/Resource/SHResourceManager.hpp b/SHADE_Engine/src/Resource/SHResourceManager.hpp new file mode 100644 index 00000000..54ced715 --- /dev/null +++ b/SHADE_Engine/src/Resource/SHResourceManager.hpp @@ -0,0 +1,171 @@ +/************************************************************************************//*! +\file SHResourceManager.hpp +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 21, 2022 +\brief Contains the definition of the function templates of the + SHResourceManager static class. + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once +// Primary Include +#include "SHResourceManager.h" +// Project Includes +#include "Assets/SHAssetManager.h" +#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h" +#include "ECS_Base/Managers/SHSystemManager.h" +#include "Tools/SHLog.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Loading Functions */ + /*-----------------------------------------------------------------------------------*/ + template + Handle SHResourceManager::LoadOrGet(AssetID assetId) + { + // Check if it is an unsupported type + if (!std::is_same_v && !std::is_same_v) + { + static_assert(true, "Unsupported Resource Type specified for SHResourceManager."); + } + + /* Attempt to get existing loaded asset */ + auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap(); + if (typedHandleMap.get().contains(assetId)) + return Handle(typedHandleMap.get()[assetId]); + + /* Otherwise, we need to load it! */ + // Meshes + if constexpr (std::is_same_v) + { + // Get system + SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem(); + if (gfxSystem == nullptr) + throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed."); + + // Load + const SHMeshAsset* assetData = SHAssetManager::GetMesh(assetId); + if (assetData == nullptr) + { + SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID."); + return {}; + } + loadedAssetData.emplace_back(assetId); + + Handle meshHandle = gfxSystem->AddMesh + ( + assetData->vertexPosition.size(), + assetData->vertexPosition.data(), + assetData->texCoords.data(), + assetData->vertexTangent.data(), + assetData->vertexNormal.data(), + assetData->indices.size(), + assetData->indices.data() + ); + Handle genericHandle = Handle(meshHandle); + typedHandleMap.get().emplace(assetId, genericHandle); + typedAssetIdMap.get().emplace(genericHandle, assetId); + return meshHandle; + } + // Textures + else if constexpr (std::is_same_v) + { + // Get system + SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem(); + if (gfxSystem == nullptr) + throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed."); + + // Load + const SHTextureAsset* assetData = SHAssetManager::GetTexture(assetId); + if (assetData == nullptr) + { + SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID."); + return {}; + } + loadedAssetData.emplace_back(assetId); + + Handle texHandle = gfxSystem->AddTexture + ( + assetData->numBytes, + assetData->pixelData, + assetData->width, + assetData->height, + assetData->format, + assetData->mipOffsets + ); + typedHandleMap.get().emplace(assetId, Handle(texHandle)); + return texHandle; + } + } + + template + void SHResourceManager::Unload(Handle assetId) + { + // Check if it is an unsupported type + if (!std::is_same_v && !std::is_same_v) + { + static_assert(true, "Unsupported Resource Type specified for SHResourceManager."); + } + + /* Attempt to get existing loaded asset */ + auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap(); + if (typedHandleMap.get().contains(assetId)) + { + // Dispose + Handle handle = typedHandleMap.get()[assetId]; + Handle typedHandle = static_cast>(handle); + typedHandle.Free(); + typedAssetIdMap.get().erase(handle); + typedHandleMap.get().erase(assetId); + } + else + { + // There's nothing to remove + SHLog::Warning("[SHResourceManager] Attempted to unload an invalid resource. Ignoring."); + } + } + + /*-----------------------------------------------------------------------------------*/ + /* Query Functions */ + /*-----------------------------------------------------------------------------------*/ + template + static std::optional SHResourceManager::GetAssetID(Handle handle) + { + const Handle GENERIC_HANDLE = Handle(handle); + auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap(); + if (typedAssetIdMap.get().contains(GENERIC_HANDLE)) + { + return typedAssetIdMap.GetId()[GENERIC_HANDLE]; + } + + return {}; + } + + /*-----------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*-----------------------------------------------------------------------------------*/ + template + std::pair SHResourceManager::getAssetHandleMap() + { + const std::type_index TYPE = typeid(ResourceType); + + if (!handlesMap.contains(TYPE)) + { + handlesMap.emplace(TYPE, AssetHandleMap{}); + assetIdMap.emplace(TYPE, HandleAssetMap{}); + typedFreeFuncMap.emplace + ( + TYPE, + [TYPE](AssetID assetId) + { + static_cast>(SHResourceManager::handlesMap[TYPE][assetId]).Free(); + } + ); + } + return std::make_pair(std::ref(handlesMap[TYPE]), std::ref(assetIdMap[TYPE])); + } +}