diff --git a/resources/ResourceCacheData.bin b/resources/ResourceCacheData.bin
deleted file mode 100644
index 905aa1cf..00000000
Binary files a/resources/ResourceCacheData.bin and /dev/null differ
diff --git a/resources/ResourceDatabase.xml b/resources/ResourceDatabase.xml
deleted file mode 100644
index 6754994b..00000000
--- a/resources/ResourceDatabase.xml
+++ /dev/null
@@ -1,505 +0,0 @@
-
-
-
-
-
-
- 08F992A8
- TXTR
- script/common/
- RandomRelay
-
-
- 0A11104B
- CMDL
- editor/
- TranslateX
-
-
- 0E04ED00
- TXTR
-
- LightAmbientMask
-
-
- 0EDB1C7A
- CMDL
- script/dkcr/
- Waypoint
-
-
- 0FB28A24
- TXTR
-
- LightAmbient
-
-
- 0FD29E3B
- CMDL
- script/common/
- Waypoint
-
-
- 115C21DD
- TXTR
- script/common/
- CameraFilterKeyframe
-
-
- 1C010ADC
- CMDL
- editor/
- TranslatePolyXY
-
-
- 1FFC7E43
- CMDL
- editor/
- RotateXYZ
-
-
- 2A14558D
- TXTR
- script/common/
- HUDMemo
-
-
- 2B75E193
- TXTR
- script/common/
- VisorFlare
-
-
- 31485556
- TXTR
- script/mp2/
- AdvancedCounter
-
-
- 31992094
- CMDL
- editor/
- TranslateY
-
-
- 32432719
- CMDL
- script/common/
- SpiderBallWaypoint
-
-
- 32C9F9D1
- TXTR
- script/common/
- StreamedAudio
-
-
- 3440526F
- CMDL
- editor/
- TranslateLinesXY
-
-
- 3A947189
- CMDL
- script/common/
- AIWaypoint
-
-
- 3C093300
- CMDL
- editor/
- ScaleXYZ
-
-
- 40969072
- TXTR
- script/common/
- AreaAttributes
-
-
- 43891B25
- CMDL
- editor/
- TranslatePolyXZ
-
-
- 43E9B0A9
- CMDL
- editor/
- ScaleX
-
-
- 4443279C
- TXTR
- script/common/
- CameraBlurKeyframe
-
-
- 4A2D76D1
- TXTR
- script/common/
- DamageableTrigger
-
-
- 4C3D3E7F
- TXTR
- script/common/
- GrapplePoint
-
-
- 4E133EF2
- TXTR
- script/common/
- SpiderBallAttractionSurface
-
-
- 57F8715F
- TXTR
- script/common/
- Dock
-
-
- 592130DD
- CMDL
- editor/
- TranslateZ
-
-
- 5BC862B8
- CMDL
- editor/
- TranslateLinesXZ
-
-
- 5D08CCF6
- TXTR
- script/mp3/
- WeaponGenerator
-
-
- 5F3B141B
- CMDL
-
- VolumeBox
-
-
- 61B511E5
- TXTR
-
- Checkerboard
-
-
- 6649251D
- CMDL
- script/common/
- Camera
-
-
- 6A17B38F
- TXTR
- script/common/
- Sound
-
-
- 6B1FABDD
- CMDL
-
- Cube
-
-
- 6B71C0F2
- CMDL
- editor/
- ScaleY
-
-
- 6C6CE7FE
- TXTR
-
- LightSpotMask
-
-
- 6D5BC167
- TXTR
- script/common/
- Effect
-
-
- 6DD88D5D
- CMDL
-
- RotationArrow
-
-
- 6E57F7E0
- CMDL
-
- VolumeCylinder
-
-
- 72978DCF
- TXTR
- script/common/
- Relay
-
-
- 791A7BFD
- CMDL
-
- SphereDoubleSided
-
-
- 7F494724
- CMDL
- editor/
- RotateX
-
-
- 81326A53
- CMDL
- editor/
- ScaleLinesYZ
-
-
- 825CDFA8
- CMDL
- editor/
- ScalePolyYZ
-
-
- 826C9800
- TXTR
- script/common/
- ColorModulate
-
-
- 85CE16D7
- TXTR
- script/common/
- StreamedMovie
-
-
- 875A6FD7
- TXTR
- script/common/
- PointOfInterest
-
-
- 9039791A
- TXTR
-
- LightDirectional
-
-
- 91437414
- CMDL
- script/common/
- CameraWaypoint
-
-
- 92F9D13B
- CMDL
- editor/
- ScaleZ
-
-
- 95261BB8
- CMDL
-
- WireSphere
-
-
- 968C405E
- TXTR
- script/common/
- SoundModifier
-
-
- 9FF04AA1
- TXTR
- script/common/
- Generator
-
-
- A6D1576D
- CMDL
- editor/
- RotateY
-
-
- A82A3F02
- TXTR
-
- LightSpot
-
-
- AC18950A
- TXTR
- script/common/
- RadialDamage
-
-
- B0D52FF7
- TXTR
-
- LightCustomMask
-
-
- B0E09096
- TXTR
-
- LightDirectionalMask
-
-
- B23F1022
- TXTR
- script/common/
- VisorGoo
-
-
- B2DBCAED
- TXTR
- script/common/
- PickupGenerator
-
-
- B3050E38
- TXTR
- script/common/
- SequenceTimer
-
-
- B97DB26B
- TXTR
- script/common/
- Timer
-
-
- BA7EA4F6
- TXTR
- script/common/
- Trigger
-
-
- C0FBED3D
- CMDL
- editor/
- ScaleLinesXY
-
-
- C2266292
- CMDL
- editor/
- ScalePolyXY
-
-
- C4E83425
- TXTR
- script/common/
- DistanceFog
-
-
- C7BEFE29
- CMDL
-
- VolumeSphere
-
-
- CB904B3D
- TXTR
- script/common/
- SpecialFunction
-
-
- CE5967B6
- CMDL
- editor/
- RotateZ
-
-
- D2F07DAF
- TXTR
- script/common/
- ConditionalRelay
-
-
- D7B6A50D
- CMDL
-
- Sphere
-
-
- DA185196
- TXTR
-
- VolumeCheckerboard
-
-
- DC3787F2
- CMDL
- editor/
- TranslatePolyYZ
-
-
- E1A0D860
- TXTR
- script/common/
- StreamedAudioModifier
-
-
- E883FD86
- CMDL
- editor/
- ScaleLinesXZ
-
-
- E9AE72DB
- CMDL
- editor/
- ScalePolyXZ
-
-
- EE340FC4
- TXTR
- script/common/
- MemoryRelay
-
-
- F476CF85
- CMDL
- editor/
- TranslateLinesYZ
-
-
- F76B369A
- TXTR
- script/common/
- Counter
-
-
- FB50DA78
- CMDL
- editor/
- RotateClipOutline
-
-
- FC8FA98B
- TXTR
-
- LightCustom
-
-
- FD78FBC8
- TXTR
- script/mp1/
- NewCameraShaker
-
-
- FFAC2525
- TXTR
- script/common/
- CameraShaker
-
-
-
diff --git a/src/Common/Flags.h b/src/Common/Flags.h
index 732b63a0..90b96b5a 100644
--- a/src/Common/Flags.h
+++ b/src/Common/Flags.h
@@ -7,7 +7,7 @@
template
class TFlags
{
- int mValue;
+ u32 mValue;
public:
TFlags() : mValue(0) {}
diff --git a/src/Common/Serialization/CBasicBinaryReader.h b/src/Common/Serialization/CBasicBinaryReader.h
index 5bd849d4..6ebe724b 100644
--- a/src/Common/Serialization/CBasicBinaryReader.h
+++ b/src/Common/Serialization/CBasicBinaryReader.h
@@ -12,22 +12,27 @@
class CBasicBinaryReader : public IArchive
{
IInputStream *mpStream;
+ bool mMagicValid;
bool mOwnsStream;
public:
- CBasicBinaryReader(const TString& rkFilename, IOUtil::EEndianness = IOUtil::eLittleEndian)
+ CBasicBinaryReader(const TString& rkFilename, u32 Magic)
: IArchive(true, false)
, mOwnsStream(true)
{
mpStream = new CFileInStream(rkFilename, IOUtil::eBigEndian);
- ASSERT(mpStream->IsValid());
- CSerialVersion Version(*mpStream);
- SetVersion(Version);
+ if (mpStream->IsValid())
+ {
+ mMagicValid = (mpStream->ReadLong() == Magic);
+ CSerialVersion Version(*mpStream);
+ SetVersion(Version);
+ }
}
CBasicBinaryReader(IInputStream *pStream, const CSerialVersion& rkVersion)
: IArchive(true, false)
+ , mMagicValid(true)
, mOwnsStream(false)
{
ASSERT(pStream->IsValid());
@@ -40,6 +45,8 @@ public:
if (mOwnsStream) delete mpStream;
}
+ inline bool IsValid() const { return mpStream->IsValid(); }
+
// Interface
virtual bool ParamBegin(const char*) { return true; }
virtual void ParamEnd() { }
diff --git a/src/Common/Serialization/CBasicBinaryWriter.h b/src/Common/Serialization/CBasicBinaryWriter.h
index 30da25e6..fe518906 100644
--- a/src/Common/Serialization/CBasicBinaryWriter.h
+++ b/src/Common/Serialization/CBasicBinaryWriter.h
@@ -11,20 +11,26 @@
class CBasicBinaryWriter : public IArchive
{
IOutputStream *mpStream;
+ u32 mMagic;
bool mOwnsStream;
public:
- CBasicBinaryWriter(const TString& rkFilename, u16 FileVersion, EGame Game = eUnknownGame, IOUtil::EEndianness = IOUtil::eLittleEndian)
+ CBasicBinaryWriter(const TString& rkFilename, u32 Magic, u16 FileVersion, EGame Game)
: IArchive(false, true)
+ , mMagic(Magic)
, mOwnsStream(true)
{
mpStream = new CFileOutStream(rkFilename, IOUtil::eBigEndian);
- ASSERT(mpStream->IsValid());
- SetVersion(skCurrentArchiveVersion, FileVersion, Game);
- GetVersionInfo().Write(*mpStream);
+
+ if (mpStream->IsValid())
+ {
+ mpStream->WriteLong(0); // Magic is written after the rest of the file is successfully saved
+ SetVersion(skCurrentArchiveVersion, FileVersion, Game);
+ GetVersionInfo().Write(*mpStream);
+ }
}
- CBasicBinaryWriter(IOutputStream *pStream, u16 FileVersion, EGame Game = eUnknownGame)
+ CBasicBinaryWriter(IOutputStream *pStream, u16 FileVersion, EGame Game)
: IArchive(false, true)
, mOwnsStream(false)
{
@@ -44,9 +50,17 @@ public:
~CBasicBinaryWriter()
{
- if (mOwnsStream) delete mpStream;
+ // Write magic and delete stream
+ if (mOwnsStream)
+ {
+ mpStream->GoTo(0);
+ mpStream->WriteLong(mMagic);
+ delete mpStream;
+ }
}
+ inline bool IsValid() const { return mpStream->IsValid(); }
+
// Interface
virtual bool ParamBegin(const char*) { return true; }
virtual void ParamEnd() { }
diff --git a/src/Common/Serialization/CBinaryReader.h b/src/Common/Serialization/CBinaryReader.h
index 62ac2298..f224d1d8 100644
--- a/src/Common/Serialization/CBinaryReader.h
+++ b/src/Common/Serialization/CBinaryReader.h
@@ -10,35 +10,40 @@ class CBinaryReader : public IArchive
struct SParameter
{
u32 Offset;
- u16 Size;
- u16 NumChildren;
- u16 ChildIndex;
+ u32 Size;
+ u32 NumChildren;
+ u32 ChildIndex;
bool Abstract;
};
std::vector mParamStack;
IInputStream *mpStream;
+ bool mMagicValid;
bool mOwnsStream;
public:
- CBinaryReader(const TString& rkFilename)
+ CBinaryReader(const TString& rkFilename, u32 Magic)
: IArchive(true, false)
, mOwnsStream(true)
{
mpStream = new CFileInStream(rkFilename, IOUtil::eBigEndian);
- ASSERT(mpStream->IsValid());
- CSerialVersion Version(*mpStream);
- SetVersion(Version);
+ if (mpStream->IsValid())
+ {
+ mMagicValid = (mpStream->ReadLong() == Magic);
+ CSerialVersion Version(*mpStream);
+ SetVersion(Version);
+ }
InitParamStack();
}
CBinaryReader(IInputStream *pStream, const CSerialVersion& rkVersion)
: IArchive(true, false)
+ , mMagicValid(true)
, mOwnsStream(false)
{
- ASSERT(pStream->IsValid());
+ ASSERT(pStream && pStream->IsValid());
mpStream = pStream;
SetVersion(rkVersion);
@@ -50,25 +55,32 @@ public:
if (mOwnsStream) delete mpStream;
}
+ inline bool IsValid() const { return mpStream->IsValid() && mMagicValid; }
+
private:
void InitParamStack()
{
mpStream->Skip(4); // Skip root ID (which is always -1)
- u16 Size = mpStream->ReadShort();
+ u32 Size = ReadSize();
u32 Offset = mpStream->Tell();
- u16 NumChildren = mpStream->ReadShort();
+ u32 NumChildren = ReadSize();
mParamStack.push_back( SParameter { Offset, Size, NumChildren, 0, false } );
mParamStack.reserve(20);
}
public:
// Interface
+ u32 ReadSize()
+ {
+ return (mArchiveVersion < eArVer_32BitBinarySize ? (u32) mpStream->ReadShort() : mpStream->ReadLong());
+ }
+
virtual bool ParamBegin(const char *pkName)
{
// If this is the parent parameter's first child, then read the child count
- if (mParamStack.back().NumChildren == 0xFFFF)
+ if (mParamStack.back().NumChildren == 0xFFFFFFFF)
{
- mParamStack.back().NumChildren = mpStream->ReadShort();
+ mParamStack.back().NumChildren = ReadSize();
}
// Save current offset
@@ -79,12 +91,12 @@ public:
if (mParamStack.back().ChildIndex < mParamStack.back().NumChildren)
{
u32 NextID = mpStream->ReadLong();
- u16 NextSize = mpStream->ReadShort();
+ u32 NextSize = ReadSize();
// Does the next parameter ID match the current one?
if (NextID == ParamID)
{
- mParamStack.push_back( SParameter { Offset, NextSize, 0xFFFF, 0, false } );
+ mParamStack.push_back( SParameter { mpStream->Tell(), NextSize, 0xFFFFFFFF, 0, false } );
return true;
}
}
@@ -94,20 +106,20 @@ public:
{
bool ParentAbstract = mParamStack.back().Abstract;
u32 ParentOffset = mParamStack.back().Offset;
- u16 NumChildren = mParamStack.back().NumChildren;
- mpStream->GoTo(ParentOffset + (ParentAbstract ? 0xC : 0x8));
+ u32 NumChildren = mParamStack.back().NumChildren;
+ mpStream->GoTo(ParentOffset + (ParentAbstract ? 4 : 0));
for (u32 ChildIdx = 0; ChildIdx < NumChildren; ChildIdx++)
{
u32 ChildID = mpStream->ReadLong();
- u16 ChildSize = mpStream->ReadShort();
+ u32 ChildSize = ReadSize();
if (ChildID != ParamID)
mpStream->Skip(ChildSize);
else
{
- mParamStack.back().ChildIndex = (u16) ChildIdx;
- mParamStack.push_back( SParameter { mpStream->Tell() - 6, ChildSize, 0xFFFF, 0, false } );
+ mParamStack.back().ChildIndex = ChildIdx;
+ mParamStack.push_back( SParameter { mpStream->Tell(), ChildSize, 0xFFFFFFFF, 0, false } );
return true;
}
}
@@ -122,7 +134,7 @@ public:
{
// Make sure we're at the end of the parameter
SParameter& rParam = mParamStack.back();
- u32 EndOffset = rParam.Offset + rParam.Size + 6;
+ u32 EndOffset = rParam.Offset + rParam.Size;
mpStream->GoTo(EndOffset);
mParamStack.pop_back();
@@ -134,7 +146,7 @@ public:
virtual void SerializeContainerSize(u32& rSize, const TString& /*rkElemName*/)
{
// Mostly handled by ParamBegin, we just need to return the size correctly so the container can be resized
- rSize = (u32) mpStream->PeekShort();
+ rSize = (mArchiveVersion < eArVer_32BitBinarySize ? (u32) mpStream->PeekShort() : mpStream->PeekLong());
}
virtual void SerializeAbstractObjectType(u32& rType)
diff --git a/src/Common/Serialization/CBinaryWriter.h b/src/Common/Serialization/CBinaryWriter.h
index 796c4c63..78ee6fec 100644
--- a/src/Common/Serialization/CBinaryWriter.h
+++ b/src/Common/Serialization/CBinaryWriter.h
@@ -9,32 +9,39 @@ class CBinaryWriter : public IArchive
struct SParameter
{
u32 Offset;
- u16 NumSubParams;
+ u32 NumSubParams;
bool Abstract;
};
std::vector mParamStack;
IOutputStream *mpStream;
+ u32 mMagic;
bool mOwnsStream;
public:
- CBinaryWriter(const TString& rkFilename, u16 FileVersion, EGame Game = eUnknownGame)
+ CBinaryWriter(const TString& rkFilename, u32 Magic, u16 FileVersion, EGame Game)
: IArchive(false, true)
+ , mMagic(Magic)
, mOwnsStream(true)
{
mpStream = new CFileOutStream(rkFilename, IOUtil::eBigEndian);
- ASSERT(mpStream->IsValid());
- SetVersion(skCurrentArchiveVersion, FileVersion, Game);
- GetVersionInfo().Write(*mpStream);
+ if (mpStream->IsValid())
+ {
+ mpStream->WriteLong(0); // Magic is written after the rest of the file has been successfully written
+ SetVersion(skCurrentArchiveVersion, FileVersion, Game);
+ GetVersionInfo().Write(*mpStream);
+ }
+
InitParamStack();
}
- CBinaryWriter(IOutputStream *pStream, u16 FileVersion, EGame Game = eUnknownGame)
+ CBinaryWriter(IOutputStream *pStream, u16 FileVersion, EGame Game)
: IArchive(false, true)
+ , mMagic(0)
, mOwnsStream(false)
{
- ASSERT(pStream->IsValid());
+ ASSERT(pStream && pStream->IsValid());
mpStream = pStream;
SetVersion(skCurrentArchiveVersion, FileVersion, Game);
InitParamStack();
@@ -42,9 +49,10 @@ public:
CBinaryWriter(IOutputStream *pStream, const CSerialVersion& rkVersion)
: IArchive(false, true)
+ , mMagic(0)
, mOwnsStream(false)
{
- ASSERT(pStream->IsValid());
+ ASSERT(pStream && pStream->IsValid());
mpStream = pStream;
SetVersion(rkVersion);
InitParamStack();
@@ -58,17 +66,23 @@ public:
// Finish root param
ParamEnd();
- // Delete stream
+ // Write magic and delete stream
if (mOwnsStream)
+ {
+ mpStream->GoTo(0);
+ mpStream->WriteLong(mMagic);
delete mpStream;
+ }
}
+ inline bool IsValid() const { return mpStream->IsValid(); }
+
private:
void InitParamStack()
{
mParamStack.reserve(20);
mpStream->WriteLong(0xFFFFFFFF);
- mpStream->WriteShort(0); // Size filler
+ mpStream->WriteLong(0); // Size filler
mParamStack.push_back( SParameter { mpStream->Tell(), 0, false } );
}
@@ -80,12 +94,12 @@ public:
mParamStack.back().NumSubParams++;
if (mParamStack.back().NumSubParams == 1)
- mpStream->WriteShort(-1); // Sub-param count filler
+ mpStream->WriteLong(-1); // Sub-param count filler
// Write param metadata
u32 ParamID = TString(pkName).Hash32();
mpStream->WriteLong(ParamID);
- mpStream->WriteShort((u16) 0xFFFF); // Param size filler
+ mpStream->WriteLong(-1); // Param size filler
// Add new param to the stack
mParamStack.push_back( SParameter { mpStream->Tell(), 0, false } );
@@ -99,16 +113,16 @@ public:
SParameter& rParam = mParamStack.back();
u32 StartOffset = rParam.Offset;
u32 EndOffset = mpStream->Tell();
- u16 ParamSize = (u16) (EndOffset - StartOffset);
+ u32 ParamSize = (EndOffset - StartOffset);
- mpStream->GoTo(StartOffset - 2);
- mpStream->WriteShort(ParamSize);
+ mpStream->GoTo(StartOffset - 4);
+ mpStream->WriteLong(ParamSize);
// Write param child count
if (rParam.NumSubParams > 0 || mParamStack.size() == 1)
{
if (rParam.Abstract) mpStream->Skip(4);
- mpStream->WriteShort(rParam.NumSubParams);
+ mpStream->WriteLong(rParam.NumSubParams);
}
mpStream->GoTo(EndOffset);
@@ -119,7 +133,7 @@ public:
{
// Normally handled by ParamBegin and ParamEnd but we need to do something here to account for zero-sized containers
if (rSize == 0)
- mpStream->WriteShort(0);
+ mpStream->WriteLong(0);
}
virtual void SerializeAbstractObjectType(u32& rType)
diff --git a/src/Common/Serialization/IArchive.h b/src/Common/Serialization/IArchive.h
index 18ec61ff..b7a871d3 100644
--- a/src/Common/Serialization/IArchive.h
+++ b/src/Common/Serialization/IArchive.h
@@ -178,7 +178,14 @@ protected:
bool mIsWriter;
public:
- static const u32 skCurrentArchiveVersion = 0;
+ enum EArchiveVersion
+ {
+ eArVer_Initial,
+ eArVer_32BitBinarySize,
+ // Insert new versions before this line
+ eArVer_Max
+ };
+ static const u32 skCurrentArchiveVersion = (eArVer_Max - 1);
IArchive(bool IsReader, bool IsWriter)
: mFileVersion(0)
diff --git a/src/Core/GameProject/CGameExporter.cpp b/src/Core/GameProject/CGameExporter.cpp
index 2875262e..91a90807 100644
--- a/src/Core/GameProject/CGameExporter.cpp
+++ b/src/Core/GameProject/CGameExporter.cpp
@@ -542,11 +542,11 @@ void CGameExporter::ExportResourceEditorData()
// All resources should have dependencies generated, so save the project files
SCOPED_TIMER(SaveResourceDatabase);
#if EXPORT_COOKED
- mpStore->SaveResourceDatabase();
+ bool ResDBSaveSuccess = mpStore->SaveDatabaseCache();
+ ASSERT(ResDBSaveSuccess);
#endif
- bool SaveSuccess = mpProject->Save();
- ASSERT(SaveSuccess);
- mpStore->SaveCacheFile();
+ bool ProjectSaveSuccess = mpProject->Save();
+ ASSERT(ProjectSaveSuccess);
}
}
diff --git a/src/Core/GameProject/CGameProject.cpp b/src/Core/GameProject/CGameProject.cpp
index 74b69bbe..6ad73368 100644
--- a/src/Core/GameProject/CGameProject.cpp
+++ b/src/Core/GameProject/CGameProject.cpp
@@ -9,7 +9,7 @@ CGameProject::~CGameProject()
{
if (mpResourceStore)
{
- ASSERT(!mpResourceStore->IsDirty());
+ ASSERT(!mpResourceStore->IsCacheDirty());
if (gpResourceStore == mpResourceStore)
gpResourceStore = nullptr;
@@ -238,7 +238,7 @@ CGameProject* CGameProject::LoadProject(const TString& rkProjPath, IProgressNoti
// Load resource database
pProgress->Report("Loading resource database");
pProj->mpResourceStore = new CResourceStore(pProj);
- LoadSuccess = pProj->mpResourceStore->LoadResourceDatabase();
+ LoadSuccess = pProj->mpResourceStore->LoadDatabaseCache();
// Validate resource database
if (LoadSuccess)
diff --git a/src/Core/GameProject/CResourceEntry.cpp b/src/Core/GameProject/CResourceEntry.cpp
index d355227a..fd4ef010 100644
--- a/src/Core/GameProject/CResourceEntry.cpp
+++ b/src/Core/GameProject/CResourceEntry.cpp
@@ -10,24 +10,70 @@
#include
#include
-CResourceEntry::CResourceEntry(CResourceStore *pStore, const CAssetID& rkID,
- const TString& rkDir, const TString& rkFilename,
- EResType Type)
+CResourceEntry::CResourceEntry(CResourceStore *pStore)
: mpResource(nullptr)
+ , mpTypeInfo(nullptr)
, mpStore(pStore)
, mpDependencies(nullptr)
- , mID(rkID)
+ , mID( CAssetID::InvalidID(pStore->Game()) )
, mpDirectory(nullptr)
- , mName(rkFilename)
, mMetadataDirty(false)
, mCachedSize(-1)
- , mCachedUppercaseName(rkFilename.ToUpper())
-{
- mpTypeInfo = CResTypeInfo::FindTypeInfo(Type);
- ASSERT(mpTypeInfo);
+{}
- mpDirectory = mpStore->GetVirtualDirectory(rkDir, true);
- if (mpDirectory) mpDirectory->AddChild("", this);
+// Static constructors
+CResourceEntry* CResourceEntry::CreateNewResource(CResourceStore *pStore, const CAssetID& rkID,
+ const TString& rkDir, const TString& rkName,
+ EResType Type)
+{
+ // Initialize all entry info with the input data.
+ CResourceEntry *pEntry = new CResourceEntry(pStore);
+ pEntry->mID = rkID;
+ pEntry->mName = rkName;
+ pEntry->mCachedUppercaseName = rkName.ToUpper();
+
+ pEntry->mpTypeInfo = CResTypeInfo::FindTypeInfo(Type);
+ ASSERT(pEntry->mpTypeInfo);
+
+ pEntry->mpDirectory = pStore->GetVirtualDirectory(rkDir, true);
+ ASSERT(pEntry->mpDirectory);
+ pEntry->mpDirectory->AddChild("", pEntry);
+
+ pEntry->mMetadataDirty = true;
+ return pEntry;
+}
+
+CResourceEntry* CResourceEntry::BuildFromArchive(CResourceStore *pStore, IArchive& rArc)
+{
+ // Load all entry info from the archive.
+ CResourceEntry *pEntry = new CResourceEntry(pStore);
+ pEntry->SerializeEntryInfo(rArc, false);
+ ASSERT(pEntry->mpTypeInfo);
+ ASSERT(pEntry->mpDirectory);
+ return pEntry;
+}
+
+CResourceEntry* CResourceEntry::BuildFromDirectory(CResourceStore *pStore, CResTypeInfo *pTypeInfo,
+ const TString& rkDirPath, const TString& rkName)
+{
+ // Initialize as much entry info as possible from the input data, then load the rest from the metadata file.
+ ASSERT(pTypeInfo);
+
+ CResourceEntry *pEntry = new CResourceEntry(pStore);
+ pEntry->mpTypeInfo = pTypeInfo;
+ pEntry->mName = rkName;
+ pEntry->mCachedUppercaseName = rkName.ToUpper();
+
+ pEntry->mpDirectory = pStore->GetVirtualDirectory(rkDirPath, true);
+ ASSERT(pEntry->mpDirectory);
+ pEntry->mpDirectory->AddChild("", pEntry);
+
+ // Make sure we're valid, then load the remaining data from the metadata file
+ ASSERT(pEntry->HasCookedVersion() || pEntry->HasRawVersion());
+ bool Success = pEntry->LoadMetadata();
+ ASSERT(Success);
+
+ return pEntry;
}
CResourceEntry::~CResourceEntry()
@@ -39,25 +85,18 @@ CResourceEntry::~CResourceEntry()
bool CResourceEntry::LoadMetadata()
{
ASSERT(!mMetadataDirty);
+
TString Path = MetadataFilePath();
+ CBinaryReader MetaFile(Path, FOURCC('META'));
- if (FileUtil::Exists(Path))
+ if (MetaFile.IsValid())
{
- // Validate file
- CFileInStream MetaFile(Path, IOUtil::eBigEndian);
- u32 Magic = MetaFile.ReadLong();
-
- if (Magic == FOURCC('META'))
- {
- CSerialVersion Version(MetaFile);
- CBinaryReader Reader(&MetaFile, Version);
- SerializeMetadata(Reader);
- return true;
- }
- else
- {
- Log::Error(Path + ": Failed to load metadata file, invalid magic: " + CFourCC(Magic).ToString());
- }
+ SerializeEntryInfo(MetaFile, true);
+ return true;
+ }
+ else
+ {
+ Log::Error(Path + ": Failed to load metadata file!");
}
return false;
@@ -71,24 +110,11 @@ bool CResourceEntry::SaveMetadata(bool ForceSave /*= false*/)
TString Dir = Path.GetFileDirectory();
FileUtil::MakeDirectory(Dir);
- CFileOutStream MetaFile(Path, IOUtil::eBigEndian);
+ CBinaryWriter MetaFile(Path, FOURCC('META'), 0, Game());
if (MetaFile.IsValid())
{
- MetaFile.WriteLong(0); // Magic dummy
-
- CSerialVersion Version(IArchive::skCurrentArchiveVersion, 0, Game());
- Version.Write(MetaFile);
-
- // Scope the binary writer to ensure it finishes before we go back to write the magic value
- {
- CBinaryWriter Writer(&MetaFile, Version);
- SerializeMetadata(Writer);
- }
-
- MetaFile.GoTo(0);
- MetaFile.WriteLong(FOURCC('META'));
-
+ SerializeEntryInfo(MetaFile, true);
mMetadataDirty = false;
return true;
}
@@ -97,30 +123,34 @@ bool CResourceEntry::SaveMetadata(bool ForceSave /*= false*/)
return false;
}
-void CResourceEntry::SerializeMetadata(IArchive& rArc)
+void CResourceEntry::SerializeEntryInfo(IArchive& rArc, bool MetadataOnly)
{
- // Serialize ID. If we already have a valid ID then don't allow the file to override it.
CAssetID ID = mID;
- rArc << SERIAL("AssetID", ID);
+ rArc << SERIAL("AssetID", ID)
+ << SERIAL("Type", mpTypeInfo)
+ << SERIAL("Flags", mFlags);
+
+ // Don't allow the file to override our asset ID if we already have a valid one.
if (rArc.IsReader() && !mID.IsValid())
mID = ID;
- // Serialize type
- rArc << SERIAL("Type", mpTypeInfo);
+ // Serialize extra data that we exclude from the metadata file
+ if (!MetadataOnly)
+ {
+ TString Dir = (mpDirectory ? mpDirectory->FullPath() : "");
- // Serialize flags
- u32 Flags = mFlags & eREF_SavedFlags;
- rArc << SERIAL_AUTO(Flags);
- if (rArc.IsReader()) mFlags = Flags & eREF_SavedFlags;
-}
+ rArc << SERIAL("Name", mName)
+ << SERIAL("Directory", Dir)
+ << SERIAL_ABSTRACT("Dependencies", mpDependencies, &gDependencyNodeFactory);
-void CResourceEntry::SerializeCacheData(IArchive& rArc)
-{
- // Note: If the dependency tree format is changed this should be adjusted so that
- // we regenerate the dependencies from scratch instead of reading the tree if the
- // file version number is too low
- rArc << SERIAL_ABSTRACT("Dependencies", mpDependencies, &gDependencyNodeFactory);
+ if (rArc.IsReader())
+ {
+ mpDirectory = mpStore->GetVirtualDirectory(Dir, true);
+ mpDirectory->AddChild("", this);
+ mCachedUppercaseName = mName.ToUpper();
+ }
+ }
}
void CResourceEntry::UpdateDependencies()
@@ -150,7 +180,7 @@ void CResourceEntry::UpdateDependencies()
}
mpDependencies = mpResource->BuildDependencyTree();
- mpStore->SetCacheDataDirty();
+ mpStore->SetCacheDirty();
if (!WasLoaded)
mpStore->DestroyUnreferencedResources();
@@ -550,7 +580,7 @@ bool CResourceEntry::Move(const TString& rkDir, const TString& rkName, bool IsAu
SetFlagEnabled(eREF_AutoResName, IsAutoGenName);
}
- mpStore->SetDatabaseDirty();
+ mpStore->SetCacheDirty();
mCachedUppercaseName = rkName.ToUpper();
FileUtil::DeleteFile(OldRawPath);
FileUtil::DeleteFile(OldCookedPath);
diff --git a/src/Core/GameProject/CResourceEntry.h b/src/Core/GameProject/CResourceEntry.h
index f642f05a..bb4e7e1c 100644
--- a/src/Core/GameProject/CResourceEntry.h
+++ b/src/Core/GameProject/CResourceEntry.h
@@ -22,9 +22,6 @@ enum EResEntryFlag
eREF_HasBeenModified = 0x00000008, // Resource has been modified and resaved by the user
eREF_AutoResName = 0x00000010, // Resource name is auto-generated
eREF_AutoResDir = 0x00000020, // Resource directory name is auto-generated
- // Flags that save to the cache file
- eREF_SavedFlags = eREF_NeedsRecook | eREF_IsBaseGameResource | eREF_Hidden | eREF_HasBeenModified |
- eREF_AutoResName | eREF_AutoResDir
};
DECLARE_FLAGS(EResEntryFlag, FResEntryFlags)
@@ -43,16 +40,21 @@ class CResourceEntry
mutable u64 mCachedSize;
mutable TString mCachedUppercaseName; // This is used to speed up case-insensitive sorting and filtering.
+ // Private constructor
+ CResourceEntry(CResourceStore *pStore);
+
public:
- CResourceEntry(CResourceStore *pStore, const CAssetID& rkID,
- const TString& rkDir, const TString& rkFilename,
- EResType Type);
+ static CResourceEntry* CreateNewResource(CResourceStore *pStore, const CAssetID& rkID,
+ const TString& rkDir, const TString& rkName,
+ EResType Type);
+ static CResourceEntry* BuildFromArchive(CResourceStore *pStore, IArchive& rArc);
+ static CResourceEntry* BuildFromDirectory(CResourceStore *pStore, CResTypeInfo *pTypeInfo,
+ const TString& rkDirPath, const TString& rkName);
~CResourceEntry();
bool LoadMetadata();
bool SaveMetadata(bool ForceSave = false);
- void SerializeMetadata(IArchive& rArc);
- void SerializeCacheData(IArchive& rArc);
+ void SerializeEntryInfo(IArchive& rArc, bool MetadataOnly);
void UpdateDependencies();
bool HasRawVersion() const;
diff --git a/src/Core/GameProject/CResourceStore.cpp b/src/Core/GameProject/CResourceStore.cpp
index 2c60d6ba..623e9b30 100644
--- a/src/Core/GameProject/CResourceStore.cpp
+++ b/src/Core/GameProject/CResourceStore.cpp
@@ -2,6 +2,7 @@
#include "CGameExporter.h"
#include "CGameProject.h"
#include "CResourceIterator.h"
+#include "Core/IUIRelay.h"
#include "Core/Resource/CResource.h"
#include
#include
@@ -17,13 +18,12 @@ CResourceStore *gpEditorStore = nullptr;
// Constructor for editor store
CResourceStore::CResourceStore(const TString& rkDatabasePath)
: mpProj(nullptr)
- , mGame(eUnknownGame)
- , mDatabaseDirty(false)
- , mCacheFileDirty(false)
+ , mGame(ePrime)
+ , mDatabaseCacheDirty(false)
{
mpDatabaseRoot = new CVirtualDirectory(this);
mDatabasePath = FileUtil::MakeAbsolute(rkDatabasePath.GetFileDirectory());
- mDatabaseName = rkDatabasePath.GetFileName();
+ LoadDatabaseCache();
}
// Main constructor for game projects and game exporter
@@ -31,8 +31,7 @@ CResourceStore::CResourceStore(CGameProject *pProject)
: mpProj(nullptr)
, mGame(eUnknownGame)
, mpDatabaseRoot(nullptr)
- , mDatabaseDirty(false)
- , mCacheFileDirty(false)
+ , mDatabaseCacheDirty(false)
{
SetProject(pProject);
}
@@ -60,58 +59,60 @@ void RecursiveGetListOfEmptyDirectories(CVirtualDirectory *pDir, TStringList& rO
}
}
-bool CResourceStore::SerializeResourceDatabase(IArchive& rArc)
+bool CResourceStore::SerializeDatabaseCache(IArchive& rArc)
{
- struct SDatabaseResource
+ // Serialize resources
+ if (rArc.ParamBegin("Resources"))
{
- CAssetID ID;
- CResTypeInfo *pType;
- TString Directory;
- TString Name;
+ // Serialize resources
+ u32 ResourceCount = mResourceEntries.size();
+ rArc << SERIAL_AUTO(ResourceCount);
- void Serialize(IArchive& rArc)
+ if (rArc.IsReader())
{
- rArc << SERIAL_AUTO(ID) << SERIAL("Type", pType) << SERIAL_AUTO(Directory) << SERIAL_AUTO(Name);
+ for (u32 ResIdx = 0; ResIdx < ResourceCount; ResIdx++)
+ {
+ if (rArc.ParamBegin("Resource"))
+ {
+ CResourceEntry *pEntry = CResourceEntry::BuildFromArchive(this, rArc);
+ ASSERT( FindEntry(pEntry->ID()) == nullptr );
+ mResourceEntries[pEntry->ID()] = pEntry;
+ rArc.ParamEnd();
+ }
+ }
}
- };
- std::vector Resources;
-
- // Populate resource list
- if (!rArc.IsReader())
- {
- Resources.reserve(mResourceEntries.size());
-
- for (CResourceIterator It(this); It; ++It)
- Resources.push_back( SDatabaseResource { It->ID(), It->TypeInfo(), It->Directory()->FullPath(), It->Name() } );
+ else
+ {
+ for (CResourceIterator It(this); It; ++It)
+ {
+ if (rArc.ParamBegin("Resource"))
+ {
+ It->SerializeEntryInfo(rArc, false);
+ rArc.ParamEnd();
+ }
+ }
+ }
+ rArc.ParamEnd();
}
- // Populate directory list
+ // Serialize empty directory list
TStringList EmptyDirectories;
if (!rArc.IsReader())
RecursiveGetListOfEmptyDirectories(mpDatabaseRoot, EmptyDirectories);
- // Serialize
- rArc << SERIAL_CONTAINER_AUTO(Resources, "Resource")
- << SERIAL_CONTAINER_AUTO(EmptyDirectories, "Directory");
+ rArc << SERIAL_CONTAINER_AUTO(EmptyDirectories, "Directory");
- // Register resources
if (rArc.IsReader())
{
for (auto Iter = EmptyDirectories.begin(); Iter != EmptyDirectories.end(); Iter++)
CreateVirtualDirectory(*Iter);
-
- for (auto Iter = Resources.begin(); Iter != Resources.end(); Iter++)
- {
- SDatabaseResource& rRes = *Iter;
- RegisterResource(rRes.ID, rRes.pType->Type(), rRes.Directory, rRes.Name);
- }
}
return true;
}
-bool CResourceStore::LoadResourceDatabase()
+bool CResourceStore::LoadDatabaseCache()
{
ASSERT(!mDatabasePath.IsEmpty());
TString Path = DatabasePath();
@@ -119,139 +120,46 @@ bool CResourceStore::LoadResourceDatabase()
if (!mpDatabaseRoot)
mpDatabaseRoot = new CVirtualDirectory(this);
- CXMLReader Reader(Path);
+ // Load the resource database
+ CBinaryReader Reader(Path, FOURCC('CACH'));
- if (!Reader.IsValid())
+ if (!Reader.IsValid() || !SerializeDatabaseCache(Reader))
{
- Log::Error("Failed to open resource database for load: " + Path);
- return false;
+ if (gpUIRelay->AskYesNoQuestion("Error", "Failed to load the resource database. Attempt to build from the directory? (This may take a while.)"))
+ {
+ if (!BuildFromDirectory(true))
+ return false;
+ }
+ else return false;
+ }
+ else
+ {
+ // Database is succesfully loaded at this point
+ if (mpProj)
+ ASSERT(mpProj->Game() == Reader.Game());
}
-
- if (mpProj)
- ASSERT(mpProj->Game() == Reader.Game());
mGame = Reader.Game();
- if (!SerializeResourceDatabase(Reader)) return false;
- return LoadCacheFile();
-}
-
-bool CResourceStore::SaveResourceDatabase()
-{
- TString Path = DatabasePath();
- CXMLWriter Writer(Path, "ResourceDB", 0, mGame);
- SerializeResourceDatabase(Writer);
- bool SaveSuccess = Writer.Save();
-
- if (SaveSuccess)
- mDatabaseDirty = false;
- else
- Log::Error("Failed to save resource database: " + Path);
-
- return SaveSuccess;
-}
-
-bool CResourceStore::LoadCacheFile()
-{
- TString CachePath = CacheDataPath();
- CFileInStream CacheFile(CachePath, IOUtil::eBigEndian);
-
- if (!CacheFile.IsValid())
- {
- Log::Error("Failed to open cache file for load: " + CachePath);
- return false;
- }
-
- // Cache header
- CFourCC Magic(CacheFile);
-
- if (Magic != FOURCC('CACH'))
- {
- Log::Error("Invalid resource cache data magic: " + Magic.ToString());
- return false;
- }
-
- CSerialVersion Version(CacheFile);
- u32 NumResources = CacheFile.ReadLong();
-
- for (u32 iRes = 0; iRes < NumResources; iRes++)
- {
- CAssetID ID(CacheFile, Version.Game());
- u32 EntryCacheSize = CacheFile.ReadLong();
- u32 EntryCacheEnd = CacheFile.Tell() + EntryCacheSize;
-
- CResourceEntry *pEntry = FindEntry(ID);
-
- if (pEntry)
- {
- CBasicBinaryReader Reader(&CacheFile, Version);
-
- if (Reader.ParamBegin("EntryCache"))
- {
- pEntry->SerializeCacheData(Reader);
- Reader.ParamEnd();
- }
- }
-
- CacheFile.Seek(EntryCacheEnd, SEEK_SET);
- }
return true;
}
-bool CResourceStore::SaveCacheFile()
+bool CResourceStore::SaveDatabaseCache()
{
- TString CachePath = CacheDataPath();
- CFileOutStream CacheFile(CachePath, IOUtil::eBigEndian);
+ TString Path = DatabasePath();
- if (!CacheFile.IsValid())
- {
- Log::Error("Failed to open cache file for save: " + CachePath);
+ CBinaryWriter Writer(Path, FOURCC('CACH'), 0, mGame);
+
+ if (!Writer.IsValid())
return false;
- }
- // Cache header
- CacheFile.WriteLong(0); // Magic dummy. Magic isn't written until the rest of the file is saved successfully.
- CSerialVersion Version(IArchive::skCurrentArchiveVersion, 0, mGame);
- Version.Write(CacheFile);
-
- u32 ResCountOffset = CacheFile.Tell();
- u32 ResCount = 0;
- CacheFile.WriteLong(0); // Resource count dummy - fill in when we know the real count
-
- // Save entry cache data
- // Structure: Entry Asset ID -> Entry Cache Size -> Serialized Entry Cache Data
- for (CResourceIterator It(this); It; ++It)
- {
- ResCount++;
- It->ID().Write(CacheFile);
- u32 SizeOffset = CacheFile.Tell();
- CacheFile.WriteLong(0);
-
- CBasicBinaryWriter Writer(&CacheFile, Version.FileVersion(), Version.Game());
-
- if (Writer.ParamBegin("EntryCache"))
- {
- It->SerializeCacheData(Writer);
- Writer.ParamEnd();
- }
-
- u32 EntryCacheEnd = CacheFile.Tell();
- CacheFile.Seek(SizeOffset, SEEK_SET);
- CacheFile.WriteLong(EntryCacheEnd - SizeOffset - 4);
- CacheFile.Seek(EntryCacheEnd, SEEK_SET);
- }
-
- CacheFile.Seek(ResCountOffset, SEEK_SET);
- CacheFile.WriteLong(ResCount);
- CacheFile.Seek(0, SEEK_SET);
- CacheFile.WriteLong( FOURCC('CACH') );
- mCacheFileDirty = false;
+ SerializeDatabaseCache(Writer);
+ mDatabaseCacheDirty = false;
return true;
}
void CResourceStore::ConditionalSaveStore()
{
- if (mDatabaseDirty) SaveResourceDatabase();
- if (mCacheFileDirty) SaveCacheFile();
+ if (mDatabaseCacheDirty) SaveDatabaseCache();
}
void CResourceStore::SetProject(CGameProject *pProj)
@@ -267,7 +175,6 @@ void CResourceStore::SetProject(CGameProject *pProj)
{
TString DatabasePath = mpProj->ResourceDBPath(false);
mDatabasePath = DatabasePath.GetFileDirectory();
- mDatabaseName = DatabasePath.GetFileName();
mpDatabaseRoot = new CVirtualDirectory(this);
mGame = mpProj->Game();
}
@@ -377,13 +284,11 @@ void CResourceStore::ClearDatabase()
delete mpDatabaseRoot;
mpDatabaseRoot = new CVirtualDirectory(this);
- mDatabaseDirty = true;
- mCacheFileDirty = true;
+ mDatabaseCacheDirty = true;
}
-void CResourceStore::BuildFromDirectory()
+bool CResourceStore::BuildFromDirectory(bool ShouldGenerateCacheFile)
{
- ASSERT(mpProj != nullptr);
ASSERT(mResourceEntries.empty());
// Get list of resources
@@ -415,8 +320,7 @@ void CResourceStore::BuildFromDirectory()
}
// Create resource entry
- CResourceEntry *pEntry = new CResourceEntry(this, CAssetID::InvalidID(mGame), DirPath, ResName, pTypeInfo->Type());
- pEntry->LoadMetadata();
+ CResourceEntry *pEntry = CResourceEntry::BuildFromDirectory(this, pTypeInfo, DirPath, ResName);
// Validate the entry
CAssetID ID = pEntry->ID();
@@ -429,6 +333,31 @@ void CResourceStore::BuildFromDirectory()
else if (FileUtil::IsDirectory(Path))
CreateVirtualDirectory(RelPath);
}
+
+ // Generate new cache file
+ if (ShouldGenerateCacheFile)
+ {
+ // Make sure gpResourceStore points to this store
+ CResourceStore *pOldStore = gpResourceStore;
+ gpResourceStore = this;
+
+ // Make sure audio manager is loaded correctly so AGSC dependencies can be looked up
+ if (mpProj)
+ mpProj->AudioManager()->LoadAssets();
+
+ // Update dependencies
+ for (CResourceIterator It(this); It; ++It)
+ It->UpdateDependencies();
+
+ // Update database file
+ mDatabaseCacheDirty = true;
+ ConditionalSaveStore();
+
+ // Restore old gpResourceStore
+ gpResourceStore = pOldStore;
+ }
+
+ return true;
}
void CResourceStore::RebuildFromDirectory()
@@ -436,19 +365,7 @@ void CResourceStore::RebuildFromDirectory()
ASSERT(mpProj != nullptr);
mpProj->AudioManager()->ClearAssets();
ClearDatabase();
- BuildFromDirectory();
-
- // Make sure audio manager is loaded correctly so AGSC dependencies can be looked up
- mpProj->AudioManager()->LoadAssets();
-
- // Update dependencies
- for (CResourceIterator It(this); It; ++It)
- It->UpdateDependencies();
-
- // Update database files
- mDatabaseDirty = true;
- mCacheFileDirty = true;
- ConditionalSaveStore();
+ BuildFromDirectory(true);
}
bool CResourceStore::IsResourceRegistered(const CAssetID& rkID) const
@@ -468,8 +385,7 @@ CResourceEntry* CResourceStore::RegisterResource(const CAssetID& rkID, EResType
// Validate directory
if (IsValidResourcePath(rkDir, rkName))
{
- pEntry = new CResourceEntry(this, rkID, rkDir, rkName, Type);
- pEntry->LoadMetadata();
+ pEntry = CResourceEntry::CreateNewResource(this, rkID, rkDir, rkName, Type);
mResourceEntries[rkID] = pEntry;
}
diff --git a/src/Core/GameProject/CResourceStore.h b/src/Core/GameProject/CResourceStore.h
index 50507015..9cad0ee1 100644
--- a/src/Core/GameProject/CResourceStore.h
+++ b/src/Core/GameProject/CResourceStore.h
@@ -24,12 +24,10 @@ class CResourceStore
CVirtualDirectory *mpDatabaseRoot;
std::map mResourceEntries;
std::map mLoadedResources;
- bool mDatabaseDirty;
- bool mCacheFileDirty;
+ bool mDatabaseCacheDirty;
// Directory paths
TString mDatabasePath;
- TString mDatabaseName;
enum EDatabaseVersion
{
@@ -43,11 +41,9 @@ public:
CResourceStore(const TString& rkDatabasePath);
CResourceStore(CGameProject *pProject);
~CResourceStore();
- bool SerializeResourceDatabase(IArchive& rArc);
- bool LoadResourceDatabase();
- bool SaveResourceDatabase();
- bool LoadCacheFile();
- bool SaveCacheFile();
+ bool SerializeDatabaseCache(IArchive& rArc);
+ bool LoadDatabaseCache();
+ bool SaveDatabaseCache();
void ConditionalSaveStore();
void SetProject(CGameProject *pProj);
void CloseProject();
@@ -61,7 +57,7 @@ public:
CResourceEntry* FindEntry(const TString& rkPath) const;
bool AreAllEntriesValid() const;
void ClearDatabase();
- void BuildFromDirectory();
+ bool BuildFromDirectory(bool ShouldGenerateCacheFile);
void RebuildFromDirectory();
template ResType* LoadResource(const CAssetID& rkID) { return static_cast(LoadResource(rkID, ResType::StaticType())); }
@@ -81,15 +77,13 @@ public:
inline EGame Game() const { return mGame; }
inline TString DatabaseRootPath() const { return mDatabasePath; }
inline TString ResourcesDir() const { return IsEditorStore() ? DatabaseRootPath() : DatabaseRootPath() + "Resources/"; }
- inline TString DatabasePath() const { return DatabaseRootPath() + "ResourceDatabase.xml"; }
- inline TString CacheDataPath() const { return DatabaseRootPath() + "ResourceCacheData.bin"; }
+ inline TString DatabasePath() const { return DatabaseRootPath() + "ResourceDatabaseCache.bin"; }
inline CVirtualDirectory* RootDirectory() const { return mpDatabaseRoot; }
inline u32 NumTotalResources() const { return mResourceEntries.size(); }
inline u32 NumLoadedResources() const { return mLoadedResources.size(); }
- inline bool IsDirty() const { return mDatabaseDirty || mCacheFileDirty; }
+ inline bool IsCacheDirty() const { return mDatabaseCacheDirty; }
- inline void SetDatabaseDirty() { mDatabaseDirty = true; }
- inline void SetCacheDataDirty() { mCacheFileDirty = true; }
+ inline void SetCacheDirty() { mDatabaseCacheDirty = true; }
inline bool IsEditorStore() const { return mpProj == nullptr; }
};
diff --git a/src/Editor/CEditorApplication.cpp b/src/Editor/CEditorApplication.cpp
index c41c9b7f..199b3e5b 100644
--- a/src/Editor/CEditorApplication.cpp
+++ b/src/Editor/CEditorApplication.cpp
@@ -253,7 +253,7 @@ void CEditorApplication::TickEditors()
double DeltaTime = mLastUpdate - LastUpdate;
// The resource store should NOT be dirty at the beginning of a tick - this indicates we forgot to save it after updating somewhere
- if (gpResourceStore && gpResourceStore->IsDirty())
+ if (gpResourceStore && gpResourceStore->IsCacheDirty())
{
Log::Error("Resource store is dirty at the beginning of a tick! Call ConditionalSaveStore() after making any significant changes to assets!");
DEBUG_BREAK;
diff --git a/src/Editor/CUIRelay.h b/src/Editor/CUIRelay.h
index ade0c451..d94ec70c 100644
--- a/src/Editor/CUIRelay.h
+++ b/src/Editor/CUIRelay.h
@@ -6,10 +6,18 @@
#include "WorldEditor/CWorldEditor.h"
#include "UICommon.h"
+#include
+
class CUIRelay : public QObject, public IUIRelay
{
Q_OBJECT
+ Qt::ConnectionType GetConnectionType()
+ {
+ bool IsUIThread = (QThread::currentThread() == gpEdApp->thread());
+ return IsUIThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection;
+ }
+
public:
explicit CUIRelay(QObject *pParent = 0)
: QObject(pParent)
@@ -20,7 +28,7 @@ public:
virtual bool AskYesNoQuestion(const TString& rkInfoBoxTitle, const TString& rkQuestion)
{
bool RetVal;
- QMetaObject::invokeMethod(this, "AskYesNoQuestionSlot", Qt::BlockingQueuedConnection,
+ QMetaObject::invokeMethod(this, "AskYesNoQuestionSlot", GetConnectionType(),
Q_RETURN_ARG(bool, RetVal),
Q_ARG(QString, TO_QSTRING(rkInfoBoxTitle)),
Q_ARG(QString, TO_QSTRING(rkQuestion)) );
diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp
index 2bd02103..64ebdb29 100644
--- a/src/Editor/main.cpp
+++ b/src/Editor/main.cpp
@@ -32,22 +32,10 @@ int main(int argc, char *argv[])
App.setOrganizationName("Aruki");
App.setWindowIcon(QIcon(":/icons/AppIcon.ico"));
- // Init log
- bool Initialized = Log::InitLog("primeworldeditor.log");
- if (!Initialized) QMessageBox::warning(0, "Error", "Couldn't open log file. Logging will not work for this session.");
- qInstallMessageHandler(QtLogRedirect);
-
// Create UI relay
CUIRelay UIRelay(&App);
gpUIRelay = &UIRelay;
- // Create editor resource store
- gpEditorStore = new CResourceStore("../resources/EditorResourceDB.rdb");
- gpEditorStore->LoadResourceDatabase();
-
- // Load templates
- CTemplateLoader::LoadGameList();
-
// Set up dark theme
qApp->setStyle(QStyleFactory::create("Fusion"));
QPalette DarkPalette;
@@ -66,6 +54,17 @@ int main(int argc, char *argv[])
DarkPalette.setColor(QPalette::HighlightedText, Qt::white);
qApp->setPalette(DarkPalette);
+ // Init log
+ bool Initialized = Log::InitLog("primeworldeditor.log");
+ if (!Initialized) QMessageBox::warning(0, "Error", "Couldn't open log file. Logging will not work for this session.");
+ qInstallMessageHandler(QtLogRedirect);
+
+ // Create editor resource store
+ gpEditorStore = new CResourceStore("../resources/");
+
+ // Load templates
+ CTemplateLoader::LoadGameList();
+
// Execute application
App.InitEditor();
return App.exec();