Dropped support for resource collections in package definitions

This commit is contained in:
Aruki 2017-02-14 19:20:22 -07:00
parent c5de322ac7
commit 3697401ebb
9 changed files with 131 additions and 274 deletions

View File

@ -122,18 +122,13 @@ void GenerateAssetNames(CGameProject *pProj)
{
CPackage *pPkg = pProj->PackageByIndex(iPkg);
for (u32 iCol = 0; iCol < pPkg->NumCollections(); iCol++)
for (u32 iRes = 0; iRes < pPkg->NumNamedResources(); iRes++)
{
CResourceCollection *pCol = pPkg->CollectionByIndex(iCol);
const SNamedResource& rkRes = pPkg->NamedResourceByIndex(iRes);
if (rkRes.Name.EndsWith("NODEPEND")) continue;
for (u32 iRes = 0; iRes < pCol->NumResources(); iRes++)
{
const SNamedResource& rkRes = pCol->ResourceByIndex(iRes);
if (rkRes.Name.EndsWith("NODEPEND")) continue;
CResourceEntry *pRes = pStore->FindEntry(rkRes.ID);
ApplyGeneratedName(pRes, pPkg->Name().ToUTF16(), rkRes.Name.ToUTF16());
}
CResourceEntry *pRes = pStore->FindEntry(rkRes.ID);
ApplyGeneratedName(pRes, pPkg->Name().ToUTF16(), rkRes.Name.ToUTF16());
}
}
#endif

View File

@ -197,7 +197,6 @@ void CGameExporter::LoadPaks()
}
CPackage *pPackage = new CPackage(mpProject, CharPak.GetFileName(false), FileUtil::MakeRelative(PakPath.GetFileDirectory(), mExportDir + mDiscDir));
CResourceCollection *pCollection = pPackage->AddCollection("Default");
// MP1-MP3Proto
if (mGame < eCorruption)
@ -218,7 +217,7 @@ void CGameExporter::LoadPaks()
CAssetID ResID(Pak, mGame);
u32 NameLen = Pak.ReadLong();
TString Name = Pak.ReadString(NameLen);
pCollection->AddResource(Name, ResID, ResType);
pPackage->AddResource(Name, ResID, ResType);
}
u32 NumResources = Pak.ReadLong();
@ -292,7 +291,7 @@ void CGameExporter::LoadPaks()
TString Name = Pak.ReadString();
CFourCC ResType = Pak.ReadLong();
CAssetID ResID(Pak, mGame);
pCollection->AddResource(Name, ResID, ResType);
pPackage->AddResource(Name, ResID, ResType);
}
}

View File

@ -100,17 +100,12 @@ void CGameProject::GetWorldList(std::list<CAssetID>& rOut) const
{
CPackage *pPkg = mPackages[iPkg];
for (u32 iCol = 0; iCol < pPkg->NumCollections(); iCol++)
for (u32 iRes = 0; iRes < pPkg->NumNamedResources(); iRes++)
{
CResourceCollection *pCol = pPkg->CollectionByIndex(iCol);
const SNamedResource& rkRes = pPkg->NamedResourceByIndex(iRes);
for (u32 iRes = 0; iRes < pCol->NumResources(); iRes++)
{
const SNamedResource& rkRes = pCol->ResourceByIndex(iRes);
if (rkRes.Type == "MLVL" && !rkRes.Name.EndsWith("NODEPEND"))
rOut.push_back(rkRes.ID);
}
if (rkRes.Type == "MLVL" && !rkRes.Name.EndsWith("NODEPEND"))
rOut.push_back(rkRes.ID);
}
}
}
@ -121,17 +116,12 @@ CAssetID CGameProject::FindNamedResource(const TString& rkName) const
{
CPackage *pPkg = mPackages[iPkg];
for (u32 iCol = 0; iCol < pPkg->NumCollections(); iCol++)
for (u32 iRes = 0; iRes < pPkg->NumNamedResources(); iRes++)
{
CResourceCollection *pCol = pPkg->CollectionByIndex(iCol);
const SNamedResource& rkRes = pPkg->NamedResourceByIndex(iRes);
for (u32 iRes = 0; iRes < pCol->NumResources(); iRes++)
{
const SNamedResource& rkRes = pCol->ResourceByIndex(iRes);
if (rkRes.Name == rkName)
return rkRes.ID;
}
if (rkRes.Name == rkName)
return rkRes.ID;
}
}

View File

@ -18,7 +18,7 @@ bool CPackage::Load()
if (Reader.IsValid())
{
Serialize(Reader);
UpdateDependencyCache();
mCacheDirty = true;
return true;
}
else return false;
@ -37,17 +37,26 @@ bool CPackage::Save()
void CPackage::Serialize(IArchive& rArc)
{
rArc << SERIAL("NeedsRecook", mNeedsRecook)
<< SERIAL_CONTAINER("Collections", mCollections, "ResourceCollection");
<< SERIAL_CONTAINER("NamedResources", mResources, "Resource");
}
void CPackage::UpdateDependencyCache()
void CPackage::AddResource(const TString& rkName, const CAssetID& rkID, const CFourCC& rkType)
{
mResources.push_back( SNamedResource { rkName, rkID, rkType } );
mCacheDirty = true;
}
void CPackage::UpdateDependencyCache() const
{
CPackageDependencyListBuilder Builder(this);
std::list<CAssetID> AssetList;
Builder.BuildDependencyList(false, AssetList);
mCachedDependencies.clear();
for (auto Iter = AssetList.begin(); Iter != AssetList.end(); Iter++)
mCachedDependencies.insert(*Iter);
mCacheDirty = false;
}
void CPackage::Cook()
@ -58,17 +67,6 @@ void CPackage::Cook()
Builder.BuildDependencyList(true, AssetList);
Log::Write(TString::FromInt32(AssetList.size(), 0, 10) + " assets in " + Name() + ".pak");
// Get named resources
std::list<const SNamedResource*> NamedResources;
for (u32 iCol = 0; iCol < mCollections.size(); iCol++)
{
CResourceCollection *pCol = mCollections[iCol];
for (u32 iRes = 0; iRes < pCol->NumResources(); iRes++)
NamedResources.push_back(&pCol->ResourceByIndex(iRes));
}
// Write new pak
TWideString PakPath = CookedPackagePath(false);
CFileOutStream Pak(PakPath.ToUTF8().ToStdString(), IOUtil::eBigEndian);
@ -84,15 +82,15 @@ void CPackage::Cook()
Pak.WriteLong(0); // Unknown
// Named Resources
Pak.WriteLong(NamedResources.size());
Pak.WriteLong(mResources.size());
for (auto Iter = NamedResources.begin(); Iter != NamedResources.end(); Iter++)
for (auto Iter = mResources.begin(); Iter != mResources.end(); Iter++)
{
const SNamedResource *pkRes = *Iter;
pkRes->Type.Write(Pak);
pkRes->ID.Write(Pak);
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
const SNamedResource& rkRes = *Iter;
rkRes.Type.Write(Pak);
rkRes.ID.Write(Pak);
Pak.WriteLong(rkRes.Name.Size());
Pak.WriteString(rkRes.Name.ToStdString(), rkRes.Name.Size()); // Note: Explicitly specifying size means we don't write the terminating 0
}
// Fill in table of contents with junk, write later
@ -290,6 +288,14 @@ void CPackage::CompareOriginalAssetList(const std::list<CAssetID>& rkNewList)
}
}
bool CPackage::ContainsAsset(const CAssetID& rkID) const
{
if (mCacheDirty)
UpdateDependencyCache();
return mCachedDependencies.find(rkID) != mCachedDependencies.end();
}
TWideString CPackage::DefinitionPath(bool Relative) const
{
TWideString RelPath = mPakPath + mPakName.ToUTF16() + L".pkd";
@ -301,30 +307,3 @@ TWideString CPackage::CookedPackagePath(bool Relative) const
TWideString RelPath = mPakPath + mPakName.ToUTF16() + L".pak";
return Relative ? RelPath : mpProject->DiscDir(false) + RelPath;
}
CResourceCollection* CPackage::AddCollection(const TString& rkName)
{
CResourceCollection *pCollection = new CResourceCollection(rkName);
mCollections.push_back(pCollection);
return pCollection;
}
void CPackage::RemoveCollection(CResourceCollection *pCollection)
{
for (u32 iCol = 0; iCol < mCollections.size(); iCol++)
{
if (mCollections[iCol] == pCollection)
{
RemoveCollection(iCol);
break;
}
}
}
void CPackage::RemoveCollection(u32 Index)
{
ASSERT(Index < mCollections.size());
auto Iter = mCollections.begin() + Index;
delete *Iter;
mCollections.erase(Iter);
}

View File

@ -20,39 +20,18 @@ struct SNamedResource
}
};
class CResourceCollection
{
TString mName;
std::vector<SNamedResource> mNamedResources;
public:
CResourceCollection() : mName("UNNAMED") {}
CResourceCollection(const TString& rkName) : mName(rkName) {}
void Serialize(IArchive& rArc)
{
rArc << SERIAL("Name", mName) << SERIAL_CONTAINER("Resources", mNamedResources, "Resource");
}
inline TString Name() const { return mName; }
inline u32 NumResources() const { return mNamedResources.size(); }
inline const SNamedResource& ResourceByIndex(u32 Idx) const { return mNamedResources[Idx]; }
inline void AddResource(const TString& rkName, const CAssetID& rkID, const CFourCC& rkType)
{
mNamedResources.push_back( SNamedResource { rkName, rkID, rkType } );
}
};
class CPackage
{
CGameProject *mpProject;
TString mPakName;
TWideString mPakPath;
std::vector<CResourceCollection*> mCollections;
std::set<CAssetID> mCachedDependencies;
std::vector<SNamedResource> mResources;
bool mNeedsRecook;
// Cached dependency list; used to figure out if a given resource is in this package
mutable bool mCacheDirty;
mutable std::set<CAssetID> mCachedDependencies;
enum EPackageDefinitionVersion
{
eVer_Initial,
@ -69,31 +48,29 @@ public:
, mPakName(rkName)
, mPakPath(rkPath)
, mNeedsRecook(false)
, mCacheDirty(true)
{}
bool Load();
bool Save();
void Serialize(IArchive& rArc);
void UpdateDependencyCache();
void AddResource(const TString& rkName, const CAssetID& rkID, const CFourCC& rkType);
void UpdateDependencyCache() const;
void Cook();
void CompareOriginalAssetList(const std::list<CAssetID>& rkNewList);
bool ContainsAsset(const CAssetID& rkID) const;
TWideString DefinitionPath(bool Relative) const;
TWideString CookedPackagePath(bool Relative) const;
CResourceCollection* AddCollection(const TString& rkName);
void RemoveCollection(CResourceCollection *pCollection);
void RemoveCollection(u32 Index);
// Accessors
inline TString Name() const { return mPakName; }
inline TWideString Path() const { return mPakPath; }
inline CGameProject* Project() const { return mpProject; }
inline u32 NumCollections() const { return mCollections.size(); }
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 TString Name() const { return mPakName; }
inline TWideString Path() const { return mPakPath; }
inline CGameProject* Project() const { return mpProject; }
inline u32 NumNamedResources() const { return mResources.size(); }
inline const SNamedResource& NamedResourceByIndex(u32 Idx) const { return mResources[Idx]; }
inline bool NeedsRecook() const { return mNeedsRecook; }
inline void SetPakName(TString NewName) { mPakName = NewName; }
inline void MarkDirty() { mNeedsRecook = true; Save(); UpdateDependencyCache(); }

View File

@ -176,35 +176,30 @@ void CPackageDependencyListBuilder::BuildDependencyList(bool AllowDuplicates, st
{
mEnableDuplicates = AllowDuplicates;
// Iterate over all resource collections and resources and parse their dependencies
for (u32 iCol = 0; iCol < mpPackage->NumCollections(); iCol++)
// Iterate over all resources and parse their dependencies
for (u32 iRes = 0; iRes < mpkPackage->NumNamedResources(); iRes++)
{
CResourceCollection *pCollection = mpPackage->CollectionByIndex(iCol);
const SNamedResource& rkRes = mpkPackage->NamedResourceByIndex(iRes);
CResourceEntry *pEntry = mpStore->FindEntry(rkRes.ID);
if (!pEntry) continue;
for (u32 iRes = 0; iRes < pCollection->NumResources(); iRes++)
if (rkRes.Name.EndsWith("NODEPEND") || rkRes.Type == "CSNG")
{
const SNamedResource& rkRes = pCollection->ResourceByIndex(iRes);
CResourceEntry *pEntry = mpStore->FindEntry(rkRes.ID);
if (!pEntry) continue;
if (rkRes.Name.EndsWith("NODEPEND") || rkRes.Type == "CSNG")
{
rOut.push_back(rkRes.ID);
continue;
}
if (rkRes.Type == "MLVL")
{
mpWorld = (CWorld*) pEntry->Load();
ASSERT(mpWorld);
}
else
mCharacterUsageMap.FindUsagesForAsset(pEntry);
AddDependency(nullptr, rkRes.ID, rOut);
mpWorld = nullptr;
rOut.push_back(rkRes.ID);
continue;
}
if (rkRes.Type == "MLVL")
{
mpWorld = (CWorld*) pEntry->Load();
ASSERT(mpWorld);
}
else
mCharacterUsageMap.FindUsagesForAsset(pEntry);
AddDependency(nullptr, rkRes.ID, rOut);
mpWorld = nullptr;
}
}

View File

@ -38,7 +38,7 @@ protected:
// ************ CPackageDependencyListBuilder ************
class CPackageDependencyListBuilder
{
CPackage *mpPackage;
const CPackage *mpkPackage;
CResourceStore *mpStore;
EGame mGame;
TResPtr<CWorld> mpWorld;
@ -51,11 +51,11 @@ class CPackageDependencyListBuilder
bool mIsPlayerActor;
public:
CPackageDependencyListBuilder(CPackage *pPackage)
: mpPackage(pPackage)
, mGame(pPackage->Project()->Game())
, mpStore(pPackage->Project()->ResourceStore())
, mCharacterUsageMap(pPackage->Project()->ResourceStore())
CPackageDependencyListBuilder(const CPackage *pkPackage)
: mpkPackage(pkPackage)
, mGame(pkPackage->Project()->Game())
, mpStore(pkPackage->Project()->ResourceStore())
, mCharacterUsageMap(pkPackage->Project()->ResourceStore())
, mCurrentAreaHasDuplicates(false)
, mIsPlayerActor(false)
{

View File

@ -13,131 +13,53 @@
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="OpenProjectButton">
<property name="text">
<string>Open Project</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ExportGameButton">
<property name="text">
<string>Export Game</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="ViewResourcesButton">
<property name="text">
<string>View Resources</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QGroupBox" name="WorldsGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Worlds</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QListWidget" name="WorldsList"/>
</item>
<item>
<widget class="QPushButton" name="LoadWorldButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Load</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="AreasGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>3</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Areas</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QComboBox" name="AreaComboBox">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="LaunchEditorButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Launch World Editor</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="PackagesGroupBox">
<property name="title">
<string>Packages</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QListWidget" name="PackagesList"/>
</item>
<item>
<widget class="QPushButton" name="CookPackageButton">
<property name="text">
<string>Cook Package</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="CookAllDirtyPackagesButton">
<property name="text">
<string>Cook All Dirty Packages</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
<widget class="QGroupBox" name="PackagesGroupBox">
<property name="geometry">
<rect>
<x>100</x>
<y>130</y>
<width>280</width>
<height>287</height>
</rect>
</property>
<property name="title">
<string>Packages</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QListWidget" name="PackagesList">
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="CookPackageButton">
<property name="text">
<string>Cook Package</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="CookAllDirtyPackagesButton">
<property name="text">
<string>Cook All Dirty Packages</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>

View File

@ -18,7 +18,7 @@ CWorldInfoSidebar::CWorldInfoSidebar(CWorldEditor *pEditor)
connect(gpEdApp, SIGNAL(ActiveProjectChanged(CGameProject*)), this, SLOT(OnActiveProjectChanged(CGameProject*)));
connect(mpUI->AreaSearchLineEdit, SIGNAL(StoppedTyping(QString)), this, SLOT(OnAreaFilterStringChanged(QString)));
connect(mpUI->WorldTreeView, SIGNAL(clicked(QModelIndex)), this, SLOT(OnWorldTreeClicked(QModelIndex)));
connect(mpUI->WorldTreeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(OnWorldTreeClicked(QModelIndex)));
connect(mpUI->WorldTreeView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnWorldTreeDoubleClicked(QModelIndex)));
// Set up UI for world/area info; disable editing for now