From a7b381f301a1c81e8d6419d834fee069a43262f6 Mon Sep 17 00:00:00 2001 From: parax0 Date: Wed, 31 Aug 2016 02:09:13 -0600 Subject: [PATCH] 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 --- resources/EditorResourceDB.rdb | 505 ++++++++++++++++++ resources/ResourceCacheData.rcd | Bin 0 -> 2008 bytes resources/VolumeBox.cmdl | Bin 1024 -> 1024 bytes ...{54475458.txtr => VolumeCheckerboard.txtr} | Bin resources/VolumeCylinder.cmdl | Bin 7296 -> 7296 bytes resources/VolumeSphere.cmdl | Bin 120544 -> 120544 bytes src/Core/GameProject/CGameExporter.cpp | 29 +- src/Core/GameProject/CGameExporter.h | 2 +- src/Core/GameProject/CGameProject.cpp | 7 +- src/Core/GameProject/CGameProject.h | 10 +- src/Core/GameProject/CResourceEntry.cpp | 28 +- src/Core/GameProject/CResourceEntry.h | 3 +- src/Core/GameProject/CResourceStore.cpp | 138 +++-- src/Core/GameProject/CResourceStore.h | 37 +- src/Core/GameProject/CVirtualDirectory.cpp | 20 +- src/Core/GameProject/CVirtualDirectory.h | 2 +- src/Core/Render/CDrawUtil.cpp | 26 +- src/Core/Resource/Factory/CTemplateLoader.cpp | 5 +- .../Factory/CUnsupportedParticleLoader.cpp | 2 +- src/Core/Resource/Script/CScriptTemplate.cpp | 10 +- src/Core/Scene/CSceneNode.cpp | 2 +- src/Core/Scene/CScriptNode.cpp | 6 +- src/Editor/CEditorApplication.cpp | 16 + src/Editor/CEditorApplication.h | 7 +- src/Editor/CGizmo.cpp | 48 +- src/Editor/IEditor.h | 8 +- src/Editor/ModelEditor/CModelEditorWindow.cpp | 5 - src/Editor/ModelEditor/CModelEditorWindow.h | 1 - .../ResourceBrowser/CResourceBrowser.cpp | 18 +- src/Editor/ResourceBrowser/CResourceBrowser.h | 2 + .../ResourceBrowser/CResourceBrowser.ui | 31 ++ .../ResourceBrowser/CResourceTableModel.h | 51 +- src/Editor/WorldEditor/CWorldEditor.cpp | 2 +- src/Editor/WorldEditor/CWorldEditor.h | 1 - src/Editor/main.cpp | 4 + 35 files changed, 848 insertions(+), 178 deletions(-) create mode 100644 resources/EditorResourceDB.rdb create mode 100644 resources/ResourceCacheData.rcd rename resources/{54475458.txtr => VolumeCheckerboard.txtr} (100%) diff --git a/resources/EditorResourceDB.rdb b/resources/EditorResourceDB.rdb new file mode 100644 index 00000000..171ebb1c --- /dev/null +++ b/resources/EditorResourceDB.rdb @@ -0,0 +1,505 @@ + + + + + + + 08F992A8 + TXTR + script\common\ + RandomRelay + + + 0A11104B + CMDL + editor\ + TranslateX + + + 0E04ED00 + TXTR + + LightAmbientMask + + + 0EDB1C7A + CMDL + script\dkcr\ + Waypoint + + + 0FB28A24 + TXTR + + LightAmbient + + + 0FD29E3B + CMDL + script\common\ + Waypoint + + + 115C21DD + TXTR + script\common\ + CameraFilterKeyframe + + + 1C010ADC + CMDL + editor\ + TranslatePolyXY + + + 1FFC7E43 + CMDL + editor\ + RotateXYZ + + + 2A14558D + TXTR + script\common\ + HUDMemo + + + 2B75E193 + TXTR + script\common\ + VisorFlare + + + 31485556 + TXTR + script\mp2\ + AdvancedCounter + + + 31992094 + CMDL + editor\ + TranslateY + + + 32432719 + CMDL + script\common\ + SpiderBallWaypoint + + + 32C9F9D1 + TXTR + script\common\ + StreamedAudio + + + 3440526F + CMDL + editor\ + TranslateLinesXY + + + 3A947189 + CMDL + script\common\ + AIWaypoint + + + 3C093300 + CMDL + editor\ + ScaleXYZ + + + 40969072 + TXTR + script\common\ + AreaAttributes + + + 43891B25 + CMDL + editor\ + TranslatePolyXZ + + + 43E9B0A9 + CMDL + editor\ + ScaleX + + + 4443279C + TXTR + script\common\ + CameraBlurKeyframe + + + 4A2D76D1 + TXTR + script\common\ + DamageableTrigger + + + 4C3D3E7F + TXTR + script\common\ + GrapplePoint + + + 4E133EF2 + TXTR + script\common\ + SpiderBallAttractionSurface + + + 57F8715F + TXTR + script\common\ + Dock + + + 592130DD + CMDL + editor\ + TranslateZ + + + 5BC862B8 + CMDL + editor\ + TranslateLinesXZ + + + 5D08CCF6 + TXTR + script\mp3\ + WeaponGenerator + + + 5F3B141B + CMDL + + VolumeBox + + + 61B511E5 + TXTR + + Checkerboard + + + 6649251D + CMDL + script\common\ + Camera + + + 6A17B38F + TXTR + script\common\ + Sound + + + 6B1FABDD + CMDL + + Cube + + + 6B71C0F2 + CMDL + editor\ + ScaleY + + + 6C6CE7FE + TXTR + + LightSpotMask + + + 6D5BC167 + TXTR + script\common\ + Effect + + + 6DD88D5D + CMDL + + RotationArrow + + + 6E57F7E0 + CMDL + + VolumeCylinder + + + 72978DCF + TXTR + script\common\ + Relay + + + 791A7BFD + CMDL + + SphereDoubleSided + + + 7F494724 + CMDL + editor\ + RotateX + + + 81326A53 + CMDL + editor\ + ScaleLinesYZ + + + 825CDFA8 + CMDL + editor\ + ScalePolyYZ + + + 826C9800 + TXTR + script\common\ + ColorModulate + + + 85CE16D7 + TXTR + script\common\ + StreamedMovie + + + 875A6FD7 + TXTR + script\common\ + PointOfInterest + + + 9039791A + TXTR + + LightDirectional + + + 91437414 + CMDL + script\common\ + CameraWaypoint + + + 92F9D13B + CMDL + editor\ + ScaleZ + + + 95261BB8 + CMDL + + WireSphere + + + 968C405E + TXTR + script\common\ + SoundModifier + + + 9FF04AA1 + TXTR + script\common\ + Generator + + + A6D1576D + CMDL + editor\ + RotateY + + + A82A3F02 + TXTR + + LightSpot + + + AC18950A + TXTR + script\common\ + RadialDamage + + + B0D52FF7 + TXTR + + LightCustomMask + + + B0E09096 + TXTR + + LightDirectionalMask + + + B23F1022 + TXTR + script\common\ + VisorGoo + + + B2DBCAED + TXTR + script\common\ + PickupGenerator + + + B3050E38 + TXTR + script\common\ + SequenceTimer + + + B97DB26B + TXTR + script\common\ + Timer + + + BA7EA4F6 + TXTR + script\common\ + Trigger + + + C0FBED3D + CMDL + editor\ + ScaleLinesXY + + + C2266292 + CMDL + editor\ + ScalePolyXY + + + C4E83425 + TXTR + script\common\ + DistanceFog + + + C7BEFE29 + CMDL + + VolumeSphere + + + CB904B3D + TXTR + script\common\ + SpecialFunction + + + CE5967B6 + CMDL + editor\ + RotateZ + + + D2F07DAF + TXTR + script\common\ + ConditionalRelay + + + D7B6A50D + CMDL + + Sphere + + + DA185196 + TXTR + + VolumeCheckerboard + + + DC3787F2 + CMDL + editor\ + TranslatePolyYZ + + + E1A0D860 + TXTR + script\common\ + StreamedAudioModifier + + + E883FD86 + CMDL + editor\ + ScaleLinesXZ + + + E9AE72DB + CMDL + editor\ + ScalePolyXZ + + + EE340FC4 + TXTR + script\common\ + MemoryRelay + + + F476CF85 + CMDL + editor\ + TranslateLinesYZ + + + F76B369A + TXTR + script\common\ + Counter + + + FB50DA78 + CMDL + editor\ + RotateClipOutline + + + FC8FA98B + TXTR + + LightCustom + + + FD78FBC8 + TXTR + script\mp1\ + NewCameraShaker + + + FFAC2525 + TXTR + script\common\ + CameraShaker + + + diff --git a/resources/ResourceCacheData.rcd b/resources/ResourceCacheData.rcd new file mode 100644 index 0000000000000000000000000000000000000000..b73cedc7c01decb00a04470b78dc7717d2430420 GIT binary patch literal 2008 zcmY+^Sx8k;7{&2b6qt|$NtqgEq>>S(Ns~FmO>)RE&BW9!9}*lAr9=yr3==ESOl=?< zph8JXl%#qH3!xE3Arv*zhe#g`iO9sEuH1#LeP0g0KOdWO&pCTr_E{oe{l&z_#aJ)# zc2l*D)~nNeI}#TjPQ%{WDOx)Xhh^jQqYLvi90onk8Qo?$wqD+-orYuY-5{ge4CfTD zui9yNEU_QbPQ!Di#G;*spG!iOb{d<{j$GGH!#^V7sCF9ux7ODg-DU(>eAjBH5%6KE z$LKaAFf1-tJB>Ycd6n8}>|L?lniroljj)EAeC;$WmG0i!X;{Wunv8BU_FH`KXr~di zrNFp<8V7?zN_C#bp;aNjw9`oZo0q1YMv~Vy}o&94@*P)S<{3b&?jhz0fRHNIB z(}|PA+G*t9sOr{EqsZ<2taciukq3-@N8>_3X1vbRC`b~_>Vb9|k9!hx zw9{zx3tg(6Mzd?Zy>=QcU$#zar_nN8(_nO)(HiQsK|77s!H@F?>%zH8qiwmvF6}g4 z7Pn?;r}3)fp|M|RbWD#2>pYFOKIygEX>^VT8s`a(cdzF*={${3HPOcUG`f;9+I5~r z??mx4?KJw@AFb3*W5D&W@jPh^?W{2NBaM;!{U>xC8lx9yFKMSS_B4M`JB^=#j-A?R r{4VG&*G^+HYsYQvG^S$*3boUiscyQWoyKh8^n2|z{xy3W?}f&H9J#BS literal 0 HcmV?d00001 diff --git a/resources/VolumeBox.cmdl b/resources/VolumeBox.cmdl index 626e34dbdc33954a9295521329acbca669b7b639..13ec966940154f6d4ea218b73b26fc6acebedcc8 100644 GIT binary patch delta 15 WcmZqRXyBNT!g5O@aN5R<8O#7GmIamo delta 15 WcmZqRXyBNT!V=;h60tF31~ULAivDiscDir(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 diff --git a/src/Core/GameProject/CGameExporter.h b/src/Core/GameProject/CGameExporter.h index 2c1ab0e9..5317b40e 100644 --- a/src/Core/GameProject/CGameExporter.h +++ b/src/Core/GameProject/CGameExporter.h @@ -13,7 +13,7 @@ class CGameExporter { // Project CGameProject *mpProject; - CResourceStore mStore; + CResourceStore *mpStore; // Directories TWideString mGameDir; diff --git a/src/Core/GameProject/CGameProject.cpp b/src/Core/GameProject/CGameProject.cpp index 5d640bb4..2a922f6b 100644 --- a/src/Core/GameProject/CGameProject.cpp +++ b/src/Core/GameProject/CGameProject.cpp @@ -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; } } diff --git a/src/Core/GameProject/CGameProject.h b/src/Core/GameProject/CGameProject.h index 18ee2f3b..21e35028 100644 --- a/src/Core/GameProject/CGameProject.h +++ b/src/Core/GameProject/CGameProject.h @@ -16,6 +16,7 @@ class CGameProject TWideString mProjectRoot; TWideString mResourceDBPath; std::vector 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; } diff --git a/src/Core/GameProject/CResourceEntry.cpp b/src/Core/GameProject/CResourceEntry.cpp index 0a6c8564..05911c21 100644 --- a/src/Core/GameProject/CResourceEntry.cpp +++ b/src/Core/GameProject/CResourceEntry.cpp @@ -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; } diff --git a/src/Core/GameProject/CResourceEntry.h b/src/Core/GameProject/CResourceEntry.h index ccfb28b1..1cd3446d 100644 --- a/src/Core/GameProject/CResourceEntry.h +++ b/src/Core/GameProject/CResourceEntry.h @@ -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; } diff --git a/src/Core/GameProject/CResourceStore.cpp b/src/Core/GameProject/CResourceStore.cpp index a36f95cb..90edc35b 100644 --- a/src/Core/GameProject/CResourceStore.cpp +++ b/src/Core/GameProject/CResourceStore.cpp @@ -11,23 +11,40 @@ #include 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; } diff --git a/src/Core/GameProject/CResourceStore.h b/src/Core/GameProject/CResourceStore.h index c3e62042..0a11684e 100644 --- a/src/Core/GameProject/CResourceStore.h +++ b/src/Core/GameProject/CResourceStore.h @@ -5,6 +5,7 @@ #include "Core/Resource/EResType.h" #include #include +#include #include #include #include @@ -19,12 +20,17 @@ class CResourceStore friend class CResourceIterator; CGameProject *mpProj; - CVirtualDirectory *mpProjectRoot; + EGame mGame; + CVirtualDirectory *mpDatabaseRoot; std::vector mTransientRoots; std::map mResourceEntries; std::map 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 diff --git a/src/Core/GameProject/CVirtualDirectory.cpp b/src/Core/GameProject/CVirtualDirectory.cpp index f98f76b3..c685bc62 100644 --- a/src/Core/GameProject/CVirtualDirectory.cpp +++ b/src/Core/GameProject/CVirtualDirectory.cpp @@ -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; diff --git a/src/Core/GameProject/CVirtualDirectory.h b/src/Core/GameProject/CVirtualDirectory.h index 90ea5b21..2700ae34 100644 --- a/src/Core/GameProject/CVirtualDirectory.h +++ b/src/Core/GameProject/CVirtualDirectory.h @@ -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); diff --git a/src/Core/Render/CDrawUtil.cpp b/src/Core/Render/CDrawUtil.cpp index 05b45dc9..2f97d64f 100644 --- a/src/Core/Render/CDrawUtil.cpp +++ b/src/Core/Render/CDrawUtil.cpp @@ -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() diff --git a/src/Core/Resource/Factory/CTemplateLoader.cpp b/src/Core/Resource/Factory/CTemplateLoader.cpp index 1e0eb25f..90108a37 100644 --- a/src/Core/Resource/Factory/CTemplateLoader.cpp +++ b/src/Core/Resource/Factory/CTemplateLoader.cpp @@ -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(); diff --git a/src/Core/Resource/Factory/CUnsupportedParticleLoader.cpp b/src/Core/Resource/Factory/CUnsupportedParticleLoader.cpp index 0de09d2e..7756b979 100644 --- a/src/Core/Resource/Factory/CUnsupportedParticleLoader.cpp +++ b/src/Core/Resource/Factory/CUnsupportedParticleLoader.cpp @@ -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; } diff --git a/src/Core/Resource/Script/CScriptTemplate.cpp b/src/Core/Resource/Script/CScriptTemplate.cpp index 3ae06b90..ddee15f9 100644 --- a/src/Core/Resource/Script/CScriptTemplate.cpp +++ b/src/Core/Resource/Script/CScriptTemplate.cpp @@ -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 diff --git a/src/Core/Scene/CSceneNode.cpp b/src/Core/Scene/CSceneNode.cpp index 101e2870..f3dd985a 100644 --- a/src/Core/Scene/CSceneNode.cpp +++ b/src/Core/Scene/CSceneNode.cpp @@ -258,7 +258,7 @@ void CSceneNode::DrawBoundingBox() const void CSceneNode::DrawRotationArrow() const { - static TResPtr spArrowModel = gpResourceStore->LoadResource("../resources/RotationArrow.cmdl"); + static TResPtr spArrowModel = gpEditorStore->LoadResource("RotationArrow.cmdl"); spArrowModel->Draw(eNoRenderOptions, 0); } diff --git a/src/Core/Scene/CScriptNode.cpp b/src/Core/Scene/CScriptNode.cpp index 6ed2147b..d26e0e51 100644 --- a/src/Core/Scene/CScriptNode.cpp +++ b/src/Core/Scene/CScriptNode.cpp @@ -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; } diff --git a/src/Editor/CEditorApplication.cpp b/src/Editor/CEditorApplication.cpp index 75b677e7..73902c01 100644 --- a/src/Editor/CEditorApplication.cpp +++ b/src/Editor/CEditorApplication.cpp @@ -1,6 +1,7 @@ #include "CEditorApplication.h" #include "IEditor.h" #include "CBasicViewport.h" +#include #include 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(sender()); + ASSERT(pEditor); + + mEditorWindows.removeOne(pEditor); + delete pEditor; +} diff --git a/src/Editor/CEditorApplication.h b/src/Editor/CEditorApplication.h index 525bf022..d7b8fce5 100644 --- a/src/Editor/CEditorApplication.h +++ b/src/Editor/CEditorApplication.h @@ -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(qApp) diff --git a/src/Editor/CGizmo.cpp b/src/Editor/CGizmo.cpp index f50983a9..e4773aaa 100644 --- a/src/Editor/CGizmo.cpp +++ b/src/Editor/CGizmo.cpp @@ -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; } diff --git a/src/Editor/IEditor.h b/src/Editor/IEditor.h index b54e3581..a9dc1ce4 100644 --- a/src/Editor/IEditor.h +++ b/src/Editor/IEditor.h @@ -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 diff --git a/src/Editor/ModelEditor/CModelEditorWindow.cpp b/src/Editor/ModelEditor/CModelEditorWindow.cpp index 01c3b817..124c5c18 100644 --- a/src/Editor/ModelEditor/CModelEditorWindow.cpp +++ b/src/Editor/ModelEditor/CModelEditorWindow.cpp @@ -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; diff --git a/src/Editor/ModelEditor/CModelEditorWindow.h b/src/Editor/ModelEditor/CModelEditorWindow.h index 7bd0b842..f6ef0ff1 100644 --- a/src/Editor/ModelEditor/CModelEditorWindow.h +++ b/src/Editor/ModelEditor/CModelEditorWindow.h @@ -34,7 +34,6 @@ public: explicit CModelEditorWindow(QWidget *pParent = 0); ~CModelEditorWindow(); void SetActiveModel(CModel *pModel); - void closeEvent(QCloseEvent *pEvent); CModelEditorViewport* Viewport() const; public slots: diff --git a/src/Editor/ResourceBrowser/CResourceBrowser.cpp b/src/Editor/ResourceBrowser/CResourceBrowser.cpp index e15418c0..29d697bd 100644 --- a/src/Editor/ResourceBrowser/CResourceBrowser.cpp +++ b/src/Editor/ResourceBrowser/CResourceBrowser.cpp @@ -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) diff --git a/src/Editor/ResourceBrowser/CResourceBrowser.h b/src/Editor/ResourceBrowser/CResourceBrowser.h index c3acd5dc..7684698c 100644 --- a/src/Editor/ResourceBrowser/CResourceBrowser.h +++ b/src/Editor/ResourceBrowser/CResourceBrowser.h @@ -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); diff --git a/src/Editor/ResourceBrowser/CResourceBrowser.ui b/src/Editor/ResourceBrowser/CResourceBrowser.ui index 2a687a0f..5e0da17f 100644 --- a/src/Editor/ResourceBrowser/CResourceBrowser.ui +++ b/src/Editor/ResourceBrowser/CResourceBrowser.ui @@ -37,6 +37,37 @@ 0 + + + + + + Store: + + + + + + + + 1 + 0 + + + + + Project + + + + + Editor + + + + + + diff --git a/src/Editor/ResourceBrowser/CResourceTableModel.h b/src/Editor/ResourceBrowser/CResourceTableModel.h index 6cf637cb..18d61141 100644 --- a/src/Editor/ResourceBrowser/CResourceTableModel.h +++ b/src/Editor/ResourceBrowser/CResourceTableModel.h @@ -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; + } } } diff --git a/src/Editor/WorldEditor/CWorldEditor.cpp b/src/Editor/WorldEditor/CWorldEditor.cpp index c367bec6..39b0c6a3 100644 --- a/src/Editor/WorldEditor/CWorldEditor.cpp +++ b/src/Editor/WorldEditor/CWorldEditor.cpp @@ -161,7 +161,7 @@ void CWorldEditor::closeEvent(QCloseEvent *pEvent) if (mpPoiDialog) mpPoiDialog->close(); - emit Closed(); + IEditor::closeEvent(pEvent); } else { diff --git a/src/Editor/WorldEditor/CWorldEditor.h b/src/Editor/WorldEditor/CWorldEditor.h index 898308ec..a0265441 100644 --- a/src/Editor/WorldEditor/CWorldEditor.h +++ b/src/Editor/WorldEditor/CWorldEditor.h @@ -135,7 +135,6 @@ private slots: void EditPoiToWorldMap(); signals: - void Closed(); void LayersModified(); void InstancesLayerAboutToChange(); void InstancesLayerChanged(const QList& rkInstanceList); diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index f5621bbf..9d98af5c 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -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();