Implemented SCAN cooker
This commit is contained in:
parent
e6702d09e8
commit
1e997dac46
|
@ -256,6 +256,7 @@ HEADERS += \
|
|||
Resource/Scan/CScan.h \
|
||||
Resource/Scan/SScanParametersMP1.h \
|
||||
Resource/Scan/ELogbookCategory.h \
|
||||
Resource/Cooker/CScanCooker.h \
|
||||
NCoreTests.h
|
||||
|
||||
# Source Files
|
||||
|
@ -374,6 +375,7 @@ SOURCES += \
|
|||
Tweaks/CTweakCooker.cpp \
|
||||
Resource/Cooker/CStringCooker.cpp \
|
||||
Resource/Scan/CScan.cpp \
|
||||
Resource/Cooker/CScanCooker.cpp \
|
||||
NCoreTests.cpp
|
||||
|
||||
# Codegen
|
||||
|
|
|
@ -559,3 +559,82 @@ void CAreaDependencyListBuilder::EvaluateDependencyNode(CResourceEntry *pCurEntr
|
|||
EvaluateDependencyNode(pCurEntry, pNode->ChildByIndex(iChild), rOut, pAudioGroupsOut);
|
||||
}
|
||||
}
|
||||
|
||||
// ************ CAssetDependencyListBuilder ************
|
||||
void CAssetDependencyListBuilder::BuildDependencyList(std::vector<CAssetID>& OutAssets)
|
||||
{
|
||||
mCharacterUsageMap.FindUsagesForAsset(mpResourceEntry);
|
||||
EvaluateDependencyNode(mpResourceEntry, mpResourceEntry->Dependencies(), OutAssets);
|
||||
}
|
||||
|
||||
void CAssetDependencyListBuilder::AddDependency(const CAssetID& kID, std::vector<CAssetID>& Out)
|
||||
{
|
||||
CResourceEntry *pEntry = mpResourceEntry->ResourceStore()->FindEntry(kID);
|
||||
if (!pEntry) return;
|
||||
|
||||
EResourceType ResType = pEntry->ResourceType();
|
||||
|
||||
if (mUsedAssets.find(kID) != mUsedAssets.end())
|
||||
return;
|
||||
|
||||
// Dependency is valid! Evaluate the node tree
|
||||
if (ResType == EResourceType::AnimSet)
|
||||
{
|
||||
ASSERT(!mCurrentAnimSetID.IsValid());
|
||||
mCurrentAnimSetID = pEntry->ID();
|
||||
}
|
||||
|
||||
EvaluateDependencyNode(pEntry, pEntry->Dependencies(), Out);
|
||||
|
||||
if (ResType == EResourceType::AnimSet)
|
||||
{
|
||||
ASSERT(mCurrentAnimSetID.IsValid());
|
||||
mCurrentAnimSetID = CAssetID::InvalidID(mpResourceEntry->Game());
|
||||
}
|
||||
|
||||
Out.push_back(kID);
|
||||
mUsedAssets.insert(kID);
|
||||
}
|
||||
|
||||
void CAssetDependencyListBuilder::EvaluateDependencyNode(CResourceEntry* pCurEntry, IDependencyNode* pNode, std::vector<CAssetID>& Out)
|
||||
{
|
||||
if (!pNode) return;
|
||||
EDependencyNodeType Type = pNode->Type();
|
||||
bool ParseChildren = false;
|
||||
|
||||
if (Type == EDependencyNodeType::Resource || Type == EDependencyNodeType::ScriptProperty || Type == EDependencyNodeType::CharacterProperty)
|
||||
{
|
||||
CResourceDependency* pDep = static_cast<CResourceDependency*>(pNode);
|
||||
AddDependency(pDep->ID(), Out);
|
||||
}
|
||||
|
||||
else if (Type == EDependencyNodeType::AnimEvent)
|
||||
{
|
||||
CAnimEventDependency* pDep = static_cast<CAnimEventDependency*>(pNode);
|
||||
uint32 CharIndex = pDep->CharIndex();
|
||||
|
||||
if (CharIndex == -1 || mCharacterUsageMap.IsCharacterUsed(mCurrentAnimSetID, CharIndex))
|
||||
AddDependency(pDep->ID(), Out);
|
||||
}
|
||||
|
||||
else if (Type == EDependencyNodeType::SetCharacter)
|
||||
{
|
||||
CSetCharacterDependency* pChar = static_cast<CSetCharacterDependency*>(pNode);
|
||||
ParseChildren = mCharacterUsageMap.IsCharacterUsed(mCurrentAnimSetID, pChar->CharSetIndex());
|
||||
}
|
||||
|
||||
else if (Type == EDependencyNodeType::SetAnimation)
|
||||
{
|
||||
CSetAnimationDependency* pAnim = static_cast<CSetAnimationDependency*>(pNode);
|
||||
ParseChildren = mCharacterUsageMap.IsAnimationUsed(mCurrentAnimSetID, pAnim);
|
||||
}
|
||||
|
||||
else
|
||||
ParseChildren = true;
|
||||
|
||||
if (ParseChildren)
|
||||
{
|
||||
for (uint32 iChild = 0; iChild < pNode->NumChildren(); iChild++)
|
||||
EvaluateDependencyNode(pCurEntry, pNode->ChildByIndex(iChild), Out);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,5 +96,25 @@ public:
|
|||
void EvaluateDependencyNode(CResourceEntry *pCurEntry, IDependencyNode *pNode, std::list<CAssetID>& rOut, std::set<CAssetID> *pAudioGroupsOut);
|
||||
};
|
||||
|
||||
// ************ CAssetDependencyListBuilder ************
|
||||
//@todo merge with CAreaDependencyListBuilder; code is very similar
|
||||
class CAssetDependencyListBuilder
|
||||
{
|
||||
CResourceEntry* mpResourceEntry;
|
||||
CCharacterUsageMap mCharacterUsageMap;
|
||||
std::set<CAssetID> mUsedAssets;
|
||||
CAssetID mCurrentAnimSetID;
|
||||
|
||||
public:
|
||||
CAssetDependencyListBuilder(CResourceEntry* pEntry)
|
||||
: mpResourceEntry(pEntry)
|
||||
, mCharacterUsageMap(pEntry->ResourceStore())
|
||||
{}
|
||||
|
||||
void BuildDependencyList(std::vector<CAssetID>& OutAssets);
|
||||
void AddDependency(const CAssetID& kID, std::vector<CAssetID>& Out);
|
||||
void EvaluateDependencyNode(CResourceEntry* pCurEntry, IDependencyNode* pNode, std::vector<CAssetID>& Out);
|
||||
};
|
||||
|
||||
#endif // DEPENDENCYLISTBUILDERS
|
||||
|
||||
|
|
|
@ -186,6 +186,13 @@ bool ValidateCooker(EResourceType ResourceType, bool DumpInvalidFileContents)
|
|||
DumpFile.WriteBytes( NewData.data(), NewData.size() );
|
||||
DumpFile.Close();
|
||||
}
|
||||
|
||||
if( NumInvalid >= 100 )
|
||||
{
|
||||
debugf( "Test aborted; at least 100 invalid resources. Checked %d resources, %d passed, %d failed",
|
||||
NumValid + NumInvalid, NumValid, NumInvalid );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test complete
|
||||
|
|
|
@ -92,7 +92,7 @@ void CAnimationParameters::Write(IOutputStream& rSCLY)
|
|||
{
|
||||
CAssetID::skInvalidID32.Write(rSCLY);
|
||||
rSCLY.WriteLong(0);
|
||||
rSCLY.WriteLong(0xFFFFFFFF);
|
||||
rSCLY.WriteLong(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "CAreaCooker.h"
|
||||
#include "CModelCooker.h"
|
||||
#include "CPoiToWorldCooker.h"
|
||||
#include "CScanCooker.h"
|
||||
#include "CStringCooker.h"
|
||||
#include "CWorldCooker.h"
|
||||
|
||||
|
@ -25,6 +26,7 @@ public:
|
|||
{
|
||||
case EResourceType::Area: return CAreaCooker::CookMREA((CGameArea*) pRes, rOutput);
|
||||
case EResourceType::Model: return CModelCooker::CookCMDL((CModel*) pRes, rOutput);
|
||||
case EResourceType::Scan: return CScanCooker::CookSCAN((CScan*) pRes, rOutput);
|
||||
case EResourceType::StaticGeometryMap: return CPoiToWorldCooker::CookEGMC((CPoiToWorld*) pRes, rOutput);
|
||||
case EResourceType::StringTable: return CStringCooker::CookSTRG((CStringTable*) pRes, rOutput);
|
||||
case EResourceType::Tweaks: return CTweakCooker::CookCTWK((CTweakData*) pRes, rOutput);
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
#include "CScanCooker.h"
|
||||
#include "Core/Resource/Cooker/CScriptCooker.h"
|
||||
#include "Core/GameProject/DependencyListBuilders.h"
|
||||
|
||||
bool CScanCooker::CookSCAN(CScan* pScan, IOutputStream& SCAN)
|
||||
{
|
||||
// File header
|
||||
if (pScan->Game() <= EGame::Prime)
|
||||
{
|
||||
// We currently do not support cooking for the MP1 demo build
|
||||
ASSERT( pScan->Game() != EGame::PrimeDemo );
|
||||
SCAN.WriteLong( 5 ); // Version number; must be 5
|
||||
SCAN.WriteLong( 0x0BADBEEF ); // SCAN magic
|
||||
|
||||
CStructRef ScanProperties = pScan->ScanData();
|
||||
CScriptCooker Cooker(pScan->Game());
|
||||
Cooker.WriteProperty(SCAN, ScanProperties.Property(), ScanProperties.DataPointer(), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
SCAN.WriteFourCC( FOURCC('SCAN') ); // SCAN magic
|
||||
SCAN.WriteLong( 2 ); // Version number; must be 2
|
||||
SCAN.WriteByte( 1 ); // Layer version number; must be 1
|
||||
SCAN.WriteLong( 1 ); // Instance count
|
||||
|
||||
// Scans in MP2/3 are saved with the script object data format
|
||||
// Write a dummy script object header here
|
||||
SCAN.WriteLong( FOURCC('SNFO') ); // ScannableObjectInfo object ID
|
||||
uint ScanInstanceSizeOffset = SCAN.Tell();
|
||||
SCAN.WriteShort( 0 ); // Object size
|
||||
SCAN.WriteLong( 0 ); // Instance ID
|
||||
SCAN.WriteShort( 0 ); // Link count
|
||||
|
||||
CStructRef ScanProperties = pScan->ScanData();
|
||||
CScriptCooker Cooker(pScan->Game());
|
||||
Cooker.WriteProperty(SCAN, ScanProperties.Property(), ScanProperties.DataPointer(), false);
|
||||
|
||||
uint ScanInstanceEnd = SCAN.Tell();
|
||||
uint ScanInstanceSize = ScanInstanceEnd - ScanInstanceSizeOffset - 2;
|
||||
SCAN.GoTo(ScanInstanceSizeOffset);
|
||||
SCAN.WriteShort( (uint16) ScanInstanceSize );
|
||||
SCAN.GoTo(ScanInstanceEnd);
|
||||
|
||||
// Write dependency list
|
||||
// @todo this output may not be 100% correct. Some dependencies seem to be conditionally excluded in base game.
|
||||
// This may cause some assets to be unnecessarily loaded into memory ingame.
|
||||
std::vector<CAssetID> Dependencies;
|
||||
CAssetDependencyListBuilder Builder(pScan->Entry());
|
||||
Builder.BuildDependencyList(Dependencies);
|
||||
SCAN.WriteLong(Dependencies.size());
|
||||
|
||||
for (const CAssetID& kID : Dependencies)
|
||||
{
|
||||
CResourceEntry* pEntry = pScan->Entry()->ResourceStore()->FindEntry(kID);
|
||||
ASSERT( pEntry != nullptr );
|
||||
|
||||
pEntry->CookedExtension().Write(SCAN);
|
||||
kID.Write(SCAN);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef CSCANCOOKER_H
|
||||
#define CSCANCOOKER_H
|
||||
|
||||
#include "Core/Resource/Scan/CScan.h"
|
||||
|
||||
/** Cooker class for writing game-compatible SCAN assets */
|
||||
class CScanCooker
|
||||
{
|
||||
CScanCooker() {}
|
||||
|
||||
public:
|
||||
static bool CookSCAN(CScan* pScan, IOutputStream& SCAN);
|
||||
};
|
||||
|
||||
#endif // CSCANCOOKER_H
|
|
@ -2383,7 +2383,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0xDFF9B92" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="BallForwardBrakingAccelWater"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0xE07B299" Type="GhorStructB"/>
|
||||
|
@ -4383,7 +4383,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x191F4F62" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="MarbleToTireThresholdSpeed"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x19275A97" Type="float"/>
|
||||
|
@ -10323,7 +10323,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x38F84011" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="ScrewAttackWallJumpGravity"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x38FABDE9" Type="asset"/>
|
||||
|
@ -14491,7 +14491,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x4ED87EBD" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="Tireness"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x4EDB1D0E" Type="bool"/>
|
||||
|
@ -14895,7 +14895,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x50F2A114" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="BallForwardBrakingAccelPhazon"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x50F77DF0" Type="float"/>
|
||||
|
@ -15579,7 +15579,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x54C20211" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="ForceToLeanGain"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x54CD1874" Type="asset"/>
|
||||
|
@ -16367,7 +16367,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x591DA5B4" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="ScrewAttackVerticalJumpVelocity"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x59276E14" Type="float"/>
|
||||
|
@ -16671,7 +16671,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x5B3C4299" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="BallForwardBrakingAccelShrubbery"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x5B3C92BC" Type="UnknownStruct55"/>
|
||||
|
@ -17611,7 +17611,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x60520222" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="BallForwardBrakingAccelOrganic"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x6057938A" Type="spline"/>
|
||||
|
@ -23063,7 +23063,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x7EAB4BAB" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="ScrewAttackGravity"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x7EAF8D70" Type="float"/>
|
||||
|
@ -27411,7 +27411,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x96226D18" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="TireToMarbleThresholdSpeed"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0x9623E44B" Type="float"/>
|
||||
|
@ -32239,7 +32239,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0xB06AC970" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="BallForwardBrakingAccelNormal"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0xB06D1B60" Type="choice"/>
|
||||
|
@ -33775,7 +33775,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0xB90A721E" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="LeanTrackingGain"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0xB90DFF44" Type="float"/>
|
||||
|
@ -34171,7 +34171,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0xBB3C2629" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="BallForwardBrakingAccelAir"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0xBB3C732E" Type="bool"/>
|
||||
|
@ -34255,7 +34255,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0xBBAF8577" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="BallForwardBrakingAccelLava"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0xBBB2D1E6" Type="SurfacePosition"/>
|
||||
|
@ -38571,7 +38571,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0xD27A50F1" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="BallForwardBrakingAccelIce"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0xD27E8786" Type="asset"/>
|
||||
|
@ -41695,7 +41695,7 @@
|
|||
</Element>
|
||||
<Element>
|
||||
<Key ID="0xE428F231" Type="float"/>
|
||||
<Value Name="Unknown"/>
|
||||
<Value Name="ScrewAttackHorizontalJumpVelocity"/>
|
||||
</Element>
|
||||
<Element>
|
||||
<Key ID="0xE42BAB04" Type="bool"/>
|
||||
|
|
Loading…
Reference in New Issue