big refactoring to merge node and widgets into a single node hierarchy
This commit is contained in:
330
engine/layout.h
330
engine/layout.h
@@ -54,8 +54,8 @@ enum class kShapeType : uint16_t
|
||||
|
||||
enum class kEventResult : uint8_t
|
||||
{
|
||||
Handled,
|
||||
UnHandled,
|
||||
Consumed,
|
||||
Available,
|
||||
};
|
||||
|
||||
enum class kEventCategory : uint8_t
|
||||
@@ -69,6 +69,8 @@ enum class kEventType : uint8_t
|
||||
MouseMove,
|
||||
MouseUpL,
|
||||
MouseUpR,
|
||||
MouseEnter,
|
||||
MouseLeave,
|
||||
};
|
||||
|
||||
class Event
|
||||
@@ -93,23 +95,15 @@ public:
|
||||
glm::mat4 scale;
|
||||
glm::mat4 pos;
|
||||
glm::vec4 clip;
|
||||
virtual std::unique_ptr<Widget> clone() = 0;
|
||||
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::UnHandled; }
|
||||
virtual kEventResult on_event(Event* e) { return kEventResult::Available; }
|
||||
};
|
||||
|
||||
class WidgetRef : public Widget
|
||||
{
|
||||
public:
|
||||
uint16_t id;
|
||||
virtual void create() { }
|
||||
virtual void draw() { }
|
||||
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) { }
|
||||
};
|
||||
|
||||
/*
|
||||
class WidgetBorder : public Widget
|
||||
{
|
||||
public:
|
||||
@@ -121,11 +115,11 @@ public:
|
||||
{
|
||||
m_plane.create<1>(1, 1);
|
||||
}
|
||||
virtual std::unique_ptr<Widget> clone() override
|
||||
virtual Widget* clone() override
|
||||
{
|
||||
auto ret = std::make_unique<WidgetBorder>();
|
||||
WidgetBorder* ret = new WidgetBorder();
|
||||
*ret = *this;
|
||||
return std::move(ret);
|
||||
return ret;
|
||||
}
|
||||
virtual void draw() override
|
||||
{
|
||||
@@ -172,8 +166,15 @@ public:
|
||||
}
|
||||
virtual kEventResult on_event(Event* e)
|
||||
{
|
||||
m_color = rand_color();
|
||||
return kEventResult::Handled;
|
||||
switch (e->m_type)
|
||||
{
|
||||
case kEventType::MouseEnter:
|
||||
m_color = rand_color();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return kEventResult::Consumed;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -186,11 +187,11 @@ public:
|
||||
glm::vec4 m_border_color;
|
||||
float m_thinkness{ 1 };
|
||||
float m_radius{ .5f };
|
||||
virtual std::unique_ptr<Widget> clone() override
|
||||
virtual Widget* clone() override
|
||||
{
|
||||
auto ret = std::make_unique<WidgetShape>();
|
||||
WidgetShape* ret = new WidgetShape();
|
||||
//*ret = *this;
|
||||
return std::move(ret);
|
||||
return ret;
|
||||
}
|
||||
virtual void create() override
|
||||
{
|
||||
@@ -272,11 +273,11 @@ public:
|
||||
std::string m_font;
|
||||
glm::vec4 m_color{ 1, 1, 1, 1 };
|
||||
int m_size;
|
||||
virtual std::unique_ptr<Widget> clone() override
|
||||
virtual Widget* clone() override
|
||||
{
|
||||
auto ret = std::make_unique<WidgetText>();
|
||||
WidgetText* ret = new WidgetText();
|
||||
*ret = *this;
|
||||
return std::move(ret);
|
||||
return ret;
|
||||
}
|
||||
virtual void create() override
|
||||
{
|
||||
@@ -329,8 +330,8 @@ public:
|
||||
}
|
||||
virtual kEventResult on_event(Event* e)
|
||||
{
|
||||
m_color = rand_color();
|
||||
return kEventResult::Handled;
|
||||
//m_color = rand_color();
|
||||
return kEventResult::Consumed;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -350,11 +351,11 @@ public:
|
||||
m_plane.create<1>(1, 1);
|
||||
m_sampler.create();
|
||||
}
|
||||
virtual std::unique_ptr<Widget> clone() override
|
||||
virtual Widget* clone() override
|
||||
{
|
||||
auto ret = std::make_unique<WidgetImage>();
|
||||
WidgetImage* ret = new WidgetImage();
|
||||
*ret = *this;
|
||||
return std::move(ret);
|
||||
return ret;
|
||||
}
|
||||
virtual void create() override
|
||||
{
|
||||
@@ -413,9 +414,27 @@ public:
|
||||
virtual kEventResult on_event(Event* e)
|
||||
{
|
||||
MouseEvent* me = static_cast<MouseEvent*>(e);
|
||||
return kEventResult::UnHandled;
|
||||
return kEventResult::Available;
|
||||
}
|
||||
};
|
||||
class WidgetButton : public Widget
|
||||
{
|
||||
public:
|
||||
std::unique_ptr<WidgetBorder> m_border;
|
||||
std::unique_ptr<WidgetText> m_text;
|
||||
virtual Widget* clone()
|
||||
{
|
||||
WidgetButton* ret = new WidgetButton();
|
||||
ret->m_border.reset((WidgetBorder*)m_border->clone());
|
||||
return std::move(ret);
|
||||
}
|
||||
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 Node
|
||||
{
|
||||
@@ -428,8 +447,12 @@ class Node
|
||||
public:
|
||||
uint16_t m_nodeID;
|
||||
std::string m_nodeID_s;
|
||||
std::vector<Node> m_children;
|
||||
std::unique_ptr<Widget> m_widget;
|
||||
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;
|
||||
@@ -442,10 +465,9 @@ public:
|
||||
{
|
||||
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;
|
||||
c->parent = this;
|
||||
m_nodeID = o.m_nodeID;
|
||||
m_display = o.m_display;
|
||||
parent = o.parent;
|
||||
@@ -495,12 +517,16 @@ public:
|
||||
|
||||
void update(float width, float height);
|
||||
void update_internal(const glm::vec2& origin, const glm::mat4& proj);
|
||||
void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr);
|
||||
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr);
|
||||
void load_internal(const tinyxml2::XMLElement* x_node);
|
||||
void draw();
|
||||
Node clone();
|
||||
virtual void draw() { }
|
||||
Node* clone();
|
||||
virtual Node* clone_instantiate() const;
|
||||
virtual void clone_copy(Node* dest) const;
|
||||
Node* find(const char* ids);
|
||||
kEventResult on_event(Event* e);
|
||||
virtual kEventResult handle_event(Event* e) { return kEventResult::Available; }
|
||||
virtual void create() { };
|
||||
|
||||
class iterator
|
||||
{
|
||||
@@ -517,7 +543,7 @@ public:
|
||||
{
|
||||
m_nodes.pop();
|
||||
for (auto& c : m_current->m_children)
|
||||
m_nodes.push(&c);
|
||||
m_nodes.push(c.get());
|
||||
m_current = m_nodes.size() ? m_nodes.top() : nullptr;
|
||||
return *this;
|
||||
}
|
||||
@@ -536,14 +562,236 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class NodeBorder : public Node
|
||||
{
|
||||
static Plane m_plane;
|
||||
glm::vec4 m_color;
|
||||
glm::vec4 m_border_color;
|
||||
float m_thinkness{ 1 };
|
||||
public:
|
||||
static void 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);
|
||||
|
||||
ShaderManager::u_vec4(kShaderUniform::Col, m_color);
|
||||
m_plane.draw_fill();
|
||||
|
||||
glLineWidth(m_thinkness);
|
||||
ShaderManager::u_vec4(kShaderUniform::Col, m_border_color);
|
||||
m_plane.draw_stroke();
|
||||
}
|
||||
virtual kEventResult handle_event(Event* e) override
|
||||
{
|
||||
switch (e->m_type)
|
||||
{
|
||||
case kEventType::MouseEnter:
|
||||
m_color = rand_color();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return kEventResult::Consumed;
|
||||
}
|
||||
};
|
||||
|
||||
class NodeText : public Node
|
||||
{
|
||||
TextMesh m_text_mesh;
|
||||
std::string m_text;
|
||||
std::string m_font;
|
||||
glm::vec4 m_color{ 1, 1, 1, 1 };
|
||||
int m_size;
|
||||
public:
|
||||
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);
|
||||
}
|
||||
virtual void create() override
|
||||
{
|
||||
char font[64];
|
||||
sprintf(font, "%s-%d", m_font.c_str(), m_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_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_id;
|
||||
static void 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);
|
||||
}
|
||||
virtual void create() override
|
||||
{
|
||||
if (TextureManager::load(m_path.c_str()))
|
||||
{
|
||||
auto tex_sz = TextureManager::get(m_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_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_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_id).unbind();
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
};
|
||||
|
||||
class LayoutManager
|
||||
{
|
||||
std::map<uint16_t, Node> m_layouts;
|
||||
std::map<uint16_t, std::unique_ptr<Node>> m_layouts;
|
||||
std::string m_path;
|
||||
struct stat m_file_info { 0 };
|
||||
public:
|
||||
bool load(const char* path);
|
||||
bool reload();
|
||||
Node& operator[](uint16_t id) { return m_layouts[id]; }
|
||||
Node& operator[](uint16_t id) { return *m_layouts[id]; }
|
||||
//Node& operator[](const char* ids) { return m_layouts[const_hash(ids)]; }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user