mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
refactor(font): return TextMesh from Font::vertices to include bounding box
Replace the plain vertex vector with a TextMesh struct that carries width, height, and min coordinates. Update Label to compute and store these values immediately on text change (removing lazy dirty update). Fix Button's width/height to factor in scale and use concrete widget types for background and foreground.
This commit is contained in:
@@ -22,6 +22,16 @@ struct Character {
|
|||||||
GLuint advance;
|
GLuint advance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TextMesh {
|
||||||
|
std::vector<Vertex2D> vertices;
|
||||||
|
|
||||||
|
float width;
|
||||||
|
float height;
|
||||||
|
|
||||||
|
float min_x;
|
||||||
|
float min_y;
|
||||||
|
};
|
||||||
|
|
||||||
class Shader;
|
class Shader;
|
||||||
|
|
||||||
class Font {
|
class Font {
|
||||||
@@ -29,7 +39,7 @@ public:
|
|||||||
Font();
|
Font();
|
||||||
~Font();
|
~Font();
|
||||||
|
|
||||||
static std::vector<Vertex2D> vertices(const std::string& text);
|
static TextMesh vertices(const std::string& text);
|
||||||
static const Texture* text_texture();
|
static const Texture* text_texture();
|
||||||
static const std::string& font_path();
|
static const std::string& font_path();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Cubed/ui/image.hpp"
|
||||||
|
#include "Cubed/ui/label.hpp"
|
||||||
#include "Cubed/ui/widget.hpp"
|
#include "Cubed/ui/widget.hpp"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -47,8 +49,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::function<void()> m_clicked;
|
std::function<void()> m_clicked;
|
||||||
std::unique_ptr<Widget> m_background;
|
std::unique_ptr<Image> m_background;
|
||||||
std::unique_ptr<Widget> m_foreground;
|
std::unique_ptr<Label> m_foreground;
|
||||||
bool m_hovered = false;
|
bool m_hovered = false;
|
||||||
glm::vec2 m_min_pos;
|
glm::vec2 m_min_pos;
|
||||||
glm::vec2 m_max_pos;
|
glm::vec2 m_max_pos;
|
||||||
|
|||||||
@@ -24,6 +24,11 @@ public:
|
|||||||
|
|
||||||
const TextStyle& text_style() const;
|
const TextStyle& text_style() const;
|
||||||
|
|
||||||
|
float width() const override;
|
||||||
|
float height() const override;
|
||||||
|
float offset_x() const;
|
||||||
|
float offset_y() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void on_update(float dt) override;
|
virtual void on_update(float dt) override;
|
||||||
virtual void on_render(Renderer& renderer) override;
|
virtual void on_render(Renderer& renderer) override;
|
||||||
@@ -31,7 +36,10 @@ protected:
|
|||||||
private:
|
private:
|
||||||
TextStyle m_text;
|
TextStyle m_text;
|
||||||
UIVertexData m_data;
|
UIVertexData m_data;
|
||||||
bool m_dirty = false;
|
float m_width = 0.0f;
|
||||||
|
float m_height = 0.0f;
|
||||||
|
float m_offset_x = 0.0f;
|
||||||
|
float m_offset_y = 0.0f;
|
||||||
void update_vertices();
|
void update_vertices();
|
||||||
};
|
};
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -62,11 +62,16 @@ void Font::setup_font_character() {
|
|||||||
m_text_texture->set_clamp_to_edge(false, true, true);
|
m_text_texture->set_clamp_to_edge(false, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Vertex2D> Font::vertices(const std::string& text) {
|
TextMesh Font::vertices(const std::string& text) {
|
||||||
static Font font;
|
static Font font;
|
||||||
|
|
||||||
std::vector<Vertex2D> vertices;
|
std::vector<Vertex2D> vertices;
|
||||||
|
|
||||||
|
float min_x = std::numeric_limits<float>::max();
|
||||||
|
float min_y = std::numeric_limits<float>::max();
|
||||||
|
float max_x = std::numeric_limits<float>::lowest();
|
||||||
|
float max_y = std::numeric_limits<float>::lowest();
|
||||||
|
|
||||||
float pen_x = 0.0f;
|
float pen_x = 0.0f;
|
||||||
float pen_y = 0.0f;
|
float pen_y = 0.0f;
|
||||||
|
|
||||||
@@ -85,6 +90,12 @@ std::vector<Vertex2D> Font::vertices(const std::string& text) {
|
|||||||
float w = ch.size.x;
|
float w = ch.size.x;
|
||||||
float h = ch.size.y;
|
float h = ch.size.y;
|
||||||
|
|
||||||
|
min_x = std::min(min_x, xpos);
|
||||||
|
min_y = std::min(min_y, ypos);
|
||||||
|
|
||||||
|
max_x = std::max(max_x, xpos + w);
|
||||||
|
max_y = std::max(max_y, ypos + h);
|
||||||
|
|
||||||
vertices.emplace_back(xpos, ypos + h, ch.uv_min.x, ch.uv_max.y,
|
vertices.emplace_back(xpos, ypos + h, ch.uv_min.x, ch.uv_max.y,
|
||||||
static_cast<float>(c));
|
static_cast<float>(c));
|
||||||
vertices.emplace_back(xpos, ypos, ch.uv_min.x, ch.uv_min.y,
|
vertices.emplace_back(xpos, ypos, ch.uv_min.x, ch.uv_min.y,
|
||||||
@@ -101,8 +112,13 @@ std::vector<Vertex2D> Font::vertices(const std::string& text) {
|
|||||||
|
|
||||||
pen_x += (ch.advance >> 6);
|
pen_x += (ch.advance >> 6);
|
||||||
}
|
}
|
||||||
|
// Top-left anchor point
|
||||||
|
for (auto& v : vertices) {
|
||||||
|
v.x -= min_x;
|
||||||
|
v.y -= min_y;
|
||||||
|
}
|
||||||
|
|
||||||
return vertices;
|
return {std::move(vertices), max_x - min_x, max_y - min_y, 0, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
const Texture* Font::text_texture() { return m_text_texture.get(); }
|
const Texture* Font::text_texture() { return m_text_texture.get(); }
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ Widget& Button::set_position(const glm::vec2& pos) {
|
|||||||
m_foreground->set_position(pos);
|
m_foreground->set_position(pos);
|
||||||
m_min_pos = pos;
|
m_min_pos = pos;
|
||||||
|
|
||||||
m_max_pos.x = m_min_pos.x + m_background->width() * m_scale;
|
m_max_pos.x = m_min_pos.x + width();
|
||||||
m_max_pos.y = m_min_pos.y + m_background->height() * m_scale;
|
m_max_pos.y = m_min_pos.y + height();
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -62,11 +62,11 @@ Widget& Button::set_position(float x, float y) {
|
|||||||
Widget& Button::set_scale(float scale) {
|
Widget& Button::set_scale(float scale) {
|
||||||
m_scale = scale;
|
m_scale = scale;
|
||||||
m_background->set_scale(scale);
|
m_background->set_scale(scale);
|
||||||
m_max_pos.x = m_min_pos.x + m_background->width() * m_scale;
|
m_max_pos.x = m_min_pos.x + width();
|
||||||
m_max_pos.y = m_min_pos.y + m_background->height() * m_scale;
|
m_max_pos.y = m_min_pos.y + height();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
float Button::width() const { return m_background->width(); }
|
float Button::width() const { return m_background->width() * m_scale; }
|
||||||
float Button::height() const { return m_background->height(); }
|
float Button::height() const { return m_background->height() * m_scale; }
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -7,7 +7,7 @@ Label::Label(const std::string& id) : Widget(id) {}
|
|||||||
Label::Label() {}
|
Label::Label() {}
|
||||||
Label& Label::set_text(std::string_view text) {
|
Label& Label::set_text(std::string_view text) {
|
||||||
m_text.text = text;
|
m_text.text = text;
|
||||||
m_dirty = true;
|
update_vertices();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,25 +18,30 @@ Label& Label::set_color(Color color) {
|
|||||||
|
|
||||||
void Label::update(float dt) { on_update(dt); }
|
void Label::update(float dt) { on_update(dt); }
|
||||||
|
|
||||||
void Label::on_update(float dt) {
|
void Label::on_update(float dt) { (void)dt; }
|
||||||
(void)dt;
|
|
||||||
if (m_dirty) {
|
|
||||||
update_vertices();
|
|
||||||
m_dirty = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Label::render(Renderer& renderer) { on_render(renderer); }
|
void Label::render(Renderer& renderer) { on_render(renderer); }
|
||||||
|
|
||||||
void Label::on_render(Renderer& renderer) { renderer.render_lable(*this); }
|
void Label::on_render(Renderer& renderer) { renderer.render_lable(*this); }
|
||||||
|
|
||||||
void Label::update_vertices() {
|
void Label::update_vertices() {
|
||||||
m_data.m_vertices = Font::vertices(m_text.text);
|
auto textmesh = Font::vertices(m_text.text);
|
||||||
|
m_data.m_vertices = std::move(textmesh.vertices);
|
||||||
|
|
||||||
|
m_offset_x = textmesh.min_x;
|
||||||
|
m_offset_y = textmesh.min_y;
|
||||||
|
m_width = textmesh.width;
|
||||||
|
m_height = textmesh.height;
|
||||||
|
|
||||||
m_data.update_sum();
|
m_data.update_sum();
|
||||||
m_data.upload();
|
m_data.upload();
|
||||||
}
|
}
|
||||||
|
|
||||||
const UIVertexData& Label::data() const { return m_data; }
|
const UIVertexData& Label::data() const { return m_data; }
|
||||||
const TextStyle& Label::text_style() const { return m_text; }
|
const TextStyle& Label::text_style() const { return m_text; }
|
||||||
|
float Label::width() const { return m_width; }
|
||||||
|
float Label::height() const { return m_height; }
|
||||||
|
float Label::offset_x() const { return m_offset_x; }
|
||||||
|
float Label::offset_y() const { return m_offset_y; }
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
Reference in New Issue
Block a user