From 39aaa4cd2c15c7fba6ca704fdf56f3b4d62db4e0 Mon Sep 17 00:00:00 2001 From: Antoine Pilote Date: Mon, 31 May 2021 23:03:29 -0400 Subject: [PATCH] Yoga layout working --- Editor/resources/Interface/Testing.css | 7 + Editor/resources/test.project | 1 + Editor/src/EditorInterface.cpp | 20 ++- Nuake/src/Core/Logger.cpp | 1 + Nuake/src/Core/Logger.h | 1 - Nuake/src/Rendering/Renderer2D.cpp | 8 +- Nuake/src/Rendering/Renderer2D.h | 2 +- Nuake/src/Scene/Scene.cpp | 37 ++-- Nuake/src/Scene/Scene.h | 4 +- Nuake/src/UI/InterfaceParser.h | 217 +++++++++++++++++++++++ Nuake/src/UI/Node.cpp | 6 +- Nuake/src/UI/Node.h | 235 ++++++++++++++++++++++++- Nuake/src/UI/UserInterface.cpp | 129 +++++++++----- Nuake/src/UI/UserInterface.h | 51 ++---- Nuake/src/Vendors/yoga/Yoga.h | 1 - Nuake/src/Window.cpp | 2 + 16 files changed, 605 insertions(+), 117 deletions(-) create mode 100644 Editor/resources/Interface/Testing.css create mode 100644 Editor/resources/test.project diff --git a/Editor/resources/Interface/Testing.css b/Editor/resources/Interface/Testing.css new file mode 100644 index 00000000..7a24cc90 --- /dev/null +++ b/Editor/resources/Interface/Testing.css @@ -0,0 +1,7 @@ + + +.button { + width: 10px; + height: 100px; + color: rgba(1, 1, 2, 1); +} \ No newline at end of file diff --git a/Editor/resources/test.project b/Editor/resources/test.project new file mode 100644 index 00000000..b53f6d95 --- /dev/null +++ b/Editor/resources/test.project @@ -0,0 +1 @@ +{"Description":"","Name":"", "DefaultScene":"Scenes/test.scene"} \ No newline at end of file diff --git a/Editor/src/EditorInterface.cpp b/Editor/src/EditorInterface.cpp index 2b1cb93f..d9bb7aa6 100644 --- a/Editor/src/EditorInterface.cpp +++ b/Editor/src/EditorInterface.cpp @@ -37,12 +37,15 @@ void EditorInterface::Init() this->filesystem = FileSystemUI(); } + +ImVec2 LastSize = ImVec2(); void EditorInterface::DrawViewport() { if(ImGui::Begin("ShadowMap")) { ImVec2 regionAvail = ImGui::GetContentRegionAvail(); glm::vec2 viewportPanelSize = glm::vec2(regionAvail.x, regionAvail.y); + if (m_IsEntitySelected && m_SelectedEntity.HasComponent()) { auto& light = m_SelectedEntity.GetComponent(); Ref texture = light.m_Framebuffer->GetTexture(GL_DEPTH_ATTACHMENT); @@ -63,6 +66,9 @@ void EditorInterface::DrawViewport() ImVec2 regionAvail = ImGui::GetContentRegionAvail(); glm::vec2 viewportPanelSize = glm::vec2(regionAvail.x, regionAvail.y); + if(Engine::GetCurrentWindow()->GetFrameBuffer()->GetSize() != viewportPanelSize) + Engine::GetCurrentWindow()->GetFrameBuffer()->UpdateSize(viewportPanelSize); + Ref texture = Engine::GetCurrentWindow()->GetFrameBuffer()->GetTexture(); ImGui::Image((void*)texture->GetID(), regionAvail, ImVec2(0, 1), ImVec2(1, 0)); @@ -891,15 +897,7 @@ void OpenProject() // Create new interface named test. Ref userInterface = UI::UserInterface::New("test"); - // Creates a rectangle covering the screen. - Ref rectangle = UI::Rect::New(0, 0, userInterface->Width, userInterface->Height); - userInterface->AddRect(rectangle); - - // Cut another rectangle at 1280 vertically - Ref rect2 = rectangle->CutLeft(1280.f); - rect2->Props.BackgroundColor = Color(0, 1, 0, 1); // Set background color to green. - userInterface->AddRect(rect2); - + // Set current interface running. Engine::GetCurrentScene()->AddInterface(userInterface); @@ -1004,6 +1002,10 @@ void EditorInterface::Draw() } if (ImGui::BeginMenu("View")) { + if (ImGui::MenuItem("Reload Interfaces", NULL)) + { + Engine::GetCurrentScene()->ReloadInterfaces(); + } if (ImGui::MenuItem("Lighting", NULL, true)) {} if (ImGui::MenuItem("Draw grid", NULL, m_DrawGrid)) m_DrawGrid = !m_DrawGrid; diff --git a/Nuake/src/Core/Logger.cpp b/Nuake/src/Core/Logger.cpp index 358fc17e..a86e2f97 100644 --- a/Nuake/src/Core/Logger.cpp +++ b/Nuake/src/Core/Logger.cpp @@ -12,6 +12,7 @@ void Logger::Log(std::string log) time_t now = time(0); strftime(buff, 100, "%Y-%m-%d %H:%M:%S.000", localtime(&now)); std::string msg = "["+ std::string(buff) + "]" + std::string(" - ") + log; + printf((msg + "\n").c_str()); logs.push_back(msg); } diff --git a/Nuake/src/Core/Logger.h b/Nuake/src/Core/Logger.h index 4ca225aa..94e19241 100644 --- a/Nuake/src/Core/Logger.h +++ b/Nuake/src/Core/Logger.h @@ -5,7 +5,6 @@ enum LOG_TYPE { VERBOSE, - DEBUG, WARNING, CRITICAL }; diff --git a/Nuake/src/Rendering/Renderer2D.cpp b/Nuake/src/Rendering/Renderer2D.cpp index 613c8b0f..edc6419d 100644 --- a/Nuake/src/Rendering/Renderer2D.cpp +++ b/Nuake/src/Rendering/Renderer2D.cpp @@ -1,6 +1,6 @@ #include "Renderer2D.h" #include "GL/glew.h" - +#include "../Core/Maths.h" Ref Renderer2D::UIShader; unsigned int Renderer2D::VAO; unsigned int Renderer2D::VBO; @@ -10,7 +10,7 @@ Matrix4 Renderer2D::Projection; void Renderer2D::Init() { UIShader = CreateRef("resources/Shaders/ui.shader"); - Projection = glm::ortho(0.f, 1920.f, 0.0f, 1080.f, -0.5f, 100.0f); + Projection = glm::ortho(0.f, 1920.f, 1080.f, 0.f, -0.5f, 100.0f); float quad_Vertices[] = { // positions // texture Coords @@ -35,8 +35,10 @@ void Renderer2D::Init() glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); } -void Renderer2D::BeginDraw() +void Renderer2D::BeginDraw(Vector2 size) { + glDisable(GL_DEPTH_TEST); + Projection = glm::ortho(0.f, size.x, size.y, 0.f, -0.5f, 1000.0f); UIShader->Bind(); UIShader->SetUniformMat4f("projection", Projection); } diff --git a/Nuake/src/Rendering/Renderer2D.h b/Nuake/src/Rendering/Renderer2D.h index 2cd6d5c3..c5873bf5 100644 --- a/Nuake/src/Rendering/Renderer2D.h +++ b/Nuake/src/Rendering/Renderer2D.h @@ -12,7 +12,7 @@ public: static Matrix4 Projection; static void Init(); - static void BeginDraw(); + static void BeginDraw(Vector2 size); static void DrawRect(); static void EndDraw(); }; \ No newline at end of file diff --git a/Nuake/src/Scene/Scene.cpp b/Nuake/src/Scene/Scene.cpp index df0dac16..1f570469 100644 --- a/Nuake/src/Scene/Scene.cpp +++ b/Nuake/src/Scene/Scene.cpp @@ -143,12 +143,20 @@ void Scene::Update(Timestep ts) auto [transform, rb] = ccGroup.get(e); rb.SyncWithTransform(m_Registry.get(e)); } + + + } void Scene::EditorUpdate(Timestep ts) { m_EditorCamera->Update(ts); + + for (auto i : m_Interfaces) + { + //i->Calculate(1280,720); + } } @@ -209,6 +217,14 @@ void Scene::DrawShadows() } } +void Scene::DrawInterface(Vector2 screensize) +{ + for (auto i : m_Interfaces) + { + i->Draw(screensize); + } +} + void Scene::Draw() { @@ -339,10 +355,7 @@ void Scene::Draw() PhysicsManager::Get()->DrawDebug(); } - for (auto i : m_Interfaces) - { - i->Draw(); - } + } void Scene::EditorDraw() @@ -355,10 +368,7 @@ void Scene::EditorDraw() // env->ProceduralSkybox->Draw(m_EditorCamera); //} - for (auto i : m_Interfaces) - { - i->Draw(); - } + @@ -510,10 +520,7 @@ void Scene::EditorDraw() } }*/ - for (auto i : m_Interfaces) - { - i->Draw(); - } + } std::vector Scene::GetAllEntities() { @@ -619,6 +626,12 @@ bool Scene::SaveAs(const std::string& path) return true; } +void Scene::ReloadInterfaces() +{ + for (auto& i : m_Interfaces) + i->Reload(); +} + void Scene::AddInterface(Ref interface) { this->m_Interfaces.push_back(interface); diff --git a/Nuake/src/Scene/Scene.h b/Nuake/src/Scene/Scene.h index a63a6a01..3f51cd01 100644 --- a/Nuake/src/Scene/Scene.h +++ b/Nuake/src/Scene/Scene.h @@ -10,7 +10,7 @@ #include "EditorCamera.h" #include "../Resource/Serializable.h" #include "src/UI/UserInterface.h" - +#include "../Core/Maths.h" class Entity; class Scene : public ISerializable { @@ -43,6 +43,7 @@ public: // TODO: Maybe move this to Renderer::DrawScene() ? void DrawShadows(); + void DrawInterface(Vector2 screensize); void Draw(); void EditorDraw(); @@ -64,6 +65,7 @@ public: bool Save(); bool SaveAs(const std::string& path); + void ReloadInterfaces(); void AddInterface(Ref interface); json Serialize() override; diff --git a/Nuake/src/UI/InterfaceParser.h b/Nuake/src/UI/InterfaceParser.h index 20044a77..54b45792 100644 --- a/Nuake/src/UI/InterfaceParser.h +++ b/Nuake/src/UI/InterfaceParser.h @@ -1,6 +1,223 @@ #pragma once +#include +#include +#include +#include +#include +#include +#include class InterfaceParser { + static Ref Root; +private: + +public: + static Ref Parse(const std::string path) + { + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_file(path.c_str()); + + std::string name = doc.first_child().name(); + if (name != "Canvas") + { + Logger::Log("InterfaceParser error: First child should be a canvas - " + path); + return nullptr; + } + + Root = CreateCanvas(doc.first_child()); + + Iterate(doc.first_child(), Root); + return Root; + } + + static void Iterate(const pugi::xml_node& xml_node, Ref node) + { + for (auto& e : xml_node.children()) + { + std::string type = e.name(); + if (type == "Canvas") + { + Ref canvas = CreateCanvas(e); + node->Childrens.push_back(canvas); + Iterate(e, canvas); + } + else if (type == "Rect") + { + Ref newNode = CreateNode(e); + node->Childrens.push_back(newNode); + Iterate(e, newNode); + } + } + } + + static Ref CreateNode(const pugi::xml_node& xml_node) + { + Ref node = CreateRef(); + for (auto& a : xml_node.attributes()) + { + std::string name = a.name(); + if (name == "height") + node->Height = GetUnit(a.value()); + if (name == "width") + node->Width = GetUnit(a.value()); + if (name == "margin") + node->Margin = GetVec4Unit(a.value()); + if (name == "padding") + node->Padding = GetVec4Unit(a.value()); + if (name == "border") + node->Border = GetVec4Unit(a.value()); + if (name == "position") + node->Position = GetVec4Unit(a.value()); + if (name == "color") + node->BackgroundColor = GetColor(a.value()); + + } + + return node; + } + + static Layout::LayoutUnit GetUnit(const std::string& value) + { + std::regex only_number("[0-9]+"); + std::regex not_number("[^0-9]+"); + + // is percentage + std::smatch match_value; + if (std::regex_search(value.begin(), value.end(), match_value, only_number)) + { + std::smatch match_type; + if (std::regex_search(value.begin(), value.end(), match_type, not_number)) + { + float value = std::stof(match_value[0]); + + if (match_type[0] == "%") + { + return Layout::LayoutUnit{ + value, + Layout::Unit::PERCENT + }; + } + else if (match_type[0] == "px") + { + return Layout::LayoutUnit{ + value, + Layout::Unit::PIXEL + }; + } + } + } + } + + static std::vector split(std::string const& str, const char delim) + { + std::vector result; + size_t start; + size_t end = 0; + + while ((start = str.find_first_not_of(delim, end)) != std::string::npos) + { + end = str.find(delim, start); + result.push_back(str.substr(start, end - start)); + } + + return result; + } + + static Layout::LayoutVec4 GetVec4Unit(const std::string& value) + { + std::regex regex("[0-9]+[^ ]+"); + std::smatch match_value; + Layout::LayoutVec4 result; + + std::vector splits = split(value, ' '); + int idx = 0; + for (auto& s : splits) + { + if (std::regex_search(value.begin(), value.end(), match_value, regex)) + { + if (idx == 0) + { + result.Left = GetUnit(s); + } + else if (idx == 1) + { + result.Right = GetUnit(s); + } + else if (idx == 2) + { + result.Top = GetUnit(s); + } + else + { + result.Bottom = GetUnit(s); + } + idx++; + } + } + return result; + } + + static Color GetColor(const std::string& value) + { + std::regex regex("[0-9]+[^ ]+"); + std::smatch match_value; + Color result; + + std::vector splits = split(value, ' '); + int idx = 0; + for (auto& s : splits) + { + if (std::regex_search(value.begin(), value.end(), match_value, regex)) + { + if (idx == 0) + { + result.r = std::stof(s); + } + else if (idx == 1) + { + result.g = std::stof(s); + } + else if (idx == 2) + { + result.b = std::stof(s); + } + else + { + result.a = std::stof(s); + } + idx++; + } + } + return result; + } + + + static Ref CreateCanvas(const pugi::xml_node& xml_node) + { + Ref node = CreateRef(); + for (auto& a : xml_node.attributes()) + { + std::string name = a.name(); + if (name == "height") + node->Height = GetUnit(a.value()); + if (name == "width") + node->Width = GetUnit(a.value()); + if (name == "margin") + node->Margin = GetVec4Unit(a.value()); + if (name == "padding") + node->Padding = GetVec4Unit(a.value()); + if (name == "border") + node->Border = GetVec4Unit(a.value()); + if (name == "position") + node->Position = GetVec4Unit(a.value()); + if (name == "color") + node->BackgroundColor = GetColor(a.value()); + + } + + return node; + + } }; \ No newline at end of file diff --git a/Nuake/src/UI/Node.cpp b/Nuake/src/UI/Node.cpp index 0f8b90e6..e0d1567c 100644 --- a/Nuake/src/UI/Node.cpp +++ b/Nuake/src/UI/Node.cpp @@ -12,9 +12,9 @@ Node::Node() FlexDirection = Layout::FlexDirection::ROW; FlexWrap = Layout::FlexWrap::WRAP; FlexGrow = 0.f; - FlexShrink = 0.f; - FlexBasis = 0.f; - AspectRatio = 0.f; + FlexShrink = 1.f; + FlexBasis = 10.f; + AspectRatio = 1.f; AlignItems = Layout::AlignItems::FLEX_START; SelfAlign = Layout::AlignItems::FLEX_START; } \ No newline at end of file diff --git a/Nuake/src/UI/Node.h b/Nuake/src/UI/Node.h index 67f58eea..5a2ef59c 100644 --- a/Nuake/src/UI/Node.h +++ b/Nuake/src/UI/Node.h @@ -1,11 +1,14 @@ #pragma once #include #include "../Core/Core.h" +#include "yoga/Yoga.h" +#include "../Rendering/Renderer2D.h" +#include "../Core/Logger.h" namespace Layout { enum class LayoutDirection { - LTR, RTL + LTR = 2, RTL = 3 }; enum class FlexWrap @@ -35,7 +38,7 @@ namespace Layout enum class PositionType { - RELATIVE, ABSOLUTE + STATIC, RELATIVE, ABSOLUTE }; enum Unit @@ -63,20 +66,25 @@ namespace Layout class Node { public: - std::vector> Childrens; + Ref Parent; + YGNodeRef YogaNode; + std::vector> Childrens = std::vector>(); + Layout::PositionType PositionType; Layout::LayoutVec4 Position; - Layout::LayoutUnit With, MaxWidth, MinWidth; + Layout::LayoutUnit Width, MaxWidth, MinWidth; Layout::LayoutUnit Height, MaxHeight, MinHeight; Layout::LayoutVec4 Margin; Layout::LayoutVec4 Padding; Layout::LayoutVec4 Border; + Color BackgroundColor; + Layout::LayoutDirection Direction; - Layout::FlexDirection FlexDirection; + Layout::FlexDirection FlexDirection = Layout::FlexDirection::ROW; Layout::FlexWrap FlexWrap; float FlexGrow; @@ -88,5 +96,220 @@ public: Layout::AlignItems SelfAlign; Node(); -}; + void SetMargin() + { + switch (Margin.Left.Unit) + { + case Layout::Unit::PIXEL: + YGNodeStyleSetMargin(YogaNode, YGEdgeLeft, Margin.Left.Value); + break; + case Layout::Unit::PERCENT: + YGNodeStyleSetMarginPercent(YogaNode, YGEdgeLeft, Margin.Left.Value); + break; + case Layout::Unit::AUTO: + YGNodeStyleSetMarginAuto(YogaNode, YGEdgeLeft); + break; + } + + switch (Margin.Right.Unit) + { + case Layout::Unit::PIXEL: + YGNodeStyleSetMargin(YogaNode, YGEdgeRight, Margin.Right.Value); + break; + case Layout::Unit::PERCENT: + YGNodeStyleSetMarginPercent(YogaNode, YGEdgeRight, Margin.Right.Value); + break; + case Layout::Unit::AUTO: + YGNodeStyleSetMarginAuto(YogaNode, YGEdgeRight); + break; + } + + switch (Margin.Top.Unit) + { + case Layout::Unit::PIXEL: + YGNodeStyleSetMargin(YogaNode, YGEdgeTop, Margin.Top.Value); + break; + case Layout::Unit::PERCENT: + YGNodeStyleSetMarginPercent(YogaNode, YGEdgeTop, Margin.Top.Value); + break; + case Layout::Unit::AUTO: + YGNodeStyleSetMarginAuto(YogaNode, YGEdgeTop); + break; + } + + switch (Margin.Bottom.Unit) + { + case Layout::Unit::PIXEL: + YGNodeStyleSetMargin(YogaNode, YGEdgeBottom, Margin.Bottom.Value); + break; + case Layout::Unit::PERCENT: + YGNodeStyleSetMarginPercent(YogaNode, YGEdgeBottom, Margin.Bottom.Value); + break; + case Layout::Unit::AUTO: + YGNodeStyleSetMarginAuto(YogaNode, YGEdgeTop); + break; + } + + } + + void SetPadding() + { + switch (Padding.Left.Unit) + { + case Layout::Unit::PIXEL: + YGNodeStyleSetPadding(YogaNode, YGEdgeLeft, Padding.Left.Value); + break; + case Layout::Unit::PERCENT: + YGNodeStyleSetPaddingPercent(YogaNode, YGEdgeLeft, Padding.Left.Value); + break; + } + + switch (Padding.Right.Unit) + { + case Layout::Unit::PIXEL: + YGNodeStyleSetPadding(YogaNode, YGEdgeRight, Padding.Right.Value); + break; + case Layout::Unit::PERCENT: + YGNodeStyleSetPaddingPercent(YogaNode, YGEdgeRight, Padding.Right.Value); + break; + } + + switch (Padding.Top.Unit) + { + case Layout::Unit::PIXEL: + YGNodeStyleSetPadding(YogaNode, YGEdgeTop, Padding.Top.Value); + break; + case Layout::Unit::PERCENT: + YGNodeStyleSetPaddingPercent(YogaNode, YGEdgeTop, Padding.Top.Value); + break; + } + + switch (Padding.Bottom.Unit) + { + case Layout::Unit::PIXEL: + YGNodeStyleSetPadding(YogaNode, YGEdgeBottom, Padding.Bottom.Value); + break; + case Layout::Unit::PERCENT: + YGNodeStyleSetPaddingPercent(YogaNode, YGEdgeBottom, Padding.Bottom.Value); + break; + } + } + + void SetBorder() + { + switch (Border.Left.Unit) + { + case Layout::Unit::PIXEL: + YGNodeStyleSetBorder(YogaNode, YGEdgeLeft, Border.Left.Value); + break; + } + + switch (Border.Right.Unit) + { + case Layout::Unit::PIXEL: + YGNodeStyleSetBorder(YogaNode, YGEdgeRight, Border.Right.Value); + break; + } + + switch (Border.Top.Unit) + { + case Layout::Unit::PIXEL: + YGNodeStyleSetBorder(YogaNode, YGEdgeTop, Border.Top.Value); + break; + } + + switch (Border.Bottom.Unit) + { + case Layout::Unit::PIXEL: + YGNodeStyleSetBorder(YogaNode, YGEdgeBottom, Border.Bottom.Value); + break; + } + } + + void SetYogaLayout() + { + switch (Width.Unit) + { + case Layout::Unit::PIXEL: + YGNodeStyleSetWidth(YogaNode, Width.Value); + break; + case Layout::Unit::PERCENT: + YGNodeStyleSetWidthPercent(YogaNode, Width.Value); + break; + case Layout::Unit::AUTO: + YGNodeStyleSetWidthAuto(YogaNode); + break; + } + + switch (Height.Unit) + { + case Layout::Unit::PIXEL: + YGNodeStyleSetHeight(YogaNode, Height.Value); + break; + case Layout::Unit::PERCENT: + YGNodeStyleSetHeightPercent(YogaNode, Height.Value); + break; + case Layout::Unit::AUTO: + YGNodeStyleSetHeightAuto(YogaNode); + break; + } + + SetMargin(); + SetPadding(); + SetBorder(); + + YGNodeStyleSetFlexWrap(YogaNode, YGWrapWrap); + YGNodeStyleSetFlexDirection(YogaNode, YGFlexDirectionRow); + YGNodeStyleSetJustifyContent(YogaNode, YGJustifyFlexStart); + } + + void Draw(float z, Vector2 offset) + { + Color color = this->BackgroundColor; + Renderer2D::UIShader->SetUniform4f("background_color", + color.r / 255.f, + color.g / 255.f, + color.b / 255.f, + color.a / 255.f); + + // Get transform + Matrix4 transform = Matrix4(1.0f); + + float width = YGNodeLayoutGetWidth(YogaNode); + float height = YGNodeLayoutGetHeight(YogaNode); + float padding = YGNodeLayoutGetPadding(YogaNode, YGEdgeLeft); + float left = YGNodeLayoutGetLeft(YogaNode); //+ offset.x; + float top = YGNodeLayoutGetTop(YogaNode);// +offset.y; + + + float parentLeft = 0.0f; + float parentTop = 0.0f; + auto parent = YGNodeGetParent(YogaNode); + if (parent) + { + parentLeft = YGNodeLayoutGetLeft(YGNodeGetParent(YogaNode)); + parentTop = YGNodeLayoutGetTop(YGNodeGetParent(YogaNode)); + float parentPaddingTop = YGNodeLayoutGetPadding(parent, YGEdgeTop); + float parentPaddingLeft = YGNodeLayoutGetPadding(parent, YGEdgeTop); + // Overflow hidden. + float parentwidth = YGNodeLayoutGetWidth(parent); + if (parentwidth - YGNodeLayoutGetMargin(YogaNode, YGEdgeLeft) < width ) + width = parentwidth - parentPaddingLeft; + float parentHeight = YGNodeLayoutGetHeight(parent); + if (parentHeight < height) + height = parentHeight - YGNodeLayoutGetMargin(YogaNode, YGEdgeTop) - parentPaddingTop; + } + + transform = glm::translate(transform, Vector3(left + parentLeft, top + parentTop, 0.f)); + + + Vector3 scale = Vector3(width, height, 0); + transform = glm::scale(transform, scale); + + //Logger::Log("Left: " + std::to_string(left) + " Top:" + std::to_string(top)); + Renderer2D::UIShader->SetUniformMat4f("model", transform); + + Renderer2D::DrawRect(); + } +}; \ No newline at end of file diff --git a/Nuake/src/UI/UserInterface.cpp b/Nuake/src/UI/UserInterface.cpp index 61188148..824e1d6c 100644 --- a/Nuake/src/UI/UserInterface.cpp +++ b/Nuake/src/UI/UserInterface.cpp @@ -1,55 +1,45 @@ #include "UserInterface.h" -#include "yoga/Yoga.h" + #include #include "Stylesheet.h" +#include "yoga/YGConfig.h" +#include "InterfaceParser.h" namespace UI { - struct simple_walker : pugi::xml_tree_walker - { - virtual bool for_each(pugi::xml_node& node) - { - for (int i = 0; i < depth(); ++i) std::cout << " "; // indentation - - std::cout << node.type() << ": name='" << node.name() << "', value='" << node.value() << "'\n"; - - return true; // continue traversal - } - }; - UserInterface::UserInterface(const std::string& name) { m_Name = name; - pugi::xml_document doc; - // Parse xml document - pugi::xml_parse_result result = doc.load_file("resources/Interface/Testing.interface"); - std::cout << "Load result: " << result.description() << ", mesh name: " << doc.child("Canvas").attribute("size").value() << std::endl; - - auto childrends = doc.child("Canvas").children(); - simple_walker walker; - doc.traverse(walker); - Logger::Log("Hello"); + Root = InterfaceParser::Parse("resources/Interface/Testing.interface"); - // Create engine structure from document + if (!Root) + { + Logger::Log("Failed to generate interface structure"); + } + yoga_config = YGConfigNew(); + yoga_config->useWebDefaults = true; + CreateYogaLayout(); + } - // Convert engine structure to yoga + UserInterface::~UserInterface() + { + YGConfigFree(yoga_config); + if (yoga_root) + YGNodeFreeRecursive(yoga_root); + } + void UserInterface::Reload() + { + Root = InterfaceParser::Parse("resources/Interface/Testing.interface"); + if (!Root) + { + Logger::Log("Failed to generate interface structure"); + } - // Calculate layout - - - // Load css styling - - //Ref stylesheet = StyleSheet::New("resources/Interface/Testing.css"); - // Iterate through css file - - // Create style sheet data structure - - // When rendering load styles to shader - - // Render - + yoga_config = YGConfigNew(); + yoga_config->useWebDefaults = true; + CreateYogaLayout(); } Ref UserInterface::New(const std::string& name) @@ -57,17 +47,68 @@ namespace UI return CreateRef(name); } - void UserInterface::Calculate() + void UserInterface::Calculate(int available_width, int available_height) { - + YGNodeRef root = Root->YogaNode; + YGNodeCalculateLayout(root, available_width, available_height, YGDirectionLTR); } - void UserInterface::Draw() + void UserInterface::CreateYogaLayout() { - Renderer2D::BeginDraw(); - for (auto r : m_Rects) + yoga_root = YGNodeNewWithConfig(yoga_config); + Root->YogaNode = yoga_root; + Root->SetYogaLayout(); + CreateYogaLayoutRecursive(Root, yoga_root); + } + + + void UserInterface::CreateYogaLayoutRecursive(Ref node, YGNodeRef yoga_node) + { + if(node->Childrens.size() > 0) + YGNodeCalculateLayout(yoga_node, YGNodeLayoutGetWidth(yoga_node), YGNodeLayoutGetHeight(yoga_node), YGDirectionLTR); + int index = 0; + for (auto& n : node->Childrens) { - r->Draw(); + YGNodeRef newYogaNode = YGNodeNew(); + n->YogaNode = newYogaNode; + n->SetYogaLayout(); + YGNodeInsertChild(yoga_node, newYogaNode, index); + CreateYogaLayoutRecursive(n, newYogaNode); + index++; + } + + Logger::Log(std::to_string(YGNodeGetChildCount(yoga_node))); + } + + void UserInterface::Draw(Vector2 size) + { + Calculate(size.x, size.y); + Renderer2D::BeginDraw(size); + + float leftOffset = YGNodeLayoutGetLeft(Root->YogaNode); + float topOffset = YGNodeLayoutGetTop(Root->YogaNode); + + DrawRecursive(Root, 0, Vector2(leftOffset, topOffset)); + } + + void UserInterface::DrawRecursive(Ref node, float z, Vector2 offset) + { + if (!node) + return; + + node->Draw(z, offset); + + if (node->Childrens.size() <= 0) + return; + + offset.x += YGNodeLayoutGetLeft(Root->YogaNode); + + if(!YGNodeLayoutGetHadOverflow(Root->YogaNode)) + offset.y += YGNodeLayoutGetTop(Root->YogaNode); + + for (auto& c : node->Childrens) + { + DrawRecursive(c, z + 1, offset); } } diff --git a/Nuake/src/UI/UserInterface.h b/Nuake/src/UI/UserInterface.h index cc5ee104..d4c89380 100644 --- a/Nuake/src/UI/UserInterface.h +++ b/Nuake/src/UI/UserInterface.h @@ -2,57 +2,36 @@ #include #include #include - +#include "yoga/Yoga.h" +#include "Node.h" +#include +#include "../Core/Maths.h" namespace UI { class UserInterface { private: - std::vector> m_Rects; Ref m_Framebuffer; // Texture of the interface. std::string m_Name; - + Ref Root; + YGConfigRef yoga_config; + YGNodeRef yoga_root; public: const int Width = 1920; const int Height = 1080; UserInterface(const std::string& name); + ~UserInterface(); + void Reload(); static Ref New(const std::string& name); - void Calculate(); - void Draw(); + void Calculate(int available_width, int available_height); + + void CreateYogaLayout(); + void CreateYogaLayoutRecursive(Ref node, YGNodeRef yoga_node); + void Draw(Vector2 size); + void DrawRecursive(Ref node, float z, Vector2 offset); void Update(Timestep ts); - - std::vector> GetRects() - { - return m_Rects; - } - - void AddRect(Ref rect) - { - m_Rects.push_back(rect); - } - - Ref GetRectByID(const std::string& id) - { - for (auto r : m_Rects) - { - if (r->GetID() == id) - return r; - } - return nullptr; - } - - std::vector> GetRectsByGroup(const std::string& group) - { - std::vector> rects = std::vector>(); - for (auto r : m_Rects) - { - if(r->HasGroup(group)) - rects.push_back(r); - } - return rects; - } }; } \ No newline at end of file diff --git a/Nuake/src/Vendors/yoga/Yoga.h b/Nuake/src/Vendors/yoga/Yoga.h index 86cd65e2..8eb61f56 100644 --- a/Nuake/src/Vendors/yoga/Yoga.h +++ b/Nuake/src/Vendors/yoga/Yoga.h @@ -360,7 +360,6 @@ WIN_EXPORT float YGRoundValueToPixelGrid( YG_EXTERN_C_END #ifdef __cplusplus - #include #include diff --git a/Nuake/src/Window.cpp b/Nuake/src/Window.cpp index 3cd67399..55c3ffb8 100644 --- a/Nuake/src/Window.cpp +++ b/Nuake/src/Window.cpp @@ -244,6 +244,8 @@ void Window::Draw() m_Scene->Draw(); else m_Scene->EditorDraw(); + + m_Scene->DrawInterface(m_Framebuffer->GetSize()); } m_Framebuffer->Unbind(); }