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); 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++) CResourceEntry *pRes = pStore->FindEntry(rkRes.ID);
{ ApplyGeneratedName(pRes, pPkg->Name().ToUTF16(), rkRes.Name.ToUTF16());
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());
}
} }
} }
#endif #endif

View File

@ -197,7 +197,6 @@ void CGameExporter::LoadPaks()
} }
CPackage *pPackage = new CPackage(mpProject, CharPak.GetFileName(false), FileUtil::MakeRelative(PakPath.GetFileDirectory(), mExportDir + mDiscDir)); CPackage *pPackage = new CPackage(mpProject, CharPak.GetFileName(false), FileUtil::MakeRelative(PakPath.GetFileDirectory(), mExportDir + mDiscDir));
CResourceCollection *pCollection = pPackage->AddCollection("Default");
// MP1-MP3Proto // MP1-MP3Proto
if (mGame < eCorruption) if (mGame < eCorruption)
@ -218,7 +217,7 @@ void CGameExporter::LoadPaks()
CAssetID ResID(Pak, mGame); CAssetID ResID(Pak, mGame);
u32 NameLen = Pak.ReadLong(); u32 NameLen = Pak.ReadLong();
TString Name = Pak.ReadString(NameLen); TString Name = Pak.ReadString(NameLen);
pCollection->AddResource(Name, ResID, ResType); pPackage->AddResource(Name, ResID, ResType);
} }
u32 NumResources = Pak.ReadLong(); u32 NumResources = Pak.ReadLong();
@ -292,7 +291,7 @@ void CGameExporter::LoadPaks()
TString Name = Pak.ReadString(); TString Name = Pak.ReadString();
CFourCC ResType = Pak.ReadLong(); CFourCC ResType = Pak.ReadLong();
CAssetID ResID(Pak, mGame); 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]; 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++) if (rkRes.Type == "MLVL" && !rkRes.Name.EndsWith("NODEPEND"))
{ rOut.push_back(rkRes.ID);
const SNamedResource& rkRes = pCol->ResourceByIndex(iRes);
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]; 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++) if (rkRes.Name == rkName)
{ return rkRes.ID;
const SNamedResource& rkRes = pCol->ResourceByIndex(iRes);
if (rkRes.Name == rkName)
return rkRes.ID;
}
} }
} }

View File

@ -18,7 +18,7 @@ bool CPackage::Load()
if (Reader.IsValid()) if (Reader.IsValid())
{ {
Serialize(Reader); Serialize(Reader);
UpdateDependencyCache(); mCacheDirty = true;
return true; return true;
} }
else return false; else return false;
@ -37,17 +37,26 @@ bool CPackage::Save()
void CPackage::Serialize(IArchive& rArc) void CPackage::Serialize(IArchive& rArc)
{ {
rArc << SERIAL("NeedsRecook", mNeedsRecook) 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); CPackageDependencyListBuilder Builder(this);
std::list<CAssetID> AssetList; std::list<CAssetID> AssetList;
Builder.BuildDependencyList(false, AssetList); Builder.BuildDependencyList(false, AssetList);
mCachedDependencies.clear();
for (auto Iter = AssetList.begin(); Iter != AssetList.end(); Iter++) for (auto Iter = AssetList.begin(); Iter != AssetList.end(); Iter++)
mCachedDependencies.insert(*Iter); mCachedDependencies.insert(*Iter);
mCacheDirty = false;
} }
void CPackage::Cook() void CPackage::Cook()
@ -58,17 +67,6 @@ void CPackage::Cook()
Builder.BuildDependencyList(true, AssetList); Builder.BuildDependencyList(true, AssetList);
Log::Write(TString::FromInt32(AssetList.size(), 0, 10) + " assets in " + Name() + ".pak"); 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 // Write new pak
TWideString PakPath = CookedPackagePath(false); TWideString PakPath = CookedPackagePath(false);
CFileOutStream Pak(PakPath.ToUTF8().ToStdString(), IOUtil::eBigEndian); CFileOutStream Pak(PakPath.ToUTF8().ToStdString(), IOUtil::eBigEndian);
@ -84,15 +82,15 @@ void CPackage::Cook()
Pak.WriteLong(0); // Unknown Pak.WriteLong(0); // Unknown
// Named Resources // 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; const SNamedResource& rkRes = *Iter;
pkRes->Type.Write(Pak); rkRes.Type.Write(Pak);
pkRes->ID.Write(Pak); rkRes.ID.Write(Pak);
Pak.WriteLong(pkRes->Name.Size()); Pak.WriteLong(rkRes.Name.Size());
Pak.WriteString(pkRes->Name.ToStdString(), pkRes->Name.Size()); // Note: Explicitly specifying size means we don't write the terminating 0 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 // 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 CPackage::DefinitionPath(bool Relative) const
{ {
TWideString RelPath = mPakPath + mPakName.ToUTF16() + L".pkd"; TWideString RelPath = mPakPath + mPakName.ToUTF16() + L".pkd";
@ -301,30 +307,3 @@ TWideString CPackage::CookedPackagePath(bool Relative) const
TWideString RelPath = mPakPath + mPakName.ToUTF16() + L".pak"; TWideString RelPath = mPakPath + mPakName.ToUTF16() + L".pak";
return Relative ? RelPath : mpProject->DiscDir(false) + RelPath; 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 class CPackage
{ {
CGameProject *mpProject; CGameProject *mpProject;
TString mPakName; TString mPakName;
TWideString mPakPath; TWideString mPakPath;
std::vector<CResourceCollection*> mCollections; std::vector<SNamedResource> mResources;
std::set<CAssetID> mCachedDependencies;
bool mNeedsRecook; 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 enum EPackageDefinitionVersion
{ {
eVer_Initial, eVer_Initial,
@ -69,31 +48,29 @@ public:
, mPakName(rkName) , mPakName(rkName)
, mPakPath(rkPath) , mPakPath(rkPath)
, mNeedsRecook(false) , mNeedsRecook(false)
, mCacheDirty(true)
{} {}
bool Load(); bool Load();
bool Save(); bool Save();
void Serialize(IArchive& rArc); void Serialize(IArchive& rArc);
void UpdateDependencyCache(); void AddResource(const TString& rkName, const CAssetID& rkID, const CFourCC& rkType);
void UpdateDependencyCache() const;
void Cook(); void Cook();
void CompareOriginalAssetList(const std::list<CAssetID>& rkNewList); void CompareOriginalAssetList(const std::list<CAssetID>& rkNewList);
bool ContainsAsset(const CAssetID& rkID) const;
TWideString DefinitionPath(bool Relative) const; TWideString DefinitionPath(bool Relative) const;
TWideString CookedPackagePath(bool Relative) const; TWideString CookedPackagePath(bool Relative) const;
CResourceCollection* AddCollection(const TString& rkName);
void RemoveCollection(CResourceCollection *pCollection);
void RemoveCollection(u32 Index);
// Accessors // Accessors
inline TString Name() const { return mPakName; } inline TString Name() const { return mPakName; }
inline TWideString Path() const { return mPakPath; } inline TWideString Path() const { return mPakPath; }
inline CGameProject* Project() const { return mpProject; } inline CGameProject* Project() const { return mpProject; }
inline u32 NumCollections() const { return mCollections.size(); } inline u32 NumNamedResources() const { return mResources.size(); }
inline CResourceCollection* CollectionByIndex(u32 Idx) const { return mCollections[Idx]; } inline const SNamedResource& NamedResourceByIndex(u32 Idx) const { return mResources[Idx]; }
inline bool ContainsAsset(const CAssetID& rkID) const { return mCachedDependencies.find(rkID) != mCachedDependencies.end(); } inline bool NeedsRecook() const { return mNeedsRecook; }
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(); } inline void MarkDirty() { mNeedsRecook = true; Save(); UpdateDependencyCache(); }

View File

@ -176,35 +176,30 @@ void CPackageDependencyListBuilder::BuildDependencyList(bool AllowDuplicates, st
{ {
mEnableDuplicates = AllowDuplicates; mEnableDuplicates = AllowDuplicates;
// Iterate over all resource collections and resources and parse their dependencies // Iterate over all resources and parse their dependencies
for (u32 iCol = 0; iCol < mpPackage->NumCollections(); iCol++) 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); rOut.push_back(rkRes.ID);
CResourceEntry *pEntry = mpStore->FindEntry(rkRes.ID); continue;
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;
} }
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 ************ // ************ CPackageDependencyListBuilder ************
class CPackageDependencyListBuilder class CPackageDependencyListBuilder
{ {
CPackage *mpPackage; const CPackage *mpkPackage;
CResourceStore *mpStore; CResourceStore *mpStore;
EGame mGame; EGame mGame;
TResPtr<CWorld> mpWorld; TResPtr<CWorld> mpWorld;
@ -51,11 +51,11 @@ class CPackageDependencyListBuilder
bool mIsPlayerActor; bool mIsPlayerActor;
public: public:
CPackageDependencyListBuilder(CPackage *pPackage) CPackageDependencyListBuilder(const CPackage *pkPackage)
: mpPackage(pPackage) : mpkPackage(pkPackage)
, mGame(pPackage->Project()->Game()) , mGame(pkPackage->Project()->Game())
, mpStore(pPackage->Project()->ResourceStore()) , mpStore(pkPackage->Project()->ResourceStore())
, mCharacterUsageMap(pPackage->Project()->ResourceStore()) , mCharacterUsageMap(pkPackage->Project()->ResourceStore())
, mCurrentAreaHasDuplicates(false) , mCurrentAreaHasDuplicates(false)
, mIsPlayerActor(false) , mIsPlayerActor(false)
{ {

View File

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

View File

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