Added support for CHAR, SAND, and SCAN dependencies in MP3

This commit is contained in:
Aruki
2017-04-30 22:28:37 -06:00
parent 11ccd23baf
commit 88c11555c0
29 changed files with 715 additions and 235 deletions

View File

@@ -5,6 +5,7 @@
#include "CAnimEventData.h"
#include "CSkeleton.h"
#include "CSkin.h"
#include "CSourceAnimData.h"
#include "IMetaAnimation.h"
#include "IMetaTransition.h"
#include "Core/Resource/CDependencyGroup.h"
@@ -43,20 +44,38 @@ struct SHalfTransition
IMetaTransition *pMetaTrans;
};
// Character structures
enum EOverlayType
{
eOT_Frozen = FOURCC('FRZN'),
eOT_Hypermode = FOURCC('HYPR'),
eOT_Acid = FOURCC('ACID'),
eOT_XRay = FOURCC('XRAY')
};
struct SOverlayModel
{
EOverlayType Type;
CAssetID ModelID;
CAssetID SkinID;
};
struct SSetCharacter
{
u32 ID;
TString Name;
TResPtr<CModel> pModel;
TResPtr<CSkin> pSkin;
TResPtr<CSkeleton> pSkeleton;
std::vector<SOverlayModel> OverlayModels;
CAssetID AnimDataID;
std::vector<CAssetID> GenericParticles;
std::vector<CAssetID> ElectricParticles;
std::vector<CAssetID> SwooshParticles;
std::vector<CAssetID> SpawnParticles;
std::vector<CAssetID> EffectParticles;
CAssetID IceModel;
CAssetID IceSkin;
std::vector<CAssetID> SoundEffects;
CAssetID SpatialPrimitives;
std::set<u32> UsedAnimationIndices;
};
@@ -114,16 +133,49 @@ public:
// Character dependencies
for (u32 iChar = 0; iChar < mCharacters.size(); iChar++)
{
CSetCharacterDependency *pCharTree = CSetCharacterDependency::BuildTree(this, iChar);
CSetCharacterDependency *pCharTree = CSetCharacterDependency::BuildTree( mCharacters[iChar] );
ASSERT(pCharTree);
pTree->AddChild(pCharTree);
}
for (u32 iAnim = 0; iAnim < mAnimations.size(); iAnim++)
// Animation dependencies
if (Game() <= eEchoes)
{
CSetAnimationDependency *pAnimTree = CSetAnimationDependency::BuildTree(this, iAnim);
ASSERT(pAnimTree);
pTree->AddChild(pAnimTree);
for (u32 iAnim = 0; iAnim < mAnimations.size(); iAnim++)
{
CSetAnimationDependency *pAnimTree = CSetAnimationDependency::BuildTree(this, iAnim);
ASSERT(pAnimTree);
pTree->AddChild(pAnimTree);
}
}
else
{
const SSetCharacter& rkChar = mCharacters[0];
std::set<CAnimPrimitive> PrimitiveSet;
// Animations
for (u32 iAnim = 0; iAnim < mAnimations.size(); iAnim++)
{
const SAnimation& rkAnim = mAnimations[iAnim];
rkAnim.pMetaAnim->GetUniquePrimitives(PrimitiveSet);
}
CSourceAnimData *pAnimData = (CSourceAnimData*) gpResourceStore->LoadResource(rkChar.AnimDataID, "SAND");
if (pAnimData)
pAnimData->AddTransitionDependencies(pTree);
// Event particles/sounds
for (auto Iter = PrimitiveSet.begin(); Iter != PrimitiveSet.end(); Iter++)
{
const CAnimPrimitive& rkPrim = *Iter;
pTree->AddDependency(rkPrim.Animation());
}
for (u32 iSound = 0; iSound < rkChar.SoundEffects.size(); iSound++)
{
pTree->AddDependency(rkChar.SoundEffects[iSound]);
}
}
return pTree;

View File

@@ -136,30 +136,32 @@ void CAnimationParameters::Write(IOutputStream& rSCLY)
}
}
const SSetCharacter* CAnimationParameters::GetCurrentSetCharacter(s32 NodeIndex /*= -1*/)
{
CAnimSet *pSet = AnimSet();
if (pSet && pSet->Type() == eAnimSet)
{
if (NodeIndex == -1)
NodeIndex = mCharIndex;
if (mCharIndex != -1 && pSet->NumCharacters() > (u32) NodeIndex)
return pSet->Character(NodeIndex);
}
return nullptr;
}
CModel* CAnimationParameters::GetCurrentModel(s32 NodeIndex /*= -1*/)
{
if (!mCharacterID.IsValid()) return nullptr;
CAnimSet *pSet = AnimSet();
if (!pSet) return nullptr;
if (pSet->Type() != eAnimSet) return nullptr;
if (NodeIndex == -1) NodeIndex = mCharIndex;
if (pSet->NumCharacters() <= (u32) NodeIndex) return nullptr;
return pSet->Character(NodeIndex)->pModel;
const SSetCharacter *pkChar = GetCurrentSetCharacter(NodeIndex);
return pkChar ? pkChar->pModel : nullptr;
}
TString CAnimationParameters::GetCurrentCharacterName(s32 NodeIndex /*= -1*/)
{
if (!mCharacterID.IsValid()) return "";
CAnimSet *pSet = AnimSet();
if (!pSet) return "";
if (pSet->Type() != eAnimSet) return "";
if (NodeIndex == -1) NodeIndex = mCharIndex;
if (pSet->NumCharacters() <= (u32) NodeIndex) return "";
return pSet->Character(NodeIndex)->Name;
const SSetCharacter *pkChar = GetCurrentSetCharacter(NodeIndex);
return pkChar ? pkChar->Name : "";
}
// ************ ACCESSORS ************

View File

@@ -1,7 +1,6 @@
#ifndef CANIMATIONPARAMETERS_H
#define CANIMATIONPARAMETERS_H
#include "CAnimSet.h"
#include "Core/Resource/TResPtr.h"
#include "Core/Resource/Model/CModel.h"
#include <Common/EGame.h>
@@ -22,6 +21,7 @@ public:
CAnimationParameters(IInputStream& rSCLY, EGame Game);
void Write(IOutputStream& rSCLY);
const SSetCharacter* GetCurrentSetCharacter(s32 NodeIndex = -1);
CModel* GetCurrentModel(s32 NodeIndex = -1);
TString GetCurrentCharacterName(s32 NodeIndex = -1);

View File

@@ -0,0 +1,109 @@
#ifndef CSOURCEANIMDATA_H
#define CSOURCEANIMDATA_H
#include "Core/Resource/CResource.h"
#include "IMetaTransition.h"
class CSourceAnimData : public CResource
{
DECLARE_RESOURCE_TYPE(eSourceAnimData)
friend class CAnimSetLoader;
struct STransition
{
CAssetID AnimA;
CAssetID AnimB;
IMetaTransition *pTransition;
};
struct SHalfTransition
{
CAssetID Anim;
IMetaTransition *pTransition;
};
std::vector<STransition> mTransitions;
std::vector<SHalfTransition> mHalfTransitions;
IMetaTransition *mpDefaultTransition;
public:
CSourceAnimData(CResourceEntry *pEntry = 0)
: CResource(pEntry)
, mpDefaultTransition(nullptr)
{}
~CSourceAnimData()
{
for (u32 TransIdx = 0; TransIdx < mTransitions.size(); TransIdx++)
delete mTransitions[TransIdx].pTransition;
for (u32 HalfIdx = 0; HalfIdx < mHalfTransitions.size(); HalfIdx++)
delete mHalfTransitions[HalfIdx].pTransition;
delete mpDefaultTransition;
}
CDependencyTree* BuildDependencyTree() const
{
// SAND normally has dependencies from meta-transitions and events
// However, all of these can be character-specific. To simplify things, all SAND
// dependencies are being added to the CHAR dependency tree instead. Therefore the
// SAND dependency tree is left empty.
return new CDependencyTree();
}
void AddTransitionDependencies(CDependencyTree *pTree)
{
// Note: All CHAR animations must have been added to the tree before this function is run
std::set<IMetaTransition*> UsedTransitions;
while (true)
{
// Find all relevant primitives
std::set<CAnimPrimitive> PrimSet;
if (UsedTransitions.find(mpDefaultTransition) == UsedTransitions.end())
{
mpDefaultTransition->GetUniquePrimitives(PrimSet);
UsedTransitions.insert(mpDefaultTransition);
}
for (u32 TransitionIdx = 0; TransitionIdx < mTransitions.size(); TransitionIdx++)
{
const STransition& rkTransition = mTransitions[TransitionIdx];
IMetaTransition *pTransition = rkTransition.pTransition;
if ( pTree->HasDependency(rkTransition.AnimA) &&
pTree->HasDependency(rkTransition.AnimB) &&
UsedTransitions.find(pTransition) == UsedTransitions.end() )
{
pTransition->GetUniquePrimitives(PrimSet);
UsedTransitions.insert(pTransition);
}
}
for (u32 HalfIdx = 0; HalfIdx < mHalfTransitions.size(); HalfIdx++)
{
const SHalfTransition& rkHalfTrans = mHalfTransitions[HalfIdx];
IMetaTransition *pTransition = rkHalfTrans.pTransition;
if ( pTree->HasDependency(rkHalfTrans.Anim) &&
UsedTransitions.find(pTransition) == UsedTransitions.end() )
{
pTransition->GetUniquePrimitives(PrimSet);
UsedTransitions.insert(pTransition);
}
}
// If we have no new primitives then we've exhausted all usable transitions; break out
if (PrimSet.empty())
break;
// Add all transition primitives to the tree
for (auto Iter = PrimSet.begin(); Iter != PrimSet.end(); Iter++)
pTree->AddDependency(Iter->Animation());
}
}
};
#endif // CSOURCEANIMDATA_H

View File

@@ -3,24 +3,24 @@
// ************ CMetaAnimFactory ************
CMetaAnimFactory gMetaAnimFactory;
IMetaAnimation* CMetaAnimFactory::LoadFromStream(IInputStream& rInput)
IMetaAnimation* CMetaAnimFactory::LoadFromStream(IInputStream& rInput, EGame Game)
{
EMetaAnimationType Type = (EMetaAnimationType) rInput.ReadLong();
switch (Type)
{
case eMAT_Play:
return new CMetaAnimPlay(rInput);
return new CMetaAnimPlay(rInput, Game);
case eMAT_Blend:
case eMAT_PhaseBlend:
return new CMetaAnimBlend(Type, rInput);
return new CMetaAnimBlend(Type, rInput, Game);
case eMAT_Random:
return new CMetaAnimRandom(rInput);
return new CMetaAnimRandom(rInput, Game);
case eMAT_Sequence:
return new CMetaAnimSequence(rInput);
return new CMetaAnimSequence(rInput, Game);
default:
Log::Error("Unrecognized meta-animation type: " + TString::FromInt32(Type, 0, 10));
@@ -29,9 +29,9 @@ IMetaAnimation* CMetaAnimFactory::LoadFromStream(IInputStream& rInput)
}
// ************ CMetaAnimationPlay ************
CMetaAnimPlay::CMetaAnimPlay(IInputStream& rInput)
CMetaAnimPlay::CMetaAnimPlay(IInputStream& rInput, EGame Game)
{
mPrimitive = CAnimPrimitive(rInput);
mPrimitive = CAnimPrimitive(rInput, Game);
mUnknownA = rInput.ReadFloat();
mUnknownB = rInput.ReadLong();
}
@@ -47,12 +47,12 @@ void CMetaAnimPlay::GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) cons
}
// ************ CMetaAnimBlend ************
CMetaAnimBlend::CMetaAnimBlend(EMetaAnimationType Type, IInputStream& rInput)
CMetaAnimBlend::CMetaAnimBlend(EMetaAnimationType Type, IInputStream& rInput, EGame Game)
{
ASSERT(Type == eMAT_Blend || Type == eMAT_PhaseBlend);
mType = Type;
mpMetaAnimA = gMetaAnimFactory.LoadFromStream(rInput);
mpMetaAnimB = gMetaAnimFactory.LoadFromStream(rInput);
mpMetaAnimA = gMetaAnimFactory.LoadFromStream(rInput, Game);
mpMetaAnimB = gMetaAnimFactory.LoadFromStream(rInput, Game);
mUnknownA = rInput.ReadFloat();
mUnknownB = rInput.ReadBool();
}
@@ -75,7 +75,7 @@ void CMetaAnimBlend::GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) con
}
// ************ CMetaAnimRandom ************
CMetaAnimRandom::CMetaAnimRandom(IInputStream& rInput)
CMetaAnimRandom::CMetaAnimRandom(IInputStream& rInput, EGame Game)
{
u32 NumPairs = rInput.ReadLong();
mProbabilityPairs.reserve(NumPairs);
@@ -83,7 +83,7 @@ CMetaAnimRandom::CMetaAnimRandom(IInputStream& rInput)
for (u32 iAnim = 0; iAnim < NumPairs; iAnim++)
{
SAnimProbabilityPair Pair;
Pair.pAnim = gMetaAnimFactory.LoadFromStream(rInput);
Pair.pAnim = gMetaAnimFactory.LoadFromStream(rInput, Game);
Pair.Probability = rInput.ReadLong();
mProbabilityPairs.push_back(Pair);
}
@@ -107,14 +107,14 @@ void CMetaAnimRandom::GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) co
}
// ************ CMetaAnimSequence ************
CMetaAnimSequence::CMetaAnimSequence(IInputStream& rInput)
CMetaAnimSequence::CMetaAnimSequence(IInputStream& rInput, EGame Game)
{
u32 NumAnims = rInput.ReadLong();
mAnimations.reserve(NumAnims);
for (u32 iAnim = 0; iAnim < NumAnims; iAnim++)
{
IMetaAnimation *pAnim = gMetaAnimFactory.LoadFromStream(rInput);
IMetaAnimation *pAnim = gMetaAnimFactory.LoadFromStream(rInput, Game);
mAnimations.push_back(pAnim);
}
}

View File

@@ -18,7 +18,7 @@ enum EMetaAnimationType
class CMetaAnimFactory
{
public:
class IMetaAnimation* LoadFromStream(IInputStream& rInput);
class IMetaAnimation* LoadFromStream(IInputStream& rInput, EGame Game);
};
extern CMetaAnimFactory gMetaAnimFactory;
@@ -32,9 +32,9 @@ class CAnimPrimitive
public:
CAnimPrimitive() : mID(0) {}
CAnimPrimitive(IInputStream& rInput)
CAnimPrimitive(IInputStream& rInput, EGame Game)
{
mpAnim = gpResourceStore->LoadResource(rInput.ReadLong(), "ANIM");
mpAnim = gpResourceStore->LoadResource( CAssetID(rInput, Game), "ANIM" );
mID = rInput.ReadLong();
mName = rInput.ReadString();
}
@@ -58,7 +58,7 @@ public:
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const = 0;
// Static
static IMetaAnimation* LoadFromStream(IInputStream& rInput);
static IMetaAnimation* LoadFromStream(IInputStream& rInput, EGame Game);
};
// CMetaAnimPlay - plays an animation
@@ -70,7 +70,7 @@ protected:
u32 mUnknownB;
public:
CMetaAnimPlay(IInputStream& rInput);
CMetaAnimPlay(IInputStream& rInput, EGame Game);
virtual EMetaAnimationType Type() const;
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const;
@@ -91,7 +91,7 @@ protected:
bool mUnknownB;
public:
CMetaAnimBlend(EMetaAnimationType Type, IInputStream& rInput);
CMetaAnimBlend(EMetaAnimationType Type, IInputStream& rInput, EGame Game);
~CMetaAnimBlend();
virtual EMetaAnimationType Type() const;
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const;
@@ -117,7 +117,7 @@ protected:
std::vector<SAnimProbabilityPair> mProbabilityPairs;
public:
CMetaAnimRandom(IInputStream& rInput);
CMetaAnimRandom(IInputStream& rInput, EGame Game);
~CMetaAnimRandom();
virtual EMetaAnimationType Type() const;
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const;
@@ -130,7 +130,7 @@ protected:
std::vector<IMetaAnimation*> mAnimations;
public:
CMetaAnimSequence(IInputStream& rInput);
CMetaAnimSequence(IInputStream& rInput, EGame Game);
~CMetaAnimSequence();
virtual EMetaAnimationType Type() const;
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const;

View File

@@ -4,21 +4,24 @@
// ************ CMetaTransFactory ************
CMetaTransFactory gMetaTransFactory;
IMetaTransition* CMetaTransFactory::LoadFromStream(IInputStream& rInput)
IMetaTransition* CMetaTransFactory::LoadFromStream(IInputStream& rInput, EGame Game)
{
EMetaTransitionType Type = (EMetaTransitionType) rInput.ReadLong();
switch (Type)
{
case eMTT_MetaAnim:
return new CMetaTransMetaAnim(rInput);
return new CMetaTransMetaAnim(rInput, Game);
case eMTT_Trans:
case eMTT_PhaseTrans:
return new CMetaTransTrans(Type, rInput);
return new CMetaTransTrans(Type, rInput, Game);
case eMTT_Snap:
return new CMetaTransSnap(rInput);
return new CMetaTransSnap(rInput, Game);
case eMTT_Type4:
return new CMetaTransType4(rInput, Game);
default:
Log::Error("Unrecognized meta-transition type: " + TString::FromInt32(Type, 0, 10));
@@ -27,9 +30,9 @@ IMetaTransition* CMetaTransFactory::LoadFromStream(IInputStream& rInput)
}
// ************ CMetaTransMetaAnim ************
CMetaTransMetaAnim::CMetaTransMetaAnim(IInputStream& rInput)
CMetaTransMetaAnim::CMetaTransMetaAnim(IInputStream& rInput, EGame Game)
{
mpAnim = gMetaAnimFactory.LoadFromStream(rInput);
mpAnim = gMetaAnimFactory.LoadFromStream(rInput, Game);
}
CMetaTransMetaAnim::~CMetaTransMetaAnim()
@@ -48,15 +51,23 @@ void CMetaTransMetaAnim::GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet)
}
// ************ CMetaTransTrans ************
CMetaTransTrans::CMetaTransTrans(EMetaTransitionType Type, IInputStream& rInput)
CMetaTransTrans::CMetaTransTrans(EMetaTransitionType Type, IInputStream& rInput, EGame Game)
{
ASSERT(Type == eMTT_Trans || Type == eMTT_PhaseTrans);
mType = Type;
mUnknownA = rInput.ReadFloat();
mUnknownB = rInput.ReadLong();
mUnknownC = rInput.ReadBool();
mUnknownD = rInput.ReadBool();
mUnknownE = rInput.ReadLong();
if (Game <= eEchoes)
{
mUnknownA = rInput.ReadFloat();
mUnknownB = rInput.ReadLong();
mUnknownC = rInput.ReadBool();
mUnknownD = rInput.ReadBool();
mUnknownE = rInput.ReadLong();
}
else
{
rInput.Skip(0x13);
}
}
EMetaTransitionType CMetaTransTrans::Type() const
@@ -69,7 +80,7 @@ void CMetaTransTrans::GetUniquePrimitives(std::set<CAnimPrimitive>&) const
}
// ************ CMetaTransSnap ************
CMetaTransSnap::CMetaTransSnap(IInputStream&)
CMetaTransSnap::CMetaTransSnap(IInputStream&, EGame)
{
}
@@ -81,3 +92,18 @@ EMetaTransitionType CMetaTransSnap::Type() const
void CMetaTransSnap::GetUniquePrimitives(std::set<CAnimPrimitive>&) const
{
}
// ************ CMetaTransType4 ************
CMetaTransType4::CMetaTransType4(IInputStream& rInput, EGame)
{
rInput.Skip(0x14);
}
EMetaTransitionType CMetaTransType4::Type() const
{
return eMTT_Type4;
}
void CMetaTransType4::GetUniquePrimitives(std::set<CAnimPrimitive>&) const
{
}

View File

@@ -11,14 +11,15 @@ enum EMetaTransitionType
eMTT_MetaAnim = 0,
eMTT_Trans = 1,
eMTT_PhaseTrans = 2, // note: structure shared with eMTT_Trans
eMTT_Snap = 3
eMTT_Snap = 3,
eMTT_Type4 = 4 // MP3 only
};
// Factory class
class CMetaTransFactory
{
public:
class IMetaTransition* LoadFromStream(IInputStream& rInput);
class IMetaTransition* LoadFromStream(IInputStream& rInput, EGame Game);
};
extern CMetaTransFactory gMetaTransFactory;
@@ -38,7 +39,7 @@ class CMetaTransMetaAnim : public IMetaTransition
IMetaAnimation *mpAnim;
public:
CMetaTransMetaAnim(IInputStream& rInput);
CMetaTransMetaAnim(IInputStream& rInput, EGame Game);
~CMetaTransMetaAnim();
virtual EMetaTransitionType Type() const;
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const;
@@ -55,7 +56,7 @@ class CMetaTransTrans : public IMetaTransition
u32 mUnknownE;
public:
CMetaTransTrans(EMetaTransitionType Type, IInputStream& rInput);
CMetaTransTrans(EMetaTransitionType Type, IInputStream& rInput, EGame Game);
virtual EMetaTransitionType Type() const;
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const;
};
@@ -64,7 +65,16 @@ public:
class CMetaTransSnap : public IMetaTransition
{
public:
CMetaTransSnap(IInputStream& rInput);
CMetaTransSnap(IInputStream& rInput, EGame Game);
virtual EMetaTransitionType Type() const;
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const;
};
// CMetaTransType4
class CMetaTransType4 : public IMetaTransition
{
public:
CMetaTransType4(IInputStream& rInput, EGame Game);
virtual EMetaTransitionType Type() const;
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const;
};