added right click, popup menu, mark for destroy
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
132
engine/layout.h
132
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<uint16_t, std::unique_ptr<class Node>> 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<class T = Node> 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<NodeMessageBox*>(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<NodeButton>("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<void()> 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<NodeButtonCustom*>(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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user