mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-06-06 22:53:35 +00:00
Added resource metadata files
This commit is contained in:
parent
5a398423e1
commit
4b73d0abcc
Binary file not shown.
@ -9,7 +9,7 @@ bool CAssetNameMap::LoadAssetNames(TString Path /*= ""*/)
|
|||||||
|
|
||||||
if (Reader.IsValid())
|
if (Reader.IsValid())
|
||||||
{
|
{
|
||||||
CAssetID FileIDLength = CAssetID::GameIDLength(Reader.Game());
|
EIDLength FileIDLength = CAssetID::GameIDLength(Reader.Game());
|
||||||
|
|
||||||
if (FileIDLength == mIDLength)
|
if (FileIDLength == mIDLength)
|
||||||
{
|
{
|
||||||
|
@ -531,6 +531,10 @@ void CGameExporter::ExportResourceEditorData()
|
|||||||
It->Save(true);
|
It->Save(true);
|
||||||
else
|
else
|
||||||
It->UpdateDependencies();
|
It->UpdateDependencies();
|
||||||
|
|
||||||
|
// Set flags, save metadata
|
||||||
|
It->SetFlag(eREF_IsRetroResource);
|
||||||
|
It->SaveMetadata(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ CResourceEntry::CResourceEntry(CResourceStore *pStore, const CAssetID& rkID,
|
|||||||
, mID(rkID)
|
, mID(rkID)
|
||||||
, mpDirectory(nullptr)
|
, mpDirectory(nullptr)
|
||||||
, mName(rkFilename)
|
, mName(rkFilename)
|
||||||
|
, mMetadataDirty(false)
|
||||||
, mCachedSize(-1)
|
, mCachedSize(-1)
|
||||||
, mCachedUppercaseName(rkFilename.ToUpper())
|
, mCachedUppercaseName(rkFilename.ToUpper())
|
||||||
{
|
{
|
||||||
@ -35,12 +36,87 @@ CResourceEntry::~CResourceEntry()
|
|||||||
if (mpDependencies) delete mpDependencies;
|
if (mpDependencies) delete mpDependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CResourceEntry::SerializeCacheData(IArchive& rArc)
|
bool CResourceEntry::LoadMetadata()
|
||||||
{
|
{
|
||||||
|
ASSERT(!mMetadataDirty);
|
||||||
|
TString Path = MetadataFilePath();
|
||||||
|
|
||||||
|
if (FileUtil::Exists(Path))
|
||||||
|
{
|
||||||
|
// Validate file
|
||||||
|
CFileInStream MetaFile(Path, IOUtil::eBigEndian);
|
||||||
|
u32 Magic = MetaFile.ReadLong();
|
||||||
|
|
||||||
|
if (Magic == FOURCC('META'))
|
||||||
|
{
|
||||||
|
CSerialVersion Version(MetaFile);
|
||||||
|
CBinaryReader Reader(&MetaFile, Version);
|
||||||
|
SerializeMetadata(Reader);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log::Error(Path + ": Failed to load metadata file, invalid magic: " + CFourCC(Magic).ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CResourceEntry::SaveMetadata(bool ForceSave /*= false*/)
|
||||||
|
{
|
||||||
|
if (mMetadataDirty || ForceSave)
|
||||||
|
{
|
||||||
|
TString Path = MetadataFilePath();
|
||||||
|
TString Dir = Path.GetFileDirectory();
|
||||||
|
FileUtil::MakeDirectory(Dir);
|
||||||
|
|
||||||
|
CFileOutStream MetaFile(Path, IOUtil::eBigEndian);
|
||||||
|
|
||||||
|
if (MetaFile.IsValid())
|
||||||
|
{
|
||||||
|
MetaFile.WriteLong(0); // Magic dummy
|
||||||
|
|
||||||
|
CSerialVersion Version(IArchive::skCurrentArchiveVersion, 0, Game());
|
||||||
|
Version.Write(MetaFile);
|
||||||
|
|
||||||
|
// Scope the binary writer to ensure it finishes before we go back to write the magic value
|
||||||
|
{
|
||||||
|
CBinaryWriter Writer(&MetaFile, Version);
|
||||||
|
SerializeMetadata(Writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaFile.GoTo(0);
|
||||||
|
MetaFile.WriteLong(FOURCC('META'));
|
||||||
|
|
||||||
|
mMetadataDirty = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CResourceEntry::SerializeMetadata(IArchive& rArc)
|
||||||
|
{
|
||||||
|
// Serialize ID. If we already have a valid ID then don't allow the file to override it.
|
||||||
|
CAssetID ID = mID;
|
||||||
|
rArc << SERIAL("AssetID", ID);
|
||||||
|
|
||||||
|
if (rArc.IsReader() && !mID.IsValid())
|
||||||
|
mID = ID;
|
||||||
|
|
||||||
|
// Serialize type
|
||||||
|
rArc << SERIAL("Type", mpTypeInfo);
|
||||||
|
|
||||||
|
// Serialize flags
|
||||||
u32 Flags = mFlags & eREF_SavedFlags;
|
u32 Flags = mFlags & eREF_SavedFlags;
|
||||||
rArc << SERIAL_AUTO(Flags);
|
rArc << SERIAL_AUTO(Flags);
|
||||||
if (rArc.IsReader()) mFlags = Flags & eREF_SavedFlags;
|
if (rArc.IsReader()) mFlags = Flags & eREF_SavedFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CResourceEntry::SerializeCacheData(IArchive& rArc)
|
||||||
|
{
|
||||||
// Note: If the dependency tree format is changed this should be adjusted so that
|
// Note: If the dependency tree format is changed this should be adjusted so that
|
||||||
// we regenerate the dependencies from scratch instead of reading the tree if the
|
// we regenerate the dependencies from scratch instead of reading the tree if the
|
||||||
// file version number is too low
|
// file version number is too low
|
||||||
@ -92,12 +168,12 @@ bool CResourceEntry::HasCookedVersion() const
|
|||||||
|
|
||||||
TString CResourceEntry::RawAssetPath(bool Relative) const
|
TString CResourceEntry::RawAssetPath(bool Relative) const
|
||||||
{
|
{
|
||||||
return CookedAssetPath(Relative) + ".raw";
|
return CookedAssetPath(Relative) + ".rsraw";
|
||||||
}
|
}
|
||||||
|
|
||||||
TString CResourceEntry::RawExtension() const
|
TString CResourceEntry::RawExtension() const
|
||||||
{
|
{
|
||||||
return CookedExtension().ToString() + ".raw";
|
return CookedExtension().ToString() + ".rsraw";
|
||||||
}
|
}
|
||||||
|
|
||||||
TString CResourceEntry::CookedAssetPath(bool Relative) const
|
TString CResourceEntry::CookedAssetPath(bool Relative) const
|
||||||
@ -113,6 +189,11 @@ CFourCC CResourceEntry::CookedExtension() const
|
|||||||
return mpTypeInfo->CookedExtension(Game());
|
return mpTypeInfo->CookedExtension(Game());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TString CResourceEntry::MetadataFilePath(bool Relative) const
|
||||||
|
{
|
||||||
|
return CookedAssetPath(Relative) + ".rsmeta";
|
||||||
|
}
|
||||||
|
|
||||||
bool CResourceEntry::IsInDirectory(CVirtualDirectory *pDir) const
|
bool CResourceEntry::IsInDirectory(CVirtualDirectory *pDir) const
|
||||||
{
|
{
|
||||||
CVirtualDirectory *pParentDir = mpDirectory;
|
CVirtualDirectory *pParentDir = mpDirectory;
|
||||||
@ -146,7 +227,7 @@ bool CResourceEntry::NeedsRecook() const
|
|||||||
// toggled to arbitrarily flag any asset for recook.
|
// toggled to arbitrarily flag any asset for recook.
|
||||||
if (!HasRawVersion()) return false;
|
if (!HasRawVersion()) return false;
|
||||||
if (!HasCookedVersion()) return true;
|
if (!HasCookedVersion()) return true;
|
||||||
if (mFlags.HasFlag(eREF_NeedsRecook)) return true;
|
if (HasFlag(eREF_NeedsRecook)) return true;
|
||||||
return (FileUtil::LastModifiedTime(CookedAssetPath()) < FileUtil::LastModifiedTime(RawAssetPath()));
|
return (FileUtil::LastModifiedTime(CookedAssetPath()) < FileUtil::LastModifiedTime(RawAssetPath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +269,7 @@ bool CResourceEntry::Save(bool SkipCacheSave /*= false*/)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mFlags |= eREF_NeedsRecook;
|
SetFlag(eREF_NeedsRecook);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This resource type doesn't have a raw format; save cooked instead
|
// This resource type doesn't have a raw format; save cooked instead
|
||||||
@ -203,11 +284,10 @@ bool CResourceEntry::Save(bool SkipCacheSave /*= false*/)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resource has been saved; now make sure dependencies, cache data, and packages are all up to date
|
// Resource has been saved; now make sure metadata, dependencies, and packages are all up to date
|
||||||
mFlags |= eREF_HasBeenModified;
|
SetFlag(eREF_HasBeenModified);
|
||||||
|
SaveMetadata();
|
||||||
UpdateDependencies();
|
UpdateDependencies();
|
||||||
mpStore->SetCacheDataDirty();
|
|
||||||
|
|
||||||
if (!SkipCacheSave)
|
if (!SkipCacheSave)
|
||||||
{
|
{
|
||||||
@ -250,9 +330,9 @@ bool CResourceEntry::Cook()
|
|||||||
|
|
||||||
if (Success)
|
if (Success)
|
||||||
{
|
{
|
||||||
mFlags &= ~eREF_NeedsRecook;
|
ClearFlag(eREF_NeedsRecook);
|
||||||
mFlags |= eREF_HasBeenModified;
|
SetFlag(eREF_HasBeenModified);
|
||||||
mpStore->SetCacheDataDirty();
|
SaveMetadata();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
@ -458,3 +538,21 @@ EGame CResourceEntry::Game() const
|
|||||||
{
|
{
|
||||||
return mpStore ? mpStore->Game() : eUnknownGame;
|
return mpStore ? mpStore->Game() : eUnknownGame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CResourceEntry::SetFlag(EResEntryFlag Flag)
|
||||||
|
{
|
||||||
|
if (!HasFlag(Flag))
|
||||||
|
{
|
||||||
|
mFlags.SetFlag(Flag);
|
||||||
|
mMetadataDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CResourceEntry::ClearFlag(EResEntryFlag Flag)
|
||||||
|
{
|
||||||
|
if (HasFlag(Flag))
|
||||||
|
{
|
||||||
|
mFlags.ClearFlag(Flag);
|
||||||
|
mMetadataDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,12 +17,14 @@ class CDependencyTree;
|
|||||||
enum EResEntryFlag
|
enum EResEntryFlag
|
||||||
{
|
{
|
||||||
eREF_NeedsRecook = 0x00000001, // Resource has been updated but not recooked
|
eREF_NeedsRecook = 0x00000001, // Resource has been updated but not recooked
|
||||||
// UNUSED = 0x00000002,
|
eREF_IsRetroResource = 0x00000002, // Resource is from the original game, not user-created
|
||||||
eREF_Hidden = 0x00000004, // Resource is hidden, doesn't show up in resource browser
|
eREF_Hidden = 0x00000004, // Resource is hidden, doesn't show up in resource browser
|
||||||
eREF_HasBeenModified = 0x00000008, // Resource has been modified and resaved by the user
|
eREF_HasBeenModified = 0x00000008, // Resource has been modified and resaved by the user
|
||||||
eREF_IsUserResource = 0x00000010, // Resource was created by the user (i.e. isn't a Retro Studios asset)
|
eREF_AutoResName = 0x00000010, // Resource name is auto-generated
|
||||||
|
eREF_AutoResDir = 0x00000020, // Resource directory name is auto-generated
|
||||||
// Flags that save to the cache file
|
// Flags that save to the cache file
|
||||||
eREF_SavedFlags = eREF_NeedsRecook | eREF_Hidden | eREF_HasBeenModified | eREF_IsUserResource
|
eREF_SavedFlags = eREF_NeedsRecook | eREF_IsRetroResource | eREF_Hidden | eREF_HasBeenModified |
|
||||||
|
eREF_AutoResName | eREF_AutoResDir
|
||||||
};
|
};
|
||||||
DECLARE_FLAGS(EResEntryFlag, FResEntryFlags)
|
DECLARE_FLAGS(EResEntryFlag, FResEntryFlags)
|
||||||
|
|
||||||
@ -37,6 +39,7 @@ class CResourceEntry
|
|||||||
TString mName;
|
TString mName;
|
||||||
FResEntryFlags mFlags;
|
FResEntryFlags mFlags;
|
||||||
|
|
||||||
|
mutable bool mMetadataDirty;
|
||||||
mutable u64 mCachedSize;
|
mutable u64 mCachedSize;
|
||||||
mutable TString mCachedUppercaseName; // This is used to speed up case-insensitive sorting and filtering.
|
mutable TString mCachedUppercaseName; // This is used to speed up case-insensitive sorting and filtering.
|
||||||
|
|
||||||
@ -46,6 +49,9 @@ public:
|
|||||||
EResType Type);
|
EResType Type);
|
||||||
~CResourceEntry();
|
~CResourceEntry();
|
||||||
|
|
||||||
|
bool LoadMetadata();
|
||||||
|
bool SaveMetadata(bool ForceSave = false);
|
||||||
|
void SerializeMetadata(IArchive& rArc);
|
||||||
void SerializeCacheData(IArchive& rArc);
|
void SerializeCacheData(IArchive& rArc);
|
||||||
void UpdateDependencies();
|
void UpdateDependencies();
|
||||||
|
|
||||||
@ -55,6 +61,7 @@ public:
|
|||||||
TString RawExtension() const;
|
TString RawExtension() const;
|
||||||
TString CookedAssetPath(bool Relative = false) const;
|
TString CookedAssetPath(bool Relative = false) const;
|
||||||
CFourCC CookedExtension() const;
|
CFourCC CookedExtension() const;
|
||||||
|
TString MetadataFilePath(bool Relative = false) const;
|
||||||
bool IsInDirectory(CVirtualDirectory *pDir) const;
|
bool IsInDirectory(CVirtualDirectory *pDir) const;
|
||||||
u64 Size() const;
|
u64 Size() const;
|
||||||
bool NeedsRecook() const;
|
bool NeedsRecook() const;
|
||||||
@ -68,9 +75,14 @@ public:
|
|||||||
CGameProject* Project() const;
|
CGameProject* Project() const;
|
||||||
EGame Game() const;
|
EGame Game() const;
|
||||||
|
|
||||||
|
void SetFlag(EResEntryFlag Flag);
|
||||||
|
void ClearFlag(EResEntryFlag Flag);
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
void SetDirty() { mFlags.SetFlag(eREF_NeedsRecook); }
|
inline void SetDirty() { SetFlag(eREF_NeedsRecook); }
|
||||||
void SetHidden(bool Hidden) { Hidden ? mFlags.SetFlag(eREF_Hidden) : mFlags.ClearFlag(eREF_Hidden); }
|
inline void SetHidden(bool Hidden) { Hidden ? SetFlag(eREF_Hidden) : ClearFlag(eREF_Hidden); }
|
||||||
|
inline bool HasFlag(EResEntryFlag Flag) const { return mFlags.HasFlag(Flag); }
|
||||||
|
inline bool IsHidden() const { return HasFlag(eREF_Hidden); }
|
||||||
|
|
||||||
inline bool IsLoaded() const { return mpResource != nullptr; }
|
inline bool IsLoaded() const { return mpResource != nullptr; }
|
||||||
inline bool IsCategorized() const { return mpDirectory && mpDirectory->FullPath() != "Uncategorized/"; }
|
inline bool IsCategorized() const { return mpDirectory && mpDirectory->FullPath() != "Uncategorized/"; }
|
||||||
@ -85,7 +97,6 @@ public:
|
|||||||
inline TString Name() const { return mName; }
|
inline TString Name() const { return mName; }
|
||||||
inline const TString& UppercaseName() const { return mCachedUppercaseName; }
|
inline const TString& UppercaseName() const { return mCachedUppercaseName; }
|
||||||
inline EResType ResourceType() const { return mpTypeInfo->Type(); }
|
inline EResType ResourceType() const { return mpTypeInfo->Type(); }
|
||||||
inline bool IsHidden() const { return mFlags.HasFlag(eREF_Hidden); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CResource* InternalLoad(IInputStream& rInput);
|
CResource* InternalLoad(IInputStream& rInput);
|
||||||
|
@ -138,7 +138,7 @@ bool CResourceStore::LoadCacheFile()
|
|||||||
// Cache header
|
// Cache header
|
||||||
CFourCC Magic(CacheFile);
|
CFourCC Magic(CacheFile);
|
||||||
|
|
||||||
if (Magic != "CACH")
|
if (Magic != FOURCC('CACH'))
|
||||||
{
|
{
|
||||||
Log::Error("Invalid resource cache data magic: " + Magic.ToString());
|
Log::Error("Invalid resource cache data magic: " + Magic.ToString());
|
||||||
return false;
|
return false;
|
||||||
@ -183,8 +183,8 @@ bool CResourceStore::SaveCacheFile()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cache header
|
// Cache header
|
||||||
CFourCC("CACH").Write(CacheFile);
|
CacheFile.WriteLong(0); // Magic dummy. Magic isn't written until the rest of the file is saved successfully.
|
||||||
CSerialVersion Version(0, 0, mGame);
|
CSerialVersion Version(IArchive::skCurrentArchiveVersion, 0, mGame);
|
||||||
Version.Write(CacheFile);
|
Version.Write(CacheFile);
|
||||||
|
|
||||||
u32 ResCountOffset = CacheFile.Tell();
|
u32 ResCountOffset = CacheFile.Tell();
|
||||||
@ -216,6 +216,8 @@ bool CResourceStore::SaveCacheFile()
|
|||||||
|
|
||||||
CacheFile.Seek(ResCountOffset, SEEK_SET);
|
CacheFile.Seek(ResCountOffset, SEEK_SET);
|
||||||
CacheFile.WriteLong(ResCount);
|
CacheFile.WriteLong(ResCount);
|
||||||
|
CacheFile.Seek(0, SEEK_SET);
|
||||||
|
CacheFile.WriteLong( FOURCC('CACH') );
|
||||||
mCacheFileDirty = false;
|
mCacheFileDirty = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -295,7 +297,7 @@ void CResourceStore::ConditionalDeleteDirectory(CVirtualDirectory *pDir)
|
|||||||
{
|
{
|
||||||
if (pDir->IsEmpty())
|
if (pDir->IsEmpty())
|
||||||
{
|
{
|
||||||
// If this directory is part of the project, then we should delete the corresponding filesystem directories
|
// If this directory is part of the project, then we should delete the corresponding filesystem directory
|
||||||
if (pDir->GetRoot() == mpDatabaseRoot && !pDir->IsRoot())
|
if (pDir->GetRoot() == mpDatabaseRoot && !pDir->IsRoot())
|
||||||
{
|
{
|
||||||
FileUtil::DeleteDirectory(ResourcesDir() + pDir->FullPath(), true);
|
FileUtil::DeleteDirectory(ResourcesDir() + pDir->FullPath(), true);
|
||||||
@ -338,6 +340,7 @@ CResourceEntry* CResourceStore::RegisterResource(const CAssetID& rkID, EResType
|
|||||||
if (IsValidResourcePath(rkDir, rkName))
|
if (IsValidResourcePath(rkDir, rkName))
|
||||||
{
|
{
|
||||||
pEntry = new CResourceEntry(this, rkID, rkDir, rkName, Type);
|
pEntry = new CResourceEntry(this, rkID, rkDir, rkName, Type);
|
||||||
|
pEntry->LoadMetadata();
|
||||||
mResourceEntries[rkID] = pEntry;
|
mResourceEntries[rkID] = pEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user