#include "assetmgr.h" #include "tier2/ifilesystem.h" #include "tier2/fileformats/json.h" #include "game.h" #define MAX_MODEL_COUNT 2048 #define MAX_MESH_COUNT 2048 #define MAX_MATERIAL_COUNT 2048 #define MAX_TEXTURE_COUNT 4096 #define MAX_SHADER_COUNT 1024 #define MAX_PHYSICAL_MESH_COUNT 1024 #define MAX_PHYSICAL_MATERIAL_COUNT 512 template class CAssetArc { struct ObjectHandle_t { CUtlString m_szName; uint32_t m_uUsageCount; T *m_pObject; }; ObjectHandle_t m_objects[nCount] = {}; public: uint32_t GetOrCreateObject( const char *szName, bool *pbHasBeenCreated ) { uint32_t uFoundIndex = 1; for ( uint32_t u = 1; u < nCount; u++ ) { if (m_objects[u].m_pObject == NULL) { continue; } if (m_objects[u].m_szName == szName) { m_objects[u].m_uUsageCount++; if (pbHasBeenCreated) *pbHasBeenCreated = false; return u; } } for ( auto &m: m_objects) { if (m.m_pObject == NULL) break; uFoundIndex++; } m_objects[uFoundIndex].m_szName = szName; m_objects[uFoundIndex].m_uUsageCount++; m_objects[uFoundIndex].m_pObject = (T*)V_malloc(sizeof(T)); if (pbHasBeenCreated) *pbHasBeenCreated = true; return uFoundIndex; } T *GetObjectPtr( uint32_t uIndex ) { if (uIndex >= nCount) return 0; return m_objects[uIndex].m_pObject; } void UnrefObject( uint32_t uIndex ) { if (uIndex >= nCount) return; m_objects[uIndex].m_uUsageCount--; if (m_objects[uIndex].m_uUsageCount == 0) { V_free(m_objects[uIndex].m_pObject); m_objects[uIndex].m_pObject = NULL; m_objects[uIndex].m_szName = NULL; } } }; class CAssetManager: public IAssetManager { public: virtual HFunnyModel LoadModel( const char *szName ) override; virtual FunnyModel_t *GetModelByIndex( HFunnyModel hModel ) override; virtual void UnrefModel( HFunnyModel uIndex ) override; virtual HFunnyMesh LoadMesh( const char *szName ) override; virtual FunnyMesh_t *GetMeshByIndex( HFunnyMesh hMesh ) override; virtual void UnrefMesh( HFunnyMesh hMesh ) override; virtual HFunnyMaterial LoadMaterial( const char *szName ) override; virtual FunnyMaterial_t *GetMaterialByIndex( HFunnyMaterial hMat ) override; virtual void UnrefMaterial( HFunnyMaterial hMat ) override; virtual HFunnyPhysicalMesh LoadPhysicalMesh( const char *szName ) override; virtual FunnyPhysicalMesh_t *GetPhysicalMeshByIndex( HFunnyPhysicalMesh hPhysicalMesh ) override; virtual void UnrefPhysicalMesh( HFunnyPhysicalMesh hPhysicalMesh ) override; virtual HFunnyPhysicalMaterial LoadPhysicalMaterial( const char *szName ) override; virtual FunnyPhysicalMaterial_t *GetPhysicalMaterialByIndex( HFunnyPhysicalMaterial hPhysicalMaterial ) override; virtual void UnrefPhysicalMaterial( HFunnyPhysicalMaterial hPhysicalMaterial ) override; uint32_t LoadShader( const char *szName ); IShader **GetShaderByIndex( uint32_t hShader ); void UnrefShader( uint32_t hShader ); CAssetArc m_models = {}; CAssetArc m_meshes = {}; CAssetArc m_materials = {}; CAssetArc m_shaders = {}; }; FunnyModel_t *CAssetManager::GetModelByIndex( uint32_t uIndex ) { return m_models.GetObjectPtr(uIndex); } FunnyMaterial_t *CAssetManager::GetMaterialByIndex( uint32_t uIndex ) { return m_materials.GetObjectPtr(uIndex); } IShader **CAssetManager::GetShaderByIndex( uint32_t uIndex ) { return m_shaders.GetObjectPtr(uIndex); } FunnyMesh_t *CAssetManager::GetMeshByIndex( uint32_t uIndex ) { return m_meshes.GetObjectPtr(uIndex); } uint32_t CAssetManager::LoadModel( const char *szName ) { bool bHasBeenCreated = false; HFunnyModel hModel = m_models.GetOrCreateObject(szName, &bHasBeenCreated); if (!bHasBeenCreated) return hModel; FunnyModel_t *pModel = m_models.GetObjectPtr(hModel); IFileHandle *pHandle = filesystem->Open(szName, FILEMODE_READ); if (!pHandle) return 0; CUtlString szProperties = filesystem->ReadString(pHandle); IJSONValue *pRoot = JSONManager()->ReadString(szProperties); filesystem->Close(pHandle); if (!pRoot) return 0; IJSONObject *pMainObject; CUtlString szMeshData; IVertexBuffer *pVertices; switch (pRoot->GetType()) { case JSON_PARAMETER_OBJECT: { pMainObject = pRoot->GetObject(); if (!pMainObject) { V_printf("Failed to load properties\n"); return 0; } IJSONValue *pMesh = pMainObject->GetValue("mesh"); IJSONValue *pMaterial = pMainObject->GetValue("material"); if (pMesh) pModel->m_hMesh = LoadMesh(pMesh->GetStringValue()); if (pMaterial) pModel->m_hMaterial = LoadMaterial(pMaterial->GetStringValue()); return hModel; } break; default: return 0; } } void CAssetManager::UnrefModel( uint32_t uIndex ) { } uint32_t CAssetManager::LoadMaterial( const char *szName ) { bool bHasBeenCreated = false; HFunnyMaterial hMaterial = m_materials.GetOrCreateObject(szName, &bHasBeenCreated); if (!bHasBeenCreated) return hMaterial; FunnyMaterial_t *pMaterial = m_materials.GetObjectPtr(hMaterial); IFileHandle *pHandle = filesystem->Open(szName, FILEMODE_READ); if (!pHandle) return 0; CUtlString szProperties = filesystem->ReadString(pHandle); IJSONValue *pRoot = JSONManager()->ReadString(szProperties); if (!pRoot) return 0; IJSONObject *pMainObject; switch (pRoot->GetType()) { case JSON_PARAMETER_OBJECT: { pMainObject = pRoot->GetObject(); if (!pMainObject) { V_printf("Failed to load properties\n"); return 0; } IJSONValue *pShaderValue = pMainObject->GetValue("shader"); CUtlString szShader = pShaderValue->GetStringValue(); CBaseMaterial *pRenderMaterial = CreateMaterial(szShader); uint32_t uShaderId = LoadShader(pRenderMaterial->GetShaderPath()); if (!uShaderId) return 0; IShader **ppShader = GetShaderByIndex(uShaderId); pMaterial->m_pShaders = *ppShader; pMaterial->m_pMaterial = g_pRenderContext->CreateMaterial(*ppShader); pMaterial->m_pLayout = pRenderMaterial; return hMaterial; } break; default: return 0; } return hMaterial; } void CAssetManager::UnrefMaterial( uint32_t uIndex ) { } HFunnyMesh CAssetManager::LoadMesh( const char *szName ) { bool bHasBeenCreated = false; HFunnyMesh hAsset = m_meshes.GetOrCreateObject(szName, &bHasBeenCreated); if (!bHasBeenCreated) return hAsset; FunnyMesh_t *pMesh = m_meshes.GetObjectPtr(hAsset); IFileHandle *hMesh = filesystem->Open(szName, FILEMODE_READ); if ( hMesh == NULL ) { V_printf("Failed to load %s\n", szName); m_meshes.UnrefObject(hAsset); return 0; } IVertexBuffer *pVertexBuffer = g_pRenderContext->CreateVertexBuffer(filesystem->Size(hMesh)); pVertexBuffer->Lock(); void *pMapped = pVertexBuffer->Map(); filesystem->Read(hMesh, pMapped, pVertexBuffer->GetSize()); pVertexBuffer->Unmap(); pVertexBuffer->Unlock(); pMesh->m_pMesh = g_pWorldRenderer->CreateMesh(szName); pMesh->m_pMesh->SetVertices(pVertexBuffer); return hAsset; } void CAssetManager::UnrefMesh( uint32_t uIndex ) { m_meshes.UnrefObject(uIndex); } uint32_t CAssetManager::LoadShader( const char *szName ) { bool bHasBeenCreated = false; uint32_t hShader = m_shaders.GetOrCreateObject(szName, &bHasBeenCreated); if (!bHasBeenCreated) return hShader; IShader **ppShader = m_shaders.GetObjectPtr(hShader); IShader *pShader = g_pRenderContext->CreateShader(szName); if ( pShader == NULL ) { V_printf("Failed to load %s\n", szName); return 0; } *ppShader = pShader; return hShader; } void CAssetManager::UnrefShader( uint32_t uIndex ) { } HFunnyPhysicalMesh CAssetManager::LoadPhysicalMesh( const char *szName ) { } FunnyPhysicalMesh_t *CAssetManager::GetPhysicalMeshByIndex( HFunnyPhysicalMesh hPhysicalMesh ) { } void CAssetManager::UnrefPhysicalMesh( HFunnyPhysicalMesh hPhysicalMesh ) { } HFunnyPhysicalMaterial CAssetManager::LoadPhysicalMaterial( const char *szName ) { } FunnyPhysicalMaterial_t *CAssetManager::GetPhysicalMaterialByIndex( HFunnyPhysicalMaterial hPhysicalMaterial ) { } void CAssetManager::UnrefPhysicalMaterial( HFunnyPhysicalMaterial hPhysicalMaterial ) { } static CAssetManager s_assetmgr; IAssetManager *g_pAssetManager = &s_assetmgr;