Completely overhauled resource loading in preparation for projects

This commit is contained in:
parax0 2016-06-29 17:18:31 -06:00
parent e53a895b29
commit 2d6dfad2d3
102 changed files with 1334 additions and 835 deletions

View File

@ -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"";
}
}

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -1,5 +1,5 @@
#include "CGameExporter.h"
#include "Core/Resource/CResCache.h"
#include "Core/GameProject/CResourceStore.h"
#include "Core/Resource/CWorld.h"
#include <FileIO/FileIO.h>
#include <Common/AssertMacro.h>
@ -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<CWorld> pWorld = (CWorld*) gResCache.GetResource(rkRes.ID, rkRes.Type);
TResPtr<CWorld> 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;
}
}

View File

@ -2,7 +2,7 @@
#define CGAMEPROJECT_H
#include "CPackage.h"
#include "CResourceDatabase.h"
#include "CResourceStore.h"
#include "Core/Resource/EGame.h"
#include <Common/CUniqueID.h>
#include <Common/TString.h>
@ -13,7 +13,7 @@ class CGameProject
EGame mGame;
TString mProjectName;
TWideString mProjectRoot;
CResourceDatabase *mpResourceDatabase;
TWideString mResourceDBPath;
std::vector<CPackage*> mWorldPaks;
std::vector<CPackage*> 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;

View File

@ -1,215 +0,0 @@
#include "CResourceDatabase.h"
#include "CGameProject.h"
#include "Core/Resource/CResCache.h"
#include <Common/AssertMacro.h>
#include <Common/FileUtil.h>
#include <Common/Log.h>
#include <tinyxml2.h>
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;
}
}
}

View File

@ -1,74 +0,0 @@
#ifndef CRESOURCEDATABASE_H
#define CRESOURCEDATABASE_H
#include "Core/Resource/CResource.h"
#include <Common/CUniqueID.h>
#include <Common/TString.h>
#include <Common/types.h>
#include <map>
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<CUniqueID, CResourceEntry*> 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

View File

@ -0,0 +1,151 @@
#include "CResourceEntry.h"
#include "CGameProject.h"
#include "CResourceStore.h"
#include "Core/Resource/CResource.h"
#include <Common/FileUtil.h>
#include <Common/TString.h>
// 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;
}

View File

@ -0,0 +1,55 @@
#ifndef CRESOURCEENTRY_H
#define CRESOURCEENTRY_H
#include "CVirtualDirectory.h"
#include "Core/Resource/EResType.h"
#include <Common/CUniqueID.h>
#include <Common/types.h>
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

View File

@ -0,0 +1,403 @@
#include "CResourceStore.h"
#include "CGameExporter.h"
#include "CGameProject.h"
#include "Core/Resource/CResource.h"
#include <Common/AssertMacro.h>
#include <Common/FileUtil.h>
#include <Common/Log.h>
#include <tinyxml2.h>
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<u8> 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);
}

View File

@ -0,0 +1,65 @@
#ifndef CRESOURCEDATABASE_H
#define CRESOURCEDATABASE_H
#include "CVirtualDirectory.h"
#include "Core/Resource/EResType.h"
#include <Common/CFourCC.h>
#include <Common/CUniqueID.h>
#include <Common/TString.h>
#include <Common/types.h>
#include <map>
#include <set>
class CGameExporter;
class CGameProject;
class CResource;
class CResourceStore
{
CGameProject *mpProj;
CVirtualDirectory *mpProjectRoot;
std::vector<CVirtualDirectory*> mTransientRoots;
std::map<CUniqueID, CResourceEntry*> mResourceEntries;
std::map<CUniqueID, CResourceEntry*> 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

View File

@ -0,0 +1,156 @@
#include "CVirtualDirectory.h"
#include "CResourceEntry.h"
#include "CResourceStore.h"
#include <algorithm>
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;
}

View File

@ -0,0 +1,44 @@
#ifndef CVIRTUALDIRECTORY
#define CVIRTUALDIRECTORY
/* Virtual directory system used to look up resources by their location in the filesystem. */
#include <Common/AssertMacro.h>
#include <Common/TString.h>
#include <vector>
class CResourceEntry;
class CVirtualDirectory
{
CVirtualDirectory *mpParent;
TWideString mName;
std::vector<CVirtualDirectory*> mSubdirectories;
std::vector<CResourceEntry*> 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

View File

@ -1,6 +1,6 @@
#include "CDrawUtil.h"
#include "CGraphics.h"
#include "Core/Resource/CResCache.h"
#include "Core/GameProject/CResourceStore.h"
#include <Common/Log.h>
#include <Math/CTransform4f.h>
#include <iostream>
@ -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()

View File

@ -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 <Math/CTransform4f.h>

View File

@ -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)

View File

@ -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 <Common/types.h>
@ -60,7 +60,7 @@ class CGameArea : public CResource
TResPtr<CPoiToWorld> mpPoiToWorldMap;
public:
CGameArea();
CGameArea(CResourceEntry *pEntry = 0);
~CGameArea();
void AddWorldModel(CModel *pModel);

View File

@ -36,7 +36,7 @@ class CAnimSet : public CResource
std::vector<SAnimation> 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; }

View File

@ -2,8 +2,9 @@
#include <Math/CTransform4f.h>
#include <Math/MathUtil.h>
CAnimation::CAnimation()
: mDuration(0.f)
CAnimation::CAnimation(CResourceEntry *pEntry /*= 0*/)
: CResource(pEntry)
, mDuration(0.f)
, mTickInterval(0.0333333f)
, mNumKeys(0)
{

View File

@ -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;

View File

@ -1,7 +1,7 @@
#include "CAnimationParameters.h"
#include "CAnimSet.h"
#include "CResCache.h"
#include "CResourceInfo.h"
#include "Core/GameProject/CResourceStore.h"
#include <Common/Log.h>
#include <iostream>

View File

@ -12,7 +12,7 @@ class CCollisionMeshGroup : public CResource
std::vector<CCollisionMesh*> mMeshes;
public:
CCollisionMeshGroup() {}
CCollisionMeshGroup(CResourceEntry *pEntry = 0) : CResource(pEntry) {}
~CCollisionMeshGroup()
{

View File

@ -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)
{
}

View File

@ -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,

View File

@ -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"

View File

@ -1,6 +1,7 @@
#include "CPoiToWorld.h"
CPoiToWorld::CPoiToWorld()
CPoiToWorld::CPoiToWorld(CResourceEntry *pEntry /*= 0*/)
: CResource(pEntry)
{
}

View File

@ -22,7 +22,7 @@ private:
std::map<u32,SPoiMap*> mPoiLookupMap;
public:
CPoiToWorld();
CPoiToWorld(CResourceEntry *pEntry = 0);
~CPoiToWorld();
void AddPoi(u32 PoiID);

View File

@ -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 <FileIO/FileIO.h>
#include <Common/AssertMacro.h>
#include <Common/FileUtil.h>
#include <Common/Log.h>
#include <Common/TString.h>
#include <iostream>
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<u8> 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;

View File

@ -1,36 +0,0 @@
#ifndef CRESCACHE_H
#define CRESCACHE_H
#include "CResource.h"
#include "Core/GameProject/CGameExporter.h"
#include <Common/types.h>
#include <Common/TString.h>
#include <unordered_map>
class CResCache
{
std::unordered_map<u64, CResource*> 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

View File

@ -1,4 +1,5 @@
#include "CResource.h"
#include "Core/GameProject/CResourceStore.h"
#include <Common/AssertMacro.h>
#include <map>
@ -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)

View File

@ -2,6 +2,8 @@
#define CRESOURCE_H
#include "EResType.h"
#include "Core/GameProject/CResourceEntry.h"
#include "Core/GameProject/CResourceStore.h"
#include <Common/CFourCC.h>
#include <Common/CUniqueID.h>
#include <Common/types.h>
@ -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

View File

@ -2,7 +2,7 @@
#define CRESOURCEINFO
#include "CResource.h"
#include "CResCache.h"
#include "Core/GameProject/CResourceStore.h"
#include <Common/CUniqueID.h>
#include <Common/CFourCC.h>
#include <Common/FileUtil.h>
@ -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

View File

@ -31,8 +31,8 @@ private:
ELogbookCategory mCategory;
public:
CScan()
: CResource()
CScan(CResourceEntry *pEntry = 0)
: CResource(pEntry)
, mpFrame(nullptr)
, mpStringTable(nullptr)
, mIsSlow(false)

View File

@ -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)
{
}

View File

@ -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;

View File

@ -23,7 +23,7 @@ class CSkin : public CResource
std::vector<SVertGroup> mVertGroups;
public:
CSkin() {}
CSkin(CResourceEntry *pEntry = 0) : CResource(pEntry) {}
const SVertexWeights& WeightsForVertex(u32 VertIdx)
{

View File

@ -23,7 +23,7 @@ class CStringTable : public CResource
std::vector<SLangTable> mLangTables;
public:
CStringTable() {}
CStringTable(CResourceEntry *pEntry = 0) : CResource(pEntry) {}
inline u32 NumStrings() const { return mNumStrings; }
inline u32 NumLanguages() const { return mLangTables.size(); }

View File

@ -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();
}
}

View File

@ -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();

View File

@ -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)

View File

@ -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 <Math/CTransform4f.h>
@ -81,7 +81,7 @@ class CWorld : public CResource
public:
CWorld();
CWorld(CResourceEntry *pEntry = 0);
~CWorld();
void SetAreaLayerInfo(CGameArea *pArea);

View File

@ -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 <FileIO/FileIO.h>

View File

@ -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

View File

@ -1,5 +1,5 @@
#include "CAnimSetLoader.h"
#include "Core/Resource/CResCache.h"
#include "Core/GameProject/CResourceStore.h"
#include <Common/Log.h>
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);
}

View File

@ -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

View File

@ -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<u8> 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)

View File

@ -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

View File

@ -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;

View File

@ -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 <FileIO/FileIO.h>
@ -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);
};

View File

@ -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);

View File

@ -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);
};

View File

@ -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);
}

View File

@ -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);
};

View File

@ -1,5 +1,5 @@
#include "CMaterialLoader.h"
#include "Core/Resource/CResCache.h"
#include "Core/GameProject/CResourceStore.h"
#include "Core/OpenGL/GLCommon.h"
#include <Common/Log.h>
#include <iostream>
@ -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();

View File

@ -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 <FileIO/FileIO.h>
#include <assimp/scene.h>

View File

@ -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);

View File

@ -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 <Common/Flags.h>
@ -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<CModel*>& rkIn, std::vector<CModel*>& rOut, bool DeleteInputModels);

View File

@ -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++)

View File

@ -11,7 +11,7 @@ class CPoiToWorldLoader
CPoiToWorldLoader() {}
public:
static CPoiToWorld* LoadEGMC(IInputStream& rEGMC);
static CPoiToWorld* LoadEGMC(IInputStream& rEGMC, CResourceEntry *pEntry);
};
#endif // CPOITOWORLDLOADER_H

View File

@ -1,5 +1,5 @@
#include "CScanLoader.h"
#include "Core/Resource/CResCache.h"
#include "Core/GameProject/CResourceStore.h"
#include <Common/Log.h>
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);
}

View File

@ -7,6 +7,7 @@
class CScanLoader
{
TResPtr<CScan> 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

View File

@ -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 <Common/Log.h>
#include <iostream>
#include <sstream>
@ -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);
}

View File

@ -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
{

View File

@ -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)
{

View File

@ -15,7 +15,7 @@ class CSkeletonLoader
void CalculateBoneInverseBindMatrices();
public:
static CSkeleton* LoadCINF(IInputStream& rCINF);
static CSkeleton* LoadCINF(IInputStream& rCINF, CResourceEntry *pEntry);
};
#endif // CSKELETONLOADER_H

View File

@ -2,12 +2,12 @@
#include <Common/AssertMacro.h>
// ************ 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++)

View File

@ -8,7 +8,7 @@ class CSkinLoader
{
CSkinLoader() {}
public:
static CSkin* LoadCSKR(IInputStream& rCSKR);
static CSkin* LoadCSKR(IInputStream& rCSKR, CResourceEntry *pEntry);
};
#endif // CSKINLOADER_H

View File

@ -1,10 +1,6 @@
#include "CStringLoader.h"
#include <Common/Log.h>
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);

View File

@ -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<CStringTable> 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);
};

View File

@ -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();

View File

@ -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

View File

@ -1,5 +1,5 @@
#include "CWorldLoader.h"
#include "Core/Resource/CResCache.h"
#include "Core/GameProject/CResourceStore.h"
#include <Common/Log.h>
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;

View File

@ -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 <FileIO/FileIO.h>
@ -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);
};

View File

@ -2,8 +2,8 @@
#include <iostream>
#include <list>
CBasicModel::CBasicModel()
: CResource()
CBasicModel::CBasicModel(CResourceEntry *pEntry /*= 0*/)
: CResource(pEntry)
, mVertexCount(0)
, mTriangleCount(0)
, mBuffered(false)

View File

@ -21,7 +21,7 @@ protected:
std::vector<SSurface*> mSurfaces;
public:
CBasicModel();
CBasicModel(CResourceEntry *pEntry = 0);
~CBasicModel();
u32 GetVertexCount();

View File

@ -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 <Common/AssertMacro.h>
CModel::CModel()
: CBasicModel()
CModel::CModel(CResourceEntry *pEntry /*= 0*/)
: CBasicModel(pEntry)
{
mHasOwnMaterials = true;
mHasOwnSurfaces = true;

View File

@ -21,7 +21,7 @@ class CModel : public CBasicModel
bool mHasOwnMaterials;
public:
CModel();
CModel(CResourceEntry *pEntry = 0);
CModel(CMaterialSet *pSet, bool OwnsMatSet);
~CModel();

View File

@ -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<u32>(mSurfaces.size()));
while (mIBOs.size() > mSurfaceEndOffsets.size())
mSurfaceEndOffsets.emplace_back(std::vector<u32>(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)

View File

@ -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<CIndexBuffer> mIBOs;
std::vector<std::vector<u32>> mSubmeshEndOffsets;
std::vector<std::vector<u32>> mSurfaceEndOffsets;
bool mTransparent;
public:

View File

@ -2,7 +2,7 @@
#define CLINK_H
#include "CScriptObject.h"
#include "Core/Resource/CGameArea.h"
#include "Core/Resource/Area/CGameArea.h"
#include <Common/TString.h>
#include <Common/types.h>

View File

@ -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;

View File

@ -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 <Common/Log.h>
@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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 <Common/AssertMacro.h>
#include <Math/CTransform4f.h>
@ -258,7 +258,7 @@ void CSceneNode::DrawBoundingBox() const
void CSceneNode::DrawRotationArrow() const
{
static TResPtr<CModel> spArrowModel = gResCache.GetResource("../resources/RotationArrow.cmdl");
static TResPtr<CModel> spArrowModel = gResourceStore.LoadResource("../resources/RotationArrow.cmdl");
spArrowModel->Draw(eNoRenderOptions, 0);
}

View File

@ -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 <Common/types.h>
#include <Math/CAABox.h>

View File

@ -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;
}

View File

@ -1,8 +1,8 @@
#include "CGizmo.h"
#include <Math/MathUtil.h>
#include <Core/GameProject/CResourceStore.h>
#include <Core/Render/CDrawUtil.h>
#include <Core/Render/CRenderer.h>
#include <Core/Resource/CResCache.h>
#include <Common/Log.h>
#include <iostream>
@ -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;
}

View File

@ -8,7 +8,7 @@
#include "Editor/ModelEditor/CModelEditorWindow.h"
#include "Editor/WorldEditor/CWorldEditor.h"
#include <Core/GameProject/CGameExporter.h>
#include <Core/Resource/CResCache.h>
#include <Core/GameProject/CResourceStore.h>
#include <QFileDialog>
#include <QMessageBox>
@ -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<CGameArea> pArea = gResCache.GetResource(AreaID, "MREA");
CUniqueID AreaID = mpWorld->AreaResourceID(mSelectedAreaIndex);
TString AreaPath = mpWorld->Entry()->CookedAssetPath().GetFileDirectory() + AreaID.ToString() + ".MREA";
TResPtr<CGameArea> 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();
}
}

View File

@ -4,8 +4,8 @@
#include "WorldEditor/CWorldEditor.h"
#include "ModelEditor/CModelEditorWindow.h"
#include "CharacterEditor/CCharacterEditor.h"
#include <Core/GameProject/CResourceStore.h>
#include <Core/Resource/CWorld.h>
#include <Core/Resource/CResCache.h>
#include <QMainWindow>

View File

@ -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)

View File

@ -580,7 +580,7 @@ void CModelEditorWindow::UpdateMaterial(QString Value)
if (mIgnoreSignals) return;
EModelEditorWidget Widget = (EModelEditorWidget) sender()->property("ModelEditorWidgetType").toInt();
TResPtr<CTexture> pTex = gResCache.GetResource(TO_TSTRING(Value));
TResPtr<CTexture> 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<CModel> pModel = gResCache.GetResource(ModelFilename.toStdString());
TResPtr<CModel> 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<CTexture> pTex = gResCache.GetResource(TexFilename);
TResPtr<CTexture> 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))

View File

@ -2,9 +2,9 @@
#define CMODELEDITORWINDOW_H
#include "CModelEditorViewport.h"
#include <Core/GameProject/CResourceStore.h>
#include <Core/Render/CRenderer.h>
#include <Core/Resource/CFont.h>
#include <Core/Resource/CResCache.h>
#include <Core/Resource/Model/CModel.h>
#include <Core/Scene/CScene.h>
#include <Core/Scene/CModelNode.h>

View File

@ -5,7 +5,7 @@
#include "CClearSelectionCommand.h"
#include "CSelectNodeCommand.h"
#include "Editor/WorldEditor/CWorldEditor.h"
#include <Core/Resource/CGameArea.h>
#include <Core/Resource/Area/CGameArea.h>
#include <Core/Resource/Script/CScriptLayer.h>
#include <Core/Resource/Script/CScriptObject.h>

View File

@ -1,7 +1,7 @@
#ifndef OBJREFERENCES
#define OBJREFERENCES
#include <Core/Resource/CGameArea.h>
#include <Core/Resource/Area/CGameArea.h>
#include <Core/Resource/Script/CLink.h>
#include <Core/Resource/Script/CScriptObject.h>
#include <Core/Scene/CScene.h>

View File

@ -1,7 +1,7 @@
#include "WAnimParamsEditor.h"
#include "Editor/UICommon.h"
#include <Core/GameProject/CResourceStore.h>
#include <Core/Resource/CAnimSet.h>
#include <Core/Resource/CResCache.h>
#include <Core/Resource/CResourceInfo.h>
WAnimParamsEditor::WAnimParamsEditor(QWidget *pParent)

View File

@ -1,7 +1,7 @@
#include "WResourceSelector.h"
#include "WTexturePreviewPanel.h"
#include "Editor/UICommon.h"
#include <Core/Resource/CResCache.h>
#include <Core/GameProject/CResourceStore.h>
#include <QApplication>
#include <QCompleter>

View File

@ -1,8 +1,8 @@
#include "WTextureGLWidget.h"
#include <Math/CTransform4f.h>
#include <Core/GameProject/CResourceStore.h>
#include <Core/Render/CDrawUtil.h>
#include <Core/Render/CGraphics.h>
#include <Core/Resource/CResCache.h>
#include <iostream>
#include <iomanip>

View File

@ -1,7 +1,7 @@
#ifndef CLAYERMODEL_H
#define CLAYERMODEL_H
#include <Core/Resource/CGameArea.h>
#include <Core/Resource/Area/CGameArea.h>
#include <QAbstractListModel>
class CLayerModel : public QAbstractListModel

Some files were not shown because too many files have changed in this diff Show More