From 81494cca6e35b86e7e4efa3c5516368e0b4a4553 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Thu, 26 Jan 2017 23:57:05 +0000 Subject: [PATCH] refactoring layout loader --- data/layout.xml | 2 +- engine/app.cpp | 369 ++++++++++++++++++++++++++++++++++++++++++------ engine/pch.h | 1 + 3 files changed, 329 insertions(+), 43 deletions(-) diff --git a/data/layout.xml b/data/layout.xml index 4d088c5..d960740 100644 --- a/data/layout.xml +++ b/data/layout.xml @@ -34,7 +34,7 @@ - + diff --git a/engine/app.cpp b/engine/app.cpp index 03e8a8b..f8c684b 100644 --- a/engine/app.cpp +++ b/engine/app.cpp @@ -19,6 +19,257 @@ glm::vec4 rect_intersection(glm::vec4 a, glm::vec4 b) return o; } +class Node +{ + const Node* parent{ nullptr }; + YGNodeRef y_node{ nullptr }; + struct stat m_file_info { 0 }; + +public: + std::vector children; + glm::vec4 color; + glm::vec2 m_pos; + glm::vec2 m_size; + glm::vec4 m_clip; + Node(const Node&) = delete; + Node& operator=(const Node&) = delete; + Node& operator=(Node&& o) { return Node(std::forward(o)); } + Node(Node&& o) + { + children = std::move(o.children); + parent = o.parent; + y_node = o.y_node; + m_pos = o.m_pos; + m_size = o.m_size; + m_clip = o.m_clip; + color = o.color; + m_file_info = o.m_file_info; + o.y_node = nullptr; + o.parent = nullptr; + } + Node() { y_node = YGNodeNew(); } + ~Node() + { +// children.clear(); + if (y_node) + YGNodeFree(y_node); + } + + void SetWidth(float value) { YGNodeStyleSetWidth(y_node, value); } + void SetWidthP(float value) { YGNodeStyleSetWidthPercent(y_node, value); } + void SetHeight(float value) { YGNodeStyleSetHeight(y_node, value); } + void SetHeightP(float value) { YGNodeStyleSetHeightPercent(y_node, value); } + + void SetPadding(float t, float r, float b, float l) + { + YGNodeStyleSetPadding(y_node, YGEdgeTop, t); + YGNodeStyleSetPadding(y_node, YGEdgeRight, r); + YGNodeStyleSetPadding(y_node, YGEdgeBottom, b); + YGNodeStyleSetPadding(y_node, YGEdgeLeft, l); + } + + void SetFlexGrow(float value) { YGNodeStyleSetFlexGrow(y_node, value); } + void SetFlexShrink(float value) { YGNodeStyleSetFlexShrink(y_node, value); } + void SetFlexDir(YGFlexDirection value) { YGNodeStyleSetFlexDirection(y_node, value); } + void SetFlexWrap(YGWrap value) { YGNodeStyleSetFlexWrap(y_node, value); } + + void update(float width, float height) + { + YGNodeStyleSetWidth(y_node, width); + YGNodeStyleSetHeight(y_node, height); + YGNodeCalculateLayout(y_node, YGUndefined, YGUndefined, YGDirectionLTR); + update_internal({ 0, 0 }); + } + + void update_internal(glm::vec2 origin) + { + float x = YGNodeLayoutGetLeft(y_node); + float y = YGNodeLayoutGetTop(y_node); + float w = YGNodeLayoutGetWidth(y_node); + float h = YGNodeLayoutGetHeight(y_node); + m_pos = origin + glm::vec2(x, y); + m_size = glm::vec2(w, h); + if (!parent) + m_clip = glm::vec4(m_pos, m_size); + else + m_clip = rect_intersection(glm::vec4(m_pos, m_size), parent->m_clip); + for (auto& c : children) + c.update_internal(m_pos); + } + + void parse_attributes(att::kAttribute ka, const tinyxml2::XMLAttribute* attr) + { + switch (ka) + { + case att::kAttribute::Width: + if (strcmp(attr->Value(), "auto") == 0) + { + YGNodeStyleSetWidth(y_node, YGUndefined); + YGNodeStyleSetWidthPercent(y_node, YGUndefined); + } + else + { + if (strchr(attr->Value(), '%')) + YGNodeStyleSetWidthPercent(y_node, attr->FloatValue()); + else + YGNodeStyleSetWidth(y_node, attr->FloatValue()); + } + break; + case att::kAttribute::MinWidth: + if (strchr(attr->Value(), '%')) + YGNodeStyleSetMinWidthPercent(y_node, attr->FloatValue()); + else + YGNodeStyleSetMinWidth(y_node, attr->FloatValue()); + break; + case att::kAttribute::MaxWidth: + YGNodeStyleSetMaxWidth(y_node, attr->FloatValue()); + break; + case att::kAttribute::Height: + if (strcmp(attr->Value(), "auto") == 0) + { + YGNodeStyleSetHeight(y_node, YGUndefined); + YGNodeStyleSetHeightPercent(y_node, YGUndefined); + } + else + { + if (strchr(attr->Value(), '%')) + YGNodeStyleSetHeightPercent(y_node, attr->FloatValue()); + else + YGNodeStyleSetHeight(y_node, attr->FloatValue()); + } + break; + case att::kAttribute::MinHeight: + YGNodeStyleSetMinHeight(y_node, attr->FloatValue()); + break; + case att::kAttribute::MaxHeight: + YGNodeStyleSetMaxHeight(y_node, attr->FloatValue()); + break; + case att::kAttribute::Grow: + YGNodeStyleSetFlexGrow(y_node, attr->FloatValue()); + break; + case att::kAttribute::Shrink: + YGNodeStyleSetFlexShrink(y_node, attr->FloatValue()); + break; + case att::kAttribute::FlexDir: + { + YGFlexDirection dir = YGFlexDirectionRow; + if (strcmp("col", attr->Value()) == 0) + dir = YGFlexDirectionColumn; + else if (strcmp("col-reverse", attr->Value()) == 0) + dir = YGFlexDirectionColumnReverse; + else if (strcmp("row", attr->Value()) == 0) + dir = YGFlexDirectionRow; + else if (strcmp("row-reverse", attr->Value()) == 0) + dir = YGFlexDirectionRowReverse; + YGNodeStyleSetFlexDirection(y_node, dir); + break; + } + case att::kAttribute::FlexWrap: + YGNodeStyleSetFlexWrap(y_node, attr->IntValue() ? YGWrapWrap : YGWrapNoWrap); + break; + case att::kAttribute::Padding: + { + glm::vec4 pad; + int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w); + if (n == 1) + { + YGNodeStyleSetPadding(y_node, YGEdgeTop, pad.x); + YGNodeStyleSetPadding(y_node, YGEdgeRight, pad.x); + YGNodeStyleSetPadding(y_node, YGEdgeBottom, pad.x); + YGNodeStyleSetPadding(y_node, YGEdgeLeft, pad.x); + } + else + { + YGNodeStyleSetPadding(y_node, YGEdgeTop, pad.x); + YGNodeStyleSetPadding(y_node, YGEdgeRight, pad.y); + YGNodeStyleSetPadding(y_node, YGEdgeBottom, pad.z); + YGNodeStyleSetPadding(y_node, YGEdgeLeft, pad.w); + } + break; + } + case att::kAttribute::Margin: + { + glm::vec4 pad; + int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w); + if (n == 1) + { + YGNodeStyleSetMargin(y_node, YGEdgeTop, pad.x); + YGNodeStyleSetMargin(y_node, YGEdgeRight, pad.x); + YGNodeStyleSetMargin(y_node, YGEdgeBottom, pad.x); + YGNodeStyleSetMargin(y_node, YGEdgeLeft, pad.x); + } + else + { + YGNodeStyleSetMargin(y_node, YGEdgeTop, pad.x); + YGNodeStyleSetMargin(y_node, YGEdgeRight, pad.y); + YGNodeStyleSetMargin(y_node, YGEdgeBottom, pad.z); + YGNodeStyleSetMargin(y_node, YGEdgeLeft, pad.w); + } + break; + } + case att::kAttribute::Color: + { + glm::vec4 pad; + int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w); + if (n == 1) + { + color = glm::vec4(pad.x); + } + else + { + color = pad; + } + break; + } + default: + // other_attributes_handler() + break; + } + } + + void load(const char* path) + { + struct stat tmp_info; + if (stat("data/layout.xml", &tmp_info) != 0) + return; + if (tmp_info.st_mtime <= m_file_info.st_mtime) + return; + m_file_info = tmp_info; + + children.clear(); + YGNodeReset(y_node); + + using NodePair = std::pair; + std::stack stack; + + tinyxml2::XMLDocument xml; + auto ret = xml.LoadFile(path); + load_internal(xml.RootElement()); + } + + void load_internal(const tinyxml2::XMLElement* x_node) + { + auto attr = x_node->FirstAttribute(); + while (attr) + { + parse_attributes(att::value(attr->Name()), attr); + attr = attr->Next(); + } + + auto x_child = x_node->FirstChildElement(); + while (x_child) + { + //Node n; + children.emplace_back(); + auto& n = children.back(); + n.parent = this; + YGNodeInsertChild(y_node, n.y_node, YGNodeGetChildCount(y_node)); + n.load_internal(x_child); + x_child = x_child->NextSiblingElement(); + } + } +}; + void App::update_layout() { YGNodeCalculateLayout(y_root, YGUndefined, YGUndefined, YGDirectionLTR); @@ -83,13 +334,13 @@ void App::load_layout() //YGNodeStyleSetWidthPercent(y_root, 100); YGNodeStyleSetHeight(y_root, height); //YGNodeStyleSetHeightPercent(y_root, 100); - YGNodeStyleSetFlexDirection(y_root, YGFlexDirectionRow); - YGNodeStyleSetFlexWrap(y_root, YGWrapWrap); - YGNodeStyleSetPadding(y_root, YGEdgeAll, 0); - YGNodeStyleSetPadding(y_root, YGEdgeTop, 0); - YGNodeStyleSetPadding(y_root, YGEdgeRight, 0); - YGNodeStyleSetPadding(y_root, YGEdgeBottom, 0); - YGNodeStyleSetPadding(y_root, YGEdgeLeft, 0); + //YGNodeStyleSetFlexDirection(y_root, YGFlexDirectionRow); + //YGNodeStyleSetFlexWrap(y_root, YGWrapWrap); + //YGNodeStyleSetPadding(y_root, YGEdgeAll, 0); + //YGNodeStyleSetPadding(y_root, YGEdgeTop, 0); + //YGNodeStyleSetPadding(y_root, YGEdgeRight, 0); + //YGNodeStyleSetPadding(y_root, YGEdgeBottom, 0); + //YGNodeStyleSetPadding(y_root, YGEdgeLeft, 0); //YGNodeStyleSetJustifyContent(y_root, YGJustifyFlexStart); using NodePair = std::pair; @@ -122,23 +373,23 @@ void App::load_layout() YGNodeSetContext(y_node, shape.get()); } printf("Element %s: ", child->Name()); - YGNodeStyleSetWidth(y_node, 0); - YGNodeStyleSetWidthPercent(y_node, 100); - YGNodeStyleSetHeight(y_node, 0); - YGNodeStyleSetHeightPercent(y_node, 100); - YGNodeStyleSetPadding(y_node, YGEdgeAll, 0); - YGNodeStyleSetPadding(y_node, YGEdgeTop, 0); - YGNodeStyleSetPadding(y_node, YGEdgeRight, 0); - YGNodeStyleSetPadding(y_node, YGEdgeBottom, 0); - YGNodeStyleSetPadding(y_node, YGEdgeLeft, 0); + //YGNodeStyleSetWidth(y_node, 0); + //YGNodeStyleSetWidthPercent(y_node, 100); + //YGNodeStyleSetHeight(y_node, 0); + //YGNodeStyleSetHeightPercent(y_node, 100); + //YGNodeStyleSetPadding(y_node, YGEdgeAll, 0); + //YGNodeStyleSetPadding(y_node, YGEdgeTop, 0); + //YGNodeStyleSetPadding(y_node, YGEdgeRight, 0); + //YGNodeStyleSetPadding(y_node, YGEdgeBottom, 0); + //YGNodeStyleSetPadding(y_node, YGEdgeLeft, 0); - YGNodeStyleSetPosition(y_node, YGEdgeAll, 0); - YGNodeStyleSetPosition(y_node, YGEdgeTop, 0); - YGNodeStyleSetPosition(y_node, YGEdgeRight, 0); - YGNodeStyleSetPosition(y_node, YGEdgeBottom, 0); - YGNodeStyleSetPosition(y_node, YGEdgeLeft, 0); - - YGNodeStyleSetOverflow(y_node, YGOverflowHidden); + //YGNodeStyleSetPosition(y_node, YGEdgeAll, 0); + //YGNodeStyleSetPosition(y_node, YGEdgeTop, 0); + //YGNodeStyleSetPosition(y_node, YGEdgeRight, 0); + //YGNodeStyleSetPosition(y_node, YGEdgeBottom, 0); + //YGNodeStyleSetPosition(y_node, YGEdgeLeft, 0); + // + //YGNodeStyleSetOverflow(y_node, YGOverflowHidden); while (attr) { @@ -284,7 +535,7 @@ void App::load_layout() } update_layout(); } - +Node nn; void App::init() { static const char* shader_v = @@ -351,6 +602,8 @@ void App::init() #endif load_layout(); + nn.load("data/layout.xml"); + nn.update(width, height); for (auto& s : shapes_list) { @@ -453,28 +706,55 @@ void App::update(float dt) shader_color.u_vec4("col", { .3f, .3f, .3f, 1 }); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - for (auto& s : shapes_list) +// for (auto& s : shapes_list) +// { +// auto layout = *reinterpret_cast(YGNodeGetContext(s->y_node)); +// auto y_parent = YGNodeGetParent(s->y_node); +// if (y_parent && YGNodeGetContext(y_parent)) +// { +// auto box = *reinterpret_cast(YGNodeGetContext(y_parent)); +// glEnable(GL_SCISSOR_TEST); +// glScissor(box.x, height - box.y - 1 - box.w, box.z, box.w); +// } +// //glScissor(10, height - 10 - 1 - 50, 480, 50); +// +// glm::mat4 pivot = glm::translate(glm::vec3(.5f, .5f, 0.f)); +// glm::mat4 scale = glm::scale(glm::vec3(layout.zw(), 1.f)); +// glm::mat4 pos = glm::translate(glm::vec3(layout.xy(), 0)); +// auto mvp = proj * pos * scale * pivot; +// +// //shader_uv.use(); +// //shader_uv.u_mat4("mvp", mvp); +// //plane.draw_fill(); +// +// shader_color.u_vec4("col", s->color); +// shader_color.use(); +// shader_color.u_mat4("mvp", mvp); +// plane.draw_fill(); +// +// shader_color.u_vec4("col", { 1, 1, 1, 1 }); +// shader_color.use(); +// shader_color.u_mat4("mvp", mvp); +// plane.draw_stroke(); +// glDisable(GL_SCISSOR_TEST); +// } + std::stack nodes; + Node* current = &nn; + nodes.push(current); + //glEnable(GL_SCISSOR_TEST); + while (current) { - auto layout = *reinterpret_cast(YGNodeGetContext(s->y_node)); - auto y_parent = YGNodeGetParent(s->y_node); - if (y_parent && YGNodeGetContext(y_parent)) - { - auto box = *reinterpret_cast(YGNodeGetContext(y_parent)); - glEnable(GL_SCISSOR_TEST); - glScissor(box.x, height - box.y - 1 - box.w, box.z, box.w); - } - //glScissor(10, height - 10 - 1 - 50, 480, 50); + nodes.pop(); glm::mat4 pivot = glm::translate(glm::vec3(.5f, .5f, 0.f)); - glm::mat4 scale = glm::scale(glm::vec3(layout.zw(), 1.f)); - glm::mat4 pos = glm::translate(glm::vec3(layout.xy(), 0)); + glm::mat4 scale = glm::scale(glm::vec3(current->m_size, 1.f)); + glm::mat4 pos = glm::translate(glm::vec3(current->m_pos, 0)); auto mvp = proj * pos * scale * pivot; - - //shader_uv.use(); - //shader_uv.u_mat4("mvp", mvp); - //plane.draw_fill(); - shader_color.u_vec4("col", s->color); + auto box = current->m_clip; + glScissor(box.x, height - box.y - 1 - box.w, box.z, box.w); + + shader_color.u_vec4("col", current->color); shader_color.use(); shader_color.u_mat4("mvp", mvp); plane.draw_fill(); @@ -483,8 +763,12 @@ void App::update(float dt) shader_color.use(); shader_color.u_mat4("mvp", mvp); plane.draw_stroke(); - glDisable(GL_SCISSOR_TEST); + + for (auto& c : current->children) + nodes.push(&c); + current = nodes.size() ? nodes.top() : nullptr; } + glDisable(GL_SCISSOR_TEST); tex.unbind(); sampler.unbind(); @@ -515,6 +799,7 @@ void App::resize(float w, float h) YGNodeStyleSetWidth(y_root, width); YGNodeStyleSetHeight(y_root, height); update_layout(); + nn.update(width, height); } void App::mouse_down(int button, float x, float y) diff --git a/engine/pch.h b/engine/pch.h index 038b910..4d4ce8b 100644 --- a/engine/pch.h +++ b/engine/pch.h @@ -5,6 +5,7 @@ #include #elif _WIN32 #define _USE_MATH_DEFINES + #define _CRT_SECURE_NO_WARNINGS #include #include #include