Added support for omitting unused animations from paks (needs work to not crash)

This commit is contained in:
parax0
2016-10-26 06:15:08 -06:00
parent a18655da00
commit 3942c09e89
14 changed files with 337 additions and 291 deletions

View File

@@ -22,14 +22,23 @@ public:
CDependencyTree* BuildDependencyTree() const
{
CDependencyTree *pTree = new CDependencyTree(ID());
AddDependenciesToTree(pTree);
return pTree;
}
void AddDependenciesToTree(CDependencyTree *pTree) const
{
for (u32 iEvt = 0; iEvt < mEvents.size(); iEvt++)
{
const SEvent& rkEvent = mEvents[iEvt];
pTree->AddEventDependency(rkEvent.mAssetRef, rkEvent.mCharacterIndex);
}
CAssetID ID = rkEvent.mAssetRef;
return pTree;
if (ID.IsValid() && !pTree->HasDependency(ID))
{
CAnimEventDependency *pDep = new CAnimEventDependency(ID, rkEvent.mCharacterIndex);
pTree->AddChild(pDep);
}
}
}
inline u32 NumEvents() const { return mEvents.size(); }

View File

@@ -27,6 +27,14 @@ struct SSetCharacter
std::vector<CAssetID> EffectParticles;
CAssetID IceModel;
CAssetID IceSkin;
std::set<u32> UsedAnimationIndices;
};
struct SSetAnimation
{
TString Name;
TResPtr<CAnimation> pAnim;
TResPtr<CAnimEventData> pEventData;
};
class CAnimSet : public CResource
@@ -35,73 +43,54 @@ class CAnimSet : public CResource
friend class CAnimSetLoader;
std::vector<SSetCharacter> mCharacters;
struct SAnimation
{
TString Name;
TResPtr<CAnimation> pAnim;
};
std::vector<SAnimation> mAnims;
std::vector<CAnimEventData*> mEventDependencies;
std::vector<SSetAnimation> mAnimations;
public:
CAnimSet(CResourceEntry *pEntry = 0) : CResource(pEntry) {}
~CAnimSet()
{
for (u32 iEvnt = 0; iEvnt < mEventDependencies.size(); iEvnt++)
// note: in MP2, event data isn't a standalone resource, so it's owned by the animset; therefore we need to delete it manually
if (Game() >= eEchoesDemo)
{
ASSERT(!mEventDependencies[iEvnt]->Entry());
delete mEventDependencies[iEvnt];
for (u32 iAnim = 0; iAnim < mAnimations.size(); iAnim++)
{
SSetAnimation& rAnim = mAnimations[iAnim];
CAnimEventData *pEvents = rAnim.pEventData;
ASSERT(pEvents && !pEvents->Entry());
rAnim.pEventData = nullptr; // make sure TResPtr destructor doesn't attempt to access
delete pEvents;
}
}
}
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());
std::set<CAssetID> BaseUsedSet;
// Base dependencies
for (u32 iAnim = 0; iAnim < mAnims.size(); iAnim++)
{
CAnimation *pAnim = mAnims[iAnim].pAnim;
if (pAnim)
{
pTree->AddDependency(mAnims[iAnim].pAnim);
BaseUsedSet.insert(pAnim->ID());
}
}
for (u32 iEvnt = 0; iEvnt < mEventDependencies.size(); iEvnt++)
{
CAnimEventData *pData = mEventDependencies[iEvnt];
for (u32 iEvt = 0; iEvt < pData->NumEvents(); iEvt++)
{
CAssetID ID = pData->EventAssetRef(iEvt);
u32 CharIdx = pData->EventCharacterIndex(iEvt);
pTree->AddEventDependency(ID, CharIdx);
BaseUsedSet.insert(ID);
}
}
CDependencyTree *pTree = new CDependencyTree(ID());
// Character dependencies
for (u32 iNode = 0; iNode < mCharacters.size(); iNode++)
pTree->AddCharacter(&mCharacters[iNode], BaseUsedSet);
for (u32 iChar = 0; iChar < mCharacters.size(); iChar++)
{
CSetCharacterDependency *pCharTree = CSetCharacterDependency::BuildTree(this, iChar);
ASSERT(pCharTree);
pTree->AddChild(pCharTree);
}
for (u32 iAnim = 0; iAnim < mAnimations.size(); iAnim++)
{
CSetAnimationDependency *pAnimTree = CSetAnimationDependency::BuildTree(this, iAnim);
ASSERT(pAnimTree);
pTree->AddChild(pAnimTree);
}
return pTree;
}
// Accessors
inline u32 NumCharacters() const { return mCharacters.size(); }
inline u32 NumAnimations() const { return mAnimations.size(); }
inline const SSetCharacter* Character(u32 Index) const { ASSERT(Index >= 0 && Index < NumCharacters()); return &mCharacters[Index]; }
inline const SSetAnimation* Animation(u32 Index) const { ASSERT(Index >= 0 && Index < NumAnimations()); return &mAnimations[Index]; }
};
#endif // CCHARACTERSET_H

View File

@@ -145,8 +145,8 @@ CModel* CAnimationParameters::GetCurrentModel(s32 NodeIndex /*= -1*/)
if (pSet->Type() != eAnimSet) return nullptr;
if (NodeIndex == -1) NodeIndex = mCharIndex;
if (pSet->NumNodes() <= (u32) NodeIndex) return nullptr;
return pSet->NodeModel(NodeIndex);
if (pSet->NumCharacters() <= (u32) NodeIndex) return nullptr;
return pSet->Character(NodeIndex)->pModel;
}
TString CAnimationParameters::GetCurrentCharacterName(s32 NodeIndex /*= -1*/)
@@ -158,8 +158,8 @@ TString CAnimationParameters::GetCurrentCharacterName(s32 NodeIndex /*= -1*/)
if (pSet->Type() != eAnimSet) return "";
if (NodeIndex == -1) NodeIndex = mCharIndex;
if (pSet->NumNodes() <= (u32) NodeIndex) return "";
return pSet->NodeName((u32) NodeIndex);
if (pSet->NumCharacters() <= (u32) NodeIndex) return "";
return pSet->Character(NodeIndex)->Name;
}
// ************ ACCESSORS ************

View File

@@ -107,9 +107,7 @@ void CAnimSetLoader::LoadPrimitive(IInputStream& rANCS)
u32 AnimIndex = rANCS.ReadLong();
TString AnimName = rANCS.ReadString();
rANCS.Seek(0x8, SEEK_CUR);
if (mAnimPrimitives.size() < (AnimIndex + 1))
mAnimPrimitives.resize(AnimIndex + 1);
ASSERT(AnimIndex < mAnimPrimitives.size());
if (!mAnimPrimitives[AnimIndex].Loaded)
{
@@ -319,8 +317,13 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
pChar->IceModel = CAssetID(rANCS, e32Bit);
pChar->IceSkin = CAssetID(rANCS, e32Bit);
u32 UnknownCount = rANCS.ReadLong();
rANCS.Seek(UnknownCount * 4, SEEK_CUR);
u32 AnimIndexCount = rANCS.ReadLong();
for (u32 iAnim = 0; iAnim < AnimIndexCount; iAnim++)
{
u32 AnimIndex = rANCS.ReadLong();
pChar->UsedAnimationIndices.insert(AnimIndex);
}
if (Loader.mVersion == eEchoes)
{
@@ -335,6 +338,7 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
SetStart = SetStart;
u16 InfoCount = rANCS.ReadShort();
u32 NumAnims = rANCS.ReadLong();
Loader.mAnimPrimitives.resize(NumAnims);
for (u32 iAnim = 0; iAnim < NumAnims; iAnim++)
Loader.LoadAnimation(rANCS);
@@ -361,16 +365,18 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
}
// Add anims to set
Loader.pSet->mAnimations.resize(Loader.mAnimPrimitives.size());
for (u32 iPrim = 0; iPrim < Loader.mAnimPrimitives.size(); iPrim++)
{
SPrimitive& rPrim = Loader.mAnimPrimitives[iPrim];
if (rPrim.Loaded)
{
CAnimSet::SAnimation Anim;
SSetAnimation Anim;
Anim.Name = rPrim.Name;
Anim.pAnim = gpResourceStore->LoadResource(rPrim.AnimID, "ANIM");
Loader.pSet->mAnims.push_back(Anim);
Loader.pSet->mAnimations[iPrim] = Anim;
}
}
@@ -378,12 +384,10 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
if (Loader.pSet->Game() >= eEchoesDemo)
{
u32 EventDataCount = rANCS.ReadLong();
ASSERT(EventDataCount == NumAnims);
for (u32 iEvnt = 0; iEvnt < EventDataCount; iEvnt++)
{
CAnimEventData *pData = CAnimEventLoader::LoadAnimSetEvents(rANCS);
Loader.pSet->mEventDependencies.push_back(pData);
}
Loader.pSet->mAnimations[iEvnt].pEventData = CAnimEventLoader::LoadAnimSetEvents(rANCS);
}
return Loader.pSet;