refactor layout loading to add multiple layout, templates and references
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<layout>
|
<layout id="button">
|
||||||
|
|
||||||
|
</layout>
|
||||||
|
<layout id="main">
|
||||||
<node dir="col" wrap="0" width="100%" height="100%" pad="5">
|
<node dir="col" wrap="0" width="100%" height="100%" pad="5">
|
||||||
<!-- toolbar -->
|
<!-- toolbar -->
|
||||||
<border height="50" width="100%" pad="5" dir="row" color=".2">
|
<border height="50" width="100%" pad="5" dir="row" color=".2">
|
||||||
@@ -34,8 +37,8 @@
|
|||||||
</plane>
|
</plane>
|
||||||
<!-- content panel -->
|
<!-- content panel -->
|
||||||
<plane width="1" grow="1" height="100%" pad="30" wrap="1">
|
<plane width="1" grow="1" height="100%" pad="30" wrap="1">
|
||||||
<border thickness="5" border-color="1" color=".4" height="100%">
|
<border thickness="5" border-color="1" color=".4" height="100%" pad="10">
|
||||||
<shape type="round-rect" width="100%" height="100%"></shape>
|
<shape type="round-rect" border-color=".5" thickness="4" width="100%" height="100%"></shape>
|
||||||
</border>
|
</border>
|
||||||
</plane>
|
</plane>
|
||||||
</plane>
|
</plane>
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ void App::init()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
layout.load("data/layout.xml");
|
layout.load("data/layout.xml");
|
||||||
layout.update(width, height);
|
//layout.update(width, height);
|
||||||
|
|
||||||
sampler.create();
|
sampler.create();
|
||||||
ShaderManager::create(kShader::Texture, shader_v, shader_f);
|
ShaderManager::create(kShader::Texture, shader_v, shader_f);
|
||||||
@@ -123,16 +123,16 @@ void App::update(float dt)
|
|||||||
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
for (auto& n : layout)
|
// for (auto& n : layout)
|
||||||
{
|
// {
|
||||||
|
//
|
||||||
if (n.m_widget)
|
// if (n.m_widget)
|
||||||
{
|
// {
|
||||||
auto box = n.m_widget->clip;
|
// auto box = n.m_widget->clip;
|
||||||
glScissor(box.x, height - box.y - box.w, box.z, box.w);
|
// glScissor(box.x, height - box.y - box.w, box.z, box.w);
|
||||||
n.m_widget->draw();
|
// n.m_widget->draw();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
tex.unbind();
|
tex.unbind();
|
||||||
sampler.unbind();
|
sampler.unbind();
|
||||||
@@ -142,7 +142,7 @@ void App::resize(float w, float h)
|
|||||||
{
|
{
|
||||||
width = w;
|
width = w;
|
||||||
height = h;
|
height = h;
|
||||||
layout.update(width, height);
|
// layout.update(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::mouse_down(int button, float x, float y)
|
void App::mouse_down(int button, float x, float y)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class App
|
|||||||
{
|
{
|
||||||
Sampler sampler;
|
Sampler sampler;
|
||||||
Texture2D tex;
|
Texture2D tex;
|
||||||
Node layout;
|
LayoutManager layout;
|
||||||
public:
|
public:
|
||||||
static App I;
|
static App I;
|
||||||
float width;
|
float width;
|
||||||
|
|||||||
@@ -21,7 +21,26 @@ void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj)
|
|||||||
float h = YGNodeLayoutGetHeight(y_node);
|
float h = YGNodeLayoutGetHeight(y_node);
|
||||||
m_pos = origin + glm::vec2(x, y);
|
m_pos = origin + glm::vec2(x, y);
|
||||||
m_size = glm::vec2(w, h);
|
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)
|
if (m_widget)
|
||||||
{
|
{
|
||||||
glm::mat4 pivot = glm::translate(glm::vec3(.5f, .5f, 0.f));
|
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)
|
void Node::load_internal(const tinyxml2::XMLElement* x_node)
|
||||||
{
|
{
|
||||||
m_name = x_node->Name();
|
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);
|
struct stat tmp_info;
|
||||||
float h = YGNodeLayoutGetHeight(y_node);
|
if (stat(path, &tmp_info) != 0)
|
||||||
// avoid conflict when assigning the same string from c_str
|
return false;
|
||||||
std::string path_copy = m_path;
|
if (tmp_info.st_mtime <= m_file_info.st_mtime)
|
||||||
load(path_copy.c_str());
|
return false;
|
||||||
update(w, h);
|
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"),
|
Poly = const_hash("poly"),
|
||||||
RoundRect = const_hash("round-rect"),
|
RoundRect = const_hash("round-rect"),
|
||||||
Slice9 = const_hash("slice9"),
|
Slice9 = const_hash("slice9"),
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Widget
|
class Widget
|
||||||
@@ -185,8 +184,6 @@ class Node
|
|||||||
{
|
{
|
||||||
const Node* parent{ nullptr };
|
const Node* parent{ nullptr };
|
||||||
YGNodeRef y_node{ nullptr };
|
YGNodeRef y_node{ nullptr };
|
||||||
struct stat m_file_info { 0 };
|
|
||||||
std::string m_path;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<Node> m_children;
|
std::vector<Node> m_children;
|
||||||
@@ -201,7 +198,6 @@ public:
|
|||||||
Node(Node&& o)
|
Node(Node&& o)
|
||||||
{
|
{
|
||||||
m_name = std::move(o.m_name);
|
m_name = std::move(o.m_name);
|
||||||
m_path = std::move(o.m_path);
|
|
||||||
m_widget = std::move(o.m_widget);
|
m_widget = std::move(o.m_widget);
|
||||||
m_children = std::move(o.m_children);
|
m_children = std::move(o.m_children);
|
||||||
for (auto& c : m_children)
|
for (auto& c : m_children)
|
||||||
@@ -211,7 +207,6 @@ public:
|
|||||||
m_pos = o.m_pos;
|
m_pos = o.m_pos;
|
||||||
m_size = o.m_size;
|
m_size = o.m_size;
|
||||||
m_clip = o.m_clip;
|
m_clip = o.m_clip;
|
||||||
m_file_info = o.m_file_info;
|
|
||||||
o.y_node = nullptr;
|
o.y_node = nullptr;
|
||||||
o.parent = nullptr;
|
o.parent = nullptr;
|
||||||
}
|
}
|
||||||
@@ -254,9 +249,7 @@ public:
|
|||||||
void update(float width, float height);
|
void update(float width, float height);
|
||||||
void update_internal(const glm::vec2& origin, const glm::mat4& proj);
|
void update_internal(const glm::vec2& origin, const glm::mat4& proj);
|
||||||
void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr);
|
void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr);
|
||||||
void load(const char* path);
|
|
||||||
void load_internal(const tinyxml2::XMLElement* x_node);
|
void load_internal(const tinyxml2::XMLElement* x_node);
|
||||||
void reload();
|
|
||||||
void draw();
|
void draw();
|
||||||
|
|
||||||
class iterator
|
class iterator
|
||||||
@@ -292,3 +285,13 @@ public:
|
|||||||
return nullptr;
|
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