diff --git a/Editor/src/ComponentsPanel/MeshPanel.h b/Editor/src/ComponentsPanel/MeshPanel.h index b8388fda..7cc6570d 100644 --- a/Editor/src/ComponentsPanel/MeshPanel.h +++ b/Editor/src/ComponentsPanel/MeshPanel.h @@ -2,18 +2,22 @@ #include #include "ComponentPanel.h" #include "ModelResourceInspector.h" +#include "../Misc/PopupHelper.h" #include #include #include #include +#include class MeshPanel : ComponentPanel { private: Scope _modelInspector; bool _expanded = false; + + std::string _importedPathMesh; public: MeshPanel() { @@ -58,6 +62,7 @@ public: _modelInspector->Draw(); } + bool shouldConvert = false; if (ImGui::BeginDragDropTarget()) { if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Model")) @@ -66,19 +71,51 @@ public: std::string fullPath = std::string(file, 256); fullPath = Nuake::FileSystem::AbsoluteToRelative(fullPath); - if (Nuake::String::EndsWith(fullPath, ".model")) + if (Nuake::String::EndsWith(fullPath, ".mesh")) { - + component.ModelPath = fullPath; + component.ModelResource = ResourceLoader::LoadModel(fullPath); } else { + // Convert to .Model component.ModelPath = fullPath; component.LoadModel(); + + _importedPathMesh = fullPath; + + auto loader = ModelLoader(); + auto modelResource = loader.LoadModel(fullPath); + shouldConvert = true; } } ImGui::EndDragDropTarget(); } + if (PopupHelper::DefineConfirmationDialog("##ConvertAsset", "Convert Asset")) + { + // Convert to disk + auto loader = ModelLoader(); + Ref modelResource = loader.LoadModel(_importedPathMesh); + json serializedData = modelResource->SerializeData(); + + const std::string exportedMeshPath = _importedPathMesh + ".mesh"; + FileSystem::BeginWriteFile(exportedMeshPath); + FileSystem::WriteLine(serializedData.dump()); + FileSystem::EndWriteFile(); + + ResourceManager::RegisterResource(modelResource); + + // Update component + component.ModelPath = exportedMeshPath; + component.ModelResource = modelResource; + } + + if (shouldConvert) + { + PopupHelper::OpenPopup("##ConvertAsset"); + } + ImGui::TableNextColumn(); ComponentTableReset(component.ModelPath, ""); } diff --git a/Editor/src/Windows/FileSystemUI.cpp b/Editor/src/Windows/FileSystemUI.cpp index 7dd4a1d9..2a962add 100644 --- a/Editor/src/Windows/FileSystemUI.cpp +++ b/Editor/src/Windows/FileSystemUI.cpp @@ -293,7 +293,7 @@ namespace Nuake { dragType = "_Material"; } - else if (fileExtension == ".obj" || fileExtension == ".mdl" || fileExtension == ".gltf" || fileExtension == ".md3" || fileExtension == ".fbx" || fileExtension == ".glb") + else if (fileExtension == ".mesh" || fileExtension == ".obj" || fileExtension == ".mdl" || fileExtension == ".gltf" || fileExtension == ".md3" || fileExtension == ".fbx" || fileExtension == ".glb") { dragType = "_Model"; } diff --git a/Nuake/src/Resource/Model.cpp b/Nuake/src/Resource/Model.cpp index 7ccba4e3..0f2f26cd 100644 --- a/Nuake/src/Resource/Model.cpp +++ b/Nuake/src/Resource/Model.cpp @@ -26,6 +26,17 @@ namespace Nuake return m_Meshes; } + json Model::SerializeData() + { + BEGIN_SERIALIZE(); + j["UUID"] = static_cast(ID); + for (uint32_t i = 0; i < std::size(m_Meshes); i++) + { + j["Meshes"][i] = m_Meshes[i]->Serialize(); + } + END_SERIALIZE(); + } + json Model::Serialize() { BEGIN_SERIALIZE(); @@ -36,6 +47,7 @@ namespace Nuake } else { + j["UUID"] = static_cast(ID); for (uint32_t i = 0; i < std::size(m_Meshes); i++) { j["Meshes"][i] = m_Meshes[i]->Serialize(); @@ -58,6 +70,11 @@ namespace Nuake } else { + if (j.contains("UUID")) + { + ID = UUID(j["UUID"]); + } + if (j.contains("Meshes")) { for (auto& m : j["Meshes"]) diff --git a/Nuake/src/Resource/Model.h b/Nuake/src/Resource/Model.h index 4dfed423..4bfe6ed7 100644 --- a/Nuake/src/Resource/Model.h +++ b/Nuake/src/Resource/Model.h @@ -19,6 +19,7 @@ namespace Nuake void AddMesh(Ref mesh); std::vector>& GetMeshes(); + json SerializeData(); json Serialize() override; bool Deserialize(const json& j) override; }; diff --git a/Nuake/src/Resource/ResourceLoader.h b/Nuake/src/Resource/ResourceLoader.h index 6c3618ac..8573f8bb 100644 --- a/Nuake/src/Resource/ResourceLoader.h +++ b/Nuake/src/Resource/ResourceLoader.h @@ -4,6 +4,7 @@ #include "src/Resource/Resource.h" #include "src/Resource/ResourceManager.h" #include "src/Rendering/Textures/Material.h" +#include "src/Resource/Model.h" namespace Nuake { @@ -60,6 +61,50 @@ namespace Nuake return material; } + + static Ref LoadModel(const std::string& path) + { + const std::string FILE_NOT_FOUND = "[Resource Loader] File doesn't exists. \n "; + const std::string WRONG_EXTENSION = "[Resource Loader] Resource type mismatch file extension. \n expected: "; + const std::string MESH_EXT = ".mesh"; + if (path.empty()) + { + Logger::Log(FILE_NOT_FOUND + path, "resource", LOG_TYPE::WARNING); + return nullptr; + } + + if (!FileSystem::FileExists(path)) + { + Logger::Log(FILE_NOT_FOUND + path, "resource", LOG_TYPE::WARNING); + return nullptr; + } + + if (!String::EndsWith(path, MESH_EXT)) + { + std::string message = WRONG_EXTENSION + MESH_EXT + " actual: " + path; + Logger::Log(message, "resource", LOG_TYPE::WARNING); + } + + std::string content = FileSystem::ReadFile(path); + json j = json::parse(content); + + UUID uuid = ReadUUID(j); + + // Check if resource is already loaded. + if (ResourceManager::IsResourceLoaded(uuid)) + { + return ResourceManager::GetResource(uuid); + } + + Ref model = CreateRef(); + model->ID = uuid; + model->Path = path; + model->Deserialize(j); + ResourceManager::RegisterResource(model); + + return model; + } + private: static UUID ReadUUID(json j) { diff --git a/Nuake/src/Scene/Components/ModelComponent.h b/Nuake/src/Scene/Components/ModelComponent.h index a60c04dc..6b099968 100644 --- a/Nuake/src/Scene/Components/ModelComponent.h +++ b/Nuake/src/Scene/Components/ModelComponent.h @@ -1,10 +1,12 @@ #pragma once -#include -#include "src/Resource/Serializable.h" #include "src/Resource/Model.h" +#include "src/Resource/ResourceLoader.h" +#include "src/Resource/Serializable.h" #include +#include + namespace Nuake { @@ -35,10 +37,17 @@ namespace Nuake ModelPath = j["ModelPath"]; ModelResource = CreateRef(); - if (j.contains("ModelResource")) + if (ModelPath.empty() || !String::EndsWith(ModelPath, ".mesh")) { - auto& res = j["ModelResource"]; - ModelResource->Deserialize(res); + if (j.contains("ModelResource")) + { + auto& res = j["ModelResource"]; + ModelResource->Deserialize(res); + } + } + else + { + ModelResource = ResourceLoader::LoadModel(ModelPath); } return true;