mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-12-21 02:39:17 +00:00
Added support for omitting unused animations from paks (needs work to not crash)
This commit is contained in:
@@ -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(); }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ************
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user