mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-12-17 00:47:05 +00:00
Lots of work to get MP2 repacking functional
This commit is contained in:
@@ -14,16 +14,17 @@
|
||||
* Note that in public release builds, asserts are compiled out entirely, so neither log messages nor debug breaks
|
||||
* will occur.
|
||||
*
|
||||
* There are two other macros defined which can be useful for debugging, but shouldn't be used as permanent error
|
||||
* checks: BREAK_ONLY_ASSERT, which doesn't write the error to the log, and LOG_ONLY_ASSERT, which doesn't trigger
|
||||
* a debug break.
|
||||
* LOG_ONLY_ASSERT is similar to a regular assert, but doesn't trigger a debug break. It can be useful for debugging,
|
||||
* but shouldn't be used as a permanent error check.
|
||||
*/
|
||||
#define __FILE_SHORT__ strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__
|
||||
|
||||
#if _DEBUG
|
||||
#define DEBUG_BREAK __debugbreak();
|
||||
#define CONDITIONAL_BREAK(Condition) if (##Condition) DEBUG_BREAK
|
||||
#else
|
||||
#define DEBUG_BREAK {}
|
||||
#define CONDITIONAL_BREAK(Condition) {}
|
||||
#endif
|
||||
|
||||
#if !PUBLIC_RELEASE
|
||||
@@ -41,11 +42,6 @@
|
||||
#define WRITE_FAILURE_TO_LOG(Expression) \
|
||||
Log::Write(TString(__FILE_SHORT__) + "(" + TString::FromInt32(__LINE__, 0, 10) + "): ASSERT FAILED: " + #Expression);
|
||||
|
||||
#define BREAK_ONLY_ASSERT(Expression) \
|
||||
ASSERT_CHECK_BEGIN(Expression) \
|
||||
DEBUG_BREAK \
|
||||
ASSERT_CHECK_END
|
||||
|
||||
#define LOG_ONLY_ASSERT(Expression) \
|
||||
ASSERT_CHECK_BEGIN(Expression) \
|
||||
WRITE_FAILURE_TO_LOG(Expression) \
|
||||
|
||||
@@ -199,7 +199,7 @@ namespace CompressionUtil
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompressSegmentedData(u8 *pSrc, u32 SrcLen, u8 *pDst, u32& rTotalOut, bool IsZlib)
|
||||
bool CompressSegmentedData(u8 *pSrc, u32 SrcLen, u8 *pDst, u32& rTotalOut, bool IsZlib, bool AllowUncompressedSegments)
|
||||
{
|
||||
u8 *pSrcEnd = pSrc + SrcLen;
|
||||
u8 *pDstStart = pDst;
|
||||
@@ -222,7 +222,7 @@ namespace CompressionUtil
|
||||
CompressLZO(pSrc, Size, Compressed.data(), TotalOut);
|
||||
|
||||
// Verify that the compressed data is actually smaller.
|
||||
if (TotalOut >= Size)
|
||||
if (AllowUncompressedSegments && TotalOut >= Size)
|
||||
{
|
||||
// Write negative size value to destination (which signifies uncompressed)
|
||||
*pDst++ = -Size >> 8;
|
||||
@@ -250,13 +250,13 @@ namespace CompressionUtil
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompressZlibSegmented(u8 *pSrc, u32 SrcLen, u8 *pDst, u32& rTotalOut)
|
||||
bool CompressZlibSegmented(u8 *pSrc, u32 SrcLen, u8 *pDst, u32& rTotalOut, bool AllowUncompressedSegments)
|
||||
{
|
||||
return CompressSegmentedData(pSrc, SrcLen, pDst, rTotalOut, true);
|
||||
return CompressSegmentedData(pSrc, SrcLen, pDst, rTotalOut, true, AllowUncompressedSegments);
|
||||
}
|
||||
|
||||
bool CompressLZOSegmented(u8 *pSrc, u32 SrcLen, u8 *pDst, u32& rTotalOut)
|
||||
bool CompressLZOSegmented(u8 *pSrc, u32 SrcLen, u8 *pDst, u32& rTotalOut, bool AllowUncompressedSegments)
|
||||
{
|
||||
return CompressSegmentedData(pSrc, SrcLen, pDst, rTotalOut, false);
|
||||
return CompressSegmentedData(pSrc, SrcLen, pDst, rTotalOut, false, AllowUncompressedSegments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ namespace CompressionUtil
|
||||
// Compression
|
||||
bool CompressZlib(u8 *pSrc, u32 SrcLen, u8 *pDst, u32 DstLen, u32& rTotalOut);
|
||||
bool CompressLZO(u8 *pSrc, u32 SrcLen, u8 *pDst, u32& rTotalOut);
|
||||
bool CompressSegmentedData(u8 *pSrc, u32 SrcLen, u8 *pDst, u32& rTotalOut, bool IsZlib);
|
||||
bool CompressZlibSegmented(u8 *pSrc, u32 SrcLen, u8 *pDst, u32& rTotalOut);
|
||||
bool CompressLZOSegmented(u8 *pSrc, u32 SrcLen, u8 *pDst, u32& rTotalOut);
|
||||
bool CompressSegmentedData(u8 *pSrc, u32 SrcLen, u8 *pDst, u32& rTotalOut, bool IsZlib, bool AllowUncompressedSegments);
|
||||
bool CompressZlibSegmented(u8 *pSrc, u32 SrcLen, u8 *pDst, u32& rTotalOut, bool AllowUncompressedSegments);
|
||||
bool CompressLZOSegmented(u8 *pSrc, u32 SrcLen, u8 *pDst, u32& rTotalOut, bool AllowUncompressedSegments);
|
||||
}
|
||||
|
||||
#endif // COMPRESSIONUTIL_H
|
||||
|
||||
@@ -55,6 +55,15 @@ void CDependencyTree::AddDependency(CResource *pRes, bool AvoidDuplicates /*= tr
|
||||
AddDependency(pRes->ID(), AvoidDuplicates);
|
||||
}
|
||||
|
||||
void CDependencyTree::AddCharacterDependency(const CAnimationParameters& rkAnimParams)
|
||||
{
|
||||
// This is for formats other than MREA that use AnimationParameters (such as SCAN).
|
||||
CAnimSet *pSet = rkAnimParams.AnimSet();
|
||||
if (!pSet || rkAnimParams.CharacterIndex() == -1) return;
|
||||
CCharPropertyDependency *pChar = new CCharPropertyDependency("NULL", pSet->ID(), rkAnimParams.CharacterIndex());
|
||||
mChildren.push_back(pChar);
|
||||
}
|
||||
|
||||
// ************ CResourceDependency ************
|
||||
EDependencyNodeType CResourceDependency::Type() const
|
||||
{
|
||||
@@ -215,6 +224,7 @@ CSetCharacterDependency* CSetCharacterDependency::BuildTree(const CAnimSet *pkOw
|
||||
|
||||
pTree->AddDependency(pkChar->IceModel);
|
||||
pTree->AddDependency(pkChar->IceSkin);
|
||||
pTree->AddDependency(pkChar->SpatialPrimitives);
|
||||
}
|
||||
|
||||
return pTree;
|
||||
@@ -300,7 +310,8 @@ void CAreaDependencyTree::AddScriptLayer(CScriptLayer *pLayer)
|
||||
CScriptInstanceDependency *pTree = CScriptInstanceDependency::BuildTree( pLayer->InstanceByIndex(iInst) );
|
||||
ASSERT(pTree != nullptr);
|
||||
|
||||
if (pTree->NumChildren() > 0)
|
||||
// Note: MP2+ need to track all instances (not just instances with dependencies) to be able to build the layer module list
|
||||
if (pTree->NumChildren() > 0 || pLayer->Area()->Game() >= eEchoesDemo)
|
||||
mChildren.push_back(pTree);
|
||||
else
|
||||
delete pTree;
|
||||
|
||||
@@ -10,6 +10,7 @@ class CScriptLayer;
|
||||
class CScriptObject;
|
||||
class CPropertyStruct;
|
||||
class CAnimSet;
|
||||
class CAnimationParameters;
|
||||
struct SSetCharacter;
|
||||
|
||||
// Group of node classes forming a tree of cached resource dependencies.
|
||||
@@ -39,8 +40,8 @@ public:
|
||||
virtual bool HasDependency(const CAssetID& rkID) const;
|
||||
|
||||
// Accessors
|
||||
u32 NumChildren() const { return mChildren.size(); }
|
||||
IDependencyNode* ChildByIndex(u32 Index) const { return mChildren[Index]; }
|
||||
inline u32 NumChildren() const { return mChildren.size(); }
|
||||
inline IDependencyNode* ChildByIndex(u32 Index) const { return mChildren[Index]; }
|
||||
};
|
||||
|
||||
// Basic dependency tree; this class is sufficient for most resource types.
|
||||
@@ -59,6 +60,7 @@ public:
|
||||
void AddChild(IDependencyNode *pNode);
|
||||
void AddDependency(const CAssetID& rkID, bool AvoidDuplicates = true);
|
||||
void AddDependency(CResource *pRes, bool AvoidDuplicates = true);
|
||||
void AddCharacterDependency(const CAnimationParameters& rkAnimParams);
|
||||
|
||||
// Accessors
|
||||
inline void SetID(const CAssetID& rkID) { mRootID = rkID; }
|
||||
@@ -183,6 +185,7 @@ public:
|
||||
|
||||
// Accessors
|
||||
inline bool IsUsedByCharacter(u32 CharIdx) const { return mCharacterIndices.find(CharIdx) != mCharacterIndices.end(); }
|
||||
inline bool IsUsedByAnyCharacter() const { return !mCharacterIndices.empty(); }
|
||||
|
||||
// Static
|
||||
static CSetAnimationDependency* BuildTree(const CAnimSet *pkOwnerSet, u32 AnimIndex);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "CGameProject.h"
|
||||
#include "Core/Resource/Factory/CTemplateLoader.h"
|
||||
#include "Core/Resource/Script/CMasterTemplate.h"
|
||||
#include <Common/Serialization/XML.h>
|
||||
|
||||
@@ -21,6 +22,7 @@ bool CGameProject::Load(const TWideString& rkPath)
|
||||
TString ProjPath = rkPath.ToUTF8();
|
||||
CXMLReader Reader(ProjPath);
|
||||
Serialize(Reader);
|
||||
CTemplateLoader::LoadGameTemplates(mGame);
|
||||
|
||||
mpResourceStore->LoadResourceDatabase();
|
||||
mpAudioManager->LoadAssets();
|
||||
|
||||
@@ -159,7 +159,7 @@ void CPackage::Cook()
|
||||
if (mpProject->Game() <= eEchoesDemo)
|
||||
Success = CompressionUtil::CompressZlib(ResourceData.data(), ResourceData.size(), CompressedData.data(), CompressedData.size(), CompressedSize);
|
||||
else
|
||||
Success = CompressionUtil::CompressLZOSegmented(ResourceData.data(), ResourceData.size(), CompressedData.data(), CompressedSize);
|
||||
Success = CompressionUtil::CompressLZOSegmented(ResourceData.data(), ResourceData.size(), CompressedData.data(), CompressedSize, false);
|
||||
|
||||
// Make sure that the compressed data is actually smaller, accounting for padding + uncompressed size value
|
||||
if (Success)
|
||||
@@ -217,7 +217,7 @@ void CPackage::CompareOriginalAssetList(const std::list<CAssetID>& rkNewList)
|
||||
TWideString CookedPath = CookedPackagePath(false);
|
||||
CFileInStream Pak(CookedPath.ToUTF8().ToStdString(), IOUtil::eBigEndian);
|
||||
|
||||
if (!Pak.IsValid())
|
||||
if (!Pak.IsValid() || Pak.Size() == 0)
|
||||
{
|
||||
Log::Error("Failed to compare to original asset list; couldn't open the original pak");
|
||||
return;
|
||||
|
||||
@@ -139,6 +139,21 @@ void CCharacterUsageMap::ParseDependencyNode(IDependencyNode *pNode)
|
||||
rUsageList[UsedChar] = true;
|
||||
}
|
||||
|
||||
// Parse dependencies of the referenced resource if it's a type that can reference animsets
|
||||
else if (Type == eDNT_ResourceDependency || Type == eDNT_ScriptProperty)
|
||||
{
|
||||
CResourceDependency *pDep = static_cast<CResourceDependency*>(pNode);
|
||||
CResourceEntry *pEntry = gpResourceStore->FindEntry(pDep->ID());
|
||||
|
||||
if (pEntry)
|
||||
{
|
||||
EResType ResType = pEntry->ResourceType();
|
||||
|
||||
if (ResType == eScan)
|
||||
ParseDependencyNode(pEntry->Dependencies());
|
||||
}
|
||||
}
|
||||
|
||||
// Look for sub-dependencies of the current node
|
||||
else
|
||||
{
|
||||
@@ -275,7 +290,7 @@ void CPackageDependencyListBuilder::EvaluateDependencyNode(CResourceEntry *pCurE
|
||||
else if (Type == eDNT_SetAnimation)
|
||||
{
|
||||
CSetAnimationDependency *pAnim = static_cast<CSetAnimationDependency*>(pNode);
|
||||
ParseChildren = mCharacterUsageMap.IsAnimationUsed(mCurrentAnimSetID, pAnim) || mIsPlayerActor; // todo - should maybe omit completely unused animations on PlayerActors?
|
||||
ParseChildren = mCharacterUsageMap.IsAnimationUsed(mCurrentAnimSetID, pAnim) || (mIsPlayerActor && pAnim->IsUsedByAnyCharacter());
|
||||
}
|
||||
|
||||
else
|
||||
@@ -409,7 +424,10 @@ void CAreaDependencyListBuilder::AddDependency(const CAssetID& rkID, std::list<C
|
||||
|
||||
// Don't add CSNGs to the output dependency list (we parse them because we need their AGSC dependencies in the output AudioGroup set)
|
||||
if (ResType != eMidi)
|
||||
{
|
||||
rOut.push_back(rkID);
|
||||
mLayerUsedAssets.insert(rkID);
|
||||
}
|
||||
}
|
||||
|
||||
void CAreaDependencyListBuilder::EvaluateDependencyNode(CResourceEntry *pCurEntry, IDependencyNode *pNode, std::list<CAssetID>& rOut, std::set<CAssetID> *pAudioGroupsOut)
|
||||
@@ -445,7 +463,7 @@ void CAreaDependencyListBuilder::EvaluateDependencyNode(CResourceEntry *pCurEntr
|
||||
else if (Type == eDNT_SetAnimation)
|
||||
{
|
||||
CSetAnimationDependency *pAnim = static_cast<CSetAnimationDependency*>(pNode);
|
||||
ParseChildren = mCharacterUsageMap.IsAnimationUsed(mCurrentAnimSetID, pAnim);
|
||||
ParseChildren = mCharacterUsageMap.IsAnimationUsed(mCurrentAnimSetID, pAnim) || (mIsPlayerActor && pAnim->IsUsedByAnyCharacter());
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
@@ -57,6 +57,7 @@ struct SSetCharacter
|
||||
std::vector<CAssetID> EffectParticles;
|
||||
CAssetID IceModel;
|
||||
CAssetID IceSkin;
|
||||
CAssetID SpatialPrimitives;
|
||||
std::set<u32> UsedAnimationIndices;
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ CGameArea::CGameArea(CResourceEntry *pEntry /*= 0*/)
|
||||
, mOriginalWorldMeshCount(0)
|
||||
, mUsesCompression(false)
|
||||
, mpMaterialSet(nullptr)
|
||||
, mpGeneratorLayer(nullptr)
|
||||
, mpCollision(nullptr)
|
||||
{
|
||||
}
|
||||
@@ -21,7 +20,6 @@ CGameArea::~CGameArea()
|
||||
ClearTerrain();
|
||||
|
||||
delete mpCollision;
|
||||
delete mpGeneratorLayer;
|
||||
|
||||
for (u32 iSCLY = 0; iSCLY < mScriptLayers.size(); iSCLY++)
|
||||
delete mScriptLayers[iSCLY];
|
||||
@@ -54,8 +52,6 @@ CDependencyTree* CGameArea::BuildDependencyTree() const
|
||||
for (u32 iLayer = 0; iLayer < mScriptLayers.size(); iLayer++)
|
||||
pTree->AddScriptLayer(mScriptLayers[iLayer]);
|
||||
|
||||
pTree->AddScriptLayer(mpGeneratorLayer);
|
||||
|
||||
return pTree;
|
||||
}
|
||||
|
||||
@@ -134,8 +130,6 @@ void CGameArea::ClearScriptLayers()
|
||||
for (auto it = mScriptLayers.begin(); it != mScriptLayers.end(); it++)
|
||||
delete *it;
|
||||
mScriptLayers.clear();
|
||||
delete mpGeneratorLayer;
|
||||
mpGeneratorLayer = nullptr;
|
||||
}
|
||||
|
||||
u32 CGameArea::TotalInstanceCount() const
|
||||
|
||||
@@ -49,7 +49,6 @@ class CGameArea : public CResource
|
||||
std::vector<CStaticModel*> mStaticWorldModels; // StaticTerrainModels is the merged terrain for faster rendering in the world editor
|
||||
// Script
|
||||
std::vector<CScriptLayer*> mScriptLayers;
|
||||
CScriptLayer *mpGeneratorLayer;
|
||||
std::unordered_map<u32, CScriptObject*> mObjectMap;
|
||||
// Collision
|
||||
CCollisionMeshGroup *mpCollision;
|
||||
@@ -92,7 +91,6 @@ public:
|
||||
inline CCollisionMeshGroup* Collision() const { return mpCollision; }
|
||||
inline u32 NumScriptLayers() const { return mScriptLayers.size(); }
|
||||
inline CScriptLayer* ScriptLayer(u32 Index) const { return mScriptLayers[Index]; }
|
||||
inline CScriptLayer* GeneratedObjectsLayer() const { return mpGeneratorLayer; }
|
||||
inline u32 NumLightLayers() const { return mLightLayers.size(); }
|
||||
inline u32 NumLights(u32 LayerIndex) const { return (LayerIndex < mLightLayers.size() ? mLightLayers[LayerIndex].size() : 0); }
|
||||
inline CLight* Light(u32 LayerIndex, u32 LightIndex) const { return mLightLayers[LayerIndex][LightIndex]; }
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "CResource.h"
|
||||
#include "CStringTable.h"
|
||||
#include "TResPtr.h"
|
||||
#include "Core/Resource/Animation/CAnimationParameters.h"
|
||||
#include <Common/EGame.h>
|
||||
|
||||
class CScan : public CResource
|
||||
@@ -22,15 +23,34 @@ public:
|
||||
eResearch
|
||||
};
|
||||
|
||||
struct SScanInfoSecondaryModel
|
||||
{
|
||||
CAssetID ModelID;
|
||||
CAnimationParameters AnimParams;
|
||||
TString AttachBoneName;
|
||||
};
|
||||
|
||||
private:
|
||||
EGame mVersion;
|
||||
CAssetID mFrameID;
|
||||
// Common
|
||||
TResPtr<CStringTable> mpStringTable;
|
||||
bool mIsSlow;
|
||||
bool mIsImportant;
|
||||
ELogbookCategory mCategory;
|
||||
|
||||
// MP1
|
||||
CAssetID mFrameID;
|
||||
CAssetID mScanImageTextures[4];
|
||||
std::vector<CAssetID> mLogbookAssets;
|
||||
|
||||
// MP2/3
|
||||
bool mUseLogbookModelPostScan;
|
||||
CAssetID mPostOverrideTexture;
|
||||
float mLogbookDefaultRotX;
|
||||
float mLogbookDefaultRotZ;
|
||||
float mLogbookScale;
|
||||
CAssetID mLogbookModel;
|
||||
CAnimationParameters mLogbookAnimParams;
|
||||
CAnimationParameters mUnknownAnimParams;
|
||||
std::vector<SScanInfoSecondaryModel> mSecondaryModels;
|
||||
|
||||
public:
|
||||
CScan(CResourceEntry *pEntry = 0)
|
||||
@@ -43,23 +63,41 @@ public:
|
||||
|
||||
CDependencyTree* BuildDependencyTree() const
|
||||
{
|
||||
// note: not handling Corruption yet
|
||||
if (Game() >= eCorruptionProto)
|
||||
Log::Warning("CScan::BuildDependencyTree not handling Corruption dependencies");
|
||||
|
||||
CDependencyTree *pTree = new CDependencyTree(ID());
|
||||
pTree->AddDependency(mFrameID);
|
||||
|
||||
if (Game() <= ePrime)
|
||||
pTree->AddDependency(mFrameID);
|
||||
|
||||
pTree->AddDependency(mpStringTable);
|
||||
|
||||
for (u32 iImg = 0; iImg < 4; iImg++)
|
||||
pTree->AddDependency(mScanImageTextures[iImg]);
|
||||
if (Game() <= ePrime)
|
||||
{
|
||||
for (u32 iImg = 0; iImg < 4; iImg++)
|
||||
pTree->AddDependency(mScanImageTextures[iImg]);
|
||||
}
|
||||
|
||||
for (u32 iLog = 0; iLog < mLogbookAssets.size(); iLog++)
|
||||
pTree->AddDependency(mLogbookAssets[iLog]);
|
||||
else if (Game() <= eEchoes)
|
||||
{
|
||||
pTree->AddDependency(mPostOverrideTexture);
|
||||
pTree->AddDependency(mLogbookModel);
|
||||
pTree->AddCharacterDependency(mLogbookAnimParams);
|
||||
pTree->AddCharacterDependency(mUnknownAnimParams);
|
||||
|
||||
for (u32 iSec = 0; iSec < mSecondaryModels.size(); iSec++)
|
||||
{
|
||||
const SScanInfoSecondaryModel& rkSecModel = mSecondaryModels[iSec];
|
||||
pTree->AddDependency(rkSecModel.ModelID);
|
||||
pTree->AddCharacterDependency(rkSecModel.AnimParams);
|
||||
}
|
||||
}
|
||||
|
||||
return pTree;
|
||||
}
|
||||
|
||||
EGame Version() const { return mVersion; }
|
||||
CStringTable* ScanText() const { return mpStringTable; }
|
||||
bool IsImportant() const { return mIsImportant; }
|
||||
bool IsSlow() const { return mIsSlow; }
|
||||
|
||||
@@ -200,10 +200,11 @@ void CAreaCooker::WritePrimeSCLY(IOutputStream& rOut)
|
||||
// SCGN
|
||||
if (mVersion == eEchoesDemo)
|
||||
{
|
||||
rOut.WriteString("SCGN", 4);
|
||||
// IMPORTANT TODO - REGENERATE SCGN LAYER
|
||||
/*rOut.WriteString("SCGN", 4);
|
||||
rOut.WriteByte(1);
|
||||
CScriptCooker::WriteLayer(mVersion, mpArea->mpGeneratorLayer, rOut);
|
||||
FinishSection(false);
|
||||
FinishSection(false);*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,9 +221,10 @@ void CAreaCooker::WriteEchoesSCLY(IOutputStream& rOut)
|
||||
}
|
||||
|
||||
// SCGN
|
||||
// IMPORTANT TODO - REGENERATE SCGN
|
||||
rOut.WriteString("SCGN", 4);
|
||||
rOut.WriteByte(0x1);
|
||||
CScriptCooker::WriteLayer(mVersion, mpArea->mpGeneratorLayer, rOut);
|
||||
//CScriptCooker::WriteLayer(mVersion, mpArea->mpGeneratorLayer, rOut);
|
||||
FinishSection(true);
|
||||
}
|
||||
|
||||
@@ -276,7 +278,7 @@ void CAreaCooker::FinishBlock()
|
||||
|
||||
if (EnableCompression)
|
||||
{
|
||||
bool Success = CompressionUtil::CompressSegmentedData((u8*) mCompressedData.Data(), mCompressedData.Size(), CompressedBuf.data(), CompressedSize, UseZlib);
|
||||
bool Success = CompressionUtil::CompressSegmentedData((u8*) mCompressedData.Data(), mCompressedData.Size(), CompressedBuf.data(), CompressedSize, UseZlib, true);
|
||||
u32 PadBytes = (32 - (CompressedSize % 32)) & 0x1F;
|
||||
WriteCompressedData = Success && (CompressedSize + PadBytes < (u32) mCompressedData.Size());
|
||||
}
|
||||
|
||||
@@ -141,6 +141,10 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
|
||||
for (u32 iOff = 0; iOff < ModuleLayerOffsets.size(); iOff++)
|
||||
rMLVL.WriteLong(ModuleLayerOffsets[iOff]);
|
||||
}
|
||||
|
||||
// Internal Name
|
||||
if (Game >= eEchoesDemo)
|
||||
rMLVL.WriteString(rArea.InternalName.ToStdString());
|
||||
}
|
||||
|
||||
if (Game <= eCorruption)
|
||||
|
||||
@@ -33,7 +33,7 @@ CAnimSet* CAnimSetLoader::LoadReturnsCHAR(IInputStream& rCHAR)
|
||||
return pSet;
|
||||
}
|
||||
|
||||
void CAnimSetLoader::LoadPASDatabase(IInputStream& rPAS4, SSetCharacter *pChar)
|
||||
void CAnimSetLoader::LoadPASDatabase(IInputStream& rPAS4)
|
||||
{
|
||||
// For now, just parse the data; don't store it
|
||||
rPAS4.Seek(0x4, SEEK_CUR); // Skipping PAS4 FourCC
|
||||
@@ -68,11 +68,7 @@ void CAnimSetLoader::LoadPASDatabase(IInputStream& rPAS4, SSetCharacter *pChar)
|
||||
}
|
||||
|
||||
for (u32 iInfo = 0; iInfo < AnimInfoCount; iInfo++)
|
||||
{
|
||||
u32 MetaAnimID = rPAS4.ReadLong();
|
||||
rPAS4.Seek(Skip, SEEK_CUR);
|
||||
pChar->UsedAnimationIndices.insert(MetaAnimID);
|
||||
}
|
||||
rPAS4.Seek(0x4 + Skip, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,7 +317,7 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
||||
}
|
||||
|
||||
// PAS Database
|
||||
Loader.LoadPASDatabase(rANCS, pChar);
|
||||
Loader.LoadPASDatabase(rANCS);
|
||||
|
||||
// Particles
|
||||
u32 ParticleCount = rANCS.ReadLong();
|
||||
@@ -394,7 +390,8 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
|
||||
|
||||
if (Loader.mVersion == eEchoes)
|
||||
{
|
||||
rANCS.Seek(0x5, SEEK_CUR);
|
||||
pChar->SpatialPrimitives = rANCS.ReadLong();
|
||||
rANCS.Seek(0x1, SEEK_CUR);
|
||||
u32 UnknownCount2 = rANCS.ReadLong();
|
||||
rANCS.Seek(UnknownCount2 * 0x1C, SEEK_CUR);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class CAnimSetLoader
|
||||
CAnimSetLoader();
|
||||
CAnimSet* LoadCorruptionCHAR(IInputStream& rCHAR);
|
||||
CAnimSet* LoadReturnsCHAR(IInputStream& rCHAR);
|
||||
void LoadPASDatabase(IInputStream& rPAS4, SSetCharacter *pChar);
|
||||
void LoadPASDatabase(IInputStream& rPAS4);
|
||||
|
||||
void LoadAnimationSet(IInputStream& rANCS);
|
||||
void ProcessPrimitives();
|
||||
|
||||
@@ -158,9 +158,8 @@ void CAreaLoader::ReadSCLYPrime()
|
||||
|
||||
if (pLayer)
|
||||
{
|
||||
mpArea->mpGeneratorLayer = pLayer;
|
||||
pLayer->SetName("Generated Objects");
|
||||
pLayer->SetActive(true);
|
||||
MergeGeneratedLayer(pLayer);
|
||||
delete pLayer;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,6 +310,7 @@ void CAreaLoader::ReadSCLYEchoes()
|
||||
}
|
||||
|
||||
// SCGN
|
||||
// we want to regenerate the SCGN layer on cook - for now just move everything back to its original layer
|
||||
CFourCC SCGN(*mpMREA);
|
||||
if (SCGN != "SCGN")
|
||||
{
|
||||
@@ -319,12 +319,12 @@ void CAreaLoader::ReadSCLYEchoes()
|
||||
}
|
||||
|
||||
mpMREA->Seek(0x1, SEEK_CUR); // Skipping unknown
|
||||
mpArea->mpGeneratorLayer = CScriptLoader::LoadLayer(*mpMREA, mpArea, mVersion);
|
||||
CScriptLayer *pGeneratedLayer = CScriptLoader::LoadLayer(*mpMREA, mpArea, mVersion);
|
||||
|
||||
if (mpArea->mpGeneratorLayer)
|
||||
if (pGeneratedLayer)
|
||||
{
|
||||
mpArea->mpGeneratorLayer->SetName("Generated Objects");
|
||||
mpArea->mpGeneratorLayer->SetActive(true);
|
||||
MergeGeneratedLayer(pGeneratedLayer);
|
||||
delete pGeneratedLayer;
|
||||
}
|
||||
|
||||
SetUpObjects();
|
||||
@@ -606,19 +606,37 @@ void CAreaLoader::ReadEGMC()
|
||||
mpArea->mpPoiToWorldMap = gpResourceStore->LoadResource(EGMC, "EGMC");
|
||||
}
|
||||
|
||||
void CAreaLoader::SetUpObjects()
|
||||
void CAreaLoader::MergeGeneratedLayer(CScriptLayer *pLayer)
|
||||
{
|
||||
// Iterate over all objects
|
||||
for (u32 iLyr = 0; iLyr < mpArea->NumScriptLayers() + 1; iLyr++)
|
||||
while (pLayer->NumInstances() != 0)
|
||||
{
|
||||
CScriptLayer *pLayer;
|
||||
if (iLyr < mpArea->NumScriptLayers()) pLayer = mpArea->mScriptLayers[iLyr];
|
||||
CScriptObject *pObj = pLayer->InstanceByIndex(0);
|
||||
u32 InstanceID = pObj->InstanceID();
|
||||
|
||||
// Check if this is a duplicate of an existing instance (this only happens with DKCR GenericCreature as far as I'm aware)
|
||||
CScriptObject *pDupe = mpArea->InstanceByID(InstanceID);
|
||||
|
||||
if (pDupe)
|
||||
{
|
||||
Log::Write("Duplicate SCGN object: [" + pObj->Template()->Name() + "] " + pObj->InstanceName() + " (" + TString::HexString(pObj->InstanceID(), 8, false) + ")");
|
||||
pLayer->RemoveInstance(pObj);
|
||||
delete pObj;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
pLayer = mpArea->GeneratedObjectsLayer();
|
||||
if (!pLayer) break;
|
||||
u32 LayerIdx = (InstanceID >> 26) & 0x3F;
|
||||
pObj->SetLayer( mpArea->ScriptLayer(LayerIdx) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CAreaLoader::SetUpObjects()
|
||||
{
|
||||
// Iterate over all objects
|
||||
for (u32 iLyr = 0; iLyr < mpArea->NumScriptLayers(); iLyr++)
|
||||
{
|
||||
CScriptLayer *pLayer = mpArea->mScriptLayers[iLyr];
|
||||
|
||||
for (u32 iObj = 0; iObj < pLayer->NumInstances(); iObj++)
|
||||
{
|
||||
|
||||
@@ -78,6 +78,7 @@ class CAreaLoader
|
||||
void ReadPATH();
|
||||
void ReadPTLA();
|
||||
void ReadEGMC();
|
||||
void MergeGeneratedLayer(CScriptLayer *pLayer);
|
||||
void SetUpObjects();
|
||||
|
||||
public:
|
||||
|
||||
@@ -27,28 +27,33 @@ CAudioGroup* CAudioGroupLoader::LoadAGSC(IInputStream& rAGSC, CResourceEntry *pE
|
||||
}
|
||||
|
||||
// Read needed data from the Proj chunk
|
||||
u32 ProjStart = rAGSC.Tell();
|
||||
rAGSC.Seek(0x4, SEEK_CUR);
|
||||
u16 GroupID = rAGSC.ReadShort();
|
||||
u16 GroupType = rAGSC.ReadShort();
|
||||
rAGSC.Seek(0x14, SEEK_CUR);
|
||||
u32 SfxTableStart = rAGSC.ReadLong();
|
||||
u16 Peek = rAGSC.PeekShort();
|
||||
|
||||
if (Game == ePrime)
|
||||
pOut->mGroupID = GroupID;
|
||||
else
|
||||
ASSERT(pOut->mGroupID == GroupID);
|
||||
|
||||
if (GroupType == 1)
|
||||
if (Peek != 0xFFFF)
|
||||
{
|
||||
rAGSC.Seek(ProjStart + SfxTableStart, SEEK_SET);
|
||||
u16 NumSounds = rAGSC.ReadShort();
|
||||
rAGSC.Seek(0x2, SEEK_CUR);
|
||||
u32 ProjStart = rAGSC.Tell();
|
||||
rAGSC.Seek(0x4, SEEK_CUR);
|
||||
u16 GroupID = rAGSC.ReadShort();
|
||||
u16 GroupType = rAGSC.ReadShort();
|
||||
rAGSC.Seek(0x14, SEEK_CUR);
|
||||
u32 SfxTableStart = rAGSC.ReadLong();
|
||||
|
||||
for (u32 iSfx = 0; iSfx < NumSounds; iSfx++)
|
||||
if (Game == ePrime)
|
||||
pOut->mGroupID = GroupID;
|
||||
else
|
||||
ASSERT(pOut->mGroupID == GroupID);
|
||||
|
||||
if (GroupType == 1)
|
||||
{
|
||||
pOut->mDefineIDs.push_back( rAGSC.ReadShort() );
|
||||
rAGSC.Seek(0x8, SEEK_CUR);
|
||||
rAGSC.Seek(ProjStart + SfxTableStart, SEEK_SET);
|
||||
u16 NumSounds = rAGSC.ReadShort();
|
||||
rAGSC.Seek(0x2, SEEK_CUR);
|
||||
|
||||
for (u32 iSfx = 0; iSfx < NumSounds; iSfx++)
|
||||
{
|
||||
pOut->mDefineIDs.push_back( rAGSC.ReadShort() );
|
||||
rAGSC.Seek(0x8, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,9 +75,10 @@ CStringList* CAudioGroupLoader::LoadSTLC(IInputStream& rSTLC, CResourceEntry *pE
|
||||
{
|
||||
CStringList *pOut = new CStringList(pEntry);
|
||||
u32 NumStrings = rSTLC.ReadLong();
|
||||
pOut->mStringList.reserve(NumStrings);
|
||||
|
||||
for (u32 iStr = 0; iStr < NumStrings; iStr++)
|
||||
pOut->mStringList[iStr] = rSTLC.ReadString();
|
||||
pOut->mStringList.push_back( rSTLC.ReadString() );
|
||||
|
||||
return pOut;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ CScan* CScanLoader::LoadScanMP1(IInputStream& rSCAN)
|
||||
rSCAN.Seek(0x18, SEEK_CUR);
|
||||
}
|
||||
|
||||
mpScan->mVersion = ePrime;
|
||||
mpScan->SetGame(ePrime);
|
||||
return mpScan;
|
||||
}
|
||||
|
||||
@@ -67,26 +67,29 @@ CScan* CScanLoader::LoadScanMP2(IInputStream& rSCAN)
|
||||
case 0xB:
|
||||
mpScan = new CScan(mpEntry);
|
||||
mpScan->SetGame(eEchoes);
|
||||
LoadParamsMP2(rSCAN);
|
||||
LoadParamsMP2(rSCAN, NumProperties);
|
||||
break;
|
||||
case 0x12:
|
||||
case 0x16:
|
||||
mpScan = new CScan(mpEntry);
|
||||
mpScan->SetGame(eCorruption);
|
||||
LoadParamsMP3(rSCAN);
|
||||
LoadParamsMP3(rSCAN, NumProperties);
|
||||
break;
|
||||
default:
|
||||
Log::FileError(rSCAN.GetSourceString(), rSCAN.Tell() - 2, "Invalid SNFO property count: " + TString::HexString(NumProperties));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mpScan->SetGame(eEchoes);
|
||||
return mpScan;
|
||||
}
|
||||
|
||||
void CScanLoader::LoadParamsMP2(IInputStream& rSCAN)
|
||||
void CScanLoader::LoadParamsMP2(IInputStream& rSCAN, u16 NumProperties)
|
||||
{
|
||||
// Function begins after the SNFO property count
|
||||
for (u32 iProp = 0; iProp < 20; iProp++)
|
||||
mpScan->mSecondaryModels.resize(9);
|
||||
|
||||
for (u32 iProp = 0; iProp < NumProperties; iProp++)
|
||||
{
|
||||
u32 PropertyID = rSCAN.ReadLong();
|
||||
u16 PropertySize = rSCAN.ReadShort();
|
||||
@@ -103,39 +106,75 @@ void CScanLoader::LoadParamsMP2(IInputStream& rSCAN)
|
||||
break;
|
||||
|
||||
case 0x7B714814:
|
||||
mpScan->mIsImportant = (rSCAN.ReadByte() != 0);
|
||||
mpScan->mIsImportant = rSCAN.ReadBool();
|
||||
break;
|
||||
|
||||
case 0x1733B1EC:
|
||||
mpScan->mUseLogbookModelPostScan = rSCAN.ReadBool();
|
||||
break;
|
||||
|
||||
// Override texture and logbook model/animsets
|
||||
case 0x53336141:
|
||||
case 0xB7ADC418:
|
||||
case 0x15694EE1:
|
||||
case 0x58F9FE99:
|
||||
mpScan->mLogbookAssets.push_back( CAssetID(rSCAN, eEchoes) );
|
||||
mpScan->mPostOverrideTexture = CAssetID(rSCAN, mVersion);
|
||||
break;
|
||||
|
||||
case 0x3DE0BA64:
|
||||
mpScan->mLogbookDefaultRotX = rSCAN.ReadFloat();
|
||||
break;
|
||||
|
||||
case 0x2ADD6628:
|
||||
mpScan->mLogbookDefaultRotZ = rSCAN.ReadFloat();
|
||||
break;
|
||||
|
||||
case 0xD0C15066:
|
||||
mpScan->mLogbookScale = rSCAN.ReadFloat();
|
||||
break;
|
||||
|
||||
case 0xB7ADC418:
|
||||
mpScan->mLogbookModel = CAssetID(rSCAN, mVersion);
|
||||
break;
|
||||
|
||||
case 0x15694EE1:
|
||||
mpScan->mLogbookAnimParams = CAnimationParameters(rSCAN, mVersion);
|
||||
break;
|
||||
|
||||
case 0x58F9FE99:
|
||||
mpScan->mUnknownAnimParams = CAnimationParameters(rSCAN, mVersion);
|
||||
break;
|
||||
|
||||
// ScanInfoSecondaryModels
|
||||
case 0x1C5B4A3A:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[0] );
|
||||
break;
|
||||
|
||||
case 0x8728A0EE:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[1] );
|
||||
break;
|
||||
|
||||
case 0xF1CD99D3:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[2] );
|
||||
break;
|
||||
|
||||
case 0x6ABE7307:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[3] );
|
||||
break;
|
||||
|
||||
case 0x1C07EBA9:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[4] );
|
||||
break;
|
||||
|
||||
case 0x8774017D:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[5] );
|
||||
break;
|
||||
|
||||
case 0xF1913840:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[6] );
|
||||
break;
|
||||
|
||||
case 0x6AE2D294:
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[7] );
|
||||
break;
|
||||
|
||||
case 0x1CE2091C:
|
||||
u16 NumSubProps = rSCAN.ReadShort();
|
||||
|
||||
for (u32 iSub = 0; iSub < NumSubProps; iSub++)
|
||||
{
|
||||
u32 SubPropertyID = rSCAN.ReadLong();
|
||||
u32 Next = rSCAN.Tell() + rSCAN.ReadShort();
|
||||
|
||||
if (SubPropertyID == 0x1F7921BC || SubPropertyID == 0xCDD202D1)
|
||||
mpScan->mLogbookAssets.push_back( CAssetID(rSCAN, eEchoes) );
|
||||
|
||||
rSCAN.Seek(Next, SEEK_SET);
|
||||
}
|
||||
LoadScanInfoSecondaryModel( rSCAN, mpScan->mSecondaryModels[8] );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -143,15 +182,12 @@ void CScanLoader::LoadParamsMP2(IInputStream& rSCAN)
|
||||
}
|
||||
|
||||
mpScan->mCategory = CScan::eNone;
|
||||
mpScan->mVersion = eEchoes;
|
||||
}
|
||||
|
||||
void CScanLoader::LoadParamsMP3(IInputStream& rSCAN)
|
||||
void CScanLoader::LoadParamsMP3(IInputStream& rSCAN, u16 NumProperties)
|
||||
{
|
||||
// Function begins after the SNFO property count
|
||||
// Function is near-identical to the MP2 one, but when I add support
|
||||
// for the other params, there will be more differences
|
||||
for (u32 iProp = 0; iProp < 20; iProp++)
|
||||
for (u32 iProp = 0; iProp < NumProperties; iProp++)
|
||||
{
|
||||
u32 PropertyID = rSCAN.ReadLong();
|
||||
u16 PropertySize = rSCAN.ReadShort();
|
||||
@@ -176,7 +212,35 @@ void CScanLoader::LoadParamsMP3(IInputStream& rSCAN)
|
||||
}
|
||||
|
||||
mpScan->mCategory = CScan::eNone;
|
||||
mpScan->mVersion = eCorruption;
|
||||
}
|
||||
|
||||
void CScanLoader::LoadScanInfoSecondaryModel(IInputStream& rSCAN, CScan::SScanInfoSecondaryModel& rSecondaryModel)
|
||||
{
|
||||
u16 NumProperties = rSCAN.ReadShort();
|
||||
|
||||
for (u32 iProp = 0; iProp < NumProperties; iProp++)
|
||||
{
|
||||
u32 PropertyID = rSCAN.ReadLong();
|
||||
u16 PropertySize = rSCAN.ReadShort();
|
||||
u32 Next = rSCAN.Tell() + PropertySize;
|
||||
|
||||
switch (PropertyID)
|
||||
{
|
||||
case 0x1F7921BC:
|
||||
rSecondaryModel.ModelID = CAssetID(rSCAN, mVersion);
|
||||
break;
|
||||
|
||||
case 0xCDD202D1:
|
||||
rSecondaryModel.AnimParams = CAnimationParameters(rSCAN, mVersion);
|
||||
break;
|
||||
|
||||
case 0x3EA2BED8:
|
||||
rSecondaryModel.AttachBoneName = rSCAN.ReadString();
|
||||
break;
|
||||
}
|
||||
|
||||
rSCAN.Seek(Next, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
// ************ STATIC/PUBLIC ************
|
||||
|
||||
@@ -13,8 +13,9 @@ class CScanLoader
|
||||
CScanLoader();
|
||||
CScan* LoadScanMP1(IInputStream& rSCAN);
|
||||
CScan* LoadScanMP2(IInputStream& rSCAN);
|
||||
void LoadParamsMP2(IInputStream& rSCAN);
|
||||
void LoadParamsMP3(IInputStream& rSCAN);
|
||||
void LoadParamsMP2(IInputStream& rSCAN, u16 NumProperties);
|
||||
void LoadParamsMP3(IInputStream& rSCAN, u16 NumProperties);
|
||||
void LoadScanInfoSecondaryModel(IInputStream& rSCAN, CScan::SScanInfoSecondaryModel& rSecondaryModel);
|
||||
|
||||
public:
|
||||
static CScan* LoadSCAN(IInputStream& rSCAN, CResourceEntry *pEntry);
|
||||
|
||||
@@ -59,7 +59,7 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY
|
||||
|
||||
u32 Check = pBitfieldCast->Get() & ~Mask;
|
||||
if (Check != 0)
|
||||
Log::FileWarning(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Bitfield property \"" + pBitfieldTemp->Name() + "\" in struct \"" + pTemp->Name() + "\" has flags set that aren't in the template: " + TString::HexString(Check));
|
||||
Log::FileWarning(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Bitfield property \"" + pBitfieldTemp->FullName() + "\" + (" + pBitfieldTemp->IDString(true) + ") has flags set that aren't in the template: " + TString::HexString(Check));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -72,7 +72,7 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY
|
||||
|
||||
// Validate
|
||||
u32 Index = pEnumTemp->EnumeratorIndex(ID);
|
||||
if (Index == -1) Log::FileError(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Enum property \"" + pEnumTemp->Name() + "\" in struct \"" + pTemp->Name() + "\" has invalid enumerator value: " + TString::HexString(ID));
|
||||
if (Index == -1) Log::FileError(rSCLY.GetSourceString(), rSCLY.Tell() - 4, "Enum property \"" + pEnumTemp->FullName() + "\" (" + pEnumTemp->IDString(true) + ") has invalid enumerator value: " + TString::HexString(ID));
|
||||
|
||||
pEnumCast->Set(ID);
|
||||
break;
|
||||
@@ -140,7 +140,7 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY
|
||||
}
|
||||
|
||||
if (!Valid)
|
||||
Log::FileWarning(rSCLY.GetSourceString(), rSCLY.Tell() - ID.Length(), "Asset property " + pTemp->IDString(true) + " in object " + pTemp->ScriptTemplate()->Name() + " has a reference to an illegal asset type: " + CookedExt);
|
||||
Log::FileWarning(rSCLY.GetSourceString(), rSCLY.Tell() - ID.Length(), "Asset property \"" + pTemp->FullName() + "\" (" + pTemp->IDString(true) + ") has a reference to an illegal asset type: " + CookedExt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ void CScriptLoader::LoadStructMP1(IInputStream& rSCLY, CPropertyStruct *pStruct,
|
||||
TIDString IDString = pTemp->IDString(true);
|
||||
if (!IDString.IsEmpty()) IDString = " (" + IDString + ")";
|
||||
|
||||
Log::FileWarning(rSCLY.GetSourceString(), StructStart, "Struct \"" + pTemp->Name() + "\"" + IDString + " template prop count doesn't match file; template is " + TString::HexString(PropCount, 2) + ", file is " + TString::HexString(FilePropCount, 2));
|
||||
Log::FileWarning(rSCLY.GetSourceString(), StructStart, "Struct \"" + pTemp->FullName() + "\" (" + IDString + ") template prop count doesn't match file; template is " + TString::HexString(PropCount, 2) + ", file is " + TString::HexString(FilePropCount, 2));
|
||||
Version = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ IPropertyTemplate* CTemplateLoader::LoadProperty(XMLElement *pElem, CScriptTempl
|
||||
pParams = pParams->NextSiblingElement();
|
||||
}
|
||||
|
||||
// File-specific parameters
|
||||
// Asset-specific parameters
|
||||
if (Type == eAssetProperty)
|
||||
{
|
||||
TString ExtensionsAttr = pElem->Attribute("extensions");
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define CSCRIPTLAYER_H
|
||||
|
||||
#include "CScriptObject.h"
|
||||
#include "Core/Resource/CDependencyGroup.h"
|
||||
#include <Common/types.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -107,9 +108,6 @@ public:
|
||||
return iLyr;
|
||||
}
|
||||
|
||||
if (mpArea->GeneratedObjectsLayer() == this)
|
||||
return mpArea->NumScriptLayers();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,11 +70,13 @@ bool CScriptObject::IsEditorProperty(IProperty *pProp)
|
||||
|
||||
void CScriptObject::SetLayer(CScriptLayer *pLayer, u32 NewLayerIndex)
|
||||
{
|
||||
ASSERT(pLayer != nullptr);
|
||||
|
||||
if (pLayer != mpLayer)
|
||||
{
|
||||
if (mpLayer) mpLayer->RemoveInstance(this);
|
||||
mpLayer = pLayer;
|
||||
if (mpLayer) mpLayer->AddInstance(this, NewLayerIndex);
|
||||
mpLayer->AddInstance(this, NewLayerIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,20 +20,25 @@ bool IPropertyTemplate::IsInVersion(u32 Version) const
|
||||
return false;
|
||||
}
|
||||
|
||||
TString IPropertyTemplate::FullName() const
|
||||
{
|
||||
return mpParent ? mpParent->FullName() + "::" + Name() : Name();
|
||||
}
|
||||
|
||||
TIDString IPropertyTemplate::IDString(bool FullPath) const
|
||||
{
|
||||
if (mID != 0xFFFFFFFF)
|
||||
{
|
||||
TIDString out;
|
||||
TIDString Out;
|
||||
|
||||
if (mpParent && FullPath)
|
||||
{
|
||||
out = mpParent->IDString(true);
|
||||
if (!out.IsEmpty()) out += ":";
|
||||
Out = mpParent->IDString(true);
|
||||
if (!Out.IsEmpty()) Out += ":";
|
||||
}
|
||||
|
||||
out += TIDString::HexString(mID);
|
||||
return out;
|
||||
Out += TIDString::HexString(mID);
|
||||
return Out;
|
||||
}
|
||||
else return "";
|
||||
}
|
||||
|
||||
@@ -113,6 +113,7 @@ public:
|
||||
|
||||
EGame Game() const;
|
||||
bool IsInVersion(u32 Version) const;
|
||||
TString FullName() const;
|
||||
TIDString IDString(bool FullPath) const;
|
||||
bool IsDescendantOf(const CStructTemplate *pStruct) const;
|
||||
bool IsFromStructTemplate() const;
|
||||
|
||||
@@ -217,16 +217,6 @@ void CScene::SetActiveArea(CGameArea *pArea)
|
||||
}
|
||||
}
|
||||
|
||||
CScriptLayer *pGenLayer = mpArea->GeneratedObjectsLayer();
|
||||
if (pGenLayer)
|
||||
{
|
||||
for (u32 iObj = 0; iObj < pGenLayer->NumInstances(); iObj++)
|
||||
{
|
||||
CScriptObject *pObj = pGenLayer->InstanceByIndex(iObj);
|
||||
CreateScriptNode(pObj);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure script nodes have valid positions + build light lists
|
||||
for (CSceneIterator It(this, eScriptNode, true); It; ++It)
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ CCreateInstanceCommand::CCreateInstanceCommand(CWorldEditor *pEditor, CScriptTem
|
||||
, mpNewInstance(nullptr)
|
||||
, mpNewNode(nullptr)
|
||||
{
|
||||
ASSERT(mLayerIndex != -1);
|
||||
}
|
||||
|
||||
void CCreateInstanceCommand::undo()
|
||||
@@ -30,7 +31,7 @@ void CCreateInstanceCommand::redo()
|
||||
{
|
||||
mpEditor->NotifyNodeAboutToBeSpawned();
|
||||
|
||||
CScriptLayer *pLayer = (mLayerIndex == -1 ? mpArea->GeneratedObjectsLayer() : mpArea->ScriptLayer(mLayerIndex));
|
||||
CScriptLayer *pLayer = mpArea->ScriptLayer(mLayerIndex);
|
||||
CScriptObject *pNewInst = mpArea->SpawnInstance(mpTemplate, pLayer, mSpawnPosition);
|
||||
CScriptNode *pNewNode = mpScene->CreateScriptNode(pNewInst);
|
||||
pNewNode->SetPosition(mSpawnPosition);
|
||||
|
||||
@@ -45,7 +45,7 @@ void WScanPreviewPanel::SetResource(CResource *pRes)
|
||||
ui->ScanTypeLabel->setText("<b><font color=\"red\">Important</font></b>");
|
||||
else
|
||||
{
|
||||
if (pScan->Version() <= ePrime)
|
||||
if (pScan->Game() <= ePrime)
|
||||
ui->ScanTypeLabel->setText("<b><font color=\"#FF9030\">Normal</font></b>");
|
||||
else
|
||||
ui->ScanTypeLabel->setText("<b><font color=\"#A0A0FF\">Normal</font></b>");
|
||||
@@ -81,7 +81,7 @@ void WScanPreviewPanel::SetResource(CResource *pRes)
|
||||
ui->ScanTextWidget->SetResource(pScan->ScanText());
|
||||
|
||||
// Show logbook category? (Yes on MP1, no on MP2+)
|
||||
if (pScan->Version() <= ePrime)
|
||||
if (pScan->Game() <= ePrime)
|
||||
{
|
||||
ui->CategoryInfoLabel->show();
|
||||
ui->ScanCategoryLabel->show();
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
#include "Editor/UICommon.h"
|
||||
#include <Core/Resource/Script/CScriptLayer.h>
|
||||
|
||||
CLayerModel::CLayerModel(QObject *pParent) : QAbstractListModel(pParent)
|
||||
CLayerModel::CLayerModel(QObject *pParent)
|
||||
: QAbstractListModel(pParent)
|
||||
, mpArea(nullptr)
|
||||
{
|
||||
mpArea = nullptr;
|
||||
mHasGenerateLayer = false;
|
||||
}
|
||||
|
||||
CLayerModel::~CLayerModel()
|
||||
@@ -14,9 +14,7 @@ CLayerModel::~CLayerModel()
|
||||
|
||||
int CLayerModel::rowCount(const QModelIndex& /*parent*/) const
|
||||
{
|
||||
if (!mpArea) return 0;
|
||||
if (mHasGenerateLayer) return mpArea->NumScriptLayers() + 1;
|
||||
else return mpArea->NumScriptLayers();
|
||||
return mpArea ? mpArea->NumScriptLayers() : 0;
|
||||
}
|
||||
|
||||
QVariant CLayerModel::data(const QModelIndex &index, int role) const
|
||||
@@ -30,7 +28,6 @@ QVariant CLayerModel::data(const QModelIndex &index, int role) const
|
||||
void CLayerModel::SetArea(CGameArea *pArea)
|
||||
{
|
||||
mpArea = pArea;
|
||||
mHasGenerateLayer = (pArea->GeneratedObjectsLayer() != nullptr);
|
||||
emit layoutChanged();
|
||||
}
|
||||
|
||||
@@ -41,8 +38,6 @@ CScriptLayer* CLayerModel::Layer(const QModelIndex& index) const
|
||||
|
||||
if (index.row() < (int) NumLayers)
|
||||
return mpArea->ScriptLayer(index.row());
|
||||
if (mHasGenerateLayer && (index.row() == NumLayers))
|
||||
return mpArea->GeneratedObjectsLayer();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
class CLayerModel : public QAbstractListModel
|
||||
{
|
||||
TResPtr<CGameArea> mpArea;
|
||||
bool mHasGenerateLayer;
|
||||
|
||||
public:
|
||||
explicit CLayerModel(QObject *pParent = 0);
|
||||
|
||||
Reference in New Issue
Block a user