refactor layout loading to add multiple layout, templates and references
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -9,7 +9,7 @@ class App
|
||||
{
|
||||
Sampler sampler;
|
||||
Texture2D tex;
|
||||
Node layout;
|
||||
LayoutManager layout;
|
||||
public:
|
||||
static App I;
|
||||
float width;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user