Added dependency tree system, methods for generating dependency trees from resources, and saving/loading dependency trees to the project cache folder

This commit is contained in:
parax0
2016-07-25 02:12:30 -06:00
parent c1405bfac1
commit 9341c11ac8
30 changed files with 886 additions and 56 deletions

View File

@@ -10,7 +10,7 @@ CGameArea::CGameArea(CResourceEntry *pEntry /*= 0*/)
, mTerrainMerged(false)
, mOriginalWorldMeshCount(0)
, mUsesCompression(false)
, mMaterialSet(nullptr)
, mpMaterialSet(nullptr)
, mpGeneratorLayer(nullptr)
, mpCollision(nullptr)
{
@@ -31,6 +31,32 @@ CGameArea::~CGameArea()
delete mLightLayers[iLyr][iLight];
}
CDependencyTree* CGameArea::BuildDependencyTree() const
{
// Base dependencies
CAreaDependencyTree *pTree = new CAreaDependencyTree(ResID());
for (u32 iMat = 0; iMat < mpMaterialSet->NumMaterials(); iMat++)
{
CMaterial *pMat = mpMaterialSet->MaterialByIndex(iMat);
pTree->AddDependency(pMat->IndTexture());
for (u32 iPass = 0; iPass < pMat->PassCount(); iPass++)
pTree->AddDependency(pMat->Pass(iPass)->Texture());
}
pTree->AddDependency(mpPoiToWorldMap);
Log::Warning("CGameArea::FindDependencies not handling PATH/PTLA");
// Layer dependencies
for (u32 iLayer = 0; iLayer < mScriptLayers.size(); iLayer++)
pTree->AddScriptLayer(mScriptLayers[iLayer]);
pTree->AddScriptLayer(mpGeneratorLayer);
return pTree;
}
void CGameArea::AddWorldModel(CModel *pModel)
{
mWorldModels.push_back(pModel);
@@ -52,7 +78,7 @@ void CGameArea::MergeTerrain()
for (u32 iSurf = 0; iSurf < SubmeshCount; iSurf++)
{
SSurface *pSurf = pMdl->GetSurface(iSurf);
CMaterial *pMat = mMaterialSet->MaterialByIndex(pSurf->MaterialID);
CMaterial *pMat = mpMaterialSet->MaterialByIndex(pSurf->MaterialID);
bool NewMat = true;
for (std::vector<CStaticModel*>::iterator it = mStaticWorldModels.begin(); it != mStaticWorldModels.end(); it++)
@@ -93,7 +119,7 @@ void CGameArea::ClearTerrain()
delete mStaticWorldModels[iStatic];
mStaticWorldModels.clear();
if (mMaterialSet) delete mMaterialSet;
if (mpMaterialSet) delete mpMaterialSet;
mVertexCount = 0;
mTriangleCount = 0;

View File

@@ -45,7 +45,7 @@ class CGameArea : public CResource
std::vector<SSectionNumber> mSectionNumbers;
// Geometry
CMaterialSet *mMaterialSet;
CMaterialSet *mpMaterialSet;
std::vector<CModel*> mWorldModels; // TerrainModels is the original version of each model; this is currently mainly used in the POI map editor
std::vector<CStaticModel*> mStaticWorldModels; // StaticTerrainModels is the merged terrain for faster rendering in the world editor
// Script
@@ -62,6 +62,7 @@ class CGameArea : public CResource
public:
CGameArea(CResourceEntry *pEntry = 0);
~CGameArea();
CDependencyTree* BuildDependencyTree() const;
void AddWorldModel(CModel *pModel);
void MergeTerrain();

View File

@@ -28,6 +28,7 @@ public:
// Accessors
inline EGame Version() const { return mGame; }
inline CUniqueID ID() const { return mCharacter.ID(); }
inline CAnimSet* AnimSet() const { return (CAnimSet*) mCharacter.Load(); }
inline u32 CharacterIndex() const { return mCharIndex; }
inline u32 AnimIndex() const { return mAnimIndex; }

View File

@@ -0,0 +1,33 @@
#ifndef CDEPENDENCYGROUP
#define CDEPENDENCYGROUP
#include "CResource.h"
class CDependencyGroup : public CResource
{
DECLARE_RESOURCE_TYPE(eDependencyGroup)
std::set<CUniqueID> mDependencies;
public:
CDependencyGroup(CResourceEntry *pEntry = 0) : CResource(pEntry) {}
inline void AddDependency(const CUniqueID& rkID) { mDependencies.insert(rkID); }
inline void AddDependency(CResource *pRes) { if (pRes) mDependencies.insert(pRes->ResID()); }
inline void RemoveDependency(const CUniqueID& rkID) { mDependencies.erase(rkID); }
inline void Clear() { mDependencies.clear(); }
inline bool HasDependency(const CUniqueID& rkID) const { return mDependencies.find(rkID) != mDependencies.end(); }
inline u32 NumDependencies() const { return mDependencies.size(); }
inline CUniqueID DependencyByIndex(u32 Index) const { return *std::next(mDependencies.begin(), Index); }
CDependencyTree* BuildDependencyTree() const
{
CDependencyTree *pTree = new CDependencyTree(ResID());
for (auto DepIt = mDependencies.begin(); DepIt != mDependencies.end(); DepIt++)
pTree->AddDependency(*DepIt);
return pTree;
}
};
#endif // CDEPENDENCYGROUP

View File

@@ -22,6 +22,13 @@ inline float PtsToFloat(s32 Pt)
return 0.00208333f * Pt;
}
CDependencyTree* CFont::BuildDependencyTree() const
{
CDependencyTree *pOut = new CDependencyTree(ResID());
pOut->AddDependency(mpFontTexture);
return pOut;
}
CVector2f CFont::RenderString(const TString& rkString, CRenderer* /*pRenderer*/, float /*AspectRatio*/,
CVector2f /*Position*/, CColor FillColor, CColor StrokeColor, u32 FontSize)
{

View File

@@ -60,6 +60,7 @@ class CFont : public CResource
public:
CFont(CResourceEntry *pEntry = 0);
~CFont();
CDependencyTree* BuildDependencyTree() const;
CVector2f RenderString(const TString& rkString, CRenderer *pRenderer, float AspectRatio,
CVector2f Position = CVector2f(0,0),
CColor FillColor = CColor::skWhite, CColor StrokeColor = CColor::skBlack,

View File

@@ -2,6 +2,7 @@
#define CRESOURCE_H
#include "EResType.h"
#include "Core/GameProject/CDependencyTree.h"
#include "Core/GameProject/CResourceEntry.h"
#include "Core/GameProject/CResourceStore.h"
#include <Common/CFourCC.h>
@@ -39,7 +40,8 @@ public:
}
virtual ~CResource() {}
virtual CDependencyTree* BuildDependencyTree() const { return new CDependencyTree(ResID()); }
inline CResourceEntry* Entry() const { return mpEntry; }
inline TString Source() const { return mpEntry ? mpEntry->CookedAssetPath(true).GetFileName() : ""; }
inline TString FullSource() const { return mpEntry ? mpEntry->CookedAssetPath(true) : ""; }

View File

@@ -40,6 +40,17 @@ public:
, mCategory(eNone)
{}
CDependencyTree* BuildDependencyTree() const
{
if (Game() >= eEchoesDemo)
Log::Warning("CScan::BuildDependencyTree not handling Echoes/Corruption dependencies");
CDependencyTree *pTree = new CDependencyTree(ResID());
pTree->AddDependency(mpFrame);
pTree->AddDependency(mpStringTable);
return pTree;
}
EGame Version() const { return mVersion; }
CStringTable* ScanText() const { return mpStringTable; }
bool IsImportant() const { return mIsImportant; }

View File

@@ -17,6 +17,28 @@ CWorld::~CWorld()
{
}
CDependencyTree* CWorld::BuildDependencyTree() const
{
CDependencyTree *pTree = new CDependencyTree(ResID());
for (u32 iArea = 0; iArea < mAreas.size(); iArea++)
{
pTree->AddDependency(mAreas[iArea].FileID);
pTree->AddDependency(mAreas[iArea].pAreaName);
}
pTree->AddDependency(mpWorldName);
pTree->AddDependency(mpDarkWorldName);
pTree->AddDependency(mpSaveWorld);
pTree->AddDependency(mpDefaultSkybox);
pTree->AddDependency(mpMapWorld);
if (Game() <= ePrime)
Log::Warning("CWorld::BuildDependencyTree not handling audio groups");
return pTree;
}
void CWorld::SetAreaLayerInfo(CGameArea *pArea)
{
// The AreaIndex parameter is a placeholder until an improved world loader is implemented.

View File

@@ -84,6 +84,7 @@ public:
CWorld(CResourceEntry *pEntry = 0);
~CWorld();
CDependencyTree* BuildDependencyTree() const;
void SetAreaLayerInfo(CGameArea *pArea);
// Accessors

View File

@@ -73,7 +73,7 @@ void CAreaLoader::ReadGeometryPrime()
mpSectionMgr->ToSection(mGeometryBlockNum);
// Materials
mpArea->mMaterialSet = CMaterialLoader::LoadMaterialSet(*mpMREA, mVersion);
mpArea->mpMaterialSet = CMaterialLoader::LoadMaterialSet(*mpMREA, mVersion);
mpSectionMgr->ToNextSection();
// Geometry
@@ -81,7 +81,7 @@ void CAreaLoader::ReadGeometryPrime()
for (u32 iMesh = 0; iMesh < mNumMeshes; iMesh++)
{
CModel *pModel = CModelLoader::LoadWorldModel(*mpMREA, *mpSectionMgr, *mpArea->mMaterialSet, mVersion);
CModel *pModel = CModelLoader::LoadWorldModel(*mpMREA, *mpSectionMgr, *mpArea->mpMaterialSet, mVersion);
FileModels.push_back(pModel);
if (mVersion <= ePrime)
@@ -394,7 +394,7 @@ void CAreaLoader::ReadGeometryCorruption()
mpSectionMgr->ToSection(mGeometryBlockNum);
// Materials
mpArea->mMaterialSet = CMaterialLoader::LoadMaterialSet(*mpMREA, mVersion);
mpArea->mpMaterialSet = CMaterialLoader::LoadMaterialSet(*mpMREA, mVersion);
mpSectionMgr->ToNextSection();
// Geometry
@@ -404,7 +404,7 @@ void CAreaLoader::ReadGeometryCorruption()
for (u32 iMesh = 0; iMesh < mNumMeshes; iMesh++)
{
CModel *pWorldModel = CModelLoader::LoadCorruptionWorldModel(*mpMREA, *mpSectionMgr, *mpArea->mMaterialSet, CurWOBJSection, CurGPUSection, mVersion);
CModel *pWorldModel = CModelLoader::LoadCorruptionWorldModel(*mpMREA, *mpSectionMgr, *mpArea->mpMaterialSet, CurWOBJSection, CurGPUSection, mVersion);
FileModels.push_back(pWorldModel);
CurWOBJSection += 4;

View File

@@ -0,0 +1,48 @@
#include "CDependencyGroupLoader.h"
#include <Common/AssertMacro.h>
EGame CDependencyGroupLoader::VersionTest(IInputStream& rDGRP, u32 DepCount)
{
// Only difference between versions is asset ID length. Just check for EOF with 32-bit ID length.
u32 Start = rDGRP.Tell();
rDGRP.Seek(DepCount * 4, SEEK_CUR);
u32 Remaining = rDGRP.Size() - Start;
EGame Game = ePrimeDemo;
if (Remaining < 32)
{
for (u32 iRem = 0; iRem < Remaining; iRem++)
{
if (rDGRP.ReadByte() != 0xFF)
{
Game = eCorruptionProto;
break;
}
}
}
rDGRP.Seek(Start, SEEK_SET);
return Game;
}
CDependencyGroup* CDependencyGroupLoader::LoadDGRP(IInputStream& rDGRP, CResourceEntry *pEntry)
{
if (!rDGRP.IsValid()) return nullptr;
u32 NumDependencies = rDGRP.ReadLong();
EGame Game = VersionTest(rDGRP, NumDependencies);
EUIDLength IDLength = (Game < eCorruptionProto ? e32Bit : e64Bit);
CDependencyGroup *pGroup = new CDependencyGroup(pEntry);
pGroup->SetGame(Game);
for (u32 iDep = 0; iDep < NumDependencies; iDep++)
{
rDGRP.Seek(0x4, SEEK_CUR); // Skip dependency type
CUniqueID AssetID(rDGRP, IDLength);
pGroup->AddDependency(AssetID);
}
return pGroup;
}

View File

@@ -0,0 +1,16 @@
#ifndef CDEPENDENCYGROUPLOADER_H
#define CDEPENDENCYGROUPLOADER_H
#include "Core/Resource/CDependencyGroup.h"
#include "Core/Resource/EGame.h"
class CDependencyGroupLoader
{
CDependencyGroupLoader() {}
static EGame VersionTest(IInputStream& rDGRP, u32 DepCount);
public:
static CDependencyGroup* LoadDGRP(IInputStream& rDGRP, CResourceEntry *pEntry);
};
#endif // CDEPENDENCYGROUPLOADER_H

View File

@@ -65,7 +65,7 @@ void CMaterialLoader::ReadPrimeMatSet()
{
mpSet->mMaterials[iMat] = ReadPrimeMaterial();
mpSet->mMaterials[iMat]->mVersion = mVersion;
mpSet->mMaterials[iMat]->mName = TString("Material #") + std::to_string(iMat + 1);
mpSet->mMaterials[iMat]->mName = TString("Material #") + TString::FromInt32(iMat + 1, 0, 10);
mpFile->Seek(MatsStart + Offsets[iMat], SEEK_SET);
}
}
@@ -261,7 +261,7 @@ void CMaterialLoader::ReadCorruptionMatSet()
u32 Next = mpFile->Tell() + Size;
mpSet->mMaterials[iMat] = ReadCorruptionMaterial();
mpSet->mMaterials[iMat]->mVersion = mVersion;
mpSet->mMaterials[iMat]->mName = TString("Material #") + std::to_string(iMat + 1);
mpSet->mMaterials[iMat]->mName = TString("Material #") + TString::FromInt32(iMat + 1, 0, 10);
mpFile->Seek(Next, SEEK_SET);
}
}

View File

@@ -29,6 +29,31 @@ CModel::~CModel()
delete mMaterialSets[iMat];
}
CDependencyTree* CModel::BuildDependencyTree() const
{
CDependencyTree *pTree = new CDependencyTree(ResID());
for (u32 iSet = 0; iSet < mMaterialSets.size(); iSet++)
{
CMaterialSet *pSet = mMaterialSets[iSet];
for (u32 iMat = 0; iMat < pSet->NumMaterials(); iMat++)
{
CMaterial *pMat = pSet->MaterialByIndex(iMat);
pTree->AddDependency(pMat->IndTexture());
for (u32 iPass = 0; iPass < pMat->PassCount(); iPass++)
{
CMaterialPass *pPass = pMat->Pass(iPass);
pTree->AddDependency(pPass->Texture());
}
}
}
return pTree;
}
void CModel::BufferGL()
{
if (!mBuffered)

View File

@@ -25,6 +25,7 @@ public:
CModel(CMaterialSet *pSet, bool OwnsMatSet);
~CModel();
CDependencyTree* BuildDependencyTree() const;
void BufferGL();
void GenerateMaterialShaders();
void ClearGLBuffer();

View File

@@ -63,6 +63,7 @@ bool CScriptObject::IsEditorProperty(IProperty *pProp)
(pProp == mpRotation) ||
(pProp == mpScale) ||
(pProp == mpActive) ||
(pProp == mpLightParameters) ||
(pProp->Parent() == mpLightParameters)
);
}