From 43c2680a8243bc0bd7955ca6f69989b39de5808d Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Fri, 21 Oct 2022 15:38:39 +0800 Subject: [PATCH] Added generic Handles and fixed bugs with SHResourceManager --- SHADE_Application/src/Scenes/SBTestScene.cpp | 41 +++++------- SHADE_Engine/src/Resource/SHHandle.h | 66 ++++++++++++++++++- SHADE_Engine/src/Resource/SHHandle.hpp | 41 +++++++++++- SHADE_Engine/src/Resource/SHResourceLibrary.h | 20 +++++- .../src/Resource/SHResourceLibrary.hpp | 5 +- .../src/Resource/SHResourceManager.cpp | 2 +- SHADE_Engine/src/Resource/SHResourceManager.h | 2 +- .../src/Resource/SHResourceManager.hpp | 14 ++-- 8 files changed, 149 insertions(+), 42 deletions(-) diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index bd812933..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->AddTexture(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/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 index cd5c7abd..a82f7890 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.cpp +++ b/SHADE_Engine/src/Resource/SHResourceManager.cpp @@ -20,7 +20,7 @@ namespace SHADE /* Static Data Member Definitions */ /*-----------------------------------------------------------------------------------*/ SHResourceHub SHResourceManager::resourceHub; - std::unordered_map> SHResourceManager::handlesMap; + std::unordered_map>> SHResourceManager::handlesMap; std::unordered_map> SHResourceManager::typedFreeFuncMap; std::vector SHResourceManager::loadedAssetData; diff --git a/SHADE_Engine/src/Resource/SHResourceManager.h b/SHADE_Engine/src/Resource/SHResourceManager.h index 8c41f778..f43b4a77 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.h +++ b/SHADE_Engine/src/Resource/SHResourceManager.h @@ -69,7 +69,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Type Definitions */ /*---------------------------------------------------------------------------------*/ - using AssetHandleMap = std::unordered_map; + using AssetHandleMap = std::unordered_map>; /*---------------------------------------------------------------------------------*/ /* Data Members */ diff --git a/SHADE_Engine/src/Resource/SHResourceManager.hpp b/SHADE_Engine/src/Resource/SHResourceManager.hpp index 7e90f499..593f8bb7 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.hpp +++ b/SHADE_Engine/src/Resource/SHResourceManager.hpp @@ -36,7 +36,7 @@ namespace SHADE /* Attempt to get existing loaded asset */ AssetHandleMap& typedHandleMap = getAssetHandleMap(); if (typedHandleMap.contains(assetId)) - return typedHandleMap[assetId]; + return Handle(typedHandleMap[assetId]); /* Otherwise, we need to load it! */ // Meshes @@ -48,7 +48,7 @@ namespace SHADE throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed."); // Load - SHMeshAsset* assetData = SHAssetManager::GetMesh(assetId); + const SHMeshAsset* assetData = SHAssetManager::GetMesh(assetId); if (assetData == nullptr) { SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID."); @@ -66,7 +66,7 @@ namespace SHADE assetData->indices.size(), assetData->indices.data() ); - typedHandleMap.insert(assetId, meshHandle); + typedHandleMap.emplace(assetId, Handle(meshHandle)); return meshHandle; } // Textures @@ -78,7 +78,7 @@ namespace SHADE throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed."); // Load - SHTextureAsset* assetData = SHAssetManager::GetTexture(assetId); + const SHTextureAsset* assetData = SHAssetManager::GetTexture(assetId); if (assetData == nullptr) { SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID."); @@ -95,7 +95,7 @@ namespace SHADE assetData->format, assetData->mipOffsets ); - typedHandleMap.insert(assetId, texHandle); + typedHandleMap.emplace(assetId, Handle(texHandle)); return texHandle; } } @@ -132,8 +132,8 @@ namespace SHADE { if (!handlesMap.contains(typeid(ResourceType))) { - handlesMap.insert(typeid(ResourceType)); - typedFreeFuncMap.insert + handlesMap.emplace(typeid(ResourceType), AssetHandleMap{}); + typedFreeFuncMap.emplace ( typeid(ResourceType), [](AssetID assetId)