mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-12-17 08:57:09 +00:00
Added support for omitting unused animations from paks (needs work to not crash)
This commit is contained in:
@@ -36,18 +36,10 @@ void CDependencyTree::Serialize(IArchive& rArc)
|
||||
<< SERIAL_ABSTRACT_CONTAINER("Children", mChildren, "Child", &gDependencyNodeFactory);
|
||||
}
|
||||
|
||||
void CDependencyTree::AddDependency(CResource *pRes, bool AvoidDuplicates /*= true*/)
|
||||
void CDependencyTree::AddChild(IDependencyNode *pNode)
|
||||
{
|
||||
if (!pRes) return;
|
||||
AddDependency(pRes->ID(), AvoidDuplicates);
|
||||
}
|
||||
|
||||
void CDependencyTree::AddEventDependency(const CAssetID& rkID, u32 CharIndex)
|
||||
{
|
||||
// Note: No duplicate check because there might be multiple events using the same asset ID with different character indices
|
||||
if (!rkID.IsValid()) return;
|
||||
CAnimEventDependency *pDepend = new CAnimEventDependency(rkID, CharIndex);
|
||||
mChildren.push_back(pDepend);
|
||||
ASSERT(pNode);
|
||||
mChildren.push_back(pNode);
|
||||
}
|
||||
|
||||
void CDependencyTree::AddDependency(const CAssetID& rkID, bool AvoidDuplicates /*= true*/)
|
||||
@@ -57,6 +49,12 @@ void CDependencyTree::AddDependency(const CAssetID& rkID, bool AvoidDuplicates /
|
||||
mChildren.push_back(pDepend);
|
||||
}
|
||||
|
||||
void CDependencyTree::AddDependency(CResource *pRes, bool AvoidDuplicates /*= true*/)
|
||||
{
|
||||
if (!pRes) return;
|
||||
AddDependency(pRes->ID(), AvoidDuplicates);
|
||||
}
|
||||
|
||||
// ************ CResourceDependency ************
|
||||
EDependencyNodeType CResourceDependency::Type() const
|
||||
{
|
||||
@@ -180,6 +178,88 @@ void CScriptInstanceDependency::ParseStructDependencies(CScriptInstanceDependenc
|
||||
}
|
||||
}
|
||||
|
||||
// ************ CSetCharacterDependency ************
|
||||
EDependencyNodeType CSetCharacterDependency::Type() const
|
||||
{
|
||||
return eDNT_SetCharacter;
|
||||
}
|
||||
|
||||
void CSetCharacterDependency::Serialize(IArchive& rArc)
|
||||
{
|
||||
rArc << SERIAL("SetIndex", mSetIndex)
|
||||
<< SERIAL_ABSTRACT_CONTAINER("Children", mChildren, "Child", &gDependencyNodeFactory);
|
||||
}
|
||||
|
||||
CSetCharacterDependency* CSetCharacterDependency::BuildTree(const CAnimSet *pkOwnerSet, u32 CharIndex)
|
||||
{
|
||||
CSetCharacterDependency *pTree = new CSetCharacterDependency(CharIndex);
|
||||
const SSetCharacter *pkChar = pkOwnerSet->Character(CharIndex);
|
||||
|
||||
if (pkChar)
|
||||
{
|
||||
pTree->AddDependency(pkChar->pModel);
|
||||
pTree->AddDependency(pkChar->pSkeleton);
|
||||
pTree->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++)
|
||||
pTree->AddDependency(pkParticleVectors[iVec]->at(iPart));
|
||||
}
|
||||
|
||||
pTree->AddDependency(pkChar->IceModel);
|
||||
pTree->AddDependency(pkChar->IceSkin);
|
||||
}
|
||||
|
||||
return pTree;
|
||||
}
|
||||
|
||||
// ************ CSetAnimationDependency ************
|
||||
EDependencyNodeType CSetAnimationDependency::Type() const
|
||||
{
|
||||
return eDNT_SetAnimation;
|
||||
}
|
||||
|
||||
void CSetAnimationDependency::Serialize(IArchive& rArc)
|
||||
{
|
||||
rArc << SERIAL_CONTAINER("CharacterIndices", mCharacterIndices, "Index")
|
||||
<< SERIAL_ABSTRACT_CONTAINER("Children", mChildren, "Child", &gDependencyNodeFactory);
|
||||
}
|
||||
|
||||
CSetAnimationDependency* CSetAnimationDependency::BuildTree(const CAnimSet *pkOwnerSet, u32 AnimIndex)
|
||||
{
|
||||
const SSetAnimation *pkAnim = pkOwnerSet->Animation(AnimIndex);
|
||||
CSetAnimationDependency *pTree = new CSetAnimationDependency;
|
||||
|
||||
// Find relevant character indices
|
||||
for (u32 iChar = 0; iChar < pkOwnerSet->NumCharacters(); iChar++)
|
||||
{
|
||||
const SSetCharacter *pkChar = pkOwnerSet->Character(iChar);
|
||||
|
||||
if ( pkChar->UsedAnimationIndices.find(AnimIndex) != pkChar->UsedAnimationIndices.end() )
|
||||
pTree->mCharacterIndices.insert(iChar);
|
||||
}
|
||||
|
||||
// Add dependencies. In MP2 animation event data is not a standalone resource.
|
||||
pTree->AddDependency(pkAnim->pAnim);
|
||||
|
||||
if (pkAnim->pEventData)
|
||||
{
|
||||
if (pkAnim->pEventData->Entry())
|
||||
pTree->AddDependency(pkAnim->pEventData);
|
||||
else
|
||||
pkAnim->pEventData->AddDependenciesToTree(pTree);
|
||||
}
|
||||
|
||||
return pTree;
|
||||
}
|
||||
|
||||
// ************ CAnimEventDependency ************
|
||||
EDependencyNodeType CAnimEventDependency::Type() const
|
||||
{
|
||||
@@ -192,59 +272,6 @@ void CAnimEventDependency::Serialize(IArchive& rArc)
|
||||
rArc << SERIAL("CharacterIndex", mCharIndex);
|
||||
}
|
||||
|
||||
// ************ CAnimSetDependencyTree ************
|
||||
EDependencyNodeType CAnimSetDependencyTree::Type() const
|
||||
{
|
||||
return eDNT_AnimSet;
|
||||
}
|
||||
|
||||
void CAnimSetDependencyTree::Serialize(IArchive& rArc)
|
||||
{
|
||||
CDependencyTree::Serialize(rArc);
|
||||
rArc << SERIAL_CONTAINER("CharacterOffsets", mCharacterOffsets, "Offset");
|
||||
}
|
||||
|
||||
void CAnimSetDependencyTree::AddCharacter(const SSetCharacter *pkChar, const std::set<CAssetID>& rkBaseUsedSet)
|
||||
{
|
||||
mCharacterOffsets.push_back( NumChildren() );
|
||||
if (!pkChar) return;
|
||||
|
||||
std::set<CAssetID> UsedSet = rkBaseUsedSet;
|
||||
AddCharDependency(pkChar->pModel, UsedSet);
|
||||
AddCharDependency(pkChar->pSkeleton, UsedSet);
|
||||
AddCharDependency(pkChar->pSkin, UsedSet);
|
||||
|
||||
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++)
|
||||
AddCharDependency(pkParticleVectors[iVec]->at(iPart), UsedSet);
|
||||
}
|
||||
|
||||
AddCharDependency(pkChar->IceModel, UsedSet);
|
||||
AddCharDependency(pkChar->IceSkin, UsedSet);
|
||||
}
|
||||
|
||||
void CAnimSetDependencyTree::AddCharDependency(const CAssetID& rkID, std::set<CAssetID>& rUsedSet)
|
||||
{
|
||||
if (rkID.IsValid() && rUsedSet.find(rkID) == rUsedSet.end())
|
||||
{
|
||||
rUsedSet.insert(rkID);
|
||||
AddDependency(rkID, false);
|
||||
}
|
||||
}
|
||||
|
||||
void CAnimSetDependencyTree::AddCharDependency(CResource *pRes, std::set<CAssetID>& rUsedSet)
|
||||
{
|
||||
if (!pRes) return;
|
||||
AddCharDependency(pRes->ID(), rUsedSet);
|
||||
}
|
||||
|
||||
// ************ CAreaDependencyTree ************
|
||||
EDependencyNodeType CAreaDependencyTree::Type() const
|
||||
{
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
class CScriptLayer;
|
||||
class CScriptObject;
|
||||
class CPropertyStruct;
|
||||
class CAnimSet;
|
||||
struct SSetCharacter;
|
||||
struct SSetAnimation;
|
||||
|
||||
// Group of node classes forming a tree of cached resource dependencies.
|
||||
enum EDependencyNodeType
|
||||
@@ -19,8 +21,9 @@ enum EDependencyNodeType
|
||||
eDNT_ScriptInstance = FOURCC_CONSTEXPR('S', 'C', 'I', 'N'),
|
||||
eDNT_ScriptProperty = FOURCC_CONSTEXPR('S', 'C', 'P', 'R'),
|
||||
eDNT_CharacterProperty = FOURCC_CONSTEXPR('C', 'R', 'P', 'R'),
|
||||
eDNT_SetCharacter = FOURCC_CONSTEXPR('S', 'C', 'H', 'R'),
|
||||
eDNT_SetAnimation = FOURCC_CONSTEXPR('S', 'A', 'N', 'M'),
|
||||
eDNT_AnimEvent = FOURCC_CONSTEXPR('E', 'V', 'N', 'T'),
|
||||
eDNT_AnimSet = FOURCC_CONSTEXPR('A', 'N', 'C', 'S'),
|
||||
eDNT_Area = FOURCC_CONSTEXPR('A', 'R', 'E', 'A'),
|
||||
};
|
||||
|
||||
@@ -54,9 +57,9 @@ public:
|
||||
virtual EDependencyNodeType Type() const;
|
||||
virtual void Serialize(IArchive& rArc);
|
||||
|
||||
void AddChild(IDependencyNode *pNode);
|
||||
void AddDependency(const CAssetID& rkID, bool AvoidDuplicates = true);
|
||||
void AddDependency(CResource *pRes, bool AvoidDuplicates = true);
|
||||
void AddEventDependency(const CAssetID& rkID, u32 CharIndex);
|
||||
|
||||
// Accessors
|
||||
inline void SetID(const CAssetID& rkID) { mRootID = rkID; }
|
||||
@@ -147,7 +150,46 @@ protected:
|
||||
static void ParseStructDependencies(CScriptInstanceDependency *pTree, CPropertyStruct *pStruct);
|
||||
};
|
||||
|
||||
// Node representing an animation event.
|
||||
// Node representing an animset character. Indicates what index the character is within the animset.
|
||||
class CSetCharacterDependency : public CDependencyTree
|
||||
{
|
||||
protected:
|
||||
u32 mSetIndex;
|
||||
|
||||
public:
|
||||
CSetCharacterDependency() : CDependencyTree() {}
|
||||
CSetCharacterDependency(u32 SetIndex) : CDependencyTree(), mSetIndex(SetIndex) {}
|
||||
|
||||
virtual EDependencyNodeType Type() const;
|
||||
virtual void Serialize(IArchive& rArc);
|
||||
|
||||
// Accessors
|
||||
inline u32 SetIndex() const { return mSetIndex; }
|
||||
|
||||
// Static
|
||||
static CSetCharacterDependency* BuildTree(const CAnimSet *pkOwnerSet, u32 CharIndex);
|
||||
};
|
||||
|
||||
// Node representing a character animation. Indicates which character indices use this animation.
|
||||
class CSetAnimationDependency : public CDependencyTree
|
||||
{
|
||||
protected:
|
||||
std::set<u32> mCharacterIndices;
|
||||
|
||||
public:
|
||||
CSetAnimationDependency() : CDependencyTree() {}
|
||||
|
||||
virtual EDependencyNodeType Type() const;
|
||||
virtual void Serialize(IArchive& rArc);
|
||||
|
||||
// Accessors
|
||||
inline bool IsUsedByCharacter(u32 CharIdx) const { return mCharacterIndices.find(CharIdx) != mCharacterIndices.end(); }
|
||||
|
||||
// Static
|
||||
static CSetAnimationDependency* BuildTree(const CAnimSet *pkOwnerSet, u32 AnimIndex);
|
||||
};
|
||||
|
||||
// Node representing an animation event. Indicates which character index uses this event.
|
||||
class CAnimEventDependency : public CResourceDependency
|
||||
{
|
||||
protected:
|
||||
@@ -165,27 +207,6 @@ public:
|
||||
inline u32 CharIndex() const { return mCharIndex; }
|
||||
};
|
||||
|
||||
// Node representing an animset resource; allows for lookup of dependencies of a particular character in the set.
|
||||
class CAnimSetDependencyTree : public CDependencyTree
|
||||
{
|
||||
protected:
|
||||
std::vector<u32> mCharacterOffsets;
|
||||
|
||||
public:
|
||||
CAnimSetDependencyTree() : CDependencyTree() {}
|
||||
CAnimSetDependencyTree(const CAssetID& rkID) : CDependencyTree(rkID) {}
|
||||
virtual EDependencyNodeType Type() const;
|
||||
virtual void Serialize(IArchive& rArc);
|
||||
|
||||
void AddCharacter(const SSetCharacter *pkChar, const std::set<CAssetID>& rkBaseUsedSet);
|
||||
void AddCharDependency(const CAssetID& rkID, std::set<CAssetID>& rUsedSet);
|
||||
void AddCharDependency(CResource *pRes, std::set<CAssetID>& rUsedSet);
|
||||
|
||||
// Accessors
|
||||
inline u32 NumCharacters() const { return mCharacterOffsets.size(); }
|
||||
inline u32 CharacterOffset(u32 CharIdx) const { return mCharacterOffsets[CharIdx]; }
|
||||
};
|
||||
|
||||
// Node representing an area. Tracks dependencies on a per-instance basis and can separate dependencies of different script layers.
|
||||
class CAreaDependencyTree : public CDependencyTree
|
||||
{
|
||||
@@ -220,8 +241,9 @@ public:
|
||||
case eDNT_ScriptInstance: return new CScriptInstanceDependency;
|
||||
case eDNT_ScriptProperty: return new CPropertyDependency;
|
||||
case eDNT_CharacterProperty: return new CCharPropertyDependency;
|
||||
case eDNT_SetCharacter: return new CSetCharacterDependency;
|
||||
case eDNT_SetAnimation: return new CSetAnimationDependency;
|
||||
case eDNT_AnimEvent: return new CAnimEventDependency;
|
||||
case eDNT_AnimSet: return new CAnimSetDependencyTree;
|
||||
case eDNT_Area: return new CAreaDependencyTree;
|
||||
default: ASSERT(false); return nullptr;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,21 @@ bool CCharacterUsageMap::IsCharacterUsed(const CAssetID& rkID, u32 CharacterInde
|
||||
else return rkUsageList[CharacterIndex];
|
||||
}
|
||||
|
||||
bool CCharacterUsageMap::IsAnimationUsed(const CAssetID& rkID, CSetAnimationDependency *pAnim) const
|
||||
{
|
||||
auto Find = mUsageMap.find(rkID);
|
||||
if (Find == mUsageMap.end()) return false;
|
||||
const std::vector<bool>& rkUsageList = Find->second;
|
||||
|
||||
for (u32 iChar = 0; iChar < rkUsageList.size(); iChar++)
|
||||
{
|
||||
if (rkUsageList[iChar] && pAnim->IsUsedByCharacter(iChar))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CCharacterUsageMap::FindUsagesForArea(CWorld *pWorld, CResourceEntry *pEntry)
|
||||
{
|
||||
ASSERT(pEntry->ResourceType() == eArea);
|
||||
@@ -76,10 +91,10 @@ void CCharacterUsageMap::DebugPrintContents()
|
||||
std::vector<bool>& rUsedList = Iter->second;
|
||||
CAnimSet *pSet = (CAnimSet*) gpResourceStore->LoadResource(ID, "ANCS");
|
||||
|
||||
for (u32 iChar = 0; iChar < pSet->NumNodes(); iChar++)
|
||||
for (u32 iChar = 0; iChar < pSet->NumCharacters(); iChar++)
|
||||
{
|
||||
bool Used = (rUsedList.size() > iChar && rUsedList[iChar]);
|
||||
TString CharName = pSet->NodeName(iChar);
|
||||
TString CharName = pSet->Character(iChar)->Name;
|
||||
Log::Write(ID.ToString() + " : Char " + TString::FromInt32(iChar, 0, 10) + " : " + CharName + " : " + (Used ? "USED" : "UNUSED"));
|
||||
}
|
||||
}
|
||||
@@ -230,43 +245,16 @@ void CPackageDependencyListBuilder::AddDependency(CResourceEntry *pCurEntry, con
|
||||
void CPackageDependencyListBuilder::EvaluateDependencyNode(CResourceEntry *pCurEntry, IDependencyNode *pNode, std::list<CAssetID>& rOut)
|
||||
{
|
||||
EDependencyNodeType Type = pNode->Type();
|
||||
bool ParseChildren = false;
|
||||
|
||||
if (Type == eDNT_AnimSet)
|
||||
{
|
||||
// Add base dependencies, then only add dependencies from used characters
|
||||
CAnimSetDependencyTree *pTree = static_cast<CAnimSetDependencyTree*>(pNode);
|
||||
u32 BaseEnd = (pTree->NumCharacters() > 0 ? pTree->CharacterOffset(0) : pTree->NumChildren());
|
||||
|
||||
for (u32 iDep = 0; iDep < BaseEnd; iDep++)
|
||||
{
|
||||
CResourceDependency *pDep = static_cast<CResourceDependency*>(pTree->ChildByIndex(iDep));
|
||||
ASSERT(pDep->Type() == eDNT_ResourceDependency);
|
||||
AddDependency(pCurEntry, pDep->ID(), rOut);
|
||||
}
|
||||
|
||||
for (u32 iChar = 0; iChar < pTree->NumCharacters(); iChar++)
|
||||
{
|
||||
if (mCharacterUsageMap.IsCharacterUsed(pCurEntry->ID(), iChar) || mGame > eEchoes || mIsPlayerActor)
|
||||
{
|
||||
u32 StartIdx = pTree->CharacterOffset(iChar);
|
||||
u32 EndIdx = (iChar == pTree->NumCharacters() - 1 ? pTree->NumChildren() : pTree->CharacterOffset(iChar + 1));
|
||||
|
||||
for (u32 iDep = StartIdx; iDep < EndIdx; iDep++)
|
||||
{
|
||||
CResourceDependency *pDep = static_cast<CResourceDependency*>(pTree->ChildByIndex(iDep));
|
||||
ASSERT(pDep->Type() == eDNT_ResourceDependency);
|
||||
AddDependency(pCurEntry, pDep->ID(), rOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (Type == eDNT_ResourceDependency || Type == eDNT_ScriptProperty || Type == eDNT_CharacterProperty)
|
||||
// Straight resource dependencies should just be added to the tree directly
|
||||
if (Type == eDNT_ResourceDependency || Type == eDNT_ScriptProperty || Type == eDNT_CharacterProperty)
|
||||
{
|
||||
CResourceDependency *pDep = static_cast<CResourceDependency*>(pNode);
|
||||
AddDependency(pCurEntry, pDep->ID(), rOut);
|
||||
}
|
||||
|
||||
// Anim events should be added if either they apply to characters, or their character index is used
|
||||
else if (Type == eDNT_AnimEvent)
|
||||
{
|
||||
CAnimEventDependency *pDep = static_cast<CAnimEventDependency*>(pNode);
|
||||
@@ -276,7 +264,25 @@ void CPackageDependencyListBuilder::EvaluateDependencyNode(CResourceEntry *pCurE
|
||||
AddDependency(pCurEntry, pDep->ID(), rOut);
|
||||
}
|
||||
|
||||
// Set characters should only be added if their character index is used
|
||||
else if (Type == eDNT_SetCharacter)
|
||||
{
|
||||
CSetCharacterDependency *pChar = static_cast<CSetCharacterDependency*>(pNode);
|
||||
ParseChildren = mCharacterUsageMap.IsCharacterUsed(mCurrentAnimSetID, pChar->SetIndex()) || mIsPlayerActor;
|
||||
}
|
||||
|
||||
// Set animations should only be added if they're being used by at least one used character
|
||||
else if (Type == eDNT_SetAnimation)
|
||||
{
|
||||
CSetAnimationDependency *pAnim = static_cast<CSetAnimationDependency*>(pNode);
|
||||
ParseChildren = mCharacterUsageMap.IsAnimationUsed(mCurrentAnimSetID, pAnim) || mIsPlayerActor; // todo - should maybe omit completely unused animations on PlayerActors?
|
||||
}
|
||||
|
||||
else
|
||||
ParseChildren = true;
|
||||
|
||||
// Analyze this node's children
|
||||
if (ParseChildren)
|
||||
{
|
||||
if (Type == eDNT_ScriptInstance)
|
||||
{
|
||||
@@ -371,7 +377,8 @@ void CAreaDependencyListBuilder::AddDependency(const CAssetID& rkID, std::list<C
|
||||
// If this is an audio group, for MP1, save it in the output set. For MP2, treat audio groups as a normal dependency.
|
||||
if (mGame <= ePrime && ResType == eAudioGroup)
|
||||
{
|
||||
if (pAudioGroupsOut) pAudioGroupsOut->insert(rkID);
|
||||
if (pAudioGroupsOut)
|
||||
pAudioGroupsOut->insert(rkID);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -382,82 +389,21 @@ void CAreaDependencyListBuilder::AddDependency(const CAssetID& rkID, std::list<C
|
||||
if (mBaseUsedAssets.find(rkID) != mBaseUsedAssets.end() || mLayerUsedAssets.find(rkID) != mLayerUsedAssets.end())
|
||||
return;
|
||||
|
||||
// Dependency is valid! Evaluate sub-dependencies
|
||||
// For animsets, only add used character indices
|
||||
if (ResType == eAnimSet && mGame <= eEchoes)
|
||||
// Dependency is valid! Evaluate the node tree (except for SCAN and DGRP)
|
||||
if (ResType != eScan && ResType != eDependencyGroup)
|
||||
{
|
||||
mCurrentAnimSetID = rkID;
|
||||
|
||||
// Add base dependencies first, then character-specific ones
|
||||
CAnimSetDependencyTree *pTree = static_cast<CAnimSetDependencyTree*>(pEntry->Dependencies());
|
||||
u32 BaseEndIdx = (pTree->NumCharacters() > 0 ? pTree->CharacterOffset(0) : pTree->NumChildren());
|
||||
|
||||
for (u32 iDep = 0; iDep < BaseEndIdx; iDep++)
|
||||
if (ResType == eAnimSet)
|
||||
{
|
||||
CResourceDependency *pDep = static_cast<CResourceDependency*>(pTree->ChildByIndex(iDep));
|
||||
EDependencyNodeType Type = pDep->Type();
|
||||
ASSERT(Type == eDNT_ResourceDependency || Type == eDNT_AnimEvent);
|
||||
|
||||
if (Type == eDNT_ResourceDependency)
|
||||
AddDependency(pDep->ID(), rOut, pAudioGroupsOut);
|
||||
|
||||
else
|
||||
{
|
||||
CAnimEventDependency *pEvent = static_cast<CAnimEventDependency*>(pDep);
|
||||
u32 CharIdx = pEvent->CharIndex();
|
||||
|
||||
if (CharIdx == -1 || mCharacterUsageMap.IsCharacterUsed(rkID, CharIdx))
|
||||
AddDependency(pDep->ID(), rOut, pAudioGroupsOut);
|
||||
}
|
||||
ASSERT(!mCurrentAnimSetID.IsValid());
|
||||
mCurrentAnimSetID = pEntry->ID();
|
||||
}
|
||||
|
||||
for (u32 iChar = 0; iChar < pTree->NumCharacters(); iChar++)
|
||||
EvaluateDependencyNode(pEntry, pEntry->Dependencies(), rOut, pAudioGroupsOut);
|
||||
|
||||
if (ResType == eAnimSet)
|
||||
{
|
||||
// Note: For MP1/2 PlayerActor, always treat as if Empty Suit is the only used one
|
||||
const u32 kEmptySuitIndex = (mGame >= eEchoesDemo ? 3 : 5);
|
||||
bool IsUsed = (mIsPlayerActor ? iChar == kEmptySuitIndex : mCharacterUsageMap.IsCharacterUsed(rkID, iChar));
|
||||
if (!IsUsed) continue;
|
||||
|
||||
u32 StartIdx = pTree->CharacterOffset(iChar);
|
||||
u32 EndIdx = (iChar == pTree->NumCharacters() - 1 ? pTree->NumChildren() : pTree->CharacterOffset(iChar + 1));
|
||||
|
||||
for (u32 iDep = StartIdx; iDep < EndIdx; iDep++)
|
||||
{
|
||||
CResourceDependency *pDep = static_cast<CResourceDependency*>(pTree->ChildByIndex(iDep));
|
||||
ASSERT(pDep->Type() == eDNT_ResourceDependency);
|
||||
AddDependency(pDep->ID(), rOut, pAudioGroupsOut);
|
||||
}
|
||||
}
|
||||
|
||||
mCurrentAnimSetID = CAssetID::InvalidID(mGame);
|
||||
}
|
||||
|
||||
// For EVNT, only add events for used character indices
|
||||
else if (ResType == eAnimEventData)
|
||||
{
|
||||
CDependencyTree *pTree = pEntry->Dependencies();
|
||||
|
||||
for (u32 iDep = 0; iDep < pTree->NumChildren(); iDep++)
|
||||
{
|
||||
CAnimEventDependency *pDep = static_cast<CAnimEventDependency*>(pTree->ChildByIndex(iDep));
|
||||
ASSERT(pDep->Type() == eDNT_AnimEvent);
|
||||
u32 CharIdx = pDep->CharIndex();
|
||||
|
||||
if (CharIdx == -1 || mCharacterUsageMap.IsCharacterUsed(mCurrentAnimSetID, CharIdx))
|
||||
AddDependency(pDep->ID(), rOut, pAudioGroupsOut);
|
||||
}
|
||||
}
|
||||
|
||||
// For other resource types (except SCAN and DGRP), evaluate all sub-dependencies
|
||||
else if (ResType != eScan && ResType != eDependencyGroup)
|
||||
{
|
||||
CDependencyTree *pTree = pEntry->Dependencies();
|
||||
|
||||
for (u32 iDep = 0; iDep < pTree->NumChildren(); iDep++)
|
||||
{
|
||||
CResourceDependency *pDep = static_cast<CResourceDependency*>(pTree->ChildByIndex(iDep));
|
||||
ASSERT(pDep->Type() == eDNT_ResourceDependency);
|
||||
AddDependency(pDep->ID(), rOut, pAudioGroupsOut);
|
||||
ASSERT(mCurrentAnimSetID.IsValid());
|
||||
mCurrentAnimSetID = CAssetID::InvalidID(mGame);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,3 +411,49 @@ void CAreaDependencyListBuilder::AddDependency(const CAssetID& rkID, std::list<C
|
||||
if (ResType != eMidi)
|
||||
rOut.push_back(rkID);
|
||||
}
|
||||
|
||||
void CAreaDependencyListBuilder::EvaluateDependencyNode(CResourceEntry *pCurEntry, IDependencyNode *pNode, std::list<CAssetID>& rOut, std::set<CAssetID> *pAudioGroupsOut)
|
||||
{
|
||||
EDependencyNodeType Type = pNode->Type();
|
||||
bool ParseChildren = false;
|
||||
|
||||
if (Type == eDNT_ResourceDependency || Type == eDNT_ScriptProperty || Type == eDNT_CharacterProperty)
|
||||
{
|
||||
CResourceDependency *pDep = static_cast<CResourceDependency*>(pNode);
|
||||
AddDependency(pDep->ID(), rOut, pAudioGroupsOut);
|
||||
}
|
||||
|
||||
else if (Type == eDNT_AnimEvent)
|
||||
{
|
||||
CAnimEventDependency *pDep = static_cast<CAnimEventDependency*>(pNode);
|
||||
u32 CharIndex = pDep->CharIndex();
|
||||
|
||||
if (CharIndex == -1 || mCharacterUsageMap.IsCharacterUsed(mCurrentAnimSetID, CharIndex))
|
||||
AddDependency(pDep->ID(), rOut, pAudioGroupsOut);
|
||||
}
|
||||
|
||||
else if (Type == eDNT_SetCharacter)
|
||||
{
|
||||
// Note: For MP1/2 PlayerActor, always treat as if Empty Suit is the only used one
|
||||
const u32 kEmptySuitIndex = (mGame >= eEchoesDemo ? 3 : 5);
|
||||
|
||||
CSetCharacterDependency *pChar = static_cast<CSetCharacterDependency*>(pNode);
|
||||
u32 SetIndex = pChar->SetIndex();
|
||||
ParseChildren = mCharacterUsageMap.IsCharacterUsed(mCurrentAnimSetID, pChar->SetIndex()) || (mIsPlayerActor && SetIndex == kEmptySuitIndex);
|
||||
}
|
||||
|
||||
else if (Type == eDNT_SetAnimation)
|
||||
{
|
||||
CSetAnimationDependency *pAnim = static_cast<CSetAnimationDependency*>(pNode);
|
||||
ParseChildren = mCharacterUsageMap.IsAnimationUsed(mCurrentAnimSetID, pAnim);
|
||||
}
|
||||
|
||||
else
|
||||
ParseChildren = true;
|
||||
|
||||
if (ParseChildren)
|
||||
{
|
||||
for (u32 iChild = 0; iChild < pNode->NumChildren(); iChild++)
|
||||
EvaluateDependencyNode(pCurEntry, pNode->ChildByIndex(iChild), rOut, pAudioGroupsOut);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ class CCharacterUsageMap
|
||||
public:
|
||||
CCharacterUsageMap() : mLayerIndex(-1), mIsInitialArea(true), mCurrentAreaAllowsDupes(false) {}
|
||||
bool IsCharacterUsed(const CAssetID& rkID, u32 CharacterIndex) const;
|
||||
bool IsAnimationUsed(const CAssetID& rkID, CSetAnimationDependency *pAnim) const;
|
||||
void FindUsagesForArea(CWorld *pWorld, CResourceEntry *pEntry);
|
||||
void FindUsagesForArea(CWorld *pWorld, u32 AreaIndex);
|
||||
void FindUsagesForLayer(CResourceEntry *pAreaEntry, u32 LayerIndex);
|
||||
@@ -76,6 +77,7 @@ public:
|
||||
|
||||
void BuildDependencyList(std::list<CAssetID>& rAssetsOut, std::list<u32>& rLayerOffsetsOut, std::set<CAssetID> *pAudioGroupsOut = nullptr);
|
||||
void AddDependency(const CAssetID& rkID, std::list<CAssetID>& rOut, std::set<CAssetID> *pAudioGroupsOut);
|
||||
void EvaluateDependencyNode(CResourceEntry *pCurEntry, IDependencyNode *pNode, std::list<CAssetID>& rOut, std::set<CAssetID> *pAudioGroupsOut);
|
||||
};
|
||||
|
||||
#endif // DEPENDENCYLISTBUILDERS
|
||||
|
||||
Reference in New Issue
Block a user