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