big refactoring to merge node and widgets into a single node hierarchy

This commit is contained in:
2017-02-11 01:40:40 +00:00
parent 914fc34331
commit b1abb42dd5
3 changed files with 439 additions and 130 deletions

View File

@@ -132,8 +132,8 @@ void App::init()
ShaderManager::create(kShader::UVs, shader_v, shader_uv_f); ShaderManager::create(kShader::UVs, shader_v, shader_uv_f);
ShaderManager::create(kShader::Font, shader_font_v, shader_font_f); ShaderManager::create(kShader::Font, shader_font_v, shader_font_f);
ShaderManager::create(kShader::Atlas, shader_atlas_v, shader_atlas_f); ShaderManager::create(kShader::Atlas, shader_atlas_v, shader_atlas_f);
WidgetBorder::init(); NodeBorder::init();
WidgetImage::init(); NodeImage::init();
if (!tex.load("data/uvs.jpg")) if (!tex.load("data/uvs.jpg"))
printf("error loading image\n"); printf("error loading image\n");
@@ -179,14 +179,14 @@ void App::update(float dt)
} }
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_SCISSOR_TEST); //glEnable(GL_SCISSOR_TEST);
for (auto& n : layout[main_id]) for (auto& n : layout[main_id])
{ {
if (n.m_display && n.m_widget) if (n.m_display)
{ {
auto box = n.m_widget->clip; auto box = n.m_clip;
glScissor((int)box.x, (int)(height - box.y - box.w), (int)box.z, (int)box.w); glScissor((int)box.x, (int)(height - box.y - box.w), (int)box.z, (int)box.w);
n.m_widget->draw(); n.draw();
} }
} }
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
@@ -229,16 +229,25 @@ void App::resize(float w, float h)
void App::mouse_down(int button, float x, float y) void App::mouse_down(int button, float x, float y)
{ {
constexpr auto main_id = const_hash("main"); constexpr auto main_id = const_hash("main");
printf("mouse click %f %f\n", x, y);
MouseEvent e; MouseEvent e;
e.m_type = kEventType::MouseDownL;
e.m_pos = { x, y }; e.m_pos = { x, y };
layout[main_id].on_event(&e); layout[main_id].on_event(&e);
printf("mouse click %f %f\n", x, y);
} }
void App::mouse_move(float x, float y) void App::mouse_move(float x, float y)
{ {
constexpr auto main_id = const_hash("main");
MouseEvent e;
e.m_type = kEventType::MouseMove;
e.m_pos = { x, y };
layout[main_id].on_event(&e);
} }
void App::mouse_up(int button, float x, float y) void App::mouse_up(int button, float x, float y)
{ {
constexpr auto main_id = const_hash("main");
MouseEvent e;
e.m_type = kEventType::MouseUpL;
e.m_pos = { x, y };
layout[main_id].on_event(&e);
} }

View File

@@ -2,9 +2,9 @@
#include "layout.h" #include "layout.h"
#include "util.h" #include "util.h"
Plane WidgetBorder::m_plane; Plane NodeBorder::m_plane;
Plane WidgetImage::m_plane; Plane NodeImage::m_plane;
Sampler WidgetImage::m_sampler; Sampler NodeImage::m_sampler;
Node* Node::find(const char* ids) Node* Node::find(const char* ids)
{ {
@@ -20,23 +20,49 @@ Node* Node::find(const char* ids)
kEventResult Node::on_event(Event* e) kEventResult Node::on_event(Event* e)
{ {
for (auto& c : m_children) for (auto& c : m_children)
if (c.on_event(e) == kEventResult::Handled) if (c->on_event(e) == kEventResult::Consumed)
return kEventResult::Handled; return kEventResult::Consumed;
if (m_widget) switch (e->m_cat)
{ {
switch (e->m_cat) case kEventCategory::MouseEvent:
{
MouseEvent* me = static_cast<MouseEvent*>(e);
bool inside = point_in_rect(me->m_pos, m_clip);
bool inside_old = m_mouse_inside;
switch (e->m_type)
{ {
case kEventCategory::MouseEvent: case kEventType::MouseDownL:
if (point_in_rect(((MouseEvent*)e)->m_pos, m_clip) && m_widget->on_event(e) == kEventResult::Handled) case kEventType::MouseDownR:
return kEventResult::Handled; case kEventType::MouseUpL:
case kEventType::MouseUpR:
if (inside && handle_event(e) == kEventResult::Consumed)
return kEventResult::Consumed;
break; break;
default: case kEventType::MouseMove:
if (m_widget->on_event(e) == kEventResult::Handled) if (inside_old == false && inside == true)
return kEventResult::Handled; {
MouseEvent e2 = *me;
e2.m_type = kEventType::MouseEnter;
handle_event(&e2);
}
m_mouse_inside = inside;
handle_event(e);
if (inside_old == true && inside == false)
{
MouseEvent e2 = *me;
e2.m_type = kEventType::MouseLeave;
handle_event(&e2);
}
break; break;
} }
break;
} }
return kEventResult::UnHandled; default:
if (handle_event(e) == kEventResult::Consumed)
return kEventResult::Consumed;
break;
}
return kEventResult::Available;
} }
void Node::update(float width, float height) void Node::update(float width, float height)
@@ -76,20 +102,13 @@ void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj)
m_clip = glm::vec4(m_pos, m_size); m_clip = glm::vec4(m_pos, m_size);
} }
if (m_widget) glm::mat4 pivot = glm::translate(glm::vec3(.5f, .5f, 0.f));
{ glm::mat4 scale = glm::scale(glm::vec3(glm::ceil(m_size), 1.f));
glm::mat4 pivot = glm::translate(glm::vec3(.5f, .5f, 0.f)); glm::mat4 pos = glm::translate(glm::vec3(glm::floor(m_pos), 0));
glm::mat4 scale = glm::scale(glm::vec3(glm::ceil(m_size), 1.f)); m_mvp = proj * pos * scale * pivot;
glm::mat4 pos = glm::translate(glm::vec3(glm::floor(m_pos), 0)); m_proj = proj;
m_widget->mvp = proj * pos * scale * pivot;
m_widget->pos = pos;
m_widget->scale = scale;
m_widget->proj = proj;
m_widget->clip = m_clip;
m_widget->update();
}
for (auto& c : m_children) for (auto& c : m_children)
c.update_internal(m_pos, proj); c->update_internal(m_pos, proj);
} }
void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
@@ -237,8 +256,6 @@ void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
break; break;
} }
default: default:
if (m_widget)
m_widget->parse_attributes(ka, attr);
break; break;
} }
} }
@@ -246,78 +263,104 @@ void Node::parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr)
void Node::load_internal(const tinyxml2::XMLElement* x_node) void Node::load_internal(const tinyxml2::XMLElement* x_node)
{ {
m_name = x_node->Name(); m_name = x_node->Name();
auto attr = x_node->FirstAttribute(); auto attr = x_node->FirstAttribute();
kWidget widget_id = (kWidget)const_hash(x_node->Name());
switch (widget_id)
{
case kWidget::Border:
m_widget = std::make_unique<WidgetBorder>();
break;
case kWidget::Shape:
m_widget = std::make_unique<WidgetShape>();
break;
case kWidget::Text:
m_widget = std::make_unique<WidgetText>();
break;
case kWidget::Image:
m_widget = std::make_unique<WidgetImage>();
break;
}
while (attr) while (attr)
{ {
parse_attributes((kAttribute)const_hash(attr->Name()), attr); parse_attributes((kAttribute)const_hash(attr->Name()), attr);
attr = attr->Next(); attr = attr->Next();
} }
if (m_widget) create();
m_widget->create();
if (widget_id == kWidget::Text)
SetSize(((WidgetText*)m_widget.get())->m_text_mesh.bb);
auto x_child = x_node->FirstChildElement(); auto x_child = x_node->FirstChildElement();
while (x_child) while (x_child)
{ {
//Node n; kWidget child_id = (kWidget)const_hash(x_child->Name());
if (strcmp("ref", x_child->Name()) == 0) switch (child_id)
{
case kWidget::Border:
{
auto n = new NodeBorder();
m_children.emplace_back(n);
n->parent = this;
n->m_manager = m_manager;
YGNodeInsertChild(y_node, n->y_node, YGNodeGetChildCount(y_node));
n->load_internal(x_child);
break;
}
// case kWidget::Shape:
// break;
case kWidget::Image:
{
auto n = new NodeImage();
m_children.emplace_back(n);
n->parent = this;
n->m_manager = m_manager;
YGNodeInsertChild(y_node, n->y_node, YGNodeGetChildCount(y_node));
n->load_internal(x_child);
break;
}
case kWidget::Text:
{
auto n = new NodeText();
m_children.emplace_back(n);
n->parent = this;
n->m_manager = m_manager;
YGNodeInsertChild(y_node, n->y_node, YGNodeGetChildCount(y_node));
n->load_internal(x_child);
break;
}
case kWidget::Ref:
{ {
auto ids = x_child->Attribute("id"); auto ids = x_child->Attribute("id");
auto id = const_hash(ids); auto id = const_hash(ids);
auto& ref = (*m_manager)[id]; auto& ref = (*m_manager)[id];
m_children.push_back(ref.clone()); auto n = ref.clone();
m_children.back().parent = this; m_children.emplace_back(n);
YGNodeInsertChild(y_node, m_children.back().y_node, YGNodeGetChildCount(y_node)); n->parent = this;
n->m_manager = m_manager;
YGNodeInsertChild(y_node, n->y_node, YGNodeGetChildCount(y_node));
break;
} }
else default:
{ {
m_children.emplace_back(); auto n = new Node();
auto& n = m_children.back(); m_children.emplace_back(n);
n.parent = this; n->parent = this;
n.m_manager = m_manager; n->m_manager = m_manager;
YGNodeInsertChild(y_node, n.y_node, YGNodeGetChildCount(y_node)); YGNodeInsertChild(y_node, n->y_node, YGNodeGetChildCount(y_node));
n.load_internal(x_child); n->load_internal(x_child);
break;
}
} }
x_child = x_child->NextSiblingElement(); x_child = x_child->NextSiblingElement();
} }
} }
Node Node::clone() Node* Node::clone()
{ {
Node n; Node* n = clone_instantiate();
YGNodeCopyStyle(n.y_node, y_node); clone_copy(n);
if (m_widget) return n;
n.m_widget = m_widget->clone(); }
n.m_manager = m_manager;
Node* Node::clone_instantiate() const
{
return new Node();
}
void Node::clone_copy(Node* dest) const
{
YGNodeCopyStyle(dest->y_node, y_node);
dest->m_manager = m_manager;
for (auto& c : m_children) for (auto& c : m_children)
{ {
n.m_children.push_back(std::move(c.clone())); Node* cn = c->clone();
auto& cn = n.m_children.back(); // child node reference dest->m_children.emplace_back(cn);
cn.parent = &n; cn->parent = dest;
YGNodeInsertChild(n.y_node, cn.y_node, YGNodeGetChildCount(n.y_node)); YGNodeInsertChild(dest->y_node, cn->y_node, YGNodeGetChildCount(dest->y_node));
} }
return std::move(n);
} }
bool LayoutManager::load(const char* path) bool LayoutManager::load(const char* path)
@@ -352,15 +395,24 @@ bool LayoutManager::load(const char* path)
if (p == m_layouts.end()) if (p == m_layouts.end())
{ {
auto& node = m_layouts[id]; auto& node = m_layouts[id];
node.m_manager = this; kWidget node_id = (kWidget)const_hash(current->Name());
switch (node_id)
{
case kWidget::Border:
node.reset(new NodeBorder());
break;
default:
node.reset(new Node());
break;
}
node->m_manager = this;
// try to copy the old size values // try to copy the old size values
if (old.count(id)) if (old.count(id))
{ {
const auto& old_node = old[id]; const auto& old_node = *old[id];
YGNodeCopyStyle(node.y_node, old_node.y_node); YGNodeCopyStyle(node->y_node, old_node.y_node);
} }
if (!current->NoChildren()) node->load_internal(current);
node.load_internal(current->FirstChildElement());
} }
else else
{ {

View File

@@ -54,8 +54,8 @@ enum class kShapeType : uint16_t
enum class kEventResult : uint8_t enum class kEventResult : uint8_t
{ {
Handled, Consumed,
UnHandled, Available,
}; };
enum class kEventCategory : uint8_t enum class kEventCategory : uint8_t
@@ -69,6 +69,8 @@ enum class kEventType : uint8_t
MouseMove, MouseMove,
MouseUpL, MouseUpL,
MouseUpR, MouseUpR,
MouseEnter,
MouseLeave,
}; };
class Event class Event
@@ -93,23 +95,15 @@ public:
glm::mat4 scale; glm::mat4 scale;
glm::mat4 pos; glm::mat4 pos;
glm::vec4 clip; glm::vec4 clip;
virtual std::unique_ptr<Widget> clone() = 0; bool m_mouse_inside = false;
virtual Widget* clone() = 0;
virtual void create() { } virtual void create() { }
virtual void draw() { } virtual void draw() { }
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) { } virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) { }
virtual void update() { } 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 class WidgetBorder : public Widget
{ {
public: public:
@@ -121,11 +115,11 @@ public:
{ {
m_plane.create<1>(1, 1); 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; *ret = *this;
return std::move(ret); return ret;
} }
virtual void draw() override virtual void draw() override
{ {
@@ -172,8 +166,15 @@ public:
} }
virtual kEventResult on_event(Event* e) virtual kEventResult on_event(Event* e)
{ {
m_color = rand_color(); switch (e->m_type)
return kEventResult::Handled; {
case kEventType::MouseEnter:
m_color = rand_color();
break;
default:
break;
}
return kEventResult::Consumed;
} }
}; };
@@ -186,11 +187,11 @@ public:
glm::vec4 m_border_color; glm::vec4 m_border_color;
float m_thinkness{ 1 }; float m_thinkness{ 1 };
float m_radius{ .5f }; 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; //*ret = *this;
return std::move(ret); return ret;
} }
virtual void create() override virtual void create() override
{ {
@@ -272,11 +273,11 @@ public:
std::string m_font; std::string m_font;
glm::vec4 m_color{ 1, 1, 1, 1 }; glm::vec4 m_color{ 1, 1, 1, 1 };
int m_size; 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; *ret = *this;
return std::move(ret); return ret;
} }
virtual void create() override virtual void create() override
{ {
@@ -329,8 +330,8 @@ public:
} }
virtual kEventResult on_event(Event* e) virtual kEventResult on_event(Event* e)
{ {
m_color = rand_color(); //m_color = rand_color();
return kEventResult::Handled; return kEventResult::Consumed;
} }
}; };
@@ -350,11 +351,11 @@ public:
m_plane.create<1>(1, 1); m_plane.create<1>(1, 1);
m_sampler.create(); 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; *ret = *this;
return std::move(ret); return ret;
} }
virtual void create() override virtual void create() override
{ {
@@ -413,9 +414,27 @@ public:
virtual kEventResult on_event(Event* e) virtual kEventResult on_event(Event* e)
{ {
MouseEvent* me = static_cast<MouseEvent*>(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 class Node
{ {
@@ -428,8 +447,12 @@ class Node
public: public:
uint16_t m_nodeID; uint16_t m_nodeID;
std::string m_nodeID_s; std::string m_nodeID_s;
std::vector<Node> m_children; std::vector<std::unique_ptr<Node>> m_children;
std::unique_ptr<Widget> m_widget;
glm::mat4 m_proj;
glm::mat4 m_mvp;
bool m_mouse_inside = false;
glm::vec2 m_pos; glm::vec2 m_pos;
glm::vec2 m_size; glm::vec2 m_size;
glm::vec4 m_clip; glm::vec4 m_clip;
@@ -442,10 +465,9 @@ public:
{ {
m_name = std::move(o.m_name); m_name = std::move(o.m_name);
m_nodeID_s = std::move(o.m_nodeID_s); m_nodeID_s = std::move(o.m_nodeID_s);
m_widget = std::move(o.m_widget);
m_children = std::move(o.m_children); m_children = std::move(o.m_children);
for (auto& c : m_children) for (auto& c : m_children)
c.parent = this; c->parent = this;
m_nodeID = o.m_nodeID; m_nodeID = o.m_nodeID;
m_display = o.m_display; m_display = o.m_display;
parent = o.parent; parent = o.parent;
@@ -495,12 +517,16 @@ public:
void update(float width, float height); void update(float width, float height);
void update_internal(const glm::vec2& origin, const glm::mat4& proj); 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 load_internal(const tinyxml2::XMLElement* x_node);
void draw(); virtual void draw() { }
Node clone(); Node* clone();
virtual Node* clone_instantiate() const;
virtual void clone_copy(Node* dest) const;
Node* find(const char* ids); Node* find(const char* ids);
kEventResult on_event(Event* e); kEventResult on_event(Event* e);
virtual kEventResult handle_event(Event* e) { return kEventResult::Available; }
virtual void create() { };
class iterator class iterator
{ {
@@ -517,7 +543,7 @@ public:
{ {
m_nodes.pop(); m_nodes.pop();
for (auto& c : m_current->m_children) 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; m_current = m_nodes.size() ? m_nodes.top() : nullptr;
return *this; 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 class LayoutManager
{ {
std::map<uint16_t, Node> m_layouts; std::map<uint16_t, std::unique_ptr<Node>> m_layouts;
std::string m_path; std::string m_path;
struct stat m_file_info { 0 }; struct stat m_file_info { 0 };
public: public:
bool load(const char* path); bool load(const char* path);
bool reload(); 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)]; } //Node& operator[](const char* ids) { return m_layouts[const_hash(ids)]; }
}; };