Files
Seele/src/Engine/Asset/AssetRegistry.cpp
T

418 lines
12 KiB
C++
Raw Normal View History

2020-06-02 11:46:18 +02:00
#include "AssetRegistry.h"
#include "MeshAsset.h"
2022-04-13 13:01:35 +02:00
#include "FontAsset.h"
2020-06-02 11:46:18 +02:00
#include "TextureAsset.h"
2023-01-21 18:43:21 +01:00
#include "MaterialAsset.h"
2023-02-13 14:56:13 +01:00
#include "MaterialInstanceAsset.h"
#include "Graphics/Mesh.h"
2020-06-02 11:46:18 +02:00
#include "Graphics/Graphics.h"
2021-01-19 15:30:00 +01:00
#include "Window/WindowManager.h"
2021-04-01 16:40:14 +02:00
#include "MeshAsset.h"
2023-01-21 18:43:21 +01:00
#include <nlohmann/json.hpp>
2020-08-11 22:38:19 +02:00
#include <iostream>
2023-08-26 15:19:12 +02:00
#include <fstream>
2020-06-02 11:46:18 +02:00
using namespace Seele;
2023-08-26 15:19:12 +02:00
AssetRegistry* instance = new AssetRegistry();
2023-02-01 22:13:04 +01:00
2020-06-02 11:46:18 +02:00
AssetRegistry::~AssetRegistry()
{
2023-02-13 14:56:13 +01:00
delete assetRoot;
2020-06-02 11:46:18 +02:00
}
2023-11-07 16:55:13 +01:00
void AssetRegistry::init(std::filesystem::path rootFolder, Gfx::PGraphics graphics)
2020-06-02 11:46:18 +02:00
{
2023-01-29 18:58:59 +01:00
get().initialize(rootFolder, graphics);
2020-06-02 11:46:18 +02:00
}
PMeshAsset AssetRegistry::findMesh(const std::string &filePath)
{
2023-02-13 14:56:13 +01:00
AssetFolder* folder = get().assetRoot;
2023-01-21 18:43:21 +01:00
std::string fileName = filePath;
size_t slashLoc = filePath.rfind("/");
2023-11-06 14:47:21 +01:00
if(slashLoc != std::string::npos)
2023-01-21 18:43:21 +01:00
{
folder = get().getOrCreateFolder(filePath.substr(0, slashLoc));
fileName = filePath.substr(slashLoc+1, filePath.size());
}
2023-02-13 14:56:13 +01:00
return folder->meshes.at(fileName);
2020-06-02 11:46:18 +02:00
}
2020-10-03 11:00:10 +02:00
PTextureAsset AssetRegistry::findTexture(const std::string &filePath)
{
2023-02-13 14:56:13 +01:00
AssetFolder* folder = get().assetRoot;
2023-01-21 18:43:21 +01:00
std::string fileName = filePath;
size_t slashLoc = filePath.rfind("/");
2023-11-06 14:47:21 +01:00
if (slashLoc != std::string::npos)
2023-01-21 18:43:21 +01:00
{
2023-02-13 14:56:13 +01:00
folder = get().getOrCreateFolder(filePath.substr(0, slashLoc));
fileName = filePath.substr(slashLoc + 1, filePath.size());
2023-01-21 18:43:21 +01:00
}
2023-02-13 14:56:13 +01:00
return folder->textures.at(fileName);
2020-10-03 11:00:10 +02:00
}
2023-01-21 18:43:21 +01:00
PFontAsset AssetRegistry::findFont(const std::string& filePath)
2022-04-13 13:01:35 +02:00
{
2023-02-13 14:56:13 +01:00
AssetFolder* folder = get().assetRoot;
2023-01-21 18:43:21 +01:00
std::string fileName = filePath;
size_t slashLoc = filePath.rfind("/");
2023-11-06 14:47:21 +01:00
if(slashLoc != std::string::npos)
2023-01-21 18:43:21 +01:00
{
folder = get().getOrCreateFolder(filePath.substr(0, slashLoc));
fileName = filePath.substr(slashLoc+1, filePath.size());
}
2023-02-13 14:56:13 +01:00
return folder->fonts.at(fileName);
2022-04-13 13:01:35 +02:00
}
2020-06-02 11:46:18 +02:00
PMaterialAsset AssetRegistry::findMaterial(const std::string &filePath)
{
2023-02-13 14:56:13 +01:00
AssetFolder* folder = get().assetRoot;
2023-01-21 18:43:21 +01:00
std::string fileName = filePath;
size_t slashLoc = filePath.rfind("/");
2023-11-06 14:47:21 +01:00
if (slashLoc != std::string::npos)
2023-01-21 18:43:21 +01:00
{
folder = get().getOrCreateFolder(filePath.substr(0, slashLoc));
2023-02-13 14:56:13 +01:00
fileName = filePath.substr(slashLoc + 1, filePath.size());
2023-01-21 18:43:21 +01:00
}
2023-02-13 14:56:13 +01:00
return folder->materials.at(fileName);
2020-06-02 11:46:18 +02:00
}
2023-11-06 14:47:21 +01:00
PMaterialInstanceAsset AssetRegistry::findMaterialInstance(const std::string &filePath)
{
AssetFolder* folder = get().assetRoot;
std::string fileName = filePath;
size_t slashLoc = filePath.rfind("/");
if (slashLoc != std::string::npos)
{
folder = get().getOrCreateFolder(filePath.substr(0, slashLoc));
fileName = filePath.substr(slashLoc + 1, filePath.size());
}
return folder->instances.at(fileName);
}
2023-07-31 21:43:20 +02:00
std::ofstream AssetRegistry::createWriteStream(const std::filesystem::path& relativePath, std::ios_base::openmode openmode)
2020-09-19 14:36:50 +02:00
{
return get().internalCreateWriteStream(relativePath, openmode);
}
2023-07-31 21:43:20 +02:00
std::ifstream AssetRegistry::createReadStream(const std::filesystem::path& relativePath, std::ios_base::openmode openmode)
2020-09-19 14:36:50 +02:00
{
return get().internalCreateReadStream(relativePath, openmode);
}
2020-06-02 11:46:18 +02:00
AssetRegistry &AssetRegistry::get()
{
2023-02-01 22:13:04 +01:00
return *instance;
2020-06-02 11:46:18 +02:00
}
AssetRegistry::AssetRegistry()
2023-11-15 17:42:57 +01:00
: assetRoot(nullptr)
2020-06-02 11:46:18 +02:00
{
}
2023-08-26 15:19:12 +02:00
AssetRegistry* AssetRegistry::getInstance()
{
return instance;
}
2023-02-13 14:56:13 +01:00
void AssetRegistry::loadRegistry()
{
get().loadRegistryInternal();
}
void AssetRegistry::saveRegistry()
{
get().saveRegistryInternal();
}
2023-02-24 22:09:07 +01:00
2023-01-29 18:58:59 +01:00
void AssetRegistry::initialize(const std::filesystem::path &_rootFolder, Gfx::PGraphics _graphics)
2020-06-02 11:46:18 +02:00
{
2023-01-29 18:58:59 +01:00
this->graphics = _graphics;
this->rootFolder = _rootFolder;
2023-02-13 14:56:13 +01:00
this->assetRoot = new AssetFolder("");
loadRegistryInternal();
2020-06-02 11:46:18 +02:00
}
2023-02-13 14:56:13 +01:00
void AssetRegistry::loadRegistryInternal()
2020-09-19 14:36:50 +02:00
{
2023-02-13 14:56:13 +01:00
peekFolder(assetRoot);
loadFolder(assetRoot);
2020-09-19 14:36:50 +02:00
}
2023-02-13 14:56:13 +01:00
void AssetRegistry::peekFolder(AssetFolder* folder)
2020-09-19 14:36:50 +02:00
{
2023-02-13 14:56:13 +01:00
for (const auto& entry : std::filesystem::directory_iterator(rootFolder / folder->folderPath))
{
const auto& stem = entry.path().stem().string();
if (entry.is_directory())
{
if (folder->folderPath.empty())
{
folder->children[stem] = new AssetFolder(stem);
}
else
{
folder->children[stem] = new AssetFolder(folder->folderPath + "/" + stem);
}
peekFolder(folder->children[stem]);
continue;
}
auto stream = std::ifstream(entry.path(), std::ios::binary);
ArchiveBuffer buffer(graphics);
buffer.readFromStream(stream);
2023-02-24 22:09:07 +01:00
peekAsset(buffer);
2023-02-13 14:56:13 +01:00
}
2023-01-21 18:43:21 +01:00
}
2023-02-13 14:56:13 +01:00
void AssetRegistry::loadFolder(AssetFolder* folder)
2023-01-21 18:43:21 +01:00
{
2023-02-13 14:56:13 +01:00
for (const auto& entry : std::filesystem::directory_iterator(rootFolder / folder->folderPath))
{
const auto& path = entry.path();
if (entry.is_directory())
{
auto relative = path.stem().string();
loadFolder(folder->children[relative]);
continue;
}
auto stream = std::ifstream(path, std::ios::binary);
ArchiveBuffer buffer(graphics);
buffer.readFromStream(stream);
2023-02-24 22:09:07 +01:00
loadAsset(buffer);
2023-02-13 14:56:13 +01:00
}
2023-01-21 18:43:21 +01:00
}
2023-02-24 22:09:07 +01:00
void AssetRegistry::peekAsset(ArchiveBuffer& buffer)
{
// Read asset type
uint64 identifier;
Serialization::load(buffer, identifier);
// Read name
std::string name;
Serialization::load(buffer, name);
// Read folder
std::string folderPath;
Serialization::load(buffer, folderPath);
uint64 assetSize;
Serialization::load(buffer, assetSize);
AssetFolder* folder = getOrCreateFolder(folderPath);
2023-11-05 10:36:01 +01:00
OAsset asset;
2023-02-24 22:09:07 +01:00
switch (identifier)
{
case TextureAsset::IDENTIFIER:
asset = new TextureAsset(folderPath, name);
2023-11-05 10:36:01 +01:00
folder->textures[name] = std::move(asset);
2023-02-24 22:09:07 +01:00
break;
case MeshAsset::IDENTIFIER:
asset = new MeshAsset(folderPath, name);
2023-11-05 10:36:01 +01:00
folder->meshes[name] = std::move(asset);
2023-02-24 22:09:07 +01:00
break;
case MaterialAsset::IDENTIFIER:
asset = new MaterialAsset(folderPath, name);
2023-11-05 10:36:01 +01:00
folder->materials[name] = std::move(asset);
2023-02-24 22:09:07 +01:00
break;
case MaterialInstanceAsset::IDENTIFIER:
asset = new MaterialInstanceAsset(folderPath, name);
2023-11-05 10:36:01 +01:00
folder->instances[name] = std::move(asset);
2023-02-24 22:09:07 +01:00
break;
case FontAsset::IDENTIFIER:
asset = new FontAsset(folderPath, name);
2023-11-05 10:36:01 +01:00
folder->fonts[name] = std::move(asset);
2023-02-24 22:09:07 +01:00
break;
default:
throw new std::logic_error("Unknown Identifier");
}
}
void AssetRegistry::loadAsset(ArchiveBuffer& buffer)
{
// Read asset type
uint64 identifier;
Serialization::load(buffer, identifier);
// Read name
std::string name;
Serialization::load(buffer, name);
// Read folder
std::string folderPath;
Serialization::load(buffer, folderPath);
AssetFolder* folder = getOrCreateFolder(folderPath);
PAsset asset;
switch (identifier)
{
case TextureAsset::IDENTIFIER:
2023-11-05 10:36:01 +01:00
asset = PTextureAsset(folder->textures.at(name));
2023-02-24 22:09:07 +01:00
break;
case MeshAsset::IDENTIFIER:
2023-11-05 10:36:01 +01:00
asset = PMeshAsset(folder->meshes.at(name));
2023-02-24 22:09:07 +01:00
break;
case MaterialAsset::IDENTIFIER:
2023-11-05 10:36:01 +01:00
asset = PMaterialAsset(folder->materials.at(name));
2023-02-24 22:09:07 +01:00
break;
case MaterialInstanceAsset::IDENTIFIER:
2023-11-05 10:36:01 +01:00
asset = PMaterialInstanceAsset(folder->instances.at(name));
2023-02-24 22:09:07 +01:00
break;
case FontAsset::IDENTIFIER:
2023-11-05 10:36:01 +01:00
asset = PFontAsset(folder->fonts.at(name));
2023-02-24 22:09:07 +01:00
break;
default:
throw new std::logic_error("Unknown Identifier");
}
asset->load(buffer);
}
2023-02-13 14:56:13 +01:00
void AssetRegistry::saveRegistryInternal()
{
saveFolder("", assetRoot);
2023-01-21 18:43:21 +01:00
}
2023-02-13 14:56:13 +01:00
void AssetRegistry::saveFolder(const std::filesystem::path& folderPath, AssetFolder* folder)
2023-01-21 18:43:21 +01:00
{
2023-02-13 14:56:13 +01:00
std::filesystem::create_directory(rootFolder / folderPath);
for (const auto& [name, texture] : folder->textures)
{
2023-11-05 10:36:01 +01:00
saveAsset(PTextureAsset(texture), TextureAsset::IDENTIFIER, folderPath, name);
2023-02-13 14:56:13 +01:00
}
for (const auto& [name, mesh] : folder->meshes)
{
2023-11-05 10:36:01 +01:00
saveAsset(PMeshAsset(mesh), MeshAsset::IDENTIFIER, folderPath, name);
2023-02-13 14:56:13 +01:00
}
for (const auto& [name, material] : folder->materials)
{
2023-11-05 10:36:01 +01:00
saveAsset(PMaterialAsset(material), MaterialAsset::IDENTIFIER, folderPath, name);
}
for (const auto& [name, material] : folder->instances)
{
saveAsset(PMaterialInstanceAsset(material), MaterialInstanceAsset::IDENTIFIER, folderPath, name);
2023-02-13 14:56:13 +01:00
}
for (const auto& [name, font] : folder->fonts)
{
2023-11-05 10:36:01 +01:00
saveAsset(PFontAsset(font), FontAsset::IDENTIFIER, folderPath, name);
2023-02-13 14:56:13 +01:00
}
for (auto& [name, child] : folder->children)
{
saveFolder(folderPath / name, child);
}
2023-01-21 18:43:21 +01:00
}
2023-02-13 14:56:13 +01:00
void AssetRegistry::saveAsset(PAsset asset, uint64 identifier, const std::filesystem::path& folderPath, std::string name)
2023-01-21 18:43:21 +01:00
{
2023-02-13 14:56:13 +01:00
if (name.empty())
return;
2023-07-31 21:43:20 +02:00
std::string path = (folderPath / name).replace_extension("asset").string();
2023-02-13 14:56:13 +01:00
auto assetStream = createWriteStream(std::move(path), std::ios::binary);
ArchiveBuffer assetBuffer(graphics);
// write identifier
Serialization::save(assetBuffer, identifier);
// write name
Serialization::save(assetBuffer, name);
// write folder
Serialization::save(assetBuffer, folderPath.string());
// write asset data
asset->save(assetBuffer);
assetBuffer.writeToStream(assetStream);
}
std::filesystem::path AssetRegistry::getRootFolder()
{
return get().rootFolder;
}
2023-11-05 10:36:01 +01:00
void AssetRegistry::registerMesh(OMeshAsset mesh)
2023-02-13 14:56:13 +01:00
{
AssetFolder* folder = getOrCreateFolder(mesh->getFolderPath());
2023-11-05 10:36:01 +01:00
folder->meshes[mesh->getName()] = std::move(mesh);
2023-02-13 14:56:13 +01:00
}
2023-11-05 10:36:01 +01:00
void AssetRegistry::registerTexture(OTextureAsset texture)
2023-02-13 14:56:13 +01:00
{
AssetFolder* folder = getOrCreateFolder(texture->getFolderPath());
2023-11-05 10:36:01 +01:00
folder->textures[texture->getName()] = std::move(texture);
2023-02-13 14:56:13 +01:00
}
2023-11-05 10:36:01 +01:00
void AssetRegistry::registerFont(OFontAsset font)
2023-02-13 14:56:13 +01:00
{
AssetFolder* folder = getOrCreateFolder(font->getFolderPath());
2023-11-05 10:36:01 +01:00
folder->fonts[font->getName()] = std::move(font);
2023-02-13 14:56:13 +01:00
}
2023-11-05 10:36:01 +01:00
void AssetRegistry::registerMaterial(OMaterialAsset material)
2023-02-13 14:56:13 +01:00
{
AssetFolder* folder = getOrCreateFolder(material->getFolderPath());
2023-11-05 10:36:01 +01:00
folder->materials[material->getName()] = std::move(material);
}
void AssetRegistry::registerMaterialInstance(OMaterialInstanceAsset material)
{
AssetFolder* folder = getOrCreateFolder(material->getFolderPath());
folder->instances[material->getName()] = std::move(material);
2023-02-13 14:56:13 +01:00
}
AssetRegistry::AssetFolder* AssetRegistry::getOrCreateFolder(std::string fullPath)
{
AssetFolder* result = assetRoot;
std::string temp = fullPath;
2023-01-21 18:43:21 +01:00
while(!fullPath.empty())
2020-09-19 14:36:50 +02:00
{
2023-01-21 18:43:21 +01:00
size_t slashLoc = fullPath.find("/");
2023-11-06 14:47:21 +01:00
if(slashLoc == std::string::npos)
2020-09-19 14:36:50 +02:00
{
2023-02-13 14:56:13 +01:00
if (!result->children.contains(fullPath))
{
result->children[fullPath] = new AssetFolder(fullPath);
}
return result->children[fullPath];
2020-09-19 14:36:50 +02:00
}
2023-01-21 18:43:21 +01:00
std::string folderName = fullPath.substr(0, slashLoc);
2023-02-13 14:56:13 +01:00
if (!result->children.contains(folderName))
{
result->children[folderName] = new AssetFolder(temp);
}
result = result->children[folderName];
2023-01-21 18:43:21 +01:00
fullPath = fullPath.substr(slashLoc+1, fullPath.size());
2020-09-19 14:36:50 +02:00
}
2023-01-21 18:43:21 +01:00
return result;
2020-10-03 11:00:10 +02:00
}
2023-07-31 21:43:20 +02:00
std::ofstream AssetRegistry::internalCreateWriteStream(const std::filesystem::path& relativePath, std::ios_base::openmode openmode)
2020-09-19 14:36:50 +02:00
{
2023-07-31 21:43:20 +02:00
auto fullPath = rootFolder / relativePath;
std::filesystem::create_directories(fullPath.parent_path());
2021-01-19 15:30:00 +01:00
return std::ofstream(fullPath.string(), openmode);
2020-09-19 14:36:50 +02:00
}
2023-07-31 21:43:20 +02:00
std::ifstream AssetRegistry::internalCreateReadStream(const std::filesystem::path& relativePath, std::ios_base::openmode openmode)
2020-09-19 14:36:50 +02:00
{
2023-07-31 21:43:20 +02:00
auto fullPath = rootFolder / relativePath;
std::filesystem::create_directories(fullPath.parent_path());
2021-01-19 15:30:00 +01:00
return std::ifstream(fullPath.string(), openmode);
2020-09-19 14:36:50 +02:00
}
2023-02-13 14:56:13 +01:00
AssetRegistry::AssetFolder::AssetFolder(std::string_view folderPath)
: folderPath(folderPath)
{}
AssetRegistry::AssetFolder::~AssetFolder()
{
for (const auto& [_, child] : children)
{
delete child;
}
}
2023-02-24 22:09:07 +01:00