Added generic Handles and fixed bugs with SHResourceManager

This commit is contained in:
Kah Wei 2022-10-21 15:38:39 +08:00
parent 7e15edb052
commit 43c2680a82
8 changed files with 149 additions and 42 deletions

View File

@ -1,4 +1,4 @@
#include "SBpch.h" #include "SBpch.h"
#include "SBTestScene.h" #include "SBTestScene.h"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
@ -14,6 +14,7 @@
#include "Physics/Components/SHColliderComponent.h" #include "Physics/Components/SHColliderComponent.h"
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "Resource/SHResourceManager.h"
using namespace SHADE; using namespace SHADE;
@ -40,34 +41,22 @@ namespace Sandbox
const auto CUBE_MESH = SHADE::SHPrimitiveGenerator::Cube(*graphicsSystem); const auto CUBE_MESH = SHADE::SHPrimitiveGenerator::Cube(*graphicsSystem);
//Test Racoon mesh //Test Racoon mesh
auto meshes = SHADE::SHAssetManager::GetAllMeshes();
std::vector<Handle<SHMesh>> handles; std::vector<Handle<SHMesh>> handles;
for (auto const& mesh : meshes) std::vector<Handle<SHTexture>> texHandles;
for (const auto& asset : SHAssetManager::GetAllAssets())
{ {
if (mesh.header.meshName == "Cube.012") switch (asset.type)
{ {
handles.push_back(graphicsSystem->AddMesh( case AssetType::MESH:
mesh.header.vertexCount, if (asset.name == "Cube.012")
mesh.vertexPosition.data(), handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
mesh.texCoords.data(), break;
mesh.vertexTangent.data(), case AssetType::TEXTURE:
mesh.vertexNormal.data(), texHandles.emplace_back(SHResourceManager::LoadOrGet<SHTexture>(asset.id));
mesh.header.indexCount, break;
mesh.indices.data()
));
} }
} }
graphicsSystem->BuildMeshBuffers(); SHResourceManager::FinaliseChanges();
// Load Textures
auto textures = SHADE::SHAssetManager::GetAllTextures();
std::vector<Handle<SHTexture>> texHandles;
for (const auto& tex : textures)
{
auto texture = graphicsSystem->AddTexture(tex);
texHandles.push_back(texture);
}
graphicsSystem->BuildTextures();
// Create Materials // Create Materials
auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance(); auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance();
@ -78,8 +67,8 @@ namespace Sandbox
// Create Stress Test Objects // Create Stress Test Objects
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One * 0.5f; static const SHVec3 TEST_OBJ_SCALE = SHVec3::One * 0.5f;
constexpr int NUM_ROWS = 10; constexpr int NUM_ROWS = 0;
constexpr int NUM_COLS = 10; constexpr int NUM_COLS = 0;
static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f }; 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 }; static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f };

View File

@ -8,6 +8,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Forward Declarations */ /* Forward Declarations */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
class SHResourceLibraryBase;
template<typename T> template<typename T>
class SHResourceLibrary; class SHResourceLibrary;
@ -25,6 +26,20 @@ namespace SHADE
using std::runtime_error::runtime_error; using std::runtime_error::runtime_error;
}; };
/// <summary>
/// Exception thrown when a generic Handle is being casted to the wrong type.
/// </summary>
class BadHandleCastException : std::runtime_error
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
BadHandleCastException()
: std::runtime_error("Attempted to cast a generic Handle to the wrong type. ")
{}
};
/// <summary> /// <summary>
/// Base implementation of the Handle that is not templated to allow for holding /// Base implementation of the Handle that is not templated to allow for holding
/// generic non-type-specific Handles. /// generic non-type-specific Handles.
@ -80,7 +95,7 @@ namespace SHADE
/// Generic implementation of a Handle object /// Generic implementation of a Handle object
/// </summary> /// </summary>
/// <typeparam name="T">Type of the handle.</typeparam> /// <typeparam name="T">Type of the handle.</typeparam>
template<typename T> template<typename T = void>
class Handle : public HandleBase class Handle : public HandleBase
{ {
public: public:
@ -88,6 +103,16 @@ namespace SHADE
/* Constructors */ /* Constructors */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle() = default; Handle() = default;
/// <summary>
/// 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.
/// </summary>
/// <param name="genericHandle">Generic handle to convert.</param>
/// <exception cref="std::bad_cast">
/// Thrown if an invalid conversion is made.
/// </exception>
explicit Handle(const Handle<void>& genericHandle);
~Handle() = default; ~Handle() = default;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -146,6 +171,41 @@ namespace SHADE
/* Friend Declarations */ /* Friend Declarations */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
friend class SHResourceLibrary<T>; friend class SHResourceLibrary<T>;
friend class Handle<void>;
};
/// <summary>
/// Template Specialization for Handle that represents a type-less Handle.
/// </summary>
template<>
class Handle<void> : public HandleBase
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
Handle() = default;
template<typename T>
explicit Handle(const Handle<T>& handle);
~Handle() = default;
/*-----------------------------------------------------------------------------*/
/* Overloaded Operators */
/*-----------------------------------------------------------------------------*/
template<typename T>
inline bool operator==(const Handle<T>& rhs) const noexcept;
protected:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
SHResourceLibraryBase* library = nullptr;
/*-----------------------------------------------------------------------------*/
/* Friend Declarations */
/*-----------------------------------------------------------------------------*/
template<typename T>
friend class Handle;
}; };
/// <summary> /// <summary>

View File

@ -21,6 +21,20 @@ namespace SHADE
return id.Raw != INVALID_ID.Raw; return id.Raw != INVALID_ID.Raw;
} }
/*---------------------------------------------------------------------------------*/
/* Handle<T> - Constructors */
/*---------------------------------------------------------------------------------*/
template<typename T>
Handle<T>::Handle(const Handle<void>& genericHandle)
: library { reinterpret_cast<SHResourceLibrary<T>*>(genericHandle.library) }
{
id = genericHandle.id;
// Check if valid
if (library != nullptr && library->GetType() != typeid(T))
throw BadHandleCastException();
}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Handle<T> - Usage Functions */ /* Handle<T> - Usage Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -63,6 +77,28 @@ namespace SHADE
return &library->Get(*this); return &library->Get(*this);
} }
/*---------------------------------------------------------------------------------*/
/* Handle<void> - Constructors */
/*---------------------------------------------------------------------------------*/
template<typename T>
Handle<void>::Handle(const Handle<T>& handle)
: library{ static_cast<SHResourceLibraryBase*>(handle.library) }
{
id = handle.id;
}
/*---------------------------------------------------------------------------------*/
/* Handle<void> - Overloaded Operators */
/*---------------------------------------------------------------------------------*/
template<typename T>
bool SHADE::Handle<void>::operator==(const Handle<T>& rhs) const noexcept
{
return id.Raw == rhs.id.Raw && library == static_cast<void*>(rhs.library);
}
/*---------------------------------------------------------------------------------*/
/* ISelfHandle<T> - Constructors */
/*---------------------------------------------------------------------------------*/
template<typename T> template<typename T>
inline ISelfHandle<T>::ISelfHandle(const ISelfHandle& rhs) inline ISelfHandle<T>::ISelfHandle(const ISelfHandle& rhs)
: handle { rhs.handle } : handle { rhs.handle }
@ -73,6 +109,9 @@ namespace SHADE
: handle { rhs.handle } : handle { rhs.handle }
{} {}
/*---------------------------------------------------------------------------------*/
/* ISelfHandle<T> - Overloaded Operators */
/*---------------------------------------------------------------------------------*/
template<typename T> template<typename T>
inline ISelfHandle<T>& ISelfHandle<T>::operator=(const ISelfHandle& rhs) inline ISelfHandle<T>& ISelfHandle<T>::operator=(const ISelfHandle& rhs)
{ {

View File

@ -11,13 +11,31 @@
namespace SHADE namespace SHADE
{ {
/// <summary>
/// Base class for SHResourceLibrary that holds information about the library type.
/// </summary>
class SHResourceLibraryBase
{
public:
/*-----------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
inline std::type_index GetType() { return libraryType; }
protected:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
std::type_index libraryType = typeid(void);
};
/// <summary> /// <summary>
/// Generic Resource Library for a specified type of Resource. This object will own /// Generic Resource Library for a specified type of Resource. This object will own
/// any resources created using it. /// any resources created using it.
/// </summary> /// </summary>
/// <typeparam name="T">Type of resources that this library stores.</typeparam> /// <typeparam name="T">Type of resources that this library stores.</typeparam>
template<typename T> template<typename T>
class SHResourceLibrary class SHResourceLibrary : public SHResourceLibraryBase
{ {
public: public:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -13,10 +13,11 @@ namespace SHADE
SHResourceLibrary<T>::SHResourceLibrary() SHResourceLibrary<T>::SHResourceLibrary()
{ {
// Type Checking // Type Checking
//static_assert(std::is_copy_assignable_v<T>, "Resource Library's resources must be copy assignable.");
//static_assert(std::is_copy_constructible_v<T>, "Resource Library's resources must be copy constructible.");
static_assert(std::is_move_assignable_v<T>, "Resource Library's resources must be move assignable."); static_assert(std::is_move_assignable_v<T>, "Resource Library's resources must be move assignable.");
static_assert(std::is_move_constructible_v<T>, "Resource Library's resources must be move constructible."); static_assert(std::is_move_constructible_v<T>, "Resource Library's resources must be move constructible.");
// Keep track of the type for conversions
libraryType = typeid(T);
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -20,7 +20,7 @@ namespace SHADE
/* Static Data Member Definitions */ /* Static Data Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHResourceHub SHResourceManager::resourceHub; SHResourceHub SHResourceManager::resourceHub;
std::unordered_map<std::type_index, std::unordered_map<AssetID, SHADE::HandleBase>> SHResourceManager::handlesMap; std::unordered_map<std::type_index, std::unordered_map<AssetID, Handle<void>>> SHResourceManager::handlesMap;
std::unordered_map<std::type_index, std::function<void(AssetID)>> SHResourceManager::typedFreeFuncMap; std::unordered_map<std::type_index, std::function<void(AssetID)>> SHResourceManager::typedFreeFuncMap;
std::vector<AssetID> SHResourceManager::loadedAssetData; std::vector<AssetID> SHResourceManager::loadedAssetData;

View File

@ -69,7 +69,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
using AssetHandleMap = std::unordered_map<AssetID, HandleBase>; using AssetHandleMap = std::unordered_map<AssetID, Handle<void>>;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */

View File

@ -36,7 +36,7 @@ namespace SHADE
/* Attempt to get existing loaded asset */ /* Attempt to get existing loaded asset */
AssetHandleMap& typedHandleMap = getAssetHandleMap<ResourceType>(); AssetHandleMap& typedHandleMap = getAssetHandleMap<ResourceType>();
if (typedHandleMap.contains(assetId)) if (typedHandleMap.contains(assetId))
return typedHandleMap[assetId]; return Handle<ResourceType>(typedHandleMap[assetId]);
/* Otherwise, we need to load it! */ /* Otherwise, we need to load it! */
// Meshes // Meshes
@ -48,7 +48,7 @@ namespace SHADE
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed."); throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
// Load // Load
SHMeshAsset* assetData = SHAssetManager::GetMesh(assetId); const SHMeshAsset* assetData = SHAssetManager::GetMesh(assetId);
if (assetData == nullptr) if (assetData == nullptr)
{ {
SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID."); SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
@ -66,7 +66,7 @@ namespace SHADE
assetData->indices.size(), assetData->indices.size(),
assetData->indices.data() assetData->indices.data()
); );
typedHandleMap.insert(assetId, meshHandle); typedHandleMap.emplace(assetId, Handle(meshHandle));
return meshHandle; return meshHandle;
} }
// Textures // Textures
@ -78,7 +78,7 @@ namespace SHADE
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed."); throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
// Load // Load
SHTextureAsset* assetData = SHAssetManager::GetTexture(assetId); const SHTextureAsset* assetData = SHAssetManager::GetTexture(assetId);
if (assetData == nullptr) if (assetData == nullptr)
{ {
SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID."); SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
@ -95,7 +95,7 @@ namespace SHADE
assetData->format, assetData->format,
assetData->mipOffsets assetData->mipOffsets
); );
typedHandleMap.insert(assetId, texHandle); typedHandleMap.emplace(assetId, Handle(texHandle));
return texHandle; return texHandle;
} }
} }
@ -132,8 +132,8 @@ namespace SHADE
{ {
if (!handlesMap.contains(typeid(ResourceType))) if (!handlesMap.contains(typeid(ResourceType)))
{ {
handlesMap.insert(typeid(ResourceType)); handlesMap.emplace(typeid(ResourceType), AssetHandleMap{});
typedFreeFuncMap.insert typedFreeFuncMap.emplace
( (
typeid(ResourceType), typeid(ResourceType),
[](AssetID assetId) [](AssetID assetId)