diff --git a/data/layout.xml b/data/layout.xml index 85840af..b21d197 100644 --- a/data/layout.xml +++ b/data/layout.xml @@ -1,5 +1,8 @@ - + + + + @@ -34,8 +37,8 @@ - - + + diff --git a/engine/app.cpp b/engine/app.cpp index 52887e5..ffe7f5f 100644 --- a/engine/app.cpp +++ b/engine/app.cpp @@ -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) diff --git a/engine/app.h b/engine/app.h index 3fe45b9..d4974db 100644 --- a/engine/app.h +++ b/engine/app.h @@ -9,7 +9,7 @@ class App { Sampler sampler; Texture2D tex; - Node layout; + LayoutManager layout; public: static App I; float width; diff --git a/engine/layout.cpp b/engine/layout.cpp index bd1b50c..62d1e73 100644 --- a/engine/layout.cpp +++ b/engine/layout.cpp @@ -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); } diff --git a/engine/layout.h b/engine/layout.h index df6d273..0c76c13 100644 --- a/engine/layout.h +++ b/engine/layout.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 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 m_layouts; + std::string m_path; + struct stat m_file_info { 0 }; +public: + bool load(const char* path); + void reload(); +};