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();