Added SHResourceManager and Generic Handle #104

Merged
Pycorax merged 3 commits from SP3-13-ResourceManager into main 2022-10-21 17:11:51 +08:00
8 changed files with 149 additions and 42 deletions
Showing only changes of commit 43c2680a82 - Show all commits

View File

@ -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<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(
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<SHMesh>(asset.id));
break;
case AssetType::TEXTURE:
texHandles.emplace_back(SHResourceManager::LoadOrGet<SHTexture>(asset.id));
break;
}
}
graphicsSystem->BuildMeshBuffers();
// 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();
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 };

View File

@ -8,6 +8,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHResourceLibraryBase;
template<typename T>
class SHResourceLibrary;
@ -25,6 +26,20 @@ namespace SHADE
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>
/// 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
/// </summary>
/// <typeparam name="T">Type of the handle.</typeparam>
template<typename T>
template<typename T = void>
class Handle : public HandleBase
{
public:
@ -88,6 +103,16 @@ namespace SHADE
/* Constructors */
/*-----------------------------------------------------------------------------*/
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;
/*-----------------------------------------------------------------------------*/
@ -146,7 +171,42 @@ namespace SHADE
/* Friend Declarations */
/*-----------------------------------------------------------------------------*/
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>
/// Interface that needs to be implemented by classes that want to store a Handle to
@ -155,7 +215,7 @@ namespace SHADE
template<typename T>
class ISelfHandle
{
public:
public:
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/

View File

@ -20,7 +20,21 @@ namespace SHADE
{
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 */
/*---------------------------------------------------------------------------------*/
@ -63,6 +77,28 @@ namespace SHADE
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>
inline ISelfHandle<T>::ISelfHandle(const ISelfHandle& rhs)
: handle { rhs.handle }
@ -73,6 +109,9 @@ namespace SHADE
: handle { rhs.handle }
{}
/*---------------------------------------------------------------------------------*/
/* ISelfHandle<T> - Overloaded Operators */
/*---------------------------------------------------------------------------------*/
template<typename T>
inline ISelfHandle<T>& ISelfHandle<T>::operator=(const ISelfHandle& rhs)
{

View File

@ -11,13 +11,31 @@
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>
/// Generic Resource Library for a specified type of Resource. This object will own
/// any resources created using it.
/// </summary>
/// <typeparam name="T">Type of resources that this library stores.</typeparam>
template<typename T>
class SHResourceLibrary
class SHResourceLibrary : public SHResourceLibraryBase
{
public:
/*-----------------------------------------------------------------------------*/

View File

@ -13,10 +13,11 @@ namespace SHADE
SHResourceLibrary<T>::SHResourceLibrary()
{
// 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_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 */
/*-----------------------------------------------------------------------------------*/
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::vector<AssetID> SHResourceManager::loadedAssetData;

View File

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

View File

@ -36,7 +36,7 @@ namespace SHADE
/* Attempt to get existing loaded asset */
AssetHandleMap& typedHandleMap = getAssetHandleMap<ResourceType>();
if (typedHandleMap.contains(assetId))
return typedHandleMap[assetId];
return Handle<ResourceType>(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)