#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_PHYSICS_COUNT 1024 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 HFunnyPhysics LoadPhysics( const char *szName ) override; virtual FunnyPhysics_t *GetPhysicsByIndex( HFunnyPhysics hPhysics ) override; virtual void UnrefPhysics( HFunnyPhysics hPhysics ) override; uint32_t LoadShader( const char *szName ); IShader **GetShaderByIndex( uint32_t hShader ); void UnrefShader( uint32_t hShader ); virtual HFunnyTexture LoadTexture( const char *szName ) override; virtual FunnyTexture_t *GetTextureByIndex( HFunnyTexture hTexture ) override; virtual void UnrefTexture( HFunnyTexture hTexture ) override; void LoadMaterialData( CBaseMaterial *pMaterial, IJSONObject *pObj ); CAssetArc m_models = {}; CAssetArc m_meshes = {}; CAssetArc m_materials = {}; CAssetArc m_textures = {}; CAssetArc m_shaders = {}; CAssetArc m_physics = {}; }; 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"); IJSONValue *pPhysics = pMainObject->GetValue("Physics"); V_printf("%s\n", pMaterial->GetStringValue()); if (pMesh) pModel->m_hMesh = LoadMesh(pMesh->GetStringValue()); if (pMaterial) pModel->m_hMaterial = LoadMaterial(pMaterial->GetStringValue()); if (pPhysics) pModel->m_hPhysics = LoadPhysics(pPhysics->GetStringValue()); return hModel; } break; default: return 0; } } void CAssetManager::UnrefModel( uint32_t uIndex ) { } void CAssetManager::LoadMaterialData( CBaseMaterial *pMaterial, IJSONObject *pObj ) { for ( int i = 0; i < pMaterial->GetDataMap()->m_iNumFields; i++ ) { typedescription_t desc = pMaterial->GetDataMap()->m_pData[i]; IJSONValue *pValue = pObj->GetValue(desc.m_szEditorName); switch ( desc.m_eFieldType ) { case FIELD_SHADER_TEXTURE: { FMat::XMTexture *texture = (FMat::XMTexture*)((char*)pMaterial+desc.m_iFieldOffset); if ( pValue->GetType() == JSON_PARAMETER_STRING ) *texture = GetTextureByIndex(LoadTexture(pValue->GetStringValue()))->m_hTexture; break; } case FIELD_SHADER_COLOR_FLOAT4: { FMat::XMFLOAT4 *data = (FMat::XMFLOAT4*)((char*)pMaterial+desc.m_iFieldOffset); if ( pValue->GetArray()->GetParameter(0)->GetType() == JSON_PARAMETER_NUMBER ) data->x = pValue->GetArray()->GetParameter(0)->GetNumberValue(); if ( pValue->GetArray()->GetParameter(1)->GetType() == JSON_PARAMETER_NUMBER ) data->y = pValue->GetArray()->GetParameter(1)->GetNumberValue(); if ( pValue->GetArray()->GetParameter(2)->GetType() == JSON_PARAMETER_NUMBER ) data->z = pValue->GetArray()->GetParameter(2)->GetNumberValue(); if ( pValue->GetArray()->GetParameter(3)->GetType() == JSON_PARAMETER_NUMBER ) data->w = pValue->GetArray()->GetParameter(3)->GetNumberValue(); V_printf("%s %f %f %f %f\n", desc.m_szEditorName, data->x, data->y, data->z, data->w); break; } default: break; } } } 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); LoadMaterialData(pRenderMaterial, pMainObject); 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); m_shaders.UnrefObject(hShader); return 0; } *ppShader = pShader; return hShader; } void CAssetManager::UnrefShader( uint32_t uIndex ) { m_shaders.UnrefObject(uIndex); } HFunnyTexture CAssetManager::LoadTexture( const char *szName ) { bool bHasBeenCreated = false; uint32_t hTexture = m_textures.GetOrCreateObject(szName, &bHasBeenCreated); if (!bHasBeenCreated) return hTexture; FunnyTexture_t *pTexture = m_textures.GetObjectPtr(hTexture); uint32_t hTex = g_pWorldRenderer->GetTextures()->LoadTexture(szName); if ( hTex == 0 ) { V_printf("Failed to load %s\n", szName); m_textures.UnrefObject(hTexture); return 0; } pTexture->m_hTexture = hTex; return hTexture; } FunnyTexture_t *CAssetManager::GetTextureByIndex( HFunnyTexture hTexture ) { return m_textures.GetObjectPtr(hTexture); } void CAssetManager::UnrefTexture( uint32_t hTexture ) { } HFunnyPhysics CAssetManager::LoadPhysics( const char *szName ) { bool bHasBeenCreated = false; HFunnyPhysics hPhysics = m_physics.GetOrCreateObject(szName, &bHasBeenCreated); if (!bHasBeenCreated) return hPhysics; FunnyPhysics_t *pPhysics = m_physics.GetObjectPtr(hPhysics); 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"); m_physics.UnrefObject(hPhysics); return 0; } IJSONValue *pTypeValue = pMainObject->GetValue("Type"); if (!pTypeValue) { V_printf("\"Type\" must be specified\n"); m_physics.UnrefObject(hPhysics); return 0; } CUtlString szType = pTypeValue->GetStringValue(); if (szType == "Sphere") { pPhysics->m_hShape = g_pPhysics->CreateBall({0.1}); } return hPhysics; } break; default: return 0; } return hPhysics; } FunnyPhysics_t *CAssetManager::GetPhysicsByIndex( HFunnyPhysics hPhysics ) { return m_physics.GetObjectPtr(hPhysics); } void CAssetManager::UnrefPhysics( HFunnyPhysics hPhysics ) { m_physics.UnrefObject(hPhysics); } static CAssetManager s_assetmgr; IAssetManager *g_pAssetManager = &s_assetmgr;