refactor layout loading to add multiple layout, templates and references

This commit is contained in:
2017-02-01 20:35:57 +00:00
parent ed02e38805
commit 70792669e7
5 changed files with 97 additions and 51 deletions

View File

@@ -1,5 +1,8 @@
<?xml version="1.0"?>
<layout>
<layout id="button">
</layout>
<layout id="main">
<node dir="col" wrap="0" width="100%" height="100%" pad="5">
<!-- toolbar -->
<border height="50" width="100%" pad="5" dir="row" color=".2">
@@ -34,8 +37,8 @@
</plane>
<!-- content panel -->
<plane width="1" grow="1" height="100%" pad="30" wrap="1">
<border thickness="5" border-color="1" color=".4" height="100%">
<shape type="round-rect" width="100%" height="100%"></shape>
<border thickness="5" border-color="1" color=".4" height="100%" pad="10">
<shape type="round-rect" border-color=".5" thickness="4" width="100%" height="100%"></shape>
</border>
</plane>
</plane>

View File

@@ -75,7 +75,7 @@ void App::init()
#endif
layout.load("data/layout.xml");
layout.update(width, height);
//layout.update(width, height);
sampler.create();
ShaderManager::create(kShader::Texture, shader_v, shader_f);
@@ -123,16 +123,16 @@ void App::update(float dt)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_SCISSOR_TEST);
for (auto& n : layout)
{
if (n.m_widget)
{
auto box = n.m_widget->clip;
glScissor(box.x, height - box.y - box.w, box.z, box.w);
n.m_widget->draw();
}
}
// for (auto& n : layout)
// {
//
// if (n.m_widget)
// {
// auto box = n.m_widget->clip;
// glScissor(box.x, height - box.y - box.w, box.z, box.w);
// n.m_widget->draw();
// }
// }
glDisable(GL_SCISSOR_TEST);
tex.unbind();
sampler.unbind();
@@ -142,7 +142,7 @@ void App::resize(float w, float h)
{
width = w;
height = h;
layout.update(width, height);
// layout.update(width, height);
}
void App::mouse_down(int button, float x, float y)

View File

@@ -9,7 +9,7 @@ class App
{
Sampler sampler;
Texture2D tex;
Node layout;
LayoutManager layout;
public:
static App I;
float width;

View File

@@ -21,7 +21,26 @@ void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj)
float h = YGNodeLayoutGetHeight(y_node);
m_pos = origin + glm::vec2(x, y);
m_size = glm::vec2(w, h);
m_clip = !parent ? glm::vec4(m_pos, m_size) : rect_intersection(glm::vec4(m_pos, m_size), parent->m_clip);
if (parent)
{
// correct the padding clip
// should not clip the padded area
// useful to draw decorations
float pt = YGNodeLayoutGetPadding(parent->y_node, YGEdgeTop);
float pr = YGNodeLayoutGetPadding(parent->y_node, YGEdgeRight);
float pb = YGNodeLayoutGetPadding(parent->y_node, YGEdgeBottom);
float pl = YGNodeLayoutGetPadding(parent->y_node, YGEdgeLeft);
glm::vec2 off_p(pl, pt);
glm::vec2 off_s(pr, pb);
m_clip = glm::vec4(m_pos - off_p, m_size + off_p + off_s);
m_clip = rect_intersection(m_clip, parent->m_clip);
}
else
{
m_clip = glm::vec4(m_pos, m_size);
}
if (m_widget)
{
glm::mat4 pivot = glm::translate(glm::vec3(.5f, .5f, 0.f));
@@ -151,26 +170,6 @@ void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
}
}
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;
m_children.clear();
YGNodeReset(y_node);
tinyxml2::XMLDocument xml;
auto ret = xml.LoadFile(path);
if (ret != tinyxml2::XMLError::XML_SUCCESS)
return;
load_internal(xml.RootElement());
}
void Node::load_internal(const tinyxml2::XMLElement* x_node)
{
m_name = x_node->Name();
@@ -209,12 +208,53 @@ void Node::load_internal(const tinyxml2::XMLElement* x_node)
}
}
void Node::reload()
bool LayoutManager::load(const char* path)
{
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);
struct stat tmp_info;
if (stat(path, &tmp_info) != 0)
return false;
if (tmp_info.st_mtime <= m_file_info.st_mtime)
return false;
m_file_info = tmp_info;
m_path = path;
m_layouts.clear();
tinyxml2::XMLDocument xml;
auto ret = xml.LoadFile(path);
if (ret != tinyxml2::XMLError::XML_SUCCESS)
return false;
tinyxml2::XMLElement* current = xml.RootElement();
while (current)
{
auto id_str = current->Attribute("id");
if (!id_str)
{
printf("Layout node without id\n");
return false;
}
uint16_t id = const_hash(id_str);
auto p = m_layouts.try_emplace(id);
if (p.second)
{
auto& node = p.first->second;
node.load_internal(current);
}
else
{
printf("Layout id \"%s\" duplicated\n", id_str);
}
current = current->NextSiblingElement("layout");
}
}
void LayoutManager::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);
}

View File

@@ -39,7 +39,6 @@ enum class kShapeType : uint16_t
Poly = const_hash("poly"),
RoundRect = const_hash("round-rect"),
Slice9 = const_hash("slice9"),
};
class Widget
@@ -185,8 +184,6 @@ class Node
{
const Node* parent{ nullptr };
YGNodeRef y_node{ nullptr };
struct stat m_file_info { 0 };
std::string m_path;
public:
std::vector<Node> m_children;
@@ -201,7 +198,6 @@ public:
Node(Node&& o)
{
m_name = std::move(o.m_name);
m_path = std::move(o.m_path);
m_widget = std::move(o.m_widget);
m_children = std::move(o.m_children);
for (auto& c : m_children)
@@ -211,7 +207,6 @@ public:
m_pos = o.m_pos;
m_size = o.m_size;
m_clip = o.m_clip;
m_file_info = o.m_file_info;
o.y_node = nullptr;
o.parent = nullptr;
}
@@ -254,9 +249,7 @@ public:
void update(float width, float height);
void update_internal(const glm::vec2& origin, const glm::mat4& proj);
void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr);
void load(const char* path);
void load_internal(const tinyxml2::XMLElement* x_node);
void reload();
void draw();
class iterator
@@ -292,3 +285,13 @@ public:
return nullptr;
}
};
class LayoutManager
{
std::map<uint16_t, Node> m_layouts;
std::string m_path;
struct stat m_file_info { 0 };
public:
bool load(const char* path);
void reload();
};