complete refactoring and cleanup old layout loading code
This commit is contained in:
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);
|
||||
}
|
||||
Reference in New Issue
Block a user