Added support for CHAR, SAND, and SCAN dependencies in MP3
This commit is contained in:
parent
11ccd23baf
commit
88c11555c0
|
@ -228,8 +228,8 @@ HEADERS += \
|
|||
Resource/CResTypeInfo.h \
|
||||
Resource/Cooker/CResourceCooker.h \
|
||||
Resource/CAudioMacro.h \
|
||||
Resource/Animation/CCharacter.h \
|
||||
CompressionUtil.h
|
||||
CompressionUtil.h \
|
||||
Resource/Animation/CSourceAnimData.h
|
||||
|
||||
# Source Files
|
||||
SOURCES += \
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "Core/Resource/CFont.h"
|
||||
#include "Core/Resource/CScan.h"
|
||||
#include "Core/Resource/CWorld.h"
|
||||
#include "Core/Resource/Animation/CAnimSet.h"
|
||||
#include "Core/Resource/Script/CScriptLayer.h"
|
||||
#include <Math/MathUtil.h>
|
||||
|
||||
|
@ -398,19 +399,44 @@ void GenerateAssetNames(CGameProject *pProj)
|
|||
if (pkChar->pSkeleton) ApplyGeneratedName(pkChar->pSkeleton->Entry(), SetDir, CharName);
|
||||
if (pkChar->pSkin) ApplyGeneratedName(pkChar->pSkin->Entry(), SetDir, CharName);
|
||||
|
||||
if (pkChar->IceModel.IsValid() || pkChar->IceSkin.IsValid())
|
||||
if (pProj->Game() >= eCorruptionProto && pProj->Game() <= eCorruption && pkChar->ID == 0)
|
||||
{
|
||||
TWideString IceName = TWideString::Format(L"%s_frozen", *CharName);
|
||||
CResourceEntry *pAnimDataEntry = gpResourceStore->FindEntry( pkChar->AnimDataID );
|
||||
|
||||
if (pkChar->IceModel.IsValid())
|
||||
if (pAnimDataEntry)
|
||||
{
|
||||
CResourceEntry *pIceModelEntry = pStore->FindEntry(pkChar->IceModel);
|
||||
ApplyGeneratedName(pIceModelEntry, SetDir, IceName);
|
||||
TWideString AnimDataName = TString::Format(L"%s_animdata", *CharName);
|
||||
ApplyGeneratedName(pAnimDataEntry, SetDir, AnimDataName);
|
||||
}
|
||||
if (pkChar->IceSkin.IsValid())
|
||||
}
|
||||
|
||||
for (u32 iOverlay = 0; iOverlay < pkChar->OverlayModels.size(); iOverlay++)
|
||||
{
|
||||
const SOverlayModel& rkOverlay = pkChar->OverlayModels[iOverlay];
|
||||
|
||||
if (rkOverlay.ModelID.IsValid() || rkOverlay.SkinID.IsValid())
|
||||
{
|
||||
CResourceEntry *pIceSkinEntry = pStore->FindEntry(pkChar->IceSkin);
|
||||
ApplyGeneratedName(pIceSkinEntry, SetDir, IceName);
|
||||
TWideString TypeName = (
|
||||
rkOverlay.Type == eOT_Frozen ? L"frozen" :
|
||||
rkOverlay.Type == eOT_Acid ? L"acid" :
|
||||
rkOverlay.Type == eOT_Hypermode ? L"hypermode" :
|
||||
rkOverlay.Type == eOT_XRay ? L"xray" :
|
||||
L""
|
||||
);
|
||||
ASSERT(TypeName != L"");
|
||||
|
||||
TWideString OverlayName = TWideString::Format(L"%s_%s", *CharName, *TypeName);
|
||||
|
||||
if (rkOverlay.ModelID.IsValid())
|
||||
{
|
||||
CResourceEntry *pModelEntry = pStore->FindEntry(rkOverlay.ModelID);
|
||||
ApplyGeneratedName(pModelEntry, SetDir, OverlayName);
|
||||
}
|
||||
if (rkOverlay.SkinID.IsValid())
|
||||
{
|
||||
CResourceEntry *pSkinEntry = pStore->FindEntry(rkOverlay.SkinID);
|
||||
ApplyGeneratedName(pSkinEntry, SetDir, OverlayName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "CDependencyTree.h"
|
||||
#include "Core/GameProject/CGameProject.h"
|
||||
#include "Core/Resource/Animation/CAnimSet.h"
|
||||
#include "Core/Resource/Script/CMasterTemplate.h"
|
||||
#include "Core/Resource/Script/CScriptLayer.h"
|
||||
#include "Core/Resource/Script/CScriptObject.h"
|
||||
|
@ -199,34 +200,35 @@ void CSetCharacterDependency::Serialize(IArchive& rArc)
|
|||
<< SERIAL_ABSTRACT_CONTAINER("Children", mChildren, "Child", &gDependencyNodeFactory);
|
||||
}
|
||||
|
||||
CSetCharacterDependency* CSetCharacterDependency::BuildTree(const CAnimSet *pkOwnerSet, u32 CharIndex)
|
||||
CSetCharacterDependency* CSetCharacterDependency::BuildTree(const SSetCharacter& rkChar)
|
||||
{
|
||||
CSetCharacterDependency *pTree = new CSetCharacterDependency(CharIndex);
|
||||
const SSetCharacter *pkChar = pkOwnerSet->Character(CharIndex);
|
||||
CSetCharacterDependency *pTree = new CSetCharacterDependency(rkChar.ID);
|
||||
pTree->AddDependency(rkChar.pModel);
|
||||
pTree->AddDependency(rkChar.pSkeleton);
|
||||
pTree->AddDependency(rkChar.pSkin);
|
||||
pTree->AddDependency(rkChar.AnimDataID);
|
||||
|
||||
if (pkChar)
|
||||
const std::vector<CAssetID> *pkParticleVectors[5] = {
|
||||
&rkChar.GenericParticles, &rkChar.ElectricParticles,
|
||||
&rkChar.SwooshParticles, &rkChar.SpawnParticles,
|
||||
&rkChar.EffectParticles
|
||||
};
|
||||
|
||||
for (u32 iVec = 0; iVec < 5; iVec++)
|
||||
{
|
||||
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);
|
||||
pTree->AddDependency(pkChar->SpatialPrimitives);
|
||||
for (u32 iPart = 0; iPart < pkParticleVectors[iVec]->size(); iPart++)
|
||||
pTree->AddDependency(pkParticleVectors[iVec]->at(iPart));
|
||||
}
|
||||
|
||||
for (u32 iOverlay = 0; iOverlay < rkChar.OverlayModels.size(); iOverlay++)
|
||||
{
|
||||
const SOverlayModel& rkOverlay = rkChar.OverlayModels[iOverlay];
|
||||
pTree->AddDependency(rkOverlay.ModelID);
|
||||
pTree->AddDependency(rkOverlay.SkinID);
|
||||
}
|
||||
|
||||
pTree->AddDependency(rkChar.SpatialPrimitives);
|
||||
|
||||
return pTree;
|
||||
}
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ public:
|
|||
inline u32 CharSetIndex() const { return mCharSetIndex; }
|
||||
|
||||
// Static
|
||||
static CSetCharacterDependency* BuildTree(const CAnimSet *pkOwnerSet, u32 CharIndex);
|
||||
static CSetCharacterDependency* BuildTree(const SSetCharacter& rkChar);
|
||||
};
|
||||
|
||||
// Node representing a character animation. Indicates which character indices use this animation.
|
||||
|
|
|
@ -154,12 +154,9 @@ void CCharacterUsageMap::ParseDependencyNode(IDependencyNode *pNode)
|
|||
CResourceDependency *pDep = static_cast<CResourceDependency*>(pNode);
|
||||
CResourceEntry *pEntry = mpStore->FindEntry(pDep->ID());
|
||||
|
||||
if (pEntry)
|
||||
if (pEntry && pEntry->ResourceType() == eScan)
|
||||
{
|
||||
EResType ResType = pEntry->ResourceType();
|
||||
|
||||
if (ResType == eScan)
|
||||
ParseDependencyNode(pEntry->Dependencies());
|
||||
ParseDependencyNode(pEntry->Dependencies());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -144,8 +144,8 @@ void CRenderer::RenderBuckets(const SViewInfo& rkViewInfo)
|
|||
|
||||
void CRenderer::RenderBloom()
|
||||
{
|
||||
// Check to ensure bloom is enabled
|
||||
if (mBloomMode == eNoBloom) return;
|
||||
// Check to ensure bloom is enabled. Also don't render bloom in unlit mode.
|
||||
if (mBloomMode == eNoBloom || CGraphics::sLightMode != CGraphics::eWorldLighting) return;
|
||||
|
||||
// Setup
|
||||
static const float skHOffset[6] = { -0.008595f, -0.005470f, -0.002345f,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ************
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -351,6 +351,7 @@ void CResTypeInfo::CResTypeInfoFactory::InitTypes()
|
|||
CResTypeInfo *pType = new CResTypeInfo(eSourceAnimData, "Source Animation Data");
|
||||
AddExtension(pType, "SAND", eCorruptionProto, eCorruption);
|
||||
pType->mHidden = true;
|
||||
pType->mCanHaveDependencies = false; // all dependencies are added to the CHAR dependency tree
|
||||
}
|
||||
{
|
||||
CResTypeInfo *pType = new CResTypeInfo(eSpatialPrimitive, "Spatial Primitive");
|
||||
|
|
|
@ -52,6 +52,9 @@ private:
|
|||
CAnimationParameters mUnknownAnimParams;
|
||||
std::vector<SScanInfoSecondaryModel> mSecondaryModels;
|
||||
|
||||
// MP3
|
||||
std::vector<CAssetID> mDependencyList;
|
||||
|
||||
public:
|
||||
CScan(CResourceEntry *pEntry = 0)
|
||||
: CResource(pEntry)
|
||||
|
@ -63,12 +66,20 @@ public:
|
|||
|
||||
CDependencyTree* BuildDependencyTree() const
|
||||
{
|
||||
// note: not handling Corruption yet
|
||||
if (Game() >= eCorruptionProto)
|
||||
Log::Warning("CScan::BuildDependencyTree not handling Corruption dependencies");
|
||||
|
||||
CDependencyTree *pTree = new CDependencyTree();
|
||||
|
||||
// Corruption's SCAN has a list of all assets - just grab that
|
||||
if (Game() >= eCorruptionProto)
|
||||
{
|
||||
for (u32 iDep = 0; iDep < mDependencyList.size(); iDep++)
|
||||
{
|
||||
pTree->AddDependency(mDependencyList[iDep]);
|
||||
}
|
||||
|
||||
return pTree;
|
||||
}
|
||||
|
||||
// Otherwise add all the dependencies we need from the properties
|
||||
if (Game() <= ePrime)
|
||||
pTree->AddDependency(mFrameID);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "Core/CAudioManager.h"
|
||||
#include "Core/GameProject/CGameProject.h"
|
||||
|
||||
void CAnimEventLoader::LoadEvents(IInputStream& rEVNT, bool IsEchoes)
|
||||
void CAnimEventLoader::LoadEvents(IInputStream& rEVNT)
|
||||
{
|
||||
u32 Version = rEVNT.ReadLong();
|
||||
ASSERT(Version == 1 || Version == 2);
|
||||
|
@ -12,9 +12,7 @@ void CAnimEventLoader::LoadEvents(IInputStream& rEVNT, bool IsEchoes)
|
|||
|
||||
for (u32 iLoop = 0; iLoop < NumLoopEvents; iLoop++)
|
||||
{
|
||||
rEVNT.Seek(0x2, SEEK_CUR);
|
||||
rEVNT.ReadString();
|
||||
rEVNT.Seek(0x1C, SEEK_CUR);
|
||||
LoadLoopEvent(rEVNT);
|
||||
}
|
||||
|
||||
// User Events
|
||||
|
@ -22,10 +20,7 @@ void CAnimEventLoader::LoadEvents(IInputStream& rEVNT, bool IsEchoes)
|
|||
|
||||
for (u32 iUser = 0; iUser < NumUserEvents; iUser++)
|
||||
{
|
||||
rEVNT.Seek(0x2, SEEK_CUR);
|
||||
rEVNT.ReadString();
|
||||
rEVNT.Seek(0x1F, SEEK_CUR);
|
||||
rEVNT.ReadString();
|
||||
LoadUserEvent(rEVNT);
|
||||
}
|
||||
|
||||
// Effect Events
|
||||
|
@ -33,20 +28,7 @@ void CAnimEventLoader::LoadEvents(IInputStream& rEVNT, bool IsEchoes)
|
|||
|
||||
for (u32 iFX = 0; iFX < NumEffectEvents; iFX++)
|
||||
{
|
||||
rEVNT.Seek(0x2, SEEK_CUR);
|
||||
rEVNT.ReadString();
|
||||
rEVNT.Seek(0x13, SEEK_CUR);
|
||||
u32 CharIndex = rEVNT.ReadLong();
|
||||
rEVNT.Seek(0xC, SEEK_CUR);
|
||||
CAssetID ParticleID = rEVNT.ReadLong();
|
||||
mpEventData->AddEvent(CharIndex, ParticleID);
|
||||
|
||||
if (IsEchoes)
|
||||
rEVNT.Seek(0x4, SEEK_CUR);
|
||||
else
|
||||
rEVNT.ReadString();
|
||||
|
||||
rEVNT.Seek(0x8, SEEK_CUR);
|
||||
LoadEffectEvent(rEVNT);
|
||||
}
|
||||
|
||||
// Sound Events
|
||||
|
@ -56,21 +38,92 @@ void CAnimEventLoader::LoadEvents(IInputStream& rEVNT, bool IsEchoes)
|
|||
|
||||
for (u32 iSound = 0; iSound < NumSoundEvents; iSound++)
|
||||
{
|
||||
rEVNT.Seek(0x2, SEEK_CUR);
|
||||
rEVNT.ReadString();
|
||||
rEVNT.Seek(0x13, SEEK_CUR);
|
||||
u32 CharIndex = rEVNT.ReadLong();
|
||||
rEVNT.Seek(0x4, SEEK_CUR);
|
||||
u32 SoundID = rEVNT.ReadLong() & 0xFFFF;
|
||||
rEVNT.Seek(0x8, SEEK_CUR);
|
||||
if (IsEchoes) rEVNT.Seek(0xC, SEEK_CUR);
|
||||
LoadSoundEvent(rEVNT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SoundID != 0xFFFF)
|
||||
s32 CAnimEventLoader::LoadEventBase(IInputStream& rEVNT)
|
||||
{
|
||||
rEVNT.Skip(0x2);
|
||||
rEVNT.ReadString();
|
||||
rEVNT.Skip(mGame < eCorruptionProto ? 0x13 : 0x17);
|
||||
s32 CharacterIndex = rEVNT.ReadLong();
|
||||
rEVNT.Skip(mGame < eCorruptionProto ? 0x4 : 0x18);
|
||||
return CharacterIndex;
|
||||
}
|
||||
|
||||
void CAnimEventLoader::LoadLoopEvent(IInputStream& rEVNT)
|
||||
{
|
||||
LoadEventBase(rEVNT);
|
||||
rEVNT.Skip(0x1);
|
||||
}
|
||||
|
||||
void CAnimEventLoader::LoadUserEvent(IInputStream& rEVNT)
|
||||
{
|
||||
LoadEventBase(rEVNT);
|
||||
rEVNT.Skip(0x4);
|
||||
rEVNT.ReadString();
|
||||
}
|
||||
|
||||
void CAnimEventLoader::LoadEffectEvent(IInputStream& rEVNT)
|
||||
{
|
||||
s32 CharIndex = LoadEventBase(rEVNT);
|
||||
rEVNT.Skip(mGame < eCorruptionProto ? 0x8 : 0x4);
|
||||
CAssetID ParticleID(rEVNT, mGame);
|
||||
mpEventData->AddEvent(CharIndex, ParticleID);
|
||||
|
||||
if (mGame <= ePrime)
|
||||
rEVNT.ReadString();
|
||||
else if (mGame <= eEchoes)
|
||||
rEVNT.Skip(0x4);
|
||||
|
||||
rEVNT.Skip(0x8);
|
||||
}
|
||||
|
||||
void CAnimEventLoader::LoadSoundEvent(IInputStream& rEVNT)
|
||||
{
|
||||
s32 CharIndex = LoadEventBase(rEVNT);
|
||||
|
||||
// Metroid Prime 1/2
|
||||
if (mGame <= eEchoes)
|
||||
{
|
||||
u32 SoundID = rEVNT.ReadLong() & 0xFFFF;
|
||||
rEVNT.Skip(0x8);
|
||||
if (mGame >= eEchoes) rEVNT.Skip(0xC);
|
||||
|
||||
if (SoundID != 0xFFFF)
|
||||
{
|
||||
SSoundInfo SoundInfo = gpResourceStore->Project()->AudioManager()->GetSoundInfo(SoundID);
|
||||
|
||||
if (SoundInfo.pAudioGroup)
|
||||
mpEventData->AddEvent(CharIndex, SoundInfo.pAudioGroup->ID());
|
||||
}
|
||||
}
|
||||
|
||||
// Metroid Prime 3
|
||||
else
|
||||
{
|
||||
CAssetID SoundID(rEVNT, mGame);
|
||||
mpEventData->AddEvent(CharIndex, SoundID);
|
||||
rEVNT.Skip(0x8);
|
||||
|
||||
for (u32 StructIdx = 0; StructIdx < 2; StructIdx++)
|
||||
{
|
||||
u32 StructType = rEVNT.ReadLong();
|
||||
ASSERT(StructType <= 2);
|
||||
|
||||
if (StructType == 1)
|
||||
{
|
||||
SSoundInfo SoundInfo = gpResourceStore->Project()->AudioManager()->GetSoundInfo(SoundID);
|
||||
|
||||
if (SoundInfo.pAudioGroup)
|
||||
mpEventData->AddEvent(CharIndex, SoundInfo.pAudioGroup->ID());
|
||||
rEVNT.Skip(4);
|
||||
}
|
||||
else if (StructType == 2)
|
||||
{
|
||||
// This is a maya spline
|
||||
rEVNT.Skip(2);
|
||||
u32 KnotCount = rEVNT.ReadLong();
|
||||
rEVNT.Skip(0xA * KnotCount);
|
||||
rEVNT.Skip(9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +134,8 @@ CAnimEventData* CAnimEventLoader::LoadEVNT(IInputStream& rEVNT, CResourceEntry *
|
|||
{
|
||||
CAnimEventLoader Loader;
|
||||
Loader.mpEventData = new CAnimEventData(pEntry);
|
||||
Loader.LoadEvents(rEVNT, false);
|
||||
Loader.mGame = ePrime;
|
||||
Loader.LoadEvents(rEVNT);
|
||||
return Loader.mpEventData;
|
||||
}
|
||||
|
||||
|
@ -89,6 +143,38 @@ CAnimEventData* CAnimEventLoader::LoadAnimSetEvents(IInputStream& rANCS)
|
|||
{
|
||||
CAnimEventLoader Loader;
|
||||
Loader.mpEventData = new CAnimEventData();
|
||||
Loader.LoadEvents(rANCS, true);
|
||||
Loader.mGame = eEchoes;
|
||||
Loader.LoadEvents(rANCS);
|
||||
return Loader.mpEventData;
|
||||
}
|
||||
|
||||
CAnimEventData* CAnimEventLoader::LoadCorruptionCharacterEventSet(IInputStream& rCHAR)
|
||||
{
|
||||
CAnimEventLoader Loader;
|
||||
Loader.mpEventData = new CAnimEventData();
|
||||
Loader.mGame = eCorruption;
|
||||
|
||||
// Read event set header
|
||||
rCHAR.Skip(0x4); // Skip animation ID
|
||||
rCHAR.ReadString(); // Skip set name
|
||||
|
||||
// Read effect events
|
||||
u32 NumEffectEvents = rCHAR.ReadLong();
|
||||
|
||||
for (u32 EventIdx = 0; EventIdx < NumEffectEvents; EventIdx++)
|
||||
{
|
||||
rCHAR.ReadString();
|
||||
Loader.LoadEffectEvent(rCHAR);
|
||||
}
|
||||
|
||||
// Read sound events
|
||||
u32 NumSoundEvents = rCHAR.ReadLong();
|
||||
|
||||
for (u32 EventIdx = 0; EventIdx < NumSoundEvents; EventIdx++)
|
||||
{
|
||||
rCHAR.ReadString();
|
||||
Loader.LoadSoundEvent(rCHAR);
|
||||
}
|
||||
|
||||
return Loader.mpEventData;
|
||||
}
|
||||
|
|
|
@ -7,13 +7,20 @@
|
|||
class CAnimEventLoader
|
||||
{
|
||||
TResPtr<CAnimEventData> mpEventData;
|
||||
EGame mGame;
|
||||
|
||||
CAnimEventLoader() {}
|
||||
void LoadEvents(IInputStream& rEVNT, bool IsEchoes);
|
||||
void LoadEvents(IInputStream& rEVNT);
|
||||
s32 LoadEventBase(IInputStream& rEVNT);
|
||||
void LoadLoopEvent(IInputStream& rEVNT);
|
||||
void LoadUserEvent(IInputStream& rEVNT);
|
||||
void LoadEffectEvent(IInputStream& rEVNT);
|
||||
void LoadSoundEvent(IInputStream& rEVNT);
|
||||
|
||||
public:
|
||||
static CAnimEventData* LoadEVNT(IInputStream& rEVNT, CResourceEntry *pEntry);
|
||||
static CAnimEventData* LoadAnimSetEvents(IInputStream& rANCS);
|
||||
static CAnimEventData* LoadCorruptionCharacterEventSet(IInputStream& rCHAR);
|
||||
};
|
||||
|
||||
#endif // CANIMEVENTLOADER_H
|
||||
|
|
|
@ -9,13 +9,89 @@ CAnimSetLoader::CAnimSetLoader()
|
|||
|
||||
CAnimSet* CAnimSetLoader::LoadCorruptionCHAR(IInputStream& rCHAR)
|
||||
{
|
||||
// For now, we only read enough to fetch the model
|
||||
rCHAR.Seek(0x1, SEEK_CUR);
|
||||
pSet->mCharacters.resize(1);
|
||||
SSetCharacter& rNode = pSet->mCharacters[0];
|
||||
pSet->mCharacters.emplace_back( SSetCharacter() );;
|
||||
SSetCharacter& rChar = pSet->mCharacters.back();
|
||||
|
||||
// Character Header
|
||||
rChar.ID = rCHAR.ReadByte();
|
||||
rChar.Name = rCHAR.ReadString();
|
||||
rChar.pModel = gpResourceStore->LoadResource(rCHAR.ReadLongLong(), "CMDL");
|
||||
rChar.pSkin = gpResourceStore->LoadResource(rCHAR.ReadLongLong(), "CSKR");
|
||||
|
||||
u32 NumOverlays = rCHAR.ReadLong();
|
||||
|
||||
for (u32 iOverlay = 0; iOverlay < NumOverlays; iOverlay++)
|
||||
{
|
||||
SOverlayModel Overlay;
|
||||
Overlay.Type = (EOverlayType) rCHAR.ReadLong();
|
||||
Overlay.ModelID = CAssetID(rCHAR, e64Bit);
|
||||
Overlay.SkinID = CAssetID(rCHAR, e64Bit);
|
||||
rChar.OverlayModels.push_back(Overlay);
|
||||
}
|
||||
|
||||
rChar.pSkeleton = gpResourceStore->LoadResource(rCHAR.ReadLongLong(), "CINF");
|
||||
rChar.AnimDataID = CAssetID(rCHAR, e64Bit);
|
||||
|
||||
// PAS Database
|
||||
LoadPASDatabase(rCHAR);
|
||||
|
||||
// Particle Resource Data
|
||||
LoadParticleResourceData(rCHAR, &rChar, 10);
|
||||
|
||||
// Events
|
||||
u32 NumEventSets = rCHAR.ReadLong();
|
||||
|
||||
for (u32 iSet = 0; iSet < NumEventSets; iSet++)
|
||||
{
|
||||
CAnimEventData *pEvents = CAnimEventLoader::LoadCorruptionCharacterEventSet(rCHAR);
|
||||
pSet->mAnimEvents.push_back(pEvents);
|
||||
}
|
||||
|
||||
// Animations
|
||||
u32 NumAnimations = rCHAR.ReadLong();
|
||||
|
||||
for (u32 AnimIdx = 0; AnimIdx < NumAnimations; AnimIdx++)
|
||||
{
|
||||
SAnimation Anim;
|
||||
Anim.Name = rCHAR.ReadString();
|
||||
Anim.pMetaAnim = gMetaAnimFactory.LoadFromStream(rCHAR, mGame);
|
||||
pSet->mAnimations.push_back(Anim);
|
||||
}
|
||||
|
||||
// Animation Bounds
|
||||
u32 NumAnimationBounds = rCHAR.ReadLong();
|
||||
rCHAR.Skip(NumAnimationBounds * 0x20);
|
||||
rCHAR.Skip(1);
|
||||
|
||||
// Bool Array
|
||||
u32 BoolArraySize = rCHAR.ReadLong();
|
||||
rCHAR.Skip(BoolArraySize);
|
||||
|
||||
// Collision Primitives
|
||||
u32 NumPrimitiveSets = rCHAR.ReadLong();
|
||||
|
||||
for (u32 SetIdx = 0; SetIdx < NumPrimitiveSets; SetIdx++)
|
||||
{
|
||||
rCHAR.ReadString();
|
||||
u32 NumPrimitives = rCHAR.ReadLong();
|
||||
|
||||
for (u32 PrimIdx = 0; PrimIdx < NumPrimitives; PrimIdx++)
|
||||
{
|
||||
rCHAR.Skip(0x34);
|
||||
rCHAR.ReadString();
|
||||
rCHAR.Skip(4);
|
||||
}
|
||||
}
|
||||
|
||||
// Sound Resources
|
||||
u32 NumSounds = rCHAR.ReadLong();
|
||||
|
||||
for (u32 SoundIdx = 0; SoundIdx < NumSounds; SoundIdx++)
|
||||
{
|
||||
CAssetID SoundID(rCHAR, e64Bit);
|
||||
rChar.SoundEffects.push_back(SoundID);
|
||||
}
|
||||
|
||||
rNode.Name = rCHAR.ReadString();
|
||||
rNode.pModel = gpResourceStore->LoadResource(rCHAR.ReadLongLong(), "CMDL");
|
||||
return pSet;
|
||||
}
|
||||
|
||||
|
@ -23,22 +99,25 @@ CAnimSet* CAnimSetLoader::LoadReturnsCHAR(IInputStream& rCHAR)
|
|||
{
|
||||
// For now, we only read enough to fetch the model
|
||||
rCHAR.Seek(0x16, SEEK_CUR);
|
||||
pSet->mCharacters.resize(1);
|
||||
SSetCharacter& rNode = pSet->mCharacters[0];
|
||||
|
||||
rNode.Name = rCHAR.ReadString();
|
||||
pSet->mCharacters.emplace_back( SSetCharacter() );;
|
||||
SSetCharacter& rChar = pSet->mCharacters.back();
|
||||
|
||||
rChar.ID = 0;
|
||||
rChar.Name = rCHAR.ReadString();
|
||||
rCHAR.Seek(0x14, SEEK_CUR);
|
||||
rCHAR.ReadString();
|
||||
rNode.pModel = gpResourceStore->LoadResource(rCHAR.ReadLongLong(), "CMDL");
|
||||
rChar.pModel = gpResourceStore->LoadResource(rCHAR.ReadLongLong(), "CMDL");
|
||||
return pSet;
|
||||
}
|
||||
|
||||
void CAnimSetLoader::LoadPASDatabase(IInputStream& rPAS4)
|
||||
{
|
||||
// For now, just parse the data; don't store it
|
||||
rPAS4.Seek(0x4, SEEK_CUR); // Skipping PAS4 FourCC
|
||||
u32 Magic = rPAS4.ReadLong();
|
||||
u32 AnimStateCount = rPAS4.ReadLong();
|
||||
rPAS4.Seek(0x4, SEEK_CUR); // Skipping default anim state
|
||||
ASSERT(Magic == FOURCC('PAS4'));
|
||||
|
||||
for (u32 iState = 0; iState < AnimStateCount; iState++)
|
||||
{
|
||||
|
@ -72,6 +151,41 @@ void CAnimSetLoader::LoadPASDatabase(IInputStream& rPAS4)
|
|||
}
|
||||
}
|
||||
|
||||
void CAnimSetLoader::LoadParticleResourceData(IInputStream& rFile, SSetCharacter *pChar, u16 CharVersion)
|
||||
{
|
||||
u32 ParticleCount = rFile.ReadLong();
|
||||
pChar->GenericParticles.reserve(ParticleCount);
|
||||
|
||||
for (u32 iPart = 0; iPart < ParticleCount; iPart++)
|
||||
pChar->GenericParticles.push_back( CAssetID(rFile, mGame) );
|
||||
|
||||
u32 SwooshCount = rFile.ReadLong();
|
||||
pChar->SwooshParticles.reserve(SwooshCount);
|
||||
|
||||
for (u32 iSwoosh = 0; iSwoosh < SwooshCount; iSwoosh++)
|
||||
pChar->SwooshParticles.push_back( CAssetID(rFile, mGame) );
|
||||
|
||||
if (CharVersion >= 6 && mGame <= eEchoes) rFile.Seek(0x4, SEEK_CUR);
|
||||
|
||||
u32 ElectricCount = rFile.ReadLong();
|
||||
pChar->ElectricParticles.reserve(ElectricCount);
|
||||
|
||||
for (u32 iElec = 0; iElec < ElectricCount; iElec++)
|
||||
pChar->ElectricParticles.push_back( CAssetID(rFile, mGame) );
|
||||
|
||||
if (mGame >= eEchoes)
|
||||
{
|
||||
u32 SpawnCount = rFile.ReadLong();
|
||||
pChar->SpawnParticles.reserve(SpawnCount);
|
||||
|
||||
for (u32 iSpawn = 0; iSpawn < SpawnCount; iSpawn++)
|
||||
pChar->SpawnParticles.push_back( CAssetID(rFile, mGame) );
|
||||
}
|
||||
|
||||
rFile.Seek(0x4, SEEK_CUR);
|
||||
if (mGame >= eEchoes) rFile.Seek(0x4, SEEK_CUR);
|
||||
}
|
||||
|
||||
void CAnimSetLoader::LoadAnimationSet(IInputStream& rANCS)
|
||||
{
|
||||
u16 Version = rANCS.ReadShort();
|
||||
|
@ -84,7 +198,7 @@ void CAnimSetLoader::LoadAnimationSet(IInputStream& rANCS)
|
|||
{
|
||||
SAnimation Anim;
|
||||
Anim.Name = rANCS.ReadString();
|
||||
Anim.pMetaAnim = gMetaAnimFactory.LoadFromStream(rANCS);
|
||||
Anim.pMetaAnim = gMetaAnimFactory.LoadFromStream(rANCS, mGame);
|
||||
pSet->mAnimations.push_back(Anim);
|
||||
}
|
||||
|
||||
|
@ -98,11 +212,11 @@ void CAnimSetLoader::LoadAnimationSet(IInputStream& rANCS)
|
|||
Trans.Unknown = rANCS.ReadLong();
|
||||
Trans.AnimIdA = rANCS.ReadLong();
|
||||
Trans.AnimIdB = rANCS.ReadLong();
|
||||
Trans.pMetaTrans = gMetaTransFactory.LoadFromStream(rANCS);
|
||||
Trans.pMetaTrans = gMetaTransFactory.LoadFromStream(rANCS, mGame);
|
||||
pSet->mTransitions.push_back(Trans);
|
||||
}
|
||||
|
||||
pSet->mpDefaultTransition = gMetaTransFactory.LoadFromStream(rANCS);
|
||||
pSet->mpDefaultTransition = gMetaTransFactory.LoadFromStream(rANCS, mGame);
|
||||
|
||||
// Additive Animations
|
||||
u32 NumAdditive = rANCS.ReadLong();
|
||||
|
@ -130,14 +244,14 @@ void CAnimSetLoader::LoadAnimationSet(IInputStream& rANCS)
|
|||
{
|
||||
SHalfTransition Trans;
|
||||
Trans.AnimID = rANCS.ReadLong();
|
||||
Trans.pMetaTrans = gMetaTransFactory.LoadFromStream(rANCS);
|
||||
Trans.pMetaTrans = gMetaTransFactory.LoadFromStream(rANCS, mGame);
|
||||
pSet->mHalfTransitions.push_back(Trans);
|
||||
}
|
||||
}
|
||||
|
||||
// Skipping MP1 ANIM asset list
|
||||
// Events
|
||||
if (mVersion >= eEchoesDemo)
|
||||
if (mGame >= eEchoesDemo)
|
||||
{
|
||||
u32 EventDataCount = rANCS.ReadLong();
|
||||
pSet->mAnimEvents.reserve(EventDataCount);
|
||||
|
@ -260,20 +374,6 @@ void CAnimSetLoader::ProcessPrimitives()
|
|||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
CAnimSet* CAnimSetLoader::LoadANCSOrCHAR(IInputStream& rFile, CResourceEntry *pEntry)
|
||||
{
|
||||
if (!rFile.IsValid()) return nullptr;
|
||||
u8 Test = rFile.PeekByte();
|
||||
|
||||
if (Test == 0x3 || Test == 0x5 || Test == 0x59)
|
||||
return LoadCHAR(rFile, pEntry);
|
||||
else if (Test == 0x0)
|
||||
return LoadANCS(rFile, pEntry);
|
||||
|
||||
Log::Error("Failed to determine animset format for " + rFile.GetSourceString() + "; first byte is " + TString::HexString(Test, 2));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
||||
{
|
||||
if (!rANCS.IsValid()) return nullptr;
|
||||
|
@ -287,7 +387,7 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
|||
|
||||
CAnimSetLoader Loader;
|
||||
Loader.pSet = new CAnimSet(pEntry);
|
||||
Loader.mVersion = pEntry->Game();
|
||||
Loader.mGame = pEntry->Game();
|
||||
|
||||
u32 NodeCount = rANCS.ReadLong();
|
||||
Loader.pSet->mCharacters.resize(NodeCount);
|
||||
|
@ -296,11 +396,11 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
|||
{
|
||||
SSetCharacter *pChar = &Loader.pSet->mCharacters[iNode];
|
||||
|
||||
rANCS.Seek(0x4, SEEK_CUR); // Skipping node self-index
|
||||
u16 Unknown1 = rANCS.ReadShort();
|
||||
if (iNode == 0 && Loader.mVersion == eUnknownGame)
|
||||
pChar->ID = rANCS.ReadLong();
|
||||
u16 CharVersion = rANCS.ReadShort();
|
||||
if (iNode == 0 && Loader.mGame == eUnknownGame)
|
||||
{
|
||||
Loader.mVersion = (Unknown1 == 0xA) ? eEchoes : ePrime; // Best version indicator we know of unfortunately
|
||||
Loader.mGame = (CharVersion == 0xA) ? eEchoes : ePrime;
|
||||
}
|
||||
pChar->Name = rANCS.ReadString();
|
||||
pChar->pModel = gpResourceStore->LoadResource(rANCS.ReadLong(), "CMDL");
|
||||
|
@ -315,7 +415,7 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
|||
for (u32 iAnim = 0; iAnim < AnimCount; iAnim++)
|
||||
{
|
||||
rANCS.Seek(0x4, SEEK_CUR);
|
||||
if (Loader.mVersion == ePrime) rANCS.Seek(0x1, SEEK_CUR);
|
||||
if (Loader.mGame == ePrime) rANCS.Seek(0x1, SEEK_CUR);
|
||||
rANCS.ReadString();
|
||||
}
|
||||
|
||||
|
@ -323,37 +423,7 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
|||
Loader.LoadPASDatabase(rANCS);
|
||||
|
||||
// Particles
|
||||
u32 ParticleCount = rANCS.ReadLong();
|
||||
pChar->GenericParticles.reserve(ParticleCount);
|
||||
|
||||
for (u32 iPart = 0; iPart < ParticleCount; iPart++)
|
||||
pChar->GenericParticles.push_back( CAssetID(rANCS, e32Bit) );
|
||||
|
||||
u32 SwooshCount = rANCS.ReadLong();
|
||||
pChar->SwooshParticles.reserve(SwooshCount);
|
||||
|
||||
for (u32 iSwoosh = 0; iSwoosh < SwooshCount; iSwoosh++)
|
||||
pChar->SwooshParticles.push_back( CAssetID(rANCS, e32Bit) );
|
||||
|
||||
if (Unknown1 != 5) rANCS.Seek(0x4, SEEK_CUR);
|
||||
|
||||
u32 ElectricCount = rANCS.ReadLong();
|
||||
pChar->ElectricParticles.reserve(ElectricCount);
|
||||
|
||||
for (u32 iElec = 0; iElec < ElectricCount; iElec++)
|
||||
pChar->ElectricParticles.push_back( CAssetID(rANCS, e32Bit) );
|
||||
|
||||
if (Loader.mVersion == eEchoes)
|
||||
{
|
||||
u32 SpawnCount = rANCS.ReadLong();
|
||||
pChar->SpawnParticles.reserve(SpawnCount);
|
||||
|
||||
for (u32 iSpawn = 0; iSpawn < SpawnCount; iSpawn++)
|
||||
pChar->SpawnParticles.push_back( CAssetID(rANCS, e32Bit) );
|
||||
}
|
||||
|
||||
rANCS.Seek(0x4, SEEK_CUR);
|
||||
if (Loader.mVersion == eEchoes) rANCS.Seek(0x4, SEEK_CUR);
|
||||
Loader.LoadParticleResourceData(rANCS, pChar, CharVersion);
|
||||
|
||||
u32 AnimCount2 = rANCS.ReadLong();
|
||||
for (u32 iAnim = 0; iAnim < AnimCount2; iAnim++)
|
||||
|
@ -375,13 +445,17 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
|||
CAssetID ParticleID(rANCS, e32Bit);
|
||||
if (ParticleID.IsValid()) pChar->EffectParticles.push_back(ParticleID);
|
||||
|
||||
if (Loader.mVersion == ePrime) rANCS.ReadString();
|
||||
if (Loader.mVersion == eEchoes) rANCS.Seek(0x4, SEEK_CUR);
|
||||
if (Loader.mGame == ePrime) rANCS.ReadString();
|
||||
if (Loader.mGame == eEchoes) rANCS.Seek(0x4, SEEK_CUR);
|
||||
rANCS.Seek(0xC, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
pChar->IceModel = CAssetID(rANCS, e32Bit);
|
||||
pChar->IceSkin = CAssetID(rANCS, e32Bit);
|
||||
|
||||
SOverlayModel Overlay;
|
||||
Overlay.Type = eOT_Frozen;
|
||||
Overlay.ModelID = CAssetID(rANCS, e32Bit);
|
||||
Overlay.SkinID = CAssetID(rANCS, e32Bit);
|
||||
pChar->OverlayModels.push_back(Overlay);
|
||||
|
||||
u32 AnimIndexCount = rANCS.ReadLong();
|
||||
|
||||
|
@ -391,7 +465,7 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
|||
pChar->UsedAnimationIndices.insert(AnimIndex);
|
||||
}
|
||||
|
||||
if (Loader.mVersion == eEchoes)
|
||||
if (Loader.mGame == eEchoes)
|
||||
{
|
||||
pChar->SpatialPrimitives = rANCS.ReadLong();
|
||||
rANCS.Seek(0x1, SEEK_CUR);
|
||||
|
@ -416,14 +490,14 @@ CAnimSet* CAnimSetLoader::LoadCHAR(IInputStream& rCHAR, CResourceEntry *pEntry)
|
|||
|
||||
if (Check == 0x5 || Check == 0x3)
|
||||
{
|
||||
Loader.mVersion = eCorruption;
|
||||
Loader.mGame = eCorruption;
|
||||
Loader.pSet = new CAnimSet(pEntry);
|
||||
return Loader.LoadCorruptionCHAR(rCHAR);
|
||||
}
|
||||
|
||||
if (Check == 0x59)
|
||||
{
|
||||
Loader.mVersion = eReturns;
|
||||
Loader.mGame = eReturns;
|
||||
Loader.pSet = new CAnimSet(pEntry);
|
||||
return Loader.LoadReturnsCHAR(rCHAR);
|
||||
}
|
||||
|
@ -431,3 +505,48 @@ CAnimSet* CAnimSetLoader::LoadCHAR(IInputStream& rCHAR, CResourceEntry *pEntry)
|
|||
Log::FileError(rCHAR.GetSourceString(), "CHAR has invalid first byte: " + TString::HexString(Check, 2));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CSourceAnimData* CAnimSetLoader::LoadSAND(IInputStream& rSAND, CResourceEntry *pEntry)
|
||||
{
|
||||
if (!rSAND.IsValid()) return nullptr;
|
||||
|
||||
// We only care about the transitions right now
|
||||
CSourceAnimData *pData = new CSourceAnimData(pEntry);
|
||||
|
||||
u16 Unknown = rSAND.ReadShort(); // probably version
|
||||
ASSERT(Unknown == 0);
|
||||
|
||||
// Transitions
|
||||
u32 NumTransitions = rSAND.ReadLong();
|
||||
|
||||
for (u32 TransitionIdx = 0; TransitionIdx < NumTransitions; TransitionIdx++)
|
||||
{
|
||||
u8 UnkByte = rSAND.ReadByte();
|
||||
ASSERT(UnkByte == 0);
|
||||
|
||||
CSourceAnimData::STransition Transition;
|
||||
Transition.AnimA = CAssetID(rSAND, e64Bit);
|
||||
Transition.AnimB = CAssetID(rSAND, e64Bit);
|
||||
Transition.pTransition = gMetaTransFactory.LoadFromStream(rSAND, pEntry->Game());
|
||||
pData->mTransitions.push_back(Transition);
|
||||
}
|
||||
|
||||
// Half Transitions
|
||||
u32 NumHalfTransitions = rSAND.ReadLong();
|
||||
|
||||
for (u32 HalfIdx = 0; HalfIdx < NumHalfTransitions; HalfIdx++)
|
||||
{
|
||||
u8 UnkByte = rSAND.ReadByte();
|
||||
ASSERT(UnkByte == 0);
|
||||
|
||||
CSourceAnimData::SHalfTransition HalfTrans;
|
||||
HalfTrans.Anim = CAssetID(rSAND, e64Bit);
|
||||
HalfTrans.pTransition = gMetaTransFactory.LoadFromStream(rSAND, pEntry->Game());
|
||||
pData->mHalfTransitions.push_back(HalfTrans);
|
||||
}
|
||||
|
||||
// Default Transition
|
||||
pData->mpDefaultTransition = gMetaTransFactory.LoadFromStream(rSAND, pEntry->Game());
|
||||
|
||||
return pData;
|
||||
}
|
||||
|
|
|
@ -2,25 +2,27 @@
|
|||
#define CCHARACTERLOADER_H
|
||||
|
||||
#include "Core/Resource/Animation/CAnimSet.h"
|
||||
#include "Core/Resource/Animation/CSourceAnimData.h"
|
||||
#include <Common/EGame.h>
|
||||
|
||||
class CAnimSetLoader
|
||||
{
|
||||
TResPtr<CAnimSet> pSet;
|
||||
EGame mVersion;
|
||||
EGame mGame;
|
||||
|
||||
CAnimSetLoader();
|
||||
CAnimSet* LoadCorruptionCHAR(IInputStream& rCHAR);
|
||||
CAnimSet* LoadReturnsCHAR(IInputStream& rCHAR);
|
||||
void LoadPASDatabase(IInputStream& rPAS4);
|
||||
void LoadParticleResourceData(IInputStream& rFile, SSetCharacter *pChar, u16 Version);
|
||||
|
||||
void LoadAnimationSet(IInputStream& rANCS);
|
||||
void ProcessPrimitives();
|
||||
|
||||
public:
|
||||
static CAnimSet* LoadANCSOrCHAR(IInputStream& rFile, CResourceEntry *pEntry);
|
||||
static CAnimSet* LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry);
|
||||
static CAnimSet* LoadCHAR(IInputStream& rCHAR, CResourceEntry *pEntry);
|
||||
static CSourceAnimData* LoadSAND(IInputStream& rSAND, CResourceEntry *pEntry);
|
||||
};
|
||||
|
||||
#endif // CCHARACTERLOADER_H
|
||||
|
|
|
@ -466,7 +466,7 @@ CAnimation* CAnimationLoader::LoadANIM(IInputStream& rANIM, CResourceEntry *pEnt
|
|||
{
|
||||
// MP3/DKCR unsupported
|
||||
if (pEntry->Game() > eEchoes)
|
||||
return nullptr;
|
||||
return new CAnimation(pEntry);
|
||||
|
||||
u32 CompressionType = rANIM.ReadLong();
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ public:
|
|||
case eScan: return new CScan(pEntry);
|
||||
case eSkeleton: return new CSkeleton(pEntry);
|
||||
case eSkin: return new CSkin(pEntry);
|
||||
case eSourceAnimData: return new CSourceAnimData(pEntry);
|
||||
case eStaticGeometryMap: return new CPoiToWorld(pEntry);
|
||||
case eStringList: return new CStringList(pEntry);
|
||||
case eStringTable: return new CStringTable(pEntry);
|
||||
|
@ -88,6 +89,7 @@ public:
|
|||
case eScan: pRes = CScanLoader::LoadSCAN(rInput, pEntry); break;
|
||||
case eSkeleton: pRes = CSkeletonLoader::LoadCINF(rInput, pEntry); break;
|
||||
case eSkin: pRes = CSkinLoader::LoadCSKR(rInput, pEntry); break;
|
||||
case eSourceAnimData: pRes = CAnimSetLoader::LoadSAND(rInput, pEntry); break;
|
||||
case eStateMachine2: pRes = CUnsupportedFormatLoader::LoadFSM2(rInput, pEntry); break;
|
||||
case eStaticGeometryMap: pRes = CPoiToWorldLoader::LoadEGMC(rInput, pEntry); break;
|
||||
case eStringList: pRes = CAudioGroupLoader::LoadSTLC(rInput, pEntry); break;
|
||||
|
|
|
@ -44,7 +44,10 @@ CScan* CScanLoader::LoadScanMP2(IInputStream& rSCAN)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
rSCAN.Seek(0x6, SEEK_CUR);
|
||||
u16 InstanceSize = rSCAN.ReadShort();
|
||||
u32 InstanceEnd = rSCAN.Tell() + InstanceSize;
|
||||
rSCAN.Seek(0x4, SEEK_CUR);
|
||||
|
||||
u16 NumConnections = rSCAN.ReadShort();
|
||||
if (NumConnections > 0) {
|
||||
Log::FileWarning(rSCAN.GetSourceString(), ScanInfoStart, "SNFO object in SCAN has connections");
|
||||
|
@ -68,6 +71,7 @@ CScan* CScanLoader::LoadScanMP2(IInputStream& rSCAN)
|
|||
LoadParamsMP2(rSCAN, NumProperties);
|
||||
break;
|
||||
case 0x12:
|
||||
case 0x15:
|
||||
case 0x16:
|
||||
mpScan = new CScan(mpEntry);
|
||||
LoadParamsMP3(rSCAN, NumProperties);
|
||||
|
@ -77,6 +81,20 @@ CScan* CScanLoader::LoadScanMP2(IInputStream& rSCAN)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Load MP3 dependency list
|
||||
if (mpScan->Game() == eCorruption)
|
||||
{
|
||||
rSCAN.GoTo(InstanceEnd);
|
||||
u32 NumDeps = rSCAN.ReadLong();
|
||||
|
||||
for (u32 DepIdx = 0; DepIdx < NumDeps; DepIdx++)
|
||||
{
|
||||
rSCAN.Skip(4);
|
||||
CAssetID ID(rSCAN, mpScan->Game());
|
||||
mpScan->mDependencyList.push_back(ID);
|
||||
}
|
||||
}
|
||||
|
||||
return mpScan;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,10 @@ CSkeleton* CSkeletonLoader::LoadCINF(IInputStream& rCINF, CResourceEntry *pEntry
|
|||
Loader.mpSkeleton = pSkel;
|
||||
EGame Game = pEntry->Game();
|
||||
|
||||
// We don't support DKCR CINF right now
|
||||
if (rCINF.PeekLong() == 0x9E220006)
|
||||
return pSkel;
|
||||
|
||||
u32 NumBones = rCINF.ReadLong();
|
||||
pSkel->mBones.reserve(NumBones);
|
||||
|
||||
|
@ -61,7 +65,7 @@ CSkeleton* CSkeletonLoader::LoadCINF(IInputStream& rCINF, CResourceEntry *pEntry
|
|||
u32 Check = rCINF.PeekLong();
|
||||
Game = ((Check > 100 || Check == 0) ? eEchoes : ePrime);
|
||||
}
|
||||
if (Game == eEchoes)
|
||||
if (Game >= eEchoes)
|
||||
{
|
||||
pBone->mRotation = CQuaternion(rCINF);
|
||||
pBone->mLocalRotation = CQuaternion(rCINF);
|
||||
|
|
|
@ -5,9 +5,13 @@
|
|||
CSkin* CSkinLoader::LoadCSKR(IInputStream& rCSKR, CResourceEntry *pEntry)
|
||||
{
|
||||
if (!rCSKR.IsValid()) return nullptr;
|
||||
CSkin *pSkin = new CSkin(pEntry);
|
||||
|
||||
// We don't support MP3/DKCR CSKR yet
|
||||
if (rCSKR.PeekLong() == FOURCC('SKIN'))
|
||||
return pSkin;
|
||||
|
||||
u32 NumVertexGroups = rCSKR.ReadLong();
|
||||
CSkin *pSkin = new CSkin(pEntry);
|
||||
pSkin->mVertGroups.resize(NumVertexGroups);
|
||||
|
||||
for (u32 iGrp = 0; iGrp < NumVertexGroups; iGrp++)
|
||||
|
|
|
@ -179,7 +179,8 @@ CResource* CScriptTemplate::FindDisplayAsset(CPropertyStruct *pProperties, u32&
|
|||
|
||||
if (pRes)
|
||||
{
|
||||
rOutCharIndex = (it->ForceNodeIndex >= 0 && it->ForceNodeIndex < (s32) static_cast<CAnimSet*>(pRes)->NumCharacters() ? it->ForceNodeIndex : pChar->Get().CharacterIndex());
|
||||
u32 MaxNumChars = static_cast<CAnimSet*>(pRes)->NumCharacters();
|
||||
rOutCharIndex = (it->ForceNodeIndex >= 0 && it->ForceNodeIndex < (s32) MaxNumChars ? it->ForceNodeIndex : pChar->Get().CharacterIndex());
|
||||
rOutAnimIndex = pChar->Get().AnimIndex();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "Core/Render/CDrawUtil.h"
|
||||
#include "Core/Render/CGraphics.h"
|
||||
#include "Core/Render/CRenderer.h"
|
||||
#include "Core/Resource/Animation/CAnimSet.h"
|
||||
#include "Core/Resource/Script/CMasterTemplate.h"
|
||||
#include "Core/Resource/Script/CScriptLayer.h"
|
||||
#include "Core/ScriptExtra/CScriptExtra.h"
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Editor/Widgets/WDraggableSpinBox.h"
|
||||
#include "Editor/Widgets/WIntegralSpinBox.h"
|
||||
|
||||
#include <Core/Resource/Animation/CAnimSet.h>
|
||||
#include <Core/Resource/Script/IProperty.h>
|
||||
#include <Core/Resource/Script/IPropertyTemplate.h>
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ void IOutputStream::WriteString(const std::string& rkVal)
|
|||
for (unsigned int i = 0; i < rkVal.size(); i++)
|
||||
WriteByte(rkVal[i]);
|
||||
|
||||
if ((rkVal.empty()) || (rkVal.back() != '\0'))
|
||||
if (rkVal.empty() || rkVal.back() != '\0')
|
||||
WriteByte(0);
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ void IOutputStream::WriteString(const std::string& rkVal, unsigned long Count, b
|
|||
for (unsigned int iChr = 0; iChr < Count; iChr++)
|
||||
WriteByte(rkVal[iChr]);
|
||||
|
||||
if (Terminate && (rkVal[Count-1] != '\0'))
|
||||
if (Terminate && (Count == 0 || rkVal[Count-1] != '\0'))
|
||||
WriteByte(0);
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ void IOutputStream::WriteWideString(const std::wstring& rkVal)
|
|||
for (unsigned int iChr = 0; iChr < rkVal.size(); iChr++)
|
||||
WriteShort(rkVal[iChr]);
|
||||
|
||||
if ((!rkVal.empty()) && (rkVal.back() != '\0'))
|
||||
if (rkVal.empty() || rkVal.back() != '\0')
|
||||
WriteShort(0);
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ void IOutputStream::WriteWideString(const std::wstring& rkVal, unsigned long Cou
|
|||
for (unsigned int iChr = 0; iChr < Count; iChr++)
|
||||
WriteShort(rkVal[iChr]);
|
||||
|
||||
if (Terminate && (rkVal[Count-1] != 0))
|
||||
if (Terminate && (Count == 0 || rkVal[Count-1] != 0))
|
||||
WriteShort(0);
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,6 @@ void IOutputStream::WriteSizedWideString(const std::wstring& rkVal)
|
|||
WriteBytes(rkVal.data(), rkVal.size() * 2);
|
||||
}
|
||||
|
||||
|
||||
bool IOutputStream::GoTo(long Address)
|
||||
{
|
||||
return Seek(Address, SEEK_SET);
|
||||
|
|
Loading…
Reference in New Issue