mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-05-29 02:31:20 +00:00
Added support for loading meta-animations and meta-transitions (yay! animation exclusion doesn't crash anymore!)
This commit is contained in:
parent
595e4b931e
commit
040caca896
@ -211,7 +211,9 @@ HEADERS += \
|
|||||||
Resource/Animation/CAnimEventData.h \
|
Resource/Animation/CAnimEventData.h \
|
||||||
Resource/Animation/CAnimSet.h \
|
Resource/Animation/CAnimSet.h \
|
||||||
Resource/Animation/CSkeleton.h \
|
Resource/Animation/CSkeleton.h \
|
||||||
Resource/Animation/CSkin.h
|
Resource/Animation/CSkin.h \
|
||||||
|
Resource/Animation/IMetaTransition.h \
|
||||||
|
Resource/Animation/IMetaAnimation.h
|
||||||
|
|
||||||
# Source Files
|
# Source Files
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
@ -310,4 +312,6 @@ SOURCES += \
|
|||||||
Resource/Factory/CAnimEventLoader.cpp \
|
Resource/Factory/CAnimEventLoader.cpp \
|
||||||
Resource/Animation/CAnimation.cpp \
|
Resource/Animation/CAnimation.cpp \
|
||||||
Resource/Animation/CAnimationParameters.cpp \
|
Resource/Animation/CAnimationParameters.cpp \
|
||||||
Resource/Animation/CSkeleton.cpp
|
Resource/Animation/CSkeleton.cpp \
|
||||||
|
Resource/Animation/IMetaAnimation.cpp \
|
||||||
|
Resource/Animation/IMetaTransition.cpp
|
||||||
|
@ -186,7 +186,7 @@ EDependencyNodeType CSetCharacterDependency::Type() const
|
|||||||
|
|
||||||
void CSetCharacterDependency::Serialize(IArchive& rArc)
|
void CSetCharacterDependency::Serialize(IArchive& rArc)
|
||||||
{
|
{
|
||||||
rArc << SERIAL("SetIndex", mSetIndex)
|
rArc << SERIAL("CharSetIndex", mCharSetIndex)
|
||||||
<< SERIAL_ABSTRACT_CONTAINER("Children", mChildren, "Child", &gDependencyNodeFactory);
|
<< SERIAL_ABSTRACT_CONTAINER("Children", mChildren, "Child", &gDependencyNodeFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,8 +234,8 @@ void CSetAnimationDependency::Serialize(IArchive& rArc)
|
|||||||
|
|
||||||
CSetAnimationDependency* CSetAnimationDependency::BuildTree(const CAnimSet *pkOwnerSet, u32 AnimIndex)
|
CSetAnimationDependency* CSetAnimationDependency::BuildTree(const CAnimSet *pkOwnerSet, u32 AnimIndex)
|
||||||
{
|
{
|
||||||
const SSetAnimation *pkAnim = pkOwnerSet->Animation(AnimIndex);
|
|
||||||
CSetAnimationDependency *pTree = new CSetAnimationDependency;
|
CSetAnimationDependency *pTree = new CSetAnimationDependency;
|
||||||
|
const SAnimation *pkAnim = pkOwnerSet->Animation(AnimIndex);
|
||||||
|
|
||||||
// Find relevant character indices
|
// Find relevant character indices
|
||||||
for (u32 iChar = 0; iChar < pkOwnerSet->NumCharacters(); iChar++)
|
for (u32 iChar = 0; iChar < pkOwnerSet->NumCharacters(); iChar++)
|
||||||
@ -246,15 +246,21 @@ CSetAnimationDependency* CSetAnimationDependency::BuildTree(const CAnimSet *pkOw
|
|||||||
pTree->mCharacterIndices.insert(iChar);
|
pTree->mCharacterIndices.insert(iChar);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add dependencies. In MP2 animation event data is not a standalone resource.
|
// Add primitive dependencies. In MP2 animation event data is not a standalone resource.
|
||||||
pTree->AddDependency(pkAnim->pAnim);
|
std::set<CAnimPrimitive> UsedPrimitives;
|
||||||
|
pkAnim->pMetaAnim->GetUniquePrimitives(UsedPrimitives);
|
||||||
|
|
||||||
if (pkAnim->pEventData)
|
for (auto Iter = UsedPrimitives.begin(); Iter != UsedPrimitives.end(); Iter++)
|
||||||
{
|
{
|
||||||
if (pkAnim->pEventData->Entry())
|
const CAnimPrimitive& rkPrim = *Iter;
|
||||||
pTree->AddDependency(pkAnim->pEventData);
|
pTree->AddDependency(rkPrim.Animation());
|
||||||
else
|
|
||||||
pkAnim->pEventData->AddDependenciesToTree(pTree);
|
if (pkOwnerSet->Game() >= eEchoesDemo)
|
||||||
|
{
|
||||||
|
CAnimEventData *pEvents = pkOwnerSet->AnimationEventData(rkPrim.ID());
|
||||||
|
ASSERT(pEvents && !pEvents->Entry());
|
||||||
|
pEvents->AddDependenciesToTree(pTree);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pTree;
|
return pTree;
|
||||||
|
@ -11,7 +11,6 @@ class CScriptObject;
|
|||||||
class CPropertyStruct;
|
class CPropertyStruct;
|
||||||
class CAnimSet;
|
class CAnimSet;
|
||||||
struct SSetCharacter;
|
struct SSetCharacter;
|
||||||
struct SSetAnimation;
|
|
||||||
|
|
||||||
// Group of node classes forming a tree of cached resource dependencies.
|
// Group of node classes forming a tree of cached resource dependencies.
|
||||||
enum EDependencyNodeType
|
enum EDependencyNodeType
|
||||||
@ -154,17 +153,17 @@ protected:
|
|||||||
class CSetCharacterDependency : public CDependencyTree
|
class CSetCharacterDependency : public CDependencyTree
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
u32 mSetIndex;
|
u32 mCharSetIndex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CSetCharacterDependency() : CDependencyTree() {}
|
CSetCharacterDependency() : CDependencyTree() {}
|
||||||
CSetCharacterDependency(u32 SetIndex) : CDependencyTree(), mSetIndex(SetIndex) {}
|
CSetCharacterDependency(u32 SetIndex) : CDependencyTree(), mCharSetIndex(SetIndex) {}
|
||||||
|
|
||||||
virtual EDependencyNodeType Type() const;
|
virtual EDependencyNodeType Type() const;
|
||||||
virtual void Serialize(IArchive& rArc);
|
virtual void Serialize(IArchive& rArc);
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
inline u32 SetIndex() const { return mSetIndex; }
|
inline u32 CharSetIndex() const { return mCharSetIndex; }
|
||||||
|
|
||||||
// Static
|
// Static
|
||||||
static CSetCharacterDependency* BuildTree(const CAnimSet *pkOwnerSet, u32 CharIndex);
|
static CSetCharacterDependency* BuildTree(const CAnimSet *pkOwnerSet, u32 CharIndex);
|
||||||
|
@ -268,7 +268,7 @@ void CPackageDependencyListBuilder::EvaluateDependencyNode(CResourceEntry *pCurE
|
|||||||
else if (Type == eDNT_SetCharacter)
|
else if (Type == eDNT_SetCharacter)
|
||||||
{
|
{
|
||||||
CSetCharacterDependency *pChar = static_cast<CSetCharacterDependency*>(pNode);
|
CSetCharacterDependency *pChar = static_cast<CSetCharacterDependency*>(pNode);
|
||||||
ParseChildren = mCharacterUsageMap.IsCharacterUsed(mCurrentAnimSetID, pChar->SetIndex()) || mIsPlayerActor;
|
ParseChildren = mCharacterUsageMap.IsCharacterUsed(mCurrentAnimSetID, pChar->CharSetIndex()) || mIsPlayerActor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set animations should only be added if they're being used by at least one used character
|
// Set animations should only be added if they're being used by at least one used character
|
||||||
@ -438,8 +438,8 @@ void CAreaDependencyListBuilder::EvaluateDependencyNode(CResourceEntry *pCurEntr
|
|||||||
const u32 kEmptySuitIndex = (mGame >= eEchoesDemo ? 3 : 5);
|
const u32 kEmptySuitIndex = (mGame >= eEchoesDemo ? 3 : 5);
|
||||||
|
|
||||||
CSetCharacterDependency *pChar = static_cast<CSetCharacterDependency*>(pNode);
|
CSetCharacterDependency *pChar = static_cast<CSetCharacterDependency*>(pNode);
|
||||||
u32 SetIndex = pChar->SetIndex();
|
u32 SetIndex = pChar->CharSetIndex();
|
||||||
ParseChildren = mCharacterUsageMap.IsCharacterUsed(mCurrentAnimSetID, pChar->SetIndex()) || (mIsPlayerActor && SetIndex == kEmptySuitIndex);
|
ParseChildren = mCharacterUsageMap.IsCharacterUsed(mCurrentAnimSetID, pChar->CharSetIndex()) || (mIsPlayerActor && SetIndex == kEmptySuitIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Type == eDNT_SetAnimation)
|
else if (Type == eDNT_SetAnimation)
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include "CAnimEventData.h"
|
#include "CAnimEventData.h"
|
||||||
#include "CSkeleton.h"
|
#include "CSkeleton.h"
|
||||||
#include "CSkin.h"
|
#include "CSkin.h"
|
||||||
|
#include "IMetaAnimation.h"
|
||||||
|
#include "IMetaTransition.h"
|
||||||
#include "Core/Resource/CDependencyGroup.h"
|
#include "Core/Resource/CDependencyGroup.h"
|
||||||
#include "Core/Resource/CResource.h"
|
#include "Core/Resource/CResource.h"
|
||||||
#include "Core/Resource/TResPtr.h"
|
#include "Core/Resource/TResPtr.h"
|
||||||
@ -13,6 +15,34 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
// Animation structures
|
||||||
|
struct SAdditiveAnim
|
||||||
|
{
|
||||||
|
u32 AnimID;
|
||||||
|
float FadeInTime;
|
||||||
|
float FadeOutTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SAnimation
|
||||||
|
{
|
||||||
|
TString Name;
|
||||||
|
IMetaAnimation *pMetaAnim;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct STransition
|
||||||
|
{
|
||||||
|
u32 Unknown;
|
||||||
|
u32 AnimIdA;
|
||||||
|
u32 AnimIdB;
|
||||||
|
IMetaTransition *pMetaTrans;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SHalfTransition
|
||||||
|
{
|
||||||
|
u32 AnimID;
|
||||||
|
IMetaTransition *pMetaTrans;
|
||||||
|
};
|
||||||
|
|
||||||
struct SSetCharacter
|
struct SSetCharacter
|
||||||
{
|
{
|
||||||
TString Name;
|
TString Name;
|
||||||
@ -30,36 +60,37 @@ struct SSetCharacter
|
|||||||
std::set<u32> UsedAnimationIndices;
|
std::set<u32> UsedAnimationIndices;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SSetAnimation
|
|
||||||
{
|
|
||||||
TString Name;
|
|
||||||
TResPtr<CAnimation> pAnim;
|
|
||||||
TResPtr<CAnimEventData> pEventData;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CAnimSet : public CResource
|
class CAnimSet : public CResource
|
||||||
{
|
{
|
||||||
DECLARE_RESOURCE_TYPE(eAnimSet)
|
DECLARE_RESOURCE_TYPE(eAnimSet)
|
||||||
friend class CAnimSetLoader;
|
friend class CAnimSetLoader;
|
||||||
|
|
||||||
|
// Character Set
|
||||||
std::vector<SSetCharacter> mCharacters;
|
std::vector<SSetCharacter> mCharacters;
|
||||||
std::vector<SSetAnimation> mAnimations;
|
|
||||||
|
// Animation Set
|
||||||
|
std::vector<CAnimPrimitive> mAnimPrimitives;
|
||||||
|
std::vector<SAnimation> mAnimations;
|
||||||
|
std::vector<STransition> mTransitions;
|
||||||
|
IMetaTransition *mpDefaultTransition;
|
||||||
|
std::vector<SAdditiveAnim> mAdditiveAnims;
|
||||||
|
float mDefaultAdditiveFadeIn;
|
||||||
|
float mDefaultAdditiveFadeOut;
|
||||||
|
std::vector<SHalfTransition> mHalfTransitions;
|
||||||
|
std::vector<CAnimEventData*> mAnimEvents; // note: these are for MP2, where event data isn't a standalone resource; these are owned by the animset
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CAnimSet(CResourceEntry *pEntry = 0) : CResource(pEntry) {}
|
CAnimSet(CResourceEntry *pEntry = 0) : CResource(pEntry) {}
|
||||||
|
|
||||||
~CAnimSet()
|
~CAnimSet()
|
||||||
{
|
{
|
||||||
// note: in MP2, event data isn't a standalone resource, so it's owned by the animset; therefore we need to delete it manually
|
// For MP2, anim events need to be cleaned up manually
|
||||||
if (Game() >= eEchoesDemo)
|
if (Game() >= eEchoesDemo)
|
||||||
{
|
{
|
||||||
for (u32 iAnim = 0; iAnim < mAnimations.size(); iAnim++)
|
for (u32 iEvent = 0; iEvent < mAnimEvents.size(); iEvent++)
|
||||||
{
|
{
|
||||||
SSetAnimation& rAnim = mAnimations[iAnim];
|
ASSERT(mAnimEvents[iEvent] && !mAnimEvents[iEvent]->Entry());
|
||||||
CAnimEventData *pEvents = rAnim.pEventData;
|
delete mAnimEvents[iEvent];
|
||||||
ASSERT(pEvents && !pEvents->Entry());
|
|
||||||
rAnim.pEventData = nullptr; // make sure TResPtr destructor doesn't attempt to access
|
|
||||||
delete pEvents;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,11 +117,48 @@ public:
|
|||||||
return pTree;
|
return pTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CAnimation* FindAnimationAsset(u32 AnimID) const
|
||||||
|
{
|
||||||
|
if (AnimID >= 0 && AnimID < mAnimPrimitives.size())
|
||||||
|
{
|
||||||
|
CAnimPrimitive Prim = mAnimPrimitives[AnimID];
|
||||||
|
return Prim.Animation();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
inline u32 NumCharacters() const { return mCharacters.size(); }
|
inline u32 NumCharacters() const { return mCharacters.size(); }
|
||||||
inline u32 NumAnimations() const { return mAnimations.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]; }
|
inline const SSetCharacter* Character(u32 Index) const
|
||||||
|
{
|
||||||
|
ASSERT(Index >= 0 && Index < NumCharacters());
|
||||||
|
return &mCharacters[Index];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const SAnimation* Animation(u32 Index) const
|
||||||
|
{
|
||||||
|
ASSERT(Index >= 0 && Index < NumAnimations());
|
||||||
|
return &mAnimations[Index];
|
||||||
|
}
|
||||||
|
|
||||||
|
CAnimEventData* AnimationEventData(u32 Index) const
|
||||||
|
{
|
||||||
|
ASSERT(Index >= 0 && Index < NumAnimations());
|
||||||
|
|
||||||
|
if (Game() <= ePrime)
|
||||||
|
{
|
||||||
|
const CAnimPrimitive& rkPrim = mAnimPrimitives[Index];
|
||||||
|
return rkPrim.Animation() ? rkPrim.Animation()->EventData() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (Index < mAnimEvents.size() ? mAnimEvents[Index] : nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CCHARACTERSET_H
|
#endif // CCHARACTERSET_H
|
||||||
|
@ -19,7 +19,7 @@ CAnimation::CAnimation(CResourceEntry *pEntry /*= 0*/)
|
|||||||
CDependencyTree* CAnimation::BuildDependencyTree() const
|
CDependencyTree* CAnimation::BuildDependencyTree() const
|
||||||
{
|
{
|
||||||
CDependencyTree *pTree = new CDependencyTree(ID());
|
CDependencyTree *pTree = new CDependencyTree(ID());
|
||||||
pTree->AddDependency(mEventData);
|
pTree->AddDependency(mpEventData);
|
||||||
return pTree;
|
return pTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#define CANIMATION_H
|
#define CANIMATION_H
|
||||||
|
|
||||||
#include "Core/Resource/CResource.h"
|
#include "Core/Resource/CResource.h"
|
||||||
|
#include "Core/Resource/TResPtr.h"
|
||||||
|
#include "Core/Resource/Animation/CAnimEventData.h"
|
||||||
#include <Math/CQuaternion.h>
|
#include <Math/CQuaternion.h>
|
||||||
#include <Math/CVector3f.h>
|
#include <Math/CVector3f.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -31,7 +33,7 @@ class CAnimation : public CResource
|
|||||||
};
|
};
|
||||||
SBoneChannelInfo mBoneInfo[100];
|
SBoneChannelInfo mBoneInfo[100];
|
||||||
|
|
||||||
CAssetID mEventData;
|
TResPtr<CAnimEventData> mpEventData;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CAnimation(CResourceEntry *pEntry = 0);
|
CAnimation(CResourceEntry *pEntry = 0);
|
||||||
@ -39,9 +41,10 @@ public:
|
|||||||
void EvaluateTransform(float Time, u32 BoneID, CVector3f *pOutTranslation, CQuaternion *pOutRotation, CVector3f *pOutScale) const;
|
void EvaluateTransform(float Time, u32 BoneID, CVector3f *pOutTranslation, CQuaternion *pOutRotation, CVector3f *pOutScale) const;
|
||||||
bool HasTranslation(u32 BoneID) const;
|
bool HasTranslation(u32 BoneID) const;
|
||||||
|
|
||||||
inline float Duration() const { return mDuration; }
|
inline float Duration() const { return mDuration; }
|
||||||
inline u32 NumKeys() const { return mNumKeys; }
|
inline u32 NumKeys() const { return mNumKeys; }
|
||||||
inline float TickInterval() const { return mTickInterval; }
|
inline float TickInterval() const { return mTickInterval; }
|
||||||
|
inline CAnimEventData* EventData() const { return mpEventData; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CANIMATION_H
|
#endif // CANIMATION_H
|
||||||
|
137
src/Core/Resource/Animation/IMetaAnimation.cpp
Normal file
137
src/Core/Resource/Animation/IMetaAnimation.cpp
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
#include "IMetaAnimation.h"
|
||||||
|
|
||||||
|
// ************ CMetaAnimFactory ************
|
||||||
|
CMetaAnimFactory gMetaAnimFactory;
|
||||||
|
|
||||||
|
IMetaAnimation* CMetaAnimFactory::LoadFromStream(IInputStream& rInput)
|
||||||
|
{
|
||||||
|
EMetaAnimationType Type = (EMetaAnimationType) rInput.ReadLong();
|
||||||
|
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case eMAT_Play:
|
||||||
|
return new CMetaAnimPlay(rInput);
|
||||||
|
|
||||||
|
case eMAT_Blend:
|
||||||
|
case eMAT_PhaseBlend:
|
||||||
|
return new CMetaAnimBlend(Type, rInput);
|
||||||
|
|
||||||
|
case eMAT_Random:
|
||||||
|
return new CMetaAnimRandom(rInput);
|
||||||
|
|
||||||
|
case eMAT_Sequence:
|
||||||
|
return new CMetaAnimSequence(rInput);
|
||||||
|
|
||||||
|
default:
|
||||||
|
Log::Error("Unrecognized meta-animation type: " + TString::FromInt32(Type, 0, 10));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ CMetaAnimationPlay ************
|
||||||
|
CMetaAnimPlay::CMetaAnimPlay(IInputStream& rInput)
|
||||||
|
{
|
||||||
|
mPrimitive = CAnimPrimitive(rInput);
|
||||||
|
mUnknownA = rInput.ReadFloat();
|
||||||
|
mUnknownB = rInput.ReadLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
EMetaAnimationType CMetaAnimPlay::Type() const
|
||||||
|
{
|
||||||
|
return eMAT_Play;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMetaAnimPlay::GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const
|
||||||
|
{
|
||||||
|
rPrimSet.insert(mPrimitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ CMetaAnimBlend ************
|
||||||
|
CMetaAnimBlend::CMetaAnimBlend(EMetaAnimationType Type, IInputStream& rInput)
|
||||||
|
{
|
||||||
|
ASSERT(Type == eMAT_Blend || Type == eMAT_PhaseBlend);
|
||||||
|
mType = Type;
|
||||||
|
mpMetaAnimA = gMetaAnimFactory.LoadFromStream(rInput);
|
||||||
|
mpMetaAnimB = gMetaAnimFactory.LoadFromStream(rInput);
|
||||||
|
mUnknownA = rInput.ReadFloat();
|
||||||
|
mUnknownB = rInput.ReadBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
CMetaAnimBlend::~CMetaAnimBlend()
|
||||||
|
{
|
||||||
|
delete mpMetaAnimA;
|
||||||
|
delete mpMetaAnimB;
|
||||||
|
}
|
||||||
|
|
||||||
|
EMetaAnimationType CMetaAnimBlend::Type() const
|
||||||
|
{
|
||||||
|
return mType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMetaAnimBlend::GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const
|
||||||
|
{
|
||||||
|
mpMetaAnimA->GetUniquePrimitives(rPrimSet);
|
||||||
|
mpMetaAnimB->GetUniquePrimitives(rPrimSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ CMetaAnimRandom ************
|
||||||
|
CMetaAnimRandom::CMetaAnimRandom(IInputStream& rInput)
|
||||||
|
{
|
||||||
|
u32 NumPairs = rInput.ReadLong();
|
||||||
|
mProbabilityPairs.reserve(NumPairs);
|
||||||
|
|
||||||
|
for (u32 iAnim = 0; iAnim < NumPairs; iAnim++)
|
||||||
|
{
|
||||||
|
SAnimProbabilityPair Pair;
|
||||||
|
Pair.pAnim = gMetaAnimFactory.LoadFromStream(rInput);
|
||||||
|
Pair.Probability = rInput.ReadLong();
|
||||||
|
mProbabilityPairs.push_back(Pair);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CMetaAnimRandom::~CMetaAnimRandom()
|
||||||
|
{
|
||||||
|
for (u32 iPair = 0; iPair < mProbabilityPairs.size(); iPair++)
|
||||||
|
delete mProbabilityPairs[iPair].pAnim;
|
||||||
|
}
|
||||||
|
|
||||||
|
EMetaAnimationType CMetaAnimRandom::Type() const
|
||||||
|
{
|
||||||
|
return eMAT_Random;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMetaAnimRandom::GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const
|
||||||
|
{
|
||||||
|
for (u32 iPair = 0; iPair < mProbabilityPairs.size(); iPair++)
|
||||||
|
mProbabilityPairs[iPair].pAnim->GetUniquePrimitives(rPrimSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ CMetaAnimSequence ************
|
||||||
|
CMetaAnimSequence::CMetaAnimSequence(IInputStream& rInput)
|
||||||
|
{
|
||||||
|
u32 NumAnims = rInput.ReadLong();
|
||||||
|
mAnimations.reserve(NumAnims);
|
||||||
|
|
||||||
|
for (u32 iAnim = 0; iAnim < NumAnims; iAnim++)
|
||||||
|
{
|
||||||
|
IMetaAnimation *pAnim = gMetaAnimFactory.LoadFromStream(rInput);
|
||||||
|
mAnimations.push_back(pAnim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CMetaAnimSequence::~CMetaAnimSequence()
|
||||||
|
{
|
||||||
|
for (u32 iAnim = 0; iAnim < mAnimations.size(); iAnim++)
|
||||||
|
delete mAnimations[iAnim];
|
||||||
|
}
|
||||||
|
|
||||||
|
EMetaAnimationType CMetaAnimSequence::Type() const
|
||||||
|
{
|
||||||
|
return eMAT_Sequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMetaAnimSequence::GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const
|
||||||
|
{
|
||||||
|
for (u32 iAnim = 0; iAnim < mAnimations.size(); iAnim++)
|
||||||
|
mAnimations[iAnim]->GetUniquePrimitives(rPrimSet);
|
||||||
|
}
|
@ -9,62 +9,98 @@ enum EMetaAnimationType
|
|||||||
{
|
{
|
||||||
eMAT_Play = 0,
|
eMAT_Play = 0,
|
||||||
eMAT_Blend = 1,
|
eMAT_Blend = 1,
|
||||||
eMAT_PhaseBlend = 2, // note: structure shared with eMAT_Blend, differences are currently unknown
|
eMAT_PhaseBlend = 2, // note: structure shared with eMAT_Blend
|
||||||
eMAT_Random = 3,
|
eMAT_Random = 3,
|
||||||
eMAT_Sequence = 4
|
eMAT_Sequence = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Factory class
|
||||||
|
class CMetaAnimFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class IMetaAnimation* LoadFromStream(IInputStream& rInput);
|
||||||
|
};
|
||||||
|
extern CMetaAnimFactory gMetaAnimFactory;
|
||||||
|
|
||||||
|
// Animation primitive class
|
||||||
|
class CAnimPrimitive
|
||||||
|
{
|
||||||
|
TResPtr<CAnimation> mpAnim;
|
||||||
|
u32 mID;
|
||||||
|
TString mName;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CAnimPrimitive() : mID(0) {}
|
||||||
|
|
||||||
|
CAnimPrimitive(IInputStream& rInput)
|
||||||
|
{
|
||||||
|
mpAnim = gpResourceStore->LoadResource(rInput.ReadLong(), "ANIM");
|
||||||
|
mID = rInput.ReadLong();
|
||||||
|
mName = rInput.ReadString();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator==(const CAnimPrimitive& rkRight) const { return mID == rkRight.mID; }
|
||||||
|
inline bool operator< (const CAnimPrimitive& rkRight) const { return mID < rkRight.mID; }
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
CAnimation* Animation() const { return mpAnim; }
|
||||||
|
u32 ID() const { return mID; }
|
||||||
|
TString Name() const { return mName; }
|
||||||
|
};
|
||||||
|
|
||||||
// Base MetaAnimation interface
|
// Base MetaAnimation interface
|
||||||
class IMetaAnimation
|
class IMetaAnimation
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
IMetaAnimation() {}
|
||||||
|
virtual ~IMetaAnimation() {}
|
||||||
|
virtual EMetaAnimationType Type() const = 0;
|
||||||
|
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const = 0;
|
||||||
|
|
||||||
|
// Static
|
||||||
|
static IMetaAnimation* LoadFromStream(IInputStream& rInput);
|
||||||
|
};
|
||||||
|
|
||||||
|
// CMetaAnimPlay - plays an animation
|
||||||
|
class CMetaAnimPlay : public IMetaAnimation
|
||||||
|
{
|
||||||
protected:
|
protected:
|
||||||
TString mName;
|
CAnimPrimitive mPrimitive;
|
||||||
EMetaAnimationType mType;
|
float mUnknownA;
|
||||||
|
u32 mUnknownB;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IMetaAnimation(EMetaAnimationType Type)
|
CMetaAnimPlay(IInputStream& rInput);
|
||||||
: mType(Type) {}
|
virtual EMetaAnimationType Type() const;
|
||||||
|
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const;
|
||||||
virtual ~IMetaAnimation() {}
|
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
inline void SetName(const TString& rkName) { mName = rkName; }
|
inline CAnimPrimitive Primitive() const { return mPrimitive; }
|
||||||
inline TString Name() const { return mName; }
|
inline float UnknownA() const { return mUnknownA; }
|
||||||
inline EMetaAnimationType Type() const { return mType; }
|
inline u32 UnknownB() const { return mUnknownB; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// CMetaAnimationPlay - plays an animation
|
// CMetaAnimBlend - blend between two animations
|
||||||
class CMetaAnimationPlay : public IMetaAnimation
|
class CMetaAnimBlend : public IMetaAnimation
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
TResPtr<CAnimation> mpAnim;
|
EMetaAnimationType mType;
|
||||||
|
IMetaAnimation *mpMetaAnimA;
|
||||||
|
IMetaAnimation *mpMetaAnimB;
|
||||||
|
float mUnknownA;
|
||||||
|
bool mUnknownB;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CMetaAnimationPlay(CAnimation *pAnim)
|
CMetaAnimBlend(EMetaAnimationType Type, IInputStream& rInput);
|
||||||
: IMetaAnimation(eMAT_Play), mpAnim(pAnim) {}
|
~CMetaAnimBlend();
|
||||||
|
virtual EMetaAnimationType Type() const;
|
||||||
|
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const;
|
||||||
|
|
||||||
inline CAnimation* GetPlayAnimation() const { return mpAnim; }
|
// Accessors
|
||||||
};
|
inline IMetaAnimation* BlendAnimationA() const { return mpMetaAnimA; }
|
||||||
|
inline IMetaAnimation* BlendAnimationB() const { return mpMetaAnimB; }
|
||||||
// CMetaAnimationBlend - blend between two animations
|
inline float UnknownA() const { return mUnknownA; }
|
||||||
class CMetaAnimationBlend : public IMetaAnimation
|
inline bool UnknownB() const { return mUnknownB; }
|
||||||
{
|
|
||||||
protected:
|
|
||||||
IMetaAnimation *mpAnimA;
|
|
||||||
IMetaAnimation *mpAnimB;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CMetaAnimationBlend(IMetaAnimation *pAnimA, IMetaAnimation *pAnimB)
|
|
||||||
: IMetaAnimation(eMAT_Blend), mpAnimA(pAnimA), mpAnimB(pAnimB) {}
|
|
||||||
|
|
||||||
~CMetaAnimationBlend()
|
|
||||||
{
|
|
||||||
delete mpAnimA;
|
|
||||||
delete mpAnimB;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline IMetaAnimation* BlendAnimationA() const { return mpAnimA; }
|
|
||||||
inline IMetaAnimation* BlendAnimationB() const { return mpAnimB; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// SAnimProbabilityPair - structure used by CMetaAnimationRandom to associate an animation with a probability value
|
// SAnimProbabilityPair - structure used by CMetaAnimationRandom to associate an animation with a probability value
|
||||||
@ -74,14 +110,30 @@ struct SAnimProbabilityPair
|
|||||||
u32 Probability;
|
u32 Probability;
|
||||||
};
|
};
|
||||||
|
|
||||||
// CMetaAnimationRandom - play random animation
|
// CMetaAnimRandom - play random animation
|
||||||
class CMetaAnimationRandom : public IMetaAnimation
|
class CMetaAnimRandom : public IMetaAnimation
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
std::vector<SAnimProbabilityPair> mProbabilityPairs;
|
std::vector<SAnimProbabilityPair> mProbabilityPairs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
CMetaAnimRandom(IInputStream& rInput);
|
||||||
|
~CMetaAnimRandom();
|
||||||
|
virtual EMetaAnimationType Type() const;
|
||||||
|
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// CMetaAnim - play a series of animations in sequence
|
||||||
|
class CMetaAnimSequence : public IMetaAnimation
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::vector<IMetaAnimation*> mAnimations;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CMetaAnimSequence(IInputStream& rInput);
|
||||||
|
~CMetaAnimSequence();
|
||||||
|
virtual EMetaAnimationType Type() const;
|
||||||
|
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // IMETAANIMATION
|
#endif // IMETAANIMATION
|
||||||
|
83
src/Core/Resource/Animation/IMetaTransition.cpp
Normal file
83
src/Core/Resource/Animation/IMetaTransition.cpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#include "IMetaTransition.h"
|
||||||
|
#include "IMetaAnimation.h"
|
||||||
|
|
||||||
|
// ************ CMetaTransFactory ************
|
||||||
|
CMetaTransFactory gMetaTransFactory;
|
||||||
|
|
||||||
|
IMetaTransition* CMetaTransFactory::LoadFromStream(IInputStream& rInput)
|
||||||
|
{
|
||||||
|
EMetaTransitionType Type = (EMetaTransitionType) rInput.ReadLong();
|
||||||
|
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case eMTT_MetaAnim:
|
||||||
|
return new CMetaTransMetaAnim(rInput);
|
||||||
|
|
||||||
|
case eMTT_Trans:
|
||||||
|
case eMTT_PhaseTrans:
|
||||||
|
return new CMetaTransTrans(Type, rInput);
|
||||||
|
|
||||||
|
case eMTT_Snap:
|
||||||
|
return new CMetaTransSnap(rInput);
|
||||||
|
|
||||||
|
default:
|
||||||
|
Log::Error("Unrecognized meta-transition type: " + TString::FromInt32(Type, 0, 10));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ CMetaTransMetaAnim ************
|
||||||
|
CMetaTransMetaAnim::CMetaTransMetaAnim(IInputStream& rInput)
|
||||||
|
{
|
||||||
|
mpAnim = gMetaAnimFactory.LoadFromStream(rInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
CMetaTransMetaAnim::~CMetaTransMetaAnim()
|
||||||
|
{
|
||||||
|
delete mpAnim;
|
||||||
|
}
|
||||||
|
|
||||||
|
EMetaTransitionType CMetaTransMetaAnim::Type() const
|
||||||
|
{
|
||||||
|
return eMTT_MetaAnim;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMetaTransMetaAnim::GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const
|
||||||
|
{
|
||||||
|
mpAnim->GetUniquePrimitives(rPrimSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ CMetaTransTrans ************
|
||||||
|
CMetaTransTrans::CMetaTransTrans(EMetaTransitionType Type, IInputStream& rInput)
|
||||||
|
{
|
||||||
|
ASSERT(Type == eMTT_Trans || Type == eMTT_PhaseTrans);
|
||||||
|
mType = Type;
|
||||||
|
mUnknownA = rInput.ReadFloat();
|
||||||
|
mUnknownB = rInput.ReadLong();
|
||||||
|
mUnknownC = rInput.ReadBool();
|
||||||
|
mUnknownD = rInput.ReadBool();
|
||||||
|
mUnknownE = rInput.ReadLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
EMetaTransitionType CMetaTransTrans::Type() const
|
||||||
|
{
|
||||||
|
return mType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMetaTransTrans::GetUniquePrimitives(std::set<CAnimPrimitive>&) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ CMetaTransSnap ************
|
||||||
|
CMetaTransSnap::CMetaTransSnap(IInputStream&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EMetaTransitionType CMetaTransSnap::Type() const
|
||||||
|
{
|
||||||
|
return eMTT_Snap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMetaTransSnap::GetUniquePrimitives(std::set<CAnimPrimitive>&) const
|
||||||
|
{
|
||||||
|
}
|
72
src/Core/Resource/Animation/IMetaTransition.h
Normal file
72
src/Core/Resource/Animation/IMetaTransition.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#ifndef IMETATRANSITION_H
|
||||||
|
#define IMETATRANSITION_H
|
||||||
|
|
||||||
|
#include "IMetaAnimation.h"
|
||||||
|
|
||||||
|
class IMetaAnimation;
|
||||||
|
class IMetaTransition;
|
||||||
|
|
||||||
|
enum EMetaTransitionType
|
||||||
|
{
|
||||||
|
eMTT_MetaAnim = 0,
|
||||||
|
eMTT_Trans = 1,
|
||||||
|
eMTT_PhaseTrans = 2, // note: structure shared with eMTT_Trans
|
||||||
|
eMTT_Snap = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
// Factory class
|
||||||
|
class CMetaTransFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class IMetaTransition* LoadFromStream(IInputStream& rInput);
|
||||||
|
};
|
||||||
|
extern CMetaTransFactory gMetaTransFactory;
|
||||||
|
|
||||||
|
// Base MetaTransition interface
|
||||||
|
class IMetaTransition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IMetaTransition() {}
|
||||||
|
virtual ~IMetaTransition() {}
|
||||||
|
virtual EMetaTransitionType Type() const = 0;
|
||||||
|
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// CMetaTransMetaAnim
|
||||||
|
class CMetaTransMetaAnim : public IMetaTransition
|
||||||
|
{
|
||||||
|
IMetaAnimation *mpAnim;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CMetaTransMetaAnim(IInputStream& rInput);
|
||||||
|
~CMetaTransMetaAnim();
|
||||||
|
virtual EMetaTransitionType Type() const;
|
||||||
|
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// CMetaTransTrans
|
||||||
|
class CMetaTransTrans : public IMetaTransition
|
||||||
|
{
|
||||||
|
EMetaTransitionType mType;
|
||||||
|
float mUnknownA;
|
||||||
|
u32 mUnknownB;
|
||||||
|
bool mUnknownC;
|
||||||
|
bool mUnknownD;
|
||||||
|
u32 mUnknownE;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CMetaTransTrans(EMetaTransitionType Type, IInputStream& rInput);
|
||||||
|
virtual EMetaTransitionType Type() const;
|
||||||
|
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// CMetaTransSnap
|
||||||
|
class CMetaTransSnap : public IMetaTransition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CMetaTransSnap(IInputStream& rInput);
|
||||||
|
virtual EMetaTransitionType Type() const;
|
||||||
|
virtual void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IMETATRANSITION_H
|
@ -33,7 +33,7 @@ CAnimSet* CAnimSetLoader::LoadReturnsCHAR(IInputStream& rCHAR)
|
|||||||
return pSet;
|
return pSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAnimSetLoader::LoadPASDatabase(IInputStream& rPAS4)
|
void CAnimSetLoader::LoadPASDatabase(IInputStream& rPAS4, SSetCharacter *pChar)
|
||||||
{
|
{
|
||||||
// For now, just parse the data; don't store it
|
// For now, just parse the data; don't store it
|
||||||
rPAS4.Seek(0x4, SEEK_CUR); // Skipping PAS4 FourCC
|
rPAS4.Seek(0x4, SEEK_CUR); // Skipping PAS4 FourCC
|
||||||
@ -68,128 +68,195 @@ void CAnimSetLoader::LoadPASDatabase(IInputStream& rPAS4)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (u32 iInfo = 0; iInfo < AnimInfoCount; iInfo++)
|
for (u32 iInfo = 0; iInfo < AnimInfoCount; iInfo++)
|
||||||
rPAS4.Seek(0x4 + Skip, SEEK_CUR);
|
{
|
||||||
|
u32 MetaAnimID = rPAS4.ReadLong();
|
||||||
|
rPAS4.Seek(Skip, SEEK_CUR);
|
||||||
|
pChar->UsedAnimationIndices.insert(MetaAnimID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAnimSetLoader::LoadAnimation(IInputStream& rANCS)
|
void CAnimSetLoader::LoadAnimationSet(IInputStream& rANCS)
|
||||||
{
|
{
|
||||||
TString Name = rANCS.ReadString();
|
u16 Version = rANCS.ReadShort();
|
||||||
Name = Name;
|
|
||||||
LoadMetaAnimation(rANCS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAnimSetLoader::LoadMetaAnimation(IInputStream& rANCS)
|
// Animations
|
||||||
{
|
|
||||||
u32 Type = rANCS.ReadLong();
|
|
||||||
|
|
||||||
switch (Type)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
LoadPrimitive(rANCS);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
case 2:
|
|
||||||
LoadBlend(rANCS);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
LoadRandom(rANCS);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
LoadSequence(rANCS);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAnimSetLoader::LoadPrimitive(IInputStream& rANCS)
|
|
||||||
{
|
|
||||||
u32 AnimID = rANCS.ReadLong();
|
|
||||||
u32 AnimIndex = rANCS.ReadLong();
|
|
||||||
TString AnimName = rANCS.ReadString();
|
|
||||||
rANCS.Seek(0x8, SEEK_CUR);
|
|
||||||
ASSERT(AnimIndex < mAnimPrimitives.size());
|
|
||||||
|
|
||||||
if (!mAnimPrimitives[AnimIndex].Loaded)
|
|
||||||
{
|
|
||||||
mAnimPrimitives[AnimIndex].Index = AnimIndex;
|
|
||||||
mAnimPrimitives[AnimIndex].AnimID = AnimID;
|
|
||||||
mAnimPrimitives[AnimIndex].Name = AnimName;
|
|
||||||
mAnimPrimitives[AnimIndex].Loaded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAnimSetLoader::LoadBlend(IInputStream& rANCS)
|
|
||||||
{
|
|
||||||
LoadMetaAnimation(rANCS);
|
|
||||||
LoadMetaAnimation(rANCS);
|
|
||||||
rANCS.Seek(0x5, SEEK_CUR);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAnimSetLoader::LoadRandom(IInputStream& rANCS)
|
|
||||||
{
|
|
||||||
u32 NumAnims = rANCS.ReadLong();
|
u32 NumAnims = rANCS.ReadLong();
|
||||||
|
pSet->mAnimations.reserve(NumAnims);
|
||||||
|
|
||||||
for (u32 iAnim = 0; iAnim < NumAnims; iAnim++)
|
for (u32 iAnim = 0; iAnim < NumAnims; iAnim++)
|
||||||
LoadAnimProbabilityPair(rANCS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAnimSetLoader::LoadAnimProbabilityPair(IInputStream& rANCS)
|
|
||||||
{
|
|
||||||
LoadMetaAnimation(rANCS);
|
|
||||||
rANCS.Seek(0x4, SEEK_CUR);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAnimSetLoader::LoadSequence(IInputStream& rANCS)
|
|
||||||
{
|
|
||||||
u32 NumAnims = rANCS.ReadLong();
|
|
||||||
|
|
||||||
for (u32 iAnim = 0; iAnim < NumAnims; iAnim++)
|
|
||||||
LoadMetaAnimation(rANCS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAnimSetLoader::LoadTransition(IInputStream& rANCS)
|
|
||||||
{
|
|
||||||
rANCS.Seek(0xC, SEEK_CUR);
|
|
||||||
LoadMetaTransition(rANCS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAnimSetLoader::LoadMetaTransition(IInputStream& rANCS)
|
|
||||||
{
|
|
||||||
u32 Type = rANCS.ReadLong();
|
|
||||||
|
|
||||||
switch (Type)
|
|
||||||
{
|
{
|
||||||
case 0:
|
SAnimation Anim;
|
||||||
LoadTransAnimation(rANCS);
|
Anim.Name = rANCS.ReadString();
|
||||||
break;
|
Anim.pMetaAnim = gMetaAnimFactory.LoadFromStream(rANCS);
|
||||||
case 1:
|
pSet->mAnimations.push_back(Anim);
|
||||||
case 2:
|
}
|
||||||
LoadTransTransition(rANCS);
|
|
||||||
break;
|
// Transitions
|
||||||
case 3:
|
u32 NumTransitions = rANCS.ReadLong();
|
||||||
break;
|
pSet->mTransitions.reserve(NumTransitions);
|
||||||
|
|
||||||
|
for (u32 iTrans = 0; iTrans < NumTransitions; iTrans++)
|
||||||
|
{
|
||||||
|
STransition Trans;
|
||||||
|
Trans.Unknown = rANCS.ReadLong();
|
||||||
|
Trans.AnimIdA = rANCS.ReadLong();
|
||||||
|
Trans.AnimIdB = rANCS.ReadLong();
|
||||||
|
Trans.pMetaTrans = gMetaTransFactory.LoadFromStream(rANCS);
|
||||||
|
pSet->mTransitions.push_back(Trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
pSet->mpDefaultTransition = gMetaTransFactory.LoadFromStream(rANCS);
|
||||||
|
|
||||||
|
// Additive Animations
|
||||||
|
u32 NumAdditive = rANCS.ReadLong();
|
||||||
|
pSet->mAdditiveAnims.reserve(NumAdditive);
|
||||||
|
|
||||||
|
for (u32 iAdd = 0; iAdd < NumAdditive; iAdd++)
|
||||||
|
{
|
||||||
|
SAdditiveAnim Anim;
|
||||||
|
Anim.AnimID = rANCS.ReadLong();
|
||||||
|
Anim.FadeInTime = rANCS.ReadFloat();
|
||||||
|
Anim.FadeOutTime = rANCS.ReadFloat();
|
||||||
|
pSet->mAdditiveAnims.push_back(Anim);
|
||||||
|
}
|
||||||
|
|
||||||
|
pSet->mDefaultAdditiveFadeIn = rANCS.ReadFloat();
|
||||||
|
pSet->mDefaultAdditiveFadeOut = rANCS.ReadFloat();
|
||||||
|
|
||||||
|
// Half Transitions
|
||||||
|
if (Version > 2)
|
||||||
|
{
|
||||||
|
u32 NumHalfTransitions = rANCS.ReadLong();
|
||||||
|
pSet->mHalfTransitions.reserve(NumHalfTransitions);
|
||||||
|
|
||||||
|
for (u32 iTrans = 0; iTrans < NumHalfTransitions; iTrans++)
|
||||||
|
{
|
||||||
|
SHalfTransition Trans;
|
||||||
|
Trans.AnimID = rANCS.ReadLong();
|
||||||
|
Trans.pMetaTrans = gMetaTransFactory.LoadFromStream(rANCS);
|
||||||
|
pSet->mHalfTransitions.push_back(Trans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skipping MP1 ANIM asset list
|
||||||
|
// Events
|
||||||
|
if (mVersion >= eEchoesDemo)
|
||||||
|
{
|
||||||
|
u32 EventDataCount = rANCS.ReadLong();
|
||||||
|
pSet->mAnimEvents.reserve(EventDataCount);
|
||||||
|
ASSERT(EventDataCount == NumAnims);
|
||||||
|
|
||||||
|
for (u32 iEvent = 0; iEvent < EventDataCount; iEvent++)
|
||||||
|
{
|
||||||
|
CAnimEventData *pData = CAnimEventLoader::LoadAnimSetEvents(rANCS);
|
||||||
|
pSet->mAnimEvents.push_back(pData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAnimSetLoader::LoadTransAnimation(IInputStream& rANCS)
|
void CAnimSetLoader::ProcessPrimitives()
|
||||||
{
|
{
|
||||||
LoadMetaAnimation(rANCS);
|
// Find all unique anim primitives
|
||||||
}
|
std::set<CAnimPrimitive> UniquePrimitives;
|
||||||
|
|
||||||
void CAnimSetLoader::LoadTransTransition(IInputStream& rANCS)
|
for (u32 iAnim = 0; iAnim < pSet->mAnimations.size(); iAnim++)
|
||||||
{
|
pSet->mAnimations[iAnim].pMetaAnim->GetUniquePrimitives(UniquePrimitives);
|
||||||
rANCS.Seek(0xE, SEEK_CUR);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAnimSetLoader::LoadAdditiveAnimation(IInputStream& rANCS)
|
for (u32 iTrans = 0; iTrans < pSet->mTransitions.size(); iTrans++)
|
||||||
{
|
pSet->mTransitions[iTrans].pMetaTrans->GetUniquePrimitives(UniquePrimitives);
|
||||||
rANCS.Seek(0xC, SEEK_CUR);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAnimSetLoader::LoadHalfTransition(IInputStream& rANCS)
|
pSet->mpDefaultTransition->GetUniquePrimitives(UniquePrimitives);
|
||||||
{
|
|
||||||
rANCS.Seek(0x4, SEEK_CUR);
|
for (u32 iTrans = 0; iTrans < pSet->mHalfTransitions.size(); iTrans++)
|
||||||
LoadMetaTransition(rANCS);
|
pSet->mHalfTransitions[iTrans].pMetaTrans->GetUniquePrimitives(UniquePrimitives);
|
||||||
|
|
||||||
|
// Copy anim primitives into the animset
|
||||||
|
for (auto Iter = UniquePrimitives.begin(); Iter != UniquePrimitives.end(); Iter++)
|
||||||
|
{
|
||||||
|
const CAnimPrimitive& rkPrim = *Iter;
|
||||||
|
u32 ID = rkPrim.ID();
|
||||||
|
|
||||||
|
if (ID >= pSet->mAnimPrimitives.size())
|
||||||
|
pSet->mAnimPrimitives.resize(ID + 1);
|
||||||
|
|
||||||
|
pSet->mAnimPrimitives[ID] = rkPrim;
|
||||||
|
ASSERT(pSet->Animation(ID)->pMetaAnim->Type() == eMAT_Play);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add animations referenced by default transition
|
||||||
|
std::set<CAnimPrimitive> DefaultTransPrimitives;
|
||||||
|
pSet->mpDefaultTransition->GetUniquePrimitives(DefaultTransPrimitives);
|
||||||
|
|
||||||
|
for (u32 iChar = 0; iChar < pSet->mCharacters.size(); iChar++)
|
||||||
|
{
|
||||||
|
SSetCharacter& rChar = pSet->mCharacters[iChar];
|
||||||
|
|
||||||
|
for (auto Iter = DefaultTransPrimitives.begin(); Iter != DefaultTransPrimitives.end(); Iter++)
|
||||||
|
{
|
||||||
|
const CAnimPrimitive& rkPrim = *Iter;
|
||||||
|
rChar.UsedAnimationIndices.insert(rkPrim.ID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add animations referenced by used transitions
|
||||||
|
for (u32 iChar = 0; iChar < pSet->mCharacters.size(); iChar++)
|
||||||
|
{
|
||||||
|
SSetCharacter& rChar = pSet->mCharacters[iChar];
|
||||||
|
bool AddedNewAnims = true;
|
||||||
|
|
||||||
|
// Loop this until we run out of new animations. This is in case any animations
|
||||||
|
// referenced by any transitions are also referenced by earlier transitions.
|
||||||
|
while (AddedNewAnims)
|
||||||
|
{
|
||||||
|
AddedNewAnims = false;
|
||||||
|
|
||||||
|
for (u32 iTrans = 0; iTrans < pSet->mTransitions.size(); iTrans++)
|
||||||
|
{
|
||||||
|
STransition& rTrans = pSet->mTransitions[iTrans];
|
||||||
|
|
||||||
|
if ( rChar.UsedAnimationIndices.find(rTrans.AnimIdA) != rChar.UsedAnimationIndices.end() &&
|
||||||
|
rChar.UsedAnimationIndices.find(rTrans.AnimIdB) != rChar.UsedAnimationIndices.end() )
|
||||||
|
{
|
||||||
|
std::set<CAnimPrimitive> Primitives;
|
||||||
|
rTrans.pMetaTrans->GetUniquePrimitives(Primitives);
|
||||||
|
|
||||||
|
for (auto Iter = Primitives.begin(); Iter != Primitives.end(); Iter++)
|
||||||
|
{
|
||||||
|
const CAnimPrimitive& rkPrim = *Iter;
|
||||||
|
|
||||||
|
if (rChar.UsedAnimationIndices.find(rkPrim.ID()) == rChar.UsedAnimationIndices.end())
|
||||||
|
{
|
||||||
|
rChar.UsedAnimationIndices.insert(rkPrim.ID());
|
||||||
|
AddedNewAnims = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 iHalf = 0; iHalf < pSet->mHalfTransitions.size(); iHalf++)
|
||||||
|
{
|
||||||
|
SHalfTransition& rTrans = pSet->mHalfTransitions[iHalf];
|
||||||
|
|
||||||
|
if (rChar.UsedAnimationIndices.find(rTrans.AnimID) != rChar.UsedAnimationIndices.end())
|
||||||
|
{
|
||||||
|
std::set<CAnimPrimitive> Primitives;
|
||||||
|
rTrans.pMetaTrans->GetUniquePrimitives(Primitives);
|
||||||
|
|
||||||
|
for (auto Iter = Primitives.begin(); Iter != Primitives.end(); Iter++)
|
||||||
|
{
|
||||||
|
const CAnimPrimitive& rkPrim = *Iter;
|
||||||
|
|
||||||
|
if (rChar.UsedAnimationIndices.find(rkPrim.ID()) == rChar.UsedAnimationIndices.end())
|
||||||
|
{
|
||||||
|
rChar.UsedAnimationIndices.insert(rkPrim.ID());
|
||||||
|
AddedNewAnims = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ STATIC ************
|
// ************ STATIC ************
|
||||||
@ -254,7 +321,7 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PAS Database
|
// PAS Database
|
||||||
Loader.LoadPASDatabase(rANCS);
|
Loader.LoadPASDatabase(rANCS, pChar);
|
||||||
|
|
||||||
// Particles
|
// Particles
|
||||||
u32 ParticleCount = rANCS.ReadLong();
|
u32 ParticleCount = rANCS.ReadLong();
|
||||||
@ -334,61 +401,8 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load Animation Set
|
// Load Animation Set
|
||||||
u32 SetStart = rANCS.Tell();
|
Loader.LoadAnimationSet(rANCS);
|
||||||
SetStart = SetStart;
|
Loader.ProcessPrimitives();
|
||||||
u16 InfoCount = rANCS.ReadShort();
|
|
||||||
u32 NumAnims = rANCS.ReadLong();
|
|
||||||
Loader.mAnimPrimitives.resize(NumAnims);
|
|
||||||
|
|
||||||
for (u32 iAnim = 0; iAnim < NumAnims; iAnim++)
|
|
||||||
Loader.LoadAnimation(rANCS);
|
|
||||||
|
|
||||||
u32 NumTransitions = rANCS.ReadLong();
|
|
||||||
|
|
||||||
for (u32 iTrans = 0; iTrans < NumTransitions; iTrans++)
|
|
||||||
Loader.LoadTransition(rANCS);
|
|
||||||
Loader.LoadMetaTransition(rANCS);
|
|
||||||
|
|
||||||
u32 NumAdditiveAnims = rANCS.ReadLong();
|
|
||||||
|
|
||||||
for (u32 iAnim = 0; iAnim < NumAdditiveAnims; iAnim++)
|
|
||||||
Loader.LoadAdditiveAnimation(rANCS);
|
|
||||||
|
|
||||||
rANCS.Seek(0x8, SEEK_CUR);
|
|
||||||
|
|
||||||
if (InfoCount > 2)
|
|
||||||
{
|
|
||||||
u32 NumHalfTransitions = rANCS.ReadLong();
|
|
||||||
|
|
||||||
for (u32 iHalf = 0; iHalf < NumHalfTransitions; iHalf++)
|
|
||||||
Loader.LoadHalfTransition(rANCS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
{
|
|
||||||
SSetAnimation Anim;
|
|
||||||
Anim.Name = rPrim.Name;
|
|
||||||
Anim.pAnim = gpResourceStore->LoadResource(rPrim.AnimID, "ANIM");
|
|
||||||
Loader.pSet->mAnimations[iPrim] = Anim;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse anim event data
|
|
||||||
if (Loader.pSet->Game() >= eEchoesDemo)
|
|
||||||
{
|
|
||||||
u32 EventDataCount = rANCS.ReadLong();
|
|
||||||
ASSERT(EventDataCount == NumAnims);
|
|
||||||
|
|
||||||
for (u32 iEvnt = 0; iEvnt < EventDataCount; iEvnt++)
|
|
||||||
Loader.pSet->mAnimations[iEvnt].pEventData = CAnimEventLoader::LoadAnimSetEvents(rANCS);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Loader.pSet;
|
return Loader.pSet;
|
||||||
}
|
}
|
||||||
|
@ -12,33 +12,10 @@ class CAnimSetLoader
|
|||||||
CAnimSetLoader();
|
CAnimSetLoader();
|
||||||
CAnimSet* LoadCorruptionCHAR(IInputStream& rCHAR);
|
CAnimSet* LoadCorruptionCHAR(IInputStream& rCHAR);
|
||||||
CAnimSet* LoadReturnsCHAR(IInputStream& rCHAR);
|
CAnimSet* LoadReturnsCHAR(IInputStream& rCHAR);
|
||||||
void LoadPASDatabase(IInputStream& rPAS4);
|
void LoadPASDatabase(IInputStream& rPAS4, SSetCharacter *pChar);
|
||||||
|
|
||||||
// Animation Set load functions
|
void LoadAnimationSet(IInputStream& rANCS);
|
||||||
struct SPrimitive
|
void ProcessPrimitives();
|
||||||
{
|
|
||||||
u32 Index;
|
|
||||||
u32 AnimID;
|
|
||||||
TString Name;
|
|
||||||
bool Loaded;
|
|
||||||
|
|
||||||
SPrimitive() : Loaded(false) {}
|
|
||||||
};
|
|
||||||
std::vector<SPrimitive> mAnimPrimitives;
|
|
||||||
|
|
||||||
void LoadAnimation(IInputStream& rANCS);
|
|
||||||
void LoadMetaAnimation(IInputStream& rANCS);
|
|
||||||
void LoadPrimitive(IInputStream& rANCS);
|
|
||||||
void LoadBlend(IInputStream& rANCS);
|
|
||||||
void LoadRandom(IInputStream& rANCS);
|
|
||||||
void LoadAnimProbabilityPair(IInputStream& rANCS);
|
|
||||||
void LoadSequence(IInputStream& rANCS);
|
|
||||||
void LoadTransition(IInputStream& rANCS);
|
|
||||||
void LoadMetaTransition(IInputStream& rANCS);
|
|
||||||
void LoadTransAnimation(IInputStream& rANCS);
|
|
||||||
void LoadTransTransition(IInputStream& rANCS);
|
|
||||||
void LoadAdditiveAnimation(IInputStream& rANCS);
|
|
||||||
void LoadHalfTransition(IInputStream& rANCS);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static CAnimSet* LoadANCSOrCHAR(IInputStream& rFile, CResourceEntry *pEntry);
|
static CAnimSet* LoadANCSOrCHAR(IInputStream& rFile, CResourceEntry *pEntry);
|
||||||
|
@ -202,7 +202,7 @@ void CAnimationLoader::ReadUncompressedANIM()
|
|||||||
|
|
||||||
if (mGame == ePrime)
|
if (mGame == ePrime)
|
||||||
{
|
{
|
||||||
mpAnim->mEventData = mpInput->ReadLong();
|
mpAnim->mpEventData = gpResourceStore->LoadResource(mpInput->ReadLong(), "EVNT");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ void CAnimationLoader::ReadCompressedANIM()
|
|||||||
|
|
||||||
if (mGame == ePrime)
|
if (mGame == ePrime)
|
||||||
{
|
{
|
||||||
mpAnim->mEventData = mpInput->ReadLong();
|
mpAnim->mpEventData = gpResourceStore->LoadResource(mpInput->ReadLong(), "EVNT");
|
||||||
mpInput->Seek(0x4, SEEK_CUR); // Skip unknown
|
mpInput->Seek(0x4, SEEK_CUR); // Skip unknown
|
||||||
}
|
}
|
||||||
else mpInput->Seek(0x2, SEEK_CUR); // Skip unknowns
|
else mpInput->Seek(0x2, SEEK_CUR); // Skip unknowns
|
||||||
|
@ -33,7 +33,7 @@ public:
|
|||||||
inline CAnimSet* Character() const { return mpCharacter; }
|
inline CAnimSet* Character() const { return mpCharacter; }
|
||||||
inline u32 ActiveCharIndex() const { return mActiveCharSet; }
|
inline u32 ActiveCharIndex() const { return mActiveCharSet; }
|
||||||
inline u32 ActiveAnimIndex() const { return mActiveAnim; }
|
inline u32 ActiveAnimIndex() const { return mActiveAnim; }
|
||||||
inline CAnimation* CurrentAnim() const { return (mAnimated && mpCharacter ? mpCharacter->Animation(mActiveAnim)->pAnim : nullptr); }
|
inline CAnimation* CurrentAnim() const { return (mAnimated && mpCharacter ? mpCharacter->FindAnimationAsset(mActiveAnim) : nullptr); }
|
||||||
inline bool IsAnimated() const { return (mAnimated && CurrentAnim() != nullptr); }
|
inline bool IsAnimated() const { return (mAnimated && CurrentAnim() != nullptr); }
|
||||||
|
|
||||||
void SetAnimated(bool Animated) { mAnimated = Animated; SetDirty(); }
|
void SetAnimated(bool Animated) { mAnimated = Animated; SetDirty(); }
|
||||||
|
@ -679,8 +679,7 @@ CSkeleton* CScriptNode::ActiveSkeleton() const
|
|||||||
CAnimation* CScriptNode::ActiveAnimation() const
|
CAnimation* CScriptNode::ActiveAnimation() const
|
||||||
{
|
{
|
||||||
CAnimSet *pSet = ActiveAnimSet();
|
CAnimSet *pSet = ActiveAnimSet();
|
||||||
if (pSet) return pSet->Animation(mAnimIndex)->pAnim;
|
return pSet ? pSet->FindAnimationAsset(mAnimIndex) : nullptr;
|
||||||
else return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CTexture* CScriptNode::ActiveBillboard() const
|
CTexture* CScriptNode::ActiveBillboard() const
|
||||||
|
@ -160,18 +160,12 @@ void CCharacterEditor::UpdateCameraOrbit()
|
|||||||
|
|
||||||
CSkeleton* CCharacterEditor::CurrentSkeleton() const
|
CSkeleton* CCharacterEditor::CurrentSkeleton() const
|
||||||
{
|
{
|
||||||
if (mpSet)
|
return mpSet ? mpSet->Character(mCurrentChar)->pSkeleton : nullptr;
|
||||||
return mpSet->Character(mCurrentChar)->pSkeleton;
|
|
||||||
else
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CAnimation* CCharacterEditor::CurrentAnimation() const
|
CAnimation* CCharacterEditor::CurrentAnimation() const
|
||||||
{
|
{
|
||||||
if (mpSet)
|
return mpSet ? mpSet->FindAnimationAsset(mCurrentAnim) : nullptr;
|
||||||
return mpSet->Animation(mCurrentAnim)->pAnim;
|
|
||||||
else
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCharacterEditor::SetActiveAnimSet(CAnimSet *pSet)
|
void CCharacterEditor::SetActiveAnimSet(CAnimSet *pSet)
|
||||||
@ -385,7 +379,7 @@ void CCharacterEditor::SetAnimTime(float Time)
|
|||||||
|
|
||||||
mpCharNode->SetAnimTime(Time);
|
mpCharNode->SetAnimTime(Time);
|
||||||
|
|
||||||
CAnimation *pAnim = (mpSet ? mpSet->Animation(mCurrentAnim)->pAnim : nullptr);
|
CAnimation *pAnim = CurrentAnimation();
|
||||||
u32 NumKeys = 1, CurKey = 0;
|
u32 NumKeys = 1, CurKey = 0;
|
||||||
|
|
||||||
if (pAnim)
|
if (pAnim)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user