mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-07-05 12:45:55 +00:00
Improved error handling and reporting when loading/saving project files; added file lock class to prevent the same project from being opened in multiple PWE instances
This commit is contained in:
parent
6d77604667
commit
882973d9d5
@ -18,17 +18,30 @@ public:
|
|||||||
// Load XML and set current element to the root element; read version
|
// Load XML and set current element to the root element; read version
|
||||||
mDoc.LoadFile(*rkFileName);
|
mDoc.LoadFile(*rkFileName);
|
||||||
mpCurElem = mDoc.FirstChildElement();
|
mpCurElem = mDoc.FirstChildElement();
|
||||||
ASSERT(mpCurElem != nullptr);
|
|
||||||
|
|
||||||
|
if (mpCurElem != nullptr)
|
||||||
|
{
|
||||||
mArchiveVersion = (u16) TString( mpCurElem->Attribute("ArchiveVer") ).ToInt32(10);
|
mArchiveVersion = (u16) TString( mpCurElem->Attribute("ArchiveVer") ).ToInt32(10);
|
||||||
mFileVersion = (u16) TString( mpCurElem->Attribute("FileVer") ).ToInt32(10);
|
mFileVersion = (u16) TString( mpCurElem->Attribute("FileVer") ).ToInt32(10);
|
||||||
const char *pkGameAttr = mpCurElem->Attribute("Game");
|
const char *pkGameAttr = mpCurElem->Attribute("Game");
|
||||||
mGame = pkGameAttr ? GetGameForID( CFourCC(pkGameAttr) ) : eUnknownGame;
|
mGame = pkGameAttr ? GetGameForID( CFourCC(pkGameAttr) ) : eUnknownGame;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log::Error("Failed to open XML for read: " + rkFileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsValid() const
|
||||||
|
{
|
||||||
|
return mpCurElem != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Interface
|
// Interface
|
||||||
virtual bool ParamBegin(const char *pkName)
|
virtual bool ParamBegin(const char *pkName)
|
||||||
{
|
{
|
||||||
|
ASSERT(IsValid());
|
||||||
|
|
||||||
// Push new parent if needed
|
// Push new parent if needed
|
||||||
if (!mJustEndedParam)
|
if (!mJustEndedParam)
|
||||||
{
|
{
|
||||||
|
@ -11,11 +11,13 @@ class CXMLWriter : public IArchive
|
|||||||
tinyxml2::XMLDocument mDoc;
|
tinyxml2::XMLDocument mDoc;
|
||||||
TString mOutFilename;
|
TString mOutFilename;
|
||||||
tinyxml2::XMLElement *mpCurElem;
|
tinyxml2::XMLElement *mpCurElem;
|
||||||
|
bool mSaved;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CXMLWriter(const TString& rkFileName, const TString& rkRootName, u16 FileVersion, EGame Game = eUnknownGame)
|
CXMLWriter(const TString& rkFileName, const TString& rkRootName, u16 FileVersion, EGame Game = eUnknownGame)
|
||||||
: IArchive(false, true)
|
: IArchive(false, true)
|
||||||
, mOutFilename(rkFileName)
|
, mOutFilename(rkFileName)
|
||||||
|
, mSaved(false)
|
||||||
{
|
{
|
||||||
SetVersion(skCurrentArchiveVersion, FileVersion, Game);
|
SetVersion(skCurrentArchiveVersion, FileVersion, Game);
|
||||||
|
|
||||||
@ -34,12 +36,43 @@ public:
|
|||||||
|
|
||||||
~CXMLWriter()
|
~CXMLWriter()
|
||||||
{
|
{
|
||||||
mDoc.SaveFile(*mOutFilename);
|
if (!mSaved)
|
||||||
|
{
|
||||||
|
bool SaveSuccess = Save();
|
||||||
|
ASSERT(SaveSuccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Save()
|
||||||
|
{
|
||||||
|
if (mSaved)
|
||||||
|
{
|
||||||
|
Log::Error("Attempted to save XML twice!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tinyxml2::XMLError Error = mDoc.SaveFile(*mOutFilename);
|
||||||
|
mSaved = true;
|
||||||
|
|
||||||
|
if (Error != tinyxml2::XML_SUCCESS)
|
||||||
|
{
|
||||||
|
Log::Error("Failed to save XML file: " + mOutFilename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsValid() const
|
||||||
|
{
|
||||||
|
return mpCurElem != nullptr && !mSaved;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interface
|
// Interface
|
||||||
virtual bool ParamBegin(const char *pkName)
|
virtual bool ParamBegin(const char *pkName)
|
||||||
{
|
{
|
||||||
|
ASSERT(IsValid());
|
||||||
|
|
||||||
tinyxml2::XMLElement *pElem = mDoc.NewElement(pkName);
|
tinyxml2::XMLElement *pElem = mDoc.NewElement(pkName);
|
||||||
mpCurElem->LinkEndChild(pElem);
|
mpCurElem->LinkEndChild(pElem);
|
||||||
mpCurElem = pElem;
|
mpCurElem = pElem;
|
||||||
|
@ -1,15 +1,22 @@
|
|||||||
#include "CAssetNameMap.h"
|
#include "CAssetNameMap.h"
|
||||||
|
|
||||||
void CAssetNameMap::LoadAssetNames(TString Path /*= gkAssetMapPath*/)
|
bool CAssetNameMap::LoadAssetNames(TString Path /*= gkAssetMapPath*/)
|
||||||
{
|
{
|
||||||
CXMLReader Reader(Path);
|
CXMLReader Reader(Path);
|
||||||
|
|
||||||
|
if (Reader.IsValid())
|
||||||
|
{
|
||||||
Serialize(Reader);
|
Serialize(Reader);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAssetNameMap::SaveAssetNames(TString Path /*= gkAssetMapPath*/)
|
bool CAssetNameMap::SaveAssetNames(TString Path /*= gkAssetMapPath*/)
|
||||||
{
|
{
|
||||||
CXMLWriter Writer(Path, "AssetNameMap", 0, eUnknownGame);
|
CXMLWriter Writer(Path, "AssetNameMap", 0, eUnknownGame);
|
||||||
Serialize(Writer);
|
Serialize(Writer);
|
||||||
|
return Writer.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CAssetNameMap::GetNameInfo(CAssetID ID, TString& rOutDirectory, TString& rOutName)
|
bool CAssetNameMap::GetNameInfo(CAssetID ID, TString& rOutDirectory, TString& rOutName)
|
||||||
|
@ -50,8 +50,8 @@ class CAssetNameMap
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
CAssetNameMap() : mIsValid(true) {}
|
CAssetNameMap() : mIsValid(true) {}
|
||||||
void LoadAssetNames(TString Path = gkAssetMapPath);
|
bool LoadAssetNames(TString Path = gkAssetMapPath);
|
||||||
void SaveAssetNames(TString Path = gkAssetMapPath);
|
bool SaveAssetNames(TString Path = gkAssetMapPath);
|
||||||
bool GetNameInfo(CAssetID ID, TString& rOutDirectory, TString& rOutName);
|
bool GetNameInfo(CAssetID ID, TString& rOutDirectory, TString& rOutName);
|
||||||
void CopyFromStore(CResourceStore *pStore);
|
void CopyFromStore(CResourceStore *pStore);
|
||||||
|
|
||||||
|
@ -342,7 +342,8 @@ void CGameExporter::LoadPaks()
|
|||||||
// Add package to project and save
|
// Add package to project and save
|
||||||
mpProject->AddPackage(pPackage);
|
mpProject->AddPackage(pPackage);
|
||||||
#if SAVE_PACKAGE_DEFINITIONS
|
#if SAVE_PACKAGE_DEFINITIONS
|
||||||
pPackage->Save();
|
bool SaveSuccess = pPackage->Save();
|
||||||
|
ASSERT(SaveSuccess);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -461,7 +462,8 @@ void CGameExporter::ExportCookedResources()
|
|||||||
#if EXPORT_COOKED
|
#if EXPORT_COOKED
|
||||||
mpStore->SaveResourceDatabase();
|
mpStore->SaveResourceDatabase();
|
||||||
#endif
|
#endif
|
||||||
mpProject->Save();
|
bool SaveSuccess = mpProject->Save();
|
||||||
|
ASSERT(SaveSuccess);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,29 +1,35 @@
|
|||||||
#include "CGameInfo.h"
|
#include "CGameInfo.h"
|
||||||
#include <Common/FileUtil.h>
|
#include <Common/FileUtil.h>
|
||||||
|
|
||||||
void CGameInfo::LoadGameInfo(EGame Game)
|
bool CGameInfo::LoadGameInfo(EGame Game)
|
||||||
{
|
{
|
||||||
Game = RoundGame(Game);
|
Game = RoundGame(Game);
|
||||||
mGame = Game;
|
mGame = Game;
|
||||||
|
|
||||||
TString Path = GetDefaultGameInfoPath(Game);
|
TString Path = GetDefaultGameInfoPath(Game);
|
||||||
if (FileUtil::Exists(Path))
|
return LoadGameInfo(Path);
|
||||||
LoadGameInfo(Path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameInfo::LoadGameInfo(TString Path)
|
bool CGameInfo::LoadGameInfo(TString Path)
|
||||||
{
|
{
|
||||||
CXMLReader Reader(Path);
|
CXMLReader Reader(Path);
|
||||||
|
|
||||||
|
if (Reader.IsValid())
|
||||||
|
{
|
||||||
Serialize(Reader);
|
Serialize(Reader);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameInfo::SaveGameInfo(TString Path /*= ""*/)
|
bool CGameInfo::SaveGameInfo(TString Path /*= ""*/)
|
||||||
{
|
{
|
||||||
ASSERT(mGame != eUnknownGame); // can't save game info that was never loaded
|
ASSERT(mGame != eUnknownGame); // can't save game info that was never loaded
|
||||||
|
|
||||||
if (Path.IsEmpty()) Path = GetDefaultGameInfoPath(mGame);
|
if (Path.IsEmpty()) Path = GetDefaultGameInfoPath(mGame);
|
||||||
CXMLWriter Writer(Path, "GameInfo", 0, mGame);
|
CXMLWriter Writer(Path, "GameInfo", 0, mGame);
|
||||||
Serialize(Writer);
|
Serialize(Writer);
|
||||||
|
return Writer.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameInfo::Serialize(IArchive& rArc)
|
void CGameInfo::Serialize(IArchive& rArc)
|
||||||
|
@ -21,9 +21,9 @@ public:
|
|||||||
: mGame(eUnknownGame)
|
: mGame(eUnknownGame)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void LoadGameInfo(EGame Game);
|
bool LoadGameInfo(EGame Game);
|
||||||
void LoadGameInfo(TString Path);
|
bool LoadGameInfo(TString Path);
|
||||||
void SaveGameInfo(TString Path = "");
|
bool SaveGameInfo(TString Path = "");
|
||||||
void Serialize(IArchive& rArc);
|
void Serialize(IArchive& rArc);
|
||||||
|
|
||||||
TString GetAreaName(const CAssetID& rkID) const;
|
TString GetAreaName(const CAssetID& rkID) const;
|
||||||
|
@ -7,7 +7,10 @@ CGameProject *CGameProject::mspActiveProject = nullptr;
|
|||||||
|
|
||||||
CGameProject::~CGameProject()
|
CGameProject::~CGameProject()
|
||||||
{
|
{
|
||||||
|
if (mpResourceStore)
|
||||||
|
{
|
||||||
ASSERT(!mpResourceStore->IsDirty());
|
ASSERT(!mpResourceStore->IsDirty());
|
||||||
|
}
|
||||||
|
|
||||||
if (IsActive())
|
if (IsActive())
|
||||||
{
|
{
|
||||||
@ -15,16 +18,23 @@ CGameProject::~CGameProject()
|
|||||||
gpResourceStore = nullptr;
|
gpResourceStore = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (u32 iPkg = 0; iPkg < mPackages.size(); iPkg++)
|
||||||
|
delete mPackages[iPkg];
|
||||||
|
|
||||||
delete mpAudioManager;
|
delete mpAudioManager;
|
||||||
delete mpGameInfo;
|
delete mpGameInfo;
|
||||||
delete mpResourceStore;
|
delete mpResourceStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameProject::Save()
|
bool CGameProject::Save()
|
||||||
{
|
{
|
||||||
|
mProjFileLock.Release();
|
||||||
TString ProjPath = ProjectPath().ToUTF8();
|
TString ProjPath = ProjectPath().ToUTF8();
|
||||||
CXMLWriter Writer(ProjPath, "GameProject", eVer_Current, mGame);
|
CXMLWriter Writer(ProjPath, "GameProject", eVer_Current, mGame);
|
||||||
Serialize(Writer);
|
Serialize(Writer);
|
||||||
|
bool SaveSuccess = Writer.Save();
|
||||||
|
mProjFileLock.Lock(*ProjPath);
|
||||||
|
return SaveSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameProject::Serialize(IArchive& rArc)
|
void CGameProject::Serialize(IArchive& rArc)
|
||||||
@ -60,12 +70,14 @@ void CGameProject::Serialize(IArchive& rArc)
|
|||||||
// Load resource store
|
// Load resource store
|
||||||
ASSERT(mpResourceStore == nullptr);
|
ASSERT(mpResourceStore == nullptr);
|
||||||
mpResourceStore = new CResourceStore(this);
|
mpResourceStore = new CResourceStore(this);
|
||||||
mpResourceStore->LoadResourceDatabase();
|
|
||||||
|
|
||||||
|
if (!mpResourceStore->LoadResourceDatabase())
|
||||||
|
mLoadSuccess = false;
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
// Load packages
|
// Load packages
|
||||||
for (u32 iPkg = 0; iPkg < mPackages.size(); iPkg++)
|
ASSERT(mPackages.empty());
|
||||||
delete mPackages[iPkg];
|
|
||||||
mPackages.clear();
|
|
||||||
|
|
||||||
for (u32 iPkg = 0; iPkg < PackageList.size(); iPkg++)
|
for (u32 iPkg = 0; iPkg < PackageList.size(); iPkg++)
|
||||||
{
|
{
|
||||||
@ -74,8 +86,15 @@ void CGameProject::Serialize(IArchive& rArc)
|
|||||||
TWideString PackageDir = rkPackagePath.GetFileDirectory();
|
TWideString PackageDir = rkPackagePath.GetFileDirectory();
|
||||||
|
|
||||||
CPackage *pPackage = new CPackage(this, PackageName, PackageDir);
|
CPackage *pPackage = new CPackage(this, PackageName, PackageDir);
|
||||||
pPackage->Load();
|
bool PackageLoadSuccess = pPackage->Load();
|
||||||
mPackages.push_back(pPackage);
|
mPackages.push_back(pPackage);
|
||||||
|
|
||||||
|
if (!PackageLoadSuccess)
|
||||||
|
{
|
||||||
|
mLoadSuccess = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,6 +179,7 @@ CGameProject* CGameProject::CreateProjectForExport(
|
|||||||
pProj->mProjectRoot.Replace(L"/", L"\\");
|
pProj->mProjectRoot.Replace(L"/", L"\\");
|
||||||
pProj->mpResourceStore = new CResourceStore(pProj, pExporter, L"Content\\", L"Cooked\\", Game);
|
pProj->mpResourceStore = new CResourceStore(pProj, pExporter, L"Content\\", L"Cooked\\", Game);
|
||||||
pProj->mpGameInfo->LoadGameInfo(Game);
|
pProj->mpGameInfo->LoadGameInfo(Game);
|
||||||
|
pProj->mLoadSuccess = true;
|
||||||
return pProj;
|
return pProj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,10 +191,24 @@ CGameProject* CGameProject::LoadProject(const TWideString& rkProjPath)
|
|||||||
|
|
||||||
TString ProjPath = rkProjPath.ToUTF8();
|
TString ProjPath = rkProjPath.ToUTF8();
|
||||||
CXMLReader Reader(ProjPath);
|
CXMLReader Reader(ProjPath);
|
||||||
|
|
||||||
|
if (!Reader.IsValid())
|
||||||
|
{
|
||||||
|
delete pProj;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
pProj->mGame = Reader.Game();
|
pProj->mGame = Reader.Game();
|
||||||
pProj->Serialize(Reader);
|
pProj->Serialize(Reader);
|
||||||
CTemplateLoader::LoadGameTemplates(pProj->mGame);
|
|
||||||
|
|
||||||
|
if (!pProj->mLoadSuccess)
|
||||||
|
{
|
||||||
|
delete pProj;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CTemplateLoader::LoadGameTemplates(pProj->mGame);
|
||||||
|
pProj->mProjFileLock.Lock(*ProjPath);
|
||||||
pProj->mpGameInfo->LoadGameInfo(pProj->mGame);
|
pProj->mpGameInfo->LoadGameInfo(pProj->mGame);
|
||||||
pProj->mpAudioManager->LoadAssets();
|
pProj->mpAudioManager->LoadAssets();
|
||||||
return pProj;
|
return pProj;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "CResourceStore.h"
|
#include "CResourceStore.h"
|
||||||
#include "Core/CAudioManager.h"
|
#include "Core/CAudioManager.h"
|
||||||
#include "Core/Resource/Script/CMasterTemplate.h"
|
#include "Core/Resource/Script/CMasterTemplate.h"
|
||||||
|
#include <FileIO/CFileLock.h>
|
||||||
#include <Common/CAssetID.h>
|
#include <Common/CAssetID.h>
|
||||||
#include <Common/EGame.h>
|
#include <Common/EGame.h>
|
||||||
#include <Common/FileUtil.h>
|
#include <Common/FileUtil.h>
|
||||||
@ -31,6 +32,11 @@ class CGameProject
|
|||||||
CGameInfo *mpGameInfo;
|
CGameInfo *mpGameInfo;
|
||||||
CAudioManager *mpAudioManager;
|
CAudioManager *mpAudioManager;
|
||||||
|
|
||||||
|
// Keep file handle open for the .prj file to prevent users from opening the same project
|
||||||
|
// in multiple instances of PWE
|
||||||
|
CFileLock mProjFileLock;
|
||||||
|
bool mLoadSuccess;
|
||||||
|
|
||||||
enum EProjectVersion
|
enum EProjectVersion
|
||||||
{
|
{
|
||||||
eVer_Initial,
|
eVer_Initial,
|
||||||
@ -50,6 +56,7 @@ class CGameProject
|
|||||||
, mBuildVersion(0.f)
|
, mBuildVersion(0.f)
|
||||||
, mResourceDBPath(L"ResourceDB.rdb")
|
, mResourceDBPath(L"ResourceDB.rdb")
|
||||||
, mpResourceStore(nullptr)
|
, mpResourceStore(nullptr)
|
||||||
|
, mLoadSuccess(true)
|
||||||
{
|
{
|
||||||
mpGameInfo = new CGameInfo();
|
mpGameInfo = new CGameInfo();
|
||||||
mpAudioManager = new CAudioManager(this);
|
mpAudioManager = new CAudioManager(this);
|
||||||
@ -58,7 +65,7 @@ class CGameProject
|
|||||||
public:
|
public:
|
||||||
~CGameProject();
|
~CGameProject();
|
||||||
|
|
||||||
void Save();
|
bool Save();
|
||||||
void Serialize(IArchive& rArc);
|
void Serialize(IArchive& rArc);
|
||||||
void SetActive();
|
void SetActive();
|
||||||
void GetWorldList(std::list<CAssetID>& rOut) const;
|
void GetWorldList(std::list<CAssetID>& rOut) const;
|
||||||
|
@ -10,21 +10,28 @@
|
|||||||
|
|
||||||
using namespace tinyxml2;
|
using namespace tinyxml2;
|
||||||
|
|
||||||
void CPackage::Load()
|
bool CPackage::Load()
|
||||||
{
|
{
|
||||||
TWideString DefPath = DefinitionPath(false);
|
TWideString DefPath = DefinitionPath(false);
|
||||||
CXMLReader Reader(DefPath.ToUTF8());
|
CXMLReader Reader(DefPath.ToUTF8());
|
||||||
|
|
||||||
|
if (Reader.IsValid())
|
||||||
|
{
|
||||||
Serialize(Reader);
|
Serialize(Reader);
|
||||||
UpdateDependencyCache();
|
UpdateDependencyCache();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPackage::Save()
|
bool CPackage::Save()
|
||||||
{
|
{
|
||||||
TWideString DefPath = DefinitionPath(false);
|
TWideString DefPath = DefinitionPath(false);
|
||||||
FileUtil::MakeDirectory(DefPath.GetFileDirectory());
|
FileUtil::MakeDirectory(DefPath.GetFileDirectory());
|
||||||
|
|
||||||
CXMLWriter Writer(DefPath.ToUTF8(), "PackageDefinition", 0, mpProject ? mpProject->Game() : eUnknownGame);
|
CXMLWriter Writer(DefPath.ToUTF8(), "PackageDefinition", 0, mpProject ? mpProject->Game() : eUnknownGame);
|
||||||
Serialize(Writer);
|
Serialize(Writer);
|
||||||
|
return Writer.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPackage::Serialize(IArchive& rArc)
|
void CPackage::Serialize(IArchive& rArc)
|
||||||
|
@ -71,8 +71,8 @@ public:
|
|||||||
, mNeedsRecook(false)
|
, mNeedsRecook(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void Load();
|
bool Load();
|
||||||
void Save();
|
bool Save();
|
||||||
void Serialize(IArchive& rArc);
|
void Serialize(IArchive& rArc);
|
||||||
void UpdateDependencyCache();
|
void UpdateDependencyCache();
|
||||||
|
|
||||||
|
@ -195,9 +195,17 @@ bool CResourceEntry::Save(bool SkipCacheSave /*= false*/)
|
|||||||
|
|
||||||
TString SerialName = mpTypeInfo->TypeName();
|
TString SerialName = mpTypeInfo->TypeName();
|
||||||
SerialName.RemoveWhitespace();
|
SerialName.RemoveWhitespace();
|
||||||
|
|
||||||
CXMLWriter Writer(Path, SerialName, 0, mGame);
|
CXMLWriter Writer(Path, SerialName, 0, mGame);
|
||||||
mpResource->Serialize(Writer);
|
mpResource->Serialize(Writer);
|
||||||
|
|
||||||
|
if (!Writer.Save())
|
||||||
|
{
|
||||||
|
Log::Error("Failed to save raw resource: " + Path);
|
||||||
|
DEBUG_BREAK;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
mFlags |= eREF_NeedsRecook;
|
mFlags |= eREF_NeedsRecook;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,16 +294,28 @@ CResource* CResourceEntry::Load()
|
|||||||
gpResourceStore = mpStore;
|
gpResourceStore = mpStore;
|
||||||
|
|
||||||
CXMLReader Reader(RawAssetPath());
|
CXMLReader Reader(RawAssetPath());
|
||||||
mpResource->Serialize(Reader);
|
|
||||||
mpStore->TrackLoadedResource(this);
|
|
||||||
|
|
||||||
gpResourceStore = pOldStore;
|
if (!Reader.IsValid())
|
||||||
|
{
|
||||||
|
Log::Error("Failed to load raw resource; falling back on cooked. Raw path: " + RawAssetPath());
|
||||||
|
delete mpResource;
|
||||||
|
mpResource = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mpResource->Serialize(Reader);
|
||||||
|
mpStore->TrackLoadedResource(this);
|
||||||
|
gpResourceStore = pOldStore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mpResource)
|
||||||
return mpResource;
|
return mpResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (HasCookedVersion())
|
ASSERT(!mpResource);
|
||||||
|
if (HasCookedVersion())
|
||||||
{
|
{
|
||||||
CFileInStream File(CookedAssetPath().ToStdString(), IOUtil::eBigEndian);
|
CFileInStream File(CookedAssetPath().ToStdString(), IOUtil::eBigEndian);
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ void CResourceStore::SerializeResourceDatabase(IArchive& rArc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CResourceStore::LoadResourceDatabase()
|
bool CResourceStore::LoadResourceDatabase()
|
||||||
{
|
{
|
||||||
ASSERT(!mDatabasePath.IsEmpty());
|
ASSERT(!mDatabasePath.IsEmpty());
|
||||||
TString Path = DatabasePath().ToUTF8();
|
TString Path = DatabasePath().ToUTF8();
|
||||||
@ -118,27 +118,45 @@ void CResourceStore::LoadResourceDatabase()
|
|||||||
|
|
||||||
CXMLReader Reader(Path);
|
CXMLReader Reader(Path);
|
||||||
|
|
||||||
|
if (!Reader.IsValid())
|
||||||
|
{
|
||||||
|
Log::Error("Failed to open resource database for load: " + Path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (mpProj)
|
if (mpProj)
|
||||||
ASSERT(mpProj->Game() == Reader.Game());
|
ASSERT(mpProj->Game() == Reader.Game());
|
||||||
|
|
||||||
mGame = Reader.Game();
|
mGame = Reader.Game();
|
||||||
SerializeResourceDatabase(Reader);
|
SerializeResourceDatabase(Reader);
|
||||||
LoadCacheFile();
|
return LoadCacheFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CResourceStore::SaveResourceDatabase()
|
bool CResourceStore::SaveResourceDatabase()
|
||||||
{
|
{
|
||||||
TString Path = DatabasePath().ToUTF8();
|
TString Path = DatabasePath().ToUTF8();
|
||||||
CXMLWriter Writer(Path, "ResourceDB", 0, mGame);
|
CXMLWriter Writer(Path, "ResourceDB", 0, mGame);
|
||||||
SerializeResourceDatabase(Writer);
|
SerializeResourceDatabase(Writer);
|
||||||
|
bool SaveSuccess = Writer.Save();
|
||||||
|
|
||||||
|
if (SaveSuccess)
|
||||||
mDatabaseDirty = false;
|
mDatabaseDirty = false;
|
||||||
|
else
|
||||||
|
Log::Error("Failed to save resource database: " + Path);
|
||||||
|
|
||||||
|
return SaveSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CResourceStore::LoadCacheFile()
|
bool CResourceStore::LoadCacheFile()
|
||||||
{
|
{
|
||||||
TString CachePath = CacheDataPath().ToUTF8();
|
TString CachePath = CacheDataPath().ToUTF8();
|
||||||
CFileInStream CacheFile(CachePath.ToStdString(), IOUtil::eBigEndian);
|
CFileInStream CacheFile(CachePath.ToStdString(), IOUtil::eBigEndian);
|
||||||
ASSERT(CacheFile.IsValid());
|
|
||||||
|
if (!CacheFile.IsValid())
|
||||||
|
{
|
||||||
|
Log::Error("Failed to open cache file for load: " + CachePath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Cache header
|
// Cache header
|
||||||
CFourCC Magic(CacheFile);
|
CFourCC Magic(CacheFile);
|
||||||
@ -146,7 +164,7 @@ void CResourceStore::LoadCacheFile()
|
|||||||
if (Magic != "CACH")
|
if (Magic != "CACH")
|
||||||
{
|
{
|
||||||
Log::Error("Invalid resource cache data magic: " + Magic.ToString());
|
Log::Error("Invalid resource cache data magic: " + Magic.ToString());
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSerialVersion Version(CacheFile);
|
CSerialVersion Version(CacheFile);
|
||||||
@ -173,13 +191,19 @@ void CResourceStore::LoadCacheFile()
|
|||||||
|
|
||||||
CacheFile.Seek(EntryCacheEnd, SEEK_SET);
|
CacheFile.Seek(EntryCacheEnd, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CResourceStore::SaveCacheFile()
|
bool CResourceStore::SaveCacheFile()
|
||||||
{
|
{
|
||||||
TString CachePath = CacheDataPath().ToUTF8();
|
TString CachePath = CacheDataPath().ToUTF8();
|
||||||
CFileOutStream CacheFile(CachePath.ToStdString(), IOUtil::eBigEndian);
|
CFileOutStream CacheFile(CachePath.ToStdString(), IOUtil::eBigEndian);
|
||||||
ASSERT(CacheFile.IsValid());
|
|
||||||
|
if (!CacheFile.IsValid())
|
||||||
|
{
|
||||||
|
Log::Error("Failed to open cache file for save: " + CachePath);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Cache header
|
// Cache header
|
||||||
CFourCC("CACH").Write(CacheFile);
|
CFourCC("CACH").Write(CacheFile);
|
||||||
@ -219,6 +243,7 @@ void CResourceStore::SaveCacheFile()
|
|||||||
CacheFile.Seek(ResCountOffset, SEEK_SET);
|
CacheFile.Seek(ResCountOffset, SEEK_SET);
|
||||||
CacheFile.WriteLong(ResCount);
|
CacheFile.WriteLong(ResCount);
|
||||||
mCacheFileDirty = false;
|
mCacheFileDirty = false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CResourceStore::ConditionalSaveStore()
|
void CResourceStore::ConditionalSaveStore()
|
||||||
|
@ -52,10 +52,10 @@ public:
|
|||||||
CResourceStore(CGameProject *pProject);
|
CResourceStore(CGameProject *pProject);
|
||||||
~CResourceStore();
|
~CResourceStore();
|
||||||
void SerializeResourceDatabase(IArchive& rArc);
|
void SerializeResourceDatabase(IArchive& rArc);
|
||||||
void LoadResourceDatabase();
|
bool LoadResourceDatabase();
|
||||||
void SaveResourceDatabase();
|
bool SaveResourceDatabase();
|
||||||
void LoadCacheFile();
|
bool LoadCacheFile();
|
||||||
void SaveCacheFile();
|
bool SaveCacheFile();
|
||||||
void ConditionalSaveStore();
|
void ConditionalSaveStore();
|
||||||
void SetProject(CGameProject *pProj);
|
void SetProject(CGameProject *pProj);
|
||||||
void CloseProject();
|
void CloseProject();
|
||||||
|
@ -335,13 +335,21 @@ void CExportGameDialog::Export()
|
|||||||
CAssetNameMap NameMap;
|
CAssetNameMap NameMap;
|
||||||
|
|
||||||
if (!NameMapPath.isEmpty())
|
if (!NameMapPath.isEmpty())
|
||||||
NameMap.LoadAssetNames( TO_TSTRING(NameMapPath) );
|
{
|
||||||
|
bool LoadSuccess = NameMap.LoadAssetNames( TO_TSTRING(NameMapPath) );
|
||||||
|
|
||||||
if (!NameMap.IsValid())
|
if (!LoadSuccess)
|
||||||
|
{
|
||||||
|
UICommon::ErrorMsg(this, "Failed to load the asset name map!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (!NameMap.IsValid())
|
||||||
{
|
{
|
||||||
UICommon::ErrorMsg(this, "The Asset Name Map is invalid and cannot be used! See the log for more information.");
|
UICommon::ErrorMsg(this, "The Asset Name Map is invalid and cannot be used! See the log for more information.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Verify game info is valid
|
// Verify game info is valid
|
||||||
if (!GameInfoPath.isEmpty() && !FileUtil::Exists(TO_TSTRING(GameInfoPath)))
|
if (!GameInfoPath.isEmpty() && !FileUtil::Exists(TO_TSTRING(GameInfoPath)))
|
||||||
@ -350,12 +358,20 @@ void CExportGameDialog::Export()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do export
|
|
||||||
close();
|
|
||||||
|
|
||||||
CGameInfo GameInfo;
|
CGameInfo GameInfo;
|
||||||
if (!GameInfoPath.isEmpty())
|
if (!GameInfoPath.isEmpty())
|
||||||
GameInfo.LoadGameInfo( TO_TSTRING(GameInfoPath) );
|
{
|
||||||
|
bool LoadSuccess = GameInfo.LoadGameInfo( TO_TSTRING(GameInfoPath) );
|
||||||
|
|
||||||
|
if (!LoadSuccess)
|
||||||
|
{
|
||||||
|
UICommon::ErrorMsg(this, "Failed to load game info!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do export
|
||||||
|
close();
|
||||||
|
|
||||||
CGameExporter Exporter(mGame, mRegion, mGameTitle, mGameID, mBuildVer);
|
CGameExporter Exporter(mGame, mRegion, mGameTitle, mGameID, mBuildVer);
|
||||||
TString StrExportDir = TO_TSTRING(ExportDir);
|
TString StrExportDir = TO_TSTRING(ExportDir);
|
||||||
|
@ -49,7 +49,9 @@ void CProjectOverviewDialog::InternalLoadProject(const QString& rkPath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
Log::Error("Failed to load project");
|
{
|
||||||
|
UICommon::ErrorMsg(this, "Failed to open project! Is it already open in another Prime World Editor instance?");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CProjectOverviewDialog::OpenProject()
|
void CProjectOverviewDialog::OpenProject()
|
||||||
|
@ -322,7 +322,18 @@ void CResourceBrowser::OnGenerateAssetNames()
|
|||||||
void CResourceBrowser::OnImportNamesFromAssetNameMap()
|
void CResourceBrowser::OnImportNamesFromAssetNameMap()
|
||||||
{
|
{
|
||||||
CAssetNameMap Map;
|
CAssetNameMap Map;
|
||||||
Map.LoadAssetNames();
|
bool LoadSuccess = Map.LoadAssetNames();
|
||||||
|
|
||||||
|
if (!LoadSuccess)
|
||||||
|
{
|
||||||
|
UICommon::ErrorMsg(this, "Import failed; couldn't load asset name map!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!Map.IsValid())
|
||||||
|
{
|
||||||
|
UICommon::ErrorMsg(this, "Import failed; the input asset name map is invalid! See the log for details.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (CResourceIterator It(mpStore); It; ++It)
|
for (CResourceIterator It(mpStore); It; ++It)
|
||||||
{
|
{
|
||||||
@ -335,6 +346,7 @@ void CResourceBrowser::OnImportNamesFromAssetNameMap()
|
|||||||
mpStore->ConditionalSaveStore();
|
mpStore->ConditionalSaveStore();
|
||||||
RefreshResources();
|
RefreshResources();
|
||||||
RefreshDirectories();
|
RefreshDirectories();
|
||||||
|
UICommon::InfoMsg(this, "Success", "New asset names imported successfully!");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CResourceBrowser::ExportAssetNames()
|
void CResourceBrowser::ExportAssetNames()
|
||||||
@ -346,10 +358,29 @@ void CResourceBrowser::ExportAssetNames()
|
|||||||
CAssetNameMap NameMap;
|
CAssetNameMap NameMap;
|
||||||
|
|
||||||
if (FileUtil::Exists(OutFileStr))
|
if (FileUtil::Exists(OutFileStr))
|
||||||
NameMap.LoadAssetNames(OutFileStr);
|
{
|
||||||
|
bool LoadSuccess = NameMap.LoadAssetNames(OutFileStr);
|
||||||
|
|
||||||
|
if (!LoadSuccess)
|
||||||
|
{
|
||||||
|
UICommon::ErrorMsg(this, "Unable to export; failed to load existing names from the original asset name map file!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (!NameMap.IsValid())
|
||||||
|
{
|
||||||
|
UICommon::ErrorMsg(this, "Unable to export; the original asset name map file is invalid! See the log for details.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NameMap.CopyFromStore(mpStore);
|
NameMap.CopyFromStore(mpStore);
|
||||||
NameMap.SaveAssetNames(OutFileStr);
|
bool SaveSuccess = NameMap.SaveAssetNames(OutFileStr);
|
||||||
|
|
||||||
|
if (SaveSuccess)
|
||||||
|
UICommon::ErrorMsg(this, "Failed to export asset names!");
|
||||||
|
else
|
||||||
|
UICommon::InfoMsg(this, "Success", "Asset names exported successfully!");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CResourceBrowser::UpdateFilter()
|
void CResourceBrowser::UpdateFilter()
|
||||||
|
@ -102,6 +102,11 @@ inline QString OpenDirDialog(QWidget *pParent, const QString& rkCaption, const Q
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QMessageBox wrappers
|
// QMessageBox wrappers
|
||||||
|
inline void InfoMsg(QWidget *pParent, QString InfoBoxTitle, QString InfoText)
|
||||||
|
{
|
||||||
|
QMessageBox::information(pParent, InfoBoxTitle, InfoText);
|
||||||
|
}
|
||||||
|
|
||||||
inline void ErrorMsg(QWidget *pParent, QString ErrorText)
|
inline void ErrorMsg(QWidget *pParent, QString ErrorText)
|
||||||
{
|
{
|
||||||
QMessageBox::warning(pParent, "Error", ErrorText);
|
QMessageBox::warning(pParent, "Error", ErrorText);
|
||||||
|
34
src/FileIO/CFileLock.h
Normal file
34
src/FileIO/CFileLock.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef CFILELOCK_H
|
||||||
|
#define CFILELOCK_H
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
// Maintain a file handle to prevent other processes from accessing the file.
|
||||||
|
class CFileLock
|
||||||
|
{
|
||||||
|
FILE* mpFile;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CFileLock()
|
||||||
|
: mpFile(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~CFileLock()
|
||||||
|
{
|
||||||
|
Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lock(const char *pkPath)
|
||||||
|
{
|
||||||
|
Release();
|
||||||
|
mpFile = fopen(pkPath, "a+");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Release()
|
||||||
|
{
|
||||||
|
if (mpFile)
|
||||||
|
fclose(mpFile);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CFILELOCK_H
|
@ -41,7 +41,8 @@ HEADERS += \
|
|||||||
IOUtil.h \
|
IOUtil.h \
|
||||||
IInputStream.h \
|
IInputStream.h \
|
||||||
IOutputStream.h \
|
IOutputStream.h \
|
||||||
CBitStreamInWrapper.h
|
CBitStreamInWrapper.h \
|
||||||
|
CFileLock.h
|
||||||
|
|
||||||
# Source Files
|
# Source Files
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<enumerator ID="0x03" name="Immune"/>
|
<enumerator ID="0x03" name="Immune"/>
|
||||||
<enumerator ID="0x04" name="Pass Through"/>
|
<enumerator ID="0x04" name="Pass Through"/>
|
||||||
<enumerator ID="0x05" name="Direct/Double"/>
|
<enumerator ID="0x05" name="Direct/Double"/>
|
||||||
<enumerator ID="0x06" name="Direct"/>
|
<enumerator ID="0x06" name="Direct/Normal"/>
|
||||||
<enumerator ID="0x07" name="Immune?"/>
|
<enumerator ID="0x07" name="Direct/Immune"/>
|
||||||
</enumerators>
|
</enumerators>
|
||||||
</enum>
|
</enum>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user