complete refactoring and cleanup old layout loading code
This commit is contained in:
@@ -19,13 +19,13 @@
|
|||||||
<plane grow="1" dir="row" wrap="1" height="0">
|
<plane grow="1" dir="row" wrap="1" height="0">
|
||||||
<!-- side bar -->
|
<!-- side bar -->
|
||||||
<plane width="200" height="100%" dir="col" color=".2">
|
<plane width="200" height="100%" dir="col" color=".2">
|
||||||
<plane pad="15" margin="2 2 10 2" color=".3" width="100%" height="auto">
|
<plane pad="15" margin="0 0 10 0" color=".3" width="100%" height="auto">
|
||||||
<plane height="30" color=".4" />
|
<plane height="30" color=".4" />
|
||||||
<plane height="30" color=".4" />
|
<plane height="30" color=".4" />
|
||||||
<plane height="30" color=".4" />
|
<plane height="30" color=".4" />
|
||||||
<plane height="30" color=".4" />
|
<plane height="30" color=".4" />
|
||||||
</plane>
|
</plane>
|
||||||
<plane pad="15" margin="2 2 10 2" color=".3" width="100%" height="auto">
|
<plane pad="15" margin="0 0 10 0" color=".3" width="100%" height="auto">
|
||||||
<plane height="30" color=".4" />
|
<plane height="30" color=".4" />
|
||||||
<plane height="30" color=".4" />
|
<plane height="30" color=".4" />
|
||||||
<plane height="30" color=".4" />
|
<plane height="30" color=".4" />
|
||||||
|
|||||||
@@ -152,6 +152,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="engine\app.cpp" />
|
<ClCompile Include="engine\app.cpp" />
|
||||||
<ClCompile Include="engine\image.cpp" />
|
<ClCompile Include="engine\image.cpp" />
|
||||||
|
<ClCompile Include="engine\layout.cpp" />
|
||||||
<ClCompile Include="engine\main.cpp" />
|
<ClCompile Include="engine\main.cpp" />
|
||||||
<ClCompile Include="engine\pch.cpp">
|
<ClCompile Include="engine\pch.cpp">
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||||
@@ -184,6 +185,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="engine\app.hpp" />
|
<ClInclude Include="engine\app.hpp" />
|
||||||
<ClInclude Include="engine\image.hpp" />
|
<ClInclude Include="engine\image.hpp" />
|
||||||
|
<ClInclude Include="engine\layout.h" />
|
||||||
<ClInclude Include="engine\pch.h" />
|
<ClInclude Include="engine\pch.h" />
|
||||||
<ClInclude Include="engine\shader.hpp" />
|
<ClInclude Include="engine\shader.hpp" />
|
||||||
<ClInclude Include="engine\shape.hpp" />
|
<ClInclude Include="engine\shape.hpp" />
|
||||||
|
|||||||
@@ -45,6 +45,9 @@
|
|||||||
<ClCompile Include="libs\yoga\yoga\Yoga.c">
|
<ClCompile Include="libs\yoga\yoga\Yoga.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="engine\layout.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="engine\app.hpp">
|
<ClInclude Include="engine\app.hpp">
|
||||||
@@ -65,5 +68,8 @@
|
|||||||
<ClInclude Include="engine\texture.hpp">
|
<ClInclude Include="engine\texture.hpp">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="engine\layout.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
631
engine/app.cpp
631
engine/app.cpp
@@ -9,533 +9,6 @@ void App::create()
|
|||||||
height = 500;
|
height = 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec4 rect_intersection(glm::vec4 a, glm::vec4 b)
|
|
||||||
{
|
|
||||||
// convert from [x,y,w,h] to [x1,y1,x2,y1]
|
|
||||||
a = glm::vec4(a.xy(), a.xy() + a.zw());
|
|
||||||
b = glm::vec4(b.xy(), b.xy() + b.zw());
|
|
||||||
auto o = glm::vec4(glm::max(a.xy(), b.xy()), glm::min(a.zw(), b.zw()));
|
|
||||||
o = glm::vec4(o.xy(), glm::max({ 0, 0 }, o.zw() - o.xy()));
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Node
|
|
||||||
{
|
|
||||||
const Node* parent{ nullptr };
|
|
||||||
YGNodeRef y_node{ nullptr };
|
|
||||||
struct stat m_file_info { 0 };
|
|
||||||
|
|
||||||
public:
|
|
||||||
std::vector<Node> 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<Node>(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<YGNodeRef, tinyxml2::XMLElement*>;
|
|
||||||
std::stack<NodePair> 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);
|
|
||||||
std::stack<YGNodeRef> y_stack;
|
|
||||||
y_stack.push(y_root);
|
|
||||||
auto y_current = y_root;
|
|
||||||
while (y_current)
|
|
||||||
{
|
|
||||||
y_stack.pop();
|
|
||||||
auto ctx = reinterpret_cast<glm::vec4*>(YGNodeGetContext(y_current));
|
|
||||||
if (!ctx)
|
|
||||||
{
|
|
||||||
ctx = new glm::vec4();
|
|
||||||
YGNodeSetContext(y_current, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y_current == y_root)
|
|
||||||
{
|
|
||||||
ctx->x = YGNodeLayoutGetLeft(y_current);
|
|
||||||
ctx->y = YGNodeLayoutGetTop(y_current);
|
|
||||||
ctx->z = YGNodeLayoutGetWidth(y_current);
|
|
||||||
ctx->w = YGNodeLayoutGetHeight(y_current);
|
|
||||||
}
|
|
||||||
|
|
||||||
int n = YGNodeGetChildCount(y_current);
|
|
||||||
for (int i = 0; i < n; i++)
|
|
||||||
{
|
|
||||||
auto y_child = YGNodeGetChild(y_current, i);
|
|
||||||
auto ctx_child = reinterpret_cast<glm::vec4*>(YGNodeGetContext(y_child));
|
|
||||||
if (!ctx_child) ctx_child = new glm::vec4();
|
|
||||||
float x = YGNodeLayoutGetLeft(y_child);
|
|
||||||
float y = YGNodeLayoutGetTop(y_child);
|
|
||||||
float w = YGNodeLayoutGetWidth(y_child);
|
|
||||||
float h = YGNodeLayoutGetHeight(y_child);
|
|
||||||
ctx_child->x = ctx->x + x;
|
|
||||||
ctx_child->y = ctx->y + y;
|
|
||||||
ctx_child->z = w;
|
|
||||||
ctx_child->w = h;
|
|
||||||
*ctx_child = rect_intersection(*ctx_child, *ctx);
|
|
||||||
YGNodeSetContext(y_child, ctx_child);
|
|
||||||
y_stack.emplace(y_child);
|
|
||||||
}
|
|
||||||
y_current = y_stack.size() ? y_stack.top() : nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void App::load_layout()
|
|
||||||
{
|
|
||||||
struct stat tmp_info;
|
|
||||||
if (stat("data/layout.xml", &tmp_info) != 0)
|
|
||||||
return;
|
|
||||||
if (tmp_info.st_mtime <= g_file_info.st_mtime)
|
|
||||||
return;
|
|
||||||
g_file_info = tmp_info;
|
|
||||||
|
|
||||||
if (y_root)
|
|
||||||
YGNodeFreeRecursive(y_root);
|
|
||||||
shapes_list.clear();
|
|
||||||
|
|
||||||
y_root = YGNodeNew();
|
|
||||||
YGNodeStyleSetWidth(y_root, width);
|
|
||||||
//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);
|
|
||||||
//YGNodeStyleSetJustifyContent(y_root, YGJustifyFlexStart);
|
|
||||||
|
|
||||||
using NodePair = std::pair<YGNodeRef, tinyxml2::XMLElement*>;
|
|
||||||
std::stack<NodePair> stack;
|
|
||||||
|
|
||||||
tinyxml2::XMLDocument xml;
|
|
||||||
auto ret = xml.LoadFile("data/layout.xml");
|
|
||||||
auto x_root = xml.RootElement();
|
|
||||||
|
|
||||||
NodePair current = { y_root, x_root };
|
|
||||||
stack.push(current);
|
|
||||||
while (current.first && current.second)
|
|
||||||
{
|
|
||||||
stack.pop();
|
|
||||||
auto y_root = current.first;
|
|
||||||
auto child = current.second->FirstChildElement();
|
|
||||||
//YGNodeStyleSetPosition(y_root, YGEdgeAll, 0);
|
|
||||||
//YGNodeStyleSetPositionType(y_root, YGPositionTypeRelative);
|
|
||||||
while (child)
|
|
||||||
{
|
|
||||||
auto y_node = YGNodeNew();
|
|
||||||
stack.emplace(y_node, child);
|
|
||||||
auto attr = child->FirstAttribute();
|
|
||||||
std::unique_ptr<Plane> shape;
|
|
||||||
if (strcmp("plane", child->Name()) == 0)
|
|
||||||
{
|
|
||||||
shape = std::make_unique<Plane>();
|
|
||||||
shape->create<5>(100.f, 100.f);
|
|
||||||
shape->y_node = y_node;
|
|
||||||
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);
|
|
||||||
|
|
||||||
//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)
|
|
||||||
{
|
|
||||||
const auto ka = att::value(attr->Name());
|
|
||||||
printf("%s=%s ", attr->Name(), attr->Value());
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (shape)
|
|
||||||
shape->color = glm::vec4(pad.x);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (shape)
|
|
||||||
shape->color = pad;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
attr = attr->Next();
|
|
||||||
}
|
|
||||||
int n = YGNodeGetChildCount(y_root);
|
|
||||||
YGNodeInsertChild(y_root, y_node, n);
|
|
||||||
if (shape)
|
|
||||||
shapes_list.push_back(std::move(shape));
|
|
||||||
child = child->NextSiblingElement();
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
current = stack.size() ? stack.top() : NodePair{ nullptr, nullptr };
|
|
||||||
}
|
|
||||||
update_layout();
|
|
||||||
}
|
|
||||||
Node nn;
|
|
||||||
void App::init()
|
void App::init()
|
||||||
{
|
{
|
||||||
static const char* shader_v =
|
static const char* shader_v =
|
||||||
@@ -601,30 +74,15 @@ void App::init()
|
|||||||
glEnable(GL_DEBUG_OUTPUT);
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
load_layout();
|
layout.load("data/layout.xml");
|
||||||
nn.load("data/layout.xml");
|
layout.update(width, height);
|
||||||
nn.update(width, height);
|
|
||||||
|
|
||||||
for (auto& s : shapes_list)
|
|
||||||
{
|
|
||||||
float w = YGNodeLayoutGetWidth(s->y_node);
|
|
||||||
float h = YGNodeLayoutGetHeight(s->y_node);
|
|
||||||
float x = YGNodeLayoutGetLeft(s->y_node);
|
|
||||||
float y = YGNodeLayoutGetTop(s->y_node);
|
|
||||||
printf("layout w=%f h=%f x=%f y=%f\n", w, h, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
sampler.create();
|
sampler.create();
|
||||||
shader.create(shader_v, shader_f);
|
shader.create(shader_v, shader_f);
|
||||||
shader_color.create(shader_color_v, shader_color_f);
|
shader_color.create(shader_color_v, shader_color_f);
|
||||||
shader_uv.create(shader_v, shader_uv_f);
|
shader_uv.create(shader_v, shader_uv_f);
|
||||||
plane.create<5>(1, 1);
|
plane.create<5>(1, 1);
|
||||||
circle.create<10>(25);
|
|
||||||
circle2.create<10>(25, Circle::kUVMapping::Tube);
|
|
||||||
circle3.create<10>(25, 12, Circle::kUVMapping::Tube);
|
|
||||||
circle4.create<10>(25, 12, Circle::kUVMapping::Planar);
|
|
||||||
rounded.create<3>(50, 50, 10);
|
|
||||||
slice.create(50, 50, 10, .3f);
|
|
||||||
if (!tex.load("data/uvs.jpg"))
|
if (!tex.load("data/uvs.jpg"))
|
||||||
printf("error loading image\n");
|
printf("error loading image\n");
|
||||||
|
|
||||||
@@ -653,50 +111,12 @@ void App::update(float dt)
|
|||||||
{
|
{
|
||||||
glm::mat4 proj = glm::ortho(0.f, width, height, 0.f, -1.f, 1.f);
|
glm::mat4 proj = glm::ortho(0.f, width, height, 0.f, -1.f, 1.f);
|
||||||
|
|
||||||
//Shape* shapes[] = { &circle, &circle2, &circle3, &circle4, &plane, &rounded, &slice };
|
|
||||||
|
|
||||||
glClearColor(.1f, .1f, .1f, 1.f);
|
glClearColor(.1f, .1f, .1f, 1.f);
|
||||||
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
|
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
load_layout();
|
layout.reload();
|
||||||
|
|
||||||
/*
|
|
||||||
auto s = glm::scale(glm::vec3(1.5));
|
|
||||||
int h = 100;
|
|
||||||
for (int i = 0; i < sizeof(shapes)/sizeof(Shape*); i++)
|
|
||||||
{
|
|
||||||
shader.use();
|
|
||||||
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
tex.bind();
|
|
||||||
sampler.bind(0);
|
|
||||||
shader.u_int("tex", 0);
|
|
||||||
shader.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + h * 1, 75 + h * i, 0.f}) * s);
|
|
||||||
shapes[i]->draw_fill();
|
|
||||||
tex.unbind();
|
|
||||||
|
|
||||||
shader_color.use();
|
|
||||||
shader_color.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + h * 2, 75 + h * i, 0.f}) * s);
|
|
||||||
shader_color.u_vec4("col", {1, 1, 1, 1});
|
|
||||||
shapes[i]->draw_stroke();
|
|
||||||
|
|
||||||
shader_color.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + h * 0, 75 + h * i, 0.f}) * s);
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
||||||
shapes[i]->draw_fill();
|
|
||||||
|
|
||||||
shader_uv.use();
|
|
||||||
shader_uv.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + h * 3, 75 + h * i, 0.f}) * s);
|
|
||||||
shader_uv.u_int("tex", 0);
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
||||||
shapes[i]->draw_fill();
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
||||||
shader_uv.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + h * 4, 75 + h * i, 0.f}) * s);
|
|
||||||
shapes[i]->draw_fill();
|
|
||||||
tex.unbind();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
tex.bind();
|
tex.bind();
|
||||||
sampler.bind(0);
|
sampler.bind(0);
|
||||||
@@ -706,42 +126,10 @@ void App::update(float dt)
|
|||||||
shader_color.u_vec4("col", { .3f, .3f, .3f, 1 });
|
shader_color.u_vec4("col", { .3f, .3f, .3f, 1 });
|
||||||
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
// for (auto& s : shapes_list)
|
|
||||||
// {
|
|
||||||
// auto layout = *reinterpret_cast<glm::vec4*>(YGNodeGetContext(s->y_node));
|
|
||||||
// auto y_parent = YGNodeGetParent(s->y_node);
|
|
||||||
// if (y_parent && YGNodeGetContext(y_parent))
|
|
||||||
// {
|
|
||||||
// auto box = *reinterpret_cast<glm::vec4*>(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<Node*> nodes;
|
std::stack<Node*> nodes;
|
||||||
Node* current = &nn;
|
Node* current = &layout;
|
||||||
nodes.push(current);
|
nodes.push(current);
|
||||||
//glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
while (current)
|
while (current)
|
||||||
{
|
{
|
||||||
nodes.pop();
|
nodes.pop();
|
||||||
@@ -752,7 +140,7 @@ void App::update(float dt)
|
|||||||
auto mvp = proj * pos * scale * pivot;
|
auto mvp = proj * pos * scale * pivot;
|
||||||
|
|
||||||
auto box = current->m_clip;
|
auto box = current->m_clip;
|
||||||
glScissor(box.x, height - box.y - 1 - box.w, box.z, box.w);
|
glScissor(box.x, height - box.y - box.w, box.z, box.w);
|
||||||
|
|
||||||
shader_color.u_vec4("col", current->color);
|
shader_color.u_vec4("col", current->color);
|
||||||
shader_color.use();
|
shader_color.use();
|
||||||
@@ -796,10 +184,7 @@ void App::resize(float w, float h)
|
|||||||
{
|
{
|
||||||
width = w;
|
width = w;
|
||||||
height = h;
|
height = h;
|
||||||
YGNodeStyleSetWidth(y_root, width);
|
layout.update(width, height);
|
||||||
YGNodeStyleSetHeight(y_root, height);
|
|
||||||
update_layout();
|
|
||||||
nn.update(width, height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::mouse_down(int button, float x, float y)
|
void App::mouse_down(int button, float x, float y)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "shader.hpp"
|
#include "shader.hpp"
|
||||||
#include "shape.hpp"
|
#include "shape.hpp"
|
||||||
#include "texture.hpp"
|
#include "texture.hpp"
|
||||||
|
#include "layout.h"
|
||||||
|
|
||||||
class App
|
class App
|
||||||
{
|
{
|
||||||
@@ -11,13 +12,8 @@ class App
|
|||||||
Shader shader_color;
|
Shader shader_color;
|
||||||
Shader shader_uv;
|
Shader shader_uv;
|
||||||
Plane plane;
|
Plane plane;
|
||||||
std::vector<std::unique_ptr<Shape>> shapes_list;
|
|
||||||
Circle circle, circle2, circle3, circle4;
|
|
||||||
Rounded rounded;
|
|
||||||
Slice9 slice;
|
|
||||||
Texture2D tex;
|
Texture2D tex;
|
||||||
YGNodeRef y_root { nullptr };
|
Node layout;
|
||||||
struct stat g_file_info { 0 };
|
|
||||||
public:
|
public:
|
||||||
static App I;
|
static App I;
|
||||||
float width;
|
float width;
|
||||||
@@ -29,6 +25,4 @@ public:
|
|||||||
void mouse_down(int button, float x, float y);
|
void mouse_down(int button, float x, float y);
|
||||||
void mouse_move(float x, float y);
|
void mouse_move(float x, float y);
|
||||||
void mouse_up(int button, float x, float y);
|
void mouse_up(int button, float x, float y);
|
||||||
void update_layout();
|
|
||||||
void load_layout();
|
|
||||||
};
|
};
|
||||||
|
|||||||
206
engine/layout.cpp
Normal file
206
engine/layout.cpp
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "layout.h"
|
||||||
|
|
||||||
|
void Node::update(float width, float height)
|
||||||
|
{
|
||||||
|
YGNodeStyleSetWidth(y_node, width);
|
||||||
|
YGNodeStyleSetHeight(y_node, height);
|
||||||
|
YGNodeCalculateLayout(y_node, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||||
|
update_internal({ 0, 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::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 Node::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 Node::load(const char* path)
|
||||||
|
{
|
||||||
|
struct stat tmp_info;
|
||||||
|
if (stat(path, &tmp_info) != 0)
|
||||||
|
return;
|
||||||
|
if (tmp_info.st_mtime <= m_file_info.st_mtime)
|
||||||
|
return;
|
||||||
|
m_file_info = tmp_info;
|
||||||
|
m_path = path;
|
||||||
|
|
||||||
|
children.clear();
|
||||||
|
YGNodeReset(y_node);
|
||||||
|
|
||||||
|
tinyxml2::XMLDocument xml;
|
||||||
|
auto ret = xml.LoadFile(path);
|
||||||
|
load_internal(xml.RootElement());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::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 Node::reload()
|
||||||
|
{
|
||||||
|
float w = YGNodeLayoutGetWidth(y_node);
|
||||||
|
float h = YGNodeLayoutGetHeight(y_node);
|
||||||
|
// avoid conflict when assigning the same string from c_str
|
||||||
|
std::string path_copy = m_path;
|
||||||
|
load(path_copy.c_str());
|
||||||
|
update(w, h);
|
||||||
|
}
|
||||||
171
engine/layout.h
Normal file
171
engine/layout.h
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace att
|
||||||
|
{
|
||||||
|
enum class kAttribute : uint8_t {
|
||||||
|
Width, MinWidth, MaxWidth,
|
||||||
|
Height, MinHeight, MaxHeight,
|
||||||
|
Divisions, InnerRadius, OuterRadius,
|
||||||
|
Grow, Shrink, FlexDir, FlexWrap,
|
||||||
|
Padding, Margin,
|
||||||
|
Color
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AttributeBase
|
||||||
|
{
|
||||||
|
kAttribute id;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<att::kAttribute, std::unique_ptr<att::AttributeBase>> AttrubutesMap;
|
||||||
|
|
||||||
|
template<kAttribute T, typename V>
|
||||||
|
struct Attribute : public AttributeBase
|
||||||
|
{
|
||||||
|
static const kAttribute static_id = T;
|
||||||
|
V value;
|
||||||
|
Attribute() : value{ 0 } { id = static_id; }
|
||||||
|
Attribute(V v) : value(v) { id = static_id; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct typemap
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
kAttribute value;
|
||||||
|
};
|
||||||
|
static constexpr typemap map[] =
|
||||||
|
{
|
||||||
|
{ "width", kAttribute::Width },
|
||||||
|
{ "min-width", kAttribute::MinWidth },
|
||||||
|
{ "max-width", kAttribute::MaxWidth },
|
||||||
|
{ "height", kAttribute::Height },
|
||||||
|
{ "min-height", kAttribute::MinHeight },
|
||||||
|
{ "max-height", kAttribute::MaxHeight },
|
||||||
|
{ "divisions", kAttribute::Divisions },
|
||||||
|
{ "inner-radius", kAttribute::InnerRadius },
|
||||||
|
{ "outer-radius", kAttribute::OuterRadius },
|
||||||
|
{ "grow", kAttribute::Grow },
|
||||||
|
{ "shrink", kAttribute::Shrink },
|
||||||
|
{ "dir", kAttribute::FlexDir },
|
||||||
|
{ "wrap", kAttribute::FlexWrap },
|
||||||
|
{ "pad", kAttribute::Padding },
|
||||||
|
{ "margin", kAttribute::Margin },
|
||||||
|
{ "color", kAttribute::Color },
|
||||||
|
};
|
||||||
|
static constexpr int map_size = sizeof(map) / sizeof(typemap) - 1;
|
||||||
|
constexpr bool same(const char* a, const char* b)
|
||||||
|
{
|
||||||
|
return (*a && *b) ? (*a == *b && same(a + 1, b + 1)) : !(*a || *b);
|
||||||
|
}
|
||||||
|
constexpr const kAttribute value(char const *name, int i = 0)
|
||||||
|
{
|
||||||
|
return ((i >= map_size) || same(map[i].name, name)) ?
|
||||||
|
map[i].value : value(name, i + 1);
|
||||||
|
}
|
||||||
|
constexpr const char* string(const kAttribute value, int i = 0)
|
||||||
|
{
|
||||||
|
return (map[i].value == value) ? map[i].name : string(value, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//constexpr const char* string(kAttribute a) { return names[(int)a]; }
|
||||||
|
|
||||||
|
// template<kAttribute T, typename V>
|
||||||
|
// constexpr const char* string(const Attribute<T, V> a) { return names[(int)a.id]; }
|
||||||
|
|
||||||
|
#define DECLARE_ATTRIBUTE(N,T) \
|
||||||
|
struct N : public Attribute<kAttribute::N,T> \
|
||||||
|
{ using Attribute<kAttribute::N,T>::Attribute; };
|
||||||
|
|
||||||
|
DECLARE_ATTRIBUTE(Width, float);
|
||||||
|
DECLARE_ATTRIBUTE(MinWidth, float);
|
||||||
|
DECLARE_ATTRIBUTE(MaxWidth, float);
|
||||||
|
DECLARE_ATTRIBUTE(Height, float);
|
||||||
|
DECLARE_ATTRIBUTE(MinHeight, float);
|
||||||
|
DECLARE_ATTRIBUTE(MaxHeight, float);
|
||||||
|
DECLARE_ATTRIBUTE(Divisions, int);
|
||||||
|
DECLARE_ATTRIBUTE(InnerRadius, float);
|
||||||
|
DECLARE_ATTRIBUTE(OuterRadius, float);
|
||||||
|
DECLARE_ATTRIBUTE(Grow, float);
|
||||||
|
DECLARE_ATTRIBUTE(Shrink, float);
|
||||||
|
DECLARE_ATTRIBUTE(FlexDir, int);
|
||||||
|
DECLARE_ATTRIBUTE(FlexWrap, int);
|
||||||
|
DECLARE_ATTRIBUTE(Padding, glm::vec4);
|
||||||
|
DECLARE_ATTRIBUTE(Margin, glm::vec4);
|
||||||
|
DECLARE_ATTRIBUTE(Color, glm::vec4);
|
||||||
|
|
||||||
|
#undef DECLARE_ATTRIBUTE
|
||||||
|
}
|
||||||
|
|
||||||
|
class Node
|
||||||
|
{
|
||||||
|
const Node* parent{ nullptr };
|
||||||
|
YGNodeRef y_node{ nullptr };
|
||||||
|
struct stat m_file_info { 0 };
|
||||||
|
std::string m_path;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::vector<Node> 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<Node>(o)); }
|
||||||
|
Node(Node&& o)
|
||||||
|
{
|
||||||
|
children = std::move(o.children);
|
||||||
|
for (auto& c : children)
|
||||||
|
c.parent = this;
|
||||||
|
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); }
|
||||||
|
|
||||||
|
glm::vec4 rect_intersection(glm::vec4 a, glm::vec4 b)
|
||||||
|
{
|
||||||
|
// convert from [x,y,w,h] to [x1,y1,x2,y1]
|
||||||
|
a = glm::vec4(a.xy(), a.xy() + a.zw());
|
||||||
|
b = glm::vec4(b.xy(), b.xy() + b.zw());
|
||||||
|
auto o = glm::vec4(glm::max(a.xy(), b.xy()), glm::min(a.zw(), b.zw()));
|
||||||
|
o = glm::vec4(o.xy(), glm::max({ 0, 0 }, o.zw() - o.xy()));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(float width, float height);
|
||||||
|
void update_internal(glm::vec2 origin);
|
||||||
|
void parse_attributes(att::kAttribute ka, const tinyxml2::XMLAttribute* attr);
|
||||||
|
void load(const char* path);
|
||||||
|
void load_internal(const tinyxml2::XMLElement* x_node);
|
||||||
|
void reload();
|
||||||
|
};
|
||||||
@@ -1,99 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "layout.h"
|
||||||
namespace att
|
|
||||||
{
|
|
||||||
enum class kAttribute : uint8_t {
|
|
||||||
Width, MinWidth, MaxWidth,
|
|
||||||
Height, MinHeight, MaxHeight,
|
|
||||||
Divisions, InnerRadius, OuterRadius,
|
|
||||||
Grow, Shrink, FlexDir, FlexWrap,
|
|
||||||
Padding, Margin,
|
|
||||||
Color
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AttributeBase
|
|
||||||
{
|
|
||||||
kAttribute id;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::map<att::kAttribute, std::unique_ptr<att::AttributeBase>> AttrubutesMap;
|
|
||||||
|
|
||||||
template<kAttribute T, typename V>
|
|
||||||
struct Attribute : public AttributeBase
|
|
||||||
{
|
|
||||||
static const kAttribute static_id = T;
|
|
||||||
V value;
|
|
||||||
Attribute() : value{0} { id = static_id; }
|
|
||||||
Attribute(V v) : value(v) { id = static_id; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct typemap
|
|
||||||
{
|
|
||||||
const char* name;
|
|
||||||
kAttribute value;
|
|
||||||
};
|
|
||||||
static constexpr typemap map[] =
|
|
||||||
{
|
|
||||||
{ "width", kAttribute::Width },
|
|
||||||
{ "min-width", kAttribute::MinWidth },
|
|
||||||
{ "max-width", kAttribute::MaxWidth },
|
|
||||||
{ "height", kAttribute::Height },
|
|
||||||
{ "min-height", kAttribute::MinHeight },
|
|
||||||
{ "max-height", kAttribute::MaxHeight },
|
|
||||||
{ "divisions", kAttribute::Divisions },
|
|
||||||
{ "inner-radius", kAttribute::InnerRadius },
|
|
||||||
{ "outer-radius", kAttribute::OuterRadius },
|
|
||||||
{ "grow", kAttribute::Grow },
|
|
||||||
{ "shrink", kAttribute::Shrink },
|
|
||||||
{ "dir", kAttribute::FlexDir },
|
|
||||||
{ "wrap", kAttribute::FlexWrap },
|
|
||||||
{ "pad", kAttribute::Padding },
|
|
||||||
{ "margin", kAttribute::Margin },
|
|
||||||
{ "color", kAttribute::Color },
|
|
||||||
};
|
|
||||||
constexpr int map_size = sizeof(map) / sizeof(typemap) - 1;
|
|
||||||
constexpr bool same(const char* a, const char* b)
|
|
||||||
{
|
|
||||||
return (*a && *b) ? (*a == *b && same(a + 1, b + 1)) : !(*a || *b);
|
|
||||||
}
|
|
||||||
constexpr const kAttribute value(char const *name, int i = 0)
|
|
||||||
{
|
|
||||||
return ((i >= map_size) || same(map[i].name, name)) ?
|
|
||||||
map[i].value : value(name, i + 1);
|
|
||||||
}
|
|
||||||
constexpr const char* string(const kAttribute value, int i = 0)
|
|
||||||
{
|
|
||||||
return (map[i].value == value) ? map[i].name : string(value, i + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//constexpr const char* string(kAttribute a) { return names[(int)a]; }
|
|
||||||
|
|
||||||
// template<kAttribute T, typename V>
|
|
||||||
// constexpr const char* string(const Attribute<T, V> a) { return names[(int)a.id]; }
|
|
||||||
|
|
||||||
#define DECLARE_ATTRIBUTE(N,T) \
|
|
||||||
struct N : public Attribute<kAttribute::N,T> \
|
|
||||||
{ using Attribute<kAttribute::N,T>::Attribute; };
|
|
||||||
|
|
||||||
DECLARE_ATTRIBUTE(Width, float);
|
|
||||||
DECLARE_ATTRIBUTE(MinWidth, float);
|
|
||||||
DECLARE_ATTRIBUTE(MaxWidth, float);
|
|
||||||
DECLARE_ATTRIBUTE(Height, float);
|
|
||||||
DECLARE_ATTRIBUTE(MinHeight, float);
|
|
||||||
DECLARE_ATTRIBUTE(MaxHeight, float);
|
|
||||||
DECLARE_ATTRIBUTE(Divisions, int);
|
|
||||||
DECLARE_ATTRIBUTE(InnerRadius, float);
|
|
||||||
DECLARE_ATTRIBUTE(OuterRadius, float);
|
|
||||||
DECLARE_ATTRIBUTE(Grow, float);
|
|
||||||
DECLARE_ATTRIBUTE(Shrink, float);
|
|
||||||
DECLARE_ATTRIBUTE(FlexDir, int);
|
|
||||||
DECLARE_ATTRIBUTE(FlexWrap, int);
|
|
||||||
DECLARE_ATTRIBUTE(Padding, glm::vec4);
|
|
||||||
DECLARE_ATTRIBUTE(Margin, glm::vec4);
|
|
||||||
DECLARE_ATTRIBUTE(Color, glm::vec4);
|
|
||||||
|
|
||||||
#undef DECLARE_ATTRIBUTE
|
|
||||||
}
|
|
||||||
|
|
||||||
class Shape
|
class Shape
|
||||||
{
|
{
|
||||||
@@ -104,8 +10,6 @@ protected:
|
|||||||
GLvoid* ioff[2]{ 0 };
|
GLvoid* ioff[2]{ 0 };
|
||||||
struct vertex_t { glm::vec4 pos; glm::vec2 uvs; };
|
struct vertex_t { glm::vec4 pos; glm::vec2 uvs; };
|
||||||
public:
|
public:
|
||||||
YGNodeRef y_node;
|
|
||||||
glm::vec4 color;
|
|
||||||
att::AttrubutesMap attribs;
|
att::AttrubutesMap attribs;
|
||||||
bool create_buffers(GLvoid* idx, GLvoid* vertices, int isize, int vsize);
|
bool create_buffers(GLvoid* idx, GLvoid* vertices, int isize, int vsize);
|
||||||
void draw_fill() const;
|
void draw_fill() const;
|
||||||
|
|||||||
Reference in New Issue
Block a user