diff --git a/docs/tasks/Bugs.todo b/docs/tasks/Bugs.todo index 9094a85..4e58f23 100644 --- a/docs/tasks/Bugs.todo +++ b/docs/tasks/Bugs.todo @@ -8,5 +8,6 @@ High Importance: ✔ @high Editor asset file paths are saved as absolute paths. They need to be relative to the project root. @done(22-03-18 20:41) Medium Importance: + ☐ Map Editor can be docked into the main window. The window IDs should prevent this. ☐ Map Editor does not grab tile sets if the Map Editor is opened before a project is loaded ✔ Map Editor paints the wrong tiles when scrolling with the middle mouse button (this may have to do with the parent window having the scroll bar) @done(22-04-07 13:50) \ No newline at end of file diff --git a/docs/tasks/core.todo b/docs/tasks/core.todo index a36b5bc..c9d0d2a 100644 --- a/docs/tasks/core.todo +++ b/docs/tasks/core.todo @@ -92,9 +92,11 @@ Core: ☐ Box Collider (Box2D) World (Lunariums version of a "Scene"): + ☐ Implement memento pattern to save the initial state of the world + ☐ Implement running the world and resetting to initial state ☐ Implement the world without Regions first - ☐ Serialize world - ☐ JSON + ✔ Serialize world @done(22-07-06 18:33) + ✔ JSON @done(22-07-06 18:33) ☐ Binary Implement Regions: diff --git a/docs/tasks/editor.todo b/docs/tasks/editor.todo index f24314f..0bf3989 100644 --- a/docs/tasks/editor.todo +++ b/docs/tasks/editor.todo @@ -45,6 +45,9 @@ Editor: World Hierarchy (Tree View): ☐ Handle showing Enities with children @high + ☐ Handle adding child entities @high + If an entity was right clicked on the new entity should be a child of the clicked entity + ☐ Handle drag and dropping entities to change the child/parent relationships @high Asset Viewer: ✔ Get references to the EditorAsset objects instead of the raw file locations @done(22-06-01 18:48) diff --git a/src/run_modes/editor/component_guis.cpp b/src/run_modes/editor/component_guis.cpp index c5d6f34..a11e193 100644 --- a/src/run_modes/editor/component_guis.cpp +++ b/src/run_modes/editor/component_guis.cpp @@ -10,9 +10,82 @@ #include #include #include +#include namespace lunarium { namespace editor { + ///////////////////////////////////////////////////////////////////// + // HELPERS + ///////////////////////////////////////////////////////////////////// + + /// This function was taken from the Hazel engine written by Cherno! + /// https://github.com/TheCherno/Hazel/blob/master/Hazelnut/src/Panels/SceneHierarchyPanel.cpp + static void DrawVec3Control(const std::string& label, glm::vec3& values, float resetValue = 0.0f, float columnWidth = 100.0f) + { + ImGuiIO& io = ImGui::GetIO(); + auto boldFont = io.Fonts->Fonts[0]; + + ImGui::PushID(label.c_str()); + + ImGui::Columns(2); + ImGui::SetColumnWidth(0, columnWidth); + ImGui::Text(label.c_str()); + ImGui::NextColumn(); + + ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{ 0, 0 }); + + float lineHeight = GImGui->Font->FontSize + GImGui->Style.FramePadding.y * 2.0f; + ImVec2 buttonSize = { lineHeight + 3.0f, lineHeight }; + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.8f, 0.1f, 0.15f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.9f, 0.2f, 0.2f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.8f, 0.1f, 0.15f, 1.0f }); + ImGui::PushFont(boldFont); + if (ImGui::Button("X", buttonSize)) + values.x = resetValue; + ImGui::PopFont(); + ImGui::PopStyleColor(3); + + ImGui::SameLine(); + ImGui::DragFloat("##X", &values.x, 0.1f, 0.0f, 0.0f, "%.2f"); + ImGui::PopItemWidth(); + ImGui::SameLine(); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.2f, 0.7f, 0.2f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.3f, 0.8f, 0.3f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.2f, 0.7f, 0.2f, 1.0f }); + ImGui::PushFont(boldFont); + if (ImGui::Button("Y", buttonSize)) + values.y = resetValue; + ImGui::PopFont(); + ImGui::PopStyleColor(3); + + ImGui::SameLine(); + ImGui::DragFloat("##Y", &values.y, 0.1f, 0.0f, 0.0f, "%.2f"); + ImGui::PopItemWidth(); + ImGui::SameLine(); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.1f, 0.25f, 0.8f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.2f, 0.35f, 0.9f, 1.0f }); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.1f, 0.25f, 0.8f, 1.0f }); + ImGui::PushFont(boldFont); + if (ImGui::Button("Z", buttonSize)) + values.z = resetValue; + ImGui::PopFont(); + ImGui::PopStyleColor(3); + + ImGui::SameLine(); + ImGui::DragFloat("##Z", &values.z, 0.1f, 0.0f, 0.0f, "%.2f"); + ImGui::PopItemWidth(); + + ImGui::PopStyleVar(); + + ImGui::Columns(1); + + ImGui::PopID(); + } + void CompGui::RenderTagComp(TagComponent& comp) { const int BUFFER_SIZE = 256; @@ -24,8 +97,14 @@ namespace lunarium { namespace editor comp.Info = buffer; } + /// This code also taken from the Hazel engine + /// https://github.com/TheCherno/Hazel/blob/master/Hazelnut/src/Panels/SceneHierarchyPanel.cpp void CompGui::RenderTransformComp(TransformComponent& comp) { - + DrawVec3Control("Translation", comp.Position); + glm::vec3 rotation = glm::degrees(comp.Rotation); + DrawVec3Control("Rotation", rotation); + comp.Rotation = glm::radians(rotation); + DrawVec3Control("Scale", comp.Scale, 1.0f); } }} \ No newline at end of file diff --git a/src/run_modes/editor/panels/properties_view.cpp b/src/run_modes/editor/panels/properties_view.cpp index defabb2..a748594 100644 --- a/src/run_modes/editor/panels/properties_view.cpp +++ b/src/run_modes/editor/panels/properties_view.cpp @@ -14,13 +14,43 @@ #include #include +#define PRESENT_COMP_CHOICE(str_name, type_name, pv) \ +if (ImGui::Selectable(str_name)){\ + if (pv->mpSelectedEntity->HasComponent()) {\ + pv->OpenPopup(Popup::ADD_COMP_FAIL).LogIfFailed(Editor::LogCat);\ + return false;\ + }\ + pv->mpSelectedEntity->AddComponent();\ + return false;\ +} + namespace lunarium { namespace editor { PropertiesView::PropertiesView() : Panel("Properties", PanelDockZone::DDZ_RIGHT, true, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar), mpSelectedAsset(nullptr), mpSelectedEntity(nullptr), mIsLocked(false) { - + AddPopup(Popup::ADD_COMP, "Add Component", [](Panel* p) + { + PropertiesView* pv = (PropertiesView*)p; + + // List components that can be added + PRESENT_COMP_CHOICE("Tag Component", TagComponent, pv) + PRESENT_COMP_CHOICE("Transform Component", TransformComponent, pv) + + return true; + }).LogIfFailed(Editor::LogCat); + + AddPopup(Popup::ADD_COMP_FAIL, "Add Comp Fail", [] (Panel* p) + { + ImGui::Text("Can not add that component - Entity already has it"); + if (ImGui::Button("OK") || (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsWindowHovered())) + { + return false; + } + + return true; + }).LogIfFailed(Editor::LogCat); } ///////////////////////////////////////////////////////////////////// @@ -90,6 +120,20 @@ namespace lunarium { namespace editor if (mpSelectedEntity->HasComponent()) { CompGui::RenderTagComp(mpSelectedEntity->GetComponent()); + + ImGui::Separator(); + } + + if (mpSelectedEntity->HasComponent()) + { + CompGui::RenderTransformComp(mpSelectedEntity->GetComponent()); + ImGui::Separator(); + } + + // After all components rendered + if (ImGui::Button("Add Component")) + { + OpenPopup(Popup::ADD_COMP).LogIfFailed(Editor::LogCat); } } diff --git a/src/run_modes/editor/panels/properties_view.h b/src/run_modes/editor/panels/properties_view.h index 01fc13a..5bc1d02 100644 --- a/src/run_modes/editor/panels/properties_view.h +++ b/src/run_modes/editor/panels/properties_view.h @@ -44,6 +44,13 @@ namespace editor void ShowToolBar(); void ShowEntity(); void ShowAsset(); + + private: // POPUPS + enum Popup + { + ADD_COMP, + ADD_COMP_FAIL, + }; }; } } diff --git a/src/run_modes/editor/panels/world_tree.cpp b/src/run_modes/editor/panels/world_tree.cpp index 0ac4b61..bffe782 100644 --- a/src/run_modes/editor/panels/world_tree.cpp +++ b/src/run_modes/editor/panels/world_tree.cpp @@ -76,7 +76,9 @@ namespace lunarium return; } - if (ImGui::TreeNode("World Root") && mpWorld) + ImGui::SetNextItemOpen(true); + + if (ImGui::TreeNode("World Root")) { // List all world entities // This will fail if we end up implementing child entities diff --git a/src/world/entity.cpp b/src/world/entity.cpp index 2d45c6d..8d5df0c 100644 --- a/src/world/entity.cpp +++ b/src/world/entity.cpp @@ -67,7 +67,32 @@ namespace lunarium components.emplace_back(tag); } - // TODO: If (HasComponent()) ... + if (HasComponent()) + { + nlohmann::ordered_json transform; + TransformComponent& comp = GetComponent(); + transform["type_name"] = "TransformComponent"; + + auto& pos = transform["position"]; + pos["x"] = comp.Position.x; + pos["y"] = comp.Position.y; + pos["z"] = comp.Position.z; + + auto& rot = transform["rotation"]; + rot["x"] = comp.Rotation.x; + rot["y"] = comp.Rotation.y; + rot["z"] = comp.Rotation.z; + + auto& scale = transform["scale"]; + scale["x"] = comp.Scale.x; + scale["y"] = comp.Scale.y; + scale["z"] = comp.Scale.z; + + components.emplace_back(transform); + } + + + // TODO: ADD CODE TO SERIALIZE ANY NEW COMPONENTS // Children @@ -102,6 +127,29 @@ namespace lunarium std::string info = comp["info"].get(); AddComponent(info); } + + if ("TransformComponent" == comp_type_name) + { + auto& pos = comp["position"]; + float x = pos["x"].get(); + float y = pos["y"].get(); + float z = pos["z"].get(); + glm::vec3 position(x, y, z); + + auto& rot = comp["rotation"]; + x = rot["x"].get(); + y = rot["y"].get(); + z = rot["z"].get(); + glm::vec3 rotation(x, y, z); + + auto& sc = comp["scale"]; + x = sc["x"].get(); + y = sc["y"].get(); + z = sc["z"].get(); + glm::vec3 scale(x, y, z); + + AddComponent(position, rotation, scale); + } } // TODO: Load children