From 2d6dfad2d30b6bc0586fdbb925a60bf6ea1c2d75 Mon Sep 17 00:00:00 2001 From: parax0 Date: Wed, 29 Jun 2016 17:18:31 -0600 Subject: [PATCH] Completely overhauled resource loading in preparation for projects --- src/Common/FileUtil.cpp | 23 +- src/Common/FileUtil.h | 3 + src/Core/CLightParameters.h | 2 +- src/Core/Core.pro | 18 +- src/Core/GameProject/CGameExporter.cpp | 30 +- src/Core/GameProject/CGameProject.h | 8 +- src/Core/GameProject/CResourceDatabase.cpp | 215 ---------- src/Core/GameProject/CResourceDatabase.h | 74 ---- src/Core/GameProject/CResourceEntry.cpp | 151 +++++++ src/Core/GameProject/CResourceEntry.h | 55 +++ src/Core/GameProject/CResourceStore.cpp | 403 ++++++++++++++++++ src/Core/GameProject/CResourceStore.h | 65 +++ src/Core/GameProject/CVirtualDirectory.cpp | 156 +++++++ src/Core/GameProject/CVirtualDirectory.h | 44 ++ src/Core/Render/CDrawUtil.cpp | 28 +- src/Core/Render/CRenderer.cpp | 2 +- src/Core/Resource/{ => Area}/CGameArea.cpp | 4 +- src/Core/Resource/{ => Area}/CGameArea.h | 12 +- src/Core/Resource/CAnimSet.h | 2 +- src/Core/Resource/CAnimation.cpp | 5 +- src/Core/Resource/CAnimation.h | 2 +- src/Core/Resource/CAnimationParameters.cpp | 2 +- src/Core/Resource/CCollisionMeshGroup.h | 2 +- src/Core/Resource/CFont.cpp | 4 +- src/Core/Resource/CFont.h | 2 +- src/Core/Resource/CMaterial.cpp | 2 +- src/Core/Resource/CPoiToWorld.cpp | 3 +- src/Core/Resource/CPoiToWorld.h | 2 +- src/Core/Resource/CResCache.cpp | 209 --------- src/Core/Resource/CResCache.h | 36 -- src/Core/Resource/CResource.cpp | 90 +++- src/Core/Resource/CResource.h | 33 +- src/Core/Resource/CResourceInfo.h | 6 +- src/Core/Resource/CScan.h | 4 +- src/Core/Resource/CSkeleton.cpp | 5 +- src/Core/Resource/CSkeleton.h | 2 +- src/Core/Resource/CSkin.h | 2 +- src/Core/Resource/CStringTable.h | 2 +- src/Core/Resource/CTexture.cpp | 5 +- src/Core/Resource/CTexture.h | 2 +- src/Core/Resource/CWorld.cpp | 6 +- src/Core/Resource/CWorld.h | 4 +- src/Core/Resource/Cooker/CAreaCooker.h | 2 +- src/Core/Resource/EResType.h | 14 +- src/Core/Resource/Factory/CAnimSetLoader.cpp | 33 +- src/Core/Resource/Factory/CAnimSetLoader.h | 4 +- .../Resource/Factory/CAnimationLoader.cpp | 19 +- src/Core/Resource/Factory/CAnimationLoader.h | 2 +- src/Core/Resource/Factory/CAreaLoader.cpp | 7 +- src/Core/Resource/Factory/CAreaLoader.h | 6 +- .../Resource/Factory/CCollisionLoader.cpp | 5 +- src/Core/Resource/Factory/CCollisionLoader.h | 2 +- src/Core/Resource/Factory/CFontLoader.cpp | 9 +- src/Core/Resource/Factory/CFontLoader.h | 4 +- src/Core/Resource/Factory/CMaterialLoader.cpp | 6 +- src/Core/Resource/Factory/CMaterialLoader.h | 2 +- src/Core/Resource/Factory/CModelLoader.cpp | 5 +- src/Core/Resource/Factory/CModelLoader.h | 4 +- .../Resource/Factory/CPoiToWorldLoader.cpp | 4 +- src/Core/Resource/Factory/CPoiToWorldLoader.h | 2 +- src/Core/Resource/Factory/CScanLoader.cpp | 21 +- src/Core/Resource/Factory/CScanLoader.h | 3 +- src/Core/Resource/Factory/CScriptLoader.cpp | 4 +- src/Core/Resource/Factory/CScriptLoader.h | 4 +- src/Core/Resource/Factory/CSkeletonLoader.cpp | 7 +- src/Core/Resource/Factory/CSkeletonLoader.h | 2 +- src/Core/Resource/Factory/CSkinLoader.cpp | 4 +- src/Core/Resource/Factory/CSkinLoader.h | 2 +- src/Core/Resource/Factory/CStringLoader.cpp | 9 +- src/Core/Resource/Factory/CStringLoader.h | 8 +- src/Core/Resource/Factory/CTextureDecoder.cpp | 11 +- src/Core/Resource/Factory/CTextureDecoder.h | 7 +- src/Core/Resource/Factory/CWorldLoader.cpp | 37 +- src/Core/Resource/Factory/CWorldLoader.h | 4 +- src/Core/Resource/Model/CBasicModel.cpp | 4 +- src/Core/Resource/Model/CBasicModel.h | 2 +- src/Core/Resource/Model/CModel.cpp | 5 +- src/Core/Resource/Model/CModel.h | 2 +- src/Core/Resource/Model/CStaticModel.cpp | 18 +- src/Core/Resource/Model/CStaticModel.h | 8 +- src/Core/Resource/Script/CLink.h | 2 +- src/Core/Resource/Script/CScriptObject.h | 2 +- src/Core/Resource/Script/CScriptTemplate.cpp | 6 +- src/Core/Scene/CScene.cpp | 1 - src/Core/Scene/CScene.h | 2 +- src/Core/Scene/CSceneNode.cpp | 6 +- src/Core/Scene/CSceneNode.h | 2 +- src/Core/Scene/CScriptNode.cpp | 8 +- src/Editor/CGizmo.cpp | 50 +-- src/Editor/CStartWindow.cpp | 37 +- src/Editor/CStartWindow.h | 2 +- .../CharacterEditor/CCharacterEditor.cpp | 4 +- src/Editor/ModelEditor/CModelEditorWindow.cpp | 12 +- src/Editor/ModelEditor/CModelEditorWindow.h | 2 +- src/Editor/Undo/CCreateInstanceCommand.h | 2 +- src/Editor/Undo/ObjReferences.h | 2 +- src/Editor/Widgets/WAnimParamsEditor.cpp | 2 +- src/Editor/Widgets/WResourceSelector.cpp | 2 +- src/Editor/Widgets/WTextureGLWidget.cpp | 2 +- src/Editor/WorldEditor/CLayerModel.h | 2 +- src/Editor/WorldEditor/CLinkModel.cpp | 2 +- src/Editor/WorldEditor/CWorldEditor.h | 2 +- 102 files changed, 1334 insertions(+), 835 deletions(-) delete mode 100644 src/Core/GameProject/CResourceDatabase.cpp delete mode 100644 src/Core/GameProject/CResourceDatabase.h create mode 100644 src/Core/GameProject/CResourceEntry.cpp create mode 100644 src/Core/GameProject/CResourceEntry.h create mode 100644 src/Core/GameProject/CResourceStore.cpp create mode 100644 src/Core/GameProject/CResourceStore.h create mode 100644 src/Core/GameProject/CVirtualDirectory.cpp create mode 100644 src/Core/GameProject/CVirtualDirectory.h rename src/Core/Resource/{ => Area}/CGameArea.cpp (98%) rename src/Core/Resource/{ => Area}/CGameArea.h (94%) delete mode 100644 src/Core/Resource/CResCache.cpp delete mode 100644 src/Core/Resource/CResCache.h diff --git a/src/Common/FileUtil.cpp b/src/Common/FileUtil.cpp index 13fce003..3e01b2eb 100644 --- a/src/Common/FileUtil.cpp +++ b/src/Common/FileUtil.cpp @@ -16,7 +16,7 @@ bool Exists(const TWideString &rkFilePath) bool IsRoot(const TWideString& rkPath) { - // todo: is this actually a good way of checking for root? + // todo: is this actually a good/multiplatform way of checking for root? TWideString AbsPath = MakeAbsolute(rkPath); TWideStringList Split = AbsPath.Split(L"\\/"); return (Split.size() <= 1); @@ -32,6 +32,16 @@ bool IsDirectory(const TWideString& rkDirPath) return is_directory(*rkDirPath); } +bool IsAbsolute(const TWideString& rkDirPath) +{ + return boost::filesystem::path(*rkDirPath).is_absolute(); +} + +bool IsRelative(const TWideString& rkDirPath) +{ + return !boost::filesystem::path(*rkDirPath).is_relative(); +} + bool CreateDirectory(const TWideString& rkNewDir) { if (!IsValidPath(rkNewDir, true)) @@ -412,4 +422,15 @@ void GetDirectoryContents(TWideString DirPath, TWideStringList& rOut, bool Recur } } +TWideString FindFileExtension(const TWideString& rkDir, const TWideString& rkName) +{ + for (directory_iterator It(*rkDir); It != directory_iterator(); ++It) + { + TWideString Name = It->path().filename().native(); + if (Name.GetFileName(false) == rkName) return Name.GetFileExtension(); + } + + return L""; +} + } diff --git a/src/Common/FileUtil.h b/src/Common/FileUtil.h index f1477cf1..2cec2dcc 100644 --- a/src/Common/FileUtil.h +++ b/src/Common/FileUtil.h @@ -11,6 +11,8 @@ bool Exists(const TWideString& rkFilePath); bool IsRoot(const TWideString& rkPath); bool IsFile(const TWideString& rkFilePath); bool IsDirectory(const TWideString& rkDirPath); +bool IsAbsolute(const TWideString& rkDirPath); +bool IsRelative(const TWideString& rkDirPath); bool CreateDirectory(const TWideString& rkNewDir); bool CopyFile(const TWideString& rkOrigPath, const TWideString& rkNewPath); bool CopyDirectory(const TWideString& rkOrigPath, const TWideString& rkNewPath); @@ -29,6 +31,7 @@ TWideString SanitizePath(TWideString Path, bool Directory); bool IsValidName(const TWideString& rkName, bool Directory, bool RootDir = false); bool IsValidPath(const TWideString& rkPath, bool Directory); void GetDirectoryContents(TWideString DirPath, TWideStringList& rOut, bool Recursive = true, bool IncludeFiles = true, bool IncludeDirs = true); +TWideString FindFileExtension(const TWideString& rkDir, const TWideString& rkName); } diff --git a/src/Core/CLightParameters.h b/src/Core/CLightParameters.h index e908e544..a79153f8 100644 --- a/src/Core/CLightParameters.h +++ b/src/Core/CLightParameters.h @@ -1,7 +1,7 @@ #ifndef CLIGHTPARAMETERS_H #define CLIGHTPARAMETERS_H -#include "Core/Resource/CGameArea.h" +#include "Core/Resource/Area/CGameArea.h" #include "Core/Resource/Script/IProperty.h" enum EWorldLightingOptions diff --git a/src/Core/Core.pro b/src/Core/Core.pro index 7f032fa6..1b58fb01 100644 --- a/src/Core/Core.pro +++ b/src/Core/Core.pro @@ -83,6 +83,7 @@ HEADERS += \ Render/IRenderable.h \ Render/SRenderablePtr.h \ Render/SViewInfo.h \ + Resource/Area/CGameArea.h \ Resource/Cooker/CMaterialCooker.h \ Resource/Cooker/CModelCooker.h \ Resource/Cooker/CSectionMgrOut.h \ @@ -117,12 +118,10 @@ HEADERS += \ Resource/CCollisionMesh.h \ Resource/CCollisionMeshGroup.h \ Resource/CFont.h \ - Resource/CGameArea.h \ Resource/CLight.h \ Resource/CMaterial.h \ Resource/CMaterialPass.h \ Resource/CMaterialSet.h \ - Resource/CResCache.h \ Resource/CResource.h \ Resource/CScan.h \ Resource/CStringTable.h \ @@ -192,9 +191,11 @@ HEADERS += \ Scene/CScriptAttachNode.h \ ScriptExtra/CSandwormExtra.h \ GameProject/CGameProject.h \ - GameProject/CResourceDatabase.h \ GameProject/CPackage.h \ - GameProject/CGameExporter.h + GameProject/CGameExporter.h \ + GameProject/CResourceStore.h \ + GameProject/CVirtualDirectory.h \ + GameProject/CResourceEntry.h # Source Files SOURCES += \ @@ -203,6 +204,7 @@ SOURCES += \ Render/CGraphics.cpp \ Render/CRenderer.cpp \ Render/CRenderBucket.cpp \ + Resource/Area/CGameArea.cpp \ Resource/Cooker/CMaterialCooker.cpp \ Resource/Cooker/CModelCooker.cpp \ Resource/Cooker/CTemplateWriter.cpp \ @@ -230,11 +232,9 @@ SOURCES += \ Resource/CAnimationParameters.cpp \ Resource/CCollisionMesh.cpp \ Resource/CFont.cpp \ - Resource/CGameArea.cpp \ Resource/CLight.cpp \ Resource/CMaterial.cpp \ Resource/CMaterialPass.cpp \ - Resource/CResCache.cpp \ Resource/CResource.cpp \ Resource/CTexture.cpp \ Resource/CWorld.cpp \ @@ -282,5 +282,7 @@ SOURCES += \ Scene/CScriptAttachNode.cpp \ ScriptExtra/CSandwormExtra.cpp \ GameProject/CGameProject.cpp \ - GameProject/CResourceDatabase.cpp \ - GameProject/CGameExporter.cpp + GameProject/CGameExporter.cpp \ + GameProject/CResourceStore.cpp \ + GameProject/CVirtualDirectory.cpp \ + GameProject/CResourceEntry.cpp diff --git a/src/Core/GameProject/CGameExporter.cpp b/src/Core/GameProject/CGameExporter.cpp index 2ffb57af..18fcd958 100644 --- a/src/Core/GameProject/CGameExporter.cpp +++ b/src/Core/GameProject/CGameExporter.cpp @@ -1,5 +1,5 @@ #include "CGameExporter.h" -#include "Core/Resource/CResCache.h" +#include "Core/GameProject/CResourceStore.h" #include "Core/Resource/CWorld.h" #include #include @@ -30,7 +30,7 @@ CGameExporter::CGameExporter(const TString& rkInputDir, const TString& rkOutputD bool CGameExporter::Export() { SCOPED_TIMER(ExportGame); - gResCache.SetGameExporter(this); + gResourceStore.SetGameExporter(this); FileUtil::CreateDirectory(mExportDir); FileUtil::ClearDirectory(mExportDir); @@ -40,7 +40,7 @@ bool CGameExporter::Export() ExportWorlds(); ExportCookedResources(); - gResCache.SetGameExporter(nullptr); + gResourceStore.SetGameExporter(nullptr); return true; } @@ -57,7 +57,7 @@ void CGameExporter::CopyDiscData() SCOPED_TIMER(CopyDiscData); // Create Disc output folder - FileUtil::CreateDirectory(mDiscDir); + FileUtil::CreateDirectory(mExportDir + mDiscDir); #endif // Copy data @@ -97,7 +97,7 @@ void CGameExporter::CopyDiscData() #if COPY_DISC_DATA // Create directory - TWideString OutFile = mDiscDir + RelPath; + TWideString OutFile = mExportDir + mDiscDir + RelPath; FileUtil::CreateDirectory(OutFile.GetFileDirectory()); // Copy file @@ -184,7 +184,7 @@ void CGameExporter::LoadPaks() continue; } - CPackage *pPackage = new CPackage(CharPak.GetFileName(false), FileUtil::MakeRelative(PakPath.GetFileDirectory(), mExportDir)); + CPackage *pPackage = new CPackage(CharPak.GetFileName(false), FileUtil::MakeRelative(PakPath.GetFileDirectory(), mGameDir)); // MP1-MP3Proto if (Game() < eCorruption) @@ -407,10 +407,10 @@ void CGameExporter::ExportWorlds() // Get output path. DKCR paks are stored in a Worlds folder so we should get the path relative to that so we don't have Worlds\Worlds\. // Other games have all paks in the game root dir so we're fine just taking the original root dir-relative directory. TWideString PakPath = pPak->PakPath(); - TWideString WorldsDir = PakPath.GetParentDirectoryPath(L"Worlds", false); + TWideString GameWorldsDir = PakPath.GetParentDirectoryPath(L"Worlds", false); - if (!WorldsDir.IsEmpty()) - PakPath = FileUtil::MakeRelative(PakPath, WorldsDir); + if (!GameWorldsDir.IsEmpty()) + PakPath = FileUtil::MakeRelative(PakPath, GameWorldsDir); for (u32 iRes = 0; iRes < pPak->NumNamedResources(); iRes++) { @@ -418,7 +418,7 @@ void CGameExporter::ExportWorlds() if (rkRes.Type == "MLVL" && !rkRes.Name.EndsWith("NODEPEND")) { - TResPtr pWorld = (CWorld*) gResCache.GetResource(rkRes.ID, rkRes.Type); + TResPtr pWorld = (CWorld*) gResourceStore.LoadResource(rkRes.ID, rkRes.Type); if (!pWorld) { @@ -451,7 +451,7 @@ void CGameExporter::ExportWorlds() // Load area CUniqueID AreaID = pWorld->AreaResourceID(iArea); - CGameArea *pArea = (CGameArea*) gResCache.GetResource(AreaID, "MREA"); + CGameArea *pArea = (CGameArea*) gResourceStore.LoadResource(AreaID, "MREA"); if (!pArea) { @@ -470,7 +470,7 @@ void CGameExporter::ExportWorlds() ExportResource(*pInst); } - gResCache.Clean(); + gResourceStore.DestroyUnreferencedResources(); } else @@ -485,7 +485,7 @@ void CGameExporter::ExportWorlds() void CGameExporter::ExportCookedResources() { #if EXPORT_COOKED - CResourceDatabase *pResDB = mpProject->ResourceDatabase(); + gResourceStore.CloseActiveProject(); { SCOPED_TIMER(ExportCookedResources); FileUtil::CreateDirectory(mCookedDir + mResDir); @@ -498,7 +498,7 @@ void CGameExporter::ExportCookedResources() } { SCOPED_TIMER(SaveResourceDatabase); - pResDB->Save(this->mExportDir.ToUTF8() + "ResourceDatabase.rdb"); + gResourceStore.SaveResourceDatabase(this->mExportDir.ToUTF8() + "ResourceDatabase.rdb"); } #endif } @@ -532,7 +532,7 @@ void CGameExporter::ExportResource(SResourceInstance& rRes) Out.WriteBytes(ResourceData.data(), ResourceData.size()); // Add to resource DB - mpProject->ResourceDatabase()->RegisterResource(rRes.ResourceID, OutDir, OutName, CResource::ResTypeForExtension(rRes.ResourceType)); + gResourceStore.RegisterResource(rRes.ResourceID, CResource::ResTypeForExtension(rRes.ResourceType), OutDir, OutName); rRes.Exported = true; } } diff --git a/src/Core/GameProject/CGameProject.h b/src/Core/GameProject/CGameProject.h index 76c14d40..5a9e34cd 100644 --- a/src/Core/GameProject/CGameProject.h +++ b/src/Core/GameProject/CGameProject.h @@ -2,7 +2,7 @@ #define CGAMEPROJECT_H #include "CPackage.h" -#include "CResourceDatabase.h" +#include "CResourceStore.h" #include "Core/Resource/EGame.h" #include #include @@ -13,7 +13,7 @@ class CGameProject EGame mGame; TString mProjectName; TWideString mProjectRoot; - CResourceDatabase *mpResourceDatabase; + TWideString mResourceDBPath; std::vector mWorldPaks; std::vector mResourcePaks; @@ -22,13 +22,14 @@ public: : mGame(eUnknownVersion) , mProjectName("UnnamedProject") , mProjectRoot(rkProjRootDir) - , mpResourceDatabase(new CResourceDatabase(this)) + , mResourceDBPath(L"ResourceDB.rdb") {} void AddPackage(CPackage *pPackage, bool WorldPak); // Directory Handling inline TWideString ProjectRoot() const { return mProjectRoot; } + inline TWideString ResourceDBPath(bool Relative) const { return Relative ? mResourceDBPath : mProjectRoot + mResourceDBPath; } inline TWideString DiscDir(bool Relative) const { return Relative ? L"Disc\\" : mProjectRoot + L"Disc\\"; } inline TWideString ResourcesDir(bool Relative) const { return Relative ? L"Resources\\" : mProjectRoot + L"Resources\\"; } inline TWideString WorldsDir(bool Relative) const { return Relative ? L"Worlds\\" : mProjectRoot + L"Worlds\\"; } @@ -44,7 +45,6 @@ public: inline CPackage* WorldPakByIndex(u32 Index) const { return mWorldPaks[Index]; } inline EGame Game() const { return mGame; } - inline CResourceDatabase* ResourceDatabase() const { return mpResourceDatabase; } }; extern CGameProject *gpProject; diff --git a/src/Core/GameProject/CResourceDatabase.cpp b/src/Core/GameProject/CResourceDatabase.cpp deleted file mode 100644 index 0648f99b..00000000 --- a/src/Core/GameProject/CResourceDatabase.cpp +++ /dev/null @@ -1,215 +0,0 @@ -#include "CResourceDatabase.h" -#include "CGameProject.h" -#include "Core/Resource/CResCache.h" -#include -#include -#include -#include - -using namespace tinyxml2; - -// ************ CResourceEntry ************ -bool CResourceEntry::HasRawVersion() const -{ - return FileUtil::Exists(RawAssetPath()); -} - -bool CResourceEntry::HasCookedVersion() const -{ - return FileUtil::Exists(CookedAssetPath()); -} - -TString CResourceEntry::RawAssetPath() const -{ - TWideString Ext = GetRawExtension(mResourceType, mpDatabase->GameProject()->Game()).ToUTF16(); - return mpDatabase->GameProject()->ProjectRoot() + mFileDir + mFileName + L"." + Ext; -} - -TString CResourceEntry::CookedAssetPath() const -{ - TWideString Ext = GetCookedExtension(mResourceType, mpDatabase->GameProject()->Game()).ToUTF16(); - return mpDatabase->GameProject()->CookedDir(false) + mFileDir + mFileName + L"." + Ext; -} - -bool CResourceEntry::NeedsRecook() const -{ - // Assets that do not have a raw version can't be recooked since they will always just be saved cooked to begin with. - // We will recook any asset where the raw version has been updated but not recooked yet. mNeedsRecook can also be - // toggled to arbitrarily flag any asset for recook. - if (!HasRawVersion()) return false; - if (!HasCookedVersion()) return true; - if (mNeedsRecook) return true; - return (FileUtil::LastModifiedTime(CookedAssetPath()) < FileUtil::LastModifiedTime(RawAssetPath())); -} - -// ************ CResourceDatabase ************ -CResourceDatabase::CResourceDatabase(CGameProject *pProj) - : mpProj(pProj) -{} - -CResourceDatabase::~CResourceDatabase() -{ -} - -void CResourceDatabase::Load(const TString& rkPath) -{ - XMLDocument Doc; - Doc.LoadFile(*rkPath); - - if (!Doc.Error()) - { - XMLElement *pRoot = Doc.FirstChildElement("ResourceDatabase"); - //EVersion DatabaseVersion = (EVersion) TString(pRoot->Attribute("Version")).ToInt32(10); // Version currently unused - - XMLElement *pResources = pRoot->FirstChildElement("Resources"); - XMLElement *pRes = pResources->FirstChildElement("Resource"); - u32 ResIndex = 0; - - while (pRes) - { - XMLElement *pChild = pRes->FirstChildElement(); - - bool HasID = false, HasType = false, HasDir = false, HasName = false; - CUniqueID ID; - EResType Type; - TWideString FileDir; - TWideString FileName; - - while (pChild) - { - TString NodeName = pChild->Name(); - - if (NodeName == "ID") - { - ID = CUniqueID::FromString(pChild->GetText()); - HasID = true; - } - - else if (NodeName == "Type") - { - Type = CResource::ResTypeForExtension(pChild->GetText()); - HasType = true; - ASSERT(Type != eInvalidResType); - } - - else if (NodeName == "FileDir") - { - FileDir = pChild->GetText(); - HasDir = true; - } - - else if (NodeName == "FileName") - { - FileName = pChild->GetText(); - HasName = true; - } - - pChild = pChild->NextSiblingElement(); - } - - if (HasID && HasType && HasDir && HasName) - RegisterResource(ID, FileDir, FileName, Type); - else - Log::Error("Error reading " + rkPath + ": Resource entry " + TString::FromInt32(ResIndex, 0, 10) + " is missing one or more components"); - - ResIndex++; - pRes = pRes->NextSiblingElement("Resource"); - } - } -} - -void CResourceDatabase::Save(const TString& rkPath) const -{ - XMLDocument Doc; - - XMLDeclaration *pDecl = Doc.NewDeclaration(); - Doc.LinkEndChild(pDecl); - - XMLElement *pRoot = Doc.NewElement("ResourceDatabase"); - pRoot->SetAttribute("Version", eVer_Current); - Doc.LinkEndChild(pRoot); - - XMLElement *pResources = Doc.NewElement("Resources"); - pRoot->LinkEndChild(pResources); - - for (auto It = mResourceMap.begin(); It != mResourceMap.end(); It++) - { - CResourceEntry *pEntry = It->second; - XMLElement *pRes = Doc.NewElement("Resource"); - pResources->LinkEndChild(pRes); - - XMLElement *pID = Doc.NewElement("ID"); - pID->SetText(*pEntry->ID().ToString()); - pRes->LinkEndChild(pID); - - XMLElement *pType = Doc.NewElement("Type"); - pType->SetText(*GetCookedExtension(pEntry->ResourceType(), mpProj->Game())); - pRes->LinkEndChild(pType); - - XMLElement *pDir = Doc.NewElement("FileDir"); - pDir->SetText(*pEntry->FileDirectory()); - pRes->LinkEndChild(pDir); - - XMLElement *pName = Doc.NewElement("FileName"); - pName->SetText(*pEntry->FileName()); - pRes->LinkEndChild(pName); - - XMLElement *pRecook = Doc.NewElement("NeedsRecook"); - pRecook->SetText(pEntry->NeedsRecook() ? "true" : "false"); - pRes->LinkEndChild(pRecook); - } - - Doc.SaveFile(*rkPath); -} - -CResourceEntry* CResourceDatabase::FindResourceEntry(const CUniqueID& rkID) const -{ - auto Found = mResourceMap.find(rkID); - if (Found == mResourceMap.end()) return nullptr; - else return Found->second; -} - -CResource* CResourceDatabase::LoadResource(const CUniqueID& rkID) const -{ - // todo: no handling for raw assets yet - CResourceEntry *pEntry = FindResourceEntry(rkID); - - if (pEntry) - { - TString AssetPath = pEntry->CookedAssetPath(); - - if (FileUtil::Exists(AssetPath)) - return gResCache.GetResource(pEntry->CookedAssetPath()); - } - - return nullptr; -} - -bool CResourceDatabase::RegisterResource(const CUniqueID& rkID, const TWideString& rkDir, const TWideString& rkFileName, EResType Type) -{ - CResourceEntry *pEntry = FindResourceEntry(rkID); - - if (pEntry) - { - Log::Error("Attempted to register resource that's already tracked in the database: " + rkID.ToString() + " / " + rkDir.ToUTF8() + " / " + rkFileName.ToUTF8()); - return false; - } - - else - { - pEntry = new CResourceEntry(this, rkID, rkDir, rkFileName.GetFileName(false), Type); - - if (!pEntry->HasCookedVersion() && !pEntry->HasRawVersion()) - { - Log::Error("Attempted to register a resource that doesn't exist: " + rkID.ToString() + " | " + rkDir.ToUTF8() + " | " + rkFileName.ToUTF8()); - delete pEntry; - return false; - } - - else - { - mResourceMap[rkID] = pEntry; - return true; - } - } -} diff --git a/src/Core/GameProject/CResourceDatabase.h b/src/Core/GameProject/CResourceDatabase.h deleted file mode 100644 index e7aeae93..00000000 --- a/src/Core/GameProject/CResourceDatabase.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef CRESOURCEDATABASE_H -#define CRESOURCEDATABASE_H - -#include "Core/Resource/CResource.h" -#include -#include -#include -#include - -class CGameProject; -class CResourceDatabase; - -class CResourceEntry -{ - CResourceDatabase *mpDatabase; - CUniqueID mID; - TWideString mFileDir; - TWideString mFileName; - EResType mResourceType; - bool mNeedsRecook; - -public: - CResourceEntry(CResourceDatabase *pDatabase, const CUniqueID& rkID, - const TWideString& rkDir, const TWideString& rkFilename, EResType Type) - : mpDatabase(pDatabase) - , mID(rkID) - , mFileDir(rkDir) - , mFileName(rkFilename) - , mResourceType(Type) - , mNeedsRecook(false) - {} - - bool HasRawVersion() const; - bool HasCookedVersion() const; - TString RawAssetPath() const; - TString CookedAssetPath() const; - bool NeedsRecook() const; - - // Accessors - void SetDirty() { mNeedsRecook = true; } - - inline CUniqueID ID() const { return mID; } - inline TString FileDirectory() const { return mFileDir; } - inline TString FileName() const { return mFileName; } - inline EResType ResourceType() const { return mResourceType; } -}; - -class CResourceDatabase -{ - CGameProject *mpProj; - std::map mResourceMap; - - enum EVersion - { - eVer_Initial, - - eVer_Max, - eVer_Current = eVer_Max - 1 - }; - -public: - CResourceDatabase(CGameProject *pProj); - ~CResourceDatabase(); - void Load(const TString& rkPath); - void Save(const TString& rkPath) const; - - CResourceEntry* FindResourceEntry(const CUniqueID& rkID) const; - CResource* LoadResource(const CUniqueID& rkID) const; - bool RegisterResource(const CUniqueID& rkID, const TWideString& rkDir, const TWideString& rkFileName, EResType Type); - - inline CGameProject* GameProject() const { return mpProj; } -}; - -#endif // CRESOURCEDATABASE_H diff --git a/src/Core/GameProject/CResourceEntry.cpp b/src/Core/GameProject/CResourceEntry.cpp new file mode 100644 index 00000000..5acdbdd0 --- /dev/null +++ b/src/Core/GameProject/CResourceEntry.cpp @@ -0,0 +1,151 @@ +#include "CResourceEntry.h" +#include "CGameProject.h" +#include "CResourceStore.h" +#include "Core/Resource/CResource.h" +#include +#include + +// Resource Loaders +// todo: come up with a factory setup that doesn't suck +#include "Core/Resource/Factory/CAnimationLoader.h" +#include "Core/Resource/Factory/CAnimSetLoader.h" +#include "Core/Resource/Factory/CAreaLoader.h" +#include "Core/Resource/Factory/CCollisionLoader.h" +#include "Core/Resource/Factory/CFontLoader.h" +#include "Core/Resource/Factory/CMaterialLoader.h" +#include "Core/Resource/Factory/CModelLoader.h" +#include "Core/Resource/Factory/CPoiToWorldLoader.h" +#include "Core/Resource/Factory/CScanLoader.h" +#include "Core/Resource/Factory/CScriptLoader.h" +#include "Core/Resource/Factory/CSkeletonLoader.h" +#include "Core/Resource/Factory/CSkinLoader.h" +#include "Core/Resource/Factory/CStringLoader.h" +#include "Core/Resource/Factory/CTextureDecoder.h" +#include "Core/Resource/Factory/CWorldLoader.h" + +CResourceEntry::CResourceEntry(CResourceStore *pStore, const CUniqueID& rkID, + const TWideString& rkDir, const TWideString& rkFilename, + EResType Type, bool Transient /*= false*/) + : mpStore(pStore) + , mpResource(nullptr) + , mID(rkID) + , mFileName(rkFilename) + , mType(Type) + , mNeedsRecook(false) + , mTransient(Transient) +{ + mpDirectory = mpStore->GetVirtualDirectory(rkDir, Transient, true); + if (mpDirectory) mpDirectory->AddChild(L"", this); + mGame = ((mTransient || !mpStore->ActiveProject()) ? eUnknownVersion : mpStore->ActiveProject()->Game()); +} + +CResourceEntry::~CResourceEntry() +{ + if (mpResource) delete mpResource; +} + +bool CResourceEntry::HasRawVersion() const +{ + return FileUtil::Exists(RawAssetPath()); +} + +bool CResourceEntry::HasCookedVersion() const +{ + return FileUtil::Exists(CookedAssetPath()); +} + +TString CResourceEntry::RawAssetPath(bool Relative) const +{ + TWideString Ext = GetResourceRawExtension(mType, mGame).ToUTF16(); + TWideString Path = mpDirectory ? mpDirectory->FullPath() : L""; + TWideString Name = mFileName + L"." + Ext; + return ((mTransient || Relative) ? Path + Name : mpStore->ActiveProject()->ResourcesDir(false) + Path + Name); +} + +TString CResourceEntry::CookedAssetPath(bool Relative) const +{ + TWideString Ext = GetResourceCookedExtension(mType, mGame).ToUTF16(); + TWideString Path = mpDirectory ? mpDirectory->FullPath() : L""; + TWideString Name = mFileName + L"." + Ext; + return ((mTransient || Relative) ? Path + Name : mpStore->ActiveProject()->CookedResourcesDir(false) + Path + Name); +} + +bool CResourceEntry::NeedsRecook() const +{ + // Assets that do not have a raw version can't be recooked since they will always just be saved cooked to begin with. + // We will recook any asset where the raw version has been updated but not recooked yet. mNeedsRecook can also be + // toggled to arbitrarily flag any asset for recook. + if (!HasRawVersion()) return false; + if (!HasCookedVersion()) return true; + if (mNeedsRecook) return true; + return (FileUtil::LastModifiedTime(CookedAssetPath()) < FileUtil::LastModifiedTime(RawAssetPath())); +} + +void CResourceEntry::SetGame(EGame NewGame) +{ + if (mGame != NewGame) + { + // todo: implement checks here. This needs work because we should trigger a recook and if the extension changes + // we should delete the old file. Also a lot of resources can't evaluate this correctly due to file version + // numbers being shared between games. + mGame = NewGame; + } +} + +CResource* CResourceEntry::Load() +{ + // todo: load raw + if (mpResource) return mpResource; + if (!HasCookedVersion()) return nullptr; + + CFileInStream File(CookedAssetPath().ToStdString(), IOUtil::eBigEndian); + if (!File.IsValid()) + { + Log::Error("Failed to open cooked resource: " + CookedAssetPath(true)); + return nullptr; + } + + return Load(File); +} + +CResource* CResourceEntry::Load(IInputStream& rInput) +{ + // Overload to allow for load from an arbitrary input stream. + if (mpResource) return mpResource; + if (!rInput.IsValid()) return nullptr; + + switch (mType) + { + case eAnimation: mpResource = CAnimationLoader::LoadANIM(rInput, this); break; + case eArea: mpResource = CAreaLoader::LoadMREA(rInput, this); break; + case eDynamicCollision: mpResource = CCollisionLoader::LoadDCLN(rInput, this); break; + case eFont: mpResource = CFontLoader::LoadFONT(rInput, this); break; + case eModel: mpResource = CModelLoader::LoadCMDL(rInput, this); break; + case eScan: mpResource = CScanLoader::LoadSCAN(rInput, this); break; + case eSkeleton: mpResource = CSkeletonLoader::LoadCINF(rInput, this); break; + case eSkin: mpResource = CSkinLoader::LoadCSKR(rInput, this); break; + case eStaticGeometryMap: mpResource = CPoiToWorldLoader::LoadEGMC(rInput, this); break; + case eStringTable: mpResource = CStringLoader::LoadSTRG(rInput, this); break; + case eTexture: mpResource = CTextureDecoder::LoadTXTR(rInput, this); break; + case eWorld: mpResource = CWorldLoader::LoadMLVL(rInput, this); break; + + case eAnimSet: + if (mGame <= eEchoes) + mpResource = CAnimSetLoader::LoadANCS(rInput, this); + else + mpResource = CAnimSetLoader::LoadCHAR(rInput, this); + break; + + default: mpResource = new CResource(this); break; + } + + return mpResource; +} + +bool CResourceEntry::Unload() +{ + ASSERT(mpResource != nullptr); + delete mpResource; + mpResource = nullptr; + return true; +} diff --git a/src/Core/GameProject/CResourceEntry.h b/src/Core/GameProject/CResourceEntry.h new file mode 100644 index 00000000..50309a2e --- /dev/null +++ b/src/Core/GameProject/CResourceEntry.h @@ -0,0 +1,55 @@ +#ifndef CRESOURCEENTRY_H +#define CRESOURCEENTRY_H + +#include "CVirtualDirectory.h" +#include "Core/Resource/EResType.h" +#include +#include + +class CResource; +class CResourceStore; + +class CResourceEntry +{ + CResourceStore *mpStore; + CResource *mpResource; + CUniqueID mID; + EResType mType; + EGame mGame; + CVirtualDirectory *mpDirectory; + TWideString mFileName; + bool mNeedsRecook; + bool mTransient; + +public: + CResourceEntry(CResourceStore *pStore, const CUniqueID& rkID, + const TWideString& rkDir, const TWideString& rkFilename, + EResType Type, bool Transient = false); + ~CResourceEntry(); + bool HasRawVersion() const; + bool HasCookedVersion() const; + TString RawAssetPath(bool Relative = false) const; + TString CookedAssetPath(bool Relative = false) const; + bool NeedsRecook() const; + void SetGame(EGame NewGame); + CResource* Load(); + CResource* Load(IInputStream& rInput); + bool Unload(); + + // Accessors + void SetDirty() { mNeedsRecook = true; } + + inline bool IsLoaded() const { return mpResource != nullptr; } + inline CResource* Resource() const { return mpResource; } + inline CUniqueID ID() const { return mID; } + inline EGame Game() const { return mGame; } + inline CVirtualDirectory* Directory() const { return mpDirectory; } + inline TString FileName() const { return mFileName; } + inline EResType ResourceType() const { return mType; } + inline bool IsTransient() const { return mTransient; } + +protected: + CResource* InternalLoad(IInputStream& rInput); +}; + +#endif // CRESOURCEENTRY_H diff --git a/src/Core/GameProject/CResourceStore.cpp b/src/Core/GameProject/CResourceStore.cpp new file mode 100644 index 00000000..825e7771 --- /dev/null +++ b/src/Core/GameProject/CResourceStore.cpp @@ -0,0 +1,403 @@ +#include "CResourceStore.h" +#include "CGameExporter.h" +#include "CGameProject.h" +#include "Core/Resource/CResource.h" +#include +#include +#include +#include + +using namespace tinyxml2; +CResourceStore gResourceStore; + +CResourceStore::CResourceStore() + : mpProj(nullptr) + , mpProjectRoot(nullptr) + , mpExporter(nullptr) +{} + +CResourceStore::~CResourceStore() +{ +} + +void CResourceStore::LoadResourceDatabase(const TString& rkPath) +{ + XMLDocument Doc; + Doc.LoadFile(*rkPath); + + if (!Doc.Error()) + { + XMLElement *pRoot = Doc.FirstChildElement("ResourceDatabase"); + //EDatabaseVersion Version = (EDatabaseVersion) TString(pRoot->Attribute("Version")).ToInt32(10); // Version currently unused + + XMLElement *pResources = pRoot->FirstChildElement("Resources"); + XMLElement *pRes = pResources->FirstChildElement("Resource"); + u32 ResIndex = 0; + + while (pRes) + { + XMLElement *pChild = pRes->FirstChildElement(); + + bool HasID = false, HasType = false, HasDir = false, HasName = false; + CUniqueID ID; + EResType Type; + TWideString FileDir; + TWideString FileName; + + while (pChild) + { + TString NodeName = pChild->Name(); + + if (NodeName == "ID") + { + ID = CUniqueID::FromString(pChild->GetText()); + HasID = true; + } + + else if (NodeName == "Type") + { + Type = CResource::ResTypeForExtension(pChild->GetText()); + HasType = true; + ASSERT(Type != eInvalidResType); + } + + else if (NodeName == "FileDir") + { + FileDir = pChild->GetText(); + HasDir = true; + } + + else if (NodeName == "FileName") + { + FileName = pChild->GetText(); + HasName = true; + } + + pChild = pChild->NextSiblingElement(); + } + + if (HasID && HasType && HasDir && HasName) + RegisterResource(ID, Type, FileDir, FileName); + else + Log::Error("Error reading " + rkPath + ": Resource entry " + TString::FromInt32(ResIndex, 0, 10) + " is missing one or more components"); + + ResIndex++; + pRes = pRes->NextSiblingElement("Resource"); + } + } +} + +void CResourceStore::SaveResourceDatabase(const TString& rkPath) const +{ + XMLDocument Doc; + + XMLDeclaration *pDecl = Doc.NewDeclaration(); + Doc.LinkEndChild(pDecl); + + XMLElement *pRoot = Doc.NewElement("ResourceDatabase"); + pRoot->SetAttribute("Version", eVer_Current); + Doc.LinkEndChild(pRoot); + + XMLElement *pResources = Doc.NewElement("Resources"); + pRoot->LinkEndChild(pResources); + + for (auto It = mResourceEntries.begin(); It != mResourceEntries.end(); It++) + { + CResourceEntry *pEntry = It->second; + if (pEntry->IsTransient()) continue; + + XMLElement *pRes = Doc.NewElement("Resource"); + pResources->LinkEndChild(pRes); + + XMLElement *pID = Doc.NewElement("ID"); + pID->SetText(*pEntry->ID().ToString()); + pRes->LinkEndChild(pID); + + XMLElement *pType = Doc.NewElement("Type"); + pType->SetText(*GetResourceCookedExtension(pEntry->ResourceType(), pEntry->Game())); + pRes->LinkEndChild(pType); + + XMLElement *pDir = Doc.NewElement("FileDir"); + pDir->SetText(*pEntry->Directory()->FullPath().ToUTF8()); + pRes->LinkEndChild(pDir); + + XMLElement *pName = Doc.NewElement("FileName"); + pName->SetText(*pEntry->FileName()); + pRes->LinkEndChild(pName); + + XMLElement *pRecook = Doc.NewElement("NeedsRecook"); + pRecook->SetText(pEntry->NeedsRecook() ? "true" : "false"); + pRes->LinkEndChild(pRecook); + } + + Doc.SaveFile(*rkPath); +} + +void CResourceStore::SetActiveProject(CGameProject *pProj) +{ + if (mpProj == pProj) return; + + CloseActiveProject(); + mpProj = pProj; + + if (pProj) + { + mpProjectRoot = new CVirtualDirectory(); + LoadResourceDatabase(pProj->ResourceDBPath(false)); + } +} + +void CResourceStore::CloseActiveProject() +{ + // Delete all entries from old project + for (auto It = mResourceEntries.begin(); It != mResourceEntries.end(); It++) + { + CResourceEntry *pEntry = It->second; + if (!pEntry->IsTransient()) + { + delete pEntry; + It = mResourceEntries.erase(It); + } + } + + delete mpProjectRoot; + mpProjectRoot = nullptr; + mpProj = nullptr; +} + +CVirtualDirectory* CResourceStore::GetVirtualDirectory(const TWideString& rkPath, bool Transient, bool AllowCreate) +{ + if (rkPath.IsEmpty()) return nullptr; + + else if (Transient) + { + for (u32 iTrans = 0; iTrans < mTransientRoots.size(); iTrans++) + { + if (mTransientRoots[iTrans]->Name() == rkPath) + return mTransientRoots[iTrans]; + } + + if (AllowCreate) + { + CVirtualDirectory *pDir = new CVirtualDirectory(rkPath); + mTransientRoots.push_back(pDir); + return pDir; + } + + else return nullptr; + } + + else if (mpProjectRoot) + { + return mpProjectRoot->FindChildDirectory(rkPath, AllowCreate); + } + + else return nullptr; +} + +CResourceEntry* CResourceStore::FindEntry(const CUniqueID& rkID) const +{ + if (!rkID.IsValid()) return nullptr; + auto Found = mResourceEntries.find(rkID); + if (Found == mResourceEntries.end()) return nullptr; + else return Found->second; +} + +bool CResourceStore::RegisterResource(const CUniqueID& rkID, EResType Type, const TWideString& rkDir, const TWideString& rkFileName) +{ + CResourceEntry *pEntry = FindEntry(rkID); + + if (pEntry) + { + Log::Error("Attempted to register resource that's already tracked in the database: " + rkID.ToString() + " / " + rkDir.ToUTF8() + " / " + rkFileName.ToUTF8()); + return false; + } + + else + { + pEntry = new CResourceEntry(this, rkID, rkDir, rkFileName.GetFileName(false), Type); + + if (!pEntry->HasCookedVersion() && !pEntry->HasRawVersion()) + { + Log::Error("Attempted to register a resource that doesn't exist: " + rkID.ToString() + " | " + rkDir.ToUTF8() + " | " + rkFileName.ToUTF8()); + delete pEntry; + return false; + } + + else + { + mResourceEntries[rkID] = pEntry; + return true; + } + } +} + +CResourceEntry* CResourceStore::CreateTransientEntry(EResType Type, const TWideString& rkDir /*= L""*/, const TWideString& rkFileName /*= L""*/) +{ + CResourceEntry *pEntry = new CResourceEntry(this, CUniqueID::RandomID(), rkDir, rkFileName, Type, true); + mResourceEntries[pEntry->ID()] = pEntry; + return pEntry; +} + +CResourceEntry* CResourceStore::CreateTransientEntry(EResType Type, const CUniqueID& rkID, const TWideString& rkDir /*=L ""*/, const TWideString& rkFileName /*= L""*/) +{ + CResourceEntry *pEntry = new CResourceEntry(this, rkID, rkDir, rkFileName, Type, true); + mResourceEntries[rkID] = pEntry; + return pEntry; +} + +CResource* CResourceStore::LoadResource(const CUniqueID& rkID, const CFourCC& rkType) +{ + if (!rkID.IsValid()) return nullptr; + + // Check if resource is already loaded + auto Find = mLoadedResources.find(rkID); + if (Find != mLoadedResources.end()) + return Find->second->Resource(); + + // With Game Exporter - Get data buffer from exporter + if (mpExporter) + { + std::vector DataBuffer; + mpExporter->LoadResource(rkID, DataBuffer); + if (DataBuffer.empty()) return nullptr; + + CMemoryInStream MemStream(DataBuffer.data(), DataBuffer.size(), IOUtil::eBigEndian); + EResType Type = CResource::ResTypeForExtension(rkType); + CResourceEntry *pEntry = CreateTransientEntry(Type, rkID); + CResource *pRes = pEntry->Load(MemStream); + if (pRes) mLoadedResources[rkID] = pEntry; + return pRes; + } + + // Without Game Exporter - Check store resource entries and transient load directory. + else + { + // Check for resource in store + CResourceEntry *pEntry = FindEntry(rkID); + if (pEntry) return pEntry->Load(); + + // Check in transient load directory + EResType Type = CResource::ResTypeForExtension(rkType); + + if (Type != eInvalidResType) + { + TWideString Name = rkID.ToString().ToUTF16(); + CResourceEntry *pEntry = CreateTransientEntry(Type, mTransientLoadDir, Name); + CResource *pRes = pEntry->Load(); + if (pRes) mLoadedResources[rkID] = pEntry; + return pRes; + } + + else + { + Log::Error("Can't load requested resource with ID \"" + rkID.ToString() + "\"; can't locate resource. Note: Loading raw assets from an arbitrary directory is unsupported.");; + return nullptr; + } + } +} + +CResource* CResourceStore::LoadResource(const TString& rkPath) +{ + // Construct ID from string, check if resource is loaded already + TWideString Dir = FileUtil::MakeAbsolute(TWideString(rkPath.GetFileDirectory())); + TString Name = rkPath.GetFileName(false); + CUniqueID ID = (Name.IsHexString() ? Name.ToInt64() : rkPath.Hash64()); + auto Find = mLoadedResources.find(ID); + + if (Find != mLoadedResources.end()) + return Find->second->Resource(); + + // Determine type + TString Extension = rkPath.GetFileExtension().ToUpper(); + EResType Type = CResource::ResTypeForExtension(Extension); + + if (Type == eInvalidResType) + { + Log::Error("Unable to load resource " + rkPath + "; unrecognized extension: " + Extension); + return nullptr; + } + + TString OldTransientDir = mTransientLoadDir; + mTransientLoadDir = Dir; + CResourceEntry *pEntry = CreateTransientEntry(Type, ID, Dir, Name); + CResource *pRes = pEntry->Load(); + if (pRes) mLoadedResources[ID] = pEntry; + mTransientLoadDir = OldTransientDir; + + return pRes; +} + +CFourCC CResourceStore::ResourceTypeByID(const CUniqueID& rkID, const TStringList& rkPossibleTypes) const +{ + if (!rkID.IsValid()) return eInvalidResType; + if (rkPossibleTypes.size() == 1) return CFourCC(rkPossibleTypes.front()); + + // Check for existing entry + auto Find = mResourceEntries.find(rkID); + if (Find != mResourceEntries.end()) + return GetResourceCookedExtension(Find->second->ResourceType(), Find->second->Game()); + + // Determine extension from filesystem - try every extension until we find the file + TString PathBase = mTransientLoadDir.ToUTF8() + rkID.ToString() + '.'; + + for (auto It = rkPossibleTypes.begin(); It != rkPossibleTypes.end(); It++) + { + TString NewPath = PathBase + *It; + + if (FileUtil::Exists(NewPath)) + return CFourCC(*It); + } + + // Couldn't find one, so return unknown. Note that it'd be possible to look up the extension from the + // filesystem even if it's not one of the provided possible types, but this would be too slow. + return "UNKN"; +} + +void CResourceStore::DestroyUnreferencedResources() +{ + // This can be updated to avoid the do-while loop when reference lookup is implemented. + u32 NumDeleted; + + do + { + NumDeleted = 0; + + for (auto It = mLoadedResources.begin(); It != mLoadedResources.end(); It++) + { + CResourceEntry *pEntry = It->second; + + if (!pEntry->Resource()->IsReferenced()) + { + bool Unloaded = pEntry->Unload(); + + if (Unloaded) + { + It = mLoadedResources.erase(It); + NumDeleted++; + } + } + } + } while (NumDeleted > 0); + + // Destroy empty virtual directories + for (auto DirIt = mTransientRoots.begin(); DirIt != mTransientRoots.end(); DirIt++) + { + CVirtualDirectory *pRoot = *DirIt; + + if (pRoot->IsEmpty()) + { + delete pRoot; + DirIt = mTransientRoots.erase(DirIt); + } + } + + Log::Write(TString::FromInt32(mLoadedResources.size(), 0, 10) + " resources loaded"); +} + +void CResourceStore::SetTransientLoadDir(const TString& rkDir) +{ + mTransientLoadDir = rkDir; + mTransientLoadDir.EnsureEndsWith('\\'); + Log::Write("Set resource directory: " + rkDir); +} diff --git a/src/Core/GameProject/CResourceStore.h b/src/Core/GameProject/CResourceStore.h new file mode 100644 index 00000000..328346ab --- /dev/null +++ b/src/Core/GameProject/CResourceStore.h @@ -0,0 +1,65 @@ +#ifndef CRESOURCEDATABASE_H +#define CRESOURCEDATABASE_H + +#include "CVirtualDirectory.h" +#include "Core/Resource/EResType.h" +#include +#include +#include +#include +#include +#include + +class CGameExporter; +class CGameProject; +class CResource; + +class CResourceStore +{ + CGameProject *mpProj; + CVirtualDirectory *mpProjectRoot; + std::vector mTransientRoots; + std::map mResourceEntries; + std::map mLoadedResources; + + // Directory to look for transient resources in + TWideString mTransientLoadDir; + + // Game exporter currently in use - lets us load from paks being exported + CGameExporter *mpExporter; + + enum EDatabaseVersion + { + eVer_Initial, + + eVer_Max, + eVer_Current = eVer_Max - 1 + }; + +public: + CResourceStore(); + ~CResourceStore(); + void LoadResourceDatabase(const TString& rkPath); + void SaveResourceDatabase(const TString& rkPath) const; + void SetActiveProject(CGameProject *pProj); + void CloseActiveProject(); + CVirtualDirectory* GetVirtualDirectory(const TWideString& rkPath, bool Transient, bool AllowCreate); + + bool RegisterResource(const CUniqueID& rkID, EResType Type, const TWideString& rkDir, const TWideString& rkFileName); + CResourceEntry* FindEntry(const CUniqueID& rkID) const; + CResourceEntry* CreateTransientEntry(EResType Type, const TWideString& rkDir = L"", const TWideString& rkFileName = L""); + CResourceEntry* CreateTransientEntry(EResType Type, const CUniqueID& rkID, const TWideString& rkDir = L"", const TWideString& rkFileName = L""); + + CResource* LoadResource(const CUniqueID& rkID, const CFourCC& rkType); + CResource* LoadResource(const TString& rkPath); + CFourCC ResourceTypeByID(const CUniqueID& rkID, const TStringList& rkPossibleTypes) const; + void DestroyUnreferencedResources(); + void SetTransientLoadDir(const TString& rkDir); + + inline CGameProject* ActiveProject() const { return mpProj; } + inline void SetGameExporter(CGameExporter *pExporter) { mpExporter = pExporter; } +}; + +extern CResourceStore gResourceStore; + +#endif // CRESOURCEDATABASE_H diff --git a/src/Core/GameProject/CVirtualDirectory.cpp b/src/Core/GameProject/CVirtualDirectory.cpp new file mode 100644 index 00000000..85a2fd42 --- /dev/null +++ b/src/Core/GameProject/CVirtualDirectory.cpp @@ -0,0 +1,156 @@ +#include "CVirtualDirectory.h" +#include "CResourceEntry.h" +#include "CResourceStore.h" +#include + +CVirtualDirectory::CVirtualDirectory() + : mpParent(nullptr) +{} + +CVirtualDirectory::CVirtualDirectory(const TWideString& rkName) + : mpParent(nullptr), mName(rkName) +{} + +CVirtualDirectory::CVirtualDirectory(CVirtualDirectory *pParent, const TWideString& rkName) + : mpParent(pParent), mName(rkName) +{} + +CVirtualDirectory::~CVirtualDirectory() +{ + for (u32 iSub = 0; iSub < mSubdirectories.size(); iSub++) + delete mSubdirectories[iSub]; +} + +bool CVirtualDirectory::IsEmpty() const +{ + if (!mResources.empty()) return false; + + for (u32 iSub = 0; iSub < mSubdirectories.size(); iSub++) + if (!mSubdirectories[iSub]->IsEmpty()) return false; + + return true; +} + +TWideString CVirtualDirectory::FullPath() const +{ + return (mpParent && !mpParent->IsRoot() ? mpParent->FullPath() + L'\\' + mName + L"\\" : mName + L"\\"); +} + +CVirtualDirectory* CVirtualDirectory::GetRoot() +{ + return (mpParent ? mpParent->GetRoot() : this); +} + +CVirtualDirectory* CVirtualDirectory::FindChildDirectory(const TWideString& rkName, bool AllowCreate) +{ + u32 SlashIdx = rkName.IndexOf(L"\\/"); + TWideString DirName = (SlashIdx == -1 ? rkName : rkName.SubString(0, SlashIdx)); + + for (u32 iSub = 0; iSub < mSubdirectories.size(); iSub++) + { + CVirtualDirectory *pChild = mSubdirectories[iSub]; + + if (pChild->Name() == DirName) + { + if (SlashIdx == -1) + return pChild; + else + return pChild->FindChildDirectory( rkName.SubString(SlashIdx + 1, rkName.Size() - SlashIdx), AllowCreate ); + } + } + + if (AllowCreate) + { + AddChild(rkName, nullptr); + CVirtualDirectory *pOut = FindChildDirectory(rkName, false); + ASSERT(pOut != nullptr); + return pOut; + } + + return nullptr; +} + +void CVirtualDirectory::AddChild(const TWideString &rkPath, CResourceEntry *pEntry) +{ + if (rkPath.IsEmpty()) + { + if (pEntry) + { +#if !PUBLIC_RELEASE + for (u32 iRes = 0; iRes < mResources.size(); iRes++) + ASSERT(mResources[iRes] != pEntry); +#endif + + mResources.push_back(pEntry); + } + } + + else + { + u32 SlashIdx = rkPath.IndexOf(L"\\/"); + TWideString DirName = (SlashIdx == -1 ? rkPath : rkPath.SubString(0, SlashIdx)); + CVirtualDirectory *pSubdir = nullptr; + + // Check if this subdirectory already exists + for (u32 iSub = 0; iSub < mSubdirectories.size(); iSub++) + { + if (mSubdirectories[iSub]->Name() == DirName) + { + pSubdir = mSubdirectories[iSub]; + break; + } + } + + if (!pSubdir) + { + pSubdir = new CVirtualDirectory(this, DirName); + mSubdirectories.push_back(pSubdir); + + std::sort(mSubdirectories.begin(), mSubdirectories.end(), [](CVirtualDirectory *pLeft, CVirtualDirectory *pRight) -> bool { + return (pLeft->Name() < pRight->Name()); + }); + } + + TWideString Remaining = (SlashIdx == -1 ? L"" : rkPath.SubString(SlashIdx + 1, rkPath.Size() - SlashIdx)); + pSubdir->AddChild(Remaining, pEntry); + } +} + +bool CVirtualDirectory::RemoveChildDirectory(CVirtualDirectory *pSubdir) +{ + ASSERT(pSubdir->IsEmpty()); + + for (auto It = mSubdirectories.begin(); It != mSubdirectories.end(); It++) + { + if (*It == pSubdir) + { + mSubdirectories.erase(It); + delete pSubdir; + + if (mpParent && IsEmpty()) + mpParent->RemoveChildDirectory(this); + + return true; + } + } + + return false; +} + +bool CVirtualDirectory::RemoveChildResource(CResourceEntry *pEntry) +{ + for (auto It = mResources.begin(); It != mResources.end(); It++) + { + if (*It == pEntry) + { + mResources.erase(It); + + if (mpParent && IsEmpty()) + mpParent->RemoveChildDirectory(this); + + return true; + } + } + + return false; +} diff --git a/src/Core/GameProject/CVirtualDirectory.h b/src/Core/GameProject/CVirtualDirectory.h new file mode 100644 index 00000000..f599568a --- /dev/null +++ b/src/Core/GameProject/CVirtualDirectory.h @@ -0,0 +1,44 @@ +#ifndef CVIRTUALDIRECTORY +#define CVIRTUALDIRECTORY + +/* Virtual directory system used to look up resources by their location in the filesystem. */ +#include +#include +#include + +class CResourceEntry; + +class CVirtualDirectory +{ + CVirtualDirectory *mpParent; + TWideString mName; + std::vector mSubdirectories; + std::vector mResources; + +public: + CVirtualDirectory(); + CVirtualDirectory(const TWideString& rkName); + CVirtualDirectory(CVirtualDirectory *pParent, const TWideString& rkName); + ~CVirtualDirectory(); + + bool IsEmpty() const; + TWideString FullPath() const; + CVirtualDirectory* GetRoot(); + CVirtualDirectory* FindChildDirectory(const TWideString& rkName, bool AllowCreate); + void AddChild(const TWideString& rkPath, CResourceEntry *pEntry); + bool RemoveChildDirectory(CVirtualDirectory *pSubdir); + bool RemoveChildResource(CResourceEntry *pEntry); + + // Accessors + inline CVirtualDirectory* Parent() const { return mpParent; } + inline bool IsRoot() const { return !mpParent; } + inline TWideString Name() const { return mName; } + + inline u32 NumSubdirectories() const { return mSubdirectories.size(); } + inline CVirtualDirectory* SubdirectoryByIndex(u32 Index) { return mSubdirectories[Index]; } + inline u32 NumResources() const { return mResources.size(); } + inline CResourceEntry* ResourceByIndex(u32 Index) { return mResources[Index]; } +}; + +#endif // CVIRTUALDIRECTORY + diff --git a/src/Core/Render/CDrawUtil.cpp b/src/Core/Render/CDrawUtil.cpp index 654d9409..e5cca4c9 100644 --- a/src/Core/Render/CDrawUtil.cpp +++ b/src/Core/Render/CDrawUtil.cpp @@ -1,6 +1,6 @@ #include "CDrawUtil.h" #include "CGraphics.h" -#include "Core/Resource/CResCache.h" +#include "Core/GameProject/CResourceStore.h" #include #include #include @@ -480,7 +480,7 @@ void CDrawUtil::InitLine() void CDrawUtil::InitCube() { Log::Write("Creating cube"); - mpCubeModel = gResCache.GetResource("../resources/Cube.cmdl"); + mpCubeModel = gResourceStore.LoadResource("../resources/Cube.cmdl"); } void CDrawUtil::InitWireCube() @@ -518,14 +518,14 @@ void CDrawUtil::InitWireCube() void CDrawUtil::InitSphere() { Log::Write("Creating sphere"); - mpSphereModel = gResCache.GetResource("../resources/Sphere.cmdl"); - mpDoubleSidedSphereModel = gResCache.GetResource("../resources/SphereDoubleSided.cmdl"); + mpSphereModel = gResourceStore.LoadResource("../resources/Sphere.cmdl"); + mpDoubleSidedSphereModel = gResourceStore.LoadResource("../resources/SphereDoubleSided.cmdl"); } void CDrawUtil::InitWireSphere() { Log::Write("Creating wire sphere"); - mpWireSphereModel = gResCache.GetResource("../resources/WireSphere.cmdl"); + mpWireSphereModel = gResourceStore.LoadResource("../resources/WireSphere.cmdl"); } void CDrawUtil::InitShaders() @@ -543,17 +543,17 @@ void CDrawUtil::InitShaders() void CDrawUtil::InitTextures() { Log::Write("Loading textures"); - mpCheckerTexture = gResCache.GetResource("../resources/Checkerboard.txtr"); + mpCheckerTexture = gResourceStore.LoadResource("../resources/Checkerboard.txtr"); - mpLightTextures[0] = gResCache.GetResource("../resources/LightAmbient.txtr"); - mpLightTextures[1] = gResCache.GetResource("../resources/LightDirectional.txtr"); - mpLightTextures[2] = gResCache.GetResource("../resources/LightCustom.txtr"); - mpLightTextures[3] = gResCache.GetResource("../resources/LightSpot.txtr"); + mpLightTextures[0] = gResourceStore.LoadResource("../resources/LightAmbient.txtr"); + mpLightTextures[1] = gResourceStore.LoadResource("../resources/LightDirectional.txtr"); + mpLightTextures[2] = gResourceStore.LoadResource("../resources/LightCustom.txtr"); + mpLightTextures[3] = gResourceStore.LoadResource("../resources/LightSpot.txtr"); - mpLightMasks[0] = gResCache.GetResource("../resources/LightAmbientMask.txtr"); - mpLightMasks[1] = gResCache.GetResource("../resources/LightDirectionalMask.txtr"); - mpLightMasks[2] = gResCache.GetResource("../resources/LightCustomMask.txtr"); - mpLightMasks[3] = gResCache.GetResource("../resources/LightSpotMask.txtr"); + mpLightMasks[0] = gResourceStore.LoadResource("../resources/LightAmbientMask.txtr"); + mpLightMasks[1] = gResourceStore.LoadResource("../resources/LightDirectionalMask.txtr"); + mpLightMasks[2] = gResourceStore.LoadResource("../resources/LightCustomMask.txtr"); + mpLightMasks[3] = gResourceStore.LoadResource("../resources/LightSpotMask.txtr"); } void CDrawUtil::Shutdown() diff --git a/src/Core/Render/CRenderer.cpp b/src/Core/Render/CRenderer.cpp index e1368749..fba261fc 100644 --- a/src/Core/Render/CRenderer.cpp +++ b/src/Core/Render/CRenderer.cpp @@ -2,7 +2,7 @@ #include "CDrawUtil.h" #include "CGraphics.h" -#include "Core/Resource/CResCache.h" +#include "Core/GameProject/CResourceStore.h" #include "Core/Resource/Factory/CTextureDecoder.h" #include diff --git a/src/Core/Resource/CGameArea.cpp b/src/Core/Resource/Area/CGameArea.cpp similarity index 98% rename from src/Core/Resource/CGameArea.cpp rename to src/Core/Resource/Area/CGameArea.cpp index 4df785ad..37e89d38 100644 --- a/src/Core/Resource/CGameArea.cpp +++ b/src/Core/Resource/Area/CGameArea.cpp @@ -2,8 +2,8 @@ #include "Core/Resource/Script/CScriptLayer.h" #include "Core/Render/CRenderer.h" -CGameArea::CGameArea() - : CResource() +CGameArea::CGameArea(CResourceEntry *pEntry /*= 0*/) + : CResource(pEntry) , mWorldIndex(-1) , mVertexCount(0) , mTriangleCount(0) diff --git a/src/Core/Resource/CGameArea.h b/src/Core/Resource/Area/CGameArea.h similarity index 94% rename from src/Core/Resource/CGameArea.h rename to src/Core/Resource/Area/CGameArea.h index 356e9793..ddb31453 100644 --- a/src/Core/Resource/CGameArea.h +++ b/src/Core/Resource/Area/CGameArea.h @@ -1,11 +1,11 @@ #ifndef CGAMEAREA_H #define CGAMEAREA_H -#include "CResource.h" -#include "CCollisionMeshGroup.h" -#include "CLight.h" -#include "CMaterialSet.h" -#include "CPoiToWorld.h" +#include "Core/Resource/CResource.h" +#include "Core/Resource/CCollisionMeshGroup.h" +#include "Core/Resource/CLight.h" +#include "Core/Resource/CMaterialSet.h" +#include "Core/Resource/CPoiToWorld.h" #include "Core/Resource/Model/CModel.h" #include "Core/Resource/Model/CStaticModel.h" #include @@ -60,7 +60,7 @@ class CGameArea : public CResource TResPtr mpPoiToWorldMap; public: - CGameArea(); + CGameArea(CResourceEntry *pEntry = 0); ~CGameArea(); void AddWorldModel(CModel *pModel); diff --git a/src/Core/Resource/CAnimSet.h b/src/Core/Resource/CAnimSet.h index 446f0a70..eada6963 100644 --- a/src/Core/Resource/CAnimSet.h +++ b/src/Core/Resource/CAnimSet.h @@ -36,7 +36,7 @@ class CAnimSet : public CResource std::vector mAnims; public: - CAnimSet() : CResource() {} + CAnimSet(CResourceEntry *pEntry = 0) : CResource(pEntry) {} u32 NumNodes() const { return mNodes.size(); } TString NodeName(u32 Index) { if (Index >= mNodes.size()) Index = 0; return mNodes[Index].Name; } diff --git a/src/Core/Resource/CAnimation.cpp b/src/Core/Resource/CAnimation.cpp index 51c5152b..b9ac8afc 100644 --- a/src/Core/Resource/CAnimation.cpp +++ b/src/Core/Resource/CAnimation.cpp @@ -2,8 +2,9 @@ #include #include -CAnimation::CAnimation() - : mDuration(0.f) +CAnimation::CAnimation(CResourceEntry *pEntry /*= 0*/) + : CResource(pEntry) + , mDuration(0.f) , mTickInterval(0.0333333f) , mNumKeys(0) { diff --git a/src/Core/Resource/CAnimation.h b/src/Core/Resource/CAnimation.h index 267789bb..104f3360 100644 --- a/src/Core/Resource/CAnimation.h +++ b/src/Core/Resource/CAnimation.h @@ -32,7 +32,7 @@ class CAnimation : public CResource SBoneChannelInfo mBoneInfo[100]; public: - CAnimation(); + CAnimation(CResourceEntry *pEntry = 0); void EvaluateTransform(float Time, u32 BoneID, CVector3f *pOutTranslation, CQuaternion *pOutRotation, CVector3f *pOutScale) const; bool HasTranslation(u32 BoneID) const; diff --git a/src/Core/Resource/CAnimationParameters.cpp b/src/Core/Resource/CAnimationParameters.cpp index 61f82012..bdc9ed70 100644 --- a/src/Core/Resource/CAnimationParameters.cpp +++ b/src/Core/Resource/CAnimationParameters.cpp @@ -1,7 +1,7 @@ #include "CAnimationParameters.h" #include "CAnimSet.h" -#include "CResCache.h" #include "CResourceInfo.h" +#include "Core/GameProject/CResourceStore.h" #include #include diff --git a/src/Core/Resource/CCollisionMeshGroup.h b/src/Core/Resource/CCollisionMeshGroup.h index 38fe14e7..8d4d2328 100644 --- a/src/Core/Resource/CCollisionMeshGroup.h +++ b/src/Core/Resource/CCollisionMeshGroup.h @@ -12,7 +12,7 @@ class CCollisionMeshGroup : public CResource std::vector mMeshes; public: - CCollisionMeshGroup() {} + CCollisionMeshGroup(CResourceEntry *pEntry = 0) : CResource(pEntry) {} ~CCollisionMeshGroup() { diff --git a/src/Core/Resource/CFont.cpp b/src/Core/Resource/CFont.cpp index f1d6e951..6add9989 100644 --- a/src/Core/Resource/CFont.cpp +++ b/src/Core/Resource/CFont.cpp @@ -1,5 +1,5 @@ #include "CFont.h" -#include "CResCache.h" +#include "Core/GameProject/CResourceStore.h" #include "Core/Render/CDrawUtil.h" #include "Core/Render/CRenderer.h" @@ -7,7 +7,7 @@ CDynamicVertexBuffer CFont::smGlyphVertices; CIndexBuffer CFont::smGlyphIndices; bool CFont::smBuffersInitialized = false; -CFont::CFont() : CResource() +CFont::CFont(CResourceEntry *pEntry /*= 0*/) : CResource(pEntry) { } diff --git a/src/Core/Resource/CFont.h b/src/Core/Resource/CFont.h index 1af8c9bc..e33f5262 100644 --- a/src/Core/Resource/CFont.h +++ b/src/Core/Resource/CFont.h @@ -58,7 +58,7 @@ class CFont : public CResource public: - CFont(); + CFont(CResourceEntry *pEntry = 0); ~CFont(); CResource* MakeCopy(CResCache *pCopyCache); CVector2f RenderString(const TString& rkString, CRenderer *pRenderer, float AspectRatio, diff --git a/src/Core/Resource/CMaterial.cpp b/src/Core/Resource/CMaterial.cpp index bd0a6a91..f27f501c 100644 --- a/src/Core/Resource/CMaterial.cpp +++ b/src/Core/Resource/CMaterial.cpp @@ -1,5 +1,5 @@ #include "CMaterial.h" -#include "CResCache.h" +#include "Core/GameProject/CResourceStore.h" #include "Core/Render/CDrawUtil.h" #include "Core/Render/CRenderer.h" #include "Core/OpenGL/GLCommon.h" diff --git a/src/Core/Resource/CPoiToWorld.cpp b/src/Core/Resource/CPoiToWorld.cpp index 6d26ea5b..3cd124b5 100644 --- a/src/Core/Resource/CPoiToWorld.cpp +++ b/src/Core/Resource/CPoiToWorld.cpp @@ -1,6 +1,7 @@ #include "CPoiToWorld.h" -CPoiToWorld::CPoiToWorld() +CPoiToWorld::CPoiToWorld(CResourceEntry *pEntry /*= 0*/) + : CResource(pEntry) { } diff --git a/src/Core/Resource/CPoiToWorld.h b/src/Core/Resource/CPoiToWorld.h index 6d9001ee..262e4358 100644 --- a/src/Core/Resource/CPoiToWorld.h +++ b/src/Core/Resource/CPoiToWorld.h @@ -22,7 +22,7 @@ private: std::map mPoiLookupMap; public: - CPoiToWorld(); + CPoiToWorld(CResourceEntry *pEntry = 0); ~CPoiToWorld(); void AddPoi(u32 PoiID); diff --git a/src/Core/Resource/CResCache.cpp b/src/Core/Resource/CResCache.cpp deleted file mode 100644 index 60fa696d..00000000 --- a/src/Core/Resource/CResCache.cpp +++ /dev/null @@ -1,209 +0,0 @@ -#include "CResCache.h" -#include "Core/Resource/Factory/CAreaLoader.h" -#include "Core/Resource/Factory/CAnimationLoader.h" -#include "Core/Resource/Factory/CAnimSetLoader.h" -#include "Core/Resource/Factory/CCollisionLoader.h" -#include "Core/Resource/Factory/CFontLoader.h" -#include "Core/Resource/Factory/CModelLoader.h" -#include "Core/Resource/Factory/CPoiToWorldLoader.h" -#include "Core/Resource/Factory/CScanLoader.h" -#include "Core/Resource/Factory/CSkeletonLoader.h" -#include "Core/Resource/Factory/CSkinLoader.h" -#include "Core/Resource/Factory/CStringLoader.h" -#include "Core/Resource/Factory/CTextureDecoder.h" -#include "Core/Resource/Factory/CWorldLoader.h" - -#include -#include -#include -#include -#include -#include - -CResCache::CResCache() - : mpGameExporter(nullptr) -{ -} - -CResCache::~CResCache() -{ - Clean(); -} - -void CResCache::Clean() -{ - if (mResourceCache.empty()) return; - Log::Write("Cleaning unused resources"); - - // I couldn't get this to work properly using reverse iterators, lol. - // Resources get cached after their dependencies, which is why I go backwards - // while loop is to ensure -all- unused resources are cleaned. Not sure of a better way to do it. - int NumResourcesCleaned = 1; - - while (NumResourcesCleaned) - { - NumResourcesCleaned = 0; - - for (auto it = mResourceCache.end(); it != mResourceCache.begin();) - { - it--; - if (it->second->mRefCount <= 0) - { - delete it->second; - it = mResourceCache.erase(it); - NumResourcesCleaned++; - } - } - } - Log::Write(std::to_string(mResourceCache.size()) + " resources loaded"); -} - -void CResCache::SetFolder(TString Path) -{ - Path.EnsureEndsWith("/"); - mResDir = Path; - Log::Write("Set resource folder: " + Path); -} - -TString CResCache::GetSourcePath() -{ - return mResDir; -} - -CResource* CResCache::GetResource(CUniqueID ResID, CFourCC Type) -{ - if (!ResID.IsValid()) return nullptr; - TString StringName = ResID.ToString() + "." + Type.ToString(); - - // With Game Exporter - get data buffer from exporter - if (mpGameExporter) - { - // Check if we already have resource loaded - auto Got = mResourceCache.find(ResID.ToLongLong()); - if (Got != mResourceCache.end()) - return Got->second; - - // Otherwise load resource - std::vector DataBuffer; - mpGameExporter->LoadResource(ResID, DataBuffer); - if (DataBuffer.empty()) return nullptr; - - CMemoryInStream MemStream(DataBuffer.data(), DataBuffer.size(), IOUtil::eBigEndian); - CResource *pRes = InternalLoadResource(MemStream, ResID, Type); - pRes->mResSource = StringName; - return pRes; - } - - // Without Game Exporter - load from file - else - { - TString Source = mResDir + StringName; - return GetResource(Source); - } -} - -CResource* CResCache::GetResource(const TString& rkResPath) -{ - CUniqueID ResID = rkResPath.Hash64(); - - // Check if resource already exists - auto Got = mResourceCache.find(ResID.ToLongLong()); - - if (Got != mResourceCache.end()) - return Got->second; - - // Open file - CFileInStream File(rkResPath.ToStdString(), IOUtil::eBigEndian); - if (!File.IsValid()) - { - Log::Error("Couldn't open resource: " + rkResPath); - return nullptr; - } - - // Save old ResDir to restore later - TString OldResDir = mResDir; - mResDir = rkResPath.GetFileDirectory(); - - // Load resource - CFourCC Type = rkResPath.GetFileExtension().ToUpper(); - CResource *pRes = InternalLoadResource(File, ResID, Type); - pRes->mResSource = rkResPath; - - // Add to cache and cleanup - mResDir = OldResDir; - return pRes; -} - -CFourCC CResCache::FindResourceType(CUniqueID ResID, const TStringList& rkPossibleTypes) -{ - // If we only have one type then there's only one possibility. - if (rkPossibleTypes.size() == 1) - return CFourCC(rkPossibleTypes.front()); - - // Determine extension from filesystem - try every extension until we find one that works - TString PathBase = mResDir + ResID.ToString() + "."; - - for (auto it = rkPossibleTypes.begin(); it != rkPossibleTypes.end(); it++) - { - TString NewPath = PathBase + *it; - - if (FileUtil::Exists(NewPath)) - return CFourCC(*it); - } - - return "UNKN"; -} - -void CResCache::CacheResource(CResource *pRes) -{ - u64 ID = pRes->ResID().ToLongLong(); - auto Got = mResourceCache.find(ID); - - if (Got != mResourceCache.end()) - mResourceCache[ID] = pRes; -} - -void CResCache::DeleteResource(CUniqueID ResID) -{ - auto Got = mResourceCache.find(ResID.ToLongLong()); - - if (Got != mResourceCache.end()) - { - delete Got->second; - mResourceCache.erase(Got, Got); - } -} - -// ************ PROTECTED ************ -CResource* CResCache::InternalLoadResource(IInputStream& rInput, const CUniqueID& rkID, CFourCC Type) -{ - // todo - need some sort of auto-registration of loaders to avoid this if-else mess - ASSERT(mResourceCache.find(rkID.ToLongLong()) == mResourceCache.end()); // this test should be done before calling this func! - CResource *pRes = nullptr; - - // Load resource - if (Type == "CMDL") pRes = CModelLoader::LoadCMDL(rInput); - else if (Type == "TXTR") pRes = CTextureDecoder::LoadTXTR(rInput); - else if (Type == "ANCS") pRes = CAnimSetLoader::LoadANCS(rInput); - else if (Type == "CHAR") pRes = CAnimSetLoader::LoadCHAR(rInput); - else if (Type == "MREA") pRes = CAreaLoader::LoadMREA(rInput); - else if (Type == "MLVL") pRes = CWorldLoader::LoadMLVL(rInput); - else if (Type == "STRG") pRes = CStringLoader::LoadSTRG(rInput); - else if (Type == "FONT") pRes = CFontLoader::LoadFONT(rInput); - else if (Type == "SCAN") pRes = CScanLoader::LoadSCAN(rInput); - else if (Type == "DCLN") pRes = CCollisionLoader::LoadDCLN(rInput); - else if (Type == "EGMC") pRes = CPoiToWorldLoader::LoadEGMC(rInput); - else if (Type == "CINF") pRes = CSkeletonLoader::LoadCINF(rInput); - else if (Type == "ANIM") pRes = CAnimationLoader::LoadANIM(rInput); - else if (Type == "CSKR") pRes = CSkinLoader::LoadCSKR(rInput); - if (!pRes) pRes = new CResource(); // Default for unsupported formats - - ASSERT(pRes->mRefCount == 0); - - // Cache and return - pRes->mID = rkID; - mResourceCache[rkID.ToLongLong()] = pRes; - return pRes; -} - -CResCache gResCache; diff --git a/src/Core/Resource/CResCache.h b/src/Core/Resource/CResCache.h deleted file mode 100644 index 9c4f8120..00000000 --- a/src/Core/Resource/CResCache.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef CRESCACHE_H -#define CRESCACHE_H - -#include "CResource.h" -#include "Core/GameProject/CGameExporter.h" -#include -#include -#include - -class CResCache -{ - std::unordered_map mResourceCache; - TString mResDir; - CGameExporter *mpGameExporter; - -public: - CResCache(); - ~CResCache(); - void Clean(); - void SetFolder(TString Path); - TString GetSourcePath(); - CResource* GetResource(CUniqueID ResID, CFourCC Type); - CResource* GetResource(const TString& rkResPath); - CFourCC FindResourceType(CUniqueID ResID, const TStringList& rkPossibleTypes); - void CacheResource(CResource *pRes); - void DeleteResource(CUniqueID ResID); - - inline void SetGameExporter(CGameExporter *pExporter) { mpGameExporter = pExporter; } - -protected: - CResource* InternalLoadResource(IInputStream& rInput, const CUniqueID& rkID, CFourCC Type); -}; - -extern CResCache gResCache; - -#endif // CRESCACHE_H diff --git a/src/Core/Resource/CResource.cpp b/src/Core/Resource/CResource.cpp index fa8afcfe..c7278f48 100644 --- a/src/Core/Resource/CResource.cpp +++ b/src/Core/Resource/CResource.cpp @@ -1,4 +1,5 @@ #include "CResource.h" +#include "Core/GameProject/CResourceStore.h" #include #include @@ -24,14 +25,89 @@ EResType CResource::ResTypeForExtension(CFourCC Extension) return Find->second; } -// Implementation of functions declared in EResType.h -TString GetRawExtension(EResType /*Type*/, EGame /*Game*/) +// ************ GLOBAL ************ +TString GetResourceTypeName(EResType Type) +{ + switch (Type) + { + case eAnimation: return "Animation"; + case eAnimCollisionPrimData: return "Animation Collision Primitive Data"; + case eAnimEventData: return "Animation Event Data"; + case eAnimSet: return "Animation Character Set"; + case eArea: return "Area"; + case eAreaCollision: return "Area Collision"; + case eAreaGeometry: return "Area Geometry"; + case eAreaLights: return "Area Lights"; + case eAreaMaterials: return "Area Materials"; + case eAreaSurfaceBounds: return "Area Surface Bounds"; + case eAreaOctree: return "Area Octree"; + case eAreaVisibilityTree: return "Area Visibility Tree"; + case eAudioGroupSet: return "Audio Group Set"; + case eAudioMacro: return "Audio Macro"; + case eAudioSample: return "Audio Sample"; + case eAudioLookupTable: return "Audio Lookup Table"; + case eBinaryData: return "Binary Data"; + case eBurstFireData: return "Burst Fire Data"; + case eCharacter: return "Character"; + case eDependencyGroup: return "Dependency Group"; + case eDynamicCollision: return "Dynamic Collision"; + case eFont: return "Font"; + case eGuiFrame: return "GUI Frame"; + case eGuiKeyFrame: return "GUI Keyframe"; + case eHintSystem: return "Hint System"; + case eMapArea: return "Area Map"; + case eMapWorld: return "World Map"; + case eMapUniverse: return "Universe Map"; + case eMidi: return "MIDI"; + case eModel: return "Model"; + case eMusicTrack: return "Music"; + case ePackage: return "Package"; + case eParticle: return "Particle System"; + case eParticleCollisionResponse: return "Collision Response Particle System"; + case eParticleDecal: return "Decal Particle System"; + case eParticleElectric: return "Electric Particle System"; + case eParticleSorted: return "Sorted Particle System"; + case eParticleSpawn: return "Spawn Particle System"; + case eParticleSwoosh: return "Swoosh Particle System"; + case eParticleTransform: return "Transform Particle System"; + case eParticleWeapon: return "Weapon Particle System"; + case ePathfinding: return "Pathfinding Mesh"; + case ePortalArea: return "Portal Area"; + case eResource: return "Resource"; + case eRuleSet: return "Rule Set"; + case eSaveArea: return "Area Save Info"; + case eSaveWorld: return "World Save Info"; + case eScan: return "Scan"; + case eSkeleton: return "Skeleton"; + case eSkin: return "Skin"; + case eSourceAnimData: return "Source Animation Data"; + case eSpatialPrimitive: return "Spatial Primitive"; + case eStateMachine: return "State Machine"; + case eStateMachine2: return "State Machine"; + case eStaticGeometryMap: return "Static Geometry Map"; + case eStreamedAudio: return "Streamed Audio"; + case eStringList: return "String List"; + case eStringTable: return "String Table"; + case eTexture: return "Texture"; + case eTweak: return "Tweak Data"; + case eUnknown_CAAD: return "Unknown (CAAD)"; + case eUserEvaluatorData: return "User Evaluator Data"; + case eVideo: return "Video"; + case eWorld: return "World"; + default: return "INVALID"; + } +} + +TString GetResourceRawExtension(EResType /*Type*/, EGame /*Game*/) { return ""; } -TString GetCookedExtension(EResType Type, EGame Game) +TString GetResourceCookedExtension(EResType Type, EGame Game) { + if (Game == eUnknownVersion) + Game = ePrime; + u32 GameTypeID = GetGameTypeID(Game, Type); auto Find = gTypeExtensionMap.find(GameTypeID); if (Find != gTypeExtensionMap.end()) return Find->second; @@ -138,3 +214,11 @@ REGISTER_RESOURCE_TYPE(TXTR, eTexture, ePrimeDemo, eReturns) REGISTER_RESOURCE_TYPE(USRC, eUserEvaluatorData, eCorruptionProto, eCorruption) REGISTER_RESOURCE_TYPE(XFSC, eParticleTransform, eReturns, eReturns) REGISTER_RESOURCE_TYPE(WPSC, eParticleWeapon, ePrimeDemo, eCorruption) +// Split Area Data +REGISTER_RESOURCE_TYPE(AMAT, eAreaMaterials, ePrimeDemo, eReturns) +REGISTER_RESOURCE_TYPE(AGEO, eAreaGeometry, ePrimeDemo, eReturns) +REGISTER_RESOURCE_TYPE(AOCT, eAreaOctree, ePrimeDemo, eReturns) +REGISTER_RESOURCE_TYPE(ABOX, eAreaSurfaceBounds, eEchoesDemo, eReturns) +REGISTER_RESOURCE_TYPE(ACLN, eAreaCollision, ePrimeDemo, eReturns) +REGISTER_RESOURCE_TYPE(ALIT, eAreaLights, ePrimeDemo, eReturns) +REGISTER_RESOURCE_TYPE(AVIS, eAreaVisibilityTree, ePrimeDemo, eReturns) diff --git a/src/Core/Resource/CResource.h b/src/Core/Resource/CResource.h index 73c39cba..722bb146 100644 --- a/src/Core/Resource/CResource.h +++ b/src/Core/Resource/CResource.h @@ -2,6 +2,8 @@ #define CRESOURCE_H #include "EResType.h" +#include "Core/GameProject/CResourceEntry.h" +#include "Core/GameProject/CResourceStore.h" #include #include #include @@ -28,24 +30,35 @@ private: \ class CResource { DECLARE_RESOURCE_TYPE(eResource) - friend class CResCache; - TString mResSource; - CUniqueID mID; + CResourceEntry *mpEntry; int mRefCount; public: - CResource() : mRefCount(0) {} + CResource(CResourceEntry *pEntry = 0) + : mpEntry(pEntry), mRefCount(0) + { + if (!mpEntry) mpEntry = gResourceStore.CreateTransientEntry(Type()); + } + virtual ~CResource() {} - inline TString Source() const { return mResSource.GetFileName(); } - inline TString FullSource() const { return mResSource; } - inline CUniqueID ResID() const { return mID; } - inline void Lock() { mRefCount++; } - inline void Release() { mRefCount--; } - inline bool IsValidResource() { return (Type() != eResource); } + inline CResourceEntry* Entry() const { return mpEntry; } + inline TString Source() const { return mpEntry->CookedAssetPath(true).GetFileName(); } + inline TString FullSource() const { return mpEntry->CookedAssetPath(true); } + inline CUniqueID ResID() const { return mpEntry->ID(); } + inline EGame Game() const { return mpEntry->Game(); } + inline bool IsReferenced() const { return mRefCount > 0; } + inline void SetGame(EGame Game) { mpEntry->SetGame(Game); } + inline void Lock() { mRefCount++; } + inline void Release() { mRefCount--; } static EResType ResTypeForExtension(CFourCC Extension); }; +// Global Functions +TString GetResourceTypeName(EResType Type); +TString GetResourceRawExtension(EResType Type, EGame Game); +TString GetResourceCookedExtension(EResType Type, EGame Game); + #endif // CRESOURCE_H diff --git a/src/Core/Resource/CResourceInfo.h b/src/Core/Resource/CResourceInfo.h index 628b9cbb..854381fd 100644 --- a/src/Core/Resource/CResourceInfo.h +++ b/src/Core/Resource/CResourceInfo.h @@ -2,7 +2,7 @@ #define CRESOURCEINFO #include "CResource.h" -#include "CResCache.h" +#include "Core/GameProject/CResourceStore.h" #include #include #include @@ -60,9 +60,9 @@ public: if (!IsValid()) return nullptr; if (mIsPath) - return gResCache.GetResource(mPath); + return gResourceStore.LoadResource(mPath); else - return gResCache.GetResource(ID(), Type()); + return gResourceStore.LoadResource(ID(), Type()); } inline bool IsValid() const diff --git a/src/Core/Resource/CScan.h b/src/Core/Resource/CScan.h index c7097f6d..3c070910 100644 --- a/src/Core/Resource/CScan.h +++ b/src/Core/Resource/CScan.h @@ -31,8 +31,8 @@ private: ELogbookCategory mCategory; public: - CScan() - : CResource() + CScan(CResourceEntry *pEntry = 0) + : CResource(pEntry) , mpFrame(nullptr) , mpStringTable(nullptr) , mIsSlow(false) diff --git a/src/Core/Resource/CSkeleton.cpp b/src/Core/Resource/CSkeleton.cpp index 10656e5f..6dd93b3b 100644 --- a/src/Core/Resource/CSkeleton.cpp +++ b/src/Core/Resource/CSkeleton.cpp @@ -62,8 +62,9 @@ bool CBone::IsRoot() const // ************ CSkeleton ************ const float CSkeleton::skSphereRadius = 0.025f; -CSkeleton::CSkeleton() - : mpRootBone(nullptr) +CSkeleton::CSkeleton(CResourceEntry *pEntry /*= 0*/) + : CResource(pEntry) + , mpRootBone(nullptr) { } diff --git a/src/Core/Resource/CSkeleton.h b/src/Core/Resource/CSkeleton.h index 9a1e6f1f..d7df5813 100644 --- a/src/Core/Resource/CSkeleton.h +++ b/src/Core/Resource/CSkeleton.h @@ -33,7 +33,7 @@ class CSkeleton : public CResource static const float skSphereRadius; public: - CSkeleton(); + CSkeleton(CResourceEntry *pEntry = 0); ~CSkeleton(); void UpdateTransform(CBoneTransformData& rData, CAnimation *pAnim, float Time, bool AnchorRoot); CBone* BoneByID(u32 BoneID) const; diff --git a/src/Core/Resource/CSkin.h b/src/Core/Resource/CSkin.h index 7c7355b0..aca64cb4 100644 --- a/src/Core/Resource/CSkin.h +++ b/src/Core/Resource/CSkin.h @@ -23,7 +23,7 @@ class CSkin : public CResource std::vector mVertGroups; public: - CSkin() {} + CSkin(CResourceEntry *pEntry = 0) : CResource(pEntry) {} const SVertexWeights& WeightsForVertex(u32 VertIdx) { diff --git a/src/Core/Resource/CStringTable.h b/src/Core/Resource/CStringTable.h index bb1a3b11..6322b761 100644 --- a/src/Core/Resource/CStringTable.h +++ b/src/Core/Resource/CStringTable.h @@ -23,7 +23,7 @@ class CStringTable : public CResource std::vector mLangTables; public: - CStringTable() {} + CStringTable(CResourceEntry *pEntry = 0) : CResource(pEntry) {} inline u32 NumStrings() const { return mNumStrings; } inline u32 NumLanguages() const { return mLangTables.size(); } diff --git a/src/Core/Resource/CTexture.cpp b/src/Core/Resource/CTexture.cpp index 258ad7d1..14a55c2f 100644 --- a/src/Core/Resource/CTexture.cpp +++ b/src/Core/Resource/CTexture.cpp @@ -1,7 +1,7 @@ #include "CTexture.h" -CTexture::CTexture() - : CResource() +CTexture::CTexture(CResourceEntry *pEntry /*= 0*/) + : CResource(pEntry) , mTexelFormat(eRGBA8) , mSourceTexelFormat(eRGBA8) , mWidth(0) @@ -125,6 +125,7 @@ void CTexture::Resize(u32 Width, u32 Height) mWidth = (u16) Width; mHeight = (u16) Height; mNumMipMaps = 1; + CalcLinearSize(); } } diff --git a/src/Core/Resource/CTexture.h b/src/Core/Resource/CTexture.h index 4a411631..4ff1becd 100644 --- a/src/Core/Resource/CTexture.h +++ b/src/Core/Resource/CTexture.h @@ -29,7 +29,7 @@ class CTexture : public CResource GLuint mTextureID; // ID for texture GL buffer public: - CTexture(); + CTexture(CResourceEntry *pEntry = 0); CTexture(u32 Width, u32 Height); ~CTexture(); diff --git a/src/Core/Resource/CWorld.cpp b/src/Core/Resource/CWorld.cpp index b68eaf5f..a2e64efe 100644 --- a/src/Core/Resource/CWorld.cpp +++ b/src/Core/Resource/CWorld.cpp @@ -1,9 +1,9 @@ #include "CWorld.h" -#include "CResCache.h" +#include "Core/GameProject/CResourceStore.h" #include "Core/Resource/Script/CScriptLayer.h" -CWorld::CWorld() - : CResource() +CWorld::CWorld(CResourceEntry *pEntry /*= 0*/) + : CResource(pEntry) , mWorldVersion(eUnknownVersion) , mpWorldName(nullptr) , mpDarkWorldName(nullptr) diff --git a/src/Core/Resource/CWorld.h b/src/Core/Resource/CWorld.h index dc294faf..4590e032 100644 --- a/src/Core/Resource/CWorld.h +++ b/src/Core/Resource/CWorld.h @@ -2,9 +2,9 @@ #define CWORLD_H #include "CResource.h" -#include "CGameArea.h" #include "CStringTable.h" #include "SDependency.h" +#include "Core/Resource/Area/CGameArea.h" #include "Core/Resource/Model/CModel.h" #include @@ -81,7 +81,7 @@ class CWorld : public CResource public: - CWorld(); + CWorld(CResourceEntry *pEntry = 0); ~CWorld(); void SetAreaLayerInfo(CGameArea *pArea); diff --git a/src/Core/Resource/Cooker/CAreaCooker.h b/src/Core/Resource/Cooker/CAreaCooker.h index b839d84b..b0b28290 100644 --- a/src/Core/Resource/Cooker/CAreaCooker.h +++ b/src/Core/Resource/Cooker/CAreaCooker.h @@ -2,7 +2,7 @@ #define CAREACOOKER_H #include "CSectionMgrOut.h" -#include "Core/Resource/CGameArea.h" +#include "Core/Resource/Area/CGameArea.h" #include "Core/Resource/EGame.h" #include diff --git a/src/Core/Resource/EResType.h b/src/Core/Resource/EResType.h index 86ff47d9..ec297954 100644 --- a/src/Core/Resource/EResType.h +++ b/src/Core/Resource/EResType.h @@ -11,8 +11,15 @@ enum EResType eAnimEventData, eAnimSet, eArea, - eAudioMacro, + eAreaCollision, + eAreaGeometry, + eAreaLights, + eAreaMaterials, + eAreaSurfaceBounds, + eAreaOctree, + eAreaVisibilityTree, eAudioGroupSet, + eAudioMacro, eAudioSample, eAudioLookupTable, eBinaryData, @@ -67,10 +74,5 @@ enum EResType eInvalidResType = -1 }; -// defined in CResource.cpp -TString GetTypeName(EResType Type); -TString GetRawExtension(EResType Type, EGame Game); -TString GetCookedExtension(EResType Type, EGame Game); - #endif // ERESTYPE diff --git a/src/Core/Resource/Factory/CAnimSetLoader.cpp b/src/Core/Resource/Factory/CAnimSetLoader.cpp index fbf64ce1..9615f52d 100644 --- a/src/Core/Resource/Factory/CAnimSetLoader.cpp +++ b/src/Core/Resource/Factory/CAnimSetLoader.cpp @@ -1,5 +1,5 @@ #include "CAnimSetLoader.h" -#include "Core/Resource/CResCache.h" +#include "Core/GameProject/CResourceStore.h" #include CAnimSetLoader::CAnimSetLoader() @@ -14,7 +14,7 @@ CAnimSet* CAnimSetLoader::LoadCorruptionCHAR(IInputStream& rCHAR) CAnimSet::SNode& node = pSet->mNodes[0]; node.Name = rCHAR.ReadString(); - node.pModel = gResCache.GetResource(rCHAR.ReadLongLong(), "CMDL"); + node.pModel = gResourceStore.LoadResource(rCHAR.ReadLongLong(), "CMDL"); return pSet; } @@ -28,7 +28,7 @@ CAnimSet* CAnimSetLoader::LoadReturnsCHAR(IInputStream& rCHAR) rNode.Name = rCHAR.ReadString(); rCHAR.Seek(0x14, SEEK_CUR); rCHAR.ReadString(); - rNode.pModel = gResCache.GetResource(rCHAR.ReadLongLong(), "CMDL"); + rNode.pModel = gResourceStore.LoadResource(rCHAR.ReadLongLong(), "CMDL"); return pSet; } @@ -194,7 +194,7 @@ void CAnimSetLoader::LoadHalfTransition(IInputStream& rANCS) } // ************ STATIC ************ -CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS) +CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry) { if (!rANCS.IsValid()) return nullptr; @@ -206,7 +206,8 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS) } CAnimSetLoader Loader; - Loader.pSet = new CAnimSet; + Loader.pSet = new CAnimSet(pEntry); + Loader.mVersion = pEntry->Game(); u32 NodeCount = rANCS.ReadLong(); Loader.pSet->mNodes.resize(NodeCount); @@ -217,11 +218,15 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS) rANCS.Seek(0x4, SEEK_CUR); // Skipping node self-index u16 Unknown1 = rANCS.ReadShort(); - if (iNode == 0) Loader.mVersion = (Unknown1 == 0xA) ? eEchoes : ePrime; // Best version indicator we know of unfortunately + if (iNode == 0 && Loader.mVersion == eUnknownVersion) + { + Loader.mVersion = (Unknown1 == 0xA) ? eEchoes : ePrime; // Best version indicator we know of unfortunately + Loader.pSet->SetGame(Loader.mVersion); + } pNode->Name = rANCS.ReadString(); - pNode->pModel = gResCache.GetResource(rANCS.ReadLong(), "CMDL"); - pNode->pSkin = gResCache.GetResource(rANCS.ReadLong(), "CSKR"); - pNode->pSkeleton = gResCache.GetResource(rANCS.ReadLong(), "CINF"); + pNode->pModel = gResourceStore.LoadResource(rANCS.ReadLong(), "CMDL"); + pNode->pSkin = gResourceStore.LoadResource(rANCS.ReadLong(), "CSKR"); + pNode->pSkeleton = gResourceStore.LoadResource(rANCS.ReadLong(), "CINF"); if (pNode->pModel) pNode->pModel->SetSkin(pNode->pSkin); // Unfortunately that's all that's actually supported at the moment. Hope to expand later. @@ -330,7 +335,7 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS) { CAnimSet::SAnimation Anim; Anim.Name = rPrim.Name; - Anim.pAnim = gResCache.GetResource(rPrim.AnimID, "ANIM"); + Anim.pAnim = gResourceStore.LoadResource(rPrim.AnimID, "ANIM"); Loader.pSet->mAnims.push_back(Anim); } } @@ -338,7 +343,7 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS) return Loader.pSet; } -CAnimSet* CAnimSetLoader::LoadCHAR(IInputStream& rCHAR) +CAnimSet* CAnimSetLoader::LoadCHAR(IInputStream& rCHAR, CResourceEntry *pEntry) { if (!rCHAR.IsValid()) return nullptr; @@ -348,14 +353,16 @@ CAnimSet* CAnimSetLoader::LoadCHAR(IInputStream& rCHAR) if (Check == 0x5 || Check == 0x3) { Loader.mVersion = eCorruption; - Loader.pSet = new CAnimSet(); + Loader.pSet = new CAnimSet(pEntry); + Loader.pSet->SetGame(eCorruption); return Loader.LoadCorruptionCHAR(rCHAR); } if (Check == 0x59) { Loader.mVersion = eReturns; - Loader.pSet = new CAnimSet(); + Loader.pSet = new CAnimSet(pEntry); + Loader.pSet->SetGame(eReturns); return Loader.LoadReturnsCHAR(rCHAR); } diff --git a/src/Core/Resource/Factory/CAnimSetLoader.h b/src/Core/Resource/Factory/CAnimSetLoader.h index afd54344..60a47bd2 100644 --- a/src/Core/Resource/Factory/CAnimSetLoader.h +++ b/src/Core/Resource/Factory/CAnimSetLoader.h @@ -42,8 +42,8 @@ class CAnimSetLoader void LoadHalfTransition(IInputStream& rANCS); public: - static CAnimSet* LoadANCS(IInputStream& rANCS); - static CAnimSet* LoadCHAR(IInputStream& rCHAR); + static CAnimSet* LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry); + static CAnimSet* LoadCHAR(IInputStream& rCHAR, CResourceEntry *pEntry); }; #endif // CCHARACTERLOADER_H diff --git a/src/Core/Resource/Factory/CAnimationLoader.cpp b/src/Core/Resource/Factory/CAnimationLoader.cpp index 6d2a98bb..d97a6dd8 100644 --- a/src/Core/Resource/Factory/CAnimationLoader.cpp +++ b/src/Core/Resource/Factory/CAnimationLoader.cpp @@ -75,7 +75,11 @@ void CAnimationLoader::ReadUncompressedANIM() NumBoneChannels++; } - mGame = UncompressedCheckVersion(); + if (mGame == eUnknownVersion) + { + mGame = UncompressedCheckVersion(); + mpAnim->SetGame(mGame); + } // Echoes only - rotation channel indices std::vector RotationIndices; @@ -206,7 +210,13 @@ void CAnimationLoader::ReadCompressedANIM() { // Header mpInput->Seek(0x4, SEEK_CUR); // Skip alloc size - mGame = (mpInput->PeekShort() == 0x0101 ? eEchoes : ePrime); // Version check + + if (mGame == eUnknownVersion) + { + mGame = (mpInput->PeekShort() == 0x0101 ? eEchoes : ePrime); + mpAnim->SetGame(mGame); + } + mpInput->Seek(mGame == ePrime ? 0x8 : 0x2, SEEK_CUR); // Skip EVNT (MP1) and unknowns mpAnim->mDuration = mpInput->ReadFloat(); mpAnim->mTickInterval = mpInput->ReadFloat(); @@ -452,7 +462,7 @@ CQuaternion CAnimationLoader::DequantizeRotation(bool Sign, s16 X, s16 Y, s16 Z) } // ************ STATIC ************ -CAnimation* CAnimationLoader::LoadANIM(IInputStream& rANIM) +CAnimation* CAnimationLoader::LoadANIM(IInputStream& rANIM, CResourceEntry *pEntry) { u32 CompressionType = rANIM.ReadLong(); @@ -463,7 +473,8 @@ CAnimation* CAnimationLoader::LoadANIM(IInputStream& rANIM) } CAnimationLoader Loader; - Loader.mpAnim = new CAnimation(); + Loader.mpAnim = new CAnimation(pEntry); + Loader.mGame = pEntry->Game(); Loader.mpInput = &rANIM; if (CompressionType == 0) diff --git a/src/Core/Resource/Factory/CAnimationLoader.h b/src/Core/Resource/Factory/CAnimationLoader.h index a4555c0a..9e7acb80 100644 --- a/src/Core/Resource/Factory/CAnimationLoader.h +++ b/src/Core/Resource/Factory/CAnimationLoader.h @@ -41,7 +41,7 @@ class CAnimationLoader CQuaternion DequantizeRotation(bool Sign, s16 X, s16 Y, s16 Z); public: - static CAnimation* LoadANIM(IInputStream& rANIM); + static CAnimation* LoadANIM(IInputStream& rANIM, CResourceEntry *pEntry); }; #endif // CANIMATIONLOADER_H diff --git a/src/Core/Resource/Factory/CAreaLoader.cpp b/src/Core/Resource/Factory/CAreaLoader.cpp index 7efdd64f..f7a885fd 100644 --- a/src/Core/Resource/Factory/CAreaLoader.cpp +++ b/src/Core/Resource/Factory/CAreaLoader.cpp @@ -603,7 +603,7 @@ void CAreaLoader::ReadEGMC() Log::FileWrite(mpMREA->GetSourceString(), "Reading EGMC"); mpSectionMgr->ToSection(mEGMCBlockNum); CUniqueID EGMC(*mpMREA, (mVersion <= eEchoes ? e32Bit : e64Bit)); - mpArea->mpPoiToWorldMap = gResCache.GetResource(EGMC, "EGMC"); + mpArea->mpPoiToWorldMap = gResourceStore.LoadResource(EGMC, "EGMC"); } void CAreaLoader::SetUpObjects() @@ -650,7 +650,7 @@ void CAreaLoader::SetUpObjects() } // ************ STATIC ************ -CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA) +CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA, CResourceEntry *pEntry) { CAreaLoader Loader; @@ -665,9 +665,10 @@ CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA) } // Header - Loader.mpArea = new CGameArea; + Loader.mpArea = new CGameArea(pEntry); u32 Version = MREA.ReadLong(); Loader.mVersion = GetFormatVersion(Version); + Loader.mpArea->SetGame(Loader.mVersion); Loader.mpArea->mVersion = Loader.mVersion; Loader.mpMREA = &MREA; diff --git a/src/Core/Resource/Factory/CAreaLoader.h b/src/Core/Resource/Factory/CAreaLoader.h index 6ffb42d0..728d4c27 100644 --- a/src/Core/Resource/Factory/CAreaLoader.h +++ b/src/Core/Resource/Factory/CAreaLoader.h @@ -2,10 +2,10 @@ #define CAREALOADER_H #include "CSectionMgrIn.h" +#include "Core/GameProject/CResourceStore.h" +#include "Core/Resource/Area/CGameArea.h" #include "Core/Resource/Script/CLink.h" -#include "Core/Resource/CGameArea.h" #include "Core/Resource/EGame.h" -#include "Core/Resource/CResCache.h" #include @@ -80,7 +80,7 @@ class CAreaLoader void SetUpObjects(); public: - static CGameArea* LoadMREA(IInputStream& rMREA); + static CGameArea* LoadMREA(IInputStream& rMREA, CResourceEntry *pEntry); static EGame GetFormatVersion(u32 Version); }; diff --git a/src/Core/Resource/Factory/CCollisionLoader.cpp b/src/Core/Resource/Factory/CCollisionLoader.cpp index 2ad885de..e248c865 100644 --- a/src/Core/Resource/Factory/CCollisionLoader.cpp +++ b/src/Core/Resource/Factory/CCollisionLoader.cpp @@ -159,12 +159,12 @@ CCollisionMeshGroup* CCollisionLoader::LoadAreaCollision(IInputStream& rMREA) return loader.mpGroup; } -CCollisionMeshGroup* CCollisionLoader::LoadDCLN(IInputStream& rDCLN) +CCollisionMeshGroup* CCollisionLoader::LoadDCLN(IInputStream& rDCLN, CResourceEntry *pEntry) { if (!rDCLN.IsValid()) return nullptr; CCollisionLoader Loader; - Loader.mpGroup = new CCollisionMeshGroup; + Loader.mpGroup = new CCollisionMeshGroup(pEntry); u32 NumMeshes = rDCLN.ReadLong(); @@ -183,6 +183,7 @@ CCollisionMeshGroup* CCollisionLoader::LoadDCLN(IInputStream& rDCLN) Loader.mpMesh = new CCollisionMesh; Loader.mpMesh->mOctreeLoaded = false; + Loader.mpGroup->SetGame(Loader.mVersion); if (Loader.mVersion == eReturns) Loader.mpMesh->mAABox = CAABox(rDCLN); diff --git a/src/Core/Resource/Factory/CCollisionLoader.h b/src/Core/Resource/Factory/CCollisionLoader.h index 34787ab0..89a4eedb 100644 --- a/src/Core/Resource/Factory/CCollisionLoader.h +++ b/src/Core/Resource/Factory/CCollisionLoader.h @@ -22,7 +22,7 @@ class CCollisionLoader public: static CCollisionMeshGroup* LoadAreaCollision(IInputStream& rMREA); - static CCollisionMeshGroup* LoadDCLN(IInputStream& rDCLN); + static CCollisionMeshGroup* LoadDCLN(IInputStream& rDCLN, CResourceEntry *pEntry); static EGame GetFormatVersion(u32 Version); }; diff --git a/src/Core/Resource/Factory/CFontLoader.cpp b/src/Core/Resource/Factory/CFontLoader.cpp index baa1b955..c5e7a206 100644 --- a/src/Core/Resource/Factory/CFontLoader.cpp +++ b/src/Core/Resource/Factory/CFontLoader.cpp @@ -18,8 +18,8 @@ CFont* CFontLoader::LoadFont(IInputStream& rFONT) mpFont->mDefaultSize = rFONT.ReadLong(); mpFont->mFontName = rFONT.ReadString(); - if (mVersion <= eEchoes) mpFont->mpFontTexture = gResCache.GetResource(rFONT.ReadLong(), "TXTR"); - else mpFont->mpFontTexture = gResCache.GetResource(rFONT.ReadLongLong(), "TXTR"); + if (mVersion <= eEchoes) mpFont->mpFontTexture = gResourceStore.LoadResource(rFONT.ReadLong(), "TXTR"); + else mpFont->mpFontTexture = gResourceStore.LoadResource(rFONT.ReadLongLong(), "TXTR"); mpFont->mTextureFormat = rFONT.ReadLong(); u32 NumGlyphs = rFONT.ReadLong(); @@ -79,7 +79,7 @@ CFont* CFontLoader::LoadFont(IInputStream& rFONT) return mpFont; } -CFont* CFontLoader::LoadFONT(IInputStream& rFONT) +CFont* CFontLoader::LoadFONT(IInputStream& rFONT, CResourceEntry *pEntry) { if (!rFONT.IsValid()) return nullptr; @@ -99,7 +99,8 @@ CFont* CFontLoader::LoadFONT(IInputStream& rFONT) } CFontLoader Loader; - Loader.mpFont = new CFont(); + Loader.mpFont = new CFont(pEntry); + Loader.mpFont->SetGame(Version); Loader.mVersion = Version; return Loader.LoadFont(rFONT); } diff --git a/src/Core/Resource/Factory/CFontLoader.h b/src/Core/Resource/Factory/CFontLoader.h index c260cb9b..a60db199 100644 --- a/src/Core/Resource/Factory/CFontLoader.h +++ b/src/Core/Resource/Factory/CFontLoader.h @@ -1,9 +1,9 @@ #ifndef CFONTLOADER_H #define CFONTLOADER_H +#include "Core/GameProject/CResourceStore.h" #include "Core/Resource/CFont.h" #include "Core/Resource/EGame.h" -#include "Core/Resource/CResCache.h" class CFontLoader { @@ -14,7 +14,7 @@ class CFontLoader CFont* LoadFont(IInputStream& rFONT); public: - static CFont* LoadFONT(IInputStream& rFONT); + static CFont* LoadFONT(IInputStream& rFONT, CResourceEntry *pEntry); static EGame GetFormatVersion(u32 Version); }; diff --git a/src/Core/Resource/Factory/CMaterialLoader.cpp b/src/Core/Resource/Factory/CMaterialLoader.cpp index 32900845..6db6ec8b 100644 --- a/src/Core/Resource/Factory/CMaterialLoader.cpp +++ b/src/Core/Resource/Factory/CMaterialLoader.cpp @@ -1,5 +1,5 @@ #include "CMaterialLoader.h" -#include "Core/Resource/CResCache.h" +#include "Core/GameProject/CResourceStore.h" #include "Core/OpenGL/GLCommon.h" #include #include @@ -50,7 +50,7 @@ void CMaterialLoader::ReadPrimeMatSet() for (u32 iTex = 0; iTex < NumTextures; iTex++) { u32 TextureID = mpFile->ReadLong(); - mTextures[iTex] = gResCache.GetResource(TextureID, "TXTR"); + mTextures[iTex] = gResourceStore.LoadResource(TextureID, "TXTR"); } // Materials @@ -366,7 +366,7 @@ CMaterial* CMaterialLoader::ReadCorruptionMaterial() continue; } - pPass->mpTexture = gResCache.GetResource(TextureID, "TXTR"); + pPass->mpTexture = gResourceStore.LoadResource(TextureID, "TXTR"); pPass->mTexCoordSource = 4 + (u8) mpFile->ReadLong(); u32 AnimSize = mpFile->ReadLong(); diff --git a/src/Core/Resource/Factory/CMaterialLoader.h b/src/Core/Resource/Factory/CMaterialLoader.h index a10da6bd..bbd79890 100644 --- a/src/Core/Resource/Factory/CMaterialLoader.h +++ b/src/Core/Resource/Factory/CMaterialLoader.h @@ -1,9 +1,9 @@ #ifndef CMATERIALLOADER_H #define CMATERIALLOADER_H +#include "Core/GameProject/CResourceStore.h" #include "Core/Resource/CMaterialSet.h" #include "Core/Resource/EGame.h" -#include "Core/Resource/CResCache.h" #include #include diff --git a/src/Core/Resource/Factory/CModelLoader.cpp b/src/Core/Resource/Factory/CModelLoader.cpp index 47f2ef72..7b7e7d52 100644 --- a/src/Core/Resource/Factory/CModelLoader.cpp +++ b/src/Core/Resource/Factory/CModelLoader.cpp @@ -382,7 +382,7 @@ SSurface* CModelLoader::LoadAssimpMesh(const aiMesh *pkMesh, CMaterialSet *pSet) } // ************ STATIC ************ -CModel* CModelLoader::LoadCMDL(IInputStream& rCMDL) +CModel* CModelLoader::LoadCMDL(IInputStream& rCMDL, CResourceEntry *pEntry) { CModelLoader Loader; @@ -452,7 +452,8 @@ CModel* CModelLoader::LoadCMDL(IInputStream& rCMDL) return nullptr; } - CModel *pModel = new CModel(); + CModel *pModel = new CModel(pEntry); + pModel->SetGame(Loader.mVersion); Loader.mpModel = pModel; Loader.mpSectionMgr = new CSectionMgrIn(BlockCount, &rCMDL); rCMDL.SeekToBoundary(32); diff --git a/src/Core/Resource/Factory/CModelLoader.h b/src/Core/Resource/Factory/CModelLoader.h index 2db4ca88..6c4d79e6 100644 --- a/src/Core/Resource/Factory/CModelLoader.h +++ b/src/Core/Resource/Factory/CModelLoader.h @@ -2,9 +2,9 @@ #define CMODELLOADER_H #include "CSectionMgrIn.h" +#include "Core/GameProject/CResourceStore.h" #include "Core/Resource/Model/CBasicModel.h" #include "Core/Resource/Model/CModel.h" -#include "Core/Resource/CResCache.h" #include "Core/Resource/EGame.h" #include @@ -57,7 +57,7 @@ private: SSurface* LoadAssimpMesh(const aiMesh *pkMesh, CMaterialSet *pSet); public: - static CModel* LoadCMDL(IInputStream& rCMDL); + static CModel* LoadCMDL(IInputStream& rCMDL, CResourceEntry *pEntry); static CModel* LoadWorldModel(IInputStream& rMREA, CSectionMgrIn& rBlockMgr, CMaterialSet& rMatSet, EGame Version); static CModel* LoadCorruptionWorldModel(IInputStream& rMREA, CSectionMgrIn& rBlockMgr, CMaterialSet& rMatSet, u32 HeaderSecNum, u32 GPUSecNum, EGame Version); static void BuildWorldMeshes(const std::vector& rkIn, std::vector& rOut, bool DeleteInputModels); diff --git a/src/Core/Resource/Factory/CPoiToWorldLoader.cpp b/src/Core/Resource/Factory/CPoiToWorldLoader.cpp index 693343dc..d2ad106c 100644 --- a/src/Core/Resource/Factory/CPoiToWorldLoader.cpp +++ b/src/Core/Resource/Factory/CPoiToWorldLoader.cpp @@ -1,8 +1,8 @@ #include "CPoiToWorldLoader.h" -CPoiToWorld* CPoiToWorldLoader::LoadEGMC(IInputStream& rEGMC) +CPoiToWorld* CPoiToWorldLoader::LoadEGMC(IInputStream& rEGMC, CResourceEntry *pEntry) { - CPoiToWorld *pOut = new CPoiToWorld(); + CPoiToWorld *pOut = new CPoiToWorld(pEntry); u32 NumMappings = rEGMC.ReadLong(); for (u32 iMap = 0; iMap < NumMappings; iMap++) diff --git a/src/Core/Resource/Factory/CPoiToWorldLoader.h b/src/Core/Resource/Factory/CPoiToWorldLoader.h index b79b85c9..5ab49d00 100644 --- a/src/Core/Resource/Factory/CPoiToWorldLoader.h +++ b/src/Core/Resource/Factory/CPoiToWorldLoader.h @@ -11,7 +11,7 @@ class CPoiToWorldLoader CPoiToWorldLoader() {} public: - static CPoiToWorld* LoadEGMC(IInputStream& rEGMC); + static CPoiToWorld* LoadEGMC(IInputStream& rEGMC, CResourceEntry *pEntry); }; #endif // CPOITOWORLDLOADER_H diff --git a/src/Core/Resource/Factory/CScanLoader.cpp b/src/Core/Resource/Factory/CScanLoader.cpp index c7462e6a..16cd2941 100644 --- a/src/Core/Resource/Factory/CScanLoader.cpp +++ b/src/Core/Resource/Factory/CScanLoader.cpp @@ -1,5 +1,5 @@ #include "CScanLoader.h" -#include "Core/Resource/CResCache.h" +#include "Core/GameProject/CResourceStore.h" #include CScanLoader::CScanLoader() @@ -10,7 +10,7 @@ CScan* CScanLoader::LoadScanMP1(IInputStream& rSCAN) { // Basic support at the moment - don't read animation/scan image data rSCAN.Seek(0x4, SEEK_CUR); // Skip FRME ID - mpScan->mpStringTable = gResCache.GetResource(rSCAN.ReadLong(), "STRG"); + mpScan->mpStringTable = gResourceStore.LoadResource(rSCAN.ReadLong(), "STRG"); mpScan->mIsSlow = (rSCAN.ReadLong() != 0); mpScan->mCategory = (CScan::ELogbookCategory) rSCAN.ReadLong(); mpScan->mIsImportant = (rSCAN.ReadByte() == 1); @@ -58,12 +58,14 @@ CScan* CScanLoader::LoadScanMP2(IInputStream& rSCAN) { case 0x14: case 0xB: - mpScan = new CScan(); + mpScan = new CScan(mpEntry); + mpScan->SetGame(eEchoes); LoadParamsMP2(rSCAN); break; case 0x12: case 0x16: - mpScan = new CScan(); + mpScan = new CScan(mpEntry); + mpScan->SetGame(eCorruption); LoadParamsMP3(rSCAN); break; default: @@ -86,7 +88,7 @@ void CScanLoader::LoadParamsMP2(IInputStream& rSCAN) switch (PropertyID) { case 0x2F5B6423: - mpScan->mpStringTable = gResCache.GetResource(rSCAN.ReadLong(), "STRG"); + mpScan->mpStringTable = gResourceStore.LoadResource(rSCAN.ReadLong(), "STRG"); break; case 0xC308A322: @@ -119,7 +121,7 @@ void CScanLoader::LoadParamsMP3(IInputStream& rSCAN) switch (PropertyID) { case 0x2F5B6423: - mpScan->mpStringTable = gResCache.GetResource(rSCAN.ReadLongLong(), "STRG"); + mpScan->mpStringTable = gResourceStore.LoadResource(rSCAN.ReadLongLong(), "STRG"); break; case 0xC308A322: @@ -139,7 +141,7 @@ void CScanLoader::LoadParamsMP3(IInputStream& rSCAN) } // ************ STATIC/PUBLIC ************ -CScan* CScanLoader::LoadSCAN(IInputStream& rSCAN) +CScan* CScanLoader::LoadSCAN(IInputStream& rSCAN, CResourceEntry *pEntry) { if (!rSCAN.IsValid()) return nullptr; @@ -157,6 +159,7 @@ CScan* CScanLoader::LoadSCAN(IInputStream& rSCAN) // The MP2 load function will check for MP3 CScanLoader Loader; Loader.mVersion = eEchoes; + Loader.mpEntry = pEntry; if (Magic == 0x01000000) rSCAN.Seek(-4, SEEK_CUR); // The version number isn't present in the Echoes demo return Loader.LoadScanMP2(rSCAN); } @@ -176,6 +179,8 @@ CScan* CScanLoader::LoadSCAN(IInputStream& rSCAN) // MP1 SCAN - read the file! CScanLoader Loader; Loader.mVersion = ePrime; - Loader.mpScan = new CScan(); + Loader.mpScan = new CScan(pEntry); + Loader.mpScan->SetGame(ePrime); + Loader.mpEntry = pEntry; return Loader.LoadScanMP1(rSCAN); } diff --git a/src/Core/Resource/Factory/CScanLoader.h b/src/Core/Resource/Factory/CScanLoader.h index 19b343a5..7436aee1 100644 --- a/src/Core/Resource/Factory/CScanLoader.h +++ b/src/Core/Resource/Factory/CScanLoader.h @@ -7,6 +7,7 @@ class CScanLoader { TResPtr mpScan; + CResourceEntry *mpEntry; EGame mVersion; CScanLoader(); @@ -16,7 +17,7 @@ class CScanLoader void LoadParamsMP3(IInputStream& rSCAN); public: - static CScan* LoadSCAN(IInputStream& rSCAN); + static CScan* LoadSCAN(IInputStream& rSCAN, CResourceEntry *pEntry); }; #endif // CSCANLOADER_H diff --git a/src/Core/Resource/Factory/CScriptLoader.cpp b/src/Core/Resource/Factory/CScriptLoader.cpp index 3709e8de..ac704fa2 100644 --- a/src/Core/Resource/Factory/CScriptLoader.cpp +++ b/src/Core/Resource/Factory/CScriptLoader.cpp @@ -1,7 +1,7 @@ #include "CScriptLoader.h" #include "CTemplateLoader.h" +#include "Core/GameProject/CResourceStore.h" #include "Core/Resource/Script/CMasterTemplate.h" -#include "Core/Resource/CResCache.h" #include #include #include @@ -117,7 +117,7 @@ void CScriptLoader::ReadProperty(IProperty *pProp, u32 Size, IInputStream& rSCLY if (ResID.IsValid()) { - CFourCC Type = gResCache.FindResourceType(ResID, rkExtensions); + CFourCC Type = gResourceStore.ResourceTypeByID(ResID, rkExtensions); Info = CResourceInfo(ResID, Type); } diff --git a/src/Core/Resource/Factory/CScriptLoader.h b/src/Core/Resource/Factory/CScriptLoader.h index 5170ee54..c2c53d7a 100644 --- a/src/Core/Resource/Factory/CScriptLoader.h +++ b/src/Core/Resource/Factory/CScriptLoader.h @@ -1,11 +1,11 @@ #ifndef CSCRIPTLOADER_H #define CSCRIPTLOADER_H +#include "Core/GameProject/CResourceStore.h" +#include "Core/Resource/Area/CGameArea.h" #include "Core/Resource/Script/CScriptObject.h" #include "Core/Resource/Script/CScriptLayer.h" #include "Core/Resource/Script/CMasterTemplate.h" -#include "Core/Resource/CGameArea.h" -#include "Core/Resource/CResCache.h" class CScriptLoader { diff --git a/src/Core/Resource/Factory/CSkeletonLoader.cpp b/src/Core/Resource/Factory/CSkeletonLoader.cpp index f49a0b88..32819dd0 100644 --- a/src/Core/Resource/Factory/CSkeletonLoader.cpp +++ b/src/Core/Resource/Factory/CSkeletonLoader.cpp @@ -25,12 +25,12 @@ void CSkeletonLoader::CalculateBoneInverseBindMatrices() } // ************ STATIC ************ -CSkeleton* CSkeletonLoader::LoadCINF(IInputStream& rCINF) +CSkeleton* CSkeletonLoader::LoadCINF(IInputStream& rCINF, CResourceEntry *pEntry) { CSkeletonLoader Loader; - CSkeleton *pSkel = new CSkeleton(); + CSkeleton *pSkel = new CSkeleton(pEntry); Loader.mpSkeleton = pSkel; - EGame Game = eUnknownVersion; + EGame Game = pEntry->Game(); u32 NumBones = rCINF.ReadLong(); pSkel->mBones.reserve(NumBones); @@ -60,6 +60,7 @@ CSkeleton* CSkeletonLoader::LoadCINF(IInputStream& rCINF) { u32 Check = rCINF.PeekLong(); Game = ((Check > 100 || Check == 0) ? eEchoes : ePrime); + Loader.mpSkeleton->SetGame(Game); } if (Game == eEchoes) { diff --git a/src/Core/Resource/Factory/CSkeletonLoader.h b/src/Core/Resource/Factory/CSkeletonLoader.h index 88c7d7b3..87c235f1 100644 --- a/src/Core/Resource/Factory/CSkeletonLoader.h +++ b/src/Core/Resource/Factory/CSkeletonLoader.h @@ -15,7 +15,7 @@ class CSkeletonLoader void CalculateBoneInverseBindMatrices(); public: - static CSkeleton* LoadCINF(IInputStream& rCINF); + static CSkeleton* LoadCINF(IInputStream& rCINF, CResourceEntry *pEntry); }; #endif // CSKELETONLOADER_H diff --git a/src/Core/Resource/Factory/CSkinLoader.cpp b/src/Core/Resource/Factory/CSkinLoader.cpp index 21dcd514..f8153c69 100644 --- a/src/Core/Resource/Factory/CSkinLoader.cpp +++ b/src/Core/Resource/Factory/CSkinLoader.cpp @@ -2,12 +2,12 @@ #include // ************ STATIC ************ -CSkin* CSkinLoader::LoadCSKR(IInputStream& rCSKR) +CSkin* CSkinLoader::LoadCSKR(IInputStream& rCSKR, CResourceEntry *pEntry) { if (!rCSKR.IsValid()) return nullptr; u32 NumVertexGroups = rCSKR.ReadLong(); - CSkin *pSkin = new CSkin(); + CSkin *pSkin = new CSkin(pEntry); pSkin->mVertGroups.resize(NumVertexGroups); for (u32 iGrp = 0; iGrp < NumVertexGroups; iGrp++) diff --git a/src/Core/Resource/Factory/CSkinLoader.h b/src/Core/Resource/Factory/CSkinLoader.h index ff988894..21e50f21 100644 --- a/src/Core/Resource/Factory/CSkinLoader.h +++ b/src/Core/Resource/Factory/CSkinLoader.h @@ -8,7 +8,7 @@ class CSkinLoader { CSkinLoader() {} public: - static CSkin* LoadCSKR(IInputStream& rCSKR); + static CSkin* LoadCSKR(IInputStream& rCSKR, CResourceEntry *pEntry); }; #endif // CSKINLOADER_H diff --git a/src/Core/Resource/Factory/CStringLoader.cpp b/src/Core/Resource/Factory/CStringLoader.cpp index 19a8f1dd..85385fde 100644 --- a/src/Core/Resource/Factory/CStringLoader.cpp +++ b/src/Core/Resource/Factory/CStringLoader.cpp @@ -1,10 +1,6 @@ #include "CStringLoader.h" #include -CStringLoader::CStringLoader() -{ -} - void CStringLoader::LoadPrimeDemoSTRG(IInputStream& rSTRG) { // This function starts at 0x4 in the file - right after the size @@ -158,7 +154,7 @@ void CStringLoader::LoadNameTable(IInputStream& rSTRG) } // ************ STATIC ************ -CStringTable* CStringLoader::LoadSTRG(IInputStream& rSTRG) +CStringTable* CStringLoader::LoadSTRG(IInputStream& rSTRG, CResourceEntry *pEntry) { // Verify that this is a valid STRG if (!rSTRG.IsValid()) return nullptr; @@ -198,7 +194,8 @@ CStringTable* CStringLoader::LoadSTRG(IInputStream& rSTRG) // Valid; now we create the loader and call the function that reads the rest of the file CStringLoader Loader; - Loader.mpStringTable = new CStringTable(); + Loader.mpStringTable = new CStringTable(pEntry); + Loader.mpStringTable->SetGame(Version); Loader.mVersion = Version; if (Version == ePrimeDemo) Loader.LoadPrimeDemoSTRG(rSTRG); diff --git a/src/Core/Resource/Factory/CStringLoader.h b/src/Core/Resource/Factory/CStringLoader.h index f2090047..7f2ef1c8 100644 --- a/src/Core/Resource/Factory/CStringLoader.h +++ b/src/Core/Resource/Factory/CStringLoader.h @@ -1,24 +1,24 @@ #ifndef CSTRINGLOADER_H #define CSTRINGLOADER_H +#include "Core/GameProject/CResourceStore.h" #include "Core/Resource/CStringTable.h" -#include "Core/Resource/CResCache.h" #include "Core/Resource/EGame.h" #include "Core/Resource/TResPtr.h" class CStringLoader { - TResPtr mpStringTable; + CStringTable *mpStringTable; EGame mVersion; - CStringLoader(); + CStringLoader() {} void LoadPrimeDemoSTRG(IInputStream& rSTRG); void LoadPrimeSTRG(IInputStream& rSTRG); void LoadCorruptionSTRG(IInputStream& rSTRG); void LoadNameTable(IInputStream& rSTRG); public: - static CStringTable* LoadSTRG(IInputStream& rSTRG); + static CStringTable* LoadSTRG(IInputStream &rSTRG, CResourceEntry *pEntry); static EGame GetFormatVersion(u32 Version); }; diff --git a/src/Core/Resource/Factory/CTextureDecoder.cpp b/src/Core/Resource/Factory/CTextureDecoder.cpp index c253f428..d8247096 100644 --- a/src/Core/Resource/Factory/CTextureDecoder.cpp +++ b/src/Core/Resource/Factory/CTextureDecoder.cpp @@ -44,7 +44,7 @@ CTextureDecoder::~CTextureDecoder() CTexture* CTextureDecoder::CreateTexture() { - CTexture *pTex = new CTexture; + CTexture *pTex = new CTexture(mpEntry); pTex->mSourceTexelFormat = mTexelFormat; pTex->mWidth = mWidth; pTex->mHeight = mHeight; @@ -91,17 +91,19 @@ CTexture* CTextureDecoder::CreateTexture() } // ************ STATIC ************ -CTexture* CTextureDecoder::LoadTXTR(IInputStream& rTXTR) +CTexture* CTextureDecoder::LoadTXTR(IInputStream& rTXTR, CResourceEntry *pEntry) { CTextureDecoder Decoder; + Decoder.mpEntry = pEntry; Decoder.ReadTXTR(rTXTR); Decoder.PartialDecodeGXTexture(rTXTR); return Decoder.CreateTexture(); } -CTexture* CTextureDecoder::DoFullDecode(IInputStream& rTXTR) +CTexture* CTextureDecoder::DoFullDecode(IInputStream& rTXTR, CResourceEntry *pEntry) { CTextureDecoder Decoder; + Decoder.mpEntry = pEntry; Decoder.ReadTXTR(rTXTR); Decoder.FullDecodeGXTexture(rTXTR); @@ -110,9 +112,10 @@ CTexture* CTextureDecoder::DoFullDecode(IInputStream& rTXTR) return pTexture; } -CTexture* CTextureDecoder::LoadDDS(IInputStream& rDDS) +CTexture* CTextureDecoder::LoadDDS(IInputStream& rDDS, CResourceEntry *pEntry) { CTextureDecoder Decoder; + Decoder.mpEntry = pEntry; Decoder.ReadDDS(rDDS); Decoder.DecodeDDS(rDDS); return Decoder.CreateTexture(); diff --git a/src/Core/Resource/Factory/CTextureDecoder.h b/src/Core/Resource/Factory/CTextureDecoder.h index 09e891db..af0aa87e 100644 --- a/src/Core/Resource/Factory/CTextureDecoder.h +++ b/src/Core/Resource/Factory/CTextureDecoder.h @@ -10,6 +10,7 @@ class CTextureDecoder { + CResourceEntry *mpEntry; ETexelFormat mTexelFormat; u16 mWidth, mHeight; u32 mNumMipMaps; @@ -77,9 +78,9 @@ class CTextureDecoder // Static public: - static CTexture* LoadTXTR(IInputStream& rTXTR); - static CTexture* LoadDDS(IInputStream& rDDS); - static CTexture* DoFullDecode(IInputStream& rTXTR); + static CTexture* LoadTXTR(IInputStream& rTXTR, CResourceEntry *pEntry); + static CTexture* LoadDDS(IInputStream& rDDS, CResourceEntry *pEntry); + static CTexture* DoFullDecode(IInputStream& rTXTR, CResourceEntry *pEntry); static CTexture* DoFullDecode(CTexture *pTexture); // Utility diff --git a/src/Core/Resource/Factory/CWorldLoader.cpp b/src/Core/Resource/Factory/CWorldLoader.cpp index eece52cb..045f1f7c 100644 --- a/src/Core/Resource/Factory/CWorldLoader.cpp +++ b/src/Core/Resource/Factory/CWorldLoader.cpp @@ -1,5 +1,5 @@ #include "CWorldLoader.h" -#include "Core/Resource/CResCache.h" +#include "Core/GameProject/CResourceStore.h" #include CWorldLoader::CWorldLoader() @@ -15,19 +15,19 @@ void CWorldLoader::LoadPrimeMLVL(IInputStream& rMLVL) // Header if (mVersion < eCorruptionProto) { - mpWorld->mpWorldName = gResCache.GetResource(rMLVL.ReadLong(), "STRG"); - if (mVersion == eEchoes) mpWorld->mpDarkWorldName = gResCache.GetResource(rMLVL.ReadLong(), "STRG"); + mpWorld->mpWorldName = gResourceStore.LoadResource(rMLVL.ReadLong(), "STRG"); + if (mVersion == eEchoes) mpWorld->mpDarkWorldName = gResourceStore.LoadResource(rMLVL.ReadLong(), "STRG"); if (mVersion >= eEchoes) mpWorld->mUnknown1 = rMLVL.ReadLong(); - if (mVersion >= ePrime) mpWorld->mpSaveWorld = gResCache.GetResource(rMLVL.ReadLong(), "SAVW"); - mpWorld->mpDefaultSkybox = gResCache.GetResource(rMLVL.ReadLong(), "CMDL"); + if (mVersion >= ePrime) mpWorld->mpSaveWorld = gResourceStore.LoadResource(rMLVL.ReadLong(), "SAVW"); + mpWorld->mpDefaultSkybox = gResourceStore.LoadResource(rMLVL.ReadLong(), "CMDL"); } else { - mpWorld->mpWorldName = gResCache.GetResource(rMLVL.ReadLongLong(), "STRG"); + mpWorld->mpWorldName = gResourceStore.LoadResource(rMLVL.ReadLongLong(), "STRG"); rMLVL.Seek(0x4, SEEK_CUR); // Skipping unknown value - mpWorld->mpSaveWorld = gResCache.GetResource(rMLVL.ReadLongLong(), "SAVW"); - mpWorld->mpDefaultSkybox = gResCache.GetResource(rMLVL.ReadLongLong(), "CMDL"); + mpWorld->mpSaveWorld = gResourceStore.LoadResource(rMLVL.ReadLongLong(), "SAVW"); + mpWorld->mpDefaultSkybox = gResourceStore.LoadResource(rMLVL.ReadLongLong(), "CMDL"); } // Memory relays - only in MP1 @@ -58,9 +58,9 @@ void CWorldLoader::LoadPrimeMLVL(IInputStream& rMLVL) CWorld::SArea *pArea = &mpWorld->mAreas[iArea]; if (mVersion < eCorruptionProto) - pArea->pAreaName = gResCache.GetResource(rMLVL.ReadLong(), "STRG"); + pArea->pAreaName = gResourceStore.LoadResource(rMLVL.ReadLong(), "STRG"); else - pArea->pAreaName = gResCache.GetResource(rMLVL.ReadLongLong(), "STRG"); + pArea->pAreaName = gResourceStore.LoadResource(rMLVL.ReadLongLong(), "STRG"); pArea->Transform = CTransform4f(rMLVL); pArea->AetherBox = CAABox(rMLVL); @@ -169,9 +169,9 @@ void CWorldLoader::LoadPrimeMLVL(IInputStream& rMLVL) // MapWorld if (mVersion < eCorruptionProto) - mpWorld->mpMapWorld = gResCache.GetResource(rMLVL.ReadLong(), "MAPW"); + mpWorld->mpMapWorld = gResourceStore.LoadResource(rMLVL.ReadLong(), "MAPW"); else - mpWorld->mpMapWorld = gResCache.GetResource(rMLVL.ReadLongLong(), "MAPW"); + mpWorld->mpMapWorld = gResourceStore.LoadResource(rMLVL.ReadLongLong(), "MAPW"); rMLVL.Seek(0x5, SEEK_CUR); // Unknown values which are always 0 // AudioGrps @@ -221,7 +221,7 @@ void CWorldLoader::LoadPrimeMLVL(IInputStream& rMLVL) void CWorldLoader::LoadReturnsMLVL(IInputStream& rMLVL) { - mpWorld->mpWorldName = gResCache.GetResource(rMLVL.ReadLongLong(), "STRG"); + mpWorld->mpWorldName = gResourceStore.LoadResource(rMLVL.ReadLongLong(), "STRG"); bool Check = (rMLVL.ReadByte() != 0); if (Check) @@ -230,8 +230,8 @@ void CWorldLoader::LoadReturnsMLVL(IInputStream& rMLVL) rMLVL.Seek(0x10, SEEK_CUR); } - mpWorld->mpSaveWorld = gResCache.GetResource(rMLVL.ReadLongLong(), "SAVW"); - mpWorld->mpDefaultSkybox = gResCache.GetResource(rMLVL.ReadLongLong(), "CMDL"); + mpWorld->mpSaveWorld = gResourceStore.LoadResource(rMLVL.ReadLongLong(), "SAVW"); + mpWorld->mpDefaultSkybox = gResourceStore.LoadResource(rMLVL.ReadLongLong(), "CMDL"); // Areas u32 NumAreas = rMLVL.ReadLong(); @@ -242,7 +242,7 @@ void CWorldLoader::LoadReturnsMLVL(IInputStream& rMLVL) // Area header CWorld::SArea *pArea = &mpWorld->mAreas[iArea]; - pArea->pAreaName = gResCache.GetResource(rMLVL.ReadLongLong(), "STRG"); + pArea->pAreaName = gResourceStore.LoadResource(rMLVL.ReadLongLong(), "STRG"); pArea->Transform = CTransform4f(rMLVL); pArea->AetherBox = CAABox(rMLVL); pArea->FileID = rMLVL.ReadLongLong(); @@ -281,7 +281,7 @@ void CWorldLoader::LoadReturnsMLVL(IInputStream& rMLVL) // todo: Layer ID support } -CWorld* CWorldLoader::LoadMLVL(IInputStream& rMLVL) +CWorld* CWorldLoader::LoadMLVL(IInputStream& rMLVL, CResourceEntry *pEntry) { if (!rMLVL.IsValid()) return nullptr; @@ -302,7 +302,8 @@ CWorld* CWorldLoader::LoadMLVL(IInputStream& rMLVL) // Filestream is valid, magic+version are valid; everything seems good! CWorldLoader Loader; - Loader.mpWorld = new CWorld(); + Loader.mpWorld = new CWorld(pEntry); + Loader.mpWorld->SetGame(Version); Loader.mpWorld->mWorldVersion = Version; Loader.mVersion = Version; diff --git a/src/Core/Resource/Factory/CWorldLoader.h b/src/Core/Resource/Factory/CWorldLoader.h index beef1859..f21a06f3 100644 --- a/src/Core/Resource/Factory/CWorldLoader.h +++ b/src/Core/Resource/Factory/CWorldLoader.h @@ -1,8 +1,8 @@ #ifndef CWORLDLOADER_H #define CWORLDLOADER_H +#include "Core/GameProject/CResourceStore.h" #include "Core/Resource/CWorld.h" -#include "Core/Resource/CResCache.h" #include "Core/Resource/EGame.h" #include @@ -17,7 +17,7 @@ class CWorldLoader void LoadReturnsMLVL(IInputStream& rMLVL); public: - static CWorld* LoadMLVL(IInputStream& rMLVL); + static CWorld* LoadMLVL(IInputStream& rMLVL, CResourceEntry *pEntry); static EGame GetFormatVersion(u32 Version); }; diff --git a/src/Core/Resource/Model/CBasicModel.cpp b/src/Core/Resource/Model/CBasicModel.cpp index 997ca8a6..03ab4e33 100644 --- a/src/Core/Resource/Model/CBasicModel.cpp +++ b/src/Core/Resource/Model/CBasicModel.cpp @@ -2,8 +2,8 @@ #include #include -CBasicModel::CBasicModel() - : CResource() +CBasicModel::CBasicModel(CResourceEntry *pEntry /*= 0*/) + : CResource(pEntry) , mVertexCount(0) , mTriangleCount(0) , mBuffered(false) diff --git a/src/Core/Resource/Model/CBasicModel.h b/src/Core/Resource/Model/CBasicModel.h index b5722c9e..69d1e93b 100644 --- a/src/Core/Resource/Model/CBasicModel.h +++ b/src/Core/Resource/Model/CBasicModel.h @@ -21,7 +21,7 @@ protected: std::vector mSurfaces; public: - CBasicModel(); + CBasicModel(CResourceEntry *pEntry = 0); ~CBasicModel(); u32 GetVertexCount(); diff --git a/src/Core/Resource/Model/CModel.cpp b/src/Core/Resource/Model/CModel.cpp index 23263c8e..11a0d54e 100644 --- a/src/Core/Resource/Model/CModel.cpp +++ b/src/Core/Resource/Model/CModel.cpp @@ -1,11 +1,12 @@ #include "CModel.h" #include "Core/Render/CDrawUtil.h" #include "Core/Render/CRenderer.h" +#include "Core/Resource/Area/CGameArea.h" #include "Core/OpenGL/GLCommon.h" #include -CModel::CModel() - : CBasicModel() +CModel::CModel(CResourceEntry *pEntry /*= 0*/) + : CBasicModel(pEntry) { mHasOwnMaterials = true; mHasOwnSurfaces = true; diff --git a/src/Core/Resource/Model/CModel.h b/src/Core/Resource/Model/CModel.h index 42379231..fe171284 100644 --- a/src/Core/Resource/Model/CModel.h +++ b/src/Core/Resource/Model/CModel.h @@ -21,7 +21,7 @@ class CModel : public CBasicModel bool mHasOwnMaterials; public: - CModel(); + CModel(CResourceEntry *pEntry = 0); CModel(CMaterialSet *pSet, bool OwnsMatSet); ~CModel(); diff --git a/src/Core/Resource/Model/CStaticModel.cpp b/src/Core/Resource/Model/CStaticModel.cpp index da44e374..d4586b5d 100644 --- a/src/Core/Resource/Model/CStaticModel.cpp +++ b/src/Core/Resource/Model/CStaticModel.cpp @@ -4,7 +4,7 @@ #include "Core/OpenGL/GLCommon.h" CStaticModel::CStaticModel() - : CBasicModel() + : CBasicModel(nullptr) , mpMaterial(nullptr) , mTransparent(false) { @@ -75,11 +75,11 @@ void CStaticModel::BufferGL() } // Make sure the number of submesh offset vectors matches the number of IBOs, then add the offsets - while (mIBOs.size() > mSubmeshEndOffsets.size()) - mSubmeshEndOffsets.emplace_back(std::vector(mSurfaces.size())); + while (mIBOs.size() > mSurfaceEndOffsets.size()) + mSurfaceEndOffsets.emplace_back(std::vector(mSurfaces.size())); for (u32 iIBO = 0; iIBO < mIBOs.size(); iIBO++) - mSubmeshEndOffsets[iIBO][iSurf] = mIBOs[iIBO].GetSize(); + mSurfaceEndOffsets[iIBO][iSurf] = mIBOs[iIBO].GetSize(); } mVBO.Buffer(); @@ -101,7 +101,7 @@ void CStaticModel::ClearGLBuffer() { mVBO.Clear(); mIBOs.clear(); - mSubmeshEndOffsets.clear(); + mSurfaceEndOffsets.clear(); mBuffered = false; } @@ -139,8 +139,8 @@ void CStaticModel::DrawSurface(FRenderOptions Options, u32 Surface) { // Since there is a shared IBO for every mesh, we need two things to draw a single one: an offset and a size u32 Offset = 0; - if (Surface > 0) Offset = mSubmeshEndOffsets[iIBO][Surface - 1]; - u32 Size = mSubmeshEndOffsets[iIBO][Surface] - Offset; + if (Surface > 0) Offset = mSurfaceEndOffsets[iIBO][Surface - 1]; + u32 Size = mSurfaceEndOffsets[iIBO][Surface] - Offset; if (!Size) continue; // The chosen submesh doesn't use this IBO @@ -179,7 +179,7 @@ CMaterial* CStaticModel::GetMaterial() void CStaticModel::SetMaterial(CMaterial *pMat) { mpMaterial = pMat; - mTransparent = ((pMat->Options() & CMaterial::eTransparent) != 0); + mTransparent = pMat->Options().HasFlag(CMaterial::eTransparent); } bool CStaticModel::IsTransparent() @@ -189,7 +189,7 @@ bool CStaticModel::IsTransparent() bool CStaticModel::IsOccluder() { - return ((mpMaterial->Options() & CMaterial::eOccluder) != 0); + return mpMaterial->Options().HasFlag(CMaterial::eOccluder); } CIndexBuffer* CStaticModel::InternalGetIBO(EGXPrimitiveType Primitive) diff --git a/src/Core/Resource/Model/CStaticModel.h b/src/Core/Resource/Model/CStaticModel.h index de2be5b6..9926eac1 100644 --- a/src/Core/Resource/Model/CStaticModel.h +++ b/src/Core/Resource/Model/CStaticModel.h @@ -5,14 +5,14 @@ #include "Core/Render/FRenderOptions.h" #include "Core/OpenGL/CIndexBuffer.h" -/* A CStaticModel is meant for meshes that don't move. It's built specifically with terrain in mind. - * It only links to one material, and what it does best is combining submeshes from different models - * into shared VBOs and IBOs. This allows for a significantly reduced number of draw calls. */ +/* A CStaticModel is meant for meshes that don't move. It only links to one material, + * and is used to combine surfaces from different world models into shared VBOs and + * IBOs. This allows for a significantly reduced number of draw calls. */ class CStaticModel : public CBasicModel { CMaterial *mpMaterial; std::vector mIBOs; - std::vector> mSubmeshEndOffsets; + std::vector> mSurfaceEndOffsets; bool mTransparent; public: diff --git a/src/Core/Resource/Script/CLink.h b/src/Core/Resource/Script/CLink.h index 2e0ca4d0..c2bd538f 100644 --- a/src/Core/Resource/Script/CLink.h +++ b/src/Core/Resource/Script/CLink.h @@ -2,7 +2,7 @@ #define CLINK_H #include "CScriptObject.h" -#include "Core/Resource/CGameArea.h" +#include "Core/Resource/Area/CGameArea.h" #include #include diff --git a/src/Core/Resource/Script/CScriptObject.h b/src/Core/Resource/Script/CScriptObject.h index 66162747..fe5b57be 100644 --- a/src/Core/Resource/Script/CScriptObject.h +++ b/src/Core/Resource/Script/CScriptObject.h @@ -4,9 +4,9 @@ #include "IProperty.h" #include "IPropertyTemplate.h" #include "CScriptTemplate.h" +#include "Core/Resource/Area/CGameArea.h" #include "Core/Resource/Model/CModel.h" #include "Core/Resource/CCollisionMeshGroup.h" -#include "Core/Resource/CGameArea.h" class CScriptLayer; class CLink; diff --git a/src/Core/Resource/Script/CScriptTemplate.cpp b/src/Core/Resource/Script/CScriptTemplate.cpp index 75ad944b..7198db11 100644 --- a/src/Core/Resource/Script/CScriptTemplate.cpp +++ b/src/Core/Resource/Script/CScriptTemplate.cpp @@ -1,7 +1,7 @@ #include "CScriptTemplate.h" #include "CScriptObject.h" #include "CMasterTemplate.h" -#include "Core/Resource/CResCache.h" +#include "Core/GameProject/CResourceStore.h" #include "Core/Resource/CAnimSet.h" #include @@ -166,7 +166,7 @@ CResource* CScriptTemplate::FindDisplayAsset(CPropertyStruct *pProperties, u32& if (it->AssetSource == SEditorAsset::eFile) { TString Path = "../resources/" + it->AssetLocation; - pRes = gResCache.GetResource(Path); + pRes = gResourceStore.LoadResource(Path); } // Property @@ -216,7 +216,7 @@ CCollisionMeshGroup* CScriptTemplate::FindCollision(CPropertyStruct *pProperties if (it->AssetSource == SEditorAsset::eFile) { TString path = "../resources/" + it->AssetLocation; - pRes = gResCache.GetResource(path); + pRes = gResourceStore.LoadResource(path); } // Property diff --git a/src/Core/Scene/CScene.cpp b/src/Core/Scene/CScene.cpp index 3c63668e..c7a6fc90 100644 --- a/src/Core/Scene/CScene.cpp +++ b/src/Core/Scene/CScene.cpp @@ -1,7 +1,6 @@ #include "CScene.h" #include "CSceneIterator.h" #include "Core/Render/CGraphics.h" -#include "Core/Resource/CResCache.h" #include "Core/Resource/CPoiToWorld.h" #include "Core/Resource/Script/CScriptLayer.h" #include "Core/CRayCollisionTester.h" diff --git a/src/Core/Scene/CScene.h b/src/Core/Scene/CScene.h index 6a42b174..88f6fb19 100644 --- a/src/Core/Scene/CScene.h +++ b/src/Core/Scene/CScene.h @@ -11,7 +11,7 @@ #include "FShowFlags.h" #include "Core/Render/CRenderer.h" #include "Core/Render/SViewInfo.h" -#include "Core/Resource/CGameArea.h" +#include "Core/Resource/Area/CGameArea.h" #include "Core/Resource/CWorld.h" #include "Core/CAreaAttributes.h" #include "Core/SRayIntersection.h" diff --git a/src/Core/Scene/CSceneNode.cpp b/src/Core/Scene/CSceneNode.cpp index a8b309c1..73ee55a9 100644 --- a/src/Core/Scene/CSceneNode.cpp +++ b/src/Core/Scene/CSceneNode.cpp @@ -1,9 +1,9 @@ #include "CSceneNode.h" +#include "Core/GameProject/CResourceStore.h" #include "Core/Render/CRenderer.h" #include "Core/Render/CGraphics.h" #include "Core/Render/CDrawUtil.h" -#include "Core/Resource/CGameArea.h" -#include "Core/Resource/CResCache.h" +#include "Core/Resource/Area/CGameArea.h" #include #include @@ -258,7 +258,7 @@ void CSceneNode::DrawBoundingBox() const void CSceneNode::DrawRotationArrow() const { - static TResPtr spArrowModel = gResCache.GetResource("../resources/RotationArrow.cmdl"); + static TResPtr spArrowModel = gResourceStore.LoadResource("../resources/RotationArrow.cmdl"); spArrowModel->Draw(eNoRenderOptions, 0); } diff --git a/src/Core/Scene/CSceneNode.h b/src/Core/Scene/CSceneNode.h index 8f3a7032..7f96b3c3 100644 --- a/src/Core/Scene/CSceneNode.h +++ b/src/Core/Scene/CSceneNode.h @@ -5,8 +5,8 @@ #include "Core/Render/EDepthGroup.h" #include "Core/Render/FRenderOptions.h" #include "Core/Render/IRenderable.h" +#include "Core/Resource/Area/CGameArea.h" #include "Core/Resource/CLight.h" -#include "Core/Resource/CGameArea.h" #include "Core/CRayCollisionTester.h" #include #include diff --git a/src/Core/Scene/CScriptNode.cpp b/src/Core/Scene/CScriptNode.cpp index fe18bb40..0737434e 100644 --- a/src/Core/Scene/CScriptNode.cpp +++ b/src/Core/Scene/CScriptNode.cpp @@ -1,9 +1,9 @@ #include "CScriptNode.h" #include "CScene.h" +#include "Core/GameProject/CResourceStore.h" #include "Core/Render/CDrawUtil.h" #include "Core/Render/CGraphics.h" #include "Core/Render/CRenderer.h" -#include "Core/Resource/CResCache.h" #include "Core/Resource/Script/CMasterTemplate.h" #include "Core/Resource/Script/CScriptLayer.h" #include "Core/ScriptExtra/CScriptExtra.h" @@ -535,15 +535,15 @@ void CScriptNode::UpdatePreviewVolume() { case eAxisAlignedBoxShape: case eBoxShape: - pVolumeModel = gResCache.GetResource("../resources/VolumeBox.cmdl"); + pVolumeModel = gResourceStore.LoadResource("../resources/VolumeBox.cmdl"); break; case eEllipsoidShape: - pVolumeModel = gResCache.GetResource("../resources/VolumeSphere.cmdl"); + pVolumeModel = gResourceStore.LoadResource("../resources/VolumeSphere.cmdl"); break; case eCylinderShape: - pVolumeModel = gResCache.GetResource("../resources/VolumeCylinder.cmdl"); + pVolumeModel = gResourceStore.LoadResource("../resources/VolumeCylinder.cmdl"); break; } diff --git a/src/Editor/CGizmo.cpp b/src/Editor/CGizmo.cpp index 44292c29..4bf6c71c 100644 --- a/src/Editor/CGizmo.cpp +++ b/src/Editor/CGizmo.cpp @@ -1,8 +1,8 @@ #include "CGizmo.h" #include +#include #include #include -#include #include #include @@ -543,32 +543,32 @@ void CGizmo::LoadModels() { Log::Write("Loading transform gizmo models"); - smTranslateModels[CGIZMO_TRANSLATE_X] = SModelPart(eX, true, false, gResCache.GetResource("../resources/editor/TranslateX.CMDL")); - smTranslateModels[CGIZMO_TRANSLATE_Y] = SModelPart(eY, true, false, gResCache.GetResource("../resources/editor/TranslateY.CMDL")); - smTranslateModels[CGIZMO_TRANSLATE_Z] = SModelPart(eZ, true, false, gResCache.GetResource("../resources/editor/TranslateZ.CMDL")); - smTranslateModels[CGIZMO_TRANSLATE_LINES_XY] = SModelPart(eXY, true, false, gResCache.GetResource("../resources/editor/TranslateLinesXY.CMDL")); - smTranslateModels[CGIZMO_TRANSLATE_LINES_XZ] = SModelPart(eXZ, true, false, gResCache.GetResource("../resources/editor/TranslateLinesXZ.CMDL")); - smTranslateModels[CGIZMO_TRANSLATE_LINES_YZ] = SModelPart(eYZ, true, false, gResCache.GetResource("../resources/editor/TranslateLinesYZ.CMDL")); - smTranslateModels[CGIZMO_TRANSLATE_POLY_XY] = SModelPart(eXY, false, false, gResCache.GetResource("../resources/editor/TranslatePolyXY.CMDL")); - smTranslateModels[CGIZMO_TRANSLATE_POLY_XZ] = SModelPart(eXZ, false, false, gResCache.GetResource("../resources/editor/TranslatePolyXZ.CMDL")); - smTranslateModels[CGIZMO_TRANSLATE_POLY_YZ] = SModelPart(eYZ, false, false, gResCache.GetResource("../resources/editor/TranslatePolyYZ.CMDL")); + smTranslateModels[CGIZMO_TRANSLATE_X] = SModelPart(eX, true, false, gResourceStore.LoadResource("../resources/editor/TranslateX.CMDL")); + smTranslateModels[CGIZMO_TRANSLATE_Y] = SModelPart(eY, true, false, gResourceStore.LoadResource("../resources/editor/TranslateY.CMDL")); + smTranslateModels[CGIZMO_TRANSLATE_Z] = SModelPart(eZ, true, false, gResourceStore.LoadResource("../resources/editor/TranslateZ.CMDL")); + smTranslateModels[CGIZMO_TRANSLATE_LINES_XY] = SModelPart(eXY, true, false, gResourceStore.LoadResource("../resources/editor/TranslateLinesXY.CMDL")); + smTranslateModels[CGIZMO_TRANSLATE_LINES_XZ] = SModelPart(eXZ, true, false, gResourceStore.LoadResource("../resources/editor/TranslateLinesXZ.CMDL")); + smTranslateModels[CGIZMO_TRANSLATE_LINES_YZ] = SModelPart(eYZ, true, false, gResourceStore.LoadResource("../resources/editor/TranslateLinesYZ.CMDL")); + smTranslateModels[CGIZMO_TRANSLATE_POLY_XY] = SModelPart(eXY, false, false, gResourceStore.LoadResource("../resources/editor/TranslatePolyXY.CMDL")); + smTranslateModels[CGIZMO_TRANSLATE_POLY_XZ] = SModelPart(eXZ, false, false, gResourceStore.LoadResource("../resources/editor/TranslatePolyXZ.CMDL")); + smTranslateModels[CGIZMO_TRANSLATE_POLY_YZ] = SModelPart(eYZ, false, false, gResourceStore.LoadResource("../resources/editor/TranslatePolyYZ.CMDL")); - smRotateModels[CGIZMO_ROTATE_OUTLINE] = SModelPart(eNone, true, true, gResCache.GetResource("../resources/editor/RotateClipOutline.CMDL")); - smRotateModels[CGIZMO_ROTATE_X] = SModelPart(eX, true, false, gResCache.GetResource("../resources/editor/RotateX.CMDL")); - smRotateModels[CGIZMO_ROTATE_Y] = SModelPart(eY, true, false, gResCache.GetResource("../resources/editor/RotateY.CMDL")); - smRotateModels[CGIZMO_ROTATE_Z] = SModelPart(eZ, true, false, gResCache.GetResource("../resources/editor/RotateZ.CMDL")); - smRotateModels[CGIZMO_ROTATE_XYZ] = SModelPart(eXYZ, false, false, gResCache.GetResource("../resources/editor/RotateXYZ.CMDL")); + smRotateModels[CGIZMO_ROTATE_OUTLINE] = SModelPart(eNone, true, true, gResourceStore.LoadResource("../resources/editor/RotateClipOutline.CMDL")); + smRotateModels[CGIZMO_ROTATE_X] = SModelPart(eX, true, false, gResourceStore.LoadResource("../resources/editor/RotateX.CMDL")); + smRotateModels[CGIZMO_ROTATE_Y] = SModelPart(eY, true, false, gResourceStore.LoadResource("../resources/editor/RotateY.CMDL")); + smRotateModels[CGIZMO_ROTATE_Z] = SModelPart(eZ, true, false, gResourceStore.LoadResource("../resources/editor/RotateZ.CMDL")); + smRotateModels[CGIZMO_ROTATE_XYZ] = SModelPart(eXYZ, false, false, gResourceStore.LoadResource("../resources/editor/RotateXYZ.CMDL")); - smScaleModels[CGIZMO_SCALE_X] = SModelPart(eX, true, false, gResCache.GetResource("../resources/editor/ScaleX.CMDL")); - smScaleModels[CGIZMO_SCALE_Y] = SModelPart(eY, true, false, gResCache.GetResource("../resources/editor/ScaleY.CMDL")); - smScaleModels[CGIZMO_SCALE_Z] = SModelPart(eZ, true, false, gResCache.GetResource("../resources/editor/ScaleZ.CMDL")); - smScaleModels[CGIZMO_SCALE_LINES_XY] = SModelPart(eXY, true, false, gResCache.GetResource("../resources/editor/ScaleLinesXY.CMDL")); - smScaleModels[CGIZMO_SCALE_LINES_XZ] = SModelPart(eXZ, true, false, gResCache.GetResource("../resources/editor/ScaleLinesXZ.CMDL")); - smScaleModels[CGIZMO_SCALE_LINES_YZ] = SModelPart(eYZ, true, false, gResCache.GetResource("../resources/editor/ScaleLinesYZ.CMDL")); - smScaleModels[CGIZMO_SCALE_POLY_XY] = SModelPart(eXY, true, false, gResCache.GetResource("../resources/editor/ScalePolyXY.CMDL")); - smScaleModels[CGIZMO_SCALE_POLY_XZ] = SModelPart(eXZ, true, false, gResCache.GetResource("../resources/editor/ScalePolyXZ.CMDL")); - smScaleModels[CGIZMO_SCALE_POLY_YZ] = SModelPart(eYZ, true, false, gResCache.GetResource("../resources/editor/ScalePolyYZ.CMDL")); - smScaleModels[CGIZMO_SCALE_XYZ] = SModelPart(eXYZ, true, false, gResCache.GetResource("../resources/editor/ScaleXYZ.CMDL")); + smScaleModels[CGIZMO_SCALE_X] = SModelPart(eX, true, false, gResourceStore.LoadResource("../resources/editor/ScaleX.CMDL")); + smScaleModels[CGIZMO_SCALE_Y] = SModelPart(eY, true, false, gResourceStore.LoadResource("../resources/editor/ScaleY.CMDL")); + smScaleModels[CGIZMO_SCALE_Z] = SModelPart(eZ, true, false, gResourceStore.LoadResource("../resources/editor/ScaleZ.CMDL")); + smScaleModels[CGIZMO_SCALE_LINES_XY] = SModelPart(eXY, true, false, gResourceStore.LoadResource("../resources/editor/ScaleLinesXY.CMDL")); + smScaleModels[CGIZMO_SCALE_LINES_XZ] = SModelPart(eXZ, true, false, gResourceStore.LoadResource("../resources/editor/ScaleLinesXZ.CMDL")); + smScaleModels[CGIZMO_SCALE_LINES_YZ] = SModelPart(eYZ, true, false, gResourceStore.LoadResource("../resources/editor/ScaleLinesYZ.CMDL")); + smScaleModels[CGIZMO_SCALE_POLY_XY] = SModelPart(eXY, true, false, gResourceStore.LoadResource("../resources/editor/ScalePolyXY.CMDL")); + smScaleModels[CGIZMO_SCALE_POLY_XZ] = SModelPart(eXZ, true, false, gResourceStore.LoadResource("../resources/editor/ScalePolyXZ.CMDL")); + smScaleModels[CGIZMO_SCALE_POLY_YZ] = SModelPart(eYZ, true, false, gResourceStore.LoadResource("../resources/editor/ScalePolyYZ.CMDL")); + smScaleModels[CGIZMO_SCALE_XYZ] = SModelPart(eXYZ, true, false, gResourceStore.LoadResource("../resources/editor/ScaleXYZ.CMDL")); smModelsLoaded = true; } diff --git a/src/Editor/CStartWindow.cpp b/src/Editor/CStartWindow.cpp index 964f143b..979e1552 100644 --- a/src/Editor/CStartWindow.cpp +++ b/src/Editor/CStartWindow.cpp @@ -8,7 +8,7 @@ #include "Editor/ModelEditor/CModelEditorWindow.h" #include "Editor/WorldEditor/CWorldEditor.h" #include -#include +#include #include #include @@ -55,8 +55,8 @@ void CStartWindow::on_actionOpen_MLVL_triggered() if (mpWorldEditor->close()) { TString Dir = TO_TSTRING(WorldFile).GetFileDirectory(); - gResCache.SetFolder(Dir); - mpWorld = gResCache.GetResource(WorldFile.toStdString()); + gResourceStore.SetTransientLoadDir(Dir); + mpWorld = gResourceStore.LoadResource(WorldFile.toStdString()); QString QStrDir = TO_QSTRING(Dir); mpWorldEditor->SetWorldDir(QStrDir); @@ -192,31 +192,30 @@ void CStartWindow::on_LaunchWorldEditorButton_clicked() { Log::ClearErrorLog(); - u64 AreaID = mpWorld->AreaResourceID(mSelectedAreaIndex); - TResPtr pArea = gResCache.GetResource(AreaID, "MREA"); + CUniqueID AreaID = mpWorld->AreaResourceID(mSelectedAreaIndex); + TString AreaPath = mpWorld->Entry()->CookedAssetPath().GetFileDirectory() + AreaID.ToString() + ".MREA"; + TResPtr pArea = gResourceStore.LoadResource(AreaPath); if (!pArea) { QMessageBox::warning(this, "Error", "Couldn't load area!"); + return; } - else - { - pArea->SetWorldIndex(mSelectedAreaIndex); - mpWorld->SetAreaLayerInfo(pArea); - mpWorldEditor->SetArea(mpWorld, pArea); - gResCache.Clean(); + pArea->SetWorldIndex(mSelectedAreaIndex); + mpWorld->SetAreaLayerInfo(pArea); + mpWorldEditor->SetArea(mpWorld, pArea); + gResourceStore.DestroyUnreferencedResources(); - mpWorldEditor->setWindowModality(Qt::WindowModal); - mpWorldEditor->showMaximized(); + mpWorldEditor->setWindowModality(Qt::WindowModal); + mpWorldEditor->showMaximized(); - // Display errors - CErrorLogDialog ErrorDialog(mpWorldEditor); - bool HasErrors = ErrorDialog.GatherErrors(); + // Display errors + CErrorLogDialog ErrorDialog(mpWorldEditor); + bool HasErrors = ErrorDialog.GatherErrors(); - if (HasErrors) - ErrorDialog.exec(); - } + if (HasErrors) + ErrorDialog.exec(); } } diff --git a/src/Editor/CStartWindow.h b/src/Editor/CStartWindow.h index e05f19d4..1758bb81 100644 --- a/src/Editor/CStartWindow.h +++ b/src/Editor/CStartWindow.h @@ -4,8 +4,8 @@ #include "WorldEditor/CWorldEditor.h" #include "ModelEditor/CModelEditorWindow.h" #include "CharacterEditor/CCharacterEditor.h" +#include #include -#include #include diff --git a/src/Editor/CharacterEditor/CCharacterEditor.cpp b/src/Editor/CharacterEditor/CCharacterEditor.cpp index bbcf453d..fbea3ef1 100644 --- a/src/Editor/CharacterEditor/CCharacterEditor.cpp +++ b/src/Editor/CharacterEditor/CCharacterEditor.cpp @@ -191,7 +191,7 @@ void CCharacterEditor::Open() QString CharFilename = QFileDialog::getOpenFileName(this, "Open Character", "", "Animation Character Set (*.ANCS)"); if (CharFilename.isEmpty()) return; - CAnimSet *pSet = (CAnimSet*) gResCache.GetResource(CharFilename.toStdString()); + CAnimSet *pSet = (CAnimSet*) gResourceStore.LoadResource(CharFilename.toStdString()); if (pSet) { @@ -242,7 +242,7 @@ void CCharacterEditor::Open() QMessageBox::warning(this, "Error", "Couldn't load file: " + CharFilename); } - gResCache.Clean(); + gResourceStore.DestroyUnreferencedResources(); } void CCharacterEditor::ToggleGrid(bool Enable) diff --git a/src/Editor/ModelEditor/CModelEditorWindow.cpp b/src/Editor/ModelEditor/CModelEditorWindow.cpp index aa97078f..63de190f 100644 --- a/src/Editor/ModelEditor/CModelEditorWindow.cpp +++ b/src/Editor/ModelEditor/CModelEditorWindow.cpp @@ -580,7 +580,7 @@ void CModelEditorWindow::UpdateMaterial(QString Value) if (mIgnoreSignals) return; EModelEditorWidget Widget = (EModelEditorWidget) sender()->property("ModelEditorWidgetType").toInt(); - TResPtr pTex = gResCache.GetResource(TO_TSTRING(Value)); + TResPtr pTex = gResourceStore.LoadResource(TO_TSTRING(Value)); if (pTex->Type() != eTexture) pTex = nullptr; switch (Widget) @@ -722,7 +722,7 @@ void CModelEditorWindow::Open() QString ModelFilename = QFileDialog::getOpenFileName(this, "Save model", "", "Retro Model (*.CMDL)"); if (ModelFilename.isEmpty()) return; - TResPtr pModel = gResCache.GetResource(ModelFilename.toStdString()); + TResPtr pModel = gResourceStore.LoadResource(ModelFilename.toStdString()); if (pModel) { SetActiveModel(pModel); @@ -730,7 +730,7 @@ void CModelEditorWindow::Open() mOutputFilename = TO_QSTRING(pModel->FullSource()); } - gResCache.Clean(); + gResourceStore.DestroyUnreferencedResources(); } void CModelEditorWindow::Import() @@ -773,7 +773,7 @@ void CModelEditorWindow::Import() SetActiveModel(pModel); SET_WINDOWTITLE_APPVARS("%APP_FULL_NAME% - Model Editor: Untitled"); mOutputFilename = ""; - gResCache.Clean(); + gResourceStore.DestroyUnreferencedResources(); } void CModelEditorWindow::Save() @@ -809,7 +809,7 @@ void CModelEditorWindow::ConvertToDDS() if (Input.isEmpty()) return; TString TexFilename = Input.toStdString(); - TResPtr pTex = gResCache.GetResource(TexFilename); + TResPtr pTex = gResourceStore.LoadResource(TexFilename); TString OutName = TexFilename.GetFilePathWithoutExtension() + ".dds"; CFileOutStream Out(OutName.ToStdString(), IOUtil::eLittleEndian); @@ -829,7 +829,7 @@ void CModelEditorWindow::ConvertToTXTR() if (Input.isEmpty()) return; TString TexFilename = TO_TSTRING(Input); - CTexture *pTex = CTextureDecoder::LoadDDS(CFileInStream(TexFilename.ToStdString(), IOUtil::eLittleEndian)); + CTexture *pTex = CTextureDecoder::LoadDDS(CFileInStream(TexFilename.ToStdString(), IOUtil::eLittleEndian), nullptr); TString OutName = TexFilename.GetFilePathWithoutExtension() + ".txtr"; if ((pTex->TexelFormat() != eDXT1) || (pTex->NumMipMaps() > 1)) diff --git a/src/Editor/ModelEditor/CModelEditorWindow.h b/src/Editor/ModelEditor/CModelEditorWindow.h index ae1ef266..43210180 100644 --- a/src/Editor/ModelEditor/CModelEditorWindow.h +++ b/src/Editor/ModelEditor/CModelEditorWindow.h @@ -2,9 +2,9 @@ #define CMODELEDITORWINDOW_H #include "CModelEditorViewport.h" +#include #include #include -#include #include #include #include diff --git a/src/Editor/Undo/CCreateInstanceCommand.h b/src/Editor/Undo/CCreateInstanceCommand.h index 32e68168..ee430a1d 100644 --- a/src/Editor/Undo/CCreateInstanceCommand.h +++ b/src/Editor/Undo/CCreateInstanceCommand.h @@ -5,7 +5,7 @@ #include "CClearSelectionCommand.h" #include "CSelectNodeCommand.h" #include "Editor/WorldEditor/CWorldEditor.h" -#include +#include #include #include diff --git a/src/Editor/Undo/ObjReferences.h b/src/Editor/Undo/ObjReferences.h index b95f6375..e862562d 100644 --- a/src/Editor/Undo/ObjReferences.h +++ b/src/Editor/Undo/ObjReferences.h @@ -1,7 +1,7 @@ #ifndef OBJREFERENCES #define OBJREFERENCES -#include +#include #include #include #include diff --git a/src/Editor/Widgets/WAnimParamsEditor.cpp b/src/Editor/Widgets/WAnimParamsEditor.cpp index 8be63f16..5a6e8e0f 100644 --- a/src/Editor/Widgets/WAnimParamsEditor.cpp +++ b/src/Editor/Widgets/WAnimParamsEditor.cpp @@ -1,7 +1,7 @@ #include "WAnimParamsEditor.h" #include "Editor/UICommon.h" +#include #include -#include #include WAnimParamsEditor::WAnimParamsEditor(QWidget *pParent) diff --git a/src/Editor/Widgets/WResourceSelector.cpp b/src/Editor/Widgets/WResourceSelector.cpp index ae9f8980..4e0a58b9 100644 --- a/src/Editor/Widgets/WResourceSelector.cpp +++ b/src/Editor/Widgets/WResourceSelector.cpp @@ -1,7 +1,7 @@ #include "WResourceSelector.h" #include "WTexturePreviewPanel.h" #include "Editor/UICommon.h" -#include +#include #include #include diff --git a/src/Editor/Widgets/WTextureGLWidget.cpp b/src/Editor/Widgets/WTextureGLWidget.cpp index 73c7c8cd..563e1d16 100644 --- a/src/Editor/Widgets/WTextureGLWidget.cpp +++ b/src/Editor/Widgets/WTextureGLWidget.cpp @@ -1,8 +1,8 @@ #include "WTextureGLWidget.h" #include +#include #include #include -#include #include #include diff --git a/src/Editor/WorldEditor/CLayerModel.h b/src/Editor/WorldEditor/CLayerModel.h index c8b4e778..2c19ce5a 100644 --- a/src/Editor/WorldEditor/CLayerModel.h +++ b/src/Editor/WorldEditor/CLayerModel.h @@ -1,7 +1,7 @@ #ifndef CLAYERMODEL_H #define CLAYERMODEL_H -#include +#include #include class CLayerModel : public QAbstractListModel diff --git a/src/Editor/WorldEditor/CLinkModel.cpp b/src/Editor/WorldEditor/CLinkModel.cpp index 8a87589c..b118f459 100644 --- a/src/Editor/WorldEditor/CLinkModel.cpp +++ b/src/Editor/WorldEditor/CLinkModel.cpp @@ -1,6 +1,6 @@ #include "CLinkModel.h" #include "Editor/UICommon.h" -#include +#include #include CLinkModel::CLinkModel(QObject *pParent) diff --git a/src/Editor/WorldEditor/CWorldEditor.h b/src/Editor/WorldEditor/CWorldEditor.h index 51e39f9a..ae0350e1 100644 --- a/src/Editor/WorldEditor/CWorldEditor.h +++ b/src/Editor/WorldEditor/CWorldEditor.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include