mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
refactor(ui): replace Text with Label/Widget component system
Replace the old `Text` class with a new component-based UI system consisting of `Widget` and `Label` classes. Key changes: - Remove `Text` class and its GPU upload logic; introduce `Label` as a `Widget` subclass with dirty-flag vertex update. - Add `UIVertexData` struct to manage per-label vertex buffer/array and memory. - Refactor `DebugCollector` to store labels in a `Widget` tree, removing hash-based lookup. - Simplify `Font::vertices()` signature by removing position/scale parameters; scaling is now applied in the renderer’s model matrix. - Update `Renderer` with `render_label()` and move UI rendering to a `render_ui()` that renders the widget tree. - Add new source files `label.cpp`, `widget.cpp`, `ui_vertex_data.cpp` and update CMakeLists.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Cubed/ui/text.hpp"
|
#include "Cubed/ui/label.hpp"
|
||||||
|
#include "Cubed/ui/widget.hpp"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
@@ -11,14 +12,13 @@ public:
|
|||||||
static DebugCollector& get();
|
static DebugCollector& get();
|
||||||
DebugCollector();
|
DebugCollector();
|
||||||
|
|
||||||
std::unordered_map<std::size_t, Text>& all_texts();
|
void report(const std::string& name, std::string_view content);
|
||||||
|
|
||||||
Text& text(std::string_view name);
|
|
||||||
void report(std::string_view name, std::string_view content);
|
|
||||||
void init_text();
|
void init_text();
|
||||||
|
Widget& get_widget();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::size_t, Text> m_texts;
|
Widget m_widget;
|
||||||
|
std::unordered_map<std::string, Label*> m_component;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "Cubed/render/vertex_buffer.hpp"
|
#include "Cubed/render/vertex_buffer.hpp"
|
||||||
#include "Cubed/render/world_renderer.hpp"
|
#include "Cubed/render/world_renderer.hpp"
|
||||||
#include "Cubed/shader.hpp"
|
#include "Cubed/shader.hpp"
|
||||||
#include "Cubed/ui/text.hpp"
|
#include "Cubed/ui/label.hpp"
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -31,6 +31,9 @@ public:
|
|||||||
void init(bool debug_on);
|
void init(bool debug_on);
|
||||||
const Shader& get_shader(const std::string& name) const;
|
const Shader& get_shader(const std::string& name) const;
|
||||||
void render();
|
void render();
|
||||||
|
|
||||||
|
void render_lable(const Label& label);
|
||||||
|
|
||||||
void update(float delta_time);
|
void update(float delta_time);
|
||||||
void update_fov(float fov);
|
void update_fov(float fov);
|
||||||
void update_proj_matrix(float aspect, float width, float height);
|
void update_proj_matrix(float aspect, float width, float height);
|
||||||
@@ -118,9 +121,9 @@ private:
|
|||||||
void day_night_calculation();
|
void day_night_calculation();
|
||||||
|
|
||||||
void render_sky();
|
void render_sky();
|
||||||
void render_text();
|
|
||||||
void render_ui();
|
|
||||||
|
|
||||||
|
void render_ui();
|
||||||
|
void render_crosshair();
|
||||||
void render_dev_panel();
|
void render_dev_panel();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
11
include/Cubed/scene/scene.hpp
Normal file
11
include/Cubed/scene/scene.hpp
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Cubed {
|
||||||
|
class Scene {
|
||||||
|
public:
|
||||||
|
Scene() = default;
|
||||||
|
virtual ~Scene() = default;
|
||||||
|
virtual void update(float dt) = 0;
|
||||||
|
virtual void render() = 0;
|
||||||
|
};
|
||||||
|
} // namespace Cubed
|
||||||
@@ -29,9 +29,7 @@ public:
|
|||||||
Font();
|
Font();
|
||||||
~Font();
|
~Font();
|
||||||
|
|
||||||
static std::vector<Vertex2D> vertices(const std::string& text,
|
static std::vector<Vertex2D> vertices(const std::string& text);
|
||||||
float x = 0.0f, float y = 0.0f,
|
|
||||||
float scale = 1.0f);
|
|
||||||
static const Texture* text_texture();
|
static const Texture* text_texture();
|
||||||
static const std::string& font_path();
|
static const std::string& font_path();
|
||||||
|
|
||||||
|
|||||||
42
include/Cubed/ui/label.hpp
Normal file
42
include/Cubed/ui/label.hpp
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Cubed/ui/text.hpp"
|
||||||
|
#include "Cubed/ui/ui_vertex_data.hpp"
|
||||||
|
#include "Cubed/ui/widget.hpp"
|
||||||
|
#include "glm/ext/vector_float2.hpp"
|
||||||
|
namespace Cubed {
|
||||||
|
class Label : public Widget {
|
||||||
|
public:
|
||||||
|
Label(const Label&) = delete;
|
||||||
|
Label(Label&&) = delete;
|
||||||
|
Label& operator=(const Label&) = delete;
|
||||||
|
Label& operator=(Label&&) = delete;
|
||||||
|
|
||||||
|
Label(const std::string& id);
|
||||||
|
virtual ~Label() = default;
|
||||||
|
|
||||||
|
Label& set_position(const glm::vec2& pos);
|
||||||
|
Label& set_position(float x, float y);
|
||||||
|
Label& set_text(std::string_view text);
|
||||||
|
Label& set_scale(float scale);
|
||||||
|
Label& set_color(Color color);
|
||||||
|
virtual void update(float dt) override;
|
||||||
|
virtual void render(Renderer& renderer) override;
|
||||||
|
|
||||||
|
const UIVertexData& data() const;
|
||||||
|
const glm::vec2& pos() const;
|
||||||
|
const TextStyle& text_style() const;
|
||||||
|
float scale() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void on_update(float dt) override;
|
||||||
|
virtual void on_render(Renderer& renderer) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
float m_scale = 1.0f;
|
||||||
|
glm::vec2 m_pos{0.0f, 0.0f};
|
||||||
|
TextStyle m_text;
|
||||||
|
UIVertexData m_data;
|
||||||
|
bool m_dirty = false;
|
||||||
|
void update_vertices();
|
||||||
|
};
|
||||||
|
} // namespace Cubed
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Cubed/primitive_data.hpp"
|
|
||||||
#include "Cubed/render/vertex_array.hpp"
|
|
||||||
#include "Cubed/render/vertex_buffer.hpp"
|
|
||||||
#include "Cubed/ui/color.hpp"
|
#include "Cubed/ui/color.hpp"
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
@@ -10,46 +7,9 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
class Shader;
|
struct TextStyle {
|
||||||
|
std::string text;
|
||||||
class Text {
|
Color color = Color::WHITE;
|
||||||
public:
|
|
||||||
explicit Text(std::string_view name);
|
|
||||||
Text(std::string_view name, std::string_view str,
|
|
||||||
glm::vec2 pos = glm::vec2{0.0f, 0.0f}, Color color = Color::BLACK);
|
|
||||||
~Text();
|
|
||||||
Text(const Text&) = delete;
|
|
||||||
Text(Text&&) noexcept;
|
|
||||||
Text& operator=(const Text&) = delete;
|
|
||||||
Text& operator=(Text&&) noexcept = delete;
|
|
||||||
Text& color(Color color);
|
|
||||||
// Text& color(const glm::vec4& color, int pos);
|
|
||||||
Text& position(float x, float y);
|
|
||||||
Text& scale(float s);
|
|
||||||
Text& text(std::string_view str);
|
|
||||||
|
|
||||||
std::size_t uuid() const;
|
|
||||||
void render(const Shader& shader);
|
|
||||||
|
|
||||||
bool operator==(const Text& other) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
float m_scale = 1.0f;
|
|
||||||
glm::vec2 m_pos{0.0f, 0.0f};
|
|
||||||
|
|
||||||
const std::string NAME;
|
|
||||||
const std::size_t UUID;
|
|
||||||
|
|
||||||
std::string m_text;
|
|
||||||
glm::vec4 m_color{1.0f, 1.0f, 1.0f, 1.0f};
|
|
||||||
glm::mat4 m_model_matrix;
|
|
||||||
|
|
||||||
std::vector<Vertex2D> m_vertices;
|
|
||||||
std::unique_ptr<VertexBuffer> m_vbo;
|
|
||||||
std::unique_ptr<VertexArray> m_vao;
|
|
||||||
|
|
||||||
void update_vertices();
|
|
||||||
void upload_to_gpu();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
25
include/Cubed/ui/ui_vertex_data.hpp
Normal file
25
include/Cubed/ui/ui_vertex_data.hpp
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Cubed/primitive_data.hpp"
|
||||||
|
#include "Cubed/render/vertex_array.hpp"
|
||||||
|
#include "Cubed/render/vertex_buffer.hpp"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
namespace Cubed {
|
||||||
|
struct UIVertexData {
|
||||||
|
std::vector<Vertex2D> m_vertices;
|
||||||
|
std::unique_ptr<VertexBuffer> m_vbo;
|
||||||
|
std::unique_ptr<VertexArray> m_vao;
|
||||||
|
std::atomic<std::size_t> m_sum{0};
|
||||||
|
UIVertexData();
|
||||||
|
~UIVertexData();
|
||||||
|
UIVertexData(const UIVertexData&) = delete;
|
||||||
|
UIVertexData(UIVertexData&&) noexcept;
|
||||||
|
UIVertexData& operator=(const UIVertexData&) = delete;
|
||||||
|
UIVertexData& operator=(UIVertexData&&) noexcept;
|
||||||
|
|
||||||
|
void upload();
|
||||||
|
void update_sum();
|
||||||
|
};
|
||||||
|
} // namespace Cubed
|
||||||
31
include/Cubed/ui/widget.hpp
Normal file
31
include/Cubed/ui/widget.hpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
namespace Cubed {
|
||||||
|
class Renderer;
|
||||||
|
class Widget {
|
||||||
|
|
||||||
|
public:
|
||||||
|
Widget(const std::string& id);
|
||||||
|
Widget() = default;
|
||||||
|
virtual ~Widget() = default;
|
||||||
|
virtual void update(float dt);
|
||||||
|
virtual void render(Renderer& renderer);
|
||||||
|
virtual const std::string& id() const;
|
||||||
|
template <typename T, typename... Args> T& add_child(Args&&... args) {
|
||||||
|
auto widget = std::make_unique<T>(std::forward<Args>(args)...);
|
||||||
|
T& ref = *widget;
|
||||||
|
m_children.emplace_back(std::move(widget));
|
||||||
|
return ref;
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void on_update(float dt);
|
||||||
|
virtual void on_render(Renderer& renderer);
|
||||||
|
std::string m_id;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Widget* m_parent = nullptr;
|
||||||
|
std::vector<std::unique_ptr<Widget>> m_children;
|
||||||
|
};
|
||||||
|
} // namespace Cubed
|
||||||
@@ -17,7 +17,6 @@ target_sources(${PROJECT_NAME}
|
|||||||
tools/shader_tools.cpp
|
tools/shader_tools.cpp
|
||||||
tools/font.cpp
|
tools/font.cpp
|
||||||
tools/perlin_noise.cpp
|
tools/perlin_noise.cpp
|
||||||
ui/text.cpp
|
|
||||||
window.cpp
|
window.cpp
|
||||||
gameplay/builders/biome_builder.cpp
|
gameplay/builders/biome_builder.cpp
|
||||||
gameplay/builders/plain_builder.cpp
|
gameplay/builders/plain_builder.cpp
|
||||||
@@ -59,4 +58,7 @@ target_sources(${PROJECT_NAME}
|
|||||||
render/frame_buffer.cpp
|
render/frame_buffer.cpp
|
||||||
render/shader_manager.cpp
|
render/shader_manager.cpp
|
||||||
render/world_renderer.cpp
|
render/world_renderer.cpp
|
||||||
|
ui/widget.cpp
|
||||||
|
ui/label.cpp
|
||||||
|
ui/ui_vertex_data.cpp
|
||||||
)
|
)
|
||||||
@@ -375,6 +375,7 @@ void App::update() {
|
|||||||
m_audio.update_listener(m_camera.get_camera_pos(),
|
m_audio.update_listener(m_camera.get_camera_pos(),
|
||||||
m_camera.get_camera_front(), glm::vec3(0, 1, 0));
|
m_camera.get_camera_front(), glm::vec3(0, 1, 0));
|
||||||
m_audio.update();
|
m_audio.update();
|
||||||
|
DebugCollector::get().get_widget().update(dt);
|
||||||
m_renderer.update(dt);
|
m_renderer.update(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include "Cubed/debug_collector.hpp"
|
#include "Cubed/debug_collector.hpp"
|
||||||
|
|
||||||
#include "Cubed/tools/cubed_hash.hpp"
|
|
||||||
#include "Cubed/tools/system_info.hpp"
|
#include "Cubed/tools/system_info.hpp"
|
||||||
#include "version.hpp"
|
#include "version.hpp"
|
||||||
|
|
||||||
@@ -14,88 +13,105 @@ DebugCollector& DebugCollector::get() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DebugCollector::init_text() {
|
void DebugCollector::init_text() {
|
||||||
Text version_text("version");
|
// version_text
|
||||||
Text fps_text("fps");
|
auto& version_text = m_widget.add_child<Label>("version");
|
||||||
Text player_pos_text("player_pos");
|
|
||||||
Text rendered_chunk_text("rendered_chunk");
|
|
||||||
Text rss_text("rss");
|
|
||||||
Text cpu_text("cpu");
|
|
||||||
Text gpu_text("gpu");
|
|
||||||
Text opengl_version_text("opengl_version");
|
|
||||||
Text biome_text("biome");
|
|
||||||
Text speed_text("speed");
|
|
||||||
std::string version{"Version: " CUBED_VERSION};
|
std::string version{"Version: " CUBED_VERSION};
|
||||||
#ifdef DEBUG_MODE
|
#ifdef DEBUG_MODE
|
||||||
version.append("-debug");
|
version.append("-debug");
|
||||||
#else
|
#else
|
||||||
version.append("-release");
|
version.append("-release");
|
||||||
#endif
|
#endif
|
||||||
version_text.position(0.0f, 100.0f)
|
version_text.set_position(0.0f, 100.0f)
|
||||||
.scale(0.8f)
|
.set_scale(0.8f)
|
||||||
.color(Color::WHITE)
|
.set_color(Color::WHITE)
|
||||||
.text(version);
|
.set_text(version);
|
||||||
fps_text.position(0.0f, 50.0f).text("FPS: 0");
|
m_component.try_emplace(version_text.id(), &version_text);
|
||||||
player_pos_text.position(0.0f, 150.0f)
|
|
||||||
.scale(0.8f)
|
|
||||||
.text("x: 0.00 y: 0.00 z: 0.00");
|
|
||||||
rendered_chunk_text.text("Rendered Chunk: 0")
|
|
||||||
.scale(0.8f)
|
|
||||||
.position(0.0, 200.0f);
|
|
||||||
rss_text.text("RSS: 0mb").scale(0.8f).position(0.0f, 300.0f);
|
|
||||||
std::string os;
|
|
||||||
|
|
||||||
Text os_text("os");
|
// fps
|
||||||
os_text.scale(0.8f).position(0.0f, 250.0f);
|
auto& fps_text = m_widget.add_child<Label>("fps");
|
||||||
|
fps_text.set_position(0.0f, 50.0f).set_text("FPS: 0");
|
||||||
|
m_component.try_emplace(fps_text.id(), &fps_text);
|
||||||
|
|
||||||
|
// player_pos
|
||||||
|
auto& player_pos_text = m_widget.add_child<Label>("player_pos");
|
||||||
|
player_pos_text.set_position(0.0f, 150.0f)
|
||||||
|
.set_scale(0.8f)
|
||||||
|
.set_text("x: 0.00 y: 0.00 z: 0.00");
|
||||||
|
m_component.try_emplace(player_pos_text.id(), &player_pos_text);
|
||||||
|
|
||||||
|
// rendered_chunk
|
||||||
|
auto& rendered_chunk_text = m_widget.add_child<Label>("rendered_chunk");
|
||||||
|
rendered_chunk_text.set_text("Rendered Chunk: 0")
|
||||||
|
.set_scale(0.8f)
|
||||||
|
.set_position(0.0f, 200.0f);
|
||||||
|
m_component.try_emplace(rendered_chunk_text.id(), &rendered_chunk_text);
|
||||||
|
|
||||||
|
// rss
|
||||||
|
auto& rss_text = m_widget.add_child<Label>("rss");
|
||||||
|
rss_text.set_text("RSS: 0mb").set_scale(0.8f).set_position(0.0f, 300.0f);
|
||||||
|
m_component.try_emplace(rss_text.id(), &rss_text);
|
||||||
|
|
||||||
|
// os
|
||||||
|
std::string os;
|
||||||
|
auto& os_text = m_widget.add_child<Label>("os");
|
||||||
|
os_text.set_scale(0.8f).set_position(0.0f, 250.0f);
|
||||||
if (Tools::get_os_version(os)) {
|
if (Tools::get_os_version(os)) {
|
||||||
os_text.text("OS: " + os);
|
os_text.set_text("OS: " + os);
|
||||||
Logger::info("System: {}", os);
|
Logger::info("System: {}", os);
|
||||||
} else {
|
} else {
|
||||||
os_text.text("OS: Unknown");
|
os_text.set_text("OS: Unknown");
|
||||||
}
|
}
|
||||||
cpu_text.text("CPU: " + Tools::get_cpu_info())
|
m_component.try_emplace(os_text.id(), &os_text);
|
||||||
.scale(0.7f)
|
|
||||||
.position(0.0f, 350.0f);
|
// cpu
|
||||||
|
auto& cpu_text = m_widget.add_child<Label>("cpu");
|
||||||
|
cpu_text.set_text("CPU: " + Tools::get_cpu_info())
|
||||||
|
.set_scale(0.7f)
|
||||||
|
.set_position(0.0f, 350.0f);
|
||||||
|
m_component.try_emplace(cpu_text.id(), &cpu_text);
|
||||||
|
|
||||||
|
// gpu
|
||||||
|
auto& gpu_text = m_widget.add_child<Label>("gpu");
|
||||||
gpu_text
|
gpu_text
|
||||||
.text(std::string{"GPU: "} +
|
.set_text(std::string{"GPU: "} +
|
||||||
reinterpret_cast<const char*>(glGetString(GL_RENDERER)))
|
reinterpret_cast<const char*>(glGetString(GL_RENDERER)))
|
||||||
.scale(0.7f)
|
.set_scale(0.7f)
|
||||||
.position(0.0f, 400.0f);
|
.set_position(0.0f, 400.0f);
|
||||||
|
m_component.try_emplace(gpu_text.id(), &gpu_text);
|
||||||
|
|
||||||
|
// opengl_version
|
||||||
|
auto& opengl_version_text = m_widget.add_child<Label>("opengl_version");
|
||||||
opengl_version_text
|
opengl_version_text
|
||||||
.text("OpenGL: " + std::to_string(GLVersion.major) + "." +
|
.set_text("OpenGL: " + std::to_string(GLVersion.major) + "." +
|
||||||
std::to_string(GLVersion.minor))
|
std::to_string(GLVersion.minor))
|
||||||
.scale(0.7f)
|
.set_scale(0.7f)
|
||||||
.position(0.0f, 450.0f);
|
.set_position(0.0f, 450.0f);
|
||||||
biome_text.text("Biome: ").scale(0.8f).position(0.0f, 500.0f);
|
m_component.try_emplace(opengl_version_text.id(), &opengl_version_text);
|
||||||
speed_text.text("Speed: 0 m/s").scale(0.8f).position(0.0f, 550.0f);
|
|
||||||
m_texts.insert({version_text.uuid(), std::move(version_text)});
|
// biome
|
||||||
m_texts.insert({fps_text.uuid(), std::move(fps_text)});
|
auto& biome_text = m_widget.add_child<Label>("biome");
|
||||||
m_texts.insert({player_pos_text.uuid(), std::move(player_pos_text)});
|
biome_text.set_text("Biome: ").set_scale(0.8f).set_position(0.0f, 500.0f);
|
||||||
m_texts.insert(
|
m_component.try_emplace(biome_text.id(), &biome_text);
|
||||||
{rendered_chunk_text.uuid(), std::move(rendered_chunk_text)});
|
|
||||||
m_texts.insert({os_text.uuid(), std::move(os_text)});
|
// speed
|
||||||
m_texts.insert({rss_text.uuid(), std::move(rss_text)});
|
auto& speed_text = m_widget.add_child<Label>("speed");
|
||||||
m_texts.insert({cpu_text.uuid(), std::move(cpu_text)});
|
speed_text.set_text("Speed: 0 m/s")
|
||||||
m_texts.insert({gpu_text.uuid(), std::move(gpu_text)});
|
.set_scale(0.8f)
|
||||||
m_texts.insert(
|
.set_position(0.0f, 550.0f);
|
||||||
{opengl_version_text.uuid(), std::move(opengl_version_text)});
|
m_component.try_emplace(speed_text.id(), &speed_text);
|
||||||
m_texts.insert({biome_text.uuid(), std::move(biome_text)});
|
|
||||||
m_texts.insert({speed_text.uuid(), std::move(speed_text)});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<std::size_t, Text>& DebugCollector::all_texts() {
|
Widget& DebugCollector::get_widget() { return m_widget; }
|
||||||
return m_texts;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text& DebugCollector::text(std::string_view name) {
|
void DebugCollector::report(const std::string& name, std::string_view content) {
|
||||||
std::size_t id = HASH::str(name);
|
auto t = m_component.find(name);
|
||||||
auto it = m_texts.find(id);
|
if (t == m_component.end()) {
|
||||||
ASSERT_MSG(it != m_texts.end(), "Can't Find Text");
|
return;
|
||||||
return it->second;
|
|
||||||
}
|
}
|
||||||
|
if (!t->second) {
|
||||||
void DebugCollector::report(std::string_view name, std::string_view content) {
|
return;
|
||||||
auto& t = text(name);
|
}
|
||||||
t.text(content);
|
t->second->set_text(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
@@ -152,12 +152,10 @@ void Renderer::render() {
|
|||||||
|
|
||||||
render_ui();
|
render_ui();
|
||||||
|
|
||||||
render_text();
|
|
||||||
|
|
||||||
render_dev_panel();
|
render_dev_panel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::render_text() {
|
void Renderer::render_lable(const Label& label) {
|
||||||
|
|
||||||
const auto& shader = get_shader("text");
|
const auto& shader = get_shader("text");
|
||||||
|
|
||||||
@@ -170,15 +168,33 @@ void Renderer::render_text() {
|
|||||||
|
|
||||||
shader.set_loc("projection", m_ui_proj_matrix);
|
shader.set_loc("projection", m_ui_proj_matrix);
|
||||||
|
|
||||||
auto& texts = DebugCollector::get().all_texts();
|
Font::text_texture()->bind(0);
|
||||||
for (auto& t : texts) {
|
auto& data = label.data();
|
||||||
t.second.render(shader);
|
auto& pos = label.pos();
|
||||||
}
|
auto& text_style = label.text_style();
|
||||||
|
auto color = color_value(text_style.color);
|
||||||
|
data.m_vao->bind();
|
||||||
|
glm::mat4 model_matrix =
|
||||||
|
glm::translate(glm::mat4(1.0f), glm::vec3(pos.x, pos.y, 0.0f)) *
|
||||||
|
glm::scale(glm::mat4(1.0f),
|
||||||
|
glm::vec3(label.scale(), label.scale(), 1.0f));
|
||||||
|
|
||||||
|
shader.set_loc("textColor", glm::vec3(color.x, color.y, color.z));
|
||||||
|
shader.set_loc("mv_matrix", model_matrix);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, data.m_sum);
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::render_ui() {
|
void Renderer::render_ui() {
|
||||||
|
|
||||||
|
auto& widget = DebugCollector::get().get_widget();
|
||||||
|
widget.render(*this);
|
||||||
|
render_crosshair();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::render_crosshair() {
|
||||||
const auto& shader = get_shader("ui");
|
const auto& shader = get_shader("ui");
|
||||||
shader.use();
|
shader.use();
|
||||||
|
|
||||||
|
|||||||
@@ -62,24 +62,28 @@ 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, float x, float y,
|
std::vector<Vertex2D> Font::vertices(const std::string& text) {
|
||||||
float scale) {
|
|
||||||
static Font font;
|
static Font font;
|
||||||
|
|
||||||
std::vector<Vertex2D> vertices;
|
std::vector<Vertex2D> vertices;
|
||||||
|
|
||||||
|
float pen_x = 0.0f;
|
||||||
|
float pen_y = 0.0f;
|
||||||
|
|
||||||
for (char8_t c : text) {
|
for (char8_t c : text) {
|
||||||
auto it = font.m_characters.find(c);
|
auto it = font.m_characters.find(c);
|
||||||
if (it == font.m_characters.end()) {
|
if (it == font.m_characters.end()) {
|
||||||
Logger::error("Can't find character {}", static_cast<char>(c));
|
Logger::error("Can't find character {}", static_cast<char>(c));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Character& ch = it->second;
|
|
||||||
float xpos = x + ch.bearing.x * scale;
|
|
||||||
float ypos = y - ch.bearing.y * scale;
|
|
||||||
|
|
||||||
float w = ch.size.x * scale;
|
Character& ch = it->second;
|
||||||
float h = ch.size.y * scale;
|
|
||||||
|
float xpos = pen_x + ch.bearing.x;
|
||||||
|
float ypos = pen_y - ch.bearing.y;
|
||||||
|
|
||||||
|
float w = ch.size.x;
|
||||||
|
float h = ch.size.y;
|
||||||
|
|
||||||
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));
|
||||||
@@ -87,6 +91,7 @@ std::vector<Vertex2D> Font::vertices(const std::string& text, float x, float y,
|
|||||||
static_cast<float>(c));
|
static_cast<float>(c));
|
||||||
vertices.emplace_back(xpos + w, ypos, ch.uv_max.x, ch.uv_min.y,
|
vertices.emplace_back(xpos + w, ypos, ch.uv_max.x, ch.uv_min.y,
|
||||||
static_cast<float>(c));
|
static_cast<float>(c));
|
||||||
|
|
||||||
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 + w, ypos, ch.uv_max.x, ch.uv_min.y,
|
vertices.emplace_back(xpos + w, ypos, ch.uv_max.x, ch.uv_min.y,
|
||||||
@@ -94,7 +99,7 @@ std::vector<Vertex2D> Font::vertices(const std::string& text, float x, float y,
|
|||||||
vertices.emplace_back(xpos + w, ypos + h, ch.uv_max.x, ch.uv_max.y,
|
vertices.emplace_back(xpos + w, ypos + h, ch.uv_max.x, ch.uv_max.y,
|
||||||
static_cast<float>(c));
|
static_cast<float>(c));
|
||||||
|
|
||||||
x += (ch.advance >> 6) * scale;
|
pen_x += (ch.advance >> 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
return vertices;
|
return vertices;
|
||||||
|
|||||||
58
src/ui/label.cpp
Normal file
58
src/ui/label.cpp
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#include "Cubed/ui/label.hpp"
|
||||||
|
|
||||||
|
#include "Cubed/render/renderer.hpp"
|
||||||
|
#include "Cubed/tools/font.hpp"
|
||||||
|
namespace Cubed {
|
||||||
|
Label::Label(const std::string& id) : Widget(id) {}
|
||||||
|
|
||||||
|
Label& Label::set_text(std::string_view text) {
|
||||||
|
m_text.text = text;
|
||||||
|
m_dirty = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label& Label::set_position(const glm::vec2& pos) {
|
||||||
|
return set_position(pos.x, pos.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Label& Label::set_position(float x, float y) {
|
||||||
|
m_pos.x = x;
|
||||||
|
m_pos.y = y;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label& Label::set_scale(float scale) {
|
||||||
|
m_scale = scale;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label& Label::set_color(Color color) {
|
||||||
|
m_text.color = color;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::update(float dt) { on_update(dt); }
|
||||||
|
|
||||||
|
void Label::on_update(float dt) {
|
||||||
|
(void)dt;
|
||||||
|
if (m_dirty) {
|
||||||
|
update_vertices();
|
||||||
|
m_dirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::render(Renderer& renderer) { on_render(renderer); }
|
||||||
|
|
||||||
|
void Label::on_render(Renderer& renderer) { renderer.render_lable(*this); }
|
||||||
|
|
||||||
|
void Label::update_vertices() {
|
||||||
|
m_data.m_vertices = Font::vertices(m_text.text);
|
||||||
|
m_data.update_sum();
|
||||||
|
m_data.upload();
|
||||||
|
}
|
||||||
|
|
||||||
|
const UIVertexData& Label::data() const { return m_data; }
|
||||||
|
const glm::vec2& Label::pos() const { return m_pos; }
|
||||||
|
const TextStyle& Label::text_style() const { return m_text; }
|
||||||
|
float Label::scale() const { return m_scale; }
|
||||||
|
} // namespace Cubed
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
#include "Cubed/ui/text.hpp"
|
|
||||||
|
|
||||||
#include "Cubed/shader.hpp"
|
|
||||||
#include "Cubed/tools/cubed_hash.hpp"
|
|
||||||
#include "Cubed/tools/font.hpp"
|
|
||||||
|
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
|
||||||
|
|
||||||
namespace Cubed {
|
|
||||||
|
|
||||||
Text::Text(std::string_view name)
|
|
||||||
: NAME(name), UUID(HASH::str(name)),
|
|
||||||
m_vbo(std::make_unique<VertexBuffer>()),
|
|
||||||
m_vao(std::make_unique<VertexArray>()) {}
|
|
||||||
|
|
||||||
Text::Text(std::string_view name, std::string_view str, glm::vec2 pos,
|
|
||||||
Color color)
|
|
||||||
: NAME(name), UUID(HASH::str(name)),
|
|
||||||
m_vbo(std::make_unique<VertexBuffer>()),
|
|
||||||
m_vao(std::make_unique<VertexArray>()) {
|
|
||||||
m_text.assign(str);
|
|
||||||
m_pos = pos;
|
|
||||||
m_color = color_value(color);
|
|
||||||
update_vertices();
|
|
||||||
}
|
|
||||||
|
|
||||||
Text::~Text() { m_vbo.reset(); }
|
|
||||||
|
|
||||||
Text::Text(Text&& other) noexcept
|
|
||||||
: m_scale(other.m_scale), m_pos(other.m_pos), NAME(other.NAME),
|
|
||||||
UUID(other.UUID), m_text(std::move(other.m_text)), m_color(other.m_color),
|
|
||||||
m_model_matrix(other.m_model_matrix),
|
|
||||||
m_vertices(std::move(other.m_vertices)), m_vbo(std::move(other.m_vbo)),
|
|
||||||
m_vao(std::move(other.m_vao)) {}
|
|
||||||
|
|
||||||
Text& Text::color(Color color) {
|
|
||||||
m_color = color_value(color);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text& Text::position(float x, float y) {
|
|
||||||
m_pos = glm::vec2{x, y};
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Text& Text::scale(float s) {
|
|
||||||
m_scale = s;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t Text::uuid() const { return UUID; }
|
|
||||||
|
|
||||||
Text& Text::text(std::string_view str) {
|
|
||||||
m_text.assign(str);
|
|
||||||
update_vertices();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Text::render(const Shader& shader) {
|
|
||||||
ASSERT_MSG(m_vbo != 0, "VBO not initialized!");
|
|
||||||
ASSERT_MSG(!m_vertices.empty(), "Text String Not Set");
|
|
||||||
Font::text_texture()->bind(0);
|
|
||||||
m_vao->bind();
|
|
||||||
m_model_matrix =
|
|
||||||
glm::translate(glm::mat4(1.0f), glm::vec3(m_pos.x, m_pos.y, 0.0f)) *
|
|
||||||
glm::scale(glm::mat4(1.0f), glm::vec3(m_scale, m_scale, 1.0f));
|
|
||||||
|
|
||||||
shader.set_loc("textColor", glm::vec3(m_color.x, m_color.y, m_color.z));
|
|
||||||
shader.set_loc("mv_matrix", m_model_matrix);
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, m_vertices.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Text::update_vertices() {
|
|
||||||
m_vertices = Font::vertices(m_text);
|
|
||||||
upload_to_gpu();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Text::upload_to_gpu() {
|
|
||||||
ASSERT_MSG(m_vbo, "Vbo Is Not Gen");
|
|
||||||
m_vao->bind();
|
|
||||||
m_vbo->buffer_data(m_vertices.data(), m_vertices.size() * sizeof(Vertex2D),
|
|
||||||
BufferUsage::DYNAMIC_DRAW);
|
|
||||||
m_vao->attribute(0, 2, GL_FLOAT, sizeof(Vertex2D), (void*)0);
|
|
||||||
m_vao->attribute(1, 2, GL_FLOAT, sizeof(Vertex2D),
|
|
||||||
(void*)offsetof(Vertex2D, s));
|
|
||||||
m_vao->attribute(2, 1, GL_FLOAT, sizeof(Vertex2D),
|
|
||||||
(void*)offsetof(Vertex2D, layer));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Text::operator==(const Text& other) const { return UUID == other.uuid(); }
|
|
||||||
|
|
||||||
} // namespace Cubed
|
|
||||||
46
src/ui/ui_vertex_data.cpp
Normal file
46
src/ui/ui_vertex_data.cpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
#include "Cubed/ui/ui_vertex_data.hpp"
|
||||||
|
|
||||||
|
#include "Cubed/tools/cubed_assert.hpp"
|
||||||
|
#include "Cubed/tools/log.hpp"
|
||||||
|
namespace Cubed {
|
||||||
|
UIVertexData::UIVertexData() {}
|
||||||
|
UIVertexData::~UIVertexData() {
|
||||||
|
m_vao.reset();
|
||||||
|
m_vbo.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UIVertexData::upload() {
|
||||||
|
if (m_sum == 0) {
|
||||||
|
Logger::error("You need update_sum first");
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
|
if (m_vertices.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!m_vao) {
|
||||||
|
m_vao = std::make_unique<VertexArray>();
|
||||||
|
}
|
||||||
|
if (!m_vbo) {
|
||||||
|
m_vbo = std::make_unique<VertexBuffer>();
|
||||||
|
}
|
||||||
|
m_vao->bind();
|
||||||
|
m_vbo->buffer_data(m_vertices.data(), m_vertices.size() * sizeof(Vertex2D),
|
||||||
|
BufferUsage::DYNAMIC_DRAW);
|
||||||
|
|
||||||
|
m_vao->attribute(0, 3, GL_FLOAT, sizeof(Vertex2D), (void*)0);
|
||||||
|
m_vao->attribute(1, 2, GL_FLOAT, sizeof(Vertex2D),
|
||||||
|
(void*)offsetof(Vertex2D, s));
|
||||||
|
m_vao->attribute(2, 1, GL_FLOAT, sizeof(Vertex2D),
|
||||||
|
(void*)offsetof(Vertex2D, layer));
|
||||||
|
|
||||||
|
VertexArray::unbind();
|
||||||
|
VertexBuffer::unbind();
|
||||||
|
|
||||||
|
// Release memory
|
||||||
|
m_vertices.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UIVertexData::update_sum() { m_sum = m_vertices.size(); }
|
||||||
|
|
||||||
|
} // namespace Cubed
|
||||||
26
src/ui/widget.cpp
Normal file
26
src/ui/widget.cpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#include "Cubed/ui/widget.hpp"
|
||||||
|
|
||||||
|
namespace Cubed {
|
||||||
|
Widget::Widget(const std::string& id) : m_id(id) {}
|
||||||
|
void Widget::update(float dt) {
|
||||||
|
on_update(dt);
|
||||||
|
|
||||||
|
for (auto& child : m_children) {
|
||||||
|
child->update(dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::render(Renderer& renderer) {
|
||||||
|
on_render(renderer);
|
||||||
|
|
||||||
|
for (auto& child : m_children) {
|
||||||
|
child->render(renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::on_update(float dt) {}
|
||||||
|
void Widget::on_render(Renderer& renderer) {}
|
||||||
|
|
||||||
|
const std::string& Widget::id() const { return m_id; }
|
||||||
|
|
||||||
|
} // namespace Cubed
|
||||||
Reference in New Issue
Block a user