From cc87da1001491094f87ca07022a750b867995bb7 Mon Sep 17 00:00:00 2001 From: Antoine Pilote Date: Thu, 11 Jul 2024 04:51:13 -0400 Subject: [PATCH] Added prefab thumbnails in filebrowser + fix filebrowser crash --- .gitmodules | 3 + Editor/src/Misc/ThumbnailManager.cpp | 17 ++++- Editor/src/Windows/FileSystemUI.cpp | 8 +-- Nuake/dependencies/recastnavigation | 1 + Nuake/src/Resource/Prefab.cpp | 18 +++++ Nuake/src/Resource/Prefab.h | 99 +++++++++++++++++++++++++++- 6 files changed, 139 insertions(+), 7 deletions(-) create mode 160000 Nuake/dependencies/recastnavigation diff --git a/.gitmodules b/.gitmodules index 80408c54..4427f2d6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,3 +25,6 @@ [submodule "Nuake/dependencies/Coral"] path = Nuake/dependencies/Coral url = https://github.com/antopilo/Coral.git +[submodule "Nuake/dependencies/recastnavigation"] + path = Nuake/dependencies/recastnavigation + url = https://github.com/antopilo/recastnavigation.git diff --git a/Editor/src/Misc/ThumbnailManager.cpp b/Editor/src/Misc/ThumbnailManager.cpp index 00c5d5f2..1b9ca420 100644 --- a/Editor/src/Misc/ThumbnailManager.cpp +++ b/Editor/src/Misc/ThumbnailManager.cpp @@ -69,13 +69,26 @@ Ref ThumbnailManager::GenerateThumbnail(const std::string& path, Matrix4 view = Matrix4(1.0f); view = glm::lookAt(Vector3(1, -1.0, 0), Vector3(0, 0, 0), Vector3(0, 1, 0));; - auto file = FileSystem::GetFile(path); if (file->GetFileType() == FileType::Prefab) { Ref scene = Scene::New(); auto cam = scene->CreateEntity("Camera"); - cam.AddComponent(); + TransformComponent& camTransform = cam.GetComponent(); + camTransform.SetLocalPosition({ 0.0f, 0.0f, 2.0f }); + + auto& previewLight = scene->CreateEntity("_directionalLight").AddComponent(); + previewLight.SetCastShadows(false); + previewLight.Type = LightType::Directional; + + scene->GetEnvironment()->CurrentSkyType = SkyType::ProceduralSky; + scene->GetEnvironment()->ProceduralSkybox->SunDirection = { 0.58f, 0.34f, -0.74f }; + auto& camComponent = cam.AddComponent(); + camComponent.CameraInstance->Fov = 45.0f; + camComponent.CameraInstance->AspectRatio = 1.0f; + m_ShadedFramebuffer->SetTexture(texture); + + Ref prefab = Prefab::InstanceInScene(path, scene); scene->Update(0.01f); scene->Draw(*m_ShadedFramebuffer.get()); diff --git a/Editor/src/Windows/FileSystemUI.cpp b/Editor/src/Windows/FileSystemUI.cpp index 23bdfd1c..88a97efd 100644 --- a/Editor/src/Windows/FileSystemUI.cpp +++ b/Editor/src/Windows/FileSystemUI.cpp @@ -369,10 +369,10 @@ namespace Nuake ImU32 rectColor = IM_COL32(255, 255, 255, 16); ImGui::GetWindowDrawList()->AddRectFilled(prevScreenPos + ImVec2(0, 100) - startOffset, prevScreenPos + ImVec2(100, 150) + offsetEnd, rectColor, 1.0f); std::string visibleName = file->GetName(); - const uint32_t MAX_CHAR_NAME = 35; + const uint32_t MAX_CHAR_NAME = 32; if (file->GetName().size() >= MAX_CHAR_NAME) { - visibleName = std::string(file->GetName().begin(), file->GetName().begin() + MAX_CHAR_NAME - 3) + "..."; + visibleName = std::string(visibleName.begin(), visibleName.begin() + MAX_CHAR_NAME - 3) + "..."; } ImGui::TextWrapped(visibleName.c_str()); @@ -412,11 +412,11 @@ namespace Nuake // ImGui::PopStyleVar(); // } // - if (Editor->Selection.File == file) + if (Editor->Selection.File == file && Editor->Selection.File->GetFileType() != FileType::Prefab) { ThumbnailManager::Get().MarkThumbnailAsDirty(file->GetRelativePath()); } - // + // if(pressed) // { // Editor->Selection = EditorSelection(file); diff --git a/Nuake/dependencies/recastnavigation b/Nuake/dependencies/recastnavigation new file mode 160000 index 00000000..455a019e --- /dev/null +++ b/Nuake/dependencies/recastnavigation @@ -0,0 +1 @@ +Subproject commit 455a019e7aef99354ac3020f04c1fe3541aa4d19 diff --git a/Nuake/src/Resource/Prefab.cpp b/Nuake/src/Resource/Prefab.cpp index f20fc7a9..3dd2b350 100644 --- a/Nuake/src/Resource/Prefab.cpp +++ b/Nuake/src/Resource/Prefab.cpp @@ -34,6 +34,24 @@ namespace Nuake return newPrefab; } + Ref Prefab::InstanceInScene(const std::string& path, Ref scene) + { + Ref newPrefab = CreateRef(); + newPrefab->Path = path; + + if (FileSystem::FileExists(path, false)) + { + std::string prefabTextContent = FileSystem::ReadFile(path); + + if (!prefabTextContent.empty()) + { + newPrefab->DeserializeIntoScene(json::parse(prefabTextContent), scene); + } + } + + return newPrefab; + } + void Prefab::EntityWalker(Entity entity) { Root = entity; diff --git a/Nuake/src/Resource/Prefab.h b/Nuake/src/Resource/Prefab.h index 2a782754..e1f63309 100644 --- a/Nuake/src/Resource/Prefab.h +++ b/Nuake/src/Resource/Prefab.h @@ -22,6 +22,7 @@ namespace Nuake { static Ref CreatePrefabFromEntity(Entity entity); static Ref New(const std::string& path); + static Ref InstanceInScene(const std::string& path, Ref targetScene); Prefab() { @@ -70,6 +71,102 @@ namespace Nuake { END_SERIALIZE(); } + bool DeserializeIntoScene(const json& j, Ref scene) + { + if (j == "") + return false; + + Path = j["Path"]; + + if (j.contains("DisplayName")) + { + DisplayName = j["DisplayName"]; + } + + if (j.contains("Description")) + { + Description = j["Description"]; + } + + if (j.contains("Entities")) + { + std::map newIdsLut; + for (json e : j["Entities"]) + { + Entity entity = { scene->m_Registry.create(), scene.get() }; + entity.Deserialize(e); // Id gets overriden by serialized id. + + auto& nameComponent = entity.GetComponent(); + bool isRoot = false; + if (nameComponent.ID == j["Root"]) + { + isRoot = true; // We found the root entity of the prefab. + auto& parentComponent = entity.GetComponent(); + parentComponent.HasParent = false; + parentComponent.ParentID = 0; + entity.GetComponent().Translation = { 0, 0, 0 }; + } + + uint32_t oldId = nameComponent.ID; + uint32_t newId = OS::GetTime(); + nameComponent.Name = nameComponent.Name; + nameComponent.ID = newId; + + newIdsLut[oldId] = newId; + if (isRoot) + { + Root = entity; + } + + AddEntity(entity); + } + + // Set reference to the parent entity to children + for (auto& e : Entities) + { + if (e.GetID() == Root.GetID()) + { + continue; + } + + auto& parentC = e.GetComponent(); + auto parent = scene->GetEntityByID(newIdsLut[parentC.ParentID]); + parent.AddChild(e); + } + + // Since the bones point to an entity, and we are instancing a prefab, the new skeleton is gonna be pointing to the wrong + // bones, we need to remap the skeleton to the new entities. We are simply reussing the same map we are using for the + // reparenting. Pretty neat. + std::function recursiveBoneRemapping = [&recursiveBoneRemapping, &newIdsLut](SkeletonNode& currentBone) + { + currentBone.EntityHandle = newIdsLut[currentBone.EntityHandle]; + for (SkeletonNode& bone : currentBone.Children) + { + recursiveBoneRemapping(bone); + } + }; + + // Do the remapping of the skeleton + for (auto& e : Entities) + { + if (e.GetID() == Root.GetID() || !e.HasComponent()) + { + continue; + } + + auto& skinnedModelComponent = e.GetComponent(); + if (!skinnedModelComponent.ModelResource) + { + continue; + } + + SkeletonNode& currentBone = skinnedModelComponent.ModelResource->GetSkeletonRootNode(); + recursiveBoneRemapping(currentBone); + } + } + return true; + } + bool Deserialize(const json& j) { if (j == "") @@ -89,7 +186,7 @@ namespace Nuake { if (j.contains("Entities")) { - const auto& scene = Engine::GetCurrentScene(); + auto scene = Engine::GetCurrentScene(); std::map newIdsLut; for (json e : j["Entities"])