Added support for gathering dependencies of ANCS and FRME; changed CDependencyGroup to use a vector instead of a set
This commit is contained in:
parent
11a7b86120
commit
3bca8410b0
|
@ -154,6 +154,31 @@ void CAnimSetDependencyTree::Write(IOutputStream& rFile, EIDLength IDLength) con
|
|||
rFile.WriteLong( mCharacterOffsets[iChar] );
|
||||
}
|
||||
|
||||
void CAnimSetDependencyTree::AddCharacter(const SSetCharacter *pkChar)
|
||||
{
|
||||
mCharacterOffsets.push_back( NumDependencies() );
|
||||
if (!pkChar) return;
|
||||
|
||||
AddDependency(pkChar->pModel);
|
||||
AddDependency(pkChar->pSkeleton);
|
||||
AddDependency(pkChar->pSkin);
|
||||
|
||||
const std::vector<CAssetID> *pkParticleVectors[5] = {
|
||||
&pkChar->GenericParticles, &pkChar->ElectricParticles,
|
||||
&pkChar->SwooshParticles, &pkChar->SpawnParticles,
|
||||
&pkChar->EffectParticles
|
||||
};
|
||||
|
||||
for (u32 iVec = 0; iVec < 5; iVec++)
|
||||
{
|
||||
for (u32 iPart = 0; iPart < pkParticleVectors[iVec]->size(); iPart++)
|
||||
AddDependency(pkParticleVectors[iVec]->at(iPart));
|
||||
}
|
||||
|
||||
AddDependency(pkChar->IceModel);
|
||||
AddDependency(pkChar->IceSkin);
|
||||
}
|
||||
|
||||
// ************ CScriptInstanceDependencyTree ************
|
||||
CScriptInstanceDependencyTree::~CScriptInstanceDependencyTree()
|
||||
{
|
||||
|
|
|
@ -10,6 +10,7 @@ class CScriptLayer;
|
|||
class CScriptObject;
|
||||
class CPropertyStruct;
|
||||
class TCharacterProperty;
|
||||
struct SSetCharacter;
|
||||
|
||||
// Group of node classes forming a tree of cached resource dependencies.
|
||||
enum EDependencyNodeType
|
||||
|
@ -109,6 +110,8 @@ public:
|
|||
virtual EDependencyNodeType Type() const;
|
||||
virtual void Read(IInputStream& rFile, EIDLength IDLength);
|
||||
virtual void Write(IOutputStream& rFile, EIDLength IDLength) const;
|
||||
|
||||
void AddCharacter(const SSetCharacter *pkChar);
|
||||
};
|
||||
|
||||
// Node representing a script object. Indicates the type of object.
|
||||
|
|
|
@ -116,9 +116,12 @@ bool CResourceEntry::SaveCacheData()
|
|||
|
||||
u32 DepsStart = File.Tell();
|
||||
if (mpDependencies) mpDependencies->Write(File, Game() <= eEchoes ? e32Bit : e64Bit);
|
||||
u32 DepsSize = File.Tell() - DepsStart;
|
||||
u32 DepsEnd = File.Tell();
|
||||
u32 DepsSize = DepsEnd- DepsStart;
|
||||
|
||||
File.Seek(DepsSizeOffset, SEEK_SET);
|
||||
File.WriteLong(DepsSize);
|
||||
File.Seek(DepsEnd, SEEK_SET);
|
||||
|
||||
// Thumbnail
|
||||
File.WriteLong(0); // Reserved Space (Thumbnail Size)
|
||||
|
@ -262,6 +265,7 @@ CResource* CResourceEntry::Load(IInputStream& rInput)
|
|||
case eDependencyGroup: mpResource = CDependencyGroupLoader::LoadDGRP(rInput, this); break;
|
||||
case eDynamicCollision: mpResource = CCollisionLoader::LoadDCLN(rInput, this); break;
|
||||
case eFont: mpResource = CFontLoader::LoadFONT(rInput, this); break;
|
||||
case eGuiFrame: mpResource = CUnsupportedFormatLoader::LoadFRME(rInput, this); break;
|
||||
case eHintSystem: mpResource = CUnsupportedFormatLoader::LoadHINT(rInput, this); break;
|
||||
case eMapWorld: mpResource = CUnsupportedFormatLoader::LoadMAPW(rInput, this); break;
|
||||
case eMapUniverse: mpResource = CUnsupportedFormatLoader::LoadMAPU(rInput, this); break;
|
||||
|
|
|
@ -12,21 +12,28 @@
|
|||
#include <vector>
|
||||
|
||||
// will expand later! this is where animation support will come in
|
||||
struct SSetCharacter
|
||||
{
|
||||
TString Name;
|
||||
TResPtr<CModel> pModel;
|
||||
TResPtr<CSkin> pSkin;
|
||||
TResPtr<CSkeleton> pSkeleton;
|
||||
|
||||
std::vector<CAssetID> GenericParticles;
|
||||
std::vector<CAssetID> ElectricParticles;
|
||||
std::vector<CAssetID> SwooshParticles;
|
||||
std::vector<CAssetID> SpawnParticles;
|
||||
std::vector<CAssetID> EffectParticles;
|
||||
CAssetID IceModel;
|
||||
CAssetID IceSkin;
|
||||
};
|
||||
|
||||
class CAnimSet : public CResource
|
||||
{
|
||||
DECLARE_RESOURCE_TYPE(eAnimSet)
|
||||
friend class CAnimSetLoader;
|
||||
|
||||
struct SNode
|
||||
{
|
||||
TString Name;
|
||||
TResPtr<CModel> pModel;
|
||||
TResPtr<CSkin> pSkin;
|
||||
TResPtr<CSkeleton> pSkeleton;
|
||||
|
||||
SNode() { pModel = nullptr; }
|
||||
};
|
||||
std::vector<SNode> mNodes;
|
||||
std::vector<SSetCharacter> mCharacters;
|
||||
|
||||
struct SAnimation
|
||||
{
|
||||
|
@ -38,15 +45,28 @@ class CAnimSet : public CResource
|
|||
public:
|
||||
CAnimSet(CResourceEntry *pEntry = 0) : CResource(pEntry) {}
|
||||
|
||||
u32 NumNodes() const { return mNodes.size(); }
|
||||
TString NodeName(u32 Index) { if (Index >= mNodes.size()) Index = 0; return mNodes[Index].Name; }
|
||||
CModel* NodeModel(u32 Index) { if (Index >= mNodes.size()) Index = 0; return mNodes[Index].pModel; }
|
||||
CSkin* NodeSkin(u32 Index) { if (Index >= mNodes.size()) Index = 0; return mNodes[Index].pSkin; }
|
||||
CSkeleton* NodeSkeleton(u32 Index) { if (Index >= mNodes.size()) Index = 0; return mNodes[Index].pSkeleton; }
|
||||
u32 NumNodes() const { return mCharacters.size(); }
|
||||
TString NodeName(u32 Index) { if (Index >= mCharacters.size()) Index = 0; return mCharacters[Index].Name; }
|
||||
CModel* NodeModel(u32 Index) { if (Index >= mCharacters.size()) Index = 0; return mCharacters[Index].pModel; }
|
||||
CSkin* NodeSkin(u32 Index) { if (Index >= mCharacters.size()) Index = 0; return mCharacters[Index].pSkin; }
|
||||
CSkeleton* NodeSkeleton(u32 Index) { if (Index >= mCharacters.size()) Index = 0; return mCharacters[Index].pSkeleton; }
|
||||
|
||||
u32 NumAnims() const { return mAnims.size(); }
|
||||
CAnimation* Animation(u32 Index) { if (Index >= mAnims.size()) Index = 0; return mAnims[Index].pAnim; }
|
||||
TString AnimName(u32 Index) { if (Index >= mAnims.size()) Index = 0; return mAnims[Index].Name; }
|
||||
|
||||
CDependencyTree* BuildDependencyTree() const
|
||||
{
|
||||
CAnimSetDependencyTree *pTree = new CAnimSetDependencyTree(ID());
|
||||
|
||||
for (u32 iAnim = 0; iAnim < mAnims.size(); iAnim++)
|
||||
pTree->AddDependency(mAnims[iAnim].pAnim);
|
||||
|
||||
for (u32 iNode = 0; iNode < mCharacters.size(); iNode++)
|
||||
pTree->AddCharacter(&mCharacters[iNode]);
|
||||
|
||||
return pTree;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CCHARACTERSET_H
|
||||
|
|
|
@ -6,18 +6,50 @@
|
|||
class CDependencyGroup : public CResource
|
||||
{
|
||||
DECLARE_RESOURCE_TYPE(eDependencyGroup)
|
||||
std::set<CAssetID> mDependencies;
|
||||
std::vector<CAssetID> mDependencies;
|
||||
|
||||
public:
|
||||
CDependencyGroup(CResourceEntry *pEntry = 0) : CResource(pEntry) {}
|
||||
inline void AddDependency(const CAssetID& rkID) { mDependencies.insert(rkID); }
|
||||
inline void AddDependency(CResource *pRes) { if (pRes) mDependencies.insert(pRes->ID()); }
|
||||
inline void RemoveDependency(const CAssetID& rkID) { mDependencies.erase(rkID); }
|
||||
|
||||
inline void Clear() { mDependencies.clear(); }
|
||||
inline bool HasDependency(const CAssetID& rkID) const { return mDependencies.find(rkID) != mDependencies.end(); }
|
||||
inline u32 NumDependencies() const { return mDependencies.size(); }
|
||||
inline CAssetID DependencyByIndex(u32 Index) const { return *std::next(mDependencies.begin(), Index); }
|
||||
inline CAssetID DependencyByIndex(u32 Index) const { return mDependencies[Index]; }
|
||||
|
||||
inline void AddDependency(const CAssetID& rkID)
|
||||
{
|
||||
if (!HasDependency(rkID))
|
||||
mDependencies.push_back(rkID);
|
||||
}
|
||||
|
||||
inline void AddDependency(CResource *pRes)
|
||||
{
|
||||
if ( pRes && !HasDependency(pRes->ID()) )
|
||||
mDependencies.push_back(pRes->ID());
|
||||
}
|
||||
|
||||
void RemoveDependency(const CAssetID& rkID)
|
||||
{
|
||||
for (auto Iter = mDependencies.begin(); Iter != mDependencies.end(); Iter++)
|
||||
{
|
||||
if (*Iter == rkID)
|
||||
{
|
||||
mDependencies.erase(Iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HasDependency(const CAssetID &rkID) const
|
||||
{
|
||||
for (u32 iDep = 0; iDep < mDependencies.size(); iDep++)
|
||||
{
|
||||
if (mDependencies[iDep] == rkID)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CDependencyTree* BuildDependencyTree() const
|
||||
{
|
||||
CDependencyTree *pTree = new CDependencyTree(ID());
|
||||
|
|
|
@ -10,11 +10,11 @@ CAnimSet* CAnimSetLoader::LoadCorruptionCHAR(IInputStream& rCHAR)
|
|||
{
|
||||
// For now, we only read enough to fetch the model
|
||||
rCHAR.Seek(0x1, SEEK_CUR);
|
||||
pSet->mNodes.resize(1);
|
||||
CAnimSet::SNode& node = pSet->mNodes[0];
|
||||
pSet->mCharacters.resize(1);
|
||||
SSetCharacter& rNode = pSet->mCharacters[0];
|
||||
|
||||
node.Name = rCHAR.ReadString();
|
||||
node.pModel = gpResourceStore->LoadResource(rCHAR.ReadLongLong(), "CMDL");
|
||||
rNode.Name = rCHAR.ReadString();
|
||||
rNode.pModel = gpResourceStore->LoadResource(rCHAR.ReadLongLong(), "CMDL");
|
||||
return pSet;
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,8 @@ CAnimSet* CAnimSetLoader::LoadReturnsCHAR(IInputStream& rCHAR)
|
|||
{
|
||||
// For now, we only read enough to fetch the model
|
||||
rCHAR.Seek(0x16, SEEK_CUR);
|
||||
pSet->mNodes.resize(1);
|
||||
CAnimSet::SNode& rNode = pSet->mNodes[0];
|
||||
pSet->mCharacters.resize(1);
|
||||
SSetCharacter& rNode = pSet->mCharacters[0];
|
||||
|
||||
rNode.Name = rCHAR.ReadString();
|
||||
rCHAR.Seek(0x14, SEEK_CUR);
|
||||
|
@ -224,11 +224,11 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
|||
Loader.mVersion = pEntry->Game();
|
||||
|
||||
u32 NodeCount = rANCS.ReadLong();
|
||||
Loader.pSet->mNodes.resize(NodeCount);
|
||||
Loader.pSet->mCharacters.resize(NodeCount);
|
||||
|
||||
for (u32 iNode = 0; iNode < NodeCount; iNode++)
|
||||
{
|
||||
CAnimSet::SNode *pNode = &Loader.pSet->mNodes[iNode];
|
||||
SSetCharacter *pChar = &Loader.pSet->mCharacters[iNode];
|
||||
|
||||
rANCS.Seek(0x4, SEEK_CUR); // Skipping node self-index
|
||||
u16 Unknown1 = rANCS.ReadShort();
|
||||
|
@ -237,11 +237,11 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
|||
Loader.mVersion = (Unknown1 == 0xA) ? eEchoes : ePrime; // Best version indicator we know of unfortunately
|
||||
Loader.pSet->SetGame(Loader.mVersion);
|
||||
}
|
||||
pNode->Name = rANCS.ReadString();
|
||||
pNode->pModel = gpResourceStore->LoadResource(rANCS.ReadLong(), "CMDL");
|
||||
pNode->pSkin = gpResourceStore->LoadResource(rANCS.ReadLong(), "CSKR");
|
||||
pNode->pSkeleton = gpResourceStore->LoadResource(rANCS.ReadLong(), "CINF");
|
||||
if (pNode->pModel) pNode->pModel->SetSkin(pNode->pSkin);
|
||||
pChar->Name = rANCS.ReadString();
|
||||
pChar->pModel = gpResourceStore->LoadResource(rANCS.ReadLong(), "CMDL");
|
||||
pChar->pSkin = gpResourceStore->LoadResource(rANCS.ReadLong(), "CSKR");
|
||||
pChar->pSkeleton = gpResourceStore->LoadResource(rANCS.ReadLong(), "CINF");
|
||||
if (pChar->pModel) pChar->pModel->SetSkin(pChar->pSkin);
|
||||
|
||||
// Unfortunately that's all that's actually supported at the moment. Hope to expand later.
|
||||
// Since there's no size value I have to actually read the rest of the node to reach the next one
|
||||
|
@ -259,17 +259,32 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
|||
|
||||
// Particles
|
||||
u32 ParticleCount = rANCS.ReadLong();
|
||||
rANCS.Seek(ParticleCount * 4, SEEK_CUR);
|
||||
pChar->GenericParticles.reserve(ParticleCount);
|
||||
|
||||
for (u32 iPart = 0; iPart < ParticleCount; iPart++)
|
||||
pChar->GenericParticles.push_back( CAssetID(rANCS, e32Bit) );
|
||||
|
||||
u32 SwooshCount = rANCS.ReadLong();
|
||||
rANCS.Seek(SwooshCount * 4, SEEK_CUR);
|
||||
pChar->SwooshParticles.reserve(SwooshCount);
|
||||
|
||||
for (u32 iSwoosh = 0; iSwoosh < SwooshCount; iSwoosh++)
|
||||
pChar->SwooshParticles.push_back( CAssetID(rANCS, e32Bit) );
|
||||
|
||||
if (Unknown1 != 5) rANCS.Seek(0x4, SEEK_CUR);
|
||||
|
||||
u32 ElectricCount = rANCS.ReadLong();
|
||||
rANCS.Seek(ElectricCount * 4, SEEK_CUR);
|
||||
pChar->ElectricParticles.reserve(ElectricCount);
|
||||
|
||||
for (u32 iElec = 0; iElec < ElectricCount; iElec++)
|
||||
pChar->ElectricParticles.push_back( CAssetID(rANCS, e32Bit) );
|
||||
|
||||
if (Loader.mVersion == eEchoes)
|
||||
{
|
||||
u32 SPSCCount = rANCS.ReadLong();
|
||||
rANCS.Seek(SPSCCount * 4, SEEK_CUR);
|
||||
u32 SpawnCount = rANCS.ReadLong();
|
||||
pChar->SpawnParticles.reserve(SpawnCount);
|
||||
|
||||
for (u32 iSpawn = 0; iSpawn < SpawnCount; iSpawn++)
|
||||
pChar->SpawnParticles.push_back( CAssetID(rANCS, e32Bit) );
|
||||
}
|
||||
|
||||
rANCS.Seek(0x4, SEEK_CUR);
|
||||
|
@ -291,13 +306,17 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
|||
for (u32 iEffect = 0; iEffect < EffectCount; iEffect++)
|
||||
{
|
||||
rANCS.ReadString();
|
||||
rANCS.Seek(0x8, SEEK_CUR);
|
||||
rANCS.Seek(0x4, SEEK_CUR);
|
||||
CAssetID ParticleID(rANCS, e32Bit);
|
||||
if (ParticleID.IsValid()) pChar->EffectParticles.push_back(ParticleID);
|
||||
|
||||
if (Loader.mVersion == ePrime) rANCS.ReadString();
|
||||
if (Loader.mVersion == eEchoes) rANCS.Seek(0x4, SEEK_CUR);
|
||||
rANCS.Seek(0xC, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
rANCS.Seek(0x8, SEEK_CUR);
|
||||
pChar->IceModel = CAssetID(rANCS, e32Bit);
|
||||
pChar->IceSkin = CAssetID(rANCS, e32Bit);
|
||||
|
||||
u32 UnknownCount = rANCS.ReadLong();
|
||||
rANCS.Seek(UnknownCount * 4, SEEK_CUR);
|
||||
|
|
|
@ -56,6 +56,122 @@ CDependencyGroup* CUnsupportedFormatLoader::LoadEVNT(IInputStream& rEVNT, CResou
|
|||
return pGroup;
|
||||
}
|
||||
|
||||
CDependencyGroup* CUnsupportedFormatLoader::LoadFRME(IInputStream& rFRME, CResourceEntry *pEntry)
|
||||
{
|
||||
if (pEntry->Game() >= eEchoesDemo) return nullptr;
|
||||
|
||||
u32 Version = rFRME.ReadLong();
|
||||
ASSERT(Version == 0 || Version == 1);
|
||||
|
||||
CDependencyGroup *pGroup = new CDependencyGroup(pEntry);
|
||||
rFRME.Seek(0xC, SEEK_CUR);
|
||||
u32 NumWidgets = rFRME.ReadLong();
|
||||
|
||||
for (u32 iWgt = 0; iWgt < NumWidgets; iWgt++)
|
||||
{
|
||||
// Widget Header
|
||||
CFourCC WidgetType = rFRME.ReadLong();
|
||||
rFRME.ReadString();
|
||||
rFRME.ReadString();
|
||||
rFRME.Seek(0x18, SEEK_CUR);
|
||||
|
||||
// Head Widget / Base Widget
|
||||
if (WidgetType == "HWIG" || WidgetType == "BWIG")
|
||||
{}
|
||||
|
||||
// Camera
|
||||
else if (WidgetType == "CAMR")
|
||||
{
|
||||
u32 ProjectionType = rFRME.ReadLong();
|
||||
|
||||
if (ProjectionType == 0)
|
||||
rFRME.Seek(0x10, SEEK_CUR);
|
||||
else
|
||||
rFRME.Seek(0x18, SEEK_CUR);
|
||||
}
|
||||
|
||||
// Light
|
||||
else if (WidgetType == "LITE")
|
||||
{
|
||||
u32 LightType = rFRME.ReadLong();
|
||||
rFRME.Seek(0x1C, SEEK_CUR);
|
||||
if (LightType == 0) rFRME.Seek(0x4, SEEK_CUR);
|
||||
}
|
||||
|
||||
// Meter
|
||||
else if (WidgetType == "METR")
|
||||
rFRME.Seek(0xA, SEEK_CUR);
|
||||
|
||||
// Group
|
||||
else if (WidgetType == "GRUP")
|
||||
rFRME.Seek(0x3, SEEK_CUR);
|
||||
|
||||
// Table Group
|
||||
else if (WidgetType == "TBGP")
|
||||
rFRME.Seek(0x23, SEEK_CUR);
|
||||
|
||||
// Model
|
||||
else if (WidgetType == "MODL")
|
||||
{
|
||||
pGroup->AddDependency( CAssetID(rFRME, e32Bit) ); // CMDL
|
||||
rFRME.Seek(0x8, SEEK_CUR);
|
||||
}
|
||||
|
||||
// Text Pane
|
||||
else if (WidgetType == "TXPN")
|
||||
{
|
||||
rFRME.Seek(0x14, SEEK_CUR);
|
||||
pGroup->AddDependency( CAssetID(rFRME, e32Bit) ); // FONT
|
||||
rFRME.Seek(0x32, SEEK_CUR);
|
||||
|
||||
if (Version == 1)
|
||||
{
|
||||
pGroup->AddDependency( CAssetID(rFRME, e32Bit) ); // FONT
|
||||
rFRME.Seek(0x8, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
// Image Pane
|
||||
else if (WidgetType == "IMGP")
|
||||
{
|
||||
pGroup->AddDependency( CAssetID(rFRME, e32Bit) ); // TXTR
|
||||
if (rFRME.ReadLong() != 0xFFFFFFFF) DEBUG_BREAK;
|
||||
rFRME.Seek(0x4, SEEK_CUR);
|
||||
|
||||
u32 NumQuadCoords = rFRME.ReadLong();
|
||||
rFRME.Seek(NumQuadCoords * 0xC, SEEK_CUR);
|
||||
u32 NumUVCoords = rFRME.ReadLong();
|
||||
rFRME.Seek(NumUVCoords * 8, SEEK_CUR);
|
||||
}
|
||||
|
||||
// Energy Bar
|
||||
else if (WidgetType == "ENRG")
|
||||
{
|
||||
pGroup->AddDependency( CAssetID(rFRME, e32Bit) ); // TXTR
|
||||
}
|
||||
|
||||
// Slider Group
|
||||
else if (WidgetType == "SLGP")
|
||||
{
|
||||
rFRME.Seek(0x10, SEEK_CUR);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Log::Error("Unrecognized FRME widget type: " + WidgetType.ToString());
|
||||
DEBUG_BREAK;
|
||||
}
|
||||
|
||||
// Widget Footer
|
||||
if (rFRME.ReadByte() != 0)
|
||||
rFRME.Seek(0x2, SEEK_CUR);
|
||||
|
||||
rFRME.Seek(0x42, SEEK_CUR);
|
||||
}
|
||||
|
||||
return pGroup;
|
||||
}
|
||||
|
||||
CDependencyGroup* CUnsupportedFormatLoader::LoadHINT(IInputStream& rHINT, CResourceEntry *pEntry)
|
||||
{
|
||||
u32 Magic = rHINT.ReadLong();
|
||||
|
|
|
@ -13,6 +13,7 @@ class CUnsupportedFormatLoader
|
|||
public:
|
||||
static CDependencyGroup* LoadCSNG(IInputStream& rCSNG, CResourceEntry *pEntry);
|
||||
static CDependencyGroup* LoadEVNT(IInputStream& rEVNT, CResourceEntry *pEntry);
|
||||
static CDependencyGroup* LoadFRME(IInputStream& rFRME, CResourceEntry *pEntry);
|
||||
static CDependencyGroup* LoadHINT(IInputStream& rHINT, CResourceEntry *pEntry);
|
||||
static CDependencyGroup* LoadMAPW(IInputStream& rMAPW, CResourceEntry *pEntry);
|
||||
static CDependencyGroup* LoadMAPU(IInputStream& rMAPU, CResourceEntry *pEntry);
|
||||
|
|
Loading…
Reference in New Issue