feat(Resources): Add ResourcePackage system for asset bundling
- Implement ResourcePackageBuilder for creating .xcp packages - Implement ResourcePackage for reading packaged assets - Add unit tests for package builder and package reader
This commit is contained in:
100
engine/include/XCEngine/Resources/ResourcePackage.h
Normal file
100
engine/include/XCEngine/Resources/ResourcePackage.h
Normal file
@@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include "ResourceTypes.h"
|
||||
#include "../Containers/String.h"
|
||||
#include "../Containers/Array.h"
|
||||
#include "../Core/Types.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Resources {
|
||||
|
||||
struct PackageFileEntry {
|
||||
Containers::String relativePath;
|
||||
size_t size;
|
||||
Core::uint64 checksum;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
class ResourcePackageBuilder {
|
||||
public:
|
||||
ResourcePackageBuilder();
|
||||
~ResourcePackageBuilder();
|
||||
|
||||
bool AddFile(const Containers::String& sourcePath, const Containers::String& relativePath);
|
||||
bool AddDirectory(const Containers::String& sourceDir, const Containers::String& relativeBase = "");
|
||||
|
||||
void SetOutputPath(const Containers::String& path) { m_outputPath = path; }
|
||||
const Containers::String& GetOutputPath() const { return m_outputPath; }
|
||||
|
||||
bool Build();
|
||||
|
||||
float GetProgress() const { return m_progress; }
|
||||
const Containers::String& GetError() const { return m_error; }
|
||||
|
||||
private:
|
||||
Core::uint64 CalculateChecksum(const void* data, size_t size);
|
||||
bool WriteHeader(FILE* file, size_t dataOffset);
|
||||
bool WriteManifest(FILE* file);
|
||||
bool WriteData(FILE* file);
|
||||
|
||||
struct FileEntry {
|
||||
Containers::String sourcePath;
|
||||
Containers::String relativePath;
|
||||
size_t size;
|
||||
Core::uint64 checksum;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
Containers::String m_outputPath;
|
||||
Containers::Array<FileEntry> m_files;
|
||||
float m_progress = 0.0f;
|
||||
Containers::String m_error;
|
||||
};
|
||||
|
||||
class ResourcePackage {
|
||||
public:
|
||||
ResourcePackage();
|
||||
~ResourcePackage();
|
||||
|
||||
bool Open(const Containers::String& packagePath);
|
||||
void Close();
|
||||
|
||||
bool IsValid() const { return m_isValid; }
|
||||
|
||||
bool Exists(const Containers::String& relativePath) const;
|
||||
|
||||
Containers::Array<Core::uint8> Read(const Containers::String& relativePath) const;
|
||||
size_t GetSize(const Containers::String& relativePath) const;
|
||||
|
||||
void Enumerate(const Containers::String& pattern, Containers::Array<Containers::String>& outFiles) const;
|
||||
|
||||
struct PackageInfo {
|
||||
Containers::String path;
|
||||
Core::uint16 version;
|
||||
size_t fileCount;
|
||||
size_t totalSize;
|
||||
};
|
||||
|
||||
const PackageInfo& GetInfo() const { return m_info; }
|
||||
|
||||
private:
|
||||
bool ReadHeader(FILE* file);
|
||||
bool ReadManifest(FILE* file);
|
||||
|
||||
bool m_isValid = false;
|
||||
PackageInfo m_info;
|
||||
|
||||
Containers::String m_packagePath;
|
||||
size_t m_dataOffset;
|
||||
|
||||
struct FileEntryInternal {
|
||||
Containers::String path;
|
||||
size_t size;
|
||||
size_t offset;
|
||||
Core::uint64 checksum;
|
||||
};
|
||||
Containers::Array<FileEntryInternal> m_entries;
|
||||
};
|
||||
|
||||
} // namespace Resources
|
||||
} // namespace XCEngine
|
||||
Reference in New Issue
Block a user