Made a bunch of changes to make the resource store system more friendly to multiple stores instead of just a single active one, and set up a resource database for editor assets

This commit is contained in:
parax0 2016-08-31 02:09:13 -06:00
parent 1de2691f33
commit a7b381f301
35 changed files with 848 additions and 178 deletions

View File

@ -0,0 +1,505 @@
<?xml version="1.0" encoding="UTF-8"?>
<ResourceDB ArchiveVer="0" FileVer="0" Game="MPRM">
<RawDir></RawDir>
<CookedDir></CookedDir>
<Resources Size="83">
<Resource>
<ID>08F992A8</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>RandomRelay</Name>
</Resource>
<Resource>
<ID>0A11104B</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>TranslateX</Name>
</Resource>
<Resource>
<ID>0E04ED00</ID>
<Type>TXTR</Type>
<Directory></Directory>
<Name>LightAmbientMask</Name>
</Resource>
<Resource>
<ID>0EDB1C7A</ID>
<Type>CMDL</Type>
<Directory>script\dkcr\</Directory>
<Name>Waypoint</Name>
</Resource>
<Resource>
<ID>0FB28A24</ID>
<Type>TXTR</Type>
<Directory></Directory>
<Name>LightAmbient</Name>
</Resource>
<Resource>
<ID>0FD29E3B</ID>
<Type>CMDL</Type>
<Directory>script\common\</Directory>
<Name>Waypoint</Name>
</Resource>
<Resource>
<ID>115C21DD</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>CameraFilterKeyframe</Name>
</Resource>
<Resource>
<ID>1C010ADC</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>TranslatePolyXY</Name>
</Resource>
<Resource>
<ID>1FFC7E43</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>RotateXYZ</Name>
</Resource>
<Resource>
<ID>2A14558D</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>HUDMemo</Name>
</Resource>
<Resource>
<ID>2B75E193</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>VisorFlare</Name>
</Resource>
<Resource>
<ID>31485556</ID>
<Type>TXTR</Type>
<Directory>script\mp2\</Directory>
<Name>AdvancedCounter</Name>
</Resource>
<Resource>
<ID>31992094</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>TranslateY</Name>
</Resource>
<Resource>
<ID>32432719</ID>
<Type>CMDL</Type>
<Directory>script\common\</Directory>
<Name>SpiderBallWaypoint</Name>
</Resource>
<Resource>
<ID>32C9F9D1</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>StreamedAudio</Name>
</Resource>
<Resource>
<ID>3440526F</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>TranslateLinesXY</Name>
</Resource>
<Resource>
<ID>3A947189</ID>
<Type>CMDL</Type>
<Directory>script\common\</Directory>
<Name>AIWaypoint</Name>
</Resource>
<Resource>
<ID>3C093300</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>ScaleXYZ</Name>
</Resource>
<Resource>
<ID>40969072</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>AreaAttributes</Name>
</Resource>
<Resource>
<ID>43891B25</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>TranslatePolyXZ</Name>
</Resource>
<Resource>
<ID>43E9B0A9</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>ScaleX</Name>
</Resource>
<Resource>
<ID>4443279C</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>CameraBlurKeyframe</Name>
</Resource>
<Resource>
<ID>4A2D76D1</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>DamageableTrigger</Name>
</Resource>
<Resource>
<ID>4C3D3E7F</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>GrapplePoint</Name>
</Resource>
<Resource>
<ID>4E133EF2</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>SpiderBallAttractionSurface</Name>
</Resource>
<Resource>
<ID>57F8715F</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>Dock</Name>
</Resource>
<Resource>
<ID>592130DD</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>TranslateZ</Name>
</Resource>
<Resource>
<ID>5BC862B8</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>TranslateLinesXZ</Name>
</Resource>
<Resource>
<ID>5D08CCF6</ID>
<Type>TXTR</Type>
<Directory>script\mp3\</Directory>
<Name>WeaponGenerator</Name>
</Resource>
<Resource>
<ID>5F3B141B</ID>
<Type>CMDL</Type>
<Directory></Directory>
<Name>VolumeBox</Name>
</Resource>
<Resource>
<ID>61B511E5</ID>
<Type>TXTR</Type>
<Directory></Directory>
<Name>Checkerboard</Name>
</Resource>
<Resource>
<ID>6649251D</ID>
<Type>CMDL</Type>
<Directory>script\common\</Directory>
<Name>Camera</Name>
</Resource>
<Resource>
<ID>6A17B38F</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>Sound</Name>
</Resource>
<Resource>
<ID>6B1FABDD</ID>
<Type>CMDL</Type>
<Directory></Directory>
<Name>Cube</Name>
</Resource>
<Resource>
<ID>6B71C0F2</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>ScaleY</Name>
</Resource>
<Resource>
<ID>6C6CE7FE</ID>
<Type>TXTR</Type>
<Directory></Directory>
<Name>LightSpotMask</Name>
</Resource>
<Resource>
<ID>6D5BC167</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>Effect</Name>
</Resource>
<Resource>
<ID>6DD88D5D</ID>
<Type>CMDL</Type>
<Directory></Directory>
<Name>RotationArrow</Name>
</Resource>
<Resource>
<ID>6E57F7E0</ID>
<Type>CMDL</Type>
<Directory></Directory>
<Name>VolumeCylinder</Name>
</Resource>
<Resource>
<ID>72978DCF</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>Relay</Name>
</Resource>
<Resource>
<ID>791A7BFD</ID>
<Type>CMDL</Type>
<Directory></Directory>
<Name>SphereDoubleSided</Name>
</Resource>
<Resource>
<ID>7F494724</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>RotateX</Name>
</Resource>
<Resource>
<ID>81326A53</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>ScaleLinesYZ</Name>
</Resource>
<Resource>
<ID>825CDFA8</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>ScalePolyYZ</Name>
</Resource>
<Resource>
<ID>826C9800</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>ColorModulate</Name>
</Resource>
<Resource>
<ID>85CE16D7</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>StreamedMovie</Name>
</Resource>
<Resource>
<ID>875A6FD7</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>PointOfInterest</Name>
</Resource>
<Resource>
<ID>9039791A</ID>
<Type>TXTR</Type>
<Directory></Directory>
<Name>LightDirectional</Name>
</Resource>
<Resource>
<ID>91437414</ID>
<Type>CMDL</Type>
<Directory>script\common\</Directory>
<Name>CameraWaypoint</Name>
</Resource>
<Resource>
<ID>92F9D13B</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>ScaleZ</Name>
</Resource>
<Resource>
<ID>95261BB8</ID>
<Type>CMDL</Type>
<Directory></Directory>
<Name>WireSphere</Name>
</Resource>
<Resource>
<ID>968C405E</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>SoundModifier</Name>
</Resource>
<Resource>
<ID>9FF04AA1</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>Generator</Name>
</Resource>
<Resource>
<ID>A6D1576D</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>RotateY</Name>
</Resource>
<Resource>
<ID>A82A3F02</ID>
<Type>TXTR</Type>
<Directory></Directory>
<Name>LightSpot</Name>
</Resource>
<Resource>
<ID>AC18950A</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>RadialDamage</Name>
</Resource>
<Resource>
<ID>B0D52FF7</ID>
<Type>TXTR</Type>
<Directory></Directory>
<Name>LightCustomMask</Name>
</Resource>
<Resource>
<ID>B0E09096</ID>
<Type>TXTR</Type>
<Directory></Directory>
<Name>LightDirectionalMask</Name>
</Resource>
<Resource>
<ID>B23F1022</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>VisorGoo</Name>
</Resource>
<Resource>
<ID>B2DBCAED</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>PickupGenerator</Name>
</Resource>
<Resource>
<ID>B3050E38</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>SequenceTimer</Name>
</Resource>
<Resource>
<ID>B97DB26B</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>Timer</Name>
</Resource>
<Resource>
<ID>BA7EA4F6</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>Trigger</Name>
</Resource>
<Resource>
<ID>C0FBED3D</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>ScaleLinesXY</Name>
</Resource>
<Resource>
<ID>C2266292</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>ScalePolyXY</Name>
</Resource>
<Resource>
<ID>C4E83425</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>DistanceFog</Name>
</Resource>
<Resource>
<ID>C7BEFE29</ID>
<Type>CMDL</Type>
<Directory></Directory>
<Name>VolumeSphere</Name>
</Resource>
<Resource>
<ID>CB904B3D</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>SpecialFunction</Name>
</Resource>
<Resource>
<ID>CE5967B6</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>RotateZ</Name>
</Resource>
<Resource>
<ID>D2F07DAF</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>ConditionalRelay</Name>
</Resource>
<Resource>
<ID>D7B6A50D</ID>
<Type>CMDL</Type>
<Directory></Directory>
<Name>Sphere</Name>
</Resource>
<Resource>
<ID>DA185196</ID>
<Type>TXTR</Type>
<Directory></Directory>
<Name>VolumeCheckerboard</Name>
</Resource>
<Resource>
<ID>DC3787F2</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>TranslatePolyYZ</Name>
</Resource>
<Resource>
<ID>E1A0D860</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>StreamedAudioModifier</Name>
</Resource>
<Resource>
<ID>E883FD86</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>ScaleLinesXZ</Name>
</Resource>
<Resource>
<ID>E9AE72DB</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>ScalePolyXZ</Name>
</Resource>
<Resource>
<ID>EE340FC4</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>MemoryRelay</Name>
</Resource>
<Resource>
<ID>F476CF85</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>TranslateLinesYZ</Name>
</Resource>
<Resource>
<ID>F76B369A</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>Counter</Name>
</Resource>
<Resource>
<ID>FB50DA78</ID>
<Type>CMDL</Type>
<Directory>editor\</Directory>
<Name>RotateClipOutline</Name>
</Resource>
<Resource>
<ID>FC8FA98B</ID>
<Type>TXTR</Type>
<Directory></Directory>
<Name>LightCustom</Name>
</Resource>
<Resource>
<ID>FD78FBC8</ID>
<Type>TXTR</Type>
<Directory>script\mp1\</Directory>
<Name>NewCameraShaker</Name>
</Resource>
<Resource>
<ID>FFAC2525</ID>
<Type>TXTR</Type>
<Directory>script\common\</Directory>
<Name>CameraShaker</Name>
</Resource>
</Resources>
</ResourceDB>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -18,17 +18,13 @@
#define EXPORT_COOKED 1
CGameExporter::CGameExporter(const TString& rkInputDir, const TString& rkOutputDir)
: mStore(this)
{
mGameDir = FileUtil::MakeAbsolute(rkInputDir);
mExportDir = FileUtil::MakeAbsolute(rkOutputDir);
mpProject = new CGameProject(mExportDir);
mDiscDir = mpProject->DiscDir(true);
mContentDir = mpProject->ContentDir(false);
mCookedDir = mpProject->CookedDir(false);
mWorldsDirName = L"Worlds\\";
mStore.SetActiveProject(mpProject);
}
#if PUBLIC_RELEASE
@ -39,18 +35,27 @@ bool CGameExporter::Export()
{
SCOPED_TIMER(ExportGame);
CResourceStore *pOldStore = gpResourceStore;
gpResourceStore = &mStore;
FileUtil::CreateDirectory(mExportDir);
FileUtil::ClearDirectory(mExportDir);
CopyDiscData();
mpStore = new CResourceStore(this, L"Content\\", L"Cooked\\", mpProject->Game());
mpStore->SetProject(mpProject);
mContentDir = mpStore->RawDir(false);
mCookedDir = mpStore->CookedDir(false);
CResourceStore *pOldStore = gpResourceStore;
gpResourceStore = mpStore;
LoadAssetList();
LoadPaks();
ExportWorlds();
ExportCookedResources();
gpResourceStore = pOldStore;
delete mpStore;
mpStore = nullptr;
return true;
}
@ -464,7 +469,7 @@ void CGameExporter::ExportWorlds()
if (rkRes.Type == "MLVL" && !rkRes.Name.EndsWith("NODEPEND"))
{
// Load world
CWorld *pWorld = (CWorld*) mStore.LoadResource(rkRes.ID, rkRes.Type);
CWorld *pWorld = (CWorld*) mpStore->LoadResource(rkRes.ID, rkRes.Type);
if (!pWorld)
{
@ -510,7 +515,7 @@ void CGameExporter::ExportWorlds()
}
}
mStore.DestroyUnreferencedResources();
mpStore->DestroyUnreferencedResources();
}
#endif
}
@ -530,7 +535,7 @@ void CGameExporter::ExportCookedResources()
{
SCOPED_TIMER(SaveResourceDatabase);
#if EXPORT_COOKED
mStore.SaveResourceDatabase();
mpStore->SaveResourceDatabase();
#endif
mpProject->Save();
}
@ -544,7 +549,7 @@ void CGameExporter::ExportCookedResources()
// todo: we're wasting a ton of time loading the same resources over and over because most resources automatically
// load all their dependencies and then we just clear it out from memory even though we'll need it again later. we
// should really be doing this by dependency order instead of by ID order.
for (CResourceIterator It(&mStore); It; ++It)
for (CResourceIterator It(mpStore); It; ++It)
{
if (!It->IsTransient())
{
@ -571,7 +576,7 @@ void CGameExporter::ExportCookedResources()
{
// All resources should have dependencies generated, so save the cache file
SCOPED_TIMER(SaveResourceCacheData);
mStore.SaveCacheFile();
mpStore->SaveCacheFile();
}
}
@ -596,7 +601,7 @@ void CGameExporter::ExportResource(SResourceInstance& rRes)
if (OutDir.IsEmpty()) OutDir = L"Uncategorized\\";
// Register resource and write to file
CResourceEntry *pEntry = mStore.RegisterResource(rRes.ResourceID, CResource::ResTypeForExtension(rRes.ResourceType), OutDir, OutName);
CResourceEntry *pEntry = mpStore->RegisterResource(rRes.ResourceID, CResource::ResTypeForExtension(rRes.ResourceType), OutDir, OutName);
#if EXPORT_COOKED
// Save cooked asset

View File

@ -13,7 +13,7 @@ class CGameExporter
{
// Project
CGameProject *mpProject;
CResourceStore mStore;
CResourceStore *mpStore;
// Directories
TWideString mGameDir;

View File

@ -7,10 +7,7 @@ CGameProject *CGameProject::mspActiveProject = nullptr;
CGameProject::~CGameProject()
{
if (IsActive())
{
mspActiveProject = nullptr;
gpResourceStore->SetActiveProject(nullptr);
}
}
bool CGameProject::Load(const TWideString& rkPath)
@ -21,6 +18,8 @@ bool CGameProject::Load(const TWideString& rkPath)
TString ProjPath = rkPath.ToUTF8();
CXMLReader Reader(ProjPath);
Serialize(Reader);
mpResourceStore->LoadResourceDatabase();
return true;
}
@ -72,7 +71,7 @@ void CGameProject::SetActive()
if (mspActiveProject != this)
{
mspActiveProject = this;
gpResourceStore->SetActiveProject(this);
gpResourceStore = mpResourceStore;
}
}

View File

@ -16,6 +16,7 @@ class CGameProject
TWideString mProjectRoot;
TWideString mResourceDBPath;
std::vector<CPackage*> mPackages;
CResourceStore *mpResourceStore;
enum EProjectVersion
{
@ -31,7 +32,9 @@ public:
CGameProject()
: mGame(eUnknownGame)
, mProjectName("Unnamed Project")
{}
{
mpResourceStore = new CResourceStore(this);
}
CGameProject(const TWideString& rkProjRootDir)
: mGame(eUnknownGame)
@ -39,6 +42,7 @@ public:
, mProjectRoot(rkProjRootDir)
, mResourceDBPath(L"ResourceDB.rdb")
{
mpResourceStore = new CResourceStore(this);
mProjectRoot.Replace(L"/", L"\\");
}
@ -55,8 +59,6 @@ public:
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 CacheDir(bool Relative) const { return Relative ? L"Cache\\" : mProjectRoot + L"Cache\\"; }
inline TWideString ContentDir(bool Relative) const { return Relative ? L"Content\\" : mProjectRoot + L"Content\\"; }
inline TWideString CookedDir(bool Relative) const { return Relative ? L"Cooked\\" : mProjectRoot + L"Cooked\\"; }
inline TWideString PackagesDir(bool Relative) const { return Relative ? L"Packages\\" : mProjectRoot + L"Packages\\"; }
inline TWideString ProjectPath() const { return mProjectRoot + FileUtil::SanitizeName(mProjectName.ToUTF16(), false) + L".prj"; }
inline TWideString ResourceCachePath(bool Relative) const { return ResourceDBPath(Relative).GetFileDirectory() + L"ResourceCacheData.rcd"; }
@ -68,7 +70,7 @@ public:
inline u32 NumPackages() const { return mPackages.size(); }
inline CPackage* PackageByIndex(u32 Index) const { return mPackages[Index]; }
inline void AddPackage(CPackage *pPackage) { mPackages.push_back(pPackage); }
inline CResourceStore* ResourceStore() const { return mpResourceStore; }
inline EGame Game() const { return mGame; }
inline bool IsActive() const { return mspActiveProject == this; }

View File

@ -25,7 +25,7 @@ CResourceEntry::CResourceEntry(CResourceStore *pStore, const CAssetID& rkID,
mpDirectory = mpStore->GetVirtualDirectory(rkDir, Transient, true);
if (mpDirectory) mpDirectory->AddChild(L"", this);
mGame = ((Transient || !mpStore->ActiveProject()) ? eUnknownGame : mpStore->ActiveProject()->Game());
mGame = ((Transient || !mpStore) ? eUnknownGame : mpStore->Game());
}
CResourceEntry::~CResourceEntry()
@ -80,11 +80,6 @@ void CResourceEntry::UpdateDependencies()
mpStore->DestroyUnreferencedResources();
}
TWideString CResourceEntry::CacheDataPath(bool Relative) const
{
return mpStore->ActiveProject()->CacheDir(Relative) + mID.ToString().ToUTF16() + L".rcd";
}
bool CResourceEntry::HasRawVersion() const
{
return FileUtil::Exists(RawAssetPath());
@ -100,7 +95,12 @@ TString CResourceEntry::RawAssetPath(bool Relative) const
TWideString Ext = GetResourceRawExtension(mType, mGame).ToUTF16();
TWideString Path = mpDirectory ? mpDirectory->FullPath() : L"";
TWideString Name = mName + L"." + Ext;
return ((IsTransient() || Relative) ? Path + Name : mpStore->ActiveProject()->ContentDir(false) + Path + Name);
return ((IsTransient() || Relative) ? Path + Name : mpStore->RawDir(false) + Path + Name);
}
TString CResourceEntry::RawExtension() const
{
return GetResourceRawExtension(mType, mGame);
}
TString CResourceEntry::CookedAssetPath(bool Relative) const
@ -108,7 +108,7 @@ TString CResourceEntry::CookedAssetPath(bool Relative) const
TWideString Ext = GetResourceCookedExtension(mType, mGame).ToUTF16();
TWideString Path = mpDirectory ? mpDirectory->FullPath() : L"";
TWideString Name = mName + L"." + Ext;
return ((IsTransient() || Relative) ? Path + Name : mpStore->ActiveProject()->CookedDir(false) + Path + Name);
return ((IsTransient() || Relative) ? Path + Name : mpStore->CookedDir(false) + Path + Name);
}
CFourCC CResourceEntry::CookedExtension() const
@ -218,8 +218,14 @@ CResource* CResourceEntry::Load()
if (mpResource)
{
// Set gpResourceStore to ensure the correct resource store is accessed by loader functions
CResourceStore *pOldStore = gpResourceStore;
gpResourceStore = mpStore;
CXMLReader Reader(RawAssetPath());
mpResource->Serialize(Reader);
gpResourceStore = pOldStore;
}
return mpResource;
@ -251,8 +257,14 @@ CResource* CResourceEntry::LoadCooked(IInputStream& rInput)
if (mpResource) return mpResource;
if (!rInput.IsValid()) return nullptr;
// Set gpResourceStore to ensure the correct resource store is accessed by loader functions
CResourceStore *pOldStore = gpResourceStore;
gpResourceStore = mpStore;
mpResource = CResourceFactory::LoadCookedResource(this, rInput);
mpStore->TrackLoadedResource(this);
gpResourceStore = pOldStore;
return mpResource;
}

View File

@ -46,11 +46,11 @@ public:
void SerializeCacheData(IArchive& rArc);
void UpdateDependencies();
TWideString CacheDataPath(bool Relative = false) const;
bool HasRawVersion() const;
bool HasCookedVersion() const;
TString RawAssetPath(bool Relative = false) const;
TString RawExtension() const;
TString CookedAssetPath(bool Relative = false) const;
CFourCC CookedExtension() const;
bool IsInDirectory(CVirtualDirectory *pDir) const;
@ -70,6 +70,7 @@ public:
inline bool IsLoaded() const { return mpResource != nullptr; }
inline CResource* Resource() const { return mpResource; }
inline CResourceStore* ResourceStore() const { return mpStore; }
inline CDependencyTree* Dependencies() const { return mpDependencies; }
inline CAssetID ID() const { return mID; }
inline EGame Game() const { return mGame; }

View File

@ -11,23 +11,40 @@
#include <tinyxml2.h>
using namespace tinyxml2;
CResourceStore *gpResourceStore = new CResourceStore;
CResourceStore *gpResourceStore = nullptr;
CResourceStore *gpEditorStore = nullptr;
CResourceStore::CResourceStore()
CResourceStore::CResourceStore(const TWideString& rkDatabasePath)
: mpProj(nullptr)
, mpProjectRoot(nullptr)
, mGame(eUnknownGame)
, mpExporter(nullptr)
{}
{
mpDatabaseRoot = new CVirtualDirectory();
mDatabasePath = FileUtil::MakeAbsolute(rkDatabasePath.GetFileDirectory());
mDatabaseName = rkDatabasePath.GetFileName();
}
CResourceStore::CResourceStore(CGameExporter *pExporter)
CResourceStore::CResourceStore(CGameExporter *pExporter, const TWideString& rkRawDir, const TWideString& rkCookedDir, EGame Game)
: mpProj(nullptr)
, mpProjectRoot(nullptr)
, mGame(Game)
, mRawDir(rkRawDir)
, mCookedDir(rkCookedDir)
, mpExporter(pExporter)
{}
{
}
CResourceStore::CResourceStore(CGameProject *pProject)
: mpProj(nullptr)
, mGame(eUnknownGame)
, mpDatabaseRoot(nullptr)
, mpExporter(nullptr)
{
SetProject(pProject);
}
CResourceStore::~CResourceStore()
{
CloseActiveProject();
CloseProject();
DestroyUnreferencedResources();
for (auto It = mResourceEntries.begin(); It != mResourceEntries.end(); It++)
@ -66,7 +83,9 @@ void CResourceStore::SerializeResourceDatabase(IArchive& rArc)
}
// Serialize
rArc << SERIAL_CONTAINER_AUTO(Resources, "Resource");
rArc << SERIAL("RawDir", mRawDir)
<< SERIAL("CookedDir", mCookedDir)
<< SERIAL_CONTAINER_AUTO(Resources, "Resource");
// Register resources
if (rArc.IsReader())
@ -81,27 +100,29 @@ void CResourceStore::SerializeResourceDatabase(IArchive& rArc)
void CResourceStore::LoadResourceDatabase()
{
ASSERT(mpProj);
TString Path = mpProj->ResourceDBPath(false).ToUTF8();
ASSERT(!mDatabasePath.IsEmpty());
TString Path = DatabasePath().ToUTF8();
if (!mpDatabaseRoot)
mpDatabaseRoot = new CVirtualDirectory();
CXMLReader Reader(Path);
if (!mpProj) mGame = Reader.Game();
SerializeResourceDatabase(Reader);
LoadCacheFile();
}
void CResourceStore::SaveResourceDatabase()
{
ASSERT(mpProj);
TString Path = mpProj->ResourceDBPath(false).ToUTF8();
CXMLWriter Writer(Path, "ResourceDB", 0, mpProj ? mpProj->Game() : eUnknownGame);
TString Path = DatabasePath().ToUTF8();
CXMLWriter Writer(Path, "ResourceDB", 0, mGame);
SerializeResourceDatabase(Writer);
}
void CResourceStore::LoadCacheFile()
{
TString CacheDataPath = mpProj->ResourceCachePath(false).ToUTF8();
CFileInStream CacheFile(CacheDataPath.ToStdString(), IOUtil::eBigEndian);
TString CachePath = CacheDataPath().ToUTF8();
CFileInStream CacheFile(CachePath.ToStdString(), IOUtil::eBigEndian);
ASSERT(CacheFile.IsValid());
// Cache header
@ -141,13 +162,13 @@ void CResourceStore::LoadCacheFile()
void CResourceStore::SaveCacheFile()
{
TString CacheDataPath = mpProj->ResourceCachePath(false).ToUTF8();
CFileOutStream CacheFile(CacheDataPath.ToStdString(), IOUtil::eBigEndian);
TString CachePath = CacheDataPath().ToUTF8();
CFileOutStream CacheFile(CachePath.ToStdString(), IOUtil::eBigEndian);
ASSERT(CacheFile.IsValid());
// Cache header
CFourCC("CACH").Write(CacheFile);
CSerialVersion Version(0, 0, mpProj->Game());
CSerialVersion Version(0, 0, mGame);
Version.Write(CacheFile);
u32 ResCountOffset = CacheFile.Tell();
@ -184,23 +205,26 @@ void CResourceStore::SaveCacheFile()
CacheFile.WriteLong(ResCount);
}
void CResourceStore::SetActiveProject(CGameProject *pProj)
void CResourceStore::SetProject(CGameProject *pProj)
{
if (mpProj == pProj) return;
CloseActiveProject();
if (mpProj)
CloseProject();
mpProj = pProj;
if (pProj)
if (mpProj)
{
mpProjectRoot = new CVirtualDirectory();
if (!mpExporter)
LoadResourceDatabase();
TWideString DatabasePath = mpProj->ResourceDBPath(false);
mDatabasePath = DatabasePath.GetFileDirectory();
mDatabaseName = DatabasePath.GetFileName();
mpDatabaseRoot = new CVirtualDirectory();
mGame = mpProj->Game();
}
}
void CResourceStore::CloseActiveProject()
void CResourceStore::CloseProject()
{
// Destroy unreferenced resources first. (This is necessary to avoid invalid memory accesses when
// various TResPtrs are destroyed. There might be a cleaner solution than this.)
@ -233,14 +257,15 @@ void CResourceStore::CloseActiveProject()
It++;
}
delete mpProjectRoot;
mpProjectRoot = nullptr;
delete mpDatabaseRoot;
mpDatabaseRoot = nullptr;
mpProj = nullptr;
mGame = eUnknownGame;
}
CVirtualDirectory* CResourceStore::GetVirtualDirectory(const TWideString& rkPath, bool Transient, bool AllowCreate)
{
if (rkPath.IsEmpty()) return nullptr;
if (rkPath.IsEmpty()) return mpDatabaseRoot;
else if (Transient)
{
@ -260,9 +285,9 @@ CVirtualDirectory* CResourceStore::GetVirtualDirectory(const TWideString& rkPath
else return nullptr;
}
else if (mpProjectRoot)
else if (mpDatabaseRoot)
{
return mpProjectRoot->FindChildDirectory(rkPath, AllowCreate);
return mpDatabaseRoot->FindChildDirectory(rkPath, AllowCreate);
}
else return nullptr;
@ -276,6 +301,11 @@ CResourceEntry* CResourceStore::FindEntry(const CAssetID& rkID) const
else return Found->second;
}
CResourceEntry* CResourceStore::FindEntry(const TWideString& rkPath) const
{
return (mpDatabaseRoot ? mpDatabaseRoot->FindChildResource(rkPath) : nullptr);
}
bool CResourceStore::IsResourceRegistered(const CAssetID& rkID) const
{
return FindEntry(rkID) == nullptr;
@ -382,10 +412,37 @@ CResource* CResourceStore::LoadResource(const CAssetID& rkID, const CFourCC& rkT
}
}
CResource* CResourceStore::LoadResource(const TString& rkPath)
CResource* CResourceStore::LoadResource(const TWideString& rkPath)
{
// todo - support loading raw resources from arbitrary directory
// Construct ID from string, check if resource is loaded already
// If this is a relative path then load via the resource DB
if (!FileUtil::IsAbsolute(rkPath))
{
CResourceEntry *pEntry = FindEntry(rkPath);
if (pEntry)
{
// Verify extension matches the entry + load resource
TString Ext = rkPath.ToUTF8().GetFileExtension();
if (!Ext.IsEmpty())
{
if (Ext.Length() == 4)
{
ASSERT(Ext.CaseInsensitiveCompare(pEntry->CookedExtension().ToString()));
}
else
{
ASSERT(Ext.CaseInsensitiveCompare(pEntry->RawExtension()));
}
}
return pEntry->Load();
}
else return nullptr;
}
// Otherwise create transient entry; construct ID from string, check if resource is loaded already
TWideString Dir = FileUtil::MakeAbsolute(TWideString(rkPath.GetFileDirectory()));
TString Name = rkPath.GetFileName(false);
CAssetID ID = (Name.IsHexString() ? Name.ToInt64() : rkPath.Hash64());
@ -395,21 +452,22 @@ CResource* CResourceStore::LoadResource(const TString& rkPath)
return Find->second->Resource();
// Determine type
TString Extension = rkPath.GetFileExtension().ToUpper();
TString PathUTF8 = rkPath.ToUTF8();
TString Extension = TString(PathUTF8).GetFileExtension().ToUpper();
EResType Type = CResource::ResTypeForExtension(Extension);
if (Type == eInvalidResType)
{
Log::Error("Unable to load resource " + rkPath + "; unrecognized extension: " + Extension);
Log::Error("Unable to load resource " + PathUTF8 + "; unrecognized extension: " + Extension);
return nullptr;
}
// Open file
CFileInStream File(rkPath.ToStdString(), IOUtil::eBigEndian);
CFileInStream File(PathUTF8.ToStdString(), IOUtil::eBigEndian);
if (!File.IsValid())
{
Log::Error("Unable to load resource; couldn't open file: " + rkPath);
Log::Error("Unable to load resource; couldn't open file: " + PathUTF8);
return nullptr;
}

View File

@ -5,6 +5,7 @@
#include "Core/Resource/EResType.h"
#include <Common/CAssetID.h>
#include <Common/CFourCC.h>
#include <Common/FileUtil.h>
#include <Common/TString.h>
#include <Common/types.h>
#include <map>
@ -19,12 +20,17 @@ class CResourceStore
friend class CResourceIterator;
CGameProject *mpProj;
CVirtualDirectory *mpProjectRoot;
EGame mGame;
CVirtualDirectory *mpDatabaseRoot;
std::vector<CVirtualDirectory*> mTransientRoots;
std::map<CAssetID, CResourceEntry*> mResourceEntries;
std::map<CAssetID, CResourceEntry*> mLoadedResources;
// Directory to look for transient resources in
// Directory paths
TWideString mDatabasePath;
TWideString mDatabaseName;
TWideString mRawDir;
TWideString mCookedDir;
TWideString mTransientLoadDir;
// Game exporter currently in use - lets us load from paks being exported
@ -39,26 +45,28 @@ class CResourceStore
};
public:
CResourceStore();
CResourceStore(CGameExporter *pExporter);
CResourceStore(const TWideString& rkDatabasePath);
CResourceStore(CGameExporter *pExporter, const TWideString& rkRawDir, const TWideString& rkCookedDir, EGame Game);
CResourceStore(CGameProject *pProject);
~CResourceStore();
void SerializeResourceDatabase(IArchive& rArc);
void LoadResourceDatabase();
void SaveResourceDatabase();
void LoadCacheFile();
void SaveCacheFile();
void SetActiveProject(CGameProject *pProj);
void CloseActiveProject();
void SetProject(CGameProject *pProj);
void CloseProject();
CVirtualDirectory* GetVirtualDirectory(const TWideString& rkPath, bool Transient, bool AllowCreate);
bool IsResourceRegistered(const CAssetID& rkID) const;
CResourceEntry* RegisterResource(const CAssetID& rkID, EResType Type, const TWideString& rkDir, const TWideString& rkFileName);
CResourceEntry* FindEntry(const CAssetID& rkID) const;
CResourceEntry* FindEntry(const TWideString& rkPath) const;
CResourceEntry* RegisterTransientResource(EResType Type, const TWideString& rkDir = L"", const TWideString& rkFileName = L"");
CResourceEntry* RegisterTransientResource(EResType Type, const CAssetID& rkID, const TWideString& rkDir = L"", const TWideString& rkFileName = L"");
CResource* LoadResource(const CAssetID& rkID, const CFourCC& rkType);
CResource* LoadResource(const TString& rkPath);
CResource* LoadResource(const TWideString& rkPath);
void TrackLoadedResource(CResourceEntry *pEntry);
CFourCC ResourceTypeByID(const CAssetID& rkID, const TStringList& rkPossibleTypes) const;
void DestroyUnreferencedResources();
@ -66,12 +74,19 @@ public:
void SetTransientLoadDir(const TString& rkDir);
// Accessors
inline CGameProject* ActiveProject() const { return mpProj; }
inline CVirtualDirectory* RootDirectory() const { return mpProjectRoot; }
inline u32 NumTotalResources() const { return mResourceEntries.size(); }
inline u32 NumLoadedResources() const { return mLoadedResources.size(); }
inline CGameProject* Project() const { return mpProj; }
inline EGame Game() const { return mGame; }
inline TWideString DatabaseRootPath() const { return mDatabasePath; }
inline TWideString RawDir(bool Relative) const { return Relative ? mRawDir : mDatabasePath + mRawDir; }
inline TWideString CookedDir(bool Relative) const { return Relative ? mCookedDir : mDatabasePath + mCookedDir; }
inline TWideString DatabasePath() const { return DatabaseRootPath() + mDatabaseName; }
inline TWideString CacheDataPath() const { return DatabaseRootPath() + L"ResourceCacheData.rcd"; }
inline CVirtualDirectory* RootDirectory() const { return mpDatabaseRoot; }
inline u32 NumTotalResources() const { return mResourceEntries.size(); }
inline u32 NumLoadedResources() const { return mLoadedResources.size(); }
};
extern CResourceStore *gpResourceStore;
extern CResourceStore *gpEditorStore;
#endif // CRESOURCEDATABASE_H

View File

@ -78,12 +78,24 @@ CVirtualDirectory* CVirtualDirectory::FindChildDirectory(const TWideString& rkNa
return nullptr;
}
CResourceEntry* CVirtualDirectory::FindChildResource(const TWideString& rkName) const
CResourceEntry* CVirtualDirectory::FindChildResource(const TWideString& rkPath)
{
for (u32 iRes = 0; iRes < mResources.size(); iRes++)
TWideString Dir = rkPath.GetFileDirectory();
TWideString Name = rkPath.GetFileName(false);
if (!Dir.IsEmpty())
{
if (mResources[iRes]->Name() == rkName)
return mResources[iRes];
CVirtualDirectory *pDir = FindChildDirectory(Dir, false);
if (pDir) return pDir->FindChildResource(Name);
}
else
{
for (u32 iRes = 0; iRes < mResources.size(); iRes++)
{
if (mResources[iRes]->Name() == Name)
return mResources[iRes];
}
}
return nullptr;

View File

@ -25,7 +25,7 @@ public:
TWideString FullPath() const;
CVirtualDirectory* GetRoot();
CVirtualDirectory* FindChildDirectory(const TWideString& rkName, bool AllowCreate);
CResourceEntry* FindChildResource(const TWideString& rkName) const;
CResourceEntry* FindChildResource(const TWideString& rkPath);
void AddChild(const TWideString& rkPath, CResourceEntry *pEntry);
bool RemoveChildDirectory(CVirtualDirectory *pSubdir);
bool RemoveChildResource(CResourceEntry *pEntry);

View File

@ -480,7 +480,7 @@ void CDrawUtil::InitLine()
void CDrawUtil::InitCube()
{
Log::Write("Creating cube");
mpCubeModel = gpResourceStore->LoadResource("../resources/Cube.cmdl");
mpCubeModel = gpEditorStore->LoadResource("Cube.cmdl");
}
void CDrawUtil::InitWireCube()
@ -518,14 +518,14 @@ void CDrawUtil::InitWireCube()
void CDrawUtil::InitSphere()
{
Log::Write("Creating sphere");
mpSphereModel = gpResourceStore->LoadResource("../resources/Sphere.cmdl");
mpDoubleSidedSphereModel = gpResourceStore->LoadResource("../resources/SphereDoubleSided.cmdl");
mpSphereModel = gpEditorStore->LoadResource("Sphere.cmdl");
mpDoubleSidedSphereModel = gpEditorStore->LoadResource("SphereDoubleSided.cmdl");
}
void CDrawUtil::InitWireSphere()
{
Log::Write("Creating wire sphere");
mpWireSphereModel = gpResourceStore->LoadResource("../resources/WireSphere.cmdl");
mpWireSphereModel = gpEditorStore->LoadResource("WireSphere.cmdl");
}
void CDrawUtil::InitShaders()
@ -543,17 +543,17 @@ void CDrawUtil::InitShaders()
void CDrawUtil::InitTextures()
{
Log::Write("Loading textures");
mpCheckerTexture = gpResourceStore->LoadResource("../resources/Checkerboard.txtr");
mpCheckerTexture = gpEditorStore->LoadResource("Checkerboard.txtr");
mpLightTextures[0] = gpResourceStore->LoadResource("../resources/LightAmbient.txtr");
mpLightTextures[1] = gpResourceStore->LoadResource("../resources/LightDirectional.txtr");
mpLightTextures[2] = gpResourceStore->LoadResource("../resources/LightCustom.txtr");
mpLightTextures[3] = gpResourceStore->LoadResource("../resources/LightSpot.txtr");
mpLightTextures[0] = gpEditorStore->LoadResource("LightAmbient.txtr");
mpLightTextures[1] = gpEditorStore->LoadResource("LightDirectional.txtr");
mpLightTextures[2] = gpEditorStore->LoadResource("LightCustom.txtr");
mpLightTextures[3] = gpEditorStore->LoadResource("LightSpot.txtr");
mpLightMasks[0] = gpResourceStore->LoadResource("../resources/LightAmbientMask.txtr");
mpLightMasks[1] = gpResourceStore->LoadResource("../resources/LightDirectionalMask.txtr");
mpLightMasks[2] = gpResourceStore->LoadResource("../resources/LightCustomMask.txtr");
mpLightMasks[3] = gpResourceStore->LoadResource("../resources/LightSpotMask.txtr");
mpLightMasks[0] = gpEditorStore->LoadResource("LightAmbientMask.txtr");
mpLightMasks[1] = gpEditorStore->LoadResource("LightDirectionalMask.txtr");
mpLightMasks[2] = gpEditorStore->LoadResource("LightCustomMask.txtr");
mpLightMasks[3] = gpEditorStore->LoadResource("LightSpotMask.txtr");
}
void CDrawUtil::Shutdown()

View File

@ -564,8 +564,9 @@ CScriptTemplate* CTemplateLoader::LoadScriptTemplate(XMLDocument *pDoc, const TS
// Validate file asset
else
{
TString Path = "../resources/" + ID;
if (!FileUtil::Exists(Path))
CResourceEntry *pEntry = gpEditorStore->FindEntry(ID);
if (!pEntry)
{
Log::Error(rkTemplateName + ": Invalid file for " + Type + " asset: " + ID);
pAsset = pAsset->NextSiblingElement();

View File

@ -718,7 +718,7 @@ void CUnsupportedParticleLoader::ParseIntFunction(IInputStream& rFile)
case kIntCNST:
{
u32 Value = rFile.ReadLong();
ASSERT(gpResourceStore->FindEntry(Value) == nullptr);
ASSERT(gpResourceStore->FindEntry(CAssetID(Value)) == nullptr);
break;
}

View File

@ -164,10 +164,7 @@ CResource* CScriptTemplate::FindDisplayAsset(CPropertyStruct *pProperties, u32&
// File
if (it->AssetSource == SEditorAsset::eFile)
{
TString Path = "../resources/" + it->AssetLocation;
pRes = gpResourceStore->LoadResource(Path);
}
pRes = gpEditorStore->LoadResource(it->AssetLocation);
// Property
else
@ -214,10 +211,7 @@ CCollisionMeshGroup* CScriptTemplate::FindCollision(CPropertyStruct *pProperties
// File
if (it->AssetSource == SEditorAsset::eFile)
{
TString path = "../resources/" + it->AssetLocation;
pRes = gpResourceStore->LoadResource(path);
}
pRes = gpResourceStore->LoadResource(it->AssetLocation);
// Property
else

View File

@ -258,7 +258,7 @@ void CSceneNode::DrawBoundingBox() const
void CSceneNode::DrawRotationArrow() const
{
static TResPtr<CModel> spArrowModel = gpResourceStore->LoadResource("../resources/RotationArrow.cmdl");
static TResPtr<CModel> spArrowModel = gpEditorStore->LoadResource("RotationArrow.cmdl");
spArrowModel->Draw(eNoRenderOptions, 0);
}

View File

@ -535,15 +535,15 @@ void CScriptNode::UpdatePreviewVolume()
{
case eAxisAlignedBoxShape:
case eBoxShape:
pVolumeModel = gpResourceStore->LoadResource("../resources/VolumeBox.cmdl");
pVolumeModel = gpEditorStore->LoadResource("VolumeBox.cmdl");
break;
case eEllipsoidShape:
pVolumeModel = gpResourceStore->LoadResource("../resources/VolumeSphere.cmdl");
pVolumeModel = gpEditorStore->LoadResource("VolumeSphere.cmdl");
break;
case eCylinderShape:
pVolumeModel = gpResourceStore->LoadResource("../resources/VolumeCylinder.cmdl");
pVolumeModel = gpEditorStore->LoadResource("VolumeCylinder.cmdl");
break;
}

View File

@ -1,6 +1,7 @@
#include "CEditorApplication.h"
#include "IEditor.h"
#include "CBasicViewport.h"
#include <Common/AssertMacro.h>
#include <Common/CTimer.h>
CEditorApplication::CEditorApplication(int& rArgc, char **ppArgv)
@ -12,6 +13,12 @@ CEditorApplication::CEditorApplication(int& rArgc, char **ppArgv)
mRefreshTimer.start(8);
}
void CEditorApplication::AddEditor(IEditor *pEditor)
{
mEditorWindows << pEditor;
connect(pEditor, SIGNAL(Closed()), this, SLOT(OnEditorClose()));
}
void CEditorApplication::TickEditors()
{
double LastUpdate = mLastUpdate;
@ -34,3 +41,12 @@ void CEditorApplication::TickEditors()
}
}
}
void CEditorApplication::OnEditorClose()
{
IEditor *pEditor = qobject_cast<IEditor*>(sender());
ASSERT(pEditor);
mEditorWindows.removeOne(pEditor);
delete pEditor;
}

View File

@ -20,12 +20,9 @@ public:
CEditorApplication(int& rArgc, char **ppArgv);
public slots:
void AddEditor(IEditor *pEditor);
void TickEditors();
// Accessors
public:
inline void AddEditor(IEditor *pEditor) { mEditorWindows << pEditor; }
inline void RemoveEditor(IEditor *pEditor) { mEditorWindows.removeOne(pEditor); }
void OnEditorClose();
};
#define gpEdApp static_cast<CEditorApplication*>(qApp)

View File

@ -543,32 +543,32 @@ void CGizmo::LoadModels()
{
Log::Write("Loading transform gizmo models");
smTranslateModels[CGIZMO_TRANSLATE_X] = SModelPart(eX, true, false, gpResourceStore->LoadResource("../resources/editor/TranslateX.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_Y] = SModelPart(eY, true, false, gpResourceStore->LoadResource("../resources/editor/TranslateY.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_Z] = SModelPart(eZ, true, false, gpResourceStore->LoadResource("../resources/editor/TranslateZ.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_LINES_XY] = SModelPart(eXY, true, false, gpResourceStore->LoadResource("../resources/editor/TranslateLinesXY.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_LINES_XZ] = SModelPart(eXZ, true, false, gpResourceStore->LoadResource("../resources/editor/TranslateLinesXZ.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_LINES_YZ] = SModelPart(eYZ, true, false, gpResourceStore->LoadResource("../resources/editor/TranslateLinesYZ.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_POLY_XY] = SModelPart(eXY, false, false, gpResourceStore->LoadResource("../resources/editor/TranslatePolyXY.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_POLY_XZ] = SModelPart(eXZ, false, false, gpResourceStore->LoadResource("../resources/editor/TranslatePolyXZ.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_POLY_YZ] = SModelPart(eYZ, false, false, gpResourceStore->LoadResource("../resources/editor/TranslatePolyYZ.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_X] = SModelPart(eX, true, false, gpEditorStore->LoadResource("editor\\TranslateX.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_Y] = SModelPart(eY, true, false, gpEditorStore->LoadResource("editor\\TranslateY.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_Z] = SModelPart(eZ, true, false, gpEditorStore->LoadResource("editor\\TranslateZ.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_LINES_XY] = SModelPart(eXY, true, false, gpEditorStore->LoadResource("editor\\TranslateLinesXY.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_LINES_XZ] = SModelPart(eXZ, true, false, gpEditorStore->LoadResource("editor\\TranslateLinesXZ.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_LINES_YZ] = SModelPart(eYZ, true, false, gpEditorStore->LoadResource("editor\\TranslateLinesYZ.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_POLY_XY] = SModelPart(eXY, false, false, gpEditorStore->LoadResource("editor\\TranslatePolyXY.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_POLY_XZ] = SModelPart(eXZ, false, false, gpEditorStore->LoadResource("editor\\TranslatePolyXZ.CMDL"));
smTranslateModels[CGIZMO_TRANSLATE_POLY_YZ] = SModelPart(eYZ, false, false, gpEditorStore->LoadResource("editor\\TranslatePolyYZ.CMDL"));
smRotateModels[CGIZMO_ROTATE_OUTLINE] = SModelPart(eNone, true, true, gpResourceStore->LoadResource("../resources/editor/RotateClipOutline.CMDL"));
smRotateModels[CGIZMO_ROTATE_X] = SModelPart(eX, true, false, gpResourceStore->LoadResource("../resources/editor/RotateX.CMDL"));
smRotateModels[CGIZMO_ROTATE_Y] = SModelPart(eY, true, false, gpResourceStore->LoadResource("../resources/editor/RotateY.CMDL"));
smRotateModels[CGIZMO_ROTATE_Z] = SModelPart(eZ, true, false, gpResourceStore->LoadResource("../resources/editor/RotateZ.CMDL"));
smRotateModels[CGIZMO_ROTATE_XYZ] = SModelPart(eXYZ, false, false, gpResourceStore->LoadResource("../resources/editor/RotateXYZ.CMDL"));
smRotateModels[CGIZMO_ROTATE_OUTLINE] = SModelPart(eNone, true, true, gpEditorStore->LoadResource("editor\\RotateClipOutline.CMDL"));
smRotateModels[CGIZMO_ROTATE_X] = SModelPart(eX, true, false, gpEditorStore->LoadResource("editor\\RotateX.CMDL"));
smRotateModels[CGIZMO_ROTATE_Y] = SModelPart(eY, true, false, gpEditorStore->LoadResource("editor\\RotateY.CMDL"));
smRotateModels[CGIZMO_ROTATE_Z] = SModelPart(eZ, true, false, gpEditorStore->LoadResource("editor\\RotateZ.CMDL"));
smRotateModels[CGIZMO_ROTATE_XYZ] = SModelPart(eXYZ, false, false, gpEditorStore->LoadResource("editor\\RotateXYZ.CMDL"));
smScaleModels[CGIZMO_SCALE_X] = SModelPart(eX, true, false, gpResourceStore->LoadResource("../resources/editor/ScaleX.CMDL"));
smScaleModels[CGIZMO_SCALE_Y] = SModelPart(eY, true, false, gpResourceStore->LoadResource("../resources/editor/ScaleY.CMDL"));
smScaleModels[CGIZMO_SCALE_Z] = SModelPart(eZ, true, false, gpResourceStore->LoadResource("../resources/editor/ScaleZ.CMDL"));
smScaleModels[CGIZMO_SCALE_LINES_XY] = SModelPart(eXY, true, false, gpResourceStore->LoadResource("../resources/editor/ScaleLinesXY.CMDL"));
smScaleModels[CGIZMO_SCALE_LINES_XZ] = SModelPart(eXZ, true, false, gpResourceStore->LoadResource("../resources/editor/ScaleLinesXZ.CMDL"));
smScaleModels[CGIZMO_SCALE_LINES_YZ] = SModelPart(eYZ, true, false, gpResourceStore->LoadResource("../resources/editor/ScaleLinesYZ.CMDL"));
smScaleModels[CGIZMO_SCALE_POLY_XY] = SModelPart(eXY, true, false, gpResourceStore->LoadResource("../resources/editor/ScalePolyXY.CMDL"));
smScaleModels[CGIZMO_SCALE_POLY_XZ] = SModelPart(eXZ, true, false, gpResourceStore->LoadResource("../resources/editor/ScalePolyXZ.CMDL"));
smScaleModels[CGIZMO_SCALE_POLY_YZ] = SModelPart(eYZ, true, false, gpResourceStore->LoadResource("../resources/editor/ScalePolyYZ.CMDL"));
smScaleModels[CGIZMO_SCALE_XYZ] = SModelPart(eXYZ, true, false, gpResourceStore->LoadResource("../resources/editor/ScaleXYZ.CMDL"));
smScaleModels[CGIZMO_SCALE_X] = SModelPart(eX, true, false, gpEditorStore->LoadResource("editor\\ScaleX.CMDL"));
smScaleModels[CGIZMO_SCALE_Y] = SModelPart(eY, true, false, gpEditorStore->LoadResource("editor\\ScaleY.CMDL"));
smScaleModels[CGIZMO_SCALE_Z] = SModelPart(eZ, true, false, gpEditorStore->LoadResource("editor\\ScaleZ.CMDL"));
smScaleModels[CGIZMO_SCALE_LINES_XY] = SModelPart(eXY, true, false, gpEditorStore->LoadResource("editor\\ScaleLinesXY.CMDL"));
smScaleModels[CGIZMO_SCALE_LINES_XZ] = SModelPart(eXZ, true, false, gpEditorStore->LoadResource("editor\\ScaleLinesXZ.CMDL"));
smScaleModels[CGIZMO_SCALE_LINES_YZ] = SModelPart(eYZ, true, false, gpEditorStore->LoadResource("editor\\ScaleLinesYZ.CMDL"));
smScaleModels[CGIZMO_SCALE_POLY_XY] = SModelPart(eXY, true, false, gpEditorStore->LoadResource("editor\\ScalePolyXY.CMDL"));
smScaleModels[CGIZMO_SCALE_POLY_XZ] = SModelPart(eXZ, true, false, gpEditorStore->LoadResource("editor\\ScalePolyXZ.CMDL"));
smScaleModels[CGIZMO_SCALE_POLY_YZ] = SModelPart(eYZ, true, false, gpEditorStore->LoadResource("editor\\ScalePolyYZ.CMDL"));
smScaleModels[CGIZMO_SCALE_XYZ] = SModelPart(eXYZ, true, false, gpEditorStore->LoadResource("editor\\ScaleXYZ.CMDL"));
smModelsLoaded = true;
}

View File

@ -6,6 +6,8 @@
class IEditor : public QMainWindow
{
Q_OBJECT
public:
IEditor(QWidget *pParent)
: QMainWindow(pParent)
@ -13,8 +15,12 @@ public:
gpEdApp->AddEditor(this);
}
virtual void closeEvent(QCloseEvent*) { emit Closed(); }
virtual void EditorTick(float /*DeltaTime*/) { }
virtual CBasicViewport* Viewport() const { return nullptr; }
virtual CBasicViewport* Viewport() const { return nullptr; }
signals:
void Closed();
};
#endif // IEDITOR

View File

@ -887,11 +887,6 @@ void CModelEditorWindow::ToggleGrid(bool Enabled)
ui->Viewport->SetGridEnabled(Enabled);
}
void CModelEditorWindow::closeEvent(QCloseEvent*)
{
emit Closed();
}
CModelEditorViewport* CModelEditorWindow::Viewport() const
{
return ui->Viewport;

View File

@ -34,7 +34,6 @@ public:
explicit CModelEditorWindow(QWidget *pParent = 0);
~CModelEditorWindow();
void SetActiveModel(CModel *pModel);
void closeEvent(QCloseEvent *pEvent);
CModelEditorViewport* Viewport() const;
public slots:

View File

@ -7,6 +7,7 @@
CResourceBrowser::CResourceBrowser(QWidget *pParent)
: QDialog(pParent)
, mpUI(new Ui::CResourceBrowser)
, mpStore(gpResourceStore)
{
mpUI->setupUi(this);
setWindowFlags(windowFlags() | Qt::WindowMinimizeButtonHint);
@ -25,11 +26,12 @@ CResourceBrowser::CResourceBrowser(QWidget *pParent)
// Set up directory tree model
mpDirectoryModel = new CVirtualDirectoryModel(this);
mpDirectoryModel->SetRoot(gpResourceStore->RootDirectory());
mpDirectoryModel->SetRoot(gpResourceStore ? gpResourceStore->RootDirectory() : nullptr);
mpUI->DirectoryTreeView->setModel(mpDirectoryModel);
mpUI->DirectoryTreeView->expand(mpDirectoryModel->index(0, 0, QModelIndex()));
// Set up connections
connect(mpUI->StoreComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnStoreChanged(int)));
connect(mpUI->SearchBar, SIGNAL(textChanged(QString)), this, SLOT(OnSearchStringChanged()));
connect(mpUI->SortComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSortModeChanged(int)));
connect(mpUI->DirectoryTreeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(OnDirectorySelectionChanged(QModelIndex,QModelIndex)));
@ -43,7 +45,19 @@ CResourceBrowser::~CResourceBrowser()
void CResourceBrowser::RefreshResources()
{
mpModel->FillEntryList(gpResourceStore);
mpModel->FillEntryList(mpStore);
}
void CResourceBrowser::OnStoreChanged(int Index)
{
mpStore = (Index == 0 ? gpResourceStore : gpEditorStore);
RefreshResources();
mpDirectoryModel->SetRoot(mpStore ? mpStore->RootDirectory() : nullptr);
QModelIndex RootIndex = mpDirectoryModel->index(0, 0, QModelIndex());
mpUI->DirectoryTreeView->expand(RootIndex);
mpUI->DirectoryTreeView->clearSelection();
OnDirectorySelectionChanged(QModelIndex(), QModelIndex());
}
void CResourceBrowser::OnSortModeChanged(int Index)

View File

@ -14,6 +14,7 @@ class CResourceBrowser : public QDialog
{
Q_OBJECT
Ui::CResourceBrowser *mpUI;
CResourceStore *mpStore;
CResourceTableModel *mpModel;
CResourceProxyModel *mpProxyModel;
CVirtualDirectoryModel *mpDirectoryModel;
@ -24,6 +25,7 @@ public:
void RefreshResources();
public slots:
void OnStoreChanged(int Index);
void OnSortModeChanged(int Index);
void OnSearchStringChanged();
void OnDirectorySelectionChanged(const QModelIndex& rkNewIndex, const QModelIndex& rkPrevIndex);

View File

@ -37,6 +37,37 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="StoreLabel">
<property name="text">
<string>Store:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="StoreComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Project</string>
</property>
</item>
<item>
<property name="text">
<string>Editor</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLineEdit" name="SearchBar">
<property name="sizePolicy">

View File

@ -65,32 +65,35 @@ public:
beginResetModel();
mEntries.clear();
for (CResourceIterator It(pStore); It; ++It)
if (pStore)
{
if (It->IsTransient()) continue;
EResType Type = It->ResourceType();
switch (Type)
for (CResourceIterator It(pStore); It; ++It)
{
case eArea:
case eAreaCollision:
case eAreaLights:
case eAreaMaterials:
case eAreaSurfaceBounds:
case eAreaOctree:
case eAreaVisibilityTree:
case eMapArea:
case eMapWorld:
case ePathfinding:
case ePortalArea:
case eSaveArea:
case eSaveWorld:
case eStaticGeometryMap:
case eTweak:
case eWorld:
continue;
default:
mEntries << *It;
if (It->IsTransient()) continue;
EResType Type = It->ResourceType();
switch (Type)
{
case eArea:
case eAreaCollision:
case eAreaLights:
case eAreaMaterials:
case eAreaSurfaceBounds:
case eAreaOctree:
case eAreaVisibilityTree:
case eMapArea:
case eMapWorld:
case ePathfinding:
case ePortalArea:
case eSaveArea:
case eSaveWorld:
case eStaticGeometryMap:
case eTweak:
case eWorld:
continue;
default:
mEntries << *It;
}
}
}

View File

@ -161,7 +161,7 @@ void CWorldEditor::closeEvent(QCloseEvent *pEvent)
if (mpPoiDialog)
mpPoiDialog->close();
emit Closed();
IEditor::closeEvent(pEvent);
}
else
{

View File

@ -135,7 +135,6 @@ private slots:
void EditPoiToWorldMap();
signals:
void Closed();
void LayersModified();
void InstancesLayerAboutToChange();
void InstancesLayerChanged(const QList<CScriptNode*>& rkInstanceList);

View File

@ -32,6 +32,10 @@ int main(int argc, char *argv[])
if (!Initialized) QMessageBox::warning(0, "Error", "Couldn't open log file. Logging will not work for this session.");
qInstallMessageHandler(QtLogRedirect);
// Create editor resource store
gpEditorStore = new CResourceStore(L"../resources/EditorResourceDB.rdb");
gpEditorStore->LoadResourceDatabase();
// Load templates
CTemplateLoader::LoadGameList();