From 4652e125e5b8f16cc57acf8c700214ad8d67e5ad Mon Sep 17 00:00:00 2001 From: Aruki Date: Tue, 4 Jul 2017 13:34:14 -0600 Subject: [PATCH] Resource database can now keep track of empty directories --- src/Common/Serialization/IArchive.h | 15 ++++++++ src/Core/GameProject/CResourceStore.cpp | 47 ++++++++++++++++++++++--- src/Core/GameProject/CResourceStore.h | 2 ++ 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/Common/Serialization/IArchive.h b/src/Common/Serialization/IArchive.h index c54cc06e..18ec61ff 100644 --- a/src/Common/Serialization/IArchive.h +++ b/src/Common/Serialization/IArchive.h @@ -476,6 +476,21 @@ inline void SerializeContainer(IArchive& rArc, std::list& rList, const rArc << SERIAL_ABSTRACT(*rkElemName, rVec[iElem], pFactory); } +// Overload for TStringList and TWideStringList so they can use the TString/TWideString serialize functions +inline void SerializeContainer(IArchive& rArc, TStringList& rList, const TString& rkElemName) +{ + typedef std::list ListType; + ListType& rGenericList = *reinterpret_cast(&rList); + SerializeContainer(rArc, rGenericList, rkElemName); +} + +inline void SerializeContainer(IArchive& rArc, TWideStringList& rList, const TString& rkElemName) +{ + typedef std::list ListType; + ListType& rGenericList = *reinterpret_cast(&rList); + SerializeContainer(rArc, rGenericList, rkElemName); +} + // std::set template inline void SerializeContainer(IArchive& rArc, std::set& rSet, const TString& rkElemName) diff --git a/src/Core/GameProject/CResourceStore.cpp b/src/Core/GameProject/CResourceStore.cpp index 20ac6f45..2c60d6ba 100644 --- a/src/Core/GameProject/CResourceStore.cpp +++ b/src/Core/GameProject/CResourceStore.cpp @@ -46,6 +46,20 @@ CResourceStore::~CResourceStore() delete It->second; } +void RecursiveGetListOfEmptyDirectories(CVirtualDirectory *pDir, TStringList& rOutList) +{ + // Helper function for SerializeResourceDatabase + if (pDir->IsEmpty()) + { + rOutList.push_back(pDir->FullPath()); + } + else + { + for (u32 SubIdx = 0; SubIdx < pDir->NumSubdirectories(); SubIdx++) + RecursiveGetListOfEmptyDirectories(pDir->SubdirectoryByIndex(SubIdx), rOutList); + } +} + bool CResourceStore::SerializeResourceDatabase(IArchive& rArc) { struct SDatabaseResource @@ -71,12 +85,22 @@ bool CResourceStore::SerializeResourceDatabase(IArchive& rArc) Resources.push_back( SDatabaseResource { It->ID(), It->TypeInfo(), It->Directory()->FullPath(), It->Name() } ); } + // Populate directory list + TStringList EmptyDirectories; + + if (!rArc.IsReader()) + RecursiveGetListOfEmptyDirectories(mpDatabaseRoot, EmptyDirectories); + // Serialize - rArc << SERIAL_CONTAINER_AUTO(Resources, "Resource"); + rArc << SERIAL_CONTAINER_AUTO(Resources, "Resource") + << 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; @@ -295,6 +319,12 @@ CVirtualDirectory* CResourceStore::GetVirtualDirectory(const TString& rkPath, bo return nullptr; } +void CResourceStore::CreateVirtualDirectory(const TString& rkPath) +{ + if (!rkPath.IsEmpty()) + mpDatabaseRoot->FindChildDirectory(rkPath, true); +} + void CResourceStore::ConditionalDeleteDirectory(CVirtualDirectory *pDir, bool Recurse) { if (pDir->IsEmpty() && !pDir->IsRoot()) @@ -351,11 +381,10 @@ void CResourceStore::ClearDatabase() mCacheFileDirty = true; } -void CResourceStore::RebuildFromDirectory() +void CResourceStore::BuildFromDirectory() { ASSERT(mpProj != nullptr); - mpProj->AudioManager()->ClearAssets(); - ClearDatabase(); + ASSERT(mResourceEntries.empty()); // Get list of resources TString ResDir = ResourcesDir(); @@ -398,8 +427,16 @@ void CResourceStore::RebuildFromDirectory() } else if (FileUtil::IsDirectory(Path)) - GetVirtualDirectory(RelPath, true); + CreateVirtualDirectory(RelPath); } +} + +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(); diff --git a/src/Core/GameProject/CResourceStore.h b/src/Core/GameProject/CResourceStore.h index d49bc61a..50507015 100644 --- a/src/Core/GameProject/CResourceStore.h +++ b/src/Core/GameProject/CResourceStore.h @@ -52,6 +52,7 @@ public: void SetProject(CGameProject *pProj); void CloseProject(); CVirtualDirectory* GetVirtualDirectory(const TString& rkPath, bool AllowCreate); + void CreateVirtualDirectory(const TString& rkPath); void ConditionalDeleteDirectory(CVirtualDirectory *pDir, bool Recurse); bool IsResourceRegistered(const CAssetID& rkID) const; @@ -60,6 +61,7 @@ public: CResourceEntry* FindEntry(const TString& rkPath) const; bool AreAllEntriesValid() const; void ClearDatabase(); + void BuildFromDirectory(); void RebuildFromDirectory(); template ResType* LoadResource(const CAssetID& rkID) { return static_cast(LoadResource(rkID, ResType::StaticType())); }