Reimplemented save & repack button to work in the project system

This commit is contained in:
Aruki 2017-02-08 11:20:33 -07:00
parent 1b97cd459a
commit a7b0a2480c
13 changed files with 127 additions and 67 deletions

View File

@ -62,6 +62,10 @@ public:
} }
// We couldn't find a matching element, so we can't load this parameter. // We couldn't find a matching element, so we can't load this parameter.
// If we pushed a parent earlier, undo it.
if (!mJustEndedParam)
mpCurElem = mpCurElem->Parent()->ToElement();
return false; return false;
} }

View File

@ -276,7 +276,7 @@ void GenerateAssetNames(CGameProject *pProj)
{ {
TString Name = pInst->InstanceName(); TString Name = pInst->InstanceName();
if (Name.EndsWith(".SCAN", false)) if (Name.StartsWith("POI_", false))
{ {
TIDString ScanIDString = (pProj->Game() <= ePrime ? "0x4:0x0" : "0xBDBEC295:0xB94E9BE7"); TIDString ScanIDString = (pProj->Game() <= ePrime ? "0x4:0x0" : "0xBDBEC295:0xB94E9BE7");
TAssetProperty *pScanProperty = TPropCast<TAssetProperty>(pInst->PropertyByIDString(ScanIDString)); TAssetProperty *pScanProperty = TPropCast<TAssetProperty>(pInst->PropertyByIDString(ScanIDString));
@ -289,10 +289,10 @@ void GenerateAssetNames(CGameProject *pProj)
if (pEntry && !pEntry->IsNamed()) if (pEntry && !pEntry->IsNamed())
{ {
TWideString ScanName = Name.ToUTF16().ChopBack(5); TWideString ScanName = Name.ToUTF16().ChopFront(4);
if (ScanName.StartsWith(L"POI_")) if (ScanName.EndsWith(L".SCAN", false))
ScanName = ScanName.ChopFront(4); ScanName = ScanName.ChopBack(5);
ApplyGeneratedName(pEntry, pEntry->DirectoryPath(), ScanName); ApplyGeneratedName(pEntry, pEntry->DirectoryPath(), ScanName);
@ -419,7 +419,7 @@ void GenerateAssetNames(CGameProject *pProj)
{ {
CAudioGroup *pGroup = (CAudioGroup*) It->Load(); CAudioGroup *pGroup = (CAudioGroup*) It->Load();
TWideString GroupName = pGroup->GroupName().ToUTF16(); TWideString GroupName = pGroup->GroupName().ToUTF16();
ApplyGeneratedName(*It, L"AudioGrp\\", GroupName); ApplyGeneratedName(*It, L"Audio\\", GroupName);
} }
#endif #endif

View File

@ -34,6 +34,24 @@ bool CAssetNameMap::GetNameInfo(CAssetID ID, TString& rOutDirectory, TString& rO
void CAssetNameMap::CopyFromStore(CResourceStore *pStore /*= gpResourceStore*/) void CAssetNameMap::CopyFromStore(CResourceStore *pStore /*= gpResourceStore*/)
{ {
// Do a first pass to remove old paths from used set to prevent false positives from eg. if two resources switch places
for (CResourceIterator It(pStore); It; ++It)
{
if (It->IsCategorized() || It->IsNamed())
{
auto Find = mMap.find(It->ID());
if (Find != mMap.end())
{
SAssetNameInfo& rInfo = Find->second;
auto UsedFind = mUsedSet.find(rInfo);
ASSERT(UsedFind != mUsedSet.end());
mUsedSet.erase(UsedFind);
}
}
}
// Do a second pass to add the new paths to the map
for (CResourceIterator It(pStore); It; ++It) for (CResourceIterator It(pStore); It; ++It)
{ {
if (It->IsCategorized() || It->IsNamed()) if (It->IsCategorized() || It->IsNamed())
@ -44,17 +62,6 @@ void CAssetNameMap::CopyFromStore(CResourceStore *pStore /*= gpResourceStore*/)
CFourCC Type = It->CookedExtension(); CFourCC Type = It->CookedExtension();
SAssetNameInfo NameInfo { Name, Directory, Type }; SAssetNameInfo NameInfo { Name, Directory, Type };
// Remove old path from used set
auto Find = mMap.find(ID);
if (Find != mMap.end())
{
SAssetNameInfo& rInfo = Find->second;
auto UsedFind = mUsedSet.find(rInfo);
ASSERT(UsedFind != mUsedSet.end());
mUsedSet.erase(UsedFind);
}
// Check for conflicts with new name // Check for conflicts with new name
if (mUsedSet.find(NameInfo) != mUsedSet.end()) if (mUsedSet.find(NameInfo) != mUsedSet.end())
{ {

View File

@ -57,6 +57,12 @@ void CGameProject::Serialize(IArchive& rArc)
if (rArc.IsReader()) if (rArc.IsReader())
{ {
// Load resource store
ASSERT(mpResourceStore == nullptr);
mpResourceStore = new CResourceStore(this);
mpResourceStore->LoadResourceDatabase();
// Load packages
for (u32 iPkg = 0; iPkg < mPackages.size(); iPkg++) for (u32 iPkg = 0; iPkg < mPackages.size(); iPkg++)
delete mPackages[iPkg]; delete mPackages[iPkg];
mPackages.clear(); mPackages.clear();
@ -169,8 +175,6 @@ CGameProject* CGameProject::LoadProject(const TWideString& rkProjPath)
pProj->Serialize(Reader); pProj->Serialize(Reader);
CTemplateLoader::LoadGameTemplates(pProj->mGame); CTemplateLoader::LoadGameTemplates(pProj->mGame);
pProj->mpResourceStore = new CResourceStore(pProj);
pProj->mpResourceStore->LoadResourceDatabase();
pProj->mpGameInfo->LoadGameInfo(pProj->mGame); pProj->mpGameInfo->LoadGameInfo(pProj->mGame);
pProj->mpAudioManager->LoadAssets(); pProj->mpAudioManager->LoadAssets();
return pProj; return pProj;

View File

@ -15,6 +15,7 @@ void CPackage::Load()
TWideString DefPath = DefinitionPath(false); TWideString DefPath = DefinitionPath(false);
CXMLReader Reader(DefPath.ToUTF8()); CXMLReader Reader(DefPath.ToUTF8());
Serialize(Reader); Serialize(Reader);
UpdateDependencyCache();
} }
void CPackage::Save() void CPackage::Save()
@ -28,7 +29,18 @@ void CPackage::Save()
void CPackage::Serialize(IArchive& rArc) void CPackage::Serialize(IArchive& rArc)
{ {
rArc << SERIAL_CONTAINER("Collections", mCollections, "ResourceCollection"); rArc << SERIAL("NeedsRecook", mNeedsRecook)
<< SERIAL_CONTAINER("Collections", mCollections, "ResourceCollection");
}
void CPackage::UpdateDependencyCache()
{
CPackageDependencyListBuilder Builder(this);
std::list<CAssetID> AssetList;
Builder.BuildDependencyList(false, AssetList);
for (auto Iter = AssetList.begin(); Iter != AssetList.end(); Iter++)
mCachedDependencies.insert(*Iter);
} }
void CPackage::Cook() void CPackage::Cook()
@ -74,18 +86,6 @@ void CPackage::Cook()
pkRes->ID.Write(Pak); pkRes->ID.Write(Pak);
Pak.WriteLong(pkRes->Name.Size()); Pak.WriteLong(pkRes->Name.Size());
Pak.WriteString(pkRes->Name.ToStdString(), pkRes->Name.Size()); // Note: Explicitly specifying size means we don't write the terminating 0 Pak.WriteString(pkRes->Name.ToStdString(), pkRes->Name.Size()); // Note: Explicitly specifying size means we don't write the terminating 0
// TEMP: recook world
if (pkRes->Type == "MLVL")
{
CResourceEntry *pEntry = gpResourceStore->FindEntry(pkRes->ID);
ASSERT(pEntry);
CWorld *pWorld = (CWorld*) pEntry->Load();
ASSERT(pWorld);
CFileOutStream MLVL(pEntry->CookedAssetPath().ToStdString(), IOUtil::eBigEndian);
ASSERT(MLVL.IsValid());
CWorldCooker::CookMLVL(pWorld, MLVL);
}
} }
// Fill in table of contents with junk, write later // Fill in table of contents with junk, write later
@ -114,10 +114,14 @@ void CPackage::Cook()
for (auto Iter = AssetList.begin(); Iter != AssetList.end(); Iter++, ResIdx++) for (auto Iter = AssetList.begin(); Iter != AssetList.end(); Iter++, ResIdx++)
{ {
// Initialize entry, recook assets if needed
CAssetID ID = *Iter; CAssetID ID = *Iter;
CResourceEntry *pEntry = gpResourceStore->FindEntry(ID); CResourceEntry *pEntry = gpResourceStore->FindEntry(ID);
ASSERT(pEntry != nullptr); ASSERT(pEntry != nullptr);
if (pEntry->NeedsRecook())
pEntry->Cook();
SResourceTocInfo& rTocInfo = ResourceTocData[ResIdx]; SResourceTocInfo& rTocInfo = ResourceTocData[ResIdx];
rTocInfo.pEntry = pEntry; rTocInfo.pEntry = pEntry;
rTocInfo.Offset = Pak.Tell(); rTocInfo.Offset = Pak.Tell();
@ -200,6 +204,8 @@ void CPackage::Cook()
Pak.WriteLong(rkTocInfo.Offset); Pak.WriteLong(rkTocInfo.Offset);
} }
mNeedsRecook = false;
Save();
Log::Write("Finished writing " + PakPath.ToUTF8()); Log::Write("Finished writing " + PakPath.ToUTF8());
} }

View File

@ -50,6 +50,8 @@ class CPackage
TString mPakName; TString mPakName;
TWideString mPakPath; TWideString mPakPath;
std::vector<CResourceCollection*> mCollections; std::vector<CResourceCollection*> mCollections;
std::set<CAssetID> mCachedDependencies;
bool mNeedsRecook;
enum EPackageDefinitionVersion enum EPackageDefinitionVersion
{ {
@ -66,11 +68,13 @@ public:
: mpProject(pProj) : mpProject(pProj)
, mPakName(rkName) , mPakName(rkName)
, mPakPath(rkPath) , mPakPath(rkPath)
, mNeedsRecook(false)
{} {}
void Load(); void Load();
void Save(); void Save();
void Serialize(IArchive& rArc); void Serialize(IArchive& rArc);
void UpdateDependencyCache();
void Cook(); void Cook();
void CompareOriginalAssetList(const std::list<CAssetID>& rkNewList); void CompareOriginalAssetList(const std::list<CAssetID>& rkNewList);
@ -88,8 +92,11 @@ public:
inline CGameProject* Project() const { return mpProject; } inline CGameProject* Project() const { return mpProject; }
inline u32 NumCollections() const { return mCollections.size(); } inline u32 NumCollections() const { return mCollections.size(); }
inline CResourceCollection* CollectionByIndex(u32 Idx) const { return mCollections[Idx]; } inline CResourceCollection* CollectionByIndex(u32 Idx) const { return mCollections[Idx]; }
inline bool ContainsAsset(const CAssetID& rkID) const { return mCachedDependencies.find(rkID) != mCachedDependencies.end(); }
inline bool NeedsRecook() const { return mNeedsRecook; }
inline void SetPakName(TString NewName) { mPakName = NewName; } inline void SetPakName(TString NewName) { mPakName = NewName; }
inline void MarkDirty() { mNeedsRecook = true; Save(); UpdateDependencyCache(); }
}; };
#endif // CPACKAGE #endif // CPACKAGE

View File

@ -213,13 +213,24 @@ bool CResourceEntry::Save(bool SkipCacheSave /*= false*/)
} }
} }
// Resource has been saved, now update dependencies + cache file // Resource has been saved; now make sure dependencies, cache data, and packages are all up to date
UpdateDependencies(); UpdateDependencies();
mpStore->SetCacheDataDirty(); mpStore->SetCacheDataDirty();
if (!SkipCacheSave) if (!SkipCacheSave)
{
mpStore->ConditionalSaveStore(); mpStore->ConditionalSaveStore();
// Flag dirty any packages that contain this resource.
for (u32 iPkg = 0; iPkg < mpStore->Project()->NumPackages(); iPkg++)
{
CPackage *pPkg = mpStore->Project()->PackageByIndex(iPkg);
if (pPkg->ContainsAsset(ID()))
pPkg->MarkDirty();
}
}
if (ShouldCollectGarbage) if (ShouldCollectGarbage)
mpStore->DestroyUnreferencedResources(); mpStore->DestroyUnreferencedResources();

View File

@ -57,7 +57,7 @@ void CCharacterUsageMap::FindUsagesForArea(CWorld *pWorld, u32 AreaIndex)
mCurrentAreaAllowsDupes = pWorld->DoesAreaAllowPakDuplicates(iArea); mCurrentAreaAllowsDupes = pWorld->DoesAreaAllowPakDuplicates(iArea);
CAssetID AreaID = pWorld->AreaResourceID(iArea); CAssetID AreaID = pWorld->AreaResourceID(iArea);
CResourceEntry *pEntry = gpResourceStore->FindEntry(AreaID); CResourceEntry *pEntry = mpStore->FindEntry(AreaID);
ASSERT(pEntry && pEntry->ResourceType() == eArea); ASSERT(pEntry && pEntry->ResourceType() == eArea);
ParseDependencyNode(pEntry->Dependencies()); ParseDependencyNode(pEntry->Dependencies());
@ -98,7 +98,7 @@ void CCharacterUsageMap::DebugPrintContents()
{ {
CAssetID ID = Iter->first; CAssetID ID = Iter->first;
std::vector<bool>& rUsedList = Iter->second; std::vector<bool>& rUsedList = Iter->second;
CAnimSet *pSet = (CAnimSet*) gpResourceStore->LoadResource(ID, "ANCS"); CAnimSet *pSet = (CAnimSet*) mpStore->LoadResource(ID, "ANCS");
for (u32 iChar = 0; iChar < pSet->NumCharacters(); iChar++) for (u32 iChar = 0; iChar < pSet->NumCharacters(); iChar++)
{ {
@ -152,7 +152,7 @@ void CCharacterUsageMap::ParseDependencyNode(IDependencyNode *pNode)
else if (Type == eDNT_ResourceDependency || Type == eDNT_ScriptProperty) else if (Type == eDNT_ResourceDependency || Type == eDNT_ScriptProperty)
{ {
CResourceDependency *pDep = static_cast<CResourceDependency*>(pNode); CResourceDependency *pDep = static_cast<CResourceDependency*>(pNode);
CResourceEntry *pEntry = gpResourceStore->FindEntry(pDep->ID()); CResourceEntry *pEntry = mpStore->FindEntry(pDep->ID());
if (pEntry) if (pEntry)
{ {
@ -184,7 +184,7 @@ void CPackageDependencyListBuilder::BuildDependencyList(bool AllowDuplicates, st
for (u32 iRes = 0; iRes < pCollection->NumResources(); iRes++) for (u32 iRes = 0; iRes < pCollection->NumResources(); iRes++)
{ {
const SNamedResource& rkRes = pCollection->ResourceByIndex(iRes); const SNamedResource& rkRes = pCollection->ResourceByIndex(iRes);
CResourceEntry *pEntry = gpResourceStore->FindEntry(rkRes.ID); CResourceEntry *pEntry = mpStore->FindEntry(rkRes.ID);
if (!pEntry) continue; if (!pEntry) continue;
if (rkRes.Name.EndsWith("NODEPEND") || rkRes.Type == "CSNG") if (rkRes.Name.EndsWith("NODEPEND") || rkRes.Type == "CSNG")
@ -211,7 +211,7 @@ void CPackageDependencyListBuilder::BuildDependencyList(bool AllowDuplicates, st
void CPackageDependencyListBuilder::AddDependency(CResourceEntry *pCurEntry, const CAssetID& rkID, std::list<CAssetID>& rOut) void CPackageDependencyListBuilder::AddDependency(CResourceEntry *pCurEntry, const CAssetID& rkID, std::list<CAssetID>& rOut)
{ {
if (pCurEntry && pCurEntry->ResourceType() == eDependencyGroup) return; if (pCurEntry && pCurEntry->ResourceType() == eDependencyGroup) return;
CResourceEntry *pEntry = gpResourceStore->FindEntry(rkID); CResourceEntry *pEntry = mpStore->FindEntry(rkID);
if (!pEntry) return; if (!pEntry) return;
EResType ResType = pEntry->ResourceType(); EResType ResType = pEntry->ResourceType();
@ -395,7 +395,7 @@ void CAreaDependencyListBuilder::BuildDependencyList(std::list<CAssetID>& rAsset
void CAreaDependencyListBuilder::AddDependency(const CAssetID& rkID, std::list<CAssetID>& rOut, std::set<CAssetID> *pAudioGroupsOut) void CAreaDependencyListBuilder::AddDependency(const CAssetID& rkID, std::list<CAssetID>& rOut, std::set<CAssetID> *pAudioGroupsOut)
{ {
CResourceEntry *pEntry = gpResourceStore->FindEntry(rkID); CResourceEntry *pEntry = mpStore->FindEntry(rkID);
if (!pEntry) return; if (!pEntry) return;
EResType ResType = pEntry->ResourceType(); EResType ResType = pEntry->ResourceType();

View File

@ -12,12 +12,16 @@ class CCharacterUsageMap
{ {
std::map<CAssetID, std::vector<bool>> mUsageMap; std::map<CAssetID, std::vector<bool>> mUsageMap;
std::set<CAssetID> mStillLookingIDs; std::set<CAssetID> mStillLookingIDs;
CResourceStore *mpStore;
u32 mLayerIndex; u32 mLayerIndex;
bool mIsInitialArea; bool mIsInitialArea;
bool mCurrentAreaAllowsDupes; bool mCurrentAreaAllowsDupes;
public: public:
CCharacterUsageMap() : mLayerIndex(-1), mIsInitialArea(true), mCurrentAreaAllowsDupes(false) {} CCharacterUsageMap(CResourceStore *pStore)
: mpStore(pStore), mLayerIndex(-1), mIsInitialArea(true), mCurrentAreaAllowsDupes(false)
{}
bool IsCharacterUsed(const CAssetID& rkID, u32 CharacterIndex) const; bool IsCharacterUsed(const CAssetID& rkID, u32 CharacterIndex) const;
bool IsAnimationUsed(const CAssetID& rkID, CSetAnimationDependency *pAnim) const; bool IsAnimationUsed(const CAssetID& rkID, CSetAnimationDependency *pAnim) const;
void FindUsagesForAsset(CResourceEntry *pEntry); void FindUsagesForAsset(CResourceEntry *pEntry);
@ -35,6 +39,7 @@ protected:
class CPackageDependencyListBuilder class CPackageDependencyListBuilder
{ {
CPackage *mpPackage; CPackage *mpPackage;
CResourceStore *mpStore;
EGame mGame; EGame mGame;
TResPtr<CWorld> mpWorld; TResPtr<CWorld> mpWorld;
CAssetID mCurrentAnimSetID; CAssetID mCurrentAnimSetID;
@ -49,9 +54,12 @@ public:
CPackageDependencyListBuilder(CPackage *pPackage) CPackageDependencyListBuilder(CPackage *pPackage)
: mpPackage(pPackage) : mpPackage(pPackage)
, mGame(pPackage->Project()->Game()) , mGame(pPackage->Project()->Game())
, mpStore(pPackage->Project()->ResourceStore())
, mCharacterUsageMap(pPackage->Project()->ResourceStore())
, mCurrentAreaHasDuplicates(false) , mCurrentAreaHasDuplicates(false)
, mIsPlayerActor(false) , mIsPlayerActor(false)
{} {
}
void BuildDependencyList(bool AllowDuplicates, std::list<CAssetID>& rOut); void BuildDependencyList(bool AllowDuplicates, std::list<CAssetID>& rOut);
void AddDependency(CResourceEntry *pCurEntry, const CAssetID& rkID, std::list<CAssetID>& rOut); void AddDependency(CResourceEntry *pCurEntry, const CAssetID& rkID, std::list<CAssetID>& rOut);
@ -62,6 +70,7 @@ public:
class CAreaDependencyListBuilder class CAreaDependencyListBuilder
{ {
CResourceEntry *mpAreaEntry; CResourceEntry *mpAreaEntry;
CResourceStore *mpStore;
EGame mGame; EGame mGame;
CAssetID mCurrentAnimSetID; CAssetID mCurrentAnimSetID;
CCharacterUsageMap mCharacterUsageMap; CCharacterUsageMap mCharacterUsageMap;
@ -72,7 +81,9 @@ class CAreaDependencyListBuilder
public: public:
CAreaDependencyListBuilder(CResourceEntry *pAreaEntry) CAreaDependencyListBuilder(CResourceEntry *pAreaEntry)
: mpAreaEntry(pAreaEntry) : mpAreaEntry(pAreaEntry)
, mpStore(pAreaEntry->ResourceStore())
, mGame(pAreaEntry->Game()) , mGame(pAreaEntry->Game())
, mCharacterUsageMap(pAreaEntry->ResourceStore())
{ {
ASSERT(mpAreaEntry->ResourceType() == eArea); ASSERT(mpAreaEntry->ResourceType() == eArea);
} }

View File

@ -84,6 +84,26 @@ void CEditorApplication::EditResource(CResourceEntry *pEntry)
} }
} }
void CEditorApplication::NotifyAssetsModified()
{
emit AssetsModified();
}
void CEditorApplication::CookAllDirtyPackages()
{
CGameProject *pProj = CGameProject::ActiveProject();
for (u32 iPkg = 0; iPkg < pProj->NumPackages(); iPkg++)
{
CPackage *pPackage = pProj->PackageByIndex(iPkg);
if (pPackage->NeedsRecook())
pPackage->Cook();
}
mpProjectDialog->SetupPackagesList();
}
void CEditorApplication::AddEditor(IEditor *pEditor) void CEditorApplication::AddEditor(IEditor *pEditor)
{ {
mEditorWindows << pEditor; mEditorWindows << pEditor;

View File

@ -31,6 +31,8 @@ public:
~CEditorApplication(); ~CEditorApplication();
void InitEditor(); void InitEditor();
void EditResource(CResourceEntry *pEntry); void EditResource(CResourceEntry *pEntry);
void NotifyAssetsModified();
void CookAllDirtyPackages();
// Accessors // Accessors
inline CWorldEditor* WorldEditor() const { return mpWorldEditor; } inline CWorldEditor* WorldEditor() const { return mpWorldEditor; }
@ -44,6 +46,9 @@ public slots:
void AddEditor(IEditor *pEditor); void AddEditor(IEditor *pEditor);
void TickEditors(); void TickEditors();
void OnEditorClose(); void OnEditorClose();
signals:
void AssetsModified();
}; };
#define gpEdApp static_cast<CEditorApplication*>(qApp) #define gpEdApp static_cast<CEditorApplication*>(qApp)

View File

@ -22,6 +22,8 @@ CProjectOverviewDialog::CProjectOverviewDialog(QWidget *pParent)
connect(mpUI->LaunchEditorButton, SIGNAL(clicked()), this, SLOT(LaunchEditor())); connect(mpUI->LaunchEditorButton, SIGNAL(clicked()), this, SLOT(LaunchEditor()));
connect(mpUI->ViewResourcesButton, SIGNAL(clicked()), this, SLOT(LaunchResourceBrowser())); connect(mpUI->ViewResourcesButton, SIGNAL(clicked()), this, SLOT(LaunchResourceBrowser()));
connect(mpUI->CookPackageButton, SIGNAL(clicked()), this, SLOT(CookPackage())); connect(mpUI->CookPackageButton, SIGNAL(clicked()), this, SLOT(CookPackage()));
connect(gpEdApp, SIGNAL(AssetsModified()), this, SLOT(SetupPackagesList()));
} }
CProjectOverviewDialog::~CProjectOverviewDialog() CProjectOverviewDialog::~CProjectOverviewDialog()
@ -113,7 +115,10 @@ void CProjectOverviewDialog::SetupPackagesList()
{ {
CPackage *pPackage = mpProject->PackageByIndex(iPkg); CPackage *pPackage = mpProject->PackageByIndex(iPkg);
ASSERT(pPackage != nullptr); ASSERT(pPackage != nullptr);
mpUI->PackagesList->addItem(TO_QSTRING(pPackage->Name()));
QString PackageName = TO_QSTRING(pPackage->Name());
if (pPackage->NeedsRecook()) PackageName += '*';
mpUI->PackagesList->addItem(PackageName);
} }
} }

View File

@ -17,6 +17,7 @@
#include "Editor/Widgets/WVectorEditor.h" #include "Editor/Widgets/WVectorEditor.h"
#include "Editor/Undo/UndoCommands.h" #include "Editor/Undo/UndoCommands.h"
#include <Core/GameProject/CGameProject.h>
#include <Core/Render/CDrawUtil.h> #include <Core/Render/CDrawUtil.h>
#include <Core/Scene/CSceneIterator.h> #include <Core/Scene/CSceneIterator.h>
#include <Common/Log.h> #include <Common/Log.h>
@ -360,6 +361,9 @@ bool CWorldEditor::Save()
bool SaveEGMCSuccess = mpArea->PoiToWorldMap() ? mpArea->PoiToWorldMap()->Entry()->Save() : true; bool SaveEGMCSuccess = mpArea->PoiToWorldMap() ? mpArea->PoiToWorldMap()->Entry()->Save() : true;
bool SaveWorldSuccess = mpWorld->Entry()->Save(); bool SaveWorldSuccess = mpWorld->Entry()->Save();
if (SaveAreaSuccess || SaveEGMCSuccess || SaveWorldSuccess)
gpEdApp->NotifyAssetsModified();
if (SaveAreaSuccess && SaveEGMCSuccess && SaveWorldSuccess) if (SaveAreaSuccess && SaveEGMCSuccess && SaveWorldSuccess)
{ {
mUndoStack.setClean(); mUndoStack.setClean();
@ -376,32 +380,8 @@ bool CWorldEditor::Save()
bool CWorldEditor::SaveAndRepack() bool CWorldEditor::SaveAndRepack()
{ {
if (!Save()) return false; if (!Save()) return false;
gpEdApp->CookAllDirtyPackages();
if (!CanRepack()) return true;
{
CRepackInfoDialog Dialog(mWorldDir, mPakFileList, mPakTarget, this);
Dialog.exec();
if (Dialog.result() == QDialog::Accepted)
{
SetWorldDir(Dialog.TargetFolder());
SetPakFileList(Dialog.ListFile());
SetPakTarget(Dialog.OutputPak());
if (!CanRepack()) return false;
}
else return false;
}
QString PakOut;
CPakToolDialog::EResult Result = CPakToolDialog::Repack(CurrentGame(), mPakTarget, mPakFileList, mWorldDir, &PakOut, this);
if (Result == CPakToolDialog::eError)
QMessageBox::warning(this, "Error", "Failed to repack!");
else if (Result == CPakToolDialog::eSuccess)
QMessageBox::information(this, "Success", "Successfully saved pak: " + PakOut);
return (Result == CPakToolDialog::eSuccess);
} }
void CWorldEditor::OnLinksModified(const QList<CScriptObject*>& rkInstances) void CWorldEditor::OnLinksModified(const QList<CScriptObject*>& rkInstances)