Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resource refactory #437

Merged
merged 25 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,10 @@ set(Source_Files__Resource
${CMAKE_CURRENT_SOURCE_DIR}/resource/ResourceLoader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/resource/ResourceLoader.h
${CMAKE_CURRENT_SOURCE_DIR}/resource/ResourceFactory.h
${CMAKE_CURRENT_SOURCE_DIR}/resource/ResourceFactory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/resource/ResourceFactoryBinary.h
${CMAKE_CURRENT_SOURCE_DIR}/resource/ResourceFactoryBinary.cpp
${CMAKE_CURRENT_SOURCE_DIR}/resource/ResourceFactoryXML.h
${CMAKE_CURRENT_SOURCE_DIR}/resource/ResourceFactoryXML.cpp
)
source_group("resource" FILES ${Source_Files__Resource})

Expand Down
9 changes: 6 additions & 3 deletions src/resource/File.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <string>
#include <variant>
#include <vector>
#include <memory>
#include <stdint.h>
Expand All @@ -11,22 +12,24 @@
namespace LUS {
class Archive;

#define RESOURCE_FORMAT_BINARY 0
#define RESOURCE_FORMAT_XML 1

struct ResourceInitData {
std::string Path;
Endianness ByteOrder;
uint32_t Type;
int32_t ResourceVersion;
uint64_t Id;
bool IsCustom;
bool IsXml;
uint32_t Format;
};

struct File {
std::shared_ptr<Archive> Parent;
std::shared_ptr<ResourceInitData> InitData;
std::shared_ptr<std::vector<char>> Buffer;
std::shared_ptr<tinyxml2::XMLDocument> XmlDocument;
std::shared_ptr<BinaryReader> Reader;
std::variant<std::shared_ptr<tinyxml2::XMLDocument>, std::shared_ptr<BinaryReader>> Reader;
bool IsLoaded = false;
};
} // namespace LUS
22 changes: 0 additions & 22 deletions src/resource/ResourceFactory.cpp

This file was deleted.

19 changes: 4 additions & 15 deletions src/resource/ResourceFactory.h
Original file line number Diff line number Diff line change
@@ -1,26 +1,15 @@
#pragma once

#include <memory>
#include "utils/binarytools/BinaryReader.h"
#include "utils/binarytools/BinaryWriter.h"
#include <tinyxml2.h>
#include "File.h"
#include "Resource.h"

namespace LUS {
class ResourceManager;
class ResourceFactory {
public:
virtual std::shared_ptr<IResource> ReadResource(std::shared_ptr<ResourceInitData> initData,
std::shared_ptr<BinaryReader> reader) = 0;
virtual std::shared_ptr<IResource> ReadResourceXML(std::shared_ptr<ResourceInitData> initData,
tinyxml2::XMLElement* reader);
};
virtual std::shared_ptr<IResource> ReadResource(std::shared_ptr<File> file) = 0;

class ResourceVersionFactory {
public:
virtual void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource);
virtual void ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource);
virtual void WriteFileBinary(std::shared_ptr<BinaryWriter> writer, std::shared_ptr<IResource> resource);
virtual void WriteFileXML(tinyxml2::XMLElement* writer, std::shared_ptr<IResource> resource);
protected:
virtual bool FileHasValidFormatAndReader(std::shared_ptr<File> file) = 0;
};
} // namespace LUS
19 changes: 19 additions & 0 deletions src/resource/ResourceFactoryBinary.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "ResourceFactoryBinary.h"
#include <variant>
#include "spdlog/spdlog.h"

namespace LUS {
bool ResourceFactoryBinary::FileHasValidFormatAndReader(std::shared_ptr<File> file) {
if (file->InitData->Format != RESOURCE_FORMAT_BINARY) {
SPDLOG_ERROR("resource file format does not match factory format.");
return false;
}

if (!std::holds_alternative<std::shared_ptr<BinaryReader>>(file->Reader)) {
SPDLOG_ERROR("Failed to load resource: File has Reader ({} - {})", file->InitData->Type, file->InitData->Path);
return false;
}

return true;
};
} // namespace LUS
10 changes: 10 additions & 0 deletions src/resource/ResourceFactoryBinary.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

#include "ResourceFactory.h"

namespace LUS {
class ResourceFactoryBinary : public ResourceFactory {
protected:
bool FileHasValidFormatAndReader(std::shared_ptr<File> file) override;
};
} // namespace LUS
19 changes: 19 additions & 0 deletions src/resource/ResourceFactoryXML.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "ResourceFactoryXML.h"
#include "spdlog/spdlog.h"

namespace LUS {
bool ResourceFactoryXML::FileHasValidFormatAndReader(std::shared_ptr<File> file) {
if (file->InitData->Format != RESOURCE_FORMAT_XML) {
SPDLOG_ERROR("resource file format does not match factory format.");
return false;
}

if (!std::holds_alternative<std::shared_ptr<tinyxml2::XMLDocument>>(file->Reader)) {
SPDLOG_ERROR("Failed to load resource: File has no XML document ({} - {})", file->InitData->Type,
file->InitData->Path);
return false;
}

return true;
};
} // namespace LUS
10 changes: 10 additions & 0 deletions src/resource/ResourceFactoryXML.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

#include "ResourceFactory.h"

namespace LUS {
class ResourceFactoryXML : public ResourceFactory {
protected:
bool FileHasValidFormatAndReader(std::shared_ptr<File> file) override;
};
} // namespace LUS
108 changes: 67 additions & 41 deletions src/resource/ResourceLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,69 +23,95 @@ ResourceLoader::~ResourceLoader() {
}

void ResourceLoader::RegisterGlobalResourceFactories() {
RegisterResourceFactory(static_cast<uint32_t>(ResourceType::Texture), std::make_shared<TextureFactory>());
RegisterResourceFactory(static_cast<uint32_t>(ResourceType::Vertex), std::make_shared<VertexFactory>());
RegisterResourceFactory(static_cast<uint32_t>(ResourceType::DisplayList), std::make_shared<DisplayListFactory>());
RegisterResourceFactory(static_cast<uint32_t>(ResourceType::Matrix), std::make_shared<MatrixFactory>());
RegisterResourceFactory(static_cast<uint32_t>(ResourceType::Array), std::make_shared<ArrayFactory>());
RegisterResourceFactory(static_cast<uint32_t>(ResourceType::Blob), std::make_shared<BlobFactory>());
RegisterResourceFactory(std::make_shared<ResourceFactoryBinaryTextureV0>(), RESOURCE_FORMAT_BINARY, "Texture",
static_cast<uint32_t>(ResourceType::Texture), 0);
RegisterResourceFactory(std::make_shared<ResourceFactoryBinaryTextureV1>(), RESOURCE_FORMAT_BINARY, "Texture",
static_cast<uint32_t>(ResourceType::Texture), 1);
RegisterResourceFactory(std::make_shared<ResourceFactoryBinaryVertexV0>(), RESOURCE_FORMAT_BINARY, "Vertex",
static_cast<uint32_t>(ResourceType::Vertex), 0);
RegisterResourceFactory(std::make_shared<ResourceFactoryXMLVertexV0>(), RESOURCE_FORMAT_XML, "Vertex",
static_cast<uint32_t>(ResourceType::Vertex), 0);
RegisterResourceFactory(std::make_shared<ResourceFactoryBinaryDisplayListV0>(), RESOURCE_FORMAT_BINARY,
"DisplayList", static_cast<uint32_t>(ResourceType::DisplayList), 0);
RegisterResourceFactory(std::make_shared<ResourceFactoryXMLDisplayListV0>(), RESOURCE_FORMAT_XML, "DisplayList",
static_cast<uint32_t>(ResourceType::DisplayList), 0);
RegisterResourceFactory(std::make_shared<ResourceFactoryBinaryMatrixV0>(), RESOURCE_FORMAT_BINARY, "Matrix",
static_cast<uint32_t>(ResourceType::Matrix), 0);
RegisterResourceFactory(std::make_shared<ResourceFactoryBinaryArrayV0>(), RESOURCE_FORMAT_BINARY, "Array",
static_cast<uint32_t>(ResourceType::Array), 0);
RegisterResourceFactory(std::make_shared<ResourceFactoryBinaryBlobV0>(), RESOURCE_FORMAT_BINARY, "Blob",
static_cast<uint32_t>(ResourceType::Blob), 0);
}

bool ResourceLoader::RegisterResourceFactory(uint32_t resourceType, std::shared_ptr<ResourceFactory> factory) {
if (mFactories.contains(resourceType)) {
bool ResourceLoader::RegisterResourceFactory(std::shared_ptr<ResourceFactory> factory, uint32_t format,
std::string typeName, uint32_t type, uint32_t version) {
if (mResourceTypes.contains(typeName)) {
if (mResourceTypes[typeName] != type) {
SPDLOG_ERROR("Failed to register resource factory: conflicting types for name {}", typeName);
return false;
}
} else {
mResourceTypes[typeName] = type;
}

ResourceFactoryKey key{ .resourceFormat = format, .resourceType = type, .resourceVersion = version };
if (mFactories.contains(key)) {
SPDLOG_ERROR("Failed to register resource factory: factory with key {}{}{} already exists", format, type,
version);
return false;
}
mFactories[key] = factory;

mFactories[resourceType] = factory;
return true;
}

uint32_t ResourceLoader::GetVersionFromString(const std::string& version) {
return mFactoriesTypes[version];
std::shared_ptr<ResourceFactory> ResourceLoader::GetFactory(uint32_t format, uint32_t type, uint32_t version) {
ResourceFactoryKey key{ .resourceFormat = format, .resourceType = type, .resourceVersion = version };
if (!mFactories.contains(key)) {
SPDLOG_ERROR("Could not find resource factory with key {}{}{}", format, type, version);
return nullptr;
}

return mFactories[key];
}

std::shared_ptr<IResource> ResourceLoader::LoadResource(std::shared_ptr<File> fileToLoad) {
std::shared_ptr<IResource> result = nullptr;
std::shared_ptr<ResourceFactory> ResourceLoader::GetFactory(uint32_t format, std::string typeName, uint32_t version) {
if (!mResourceTypes.contains(typeName)) {
SPDLOG_ERROR("Could not find resource type for name {}", typeName);
return nullptr;
}

return GetFactory(format, mResourceTypes[typeName], version);
}

std::shared_ptr<IResource> ResourceLoader::LoadResource(std::shared_ptr<File> fileToLoad) {
if (fileToLoad == nullptr) {
SPDLOG_ERROR("Failed to load resource: File not loaded");
return result;
return nullptr;
}

if (fileToLoad->InitData == nullptr) {
SPDLOG_ERROR("Failed to load resource: ResourceInitData not loaded");
return result;
return nullptr;
}

auto factory = mFactories[fileToLoad->InitData->Type];
auto factory =
GetFactory(fileToLoad->InitData->Format, fileToLoad->InitData->Type, fileToLoad->InitData->ResourceVersion);
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load resource: Factory does not exist ({} - {})", fileToLoad->InitData->Type,
fileToLoad->InitData->Path);
}

if (fileToLoad->InitData->IsXml) {
if (fileToLoad->XmlDocument == nullptr) {
SPDLOG_ERROR("Failed to load resource: File has no XML document ({} - {})", fileToLoad->InitData->Type,
fileToLoad->InitData->Path);
return result;
}

result = factory->ReadResourceXML(fileToLoad->InitData, fileToLoad->XmlDocument->FirstChildElement());
} else {
if (fileToLoad->Reader == nullptr) {
SPDLOG_ERROR("Failed to load resource: File has Reader ({} - {})", fileToLoad->InitData->Type,
fileToLoad->InitData->Path);
return result;
}

result = factory->ReadResource(fileToLoad->InitData, fileToLoad->Reader);
SPDLOG_ERROR("Failed to load resource: Factory does not exist.\n"
"Path: {}\n"
"Type: {}\n"
"Format: {}\n"
"Version: {}",
fileToLoad->InitData->Path, fileToLoad->InitData->Type, fileToLoad->InitData->Format,
fileToLoad->InitData->ResourceVersion);
return nullptr;
}

if (result == nullptr) {
SPDLOG_ERROR("Failed to load resource of type {} \"{}\"", fileToLoad->InitData->Type,
fileToLoad->InitData->Path);
}
return factory->ReadResource(fileToLoad);
}

return result;
uint32_t ResourceLoader::GetResourceType(const std::string& type) {
return mResourceTypes.contains(type) ? mResourceTypes[type] : static_cast<uint32_t>(ResourceType::None);
}
} // namespace LUS
29 changes: 26 additions & 3 deletions src/resource/ResourceLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,42 @@
namespace LUS {
struct File;

struct ResourceFactoryKey {
uint32_t resourceFormat;
uint32_t resourceType;
uint32_t resourceVersion;

bool operator==(const ResourceFactoryKey& o) const {
return (resourceFormat == o.resourceFormat) && (resourceType == o.resourceType) &&
(resourceVersion == o.resourceVersion);
}
};

struct ResourceFactoryKeyHash {
std::size_t operator()(const ResourceFactoryKey& key) const {
return std::hash<int>()(key.resourceFormat) ^ std::hash<int>()(key.resourceType) ^
std::hash<int>()(key.resourceVersion);
}
};

class ResourceLoader {
public:
ResourceLoader();
~ResourceLoader();

std::shared_ptr<IResource> LoadResource(std::shared_ptr<File> fileToLoad);
bool RegisterResourceFactory(uint32_t resourceType, std::shared_ptr<ResourceFactory> factory);
uint32_t GetVersionFromString(const std::string& version);
bool RegisterResourceFactory(std::shared_ptr<ResourceFactory> factory, uint32_t format, std::string typeName,
uint32_t type, uint32_t version);

uint32_t GetResourceType(const std::string& type);

protected:
void RegisterGlobalResourceFactories();
std::shared_ptr<ResourceFactory> GetFactory(uint32_t format, uint32_t type, uint32_t version);
std::shared_ptr<ResourceFactory> GetFactory(uint32_t format, std::string typeName, uint32_t version);

private:
std::unordered_map<uint32_t, std::shared_ptr<ResourceFactory>> mFactories;
std::unordered_map<std::string, uint32_t> mResourceTypes;
std::unordered_map<ResourceFactoryKey, std::shared_ptr<ResourceFactory>, ResourceFactoryKeyHash> mFactories;
};
} // namespace LUS
Loading
Loading