diff --git a/Editor/src/EditorInterface.cpp b/Editor/src/EditorInterface.cpp index 3a302b68..5aad17ee 100644 --- a/Editor/src/EditorInterface.cpp +++ b/Editor/src/EditorInterface.cpp @@ -29,6 +29,7 @@ #include "src/Scene/Systems/QuakeMapBuilder.h" #include "src/Scene/Components/LightComponent.h" #include "UIComponents/Viewport.h" +#include namespace Nuake { Ref userInterface; @@ -159,7 +160,8 @@ namespace Nuake { { ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth; - std::string name = e.GetComponent().Name; + NameComponent& nameComponent = e.GetComponent(); + std::string name = nameComponent.Name; ParentComponent& parent = e.GetComponent(); if (m_SelectedEntity == e) @@ -172,8 +174,11 @@ namespace Nuake { if (parent.Children.size() <= 0) base_flags |= ImGuiTreeNodeFlags_Leaf; + if(nameComponent.IsPrefab) + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(0,255,0,255)); bool open = ImGui::TreeNodeEx(name.c_str(), base_flags); - + if(nameComponent.IsPrefab) + ImGui::PopStyleColor(); if (ImGui::BeginDragDropSource()) { @@ -230,7 +235,12 @@ namespace Nuake { p.HasParent = false; } } - ImGui::Selectable("Save as prefab"); + if (ImGui::Selectable("Save as new prefab")) + { + Ref newPrefab = Prefab::CreatePrefabFromEntity(m_SelectedEntity); + std::string savePath = FileDialog::SaveFile("*.prefab"); + newPrefab->SaveAs(savePath); + } ImGui::EndPopup(); } if (open) @@ -256,7 +266,7 @@ namespace Nuake { if (!scene) return; - if (ImGui::Begin(" Environnement")) + if (ImGui::Begin("Environnement")) { auto env = Engine::GetCurrentScene()->GetEnvironment(); if (ImGui::CollapsingHeader("Procedural Sky")) @@ -1307,6 +1317,8 @@ namespace Nuake { DrawGizmos(); DrawRessourceWindow(); + + pInterface.DrawEntitySettings(); DrawViewport(); DrawSceneTree(); //DrawDirectoryExplorer(); @@ -1317,7 +1329,6 @@ namespace Nuake { filesystem.Draw(); filesystem.DrawDirectoryExplorer(); - pInterface.DrawEntitySettings(); if (m_ShowImGuiDemo) ImGui::ShowDemoWindow(); diff --git a/Nuake/src/Rendering/AABB.h b/Nuake/src/Rendering/AABB.h new file mode 100644 index 00000000..3f56d3db --- /dev/null +++ b/Nuake/src/Rendering/AABB.h @@ -0,0 +1,38 @@ +#pragma once + +namespace Nuake { + class AABB + { + public: + Vector3 Min; + Vector3 Max; + + // Transforms the bounding box and recalculate an axis aligned box + void Transform(Matrix4 transform) + { + Min = Vector3(transform * Vector4(Min, 0.0f)); + Max = Vector3(transform * Vector4(Max, 0.0f)); + + if (Min.x > Max.x) + { + float max = Max.x; + Max.x = Min.x; + Min.x = max; + } + + if (Min.y > Max.y) + { + float max = Max.y; + Max.y = Min.y; + Min.y = max; + } + + if (Min.z > Max.z) + { + float max = Max.z; + Max.z = Min.z; + Min.z = max; + } + } + }; +} \ No newline at end of file diff --git a/Nuake/src/Resource/Prefab.cpp b/Nuake/src/Resource/Prefab.cpp new file mode 100644 index 00000000..6f9a8e1e --- /dev/null +++ b/Nuake/src/Resource/Prefab.cpp @@ -0,0 +1,24 @@ +#include "Prefab.h" +#include "src/Scene/Components/ParentComponent.h" + +namespace Nuake { + Ref Prefab::CreatePrefabFromEntity(Entity entity) + { + Ref prefab = CreateRef(); + ParentComponent parentC = entity.GetComponent(); + prefab->EntityWalker(entity); + + return prefab; + } + + void Prefab::EntityWalker(Entity entity) + { + entity.GetComponent().IsPrefab = true; + Entities.push_back(entity); + + for (const Entity& e : entity.GetComponent().Children) + { + EntityWalker(e); + } + } +} \ No newline at end of file diff --git a/Nuake/src/Resource/Prefab.h b/Nuake/src/Resource/Prefab.h index 69a4a620..868d9f88 100644 --- a/Nuake/src/Resource/Prefab.h +++ b/Nuake/src/Resource/Prefab.h @@ -2,14 +2,16 @@ #include #include #include - +#include "src/Resource/Serializable.h" namespace Nuake { - class Prefab + class Prefab : ISerializable { public: std::string Path; std::vector Entities; + static Ref CreatePrefabFromEntity(Entity entity); + Prefab() { Path = ""; @@ -20,5 +22,36 @@ namespace Nuake { { Entities.push_back(entity); } + + void SaveAs(const std::string& path) + { + Path = path; + + FileSystem::BeginWriteFile(path); + FileSystem::WriteLine(Serialize().dump(4)); + FileSystem::EndWriteFile(); + } + + json Serialize() + { + BEGIN_SERIALIZE(); + SERIALIZE_VAL(Path); + std::vector entities = std::vector(); + for (Entity e : Entities) + entities.push_back(e.Serialize()); + SERIALIZE_VAL_LBL("Entities", entities); + END_SERIALIZE(); + } + + bool Deserialize(const std::string& str) + { + BEGIN_DESERIALIZE(); + Path = j["Path"]; + + return true; + } + + private: + void EntityWalker(Entity entity); }; } diff --git a/Nuake/src/Scene/Components/NameComponent.h b/Nuake/src/Scene/Components/NameComponent.h index b66c7507..fba2211a 100644 --- a/Nuake/src/Scene/Components/NameComponent.h +++ b/Nuake/src/Scene/Components/NameComponent.h @@ -6,8 +6,9 @@ namespace Nuake { class NameComponent { public: + int ID; std::string Name = "Entity"; - int ID; + bool IsPrefab = false; json Serialize() { diff --git a/Nuake/src/Scene/Scene.cpp b/Nuake/src/Scene/Scene.cpp index 36bcdc7d..64ca4c60 100644 --- a/Nuake/src/Scene/Scene.cpp +++ b/Nuake/src/Scene/Scene.cpp @@ -157,7 +157,7 @@ namespace Nuake { void Scene::DrawShadows() { auto meshView = m_Registry.view(); - auto quakeView = m_Registry.view(); + auto quakeView = m_Registry.view(); auto view = m_Registry.view(); Ref cam = m_EditorCamera; @@ -177,6 +177,7 @@ namespace Nuake { glCullFace(GL_BACK); + // Build a list of mesh to draw. for (auto l : view) { auto [lightTransform, light] = view.get(l);