diff --git a/data/layout.xml b/data/layout.xml
index 41fcced..576da8a 100644
--- a/data/layout.xml
+++ b/data/layout.xml
@@ -57,9 +57,9 @@
-
-
-
+
+
+
diff --git a/engine/app.cpp b/engine/app.cpp
index 67b5113..74116d2 100644
--- a/engine/app.cpp
+++ b/engine/app.cpp
@@ -93,6 +93,14 @@ void App::init()
glEnable(GL_DEBUG_OUTPUT);
#endif
+#if _WIN32
+ const char* ttf = "C:\\Windows\\Fonts\\arial.ttf";
+#else
+ const char* ttf = "/Library/Fonts/Arial.ttf";
+#endif
+ FontManager::init();
+ FontManager::load(kFont::Arial_11, ttf);
+
layout.load("data/layout.xml");
//layout["main"].update(width, height);
@@ -106,13 +114,8 @@ void App::init()
if (!tex.load("data/uvs.jpg"))
printf("error loading image\n");
-#if _WIN32
- const char* ttf = "C:\\Windows\\Fonts\\arial.ttf";
-#else
- const char* ttf = "/Library/Fonts/Arial.ttf";
-#endif
- FontManager::load(kFont::Arial_11, ttf);
text.create();
+ text.update(kFont::Arial_11, "hello font");
plane.create<1>(400, 400);
glEnable(GL_TEXTURE_2D);
@@ -165,22 +168,10 @@ void App::update(float dt)
glm::mat4 proj = glm::ortho(0.f, width, height, 0.f, -1.f, 1.f);
glm::mat4 tran = glm::translate(glm::vec3(200, 200, 0));
- glActiveTexture(GL_TEXTURE0);
- font_tex.bind();
- sampler.bind(0);
ShaderManager::use(kShader::Font);
ShaderManager::u_int(kShaderUniform::Tex, 0);
- ShaderManager::u_mat4(kShaderUniform::MVP, proj*tran);
-
-// plane.draw_fill();
- glBindVertexArray(font_array);
- glDrawElements(GL_TRIANGLES, font_array_count, GL_UNSIGNED_SHORT, 0);
- glBindVertexArray(0);
-
- font_tex.unbind();
- sampler.unbind();
-
-
+ ShaderManager::u_mat4(kShaderUniform::MVP, proj * tran);
+ text.draw();
/*
static int i = 0;
i = (i + 1) % 32;
diff --git a/engine/font.cpp b/engine/font.cpp
index 7df9a81..9d5469d 100644
--- a/engine/font.cpp
+++ b/engine/font.cpp
@@ -1,7 +1,9 @@
#include "pch.h"
#include "font.h"
+#include "shader.h"
std::map FontManager::m_fonts;
+Sampler FontManager::m_sampler;
bool Font::load(const char* ttf)
{
@@ -24,6 +26,11 @@ bool Font::load(const char* ttf)
return false;
}
+void FontManager::init()
+{
+ m_sampler.create();
+}
+
bool FontManager::load(kFont id, const char *ttf)
{
return m_fonts[id].load(ttf);
@@ -52,24 +59,23 @@ bool TextMesh::create()
void TextMesh::update(kFont id, const char* text)
{
+ font_id = id;
auto& f = FontManager::get(id);
if (f.chars.size())
{
- static char str[64];
- static int counter = 0;
- counter++;
- sprintf(str, "frame %04d", counter);
- const auto len = strlen(str);
+ const auto len = strlen(text);
float x = 0;
float y = 0;
std::vector v;
std::vector idx;
+ glm::vec2 bbmin;
+ glm::vec2 bbmax;
for (int i = 0; i < len; i++)
{
- int c = str[i] - f.start_char;
+ int c = text[i] - f.start_char;
stbtt_aligned_quad q;
stbtt_GetBakedQuad((stbtt_bakedchar*)f.chars.data(), f.w, f.h, c, &x, &y, &q, true);
- auto n = v.size();
+ auto n = (int)v.size();
v.emplace_back(q.x0, q.y1, q.s0, q.t1);
v.emplace_back(q.x0, q.y0, q.s0, q.t0);
v.emplace_back(q.x1, q.y0, q.s1, q.t0);
@@ -80,7 +86,14 @@ void TextMesh::update(kFont id, const char* text)
idx.push_back(n+0);
idx.push_back(n+2);
idx.push_back(n+3);
+ bbmin = glm::min(bbmin, { q.x0, q.y0 });
+ bbmax = glm::max(bbmax, { q.x1, q.y1 });
}
+ for (int i = 0; i < len*4; i++)
+ {
+ v[i] -= glm::vec4(bbmin, 0, 0);
+ }
+ bb = bbmax - bbmin;
font_array_count = (int)idx.size();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_buffers[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx.size() * sizeof(GLushort), idx.data(), GL_STATIC_DRAW);
@@ -90,3 +103,21 @@ void TextMesh::update(kFont id, const char* text)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
}
+
+void TextMesh::draw()
+{
+ auto& f = FontManager::get(font_id);
+ if (f.font_tex.ready())
+ {
+ glActiveTexture(GL_TEXTURE0);
+ f.font_tex.bind();
+ FontManager::m_sampler.bind(0);
+
+ glBindVertexArray(font_array);
+ glDrawElements(GL_TRIANGLES, font_array_count, GL_UNSIGNED_SHORT, 0);
+ glBindVertexArray(0);
+
+ f.font_tex.unbind();
+ FontManager::m_sampler.unbind();
+ }
+}
diff --git a/engine/font.h b/engine/font.h
index 269340c..7835354 100644
--- a/engine/font.h
+++ b/engine/font.h
@@ -4,7 +4,7 @@
enum class kFont : uint16_t
{
- Arial_11 = const_hash("arial-16"),
+ Arial_11 = const_hash("arial-11"),
};
class Font
@@ -23,8 +23,10 @@ public:
class FontManager
{
- static std::map m_fonts;
public:
+ static std::map m_fonts;
+ static Sampler m_sampler;
+ static void init();
static bool load(kFont id, const char* ttf);
static const Font& get(kFont id);
};
@@ -35,6 +37,9 @@ public:
GLuint font_array = 0;
int font_array_count = 0;
GLuint font_buffers[2] = {0, 0};
+ kFont font_id;
+ glm::vec2 bb;
bool create();
void update(kFont id, const char* text);
+ void draw();
};
diff --git a/engine/layout.cpp b/engine/layout.cpp
index 396a74f..6161441 100644
--- a/engine/layout.cpp
+++ b/engine/layout.cpp
@@ -47,7 +47,11 @@ void Node::update_internal(const glm::vec2& origin, const glm::mat4& proj)
glm::mat4 scale = glm::scale(glm::vec3(m_size, 1.f));
glm::mat4 pos = glm::translate(glm::vec3(m_pos, 0));
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)
c.update_internal(m_pos, proj);
@@ -184,6 +188,9 @@ void Node::load_internal(const tinyxml2::XMLElement* x_node)
case kWidget::Shape:
m_widget = std::make_unique();
break;
+ case kWidget::Text:
+ m_widget = std::make_unique();
+ break;
}
while (attr)
@@ -195,6 +202,9 @@ void Node::load_internal(const tinyxml2::XMLElement* x_node)
if (m_widget)
m_widget->create();
+ if (widget_id == kWidget::Text)
+ SetSize(((WidgetText*)m_widget.get())->m_text_mesh.bb);
+
auto x_child = x_node->FirstChildElement();
while (x_child)
{
diff --git a/engine/layout.h b/engine/layout.h
index dcae025..9e461bf 100644
--- a/engine/layout.h
+++ b/engine/layout.h
@@ -2,6 +2,7 @@
#include "shape.h"
#include "util.h"
#include "shader.h"
+#include "font.h"
enum class kAttribute : uint16_t
{
@@ -25,12 +26,16 @@ enum class kAttribute : uint16_t
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"),
};
enum class kWidget : uint16_t
{
Border = const_hash("border"),
Shape = const_hash("shape"),
+ Text = const_hash("text"),
Ref = const_hash("ref"),
};
@@ -46,11 +51,15 @@ class Widget
{
public:
glm::mat4 mvp;
+ glm::mat4 proj;
+ glm::mat4 scale;
+ glm::mat4 pos;
glm::vec4 clip;
virtual std::unique_ptr clone() = 0;
virtual void create() { }
virtual void draw() { }
virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) { }
+ virtual void update() { }
};
class WidgetRef : public Widget
@@ -207,6 +216,55 @@ public:
}
};
+class WidgetText : public Widget
+{
+public:
+ TextMesh m_text_mesh;
+ std::string m_text;
+ std::string m_font;
+ int m_size;
+ virtual std::unique_ptr clone() override
+ {
+ return nullptr;
+ }
+ 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());
+ }
+ virtual void draw() override
+ {
+ ShaderManager::use(kShader::Font);
+ ShaderManager::u_int(kShaderUniform::Tex, 0);
+ ShaderManager::u_mat4(kShaderUniform::MVP, mvp);
+ m_text_mesh.draw();
+ }
+ virtual void parse_attributes(kAttribute ka, const tinyxml2::XMLAttribute* attr) override
+ {
+ 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;
+ default:
+ break;
+ }
+ }
+ virtual void update() override
+ {
+ mvp = proj * pos;
+ }
+};
+
class Node
{
friend class LayoutManager;
@@ -252,6 +310,7 @@ public:
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)
{
diff --git a/engine/texture.h b/engine/texture.h
index c009cd8..165c2a8 100644
--- a/engine/texture.h
+++ b/engine/texture.h
@@ -14,6 +14,7 @@ public:
void bind() const { glBindTexture(GL_TEXTURE_2D, m_tex); }
void unbind() const { glBindTexture(GL_TEXTURE_2D, 0); }
void update(const uint8_t* data);
+ bool ready() const { return m_tex != 0; }
};
class Sampler
@@ -25,4 +26,5 @@ public:
void set(GLint filter = GL_LINEAR, GLint wrap = GL_CLAMP_TO_EDGE);
void bind(int unit);
void unbind();
+ bool ready() const { return id != 0; }
};