649 lines
19 KiB
C++
649 lines
19 KiB
C++
#pragma once
|
|
#include "shape.h"
|
|
#include "util.h"
|
|
#include "shader.h"
|
|
#include "font.h"
|
|
|
|
enum class kAttribute : uint16_t
|
|
{
|
|
id = const_hash("id"),
|
|
Width = const_hash("width"),
|
|
MinWidth = const_hash("max-width"),
|
|
MaxWidth = const_hash("min-width"),
|
|
Height = const_hash("height"),
|
|
MinHeight = const_hash("min-height"),
|
|
MaxHeight = const_hash("max-height"),
|
|
Divisions = const_hash("divisions"),
|
|
InnerRadius = const_hash("inner-radius"),
|
|
OuterRadius = const_hash("outer-radius"),
|
|
Grow = const_hash("grow"),
|
|
Shrink = const_hash("shrink"),
|
|
FlexDir = const_hash("dir"),
|
|
FlexWrap = const_hash("wrap"),
|
|
Padding = const_hash("pad"),
|
|
Margin = const_hash("margin"),
|
|
Color = const_hash("color"),
|
|
Thickness = const_hash("thickness"),
|
|
BorderColor = const_hash("border-color"),
|
|
Type = const_hash("type"),
|
|
Text = const_hash("text"),
|
|
FontFace = const_hash("font-face"),
|
|
FontSize = const_hash("font-size"),
|
|
Justify = const_hash("justify"),
|
|
Align = const_hash("align"),
|
|
Path = const_hash("path"),
|
|
Region = const_hash("region"),
|
|
Position = const_hash("position"),
|
|
Positioning = const_hash("positioning"),
|
|
};
|
|
|
|
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"),
|
|
};
|
|
|
|
enum class kShapeType : uint16_t
|
|
{
|
|
Quad = const_hash("rect"),
|
|
Poly = const_hash("poly"),
|
|
RoundRect = const_hash("round-rect"),
|
|
Slice9 = const_hash("slice9"),
|
|
};
|
|
|
|
enum class kEventResult : uint8_t
|
|
{
|
|
Consumed,
|
|
Available,
|
|
};
|
|
|
|
enum class kEventCategory : uint8_t
|
|
{
|
|
MouseEvent,
|
|
};
|
|
enum class kEventType : uint8_t
|
|
{
|
|
MouseDownL,
|
|
MouseDownR,
|
|
MouseMove,
|
|
MouseUpL,
|
|
MouseUpR,
|
|
MouseEnter,
|
|
MouseLeave,
|
|
};
|
|
|
|
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:
|
|
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;
|
|
std::string m_path;
|
|
struct stat m_file_info { 0 };
|
|
public:
|
|
std::function<void()> on_loaded;
|
|
bool load(const char* path);
|
|
bool reload();
|
|
class Node& operator[](uint16_t id) { return *m_layouts[id]; }
|
|
//Node& operator[](const char* ids) { return m_layouts[const_hash(ids)]; }
|
|
};
|
|
|
|
class Node
|
|
{
|
|
friend class LayoutManager;
|
|
public:
|
|
Node* parent{ nullptr };
|
|
YGNodeRef y_node{ nullptr };
|
|
class LayoutManager* m_manager;
|
|
uint16_t m_nodeID;
|
|
std::string m_nodeID_s;
|
|
std::vector<std::unique_ptr<Node>> m_children;
|
|
|
|
glm::mat4 m_proj;
|
|
glm::mat4 m_mvp;
|
|
bool m_mouse_inside = false;
|
|
|
|
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<Node>(o); }
|
|
Node(Node&& o)
|
|
{
|
|
m_name = std::move(o.m_name);
|
|
m_nodeID_s = std::move(o.m_nodeID_s);
|
|
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;
|
|
m_size = o.m_size;
|
|
m_clip = o.m_clip;
|
|
o.y_node = nullptr;
|
|
o.parent = nullptr;
|
|
}
|
|
Node() { y_node = YGNodeNew(); }
|
|
~Node()
|
|
{
|
|
m_children.clear();
|
|
if (y_node)
|
|
YGNodeFree(y_node);
|
|
}
|
|
|
|
void SetWidth(float value) { YGNodeStyleSetWidth(y_node, value); }
|
|
void SetWidthP(float value) { YGNodeStyleSetWidthPercent(y_node, value); }
|
|
void SetHeight(float value) { YGNodeStyleSetHeight(y_node, value); }
|
|
void SetHeightP(float value) { YGNodeStyleSetHeightPercent(y_node, value); }
|
|
void SetSize(glm::vec2 value) { SetWidth(value.x); SetHeight(value.y); }
|
|
|
|
void SetPadding(float t, float r, float b, float l)
|
|
{
|
|
YGNodeStyleSetPadding(y_node, YGEdgeTop, t);
|
|
YGNodeStyleSetPadding(y_node, YGEdgeRight, r);
|
|
YGNodeStyleSetPadding(y_node, YGEdgeBottom, b);
|
|
YGNodeStyleSetPadding(y_node, YGEdgeLeft, l);
|
|
}
|
|
void SetPosition(float l, float t, float r, float b)
|
|
{
|
|
YGNodeStyleSetPosition(y_node, YGEdgeTop, t);
|
|
YGNodeStyleSetPosition(y_node, YGEdgeRight, r);
|
|
YGNodeStyleSetPosition(y_node, YGEdgeBottom, b);
|
|
YGNodeStyleSetPosition(y_node, YGEdgeLeft, l);
|
|
}
|
|
void SetPosition(float l, float t)
|
|
{
|
|
YGNodeStyleSetPosition(y_node, YGEdgeTop, t);
|
|
YGNodeStyleSetPosition(y_node, YGEdgeLeft, l);
|
|
}
|
|
|
|
void SetFlexGrow(float value) { YGNodeStyleSetFlexGrow(y_node, value); }
|
|
void SetFlexShrink(float value) { YGNodeStyleSetFlexShrink(y_node, value); }
|
|
void SetFlexDir(YGFlexDirection value) { YGNodeStyleSetFlexDirection(y_node, value); }
|
|
void SetFlexWrap(YGWrap value) { YGNodeStyleSetFlexWrap(y_node, value); }
|
|
void SetJustify(YGJustify value) { YGNodeStyleSetJustifyContent(y_node, value); }
|
|
void SetAlign(YGAlign value) { YGNodeStyleSetAlignItems(y_node, value); }
|
|
void SetPositioning(YGPositionType value) { YGNodeStyleSetPositionType(y_node, value); }
|
|
|
|
glm::vec4 rect_intersection(glm::vec4 a, glm::vec4 b)
|
|
{
|
|
// convert from [x,y,w,h] to [x1,y1,x2,y1]
|
|
a = glm::vec4(a.xy(), a.xy() + a.zw());
|
|
b = glm::vec4(b.xy(), b.xy() + b.zw());
|
|
auto o = glm::vec4(glm::max(a.xy(), b.xy()), glm::min(a.zw(), b.zw()));
|
|
o = glm::vec4(o.xy(), glm::max({ 0, 0 }, o.zw() - o.xy()));
|
|
return o;
|
|
}
|
|
|
|
void update(float width, float height);
|
|
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);
|
|
virtual void draw() { }
|
|
Node* clone();
|
|
virtual Node* clone_instantiate() const;
|
|
virtual void clone_copy(Node* dest) const;
|
|
virtual void clone_children(Node* dest) const;
|
|
void watch(std::function<void(Node*)> observer)
|
|
{
|
|
observer(this);
|
|
for (auto& c : m_children)
|
|
c->watch(observer);
|
|
}
|
|
|
|
template<class T = Node> T* find(const char* ids)
|
|
{
|
|
uint16_t id = const_hash(ids);
|
|
if (id == m_nodeID)
|
|
return static_cast<T*>(this);
|
|
for (auto& c : m_children)
|
|
if (auto found = c->find(ids))
|
|
return static_cast<T*>(found);
|
|
return nullptr;
|
|
}
|
|
|
|
virtual kEventResult on_event(Event* e);
|
|
virtual kEventResult handle_event(Event* e) { return kEventResult::Available; }
|
|
virtual void create() { }
|
|
virtual void init() { }
|
|
void add_child(Node* n);
|
|
void remove_child(Node* n);
|
|
|
|
// class iterator
|
|
// {
|
|
// std::stack<Node*> m_nodes;
|
|
// Node* m_current;
|
|
// public:
|
|
// iterator(Node* root)
|
|
// {
|
|
// m_current = root;
|
|
// if (root)
|
|
// m_nodes.push(root);
|
|
// }
|
|
// iterator& operator++()
|
|
// {
|
|
// m_nodes.pop();
|
|
// for (auto& c : m_current->m_children)
|
|
// m_nodes.push(c.get());
|
|
// m_current = m_nodes.size() ? m_nodes.top() : nullptr;
|
|
// return *this;
|
|
// }
|
|
// Node& operator*() { return *m_current; }
|
|
// Node* operator->() { return m_current; }
|
|
// bool operator==(const iterator& rhs) { return m_current == rhs.m_current; }
|
|
// bool operator!=(const iterator& rhs) { return m_current != rhs.m_current; }
|
|
// };
|
|
// iterator begin()
|
|
// {
|
|
// return this;
|
|
// }
|
|
// iterator end()
|
|
// {
|
|
// return nullptr;
|
|
// }
|
|
};
|
|
|
|
class NodeBorder : public Node
|
|
{
|
|
public:
|
|
static Plane m_plane;
|
|
glm::vec4 m_color{ 0, 0, 0, 1 };
|
|
glm::vec4 m_border_color{ 1, 1, 1, 1 };
|
|
float m_thinkness{ 0 };
|
|
static void static_init()
|
|
{
|
|
m_plane.create<1>(1, 1);
|
|
}
|
|
virtual Node* clone_instantiate() const override { return new NodeBorder(); }
|
|
virtual void clone_copy(Node* dest) const override
|
|
{
|
|
Node::clone_copy(dest);
|
|
NodeBorder* n = static_cast<NodeBorder*>(dest);
|
|
n->m_color = m_color;
|
|
n->m_border_color = m_border_color;
|
|
n->m_thinkness = m_thinkness;
|
|
}
|
|
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) override
|
|
{
|
|
Node::parse_attributes(ka, attr);
|
|
switch (ka)
|
|
{
|
|
case kAttribute::Color:
|
|
{
|
|
glm::vec4 pad;
|
|
int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w);
|
|
if (n == 1)
|
|
m_color = glm::vec4(pad.x);
|
|
else
|
|
m_color = pad;
|
|
break;
|
|
}
|
|
case kAttribute::BorderColor:
|
|
{
|
|
glm::vec4 pad;
|
|
int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w);
|
|
if (n == 1)
|
|
m_border_color = glm::vec4(pad.x);
|
|
else
|
|
m_border_color = pad;
|
|
break;
|
|
}
|
|
case kAttribute::Thickness:
|
|
m_thinkness = attr->FloatValue();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
virtual void draw() override
|
|
{
|
|
ShaderManager::use(kShader::Color);
|
|
ShaderManager::u_mat4(kShaderUniform::MVP, m_mvp);
|
|
|
|
if (m_color.a != 1.f)
|
|
glEnable(GL_BLEND);
|
|
|
|
ShaderManager::u_vec4(kShaderUniform::Col, m_color);
|
|
m_plane.draw_fill();
|
|
|
|
if (m_thinkness > 0)
|
|
{
|
|
glLineWidth(m_thinkness);
|
|
ShaderManager::u_vec4(kShaderUniform::Col, m_border_color);
|
|
m_plane.draw_stroke();
|
|
}
|
|
|
|
if (m_color.a != 1.f)
|
|
glDisable(GL_BLEND);
|
|
}
|
|
};
|
|
|
|
class NodeText : public Node
|
|
{
|
|
public:
|
|
TextMesh m_text_mesh;
|
|
std::string m_text;
|
|
std::string m_font;
|
|
glm::vec4 m_color{ 1, 1, 1, 1 };
|
|
int m_font_size;
|
|
virtual Node* clone_instantiate() const override { return new NodeText(); }
|
|
virtual void clone_copy(Node* dest) const override
|
|
{
|
|
Node::clone_copy(dest);
|
|
NodeText* n = static_cast<NodeText*>(dest);
|
|
n->m_text_mesh = m_text_mesh;
|
|
n->m_text = m_text;
|
|
n->m_font = m_font;
|
|
n->m_color = m_color;
|
|
n->m_font_size = m_font_size;
|
|
}
|
|
virtual void create() override
|
|
{
|
|
char font[64];
|
|
sprintf(font, "%s-%d", m_font.c_str(), m_font_size);
|
|
kFont font_id = (kFont)const_hash(font);
|
|
m_text_mesh.create();
|
|
m_text_mesh.update(font_id, m_text.c_str());
|
|
SetSize(m_text_mesh.bb);
|
|
}
|
|
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) override
|
|
{
|
|
Node::parse_attributes(ka, attr);
|
|
switch (ka)
|
|
{
|
|
case kAttribute::Text:
|
|
m_text = attr->Value();
|
|
break;
|
|
case kAttribute::FontFace:
|
|
m_font = attr->Value();
|
|
break;
|
|
case kAttribute::FontSize:
|
|
m_font_size = attr->IntValue();
|
|
break;
|
|
case kAttribute::Color:
|
|
{
|
|
glm::vec4 pad;
|
|
int n = sscanf(attr->Value(), "%f %f %f %f", &pad.x, &pad.y, &pad.z, &pad.w);
|
|
if (n == 1)
|
|
m_color = glm::vec4(pad.x);
|
|
else
|
|
m_color = pad;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
virtual void draw() override
|
|
{
|
|
glm::mat4 pos = glm::translate(glm::vec3(glm::floor(m_pos), 0));
|
|
m_mvp = m_proj * pos;
|
|
ShaderManager::use(kShader::Font);
|
|
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
|
ShaderManager::u_mat4(kShaderUniform::MVP, m_mvp);
|
|
ShaderManager::u_vec4(kShaderUniform::Col, m_color);
|
|
glEnable(GL_BLEND);
|
|
m_text_mesh.draw();
|
|
glDisable(GL_BLEND);
|
|
}
|
|
};
|
|
|
|
class NodeImage : public Node
|
|
{
|
|
public:
|
|
static Plane m_plane;
|
|
static Sampler m_sampler;
|
|
bool m_use_atlas;
|
|
glm::vec4 m_region;
|
|
glm::vec2 m_off;
|
|
glm::vec2 m_sz;
|
|
std::string m_path;
|
|
uint16_t m_tex_id;
|
|
static void static_init()
|
|
{
|
|
m_plane.create<1>(1, 1);
|
|
m_sampler.create();
|
|
}
|
|
virtual Node* clone_instantiate() const override { return new NodeImage(); }
|
|
virtual void clone_copy(Node* dest) const override
|
|
{
|
|
Node::clone_copy(dest);
|
|
NodeImage* n = static_cast<NodeImage*>(dest);
|
|
n->m_use_atlas = m_use_atlas;
|
|
n->m_region = m_region;
|
|
n->m_off = m_off;
|
|
n->m_sz = m_sz;
|
|
n->m_path = m_path;
|
|
n->m_tex_id = m_tex_id;
|
|
}
|
|
virtual void create() override
|
|
{
|
|
if (TextureManager::load(m_path.c_str()))
|
|
{
|
|
auto tex_sz = TextureManager::get(m_tex_id).size();
|
|
m_off = m_region.xy / tex_sz;
|
|
m_sz = (m_region.zw - m_region.xy) / tex_sz;
|
|
}
|
|
}
|
|
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) override
|
|
{
|
|
Node::parse_attributes(ka, attr);
|
|
switch (ka)
|
|
{
|
|
case kAttribute::Path:
|
|
m_path = attr->Value();
|
|
m_tex_id = const_hash(attr->Value());
|
|
break;
|
|
case kAttribute::Region:
|
|
{
|
|
glm::vec4 v;
|
|
int n = sscanf(attr->Value(), "%f %f %f %f", &v.x, &v.y, &v.z, &v.w);
|
|
if (n == 4)
|
|
{
|
|
m_region = v;
|
|
m_use_atlas = true;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
virtual void draw() override
|
|
{
|
|
TextureManager::get(m_tex_id).bind();
|
|
m_sampler.bind(0);
|
|
glEnable(GL_BLEND);
|
|
if (m_use_atlas)
|
|
{
|
|
ShaderManager::use(kShader::Atlas);
|
|
ShaderManager::u_vec2(kShaderUniform::Tof, m_off);
|
|
ShaderManager::u_vec2(kShaderUniform::Tsz, m_sz);
|
|
}
|
|
else
|
|
{
|
|
ShaderManager::use(kShader::Texture);
|
|
}
|
|
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
|
ShaderManager::u_mat4(kShaderUniform::MVP, m_mvp);
|
|
m_plane.draw_fill();
|
|
m_sampler.unbind();
|
|
TextureManager::get(m_tex_id).unbind();
|
|
glDisable(GL_BLEND);
|
|
}
|
|
};
|
|
|
|
class NodeButton : public Node
|
|
{
|
|
public:
|
|
NodeBorder* m_border;
|
|
NodeText* m_text;
|
|
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 NodeButton(); }
|
|
virtual void clone_children(Node* dest) const override
|
|
{
|
|
Node::clone_children(dest);
|
|
NodeButton* n = static_cast<NodeButton*>(dest);
|
|
n->m_border = (NodeBorder*)n->m_children[0].get();
|
|
n->m_text = (NodeText*)n->m_border->m_children[0].get();
|
|
}
|
|
virtual void clone_copy(Node* dest) const override
|
|
{
|
|
Node::clone_copy(dest);
|
|
NodeButton* n = static_cast<NodeButton*>(dest);
|
|
//n->m_border = (NodeBorder*)m_border->clone();
|
|
//n->m_text = (NodeText*)m_text->clone();
|
|
n->color_normal = color_normal;
|
|
n->color_hover = color_hover;
|
|
n->color_down = color_down;
|
|
//n->on_click = on_click;
|
|
}
|
|
virtual void init() override
|
|
{
|
|
m_border = new NodeBorder();
|
|
m_text = new NodeText();
|
|
add_child(m_border);
|
|
m_border->add_child(m_text);
|
|
m_border->init();
|
|
m_border->m_color = color_normal;
|
|
m_text->init();
|
|
m_text->m_font = "arial";
|
|
m_text->m_font_size = 11;
|
|
m_border->SetAlign(YGAlignCenter);
|
|
m_border->SetJustify(YGJustifyCenter);
|
|
}
|
|
virtual void create() override
|
|
{
|
|
m_border->create();
|
|
m_text->create();
|
|
}
|
|
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) override
|
|
{
|
|
switch (ka)
|
|
{
|
|
case kAttribute::Padding:
|
|
case kAttribute::Width:
|
|
case kAttribute::Height:
|
|
case kAttribute::Color:
|
|
case kAttribute::Thickness:
|
|
case kAttribute::BorderColor:
|
|
m_border->parse_attributes(ka, attr);
|
|
break;
|
|
case kAttribute::Text:
|
|
case kAttribute::FontFace:
|
|
case kAttribute::FontSize:
|
|
m_text->parse_attributes(ka, attr);
|
|
break;
|
|
default:
|
|
Node::parse_attributes(ka, attr);
|
|
break;
|
|
}
|
|
// m_border->parse_attributes(ka, attr);
|
|
// m_text->parse_attributes(ka, attr);
|
|
}
|
|
virtual kEventResult handle_event(Event* e) override
|
|
{
|
|
switch (e->m_type)
|
|
{
|
|
case kEventType::MouseEnter:
|
|
m_border->m_color = color_hover;
|
|
break;
|
|
case kEventType::MouseLeave:
|
|
m_border->m_color = color_normal;
|
|
break;
|
|
case kEventType::MouseDownL:
|
|
m_border->m_color = color_down;
|
|
break;
|
|
case kEventType::MouseUpL:
|
|
m_border->m_color = color_normal;
|
|
if (m_mouse_inside && on_click != nullptr)
|
|
on_click();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return kEventResult::Consumed;
|
|
}
|
|
};
|
|
|
|
class NodeMessageBox : public Node
|
|
{
|
|
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);
|
|
SetWidthP(100);
|
|
SetHeightP(100);
|
|
SetPositioning(YGPositionTypeAbsolute);
|
|
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);
|
|
}
|
|
};
|