diff --git a/data/icons.png b/data/icons.png
index 97b6ba1..cf8a3b3 100644
Binary files a/data/icons.png and b/data/icons.png differ
diff --git a/data/layout.xml b/data/layout.xml
index 77f9666..479c14e 100644
--- a/data/layout.xml
+++ b/data/layout.xml
@@ -6,9 +6,9 @@
-
+
-
+
@@ -26,10 +26,10 @@
-
+
-
+
@@ -38,6 +38,14 @@
+
@@ -47,20 +55,29 @@
-
+
-
-
-
-
-
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
@@ -98,16 +132,17 @@
-
-
-
-
+
+
+
+
+
-
+
diff --git a/data/meme/nothing-to-do-here.jpg b/data/meme/nothing-to-do-here.jpg
new file mode 100644
index 0000000..f990382
Binary files /dev/null and b/data/meme/nothing-to-do-here.jpg differ
diff --git a/engine/app.cpp b/engine/app.cpp
index 6ac9726..dc21eb3 100644
--- a/engine/app.cpp
+++ b/engine/app.cpp
@@ -216,7 +216,7 @@ void App::resize(float w, float h)
void App::mouse_down(int button, float x, float y)
{
MouseEvent e;
- e.m_type = kEventType::MouseDownL;
+ e.m_type = button ? kEventType::MouseDownR : kEventType::MouseDownL;
e.m_pos = { x, y };
layout[main_id].on_event(&e);
printf("mouse click %f %f\n", x, y);
@@ -228,6 +228,20 @@ void App::mouse_down(int button, float x, float y)
// n->m_color = glm::vec4(.5, .5, .5, .5);
// layout[main_id].add_child(n);
// layout[main_id].update(width, height);
+ if (popup)
+ {
+ layout[main_id].remove_child(popup);
+ popup = nullptr;
+ }
+ if (button == 1)
+ {
+ popup = (NodePopupMenu*)layout[const_hash("popup-menu")].m_children[0]->clone();
+ popup->SetPositioning(YGPositionTypeAbsolute);
+ popup->SetPosition(x, y);
+ layout[main_id].add_child(popup);
+ layout[main_id].update(width, height);
+ }
+ layout[main_id].update();
}
void App::mouse_move(float x, float y)
{
@@ -239,7 +253,8 @@ void App::mouse_move(float x, float y)
void App::mouse_up(int button, float x, float y)
{
MouseEvent e;
- e.m_type = kEventType::MouseUpL;
+ e.m_type = button ? kEventType::MouseUpR : kEventType::MouseUpL;
e.m_pos = { x, y };
layout[main_id].on_event(&e);
+ layout[main_id].update();
}
diff --git a/engine/app.h b/engine/app.h
index ca8f2a3..5105c83 100644
--- a/engine/app.h
+++ b/engine/app.h
@@ -12,6 +12,7 @@ class App
Texture2D tex;
LayoutManager layout;
NodeMessageBox* msgbox;
+ NodePopupMenu* popup = nullptr;
const uint16_t main_id = const_hash("main");
public:
static App I;
diff --git a/engine/layout.cpp b/engine/layout.cpp
index 2d6aa31..f61cfde 100644
--- a/engine/layout.cpp
+++ b/engine/layout.cpp
@@ -8,9 +8,15 @@ Sampler NodeImage::m_sampler;
kEventResult Node::on_event(Event* e)
{
- for (auto& c : m_children)
- if (c->on_event(e) == kEventResult::Consumed)
- return kEventResult::Consumed;
+ kEventResult ret = kEventResult::Available;
+ for (auto it = m_children.rbegin(); it != m_children.rend(); ++it)
+ if ((*it)->on_event(e) == kEventResult::Consumed)
+ if (m_flood_events)
+ ret = kEventResult::Consumed;
+ else
+ return kEventResult::Consumed;
+ if (ret == kEventResult::Consumed)
+ return ret;
switch (e->m_cat)
{
case kEventCategory::MouseEvent:
@@ -35,7 +41,8 @@ kEventResult Node::on_event(Event* e)
handle_event(&e2);
}
m_mouse_inside = inside;
- handle_event(e);
+ if (inside)
+ ret = handle_event(e);
if (inside_old == true && inside == false)
{
MouseEvent e2 = *me;
@@ -51,7 +58,7 @@ kEventResult Node::on_event(Event* e)
return kEventResult::Consumed;
break;
}
- return kEventResult::Available;
+ return ret;
}
void Node::add_child(Node* n)
@@ -77,8 +84,14 @@ void Node::update(float width, float height)
YGNodeStyleSetWidth(y_node, width);
YGNodeStyleSetHeight(y_node, height);
YGNodeCalculateLayout(y_node, YGUndefined, YGUndefined, YGDirectionLTR);
- glm::mat4 proj = glm::ortho(0.f, width, height, 0.f, -1.f, 1.f);
- update_internal({ 0, 0 }, proj);
+ m_proj = glm::ortho(0.f, width, height, 0.f, -1.f, 1.f);
+ update_internal({ 0, 0 }, m_proj);
+}
+
+void Node::update()
+{
+ YGNodeCalculateLayout(y_node, YGUndefined, YGUndefined, YGDirectionLTR);
+ update_internal({ 0, 0 }, m_proj);
}
void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj)
@@ -88,7 +101,7 @@ void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj)
float w = YGNodeLayoutGetWidth(y_node);
float h = YGNodeLayoutGetHeight(y_node);
m_pos = glm::floor(origin + glm::vec2(x, y));
- m_size = glm::ceil(glm::vec2(w, h));
+ m_size = glm::floor(glm::vec2(w, h));
if (parent)
{
@@ -114,6 +127,16 @@ void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj)
glm::mat4 pos = glm::translate(glm::vec3(m_pos, 0));
m_mvp = proj * pos * scale * pivot;
m_proj = proj;
+
+ for (int i = 0; i < m_children.size(); i++)
+ {
+ if (m_children[i]->m_destroyed)
+ {
+ remove_child(m_children[i].get());
+ i--;
+ }
+ }
+
for (auto& c : m_children)
c->update_internal(m_pos, proj);
}
@@ -346,6 +369,20 @@ void Node::load_internal(const tinyxml2::XMLElement* x_node)
n->load_internal(x_child);
break;
}
+ case kWidget::ButtonCustom:
+ {
+ auto n = new NodeButtonCustom();
+ add_child(n);
+ n->load_internal(x_child);
+ break;
+ }
+ case kWidget::PopupMenu:
+ {
+ auto n = new NodePopupMenu();
+ add_child(n);
+ n->load_internal(x_child);
+ break;
+ }
case kWidget::Ref:
{
auto ids = x_child->Attribute("id");
@@ -365,6 +402,7 @@ void Node::load_internal(const tinyxml2::XMLElement* x_node)
}
x_child = x_child->NextSiblingElement();
}
+ loaded();
}
Node* Node::clone()
@@ -392,6 +430,7 @@ void Node::clone_copy(Node* dest) const
dest->m_pos = m_pos;
dest->m_size = m_size;
dest->m_clip = m_clip;
+ dest->m_flood_events = m_flood_events;
}
void Node::clone_children(Node* dest) const
diff --git a/engine/layout.h b/engine/layout.h
index c234daa..ef13d23 100644
--- a/engine/layout.h
+++ b/engine/layout.h
@@ -39,12 +39,14 @@ enum class kAttribute : uint16_t
enum class kWidget : uint16_t
{
- Border = const_hash("border"),
- Shape = const_hash("shape"),
- Text = const_hash("text"),
- Image = const_hash("image"),
- Button = const_hash("button"),
- Ref = const_hash("ref"),
+ Border = const_hash("border"),
+ Shape = const_hash("shape"),
+ Text = const_hash("text"),
+ Image = const_hash("image"),
+ Button = const_hash("button"),
+ ButtonCustom = const_hash("button-custom"),
+ PopupMenu = const_hash("popup-menu"),
+ Ref = const_hash("ref"),
};
enum class kShapeType : uint16_t
@@ -90,23 +92,6 @@ public:
glm::vec2 m_pos;
};
-class Widget
-{
-public:
- glm::mat4 mvp;
- glm::mat4 proj;
- glm::mat4 scale;
- glm::mat4 pos;
- glm::vec4 clip;
- bool m_mouse_inside = false;
- virtual Widget* clone() = 0;
- virtual void create() { }
- virtual void draw() { }
- virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) { }
- virtual void update() { }
- virtual kEventResult on_event(Event* e) { return kEventResult::Available; }
-};
-
class LayoutManager
{
std::map> m_layouts;
@@ -134,6 +119,8 @@ public:
glm::mat4 m_proj;
glm::mat4 m_mvp;
bool m_mouse_inside = false;
+ bool m_flood_events = false;
+ bool m_destroyed = false;
glm::vec2 m_pos;
glm::vec2 m_size;
@@ -213,6 +200,7 @@ public:
}
void update(float width, float height);
+ void update();
void update_internal(const glm::vec2& origin, const glm::mat4& proj);
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr);
void load_internal(const tinyxml2::XMLElement* x_node);
@@ -227,6 +215,7 @@ public:
for (auto& c : m_children)
c->watch(observer);
}
+ void destroy() { m_destroyed = true; }
template T* find(const char* ids)
{
@@ -243,6 +232,7 @@ public:
virtual kEventResult handle_event(Event* e) { return kEventResult::Available; }
virtual void create() { }
virtual void init() { }
+ virtual void loaded() { }
void add_child(Node* n);
void remove_child(Node* n);
@@ -557,6 +547,12 @@ public:
m_border->create();
m_text->create();
}
+ virtual void loaded() override
+ {
+ m_border->m_thinkness = 1;
+ m_border->m_border_color = glm::vec4(0, 0, 0, 1);
+ m_border->m_color = color_normal;
+ }
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) override
{
switch (ka)
@@ -612,11 +608,6 @@ public:
Node* m_template;
NodeButton* btnOk;
virtual Node* clone_instantiate() const override { return new NodeMessageBox(); }
- virtual void clone_copy(Node* dest) const override
- {
- Node::clone_copy(dest);
- NodeMessageBox* n = static_cast(dest);
- }
virtual void init() override
{
SetPosition(0, 0);
@@ -626,23 +617,72 @@ public:
m_template = (*m_manager)[const_hash("message-box")].m_children[0]->clone();
add_child(m_template);
btnOk = m_template->find("btn-ok");
- btnOk->on_click = [&] { parent->remove_child(this); };
-// btnOk = (NodeButton*)n;
-// btnOk->m_display = false;
- }
- virtual void create() override
- {
- }
- virtual void draw() override
- {
- //m_template->draw();
- }
-// virtual kEventResult handle_event(Event* e) override
-// {
-// return kEventResult::Available;
-// }
- virtual kEventResult on_event(Event* e)
- {
- return Node::on_event(e);
+ btnOk->on_click = [&] { destroy(); };
+ }
+};
+
+class NodePopupMenu : public Node
+{
+public:
+ virtual Node* clone_instantiate() const override { return new NodePopupMenu(); }
+ virtual void init() override
+ {
+ m_flood_events = true;
+ SetPadding(10, 10, 10, 10);
+ SetPosition(0, 0);
+ SetWidth(100);
+ SetHeight(400);
+ SetPositioning(YGPositionTypeAbsolute);
+ }
+ virtual kEventResult handle_event(Event* e) override
+ {
+ return kEventResult::Consumed;
+ }
+};
+
+class NodeButtonCustom : public NodeBorder
+{
+public:
+ glm::vec4 color_normal{ .1, .1, .1, 1 };
+ glm::vec4 color_hover{ .2, .2, .2, 1 };
+ glm::vec4 color_down{ .3, .3, .3, 1 };
+ std::function on_click;
+ virtual Node* clone_instantiate() const override { return new NodeButtonCustom(); }
+ virtual void clone_copy(Node* dest) const override
+ {
+ Node::clone_copy(dest);
+ NodeButtonCustom* n = static_cast(dest);
+ n->color_normal = color_normal;
+ n->color_hover = color_hover;
+ n->color_down = color_down;
+ }
+ virtual void loaded() override
+ {
+ m_thinkness = 1;
+ m_border_color = glm::vec4(0, 0, 0, 1);
+ m_color = color_normal;
+ }
+ virtual kEventResult handle_event(Event* e) override
+ {
+ switch (e->m_type)
+ {
+ case kEventType::MouseEnter:
+ m_color = color_hover;
+ break;
+ case kEventType::MouseLeave:
+ m_color = color_normal;
+ break;
+ case kEventType::MouseDownL:
+ m_color = color_down;
+ break;
+ case kEventType::MouseUpL:
+ m_color = color_normal;
+ if (m_mouse_inside && on_click != nullptr)
+ on_click();
+ break;
+ default:
+ break;
+ }
+ return kEventResult::Consumed;
}
};
diff --git a/engine/main.cpp b/engine/main.cpp
index 1618dec..29bed2c 100644
--- a/engine/main.cpp
+++ b/engine/main.cpp
@@ -470,6 +470,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
case WM_LBUTTONUP:
App::I.mouse_up(0, LOWORD(lp), HIWORD(lp));
break;
+ case WM_RBUTTONDOWN:
+ App::I.mouse_down(1, LOWORD(lp), HIWORD(lp));
+ break;
+ case WM_RBUTTONUP:
+ App::I.mouse_up(1, LOWORD(lp), HIWORD(lp));
+ break;
}
return DefWindowProc(hWnd, msg, wp, lp);
}