feat: add vec3 type to nhollman json / fix: scene serialisation stuff
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include <destrum/Components/MeshRendererComponent.h>
|
||||
#include <destrum/Assets/AssetReference.h>
|
||||
#include <destrum/Graphics/GfxDevice.h>
|
||||
#include <destrum/Graphics/Resources/PrimitiveMeshes.h>
|
||||
#include <destrum/Graphics/Renderer.h>
|
||||
#include <destrum/ObjectModel/Transform.h>
|
||||
|
||||
@@ -10,8 +11,11 @@
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
MeshRendererComponent::MeshRendererComponent(GameObject& parent): Component(parent, "MeshRendererComponent") {
|
||||
|
||||
}
|
||||
@@ -54,27 +58,39 @@ void MeshRendererComponent::Update(float) {
|
||||
}
|
||||
|
||||
nlohmann::json MeshRendererComponent::Serialize() const {
|
||||
// Only keys are saved, mesh and material ids are cache slots that change between runs
|
||||
std::string savedMeshKey = meshKey;
|
||||
std::string savedMaterialKey = materialKey;
|
||||
if (GameState::GetInstance().HasRenderer()) {
|
||||
if (const auto* resources = GameState::GetInstance().Renderer().getResources()) {
|
||||
if (savedMeshKey.empty() && meshID != NULL_MESH_ID) {
|
||||
savedMeshKey = resources->meshes().getMeshKey(meshID);
|
||||
}
|
||||
if (savedMaterialKey.empty() && materialID != NULL_MATERIAL_ID) {
|
||||
savedMaterialKey = resources->materials().getMaterialKey(materialID);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (savedMeshKey.empty() && meshID != NULL_MESH_ID) {
|
||||
throw std::runtime_error("MeshRendererComponent has a mesh without a key, it cannot be saved");
|
||||
}
|
||||
if (savedMaterialKey.empty() && materialID != NULL_MATERIAL_ID) {
|
||||
throw std::runtime_error("MeshRendererComponent has a material without a key, it cannot be saved");
|
||||
}
|
||||
|
||||
return {
|
||||
{"meshId", meshID},
|
||||
{"materialId", materialID},
|
||||
{"meshKey", meshKey},
|
||||
{"materialKey", materialKey}
|
||||
{"meshKey", savedMeshKey},
|
||||
{"materialKey", savedMaterialKey}
|
||||
};
|
||||
}
|
||||
|
||||
void MeshRendererComponent::Deserialize(const nlohmann::json& data) {
|
||||
if (data.contains("meshId")) {
|
||||
meshID = data.at("meshId").get<MeshID>();
|
||||
}
|
||||
if (data.contains("materialId")) {
|
||||
materialID = data.at("materialId").get<MaterialID>();
|
||||
}
|
||||
if (data.contains("meshKey")) {
|
||||
meshKey = data.at("meshKey").get<std::string>();
|
||||
}
|
||||
if (data.contains("materialKey")) {
|
||||
materialKey = data.at("materialKey").get<std::string>();
|
||||
}
|
||||
meshKey = data.value("meshKey", std::string{});
|
||||
materialKey = data.value("materialKey", std::string{});
|
||||
|
||||
// Older scenes also stored raw ids, only trust them when there is no key
|
||||
meshID = meshKey.empty() ? data.value("meshId", NULL_MESH_ID) : NULL_MESH_ID;
|
||||
materialID = materialKey.empty() ? data.value("materialId", NULL_MATERIAL_ID) : NULL_MATERIAL_ID;
|
||||
}
|
||||
|
||||
void MeshRendererComponent::ResolveReferences(const ObjectMap&) {
|
||||
@@ -89,7 +105,9 @@ void MeshRendererComponent::ResolveReferences(const ObjectMap&) {
|
||||
|
||||
const auto loadAssetForKey = [&](const std::string& key) {
|
||||
const auto asset = AssetReference::fromCacheKey(key);
|
||||
if (!asset) {
|
||||
// Runtime-only keys such as "BulbMaterial#2" also contain a '#', they are not files
|
||||
if (!asset || (asset->path.find("://") == std::string::npos &&
|
||||
!std::filesystem::exists(asset->path))) {
|
||||
return;
|
||||
}
|
||||
if (!GameState::GetInstance().HasGfxDevice()) {
|
||||
@@ -102,6 +120,20 @@ void MeshRendererComponent::ResolveReferences(const ObjectMap&) {
|
||||
|
||||
if (!meshKey.empty()) {
|
||||
auto resolved = resources->meshes().findMeshByKey(meshKey);
|
||||
if (!resolved && PrimitiveMeshes::IsPrimitiveKey(meshKey)) {
|
||||
resolved = resources->meshes().findMeshByKey(PrimitiveMeshes::StripDuplicateSuffix(meshKey));
|
||||
if (!resolved) {
|
||||
auto primitive = PrimitiveMeshes::MakeFromKey(meshKey);
|
||||
if (!primitive) {
|
||||
throw std::runtime_error("Invalid primitive mesh key: " + meshKey);
|
||||
}
|
||||
if (!GameState::GetInstance().HasGfxDevice()) {
|
||||
throw std::runtime_error("Cannot build primitive mesh without a graphics device: " + meshKey);
|
||||
}
|
||||
resolved = resources->meshes().addMesh(GameState::GetInstance().Gfx(), *primitive);
|
||||
}
|
||||
meshKey = resources->meshes().getMeshKey(*resolved);
|
||||
}
|
||||
if (!resolved) {
|
||||
loadAssetForKey(meshKey);
|
||||
resolved = resources->meshes().findMeshByKey(meshKey);
|
||||
@@ -129,11 +161,15 @@ void MeshRendererComponent::ResolveReferences(const ObjectMap&) {
|
||||
resolved = resources->materials().findMaterialByName(materialKey);
|
||||
}
|
||||
|
||||
if (!resolved) {
|
||||
throw std::runtime_error("Material resource not found: " + materialKey);
|
||||
if (resolved) {
|
||||
materialID = *resolved;
|
||||
materialKey = resources->materials().getMaterialKey(*resolved);
|
||||
} else {
|
||||
// Keep the key so saving again does not lose which material was meant
|
||||
spdlog::warn("Material \"{}\" on \"{}\" not found, using the placeholder material",
|
||||
materialKey, GetGameObject()->GetName());
|
||||
materialID = resources->materials().getPlaceholderMaterialId();
|
||||
}
|
||||
materialID = *resolved;
|
||||
materialKey = resources->materials().getMaterialKey(*resolved);
|
||||
}
|
||||
|
||||
if (meshID != NULL_MESH_ID && meshKey.empty()) {
|
||||
|
||||
Reference in New Issue
Block a user