diff --git a/data/layout.xml b/data/layout.xml index 22b222a..d3090c6 100644 --- a/data/layout.xml +++ b/data/layout.xml @@ -24,6 +24,11 @@ + + + + + @@ -75,16 +80,16 @@ - + - - + + - + diff --git a/engine.vcxproj b/engine.vcxproj index 256c9e9..9a1b73d 100644 --- a/engine.vcxproj +++ b/engine.vcxproj @@ -164,6 +164,7 @@ + NotUsing NotUsing @@ -192,6 +193,7 @@ + diff --git a/engine.vcxproj.filters b/engine.vcxproj.filters index 4e815b3..52fdc9e 100644 --- a/engine.vcxproj.filters +++ b/engine.vcxproj.filters @@ -51,6 +51,9 @@ Source Files + + Source Files + @@ -77,5 +80,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/engine/app.cpp b/engine/app.cpp index 6e83cf4..3f299e7 100644 --- a/engine/app.cpp +++ b/engine/app.cpp @@ -173,13 +173,16 @@ void App::update(float dt) if (layout.reload()) { layout[main_id].update(width, height); + //Node* check = layout[main_id].find("check"); + //if (check) + // check->m_display = false; } glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_SCISSOR_TEST); for (auto& n : layout[main_id]) { - if (n.m_widget) + if (n.m_display && n.m_widget) { auto box = n.m_widget->clip; glScissor((int)box.x, (int)(height - box.y - box.w), (int)box.z, (int)box.w); @@ -225,7 +228,11 @@ void App::resize(float w, float h) void App::mouse_down(int button, float x, float y) { + constexpr auto main_id = const_hash("main"); printf("mouse click %f %f\n", x, y); + MouseEvent e; + e.m_pos = { x, y }; + layout[main_id].on_event(&e); } void App::mouse_move(float x, float y) { diff --git a/engine/layout.cpp b/engine/layout.cpp index 6e7ccb6..b1025e0 100644 --- a/engine/layout.cpp +++ b/engine/layout.cpp @@ -6,6 +6,39 @@ Plane WidgetBorder::m_plane; Plane WidgetImage::m_plane; Sampler WidgetImage::m_sampler; +Node* Node::find(const char* ids) +{ + uint16_t id = const_hash(ids); + if (id == m_nodeID) + return this; + for (auto& c : *this) + if (c.m_nodeID == id) + return &c; + return nullptr; +} + +kEventResult Node::on_event(Event* e) +{ + for (auto& c : m_children) + if (c.on_event(e) == kEventResult::Handled) + return kEventResult::Handled; + if (m_widget) + { + switch (e->m_cat) + { + case kEventCategory::MouseEvent: + if (point_in_rect(((MouseEvent*)e)->m_pos, m_clip) && m_widget->on_event(e) == kEventResult::Handled) + return kEventResult::Handled; + break; + default: + if (m_widget->on_event(e) == kEventResult::Handled) + return kEventResult::Handled; + break; + } + } + return kEventResult::UnHandled; +} + void Node::update(float width, float height) { YGNodeStyleSetWidth(y_node, width); @@ -29,10 +62,10 @@ void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj) // 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); + float pt = 0;//YGNodeLayoutGetPadding(parent->y_node, YGEdgeTop); + float pr = 0;//YGNodeLayoutGetPadding(parent->y_node, YGEdgeRight); + float pb = 0;//YGNodeLayoutGetPadding(parent->y_node, YGEdgeBottom); + float pl = 0;//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); @@ -63,6 +96,10 @@ void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) { switch (ka) { + case kAttribute::id: + m_nodeID_s = attr->Value(); + m_nodeID = const_hash(attr->Value()); + break; case kAttribute::Width: if (strcmp(attr->Value(), "auto") == 0) { diff --git a/engine/layout.h b/engine/layout.h index b8ced21..a472343 100644 --- a/engine/layout.h +++ b/engine/layout.h @@ -52,6 +52,39 @@ enum class kShapeType : uint16_t Slice9 = const_hash("slice9"), }; +enum class kEventResult : uint8_t +{ + Handled, + UnHandled, +}; + +enum class kEventCategory : uint8_t +{ + MouseEvent, +}; +enum class kEventType : uint8_t +{ + MouseDownL, + MouseDownR, + MouseMove, + MouseUpL, + MouseUpR, +}; + +class Event +{ +public: + kEventCategory m_cat; + kEventType m_type; +}; + +class MouseEvent : public Event +{ +public: + MouseEvent() { m_cat = kEventCategory::MouseEvent; } + glm::vec2 m_pos; +}; + class Widget { public: @@ -65,6 +98,7 @@ public: virtual void draw() { } virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) { } virtual void update() { } + virtual kEventResult on_event(Event* e) { return kEventResult::UnHandled; } }; class WidgetRef : public Widget @@ -136,6 +170,11 @@ public: break; } } + virtual kEventResult on_event(Event* e) + { + m_color = rand_color(); + return kEventResult::Handled; + } }; class WidgetShape : public Widget @@ -288,6 +327,11 @@ public: { mvp = proj * pos; } + virtual kEventResult on_event(Event* e) + { + m_color = rand_color(); + return kEventResult::Handled; + } }; class WidgetImage : public Widget @@ -366,6 +410,11 @@ public: break; } } + virtual kEventResult on_event(Event* e) + { + MouseEvent* me = static_cast(e); + return kEventResult::UnHandled; + } }; class Node @@ -377,22 +426,28 @@ class Node class LayoutManager* m_manager; public: + uint16_t m_nodeID; + std::string m_nodeID_s; std::vector m_children; std::unique_ptr m_widget; glm::vec2 m_pos; glm::vec2 m_size; glm::vec4 m_clip; std::string m_name; + bool m_display = true; Node(const Node&) = delete; Node& operator=(const Node&) = delete; Node&& operator=(Node&& o) { return std::forward(o); } Node(Node&& o) { m_name = std::move(o.m_name); + m_nodeID_s = std::move(o.m_nodeID_s); m_widget = std::move(o.m_widget); m_children = std::move(o.m_children); for (auto& c : m_children) c.parent = this; + m_nodeID = o.m_nodeID; + m_display = o.m_display; parent = o.parent; y_node = o.y_node; m_pos = o.m_pos; @@ -444,6 +499,8 @@ public: void load_internal(const tinyxml2::XMLElement* x_node); void draw(); Node clone(); + Node* find(const char* ids); + kEventResult on_event(Event* e); class iterator { diff --git a/engine/util.cpp b/engine/util.cpp index 67f91e4..846a3b7 100644 --- a/engine/util.cpp +++ b/engine/util.cpp @@ -1,3 +1,15 @@ #include "pch.h" #include "util.h" +bool point_in_rect(const glm::vec2& p, const glm::vec4& r) +{ + return p.x > r.x && p.x < r.x+r.z && p.y > r.y && p.y < r.y+r.w; +} + +glm::vec4 rand_color() +{ + float r = (rand() % 256) / 256.f; + float g = (rand() % 256) / 256.f; + float b = (rand() % 256) / 256.f; + return { r, g, b, 1.f }; +} diff --git a/engine/util.h b/engine/util.h index 2fe3733..74740a1 100644 --- a/engine/util.h +++ b/engine/util.h @@ -3,6 +3,9 @@ uint16_t constexpr const_hash(const char* input) { return *input ? - static_cast(*input) + 33 * const_hash(input + 1) : - 5381; + static_cast(*input) + 33 * const_hash(input + 1) : + 5381; } + +bool point_in_rect(const glm::vec2& point, const glm::vec4& rect); +glm::vec4 rand_color();