From 33b3962e519952d8dc995b45b9e9dfc5ec3fc377 Mon Sep 17 00:00:00 2001 From: antopilo Date: Wed, 8 Sep 2021 21:28:53 -0400 Subject: [PATCH] Drag and drop prefab into scene tree. Play pause snapshot system --- Editor/Editor.cpp | 3 +- Editor/src/EditorInterface.cpp | 90 +++++++++++++------- Editor/src/FileSystemUI.cpp | 2 + Nuake/src/Resource/Prefab.cpp | 11 +++ Nuake/src/Resource/Prefab.h | 27 +++++- Nuake/src/Scene/Components/ParentComponent.h | 6 +- Nuake/src/Scene/Scene.cpp | 12 +-- Nuake/src/UI/InterfaceParser.cpp | 10 +-- Nuake/src/UI/InterfaceParser.h | 2 - 9 files changed, 107 insertions(+), 56 deletions(-) diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index 5062427e..f4048179 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -70,8 +70,7 @@ int main() //newEditor.Update(0.f); - if (Nuake::Input::IsKeyPressed(GLFW_KEY_F8)) - Nuake::Engine::ExitPlayMode(); + Nuake::Vector2 WindowSize = Nuake::Engine::GetCurrentWindow()->GetSize(); glViewport(0, 0, WindowSize.x, WindowSize.y); diff --git a/Editor/src/EditorInterface.cpp b/Editor/src/EditorInterface.cpp index 37de6c97..df0b7c8e 100644 --- a/Editor/src/EditorInterface.cpp +++ b/Editor/src/EditorInterface.cpp @@ -34,6 +34,7 @@ #include #include "src/Rendering/Renderer.h" #include +#include "src/Core/Input.h" namespace Nuake { Ref userInterface; @@ -270,6 +271,7 @@ namespace Nuake { parent.Children.push_back(payload_entity); } } + ImGui::EndDragDropTarget(); } if (ImGui::IsItemClicked()) @@ -386,53 +388,66 @@ namespace Nuake { ImGui::EndChild(); ImGui::Separator(); - // Draw a tree of entities. - std::vector entities = scene->GetAllEntities(); - for (Entity e : entities) + if (ImGui::BeginChild("Scene tree", ImGui::GetContentRegionAvail(), true)) { - ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth; - std::string name = e.GetComponent().Name; - // If selected add selected flag. - if (m_SelectedEntity == e) - base_flags |= ImGuiTreeNodeFlags_Selected; - - // Write in normal font. - ImGui::PushFont(normalFont); - - // Small icons + name. - std::string label = ICON_FA_CIRCLE + std::string(" ") + name; - - // Draw all entity without parents. - if (!e.GetComponent().HasParent) + std::vector entities = scene->GetAllEntities(); + for (Entity e : entities) { - // Recursively draw childrens. - DrawEntityTree(e); + ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth; + std::string name = e.GetComponent().Name; + // If selected add selected flag. + if (m_SelectedEntity == e) + base_flags |= ImGuiTreeNodeFlags_Selected; + // Write in normal font. + ImGui::PushFont(normalFont); + + // Small icons + name. + std::string label = ICON_FA_CIRCLE + std::string(" ") + name; + + // Draw all entity without parents. + if (!e.GetComponent().HasParent) + { + // Recursively draw childrens. + DrawEntityTree(e); + } + + // Pop font. + ImGui::PopFont(); + + // Right click menu + //if (ImGui::BeginPopupContextItem()) + // ImGui::EndPopup(); } + ImGui::EndChild(); + } + + if (ImGui::BeginDragDropTarget()) // Drag n drop new prefab file into scene tree + { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Prefab")) + { + char* file = (char*)payload->Data; + std::string fullPath = std::string(file, 256); + std::string relPath = FileSystem::AbsoluteToRelative(fullPath); - // Pop font. - ImGui::PopFont(); - - // Right click menu - //if (ImGui::BeginPopupContextItem()) - // ImGui::EndPopup(); + Entity newEntity = Engine::GetCurrentScene()->CreateEntity("New prefab Entity"); + PrefabComponent& prefabComponent = newEntity.AddComponent(); + prefabComponent.PrefabInstance = Prefab::New(relPath); + } + ImGui::EndDragDropTarget(); } - // Delete entity + // Deleted entity queue if (QueueDeletion.GetHandle() != -1) { Engine::GetCurrentScene()->DestroyEntity(QueueDeletion); if (m_SelectedEntity == QueueDeletion) - { m_IsEntitySelected = false; - } QueueDeletion = Entity{ (entt::entity)-1, scene.get() }; - //ImGui::TreePop(); } - } ImGui::End(); } @@ -1389,6 +1404,7 @@ namespace Nuake { } + json SceneSnapshot; void EditorInterface::Draw() { Init(); @@ -1595,9 +1611,19 @@ namespace Nuake { float needed = half - used; ImGui::Dummy(ImVec2(needed, 10)); ImGui::SameLine(); - if (ImGui::Button(ICON_FA_PLAY)) Engine::EnterPlayMode(); + if (ImGui::Button(ICON_FA_PLAY)) + { + SceneSnapshot = Engine::GetCurrentScene()->Serialize(); + Engine::EnterPlayMode(); + } ImGui::SameLine(); - if (ImGui::Button(ICON_FA_STOP)) Engine::ExitPlayMode(); + if (ImGui::Button(ICON_FA_STOP) || Input::IsKeyPressed(297)) + { + Engine::ExitPlayMode(); + + Engine::GetCurrentScene()->Deserialize(SceneSnapshot.dump()); + m_IsEntitySelected = false; + } } ImGui::End(); } diff --git a/Editor/src/FileSystemUI.cpp b/Editor/src/FileSystemUI.cpp index b21f714a..184d8423 100644 --- a/Editor/src/FileSystemUI.cpp +++ b/Editor/src/FileSystemUI.cpp @@ -123,6 +123,8 @@ namespace Nuake { dragType = "_Model"; else if (file->Type == ".interface") dragType = "_Interface"; + else if (file->Type == ".prefab") + dragType = "_Prefab"; ImGui::SetDragDropPayload(dragType.c_str(), (void*)(pathBuffer), sizeof(pathBuffer)); ImGui::Text(file->name.c_str()); diff --git a/Nuake/src/Resource/Prefab.cpp b/Nuake/src/Resource/Prefab.cpp index 6f9a8e1e..96df2f4f 100644 --- a/Nuake/src/Resource/Prefab.cpp +++ b/Nuake/src/Resource/Prefab.cpp @@ -11,6 +11,17 @@ namespace Nuake { return prefab; } + Ref Prefab::New(const std::string& path) + { + Ref newPrefab = CreateRef(); + newPrefab->Path = path; + + std::string prefabTextContent = FileSystem::ReadFile(path); + newPrefab->Deserialize(prefabTextContent); + + return newPrefab; + } + void Prefab::EntityWalker(Entity entity) { entity.GetComponent().IsPrefab = true; diff --git a/Nuake/src/Resource/Prefab.h b/Nuake/src/Resource/Prefab.h index 868d9f88..92264474 100644 --- a/Nuake/src/Resource/Prefab.h +++ b/Nuake/src/Resource/Prefab.h @@ -1,8 +1,11 @@ #pragma once +#include "src/Scene/Entities/Entity.h" +#include "src/Scene/Components/ParentComponent.h" +#include "src/Resource/Serializable.h" +#include "Engine.h" + #include #include -#include -#include "src/Resource/Serializable.h" namespace Nuake { class Prefab : ISerializable { @@ -12,6 +15,8 @@ namespace Nuake { static Ref CreatePrefabFromEntity(Entity entity); + static Ref New(const std::string& path); + Prefab() { Path = ""; @@ -47,7 +52,25 @@ namespace Nuake { { BEGIN_DESERIALIZE(); Path = j["Path"]; + if (j.contains("Entities")) + { + for (json e : j["Entities"]) + { + Entity entity = Entity { Engine::GetCurrentScene()->m_Registry.create(), Engine::GetCurrentScene().get() }; + entity.Deserialize(e.dump()); + this->AddEntity(entity); + } + for (auto& e : Entities) + { + auto parentC = e.GetComponent(); + if (!parentC.HasParent) + continue; + + auto parent = Engine::GetCurrentScene()->GetEntityByID(parentC.ParentID); + parent.AddChild(e); + } + } return true; } diff --git a/Nuake/src/Scene/Components/ParentComponent.h b/Nuake/src/Scene/Components/ParentComponent.h index 514d963b..d2ea224f 100644 --- a/Nuake/src/Scene/Components/ParentComponent.h +++ b/Nuake/src/Scene/Components/ParentComponent.h @@ -45,10 +45,10 @@ namespace Nuake BEGIN_DESERIALIZE(); this->HasParent = j["HasParent"]; if (HasParent) + { this->ParentID = j["ParentID"]; - - //this->Parent = Entity{ j["Parent"], Engine::GetCurrentScene().get() }; - + //this->Parent = Entity{ j["Parent"], Engine::GetCurrentScene().get() }; + } return true; } }; diff --git a/Nuake/src/Scene/Scene.cpp b/Nuake/src/Scene/Scene.cpp index 5f8fbcb3..3d89adf5 100644 --- a/Nuake/src/Scene/Scene.cpp +++ b/Nuake/src/Scene/Scene.cpp @@ -748,6 +748,8 @@ namespace Nuake { if (!j.contains("Name")) return false; + m_Registry.clear(); + Name = j["Name"]; m_Environement = CreateRef(); @@ -785,14 +787,4 @@ namespace Nuake { return true; } - - void Scene::Snapshot() - { - - } - - void Scene::LoadSnapshot() - { - } - } diff --git a/Nuake/src/UI/InterfaceParser.cpp b/Nuake/src/UI/InterfaceParser.cpp index 1e609c80..1ed0815e 100644 --- a/Nuake/src/UI/InterfaceParser.cpp +++ b/Nuake/src/UI/InterfaceParser.cpp @@ -1,6 +1,6 @@ #include "InterfaceParser.h" #include "Styling/Stylesheet.h" - +#include "src/Core/String.h" namespace Nuake { Ref InterfaceParser::Root = CreateRef(); @@ -59,7 +59,7 @@ namespace Nuake { std::string name = a.name(); if (name == "groups") - for (auto& g : split(a.value(), ' ')) + for (auto& g : String::Split(a.value(), ' ')) node->AddGroup(g); if (name == "id") @@ -106,7 +106,7 @@ namespace Nuake { std::string name = a.name(); if (name == "groups") - for (auto& g : split(a.value(), ' ')) + for (auto& g : String::Split(a.value(), ' ')) node->AddGroup(g); if (name == "id") @@ -201,7 +201,7 @@ namespace Nuake std::regex regex("[0-9]+[^ ]+"); std::smatch match_value; - std::vector splits = split(value, ' '); + std::vector splits = String::Split(value, ' '); for (int i = 0; i < splits.size(); i++) { if (!std::regex_search(value.begin(), value.end(), match_value, regex)) @@ -224,7 +224,7 @@ namespace Nuake { std::string name = a.name(); if (name == "groups") - for (auto& g : split(a.value(), ' ')) + for (auto& g : String::Split(a.value(), ' ')) node->AddGroup(g); if (name == "id") node->ID = a.value(); diff --git a/Nuake/src/UI/InterfaceParser.h b/Nuake/src/UI/InterfaceParser.h index 9efe1530..dc073964 100644 --- a/Nuake/src/UI/InterfaceParser.h +++ b/Nuake/src/UI/InterfaceParser.h @@ -25,8 +25,6 @@ namespace Nuake static Ref CreateCanvas(const pugi::xml_node& xml_node); static Ref CreateTextNode(const pugi::xml_node& xml_node); - static std::vector split(std::string const& str, const char delim); - static Layout::LayoutUnit GetUnit(const std::string& value); static Layout::LayoutVec4 GetVec4Unit(const std::string& value); static Color GetColor(const std::string& value);