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

418 lines
15 KiB
C++
Raw Normal View History

2020-06-02 11:46:18 +02:00
#include "AssetRegistry.h"
2025-04-04 14:44:53 +02:00
#include "Asset/FontAsset.h"
#include "Asset/MaterialAsset.h"
#include "Asset/MaterialInstanceAsset.h"
#include "Asset/MeshAsset.h"
#include "Asset/EnvironmentMapAsset.h"
#include "Asset/SVGAsset.h"
#include "Asset/TextureAsset.h"
2022-04-13 13:01:35 +02:00
#include "FontAsset.h"
2024-06-09 12:20:04 +02:00
#include "Graphics/Graphics.h"
#include "Graphics/Mesh.h"
#include "Window/WindowManager.h"
2023-08-26 15:19:12 +02:00
#include <fstream>
2024-06-09 12:20:04 +02:00
#include <iostream>
#include <nlohmann/json.hpp>
2025-05-16 13:04:43 +02:00
#include <mutex>
2024-06-09 12:20:04 +02:00
2020-06-02 11:46:18 +02:00
using namespace Seele;
2023-12-24 21:49:49 +01:00
AssetRegistry* _instance = new AssetRegistry();
2023-02-01 22:13:04 +01:00
2024-06-09 12:20:04 +02:00
AssetRegistry::~AssetRegistry() { delete assetRoot; }
2020-06-02 11:46:18 +02:00
2024-06-09 12:20:04 +02:00
void AssetRegistry::init(std::filesystem::path rootFolder, Gfx::PGraphics graphics) { get().initialize(rootFolder, graphics); }
2020-06-02 11:46:18 +02:00
2024-06-09 12:20:04 +02:00
PMeshAsset AssetRegistry::findMesh(std::string_view folderPath, std::string_view filePath) {
2024-07-19 10:42:59 +02:00
std::unique_lock l(get().assetLock);
2023-02-13 14:56:13 +01:00
AssetFolder* folder = get().assetRoot;
2024-06-09 12:20:04 +02:00
if (!folderPath.empty()) {
2024-05-01 14:10:52 +02:00
folder = get().getOrCreateFolder(folderPath);
2023-01-21 18:43:21 +01:00
}
2024-05-01 14:10:52 +02:00
return folder->meshes.at(std::string(filePath));
2020-06-02 11:46:18 +02:00
}
2024-06-09 12:20:04 +02:00
PTextureAsset AssetRegistry::findTexture(std::string_view folderPath, std::string_view filePath) {
2024-07-19 10:42:59 +02:00
std::unique_lock l(get().assetLock);
2023-02-13 14:56:13 +01:00
AssetFolder* folder = get().assetRoot;
2024-06-09 12:20:04 +02:00
if (!folderPath.empty()) {
2024-05-01 14:10:52 +02:00
folder = get().getOrCreateFolder(folderPath);
2023-01-21 18:43:21 +01:00
}
2024-05-01 14:10:52 +02:00
return folder->textures.at(std::string(filePath));
2020-10-03 11:00:10 +02:00
}
2024-06-09 12:20:04 +02:00
PFontAsset AssetRegistry::findFont(std::string_view folderPath, std::string_view filePath) {
2024-07-19 10:42:59 +02:00
std::unique_lock l(get().assetLock);
2023-02-13 14:56:13 +01:00
AssetFolder* folder = get().assetRoot;
2024-06-09 12:20:04 +02:00
if (!folderPath.empty()) {
2024-05-01 14:10:52 +02:00
folder = get().getOrCreateFolder(folderPath);
2023-01-21 18:43:21 +01:00
}
2024-05-01 14:10:52 +02:00
return folder->fonts.at(std::string(filePath));
2022-04-13 13:01:35 +02:00
}
2025-01-19 16:07:38 +01:00
PSVGAsset AssetRegistry::findSVG(std::string_view folderPath, std::string_view filePath) {
std::unique_lock l(get().assetLock);
AssetFolder* folder = get().assetRoot;
if (!folderPath.empty()) {
folder = get().getOrCreateFolder(folderPath);
}
return folder->svgs.at(std::string(filePath));
}
2025-04-04 14:44:53 +02:00
PEnvironmentMapAsset AssetRegistry::findEnvironmentMap(std::string_view folderPath, std::string_view filePath) {
std::unique_lock l(get().assetLock);
AssetFolder* folder = get().assetRoot;
if (!folderPath.empty()) {
folder = get().getOrCreateFolder(folderPath);
}
return folder->envs.at(std::string(filePath));
}
2024-06-09 12:20:04 +02:00
PMaterialAsset AssetRegistry::findMaterial(std::string_view folderPath, std::string_view filePath) {
2024-07-19 10:42:59 +02:00
std::unique_lock l(get().assetLock);
2023-02-13 14:56:13 +01:00
AssetFolder* folder = get().assetRoot;
2024-06-09 12:20:04 +02:00
if (!folderPath.empty()) {
2024-05-01 14:10:52 +02:00
folder = get().getOrCreateFolder(folderPath);
2023-01-21 18:43:21 +01:00
}
2024-05-01 14:10:52 +02:00
return folder->materials.at(std::string(filePath));
2020-06-02 11:46:18 +02:00
}
2024-06-09 12:20:04 +02:00
PMaterialInstanceAsset AssetRegistry::findMaterialInstance(std::string_view folderPath, std::string_view filePath) {
2024-07-19 10:42:59 +02:00
std::unique_lock l(get().assetLock);
2023-11-06 14:47:21 +01:00
AssetFolder* folder = get().assetRoot;
2024-06-09 12:20:04 +02:00
if (!folderPath.empty()) {
2024-05-01 14:10:52 +02:00
folder = get().getOrCreateFolder(folderPath);
2023-11-06 14:47:21 +01:00
}
2024-05-01 14:10:52 +02:00
return folder->instances.at(std::string(filePath));
2023-11-06 14:47:21 +01:00
}
2024-07-19 10:42:59 +02:00
void AssetRegistry::registerMesh(OMeshAsset mesh) {
std::unique_lock l(get().assetLock);
get().registerMeshInternal(std::move(mesh));
}
void AssetRegistry::registerTexture(OTextureAsset texture) {
std::unique_lock l(get().assetLock);
get().registerTextureInternal(std::move(texture));
}
void AssetRegistry::registerFont(OFontAsset font) {
std::unique_lock l(get().assetLock);
get().registerFontInternal(std::move(font));
}
2025-01-19 16:07:38 +01:00
void AssetRegistry::registerSVG(OSVGAsset svg) {
std::unique_lock l(get().assetLock);
get().registerSVGInternal(std::move(svg));
}
2025-04-04 14:44:53 +02:00
void AssetRegistry::registerEnvironmentMap(OEnvironmentMapAsset env) {
std::unique_lock l(get().assetLock);
get().registerEnvironmentMapInternal(std::move(env));
}
2024-07-19 10:42:59 +02:00
void AssetRegistry::registerMaterial(OMaterialAsset material) {
std::unique_lock l(get().assetLock);
get().registerMaterialInternal(std::move(material));
}
void AssetRegistry::registerMaterialInstance(OMaterialInstanceAsset instance) {
std::unique_lock l(get().assetLock);
get().registerMaterialInstanceInternal(std::move(instance));
}
2024-06-09 12:20:04 +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);
}
2024-06-09 12:20:04 +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);
}
2024-06-09 12:20:04 +02:00
void AssetRegistry::loadAsset(ArchiveBuffer& buffer) {
2023-02-24 22:09:07 +01:00
// 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);
2024-07-19 10:42:59 +02:00
AssetFolder* folder = get().getOrCreateFolder(folderPath);
2024-06-09 12:20:04 +02:00
2023-02-24 22:09:07 +01:00
PAsset asset;
2024-06-09 12:20:04 +02:00
switch (identifier) {
2023-02-24 22:09:07 +01:00
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;
2025-01-19 16:07:38 +01:00
case SVGAsset::IDENTIFIER:
asset = PSVGAsset(folder->svgs.at(name));
break;
2025-04-04 14:44:53 +02:00
case EnvironmentMapAsset::IDENTIFIER:
asset = PEnvironmentMapAsset(folder->envs.at(name));
break;
2023-02-24 22:09:07 +01:00
default:
throw new std::logic_error("Unknown Identifier");
}
asset->load(buffer);
}
2024-07-19 10:42:59 +02:00
void AssetRegistry::saveAsset(PAsset asset, uint64 identifier, const std::filesystem::path& folderPath, std::string name) {
if (name.empty())
return;
std::string path = (folderPath / name).string().append(".asset");
auto assetStream = createWriteStream(std::move(path), std::ios::binary);
ArchiveBuffer buffer(get().graphics);
// write identifier
Serialization::save(buffer, identifier);
// write name
Serialization::save(buffer, name);
// write folder
Serialization::save(buffer, folderPath.string());
// write asset data
asset->save(buffer);
buffer.writeToStream(assetStream);
}
AssetRegistry& AssetRegistry::get() { return *_instance; }
AssetRegistry::AssetRegistry() : assetRoot(nullptr) {}
AssetRegistry* AssetRegistry::getInstance() { return _instance; }
2025-04-04 14:44:53 +02:00
void AssetRegistry::loadRegistry() { get().loadRegistryInternal(); }
2024-07-19 10:42:59 +02:00
2025-04-04 14:44:53 +02:00
void AssetRegistry::saveRegistry() { get().saveRegistryInternal(); }
2024-07-19 10:42:59 +02:00
AssetRegistry::AssetFolder* AssetRegistry::getOrCreateFolder(std::string_view fullPath) {
AssetFolder* result = assetRoot;
std::string temp = std::string(fullPath);
while (!temp.empty()) {
size_t slashLoc = temp.find("/");
if (slashLoc == std::string::npos) {
if (!result->children.contains(temp)) {
result->children[temp] = new AssetFolder(temp);
}
return result->children[temp];
}
std::string folderName = temp.substr(0, slashLoc);
if (!result->children.contains(folderName)) {
result->children[folderName] = new AssetFolder(fullPath);
}
result = result->children[folderName];
temp = temp.substr(slashLoc + 1, temp.size());
}
return result;
}
void AssetRegistry::initialize(const std::filesystem::path& _rootFolder, Gfx::PGraphics _graphics) {
this->graphics = _graphics;
this->rootFolder = _rootFolder;
this->assetRoot = new AssetFolder("");
2025-04-08 22:01:42 +02:00
if (!std::filesystem::exists(rootFolder))
{
//std::filesystem::create_directories(rootFolder);
2025-04-08 22:01:42 +02:00
}
else if (!std::filesystem::is_directory(rootFolder))
{
throw std::logic_error("Asset Folder is not a directory!!");
}
2024-07-19 10:42:59 +02:00
loadRegistryInternal();
}
void AssetRegistry::loadRegistryInternal() {
2025-04-04 14:44:53 +02:00
Array<Pair<PAsset, ArchiveBuffer>> peeked;
2024-07-19 10:42:59 +02:00
{
std::unique_lock l(get().assetLock);
peeked = peekFolder(assetRoot);
}
2024-08-07 21:19:33 +02:00
uint64 assetSize = 0;
2024-07-19 10:42:59 +02:00
for (auto& [asset, buffer] : peeked) {
asset->load(buffer);
2024-08-07 21:19:33 +02:00
assetSize += asset->getSize();
2024-07-19 10:42:59 +02:00
}
2024-08-07 21:19:33 +02:00
std::cout << "Done loading " << assetSize << std::endl;
2024-07-19 10:42:59 +02:00
}
2024-08-07 21:19:33 +02:00
Array<Pair<PAsset, ArchiveBuffer>> AssetRegistry::peekFolder(AssetFolder* folder) {
Array<Pair<PAsset, ArchiveBuffer>> peeked;
2024-07-19 10:42:59 +02: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);
}
auto temp = peekFolder(folder->children[stem]);
2024-08-07 21:19:33 +02:00
for (auto& t : temp) {
peeked.add(std::move(t));
2024-07-19 10:42:59 +02:00
}
continue;
}
if (entry.path().filename().compare(".DS_Store") == 0) {
continue;
}
auto stream = std::ifstream(entry.path(), std::ios::binary);
ArchiveBuffer buffer(graphics);
buffer.readFromStream(stream);
peeked.add(peekAsset(buffer));
}
return peeked;
}
Pair<PAsset, ArchiveBuffer> 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);
AssetFolder* folder = getOrCreateFolder(folderPath);
PAsset asset;
switch (identifier) {
case TextureAsset::IDENTIFIER:
folder->textures[name] = new TextureAsset(folderPath, name);
asset = PTextureAsset(folder->textures[name]);
break;
case MeshAsset::IDENTIFIER:
folder->meshes[name] = new MeshAsset(folderPath, name);
asset = PMeshAsset(folder->meshes[name]);
break;
case MaterialAsset::IDENTIFIER:
folder->materials[name] = new MaterialAsset(folderPath, name);
asset = PMaterialAsset(folder->materials[name]);
break;
case MaterialInstanceAsset::IDENTIFIER:
folder->instances[name] = new MaterialInstanceAsset(folderPath, name);
asset = PMaterialInstanceAsset(folder->instances[name]);
break;
case FontAsset::IDENTIFIER:
folder->fonts[name] = new FontAsset(folderPath, name);
asset = PFontAsset(folder->fonts[name]);
break;
2025-01-19 16:07:38 +01:00
case SVGAsset::IDENTIFIER:
folder->svgs[name] = new SVGAsset(folderPath, name);
asset = PSVGAsset(folder->svgs[name]);
break;
2025-04-04 14:44:53 +02:00
case EnvironmentMapAsset::IDENTIFIER:
folder->envs[name] = new EnvironmentMapAsset(folderPath, name);
asset = PEnvironmentMapAsset(folder->envs[name]);
break;
2024-07-19 10:42:59 +02:00
default:
throw new std::logic_error("Unknown Identifier");
}
2024-08-07 21:19:33 +02:00
return {asset, std::move(buffer)};
2024-07-19 10:42:59 +02:00
}
2024-06-09 12:20:04 +02:00
void AssetRegistry::saveRegistryInternal() { saveFolder("", assetRoot); }
2023-01-21 18:43:21 +01:00
2024-06-09 12:20:04 +02:00
void AssetRegistry::saveFolder(const std::filesystem::path& folderPath, AssetFolder* folder) {
2023-02-13 14:56:13 +01:00
std::filesystem::create_directory(rootFolder / folderPath);
2024-06-09 12:20:04 +02:00
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
}
2024-06-09 12:20:04 +02: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
}
2024-06-09 12:20:04 +02:00
for (const auto& [name, material] : folder->materials) {
2023-11-05 10:36:01 +01:00
saveAsset(PMaterialAsset(material), MaterialAsset::IDENTIFIER, folderPath, name);
}
2024-06-09 12:20:04 +02:00
for (const auto& [name, material] : folder->instances) {
2023-11-05 10:36:01 +01:00
saveAsset(PMaterialInstanceAsset(material), MaterialInstanceAsset::IDENTIFIER, folderPath, name);
2023-02-13 14:56:13 +01:00
}
2024-06-09 12:20:04 +02: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
}
2025-01-19 16:07:38 +01:00
for (const auto& [name, svg] : folder->svgs) {
saveAsset(PSVGAsset(svg), SVGAsset::IDENTIFIER, folderPath, name);
}
2025-04-04 14:44:53 +02:00
for (const auto& [name, env] : folder->envs) {
saveAsset(PEnvironmentMapAsset(env), EnvironmentMapAsset::IDENTIFIER, folderPath, name);
}
2024-06-09 12:20:04 +02:00
for (auto& [name, child] : folder->children) {
2023-02-13 14:56:13 +01:00
saveFolder(folderPath / name, child);
}
2023-01-21 18:43:21 +01:00
}
2024-06-09 12:20:04 +02:00
std::filesystem::path AssetRegistry::getRootFolder() { return get().rootFolder; }
2023-02-13 14:56:13 +01:00
2024-07-19 10:42:59 +02:00
void AssetRegistry::registerMeshInternal(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
}
2024-07-19 10:42:59 +02:00
void AssetRegistry::registerTextureInternal(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
}
2024-07-19 10:42:59 +02:00
void AssetRegistry::registerFontInternal(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
}
2025-01-19 16:07:38 +01:00
void AssetRegistry::registerSVGInternal(OSVGAsset svg) {
AssetFolder* folder = getOrCreateFolder(svg->getFolderPath());
folder->svgs[svg->getName()] = std::move(svg);
}
2025-04-04 14:44:53 +02:00
void AssetRegistry::registerEnvironmentMapInternal(OEnvironmentMapAsset env) {
AssetFolder* folder = getOrCreateFolder(env->getFolderPath());
folder->envs[env->getName()] = std::move(env);
}
2024-07-19 10:42:59 +02:00
void AssetRegistry::registerMaterialInternal(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);
}
2024-07-19 10:42:59 +02:00
void AssetRegistry::registerMaterialInstanceInternal(OMaterialInstanceAsset material) {
2023-11-05 10:36:01 +01:00
AssetFolder* folder = getOrCreateFolder(material->getFolderPath());
folder->instances[material->getName()] = std::move(material);
2023-02-13 14:56:13 +01:00
}
2024-06-09 12:20:04 +02:00
std::ofstream AssetRegistry::internalCreateWriteStream(const std::filesystem::path& relativePath, std::ios_base::openmode openmode) {
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
}
2024-06-09 12:20:04 +02:00
std::ifstream AssetRegistry::internalCreateReadStream(const std::filesystem::path& relativePath, std::ios_base::openmode openmode) {
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
2024-06-09 12:20:04 +02:00
AssetRegistry::AssetFolder::AssetFolder(std::string_view folderPath) : folderPath(folderPath) {}
2023-02-13 14:56:13 +01:00
2024-06-09 12:20:04 +02:00
AssetRegistry::AssetFolder::~AssetFolder() {
for (auto [_, child] : children) {
2023-02-13 14:56:13 +01:00
delete child;
}
}