mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
Compare commits
5 Commits
e8157ab549
...
80ba6dad89
| Author | SHA1 | Date | |
|---|---|---|---|
| 80ba6dad89 | |||
| acb0b94d7b | |||
| e7082bdbe0 | |||
| f5e53fd13d | |||
| 0cbb353a2a |
9
assets/shaders/rect_f_shader.glsl
Normal file
9
assets/shaders/rect_f_shader.glsl
Normal file
@@ -0,0 +1,9 @@
|
||||
#version 460
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform vec4 inColor;
|
||||
|
||||
void main(void) {
|
||||
color = inColor;
|
||||
}
|
||||
11
assets/shaders/rect_v_shader.glsl
Normal file
11
assets/shaders/rect_v_shader.glsl
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec2 pos;
|
||||
|
||||
|
||||
uniform mat4 model_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = proj_matrix * model_matrix * vec4(pos, 0.0, 1.0);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/ui/column_layout.hpp"
|
||||
#include "Cubed/ui/label.hpp"
|
||||
#include "Cubed/ui/widget.hpp"
|
||||
|
||||
@@ -13,11 +14,12 @@ public:
|
||||
DebugCollector();
|
||||
|
||||
void report(const std::string& name, std::string_view content);
|
||||
void init_text();
|
||||
void init(int width, int height);
|
||||
Widget& get_widget();
|
||||
bool handle_event(const Event& e);
|
||||
|
||||
private:
|
||||
Widget m_widget;
|
||||
ColumnLayout m_widget;
|
||||
std::unordered_map<std::string, Label*> m_component;
|
||||
};
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "Cubed/shader.hpp"
|
||||
#include "Cubed/ui/image.hpp"
|
||||
#include "Cubed/ui/label.hpp"
|
||||
#include "Cubed/ui/rect.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
@@ -33,7 +34,7 @@ public:
|
||||
void render_world(ClientWorld& world);
|
||||
void render_lable(const Label& label);
|
||||
void render_image(const Image& image);
|
||||
|
||||
void render_rect(const Rect& rect);
|
||||
void begin_render_ui();
|
||||
void end_render_ui();
|
||||
|
||||
|
||||
@@ -40,6 +40,9 @@ public:
|
||||
} else if constexpr (is_same_v<dT, glm::mat4>) {
|
||||
glUniformMatrix4fv(loc(location), 1, GL_FALSE,
|
||||
glm::value_ptr(value));
|
||||
|
||||
} else if constexpr (is_same_v<dT, glm::vec4>) {
|
||||
glUniform4fv(loc(location), 1, glm::value_ptr(value));
|
||||
} else {
|
||||
static_assert(always_false<dT>::value, "Unknown Type");
|
||||
}
|
||||
|
||||
15
include/Cubed/ui/anchor.hpp
Normal file
15
include/Cubed/ui/anchor.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
enum class Anchor {
|
||||
TOP_LEFT,
|
||||
TOP_CENTER,
|
||||
TOP_RIGHT,
|
||||
|
||||
CENTER_LEFT,
|
||||
CENTER,
|
||||
CENTER_RIGHT,
|
||||
|
||||
BOTTOM_LEFT,
|
||||
BOTTOM_CENTER,
|
||||
BOTTOM_RIGHT,
|
||||
};
|
||||
@@ -9,7 +9,7 @@
|
||||
namespace Cubed {
|
||||
class Button : public Widget {
|
||||
public:
|
||||
Button();
|
||||
Button(Widget* parent);
|
||||
|
||||
Button(const Button&) = delete;
|
||||
Button(Button&&) = delete;
|
||||
@@ -21,10 +21,11 @@ public:
|
||||
|
||||
bool handle_mouse_move_event(const MouseMoveEvent& e) override;
|
||||
bool handle_mouse_button_event(const MouseButtonEvent& e) override;
|
||||
|
||||
Widget& set_position(const glm::vec2& pos) override;
|
||||
Widget& set_position(float x, float y) override;
|
||||
void set_window_size(int width, int height) override;
|
||||
Button& set_scale(float scale);
|
||||
Widget& set_anchor(Anchor anchor) override;
|
||||
Widget& set_offset(glm::ivec2 offset) override;
|
||||
glm::vec2 pos() const override;
|
||||
float width() const override;
|
||||
float height() const override;
|
||||
float scale() const;
|
||||
@@ -34,16 +35,17 @@ public:
|
||||
}
|
||||
|
||||
template <typename T, typename... Args> T& set_background(Args&&... args) {
|
||||
auto w = std::make_unique<T>(std::forward<Args>(args)...);
|
||||
auto w = std::make_unique<T>(std::forward<Args>(args)..., m_parent);
|
||||
T& ref = *w;
|
||||
m_background = std::move(w);
|
||||
return ref;
|
||||
}
|
||||
|
||||
template <typename T, typename... Args> T& set_foreground(Args&&... args) {
|
||||
auto w = std::make_unique<T>(std::forward<Args>(args)...);
|
||||
auto w = std::make_unique<T>(std::forward<Args>(args)..., this);
|
||||
T& ref = *w;
|
||||
m_foreground = std::move(w);
|
||||
m_foreground->set_anchor(Anchor::CENTER);
|
||||
return ref;
|
||||
}
|
||||
|
||||
@@ -52,7 +54,5 @@ private:
|
||||
std::unique_ptr<Image> m_background;
|
||||
std::unique_ptr<Label> m_foreground;
|
||||
bool m_hovered = false;
|
||||
glm::vec2 m_min_pos;
|
||||
glm::vec2 m_max_pos;
|
||||
};
|
||||
} // namespace Cubed
|
||||
27
include/Cubed/ui/column_layout.hpp
Normal file
27
include/Cubed/ui/column_layout.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include "Cubed/ui/widget.hpp"
|
||||
namespace Cubed {
|
||||
class ColumnLayout : public Widget {
|
||||
public:
|
||||
ColumnLayout(const ColumnLayout&) = delete;
|
||||
ColumnLayout(ColumnLayout&&) = delete;
|
||||
ColumnLayout& operator=(const ColumnLayout&) = delete;
|
||||
ColumnLayout& operator=(ColumnLayout&&) = delete;
|
||||
ColumnLayout(Widget* parent);
|
||||
~ColumnLayout();
|
||||
|
||||
void update(float dt) override;
|
||||
|
||||
float width() const override;
|
||||
float height() const override;
|
||||
|
||||
void set_spacing(int spacing);
|
||||
// No need for parent node pointer; do not modify children's anchors and
|
||||
// scale.
|
||||
|
||||
void layout();
|
||||
|
||||
private:
|
||||
int m_spacing = 0;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -8,7 +8,7 @@ namespace Cubed {
|
||||
class TextureManager;
|
||||
class Image : public Widget {
|
||||
public:
|
||||
Image();
|
||||
Image(Widget* parent);
|
||||
void update(float dt) override;
|
||||
void render(Renderer& renderer) override;
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ public:
|
||||
Label& operator=(const Label&) = delete;
|
||||
Label& operator=(Label&&) = delete;
|
||||
|
||||
Label(const std::string& id);
|
||||
Label();
|
||||
Label(const std::string& id, Widget* parent);
|
||||
Label(Widget* parent);
|
||||
virtual ~Label() = default;
|
||||
|
||||
Label& set_text(std::string_view text);
|
||||
|
||||
@@ -25,7 +25,8 @@ public:
|
||||
|
||||
private:
|
||||
MainMenuScene& m_scene;
|
||||
std::unordered_map<std::string, std::unique_ptr<Widget>> m_widgets;
|
||||
std::unique_ptr<Widget> m_root_widget;
|
||||
std::unordered_map<std::string, Widget*> m_widgets;
|
||||
bool handle_mouse_move_event(const MouseMoveEvent& e);
|
||||
bool handle_mouse_button_event(const MouseButtonEvent& e);
|
||||
bool handle_window_resize_event(const WindowResizeEvent& e);
|
||||
|
||||
41
include/Cubed/ui/rect.hpp
Normal file
41
include/Cubed/ui/rect.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/ui/color.hpp"
|
||||
#include "Cubed/ui/widget.hpp"
|
||||
namespace Cubed {
|
||||
class Rect : public Widget {
|
||||
public:
|
||||
Rect(const Rect&) = delete;
|
||||
Rect(Rect&&) = delete;
|
||||
Rect& operator=(const Rect&) = delete;
|
||||
Rect& operator=(Rect&&) = delete;
|
||||
Rect(Widget* parent);
|
||||
~Rect();
|
||||
|
||||
void update(float dt) override;
|
||||
void render(Renderer& renderer) override;
|
||||
|
||||
float width() const override;
|
||||
float height() const override;
|
||||
float alpha() const;
|
||||
|
||||
Rect& set_width(float width);
|
||||
Rect& set_height(float height);
|
||||
|
||||
Rect& set_fill(bool fill);
|
||||
|
||||
Rect& set_scale(float scale);
|
||||
Rect& set_color(Color color);
|
||||
Rect& set_alpha(float alpha);
|
||||
|
||||
Color color() const;
|
||||
|
||||
private:
|
||||
Color m_color = Color::WHITE;
|
||||
float m_width = 0.0f;
|
||||
float m_height = 0.0f;
|
||||
float m_scale = 1.0f;
|
||||
float m_alpha = 1.0f;
|
||||
bool m_fill = false;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
#include "Cubed/input/event.hpp"
|
||||
#include "glm/ext/vector_float2.hpp"
|
||||
#include "Cubed/ui/anchor.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
namespace Cubed {
|
||||
@@ -10,18 +11,19 @@ class Renderer;
|
||||
class Widget {
|
||||
|
||||
public:
|
||||
Widget(const std::string& id);
|
||||
Widget() = default;
|
||||
Widget(const std::string& id, Widget* parent);
|
||||
Widget(Widget* parent);
|
||||
virtual ~Widget() = default;
|
||||
virtual void update(float dt);
|
||||
virtual void render(Renderer& renderer);
|
||||
virtual const std::string& id() const;
|
||||
virtual Widget& set_position(const glm::vec2& pos);
|
||||
virtual Widget& set_position(float x, float y);
|
||||
virtual Widget& set_anchor(Anchor anchor);
|
||||
virtual Widget& set_offset(glm::ivec2 offset);
|
||||
virtual void set_window_size(int width, int height);
|
||||
// Returns the final display size
|
||||
virtual float width() const;
|
||||
virtual float height() const;
|
||||
virtual const glm::vec2& pos() const;
|
||||
virtual float width() const = 0;
|
||||
virtual float height() const = 0;
|
||||
virtual glm::vec2 pos() const;
|
||||
|
||||
virtual bool handle_key_event(const KeyEvent& e);
|
||||
virtual bool handle_mouse_button_event(const MouseButtonEvent& e);
|
||||
@@ -30,21 +32,30 @@ public:
|
||||
virtual bool handle_mouse_move_event(const MouseMoveEvent& e);
|
||||
|
||||
template <typename T, typename... Args> T& add_child(Args&&... args) {
|
||||
auto widget = std::make_unique<T>(std::forward<Args>(args)...);
|
||||
auto widget = std::make_unique<T>(std::forward<Args>(args)..., this);
|
||||
T& ref = *widget;
|
||||
m_children.emplace_back(std::move(widget));
|
||||
return ref;
|
||||
};
|
||||
|
||||
protected:
|
||||
Widget* m_parent = nullptr;
|
||||
std::string m_id;
|
||||
float m_window_height = 0;
|
||||
float m_window_width = 0;
|
||||
// Center is at the top-left corner, position is at the top-left corner
|
||||
Anchor m_anchor = Anchor::TOP_LEFT;
|
||||
glm::ivec2 m_offset{0, 0};
|
||||
|
||||
std::vector<std::unique_ptr<Widget>>& children();
|
||||
|
||||
const std::vector<std::unique_ptr<Widget>>& children() const;
|
||||
|
||||
virtual void on_update(float dt);
|
||||
virtual void on_render(Renderer& renderer);
|
||||
std::string m_id;
|
||||
// Center is at the top-left corner, position is at the top-left corner
|
||||
glm::vec2 m_pos{0.0f, 0.0f};
|
||||
virtual glm::vec2 compute_position() const;
|
||||
|
||||
private:
|
||||
Widget* m_parent = nullptr;
|
||||
std::vector<std::unique_ptr<Widget>> m_children;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -32,6 +32,8 @@ public:
|
||||
|
||||
void set_game_running(bool running);
|
||||
|
||||
void should_close_window();
|
||||
|
||||
private:
|
||||
bool m_mouse_enable = false;
|
||||
bool m_imgui_init = false;
|
||||
|
||||
@@ -67,4 +67,6 @@ target_sources(${PROJECT_NAME}
|
||||
ui/world_ui_manager.cpp
|
||||
ui/main_menu_ui_manager.cpp
|
||||
scene/main_menu_scene.cpp
|
||||
ui/column_layout.cpp
|
||||
ui/rect.cpp
|
||||
)
|
||||
@@ -5,56 +5,58 @@
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
DebugCollector::DebugCollector() {}
|
||||
DebugCollector::DebugCollector() : m_widget(nullptr) {}
|
||||
|
||||
DebugCollector& DebugCollector::get() {
|
||||
static DebugCollector instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void DebugCollector::init_text() {
|
||||
void DebugCollector::init(int width, int height) {
|
||||
constexpr float SCALE = 0.6f;
|
||||
|
||||
m_widget.set_window_size(width, height);
|
||||
m_widget.set_spacing(15);
|
||||
m_widget.set_anchor(Anchor::TOP_LEFT);
|
||||
m_widget.set_offset({0, 5});
|
||||
|
||||
// version_text
|
||||
auto& version_text = m_widget.add_child<Label>("version");
|
||||
std::string version{"Version: " CUBED_VERSION};
|
||||
|
||||
#ifdef DEBUG_MODE
|
||||
version.append("-debug");
|
||||
#else
|
||||
version.append("-release");
|
||||
#endif
|
||||
version_text.set_color(Color::WHITE)
|
||||
.set_text(version)
|
||||
.set_scale(0.8f)
|
||||
.set_position(0.0f, 100.0f);
|
||||
|
||||
version_text.set_color(Color::WHITE).set_text(version).set_scale(SCALE);
|
||||
m_component.try_emplace(version_text.id(), &version_text);
|
||||
|
||||
// fps
|
||||
auto& fps_text = m_widget.add_child<Label>("fps");
|
||||
fps_text.set_text("FPS: 0").set_position(0.0f, 50.0f);
|
||||
fps_text.set_text("FPS: 0").set_scale(SCALE);
|
||||
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_text("x: 0.00 y: 0.00 z: 0.00")
|
||||
.set_scale(0.8f)
|
||||
.set_position(0.0f, 150.0f);
|
||||
player_pos_text.set_text("x: 0.00 y: 0.00 z: 0.00").set_scale(SCALE);
|
||||
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);
|
||||
rendered_chunk_text.set_text("Rendered Chunk: 0").set_scale(SCALE);
|
||||
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);
|
||||
rss_text.set_text("RSS: 0mb").set_scale(SCALE);
|
||||
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);
|
||||
os_text.set_scale(SCALE);
|
||||
if (Tools::get_os_version(os)) {
|
||||
os_text.set_text("OS: " + os);
|
||||
Logger::info("System: {}", os);
|
||||
@@ -65,9 +67,7 @@ void DebugCollector::init_text() {
|
||||
|
||||
// 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);
|
||||
cpu_text.set_text("CPU: " + Tools::get_cpu_info()).set_scale(SCALE);
|
||||
m_component.try_emplace(cpu_text.id(), &cpu_text);
|
||||
|
||||
// gpu
|
||||
@@ -75,8 +75,7 @@ void DebugCollector::init_text() {
|
||||
gpu_text
|
||||
.set_text(std::string{"GPU: "} +
|
||||
reinterpret_cast<const char*>(glGetString(GL_RENDERER)))
|
||||
.set_scale(0.7f)
|
||||
.set_position(0.0f, 400.0f);
|
||||
.set_scale(SCALE);
|
||||
m_component.try_emplace(gpu_text.id(), &gpu_text);
|
||||
|
||||
// opengl_version
|
||||
@@ -84,25 +83,59 @@ void DebugCollector::init_text() {
|
||||
opengl_version_text
|
||||
.set_text("OpenGL: " + std::to_string(GLVersion.major) + "." +
|
||||
std::to_string(GLVersion.minor))
|
||||
.set_scale(0.7f)
|
||||
.set_position(0.0f, 450.0f);
|
||||
.set_scale(SCALE);
|
||||
m_component.try_emplace(opengl_version_text.id(), &opengl_version_text);
|
||||
|
||||
// biome
|
||||
auto& biome_text = m_widget.add_child<Label>("biome");
|
||||
biome_text.set_text("Biome: ").set_scale(0.8f).set_position(0.0f, 500.0f);
|
||||
biome_text.set_text("Biome: ").set_scale(SCALE);
|
||||
m_component.try_emplace(biome_text.id(), &biome_text);
|
||||
|
||||
// speed
|
||||
auto& speed_text = m_widget.add_child<Label>("speed");
|
||||
speed_text.set_text("Speed: 0 m/s")
|
||||
.set_scale(0.8f)
|
||||
.set_position(0.0f, 550.0f);
|
||||
speed_text.set_text("Speed: 0 m/s").set_scale(SCALE);
|
||||
m_component.try_emplace(speed_text.id(), &speed_text);
|
||||
}
|
||||
|
||||
Widget& DebugCollector::get_widget() { return m_widget; }
|
||||
|
||||
bool DebugCollector::handle_event(const Event& e) {
|
||||
return std::visit(
|
||||
Overloaded{[this](const MouseMoveEvent& e) {
|
||||
if (m_widget.handle_mouse_move_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[this](const MouseButtonEvent& e) {
|
||||
if (m_widget.handle_mouse_button_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[this](const MouseWheelEvent& e) {
|
||||
if (m_widget.handle_mouse_wheel_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[this](const KeyEvent& e) {
|
||||
if (m_widget.handle_key_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[](const TextInputEvent&) { return false; },
|
||||
[this](const WindowResizeEvent& e) {
|
||||
m_widget.handle_window_resize_event(e);
|
||||
return false;
|
||||
},
|
||||
[](const FrameBufferResizeEvent&) { return false; }
|
||||
|
||||
},
|
||||
e);
|
||||
}
|
||||
|
||||
void DebugCollector::report(const std::string& name, std::string_view content) {
|
||||
auto t = m_component.find(name);
|
||||
if (t == m_component.end()) {
|
||||
|
||||
@@ -135,7 +135,7 @@ void Renderer::init_quad() {
|
||||
void Renderer::init_text() {
|
||||
m_vao[4].bind();
|
||||
|
||||
DebugCollector::get().init_text();
|
||||
DebugCollector::get().init(m_window_width, m_window_height);
|
||||
}
|
||||
void Renderer::begin_frame() {
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
@@ -157,6 +157,26 @@ void Renderer::render_world(ClientWorld& world) {
|
||||
m_world_renderer.render(world);
|
||||
}
|
||||
|
||||
void Renderer::render_rect(const Rect& rect) {
|
||||
|
||||
auto& shader = get_shader("rect");
|
||||
shader.use();
|
||||
shader.set_loc("proj_matrix", m_ui_proj_matrix);
|
||||
auto pos = rect.pos();
|
||||
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(rect.width(), rect.height(), 1.0f));
|
||||
shader.set_loc("model_matrix", model_matrix);
|
||||
|
||||
auto color = color_value(rect.color());
|
||||
shader.set_loc("inColor",
|
||||
glm::vec4(color.x, color.y, color.z, rect.alpha()));
|
||||
|
||||
m_vao[3].bind();
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
}
|
||||
|
||||
void Renderer::render_lable(const Label& label) {
|
||||
|
||||
const auto& shader = get_shader("text");
|
||||
@@ -167,7 +187,7 @@ void Renderer::render_lable(const Label& label) {
|
||||
|
||||
Font::text_texture()->bind(0);
|
||||
auto& data = label.data();
|
||||
auto& pos = label.pos();
|
||||
auto pos = label.pos();
|
||||
auto& text_style = label.text_style();
|
||||
auto color = color_value(text_style.color);
|
||||
data.m_vao->bind();
|
||||
@@ -189,12 +209,11 @@ void Renderer::render_image(const Image& image) {
|
||||
}
|
||||
const auto& shader = get_shader("image");
|
||||
shader.use();
|
||||
auto& pos = image.pos();
|
||||
auto pos = image.pos();
|
||||
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(image.width() * image.scale(),
|
||||
image.height() * image.scale(), 1.0f));
|
||||
glm::vec3(image.width(), image.height(), 1.0f));
|
||||
shader.set_loc("model_matrix", model_matrix);
|
||||
shader.set_loc("proj_matrix", m_ui_proj_matrix);
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@ void ShaderManager::init() {
|
||||
"shaders/player_f_shader.glsl");
|
||||
register_shader("player_depth", "shaders/depth_player_shader.glsl",
|
||||
"shaders/depth_player_fragment_shader.glsl");
|
||||
register_shader("rect", "shaders/rect_v_shader.glsl",
|
||||
"shaders/rect_f_shader.glsl");
|
||||
}
|
||||
|
||||
void ShaderManager::register_shader(const std::string& name,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "Cubed/ui/button.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
Button::Button() {}
|
||||
Button::Button(Widget* parent) : Widget(parent) {}
|
||||
|
||||
void Button::update(float dt) {
|
||||
if (m_background) {
|
||||
@@ -22,13 +22,13 @@ void Button::render(Renderer& renderer) {
|
||||
}
|
||||
|
||||
bool Button::handle_mouse_move_event(const MouseMoveEvent& e) {
|
||||
auto pos = m_background->pos();
|
||||
|
||||
if (e.xpos >= m_min_pos.x && e.xpos <= m_max_pos.x) {
|
||||
if (e.ypos >= m_min_pos.y && e.ypos <= m_max_pos.y) {
|
||||
m_hovered = true;
|
||||
if (e.xpos >= pos.x && e.xpos <= pos.x + width() && e.ypos >= pos.y &&
|
||||
e.ypos <= pos.y + height()) {
|
||||
m_hovered = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
m_hovered = false;
|
||||
|
||||
@@ -45,26 +45,24 @@ bool Button::handle_mouse_button_event(const MouseButtonEvent& e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Widget& Button::set_position(const glm::vec2& pos) {
|
||||
m_pos = pos;
|
||||
m_background->set_position(pos);
|
||||
m_foreground->set_position(pos.x, pos.y + m_foreground->height() / 2.0f);
|
||||
m_min_pos = pos;
|
||||
|
||||
m_max_pos.x = m_min_pos.x + width();
|
||||
m_max_pos.y = m_min_pos.y + height();
|
||||
|
||||
return *this;
|
||||
}
|
||||
Widget& Button::set_position(float x, float y) {
|
||||
return set_position(glm::vec2{x, y});
|
||||
}
|
||||
Button& Button::set_scale(float scale) {
|
||||
m_background->set_scale(scale);
|
||||
m_max_pos.x = m_min_pos.x + width();
|
||||
m_max_pos.y = m_min_pos.y + height();
|
||||
return *this;
|
||||
}
|
||||
void Button::set_window_size(int width, int height) {
|
||||
m_background->set_window_size(width, height);
|
||||
}
|
||||
Widget& Button::set_anchor(Anchor anchor) {
|
||||
m_background->set_anchor(anchor);
|
||||
|
||||
return *this;
|
||||
}
|
||||
Widget& Button::set_offset(glm::ivec2 offset) {
|
||||
m_background->set_offset(offset);
|
||||
|
||||
return *this;
|
||||
}
|
||||
glm::vec2 Button::pos() const { return m_background->pos(); }
|
||||
|
||||
float Button::scale() const { return m_background->scale(); }
|
||||
|
||||
|
||||
37
src/ui/column_layout.cpp
Normal file
37
src/ui/column_layout.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "Cubed/ui/column_layout.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
ColumnLayout::ColumnLayout(Widget* parent) : Widget(parent) {}
|
||||
ColumnLayout::~ColumnLayout() {}
|
||||
|
||||
void ColumnLayout::update(float dt) {
|
||||
Widget::update(dt);
|
||||
layout();
|
||||
}
|
||||
|
||||
float ColumnLayout::width() const {
|
||||
if (m_parent) {
|
||||
return m_parent->width();
|
||||
}
|
||||
return m_window_width;
|
||||
}
|
||||
float ColumnLayout::height() const {
|
||||
if (m_parent) {
|
||||
return m_parent->height();
|
||||
}
|
||||
return m_window_height;
|
||||
}
|
||||
|
||||
void ColumnLayout::set_spacing(int spacing) { m_spacing = spacing; }
|
||||
|
||||
void ColumnLayout::layout() {
|
||||
auto& children = Widget::children();
|
||||
int y = 0;
|
||||
for (auto& child : children) {
|
||||
child->set_offset({0, y});
|
||||
child->set_anchor(m_anchor);
|
||||
y += child->height() + m_spacing;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -4,8 +4,8 @@
|
||||
#include "Cubed/texture_manager.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
Image::Image() {}
|
||||
void Image::update(float dt) { (void)dt; }
|
||||
Image::Image(Widget* parent) : Widget(parent) {}
|
||||
void Image::update(float) {}
|
||||
void Image::render(Renderer& renderer) { renderer.render_image(*this); }
|
||||
|
||||
Image& Image::set_image(const std::string& path,
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/tools/font.hpp"
|
||||
namespace Cubed {
|
||||
Label::Label(const std::string& id) : Widget(id) {}
|
||||
Label::Label() {}
|
||||
Label::Label(const std::string& id, Widget* parent) : Widget(id, parent) {}
|
||||
Label::Label(Widget* parent) : Widget(parent) {}
|
||||
Label& Label::set_text(std::string_view text) {
|
||||
m_text.text = text;
|
||||
update_vertices();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Cubed/scene/main_menu_scene.hpp"
|
||||
#include "Cubed/scene/scene_manager.hpp"
|
||||
#include "Cubed/ui/button.hpp"
|
||||
#include "Cubed/ui/column_layout.hpp"
|
||||
namespace Cubed {
|
||||
|
||||
MainMenuUIManager::MainMenuUIManager(MainMenuScene& scene) : m_scene(scene) {}
|
||||
@@ -12,38 +13,57 @@ MainMenuUIManager::~MainMenuUIManager() {}
|
||||
|
||||
void MainMenuUIManager::init() {
|
||||
|
||||
auto start_game_button = std::make_unique<Button>();
|
||||
auto& back = start_game_button->set_background<Image>();
|
||||
back.set_image("texture/ui/button001.png",
|
||||
m_scene.scene_manager().app().texture_manager());
|
||||
auto& fore = start_game_button->set_foreground<Label>();
|
||||
fore.set_text("Start Game");
|
||||
fore.set_scale(0.6f);
|
||||
auto rect = std::make_unique<Rect>(nullptr);
|
||||
|
||||
start_game_button->set_clicked(
|
||||
[this]() { m_scene.scene_manager().request_push(SceneType::WORLD); });
|
||||
start_game_button->set_scale(3.0f);
|
||||
start_game_button->set_position(
|
||||
m_scene.scene_manager().app().renderer().window_width() / 2.0f -
|
||||
back.width() / 2.0f,
|
||||
m_scene.scene_manager().app().renderer().window_height() / 2.0f -
|
||||
back.height() / 2.0f);
|
||||
rect->set_fill(true);
|
||||
rect->set_anchor(Anchor::TOP_LEFT);
|
||||
rect->set_color(Color::WHITE);
|
||||
auto& renderer = m_scene.scene_manager().app().renderer();
|
||||
rect->set_window_size(renderer.window_width(), renderer.window_height());
|
||||
|
||||
m_widgets.try_emplace("start game", std::move(start_game_button));
|
||||
}
|
||||
auto& layout = rect->add_child<ColumnLayout>();
|
||||
layout.set_spacing(20);
|
||||
layout.set_anchor(Anchor::CENTER);
|
||||
layout.set_window_size(renderer.window_width(), renderer.window_height());
|
||||
{
|
||||
auto& start_game_button = layout.add_child<Button>();
|
||||
|
||||
void MainMenuUIManager::update(float dt) {
|
||||
for (auto& w : m_widgets) {
|
||||
w.second->update(dt);
|
||||
auto& back = start_game_button.set_background<Image>();
|
||||
back.set_image("texture/ui/button001.png",
|
||||
m_scene.scene_manager().app().texture_manager());
|
||||
auto& fore = start_game_button.set_foreground<Label>();
|
||||
fore.set_text("Start Game");
|
||||
fore.set_scale(0.6f);
|
||||
start_game_button.set_clicked([this]() {
|
||||
m_scene.scene_manager().request_push(SceneType::WORLD);
|
||||
});
|
||||
start_game_button.set_scale(4.0f);
|
||||
}
|
||||
|
||||
auto& exit_game = layout.add_child<Button>();
|
||||
|
||||
{
|
||||
auto& back = exit_game.set_background<Image>();
|
||||
back.set_image("texture/ui/button001.png",
|
||||
m_scene.scene_manager().app().texture_manager());
|
||||
auto& fore = exit_game.set_foreground<Label>();
|
||||
fore.set_scale(0.6f).set_text("Exit");
|
||||
exit_game.set_scale(4.0f);
|
||||
exit_game.set_clicked([this]() {
|
||||
m_scene.scene_manager().app().window().should_close_window();
|
||||
});
|
||||
}
|
||||
m_widgets.try_emplace("background", rect.get());
|
||||
m_widgets.try_emplace("main menu layout", &layout);
|
||||
m_root_widget = std::move(rect);
|
||||
}
|
||||
|
||||
void MainMenuUIManager::update(float dt) { m_root_widget->update(dt); }
|
||||
|
||||
void MainMenuUIManager::render(Renderer& renderer) {
|
||||
renderer.begin_render_ui();
|
||||
|
||||
for (auto& widget : m_widgets) {
|
||||
widget.second->render(renderer);
|
||||
}
|
||||
m_root_widget->render(renderer);
|
||||
|
||||
renderer.end_render_ui();
|
||||
}
|
||||
@@ -84,50 +104,39 @@ bool MainMenuUIManager::handle_event(const Event& e) {
|
||||
e);
|
||||
}
|
||||
bool MainMenuUIManager::handle_mouse_move_event(const MouseMoveEvent& e) {
|
||||
for (auto& w : m_widgets) {
|
||||
if (w.second->handle_mouse_move_event(e)) {
|
||||
return true;
|
||||
}
|
||||
if (m_root_widget->handle_mouse_move_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool MainMenuUIManager::handle_mouse_button_event(const MouseButtonEvent& e) {
|
||||
for (auto& w : m_widgets) {
|
||||
if (w.second->handle_mouse_button_event(e)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_root_widget->handle_mouse_button_event(e)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool MainMenuUIManager::handle_window_resize_event(const WindowResizeEvent& e) {
|
||||
auto it = m_widgets.find("start game");
|
||||
if (it != m_widgets.end()) {
|
||||
auto* start_game = dynamic_cast<Button*>(it->second.get());
|
||||
if (start_game) {
|
||||
start_game->set_position(e.width / 2 - start_game->width() / 2,
|
||||
e.height / 2 - start_game->height() / 2);
|
||||
}
|
||||
}
|
||||
for (auto& w : m_widgets) {
|
||||
if (w.second->handle_window_resize_event(e)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_root_widget->handle_window_resize_event(e)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool MainMenuUIManager::handle_mouse_wheel_event(const MouseWheelEvent& e) {
|
||||
for (auto& w : m_widgets) {
|
||||
if (w.second->handle_mouse_wheel_event(e)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_root_widget->handle_mouse_wheel_event(e)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool MainMenuUIManager::handle_key_event(const KeyEvent& e) {
|
||||
for (auto& w : m_widgets) {
|
||||
if (w.second->handle_key_event(e)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_root_widget->handle_key_event(e)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
58
src/ui/rect.cpp
Normal file
58
src/ui/rect.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "Cubed/ui/rect.hpp"
|
||||
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
namespace Cubed {
|
||||
Rect::Rect(Widget* parent)
|
||||
: Widget(parent) {
|
||||
|
||||
};
|
||||
|
||||
Rect::~Rect() {}
|
||||
void Rect::update(float dt) {
|
||||
if (m_fill) {
|
||||
if (!m_parent) {
|
||||
m_width = m_window_width;
|
||||
m_height = m_window_height;
|
||||
} else {
|
||||
m_width = m_parent->width();
|
||||
m_height = m_parent->height();
|
||||
}
|
||||
}
|
||||
Widget::update(dt);
|
||||
}
|
||||
void Rect::render(Renderer& renderer) {
|
||||
renderer.render_rect(*this);
|
||||
Widget::render(renderer);
|
||||
}
|
||||
|
||||
float Rect::width() const { return m_width * m_scale; }
|
||||
float Rect::height() const { return m_height * m_scale; }
|
||||
float Rect::alpha() const { return m_alpha; }
|
||||
Rect& Rect::set_width(float width) {
|
||||
m_width = width;
|
||||
return *this;
|
||||
}
|
||||
Rect& Rect::set_height(float height) {
|
||||
m_height = height;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Rect& Rect::set_fill(bool fill) {
|
||||
m_fill = fill;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Rect& Rect::set_scale(float scale) {
|
||||
m_scale = scale;
|
||||
return *this;
|
||||
}
|
||||
Rect& Rect::set_color(Color color) {
|
||||
m_color = color;
|
||||
return *this;
|
||||
}
|
||||
Rect& Rect::set_alpha(float alpha) {
|
||||
m_alpha = std::clamp(alpha, 0.0f, 1.0f);
|
||||
return *this;
|
||||
}
|
||||
Color Rect::color() const { return m_color; }
|
||||
} // namespace Cubed
|
||||
@@ -1,7 +1,11 @@
|
||||
#include "Cubed/ui/widget.hpp"
|
||||
|
||||
#include "Cubed/tools/log.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
Widget::Widget(const std::string& id) : m_id(id) {}
|
||||
Widget::Widget(const std::string& id, Widget* parent)
|
||||
: m_parent(parent), m_id(id) {}
|
||||
Widget::Widget(Widget* parent) : m_parent(parent) {}
|
||||
void Widget::update(float dt) {
|
||||
on_update(dt);
|
||||
|
||||
@@ -21,20 +25,98 @@ void Widget::render(Renderer& renderer) {
|
||||
void Widget::on_update(float) {}
|
||||
void Widget::on_render(Renderer&) {}
|
||||
|
||||
Widget& Widget::set_position(const glm::vec2& pos) {
|
||||
return set_position(pos.x, pos.y);
|
||||
std::vector<std::unique_ptr<Widget>>& Widget::children() { return m_children; }
|
||||
|
||||
const std::vector<std::unique_ptr<Widget>>& Widget::children() const {
|
||||
return m_children;
|
||||
}
|
||||
|
||||
Widget& Widget::set_position(float x, float y) {
|
||||
m_pos.x = x;
|
||||
m_pos.y = y;
|
||||
glm::vec2 Widget::compute_position() const {
|
||||
glm::vec2 pos{0, 0};
|
||||
float parent_w;
|
||||
float parent_h;
|
||||
if (!m_parent) {
|
||||
if (m_window_height == 0 || m_window_width == 0) {
|
||||
Logger::error("Window Size is 0 !");
|
||||
}
|
||||
parent_h = m_window_height;
|
||||
parent_w = m_window_width;
|
||||
} else {
|
||||
parent_h = m_parent->height();
|
||||
parent_w = m_parent->width();
|
||||
}
|
||||
const float W = width();
|
||||
const float H = height();
|
||||
switch (m_anchor) {
|
||||
case Anchor::TOP_LEFT:
|
||||
pos = {0, 0};
|
||||
break;
|
||||
|
||||
case Anchor::TOP_CENTER:
|
||||
pos = {(parent_w - W) / 2, 0};
|
||||
break;
|
||||
|
||||
case Anchor::TOP_RIGHT:
|
||||
pos = {parent_w - W, 0};
|
||||
break;
|
||||
|
||||
case Anchor::CENTER_LEFT:
|
||||
pos = {0, (parent_h - H) / 2};
|
||||
break;
|
||||
|
||||
case Anchor::CENTER:
|
||||
pos = {(parent_w - W) / 2, (parent_h - H) / 2};
|
||||
break;
|
||||
|
||||
case Anchor::CENTER_RIGHT:
|
||||
pos = {parent_w - W, (parent_h - H) / 2};
|
||||
break;
|
||||
|
||||
case Anchor::BOTTOM_LEFT:
|
||||
pos = {0, parent_h - H};
|
||||
break;
|
||||
|
||||
case Anchor::BOTTOM_CENTER:
|
||||
pos = {(parent_w - W) / 2, parent_h - H};
|
||||
break;
|
||||
|
||||
case Anchor::BOTTOM_RIGHT:
|
||||
pos = {parent_w - W, parent_h - H};
|
||||
break;
|
||||
}
|
||||
if (m_parent) {
|
||||
pos += m_parent->pos();
|
||||
}
|
||||
pos += m_offset;
|
||||
return pos;
|
||||
}
|
||||
|
||||
Widget& Widget::set_anchor(Anchor anchor) {
|
||||
m_anchor = anchor;
|
||||
return *this;
|
||||
}
|
||||
Widget& Widget::set_offset(glm::ivec2 offset) {
|
||||
m_offset = offset;
|
||||
return *this;
|
||||
}
|
||||
void Widget::set_window_size(int width, int height) {
|
||||
m_window_height = height;
|
||||
m_window_width = width;
|
||||
}
|
||||
float Widget::width() const {
|
||||
if (m_parent) {
|
||||
return m_parent->width();
|
||||
}
|
||||
return m_window_width;
|
||||
}
|
||||
float Widget::height() const {
|
||||
if (m_parent) {
|
||||
return m_parent->height();
|
||||
}
|
||||
return m_window_height;
|
||||
}
|
||||
|
||||
float Widget::width() const { return 0.0f; }
|
||||
float Widget::height() const { return 0.0f; }
|
||||
|
||||
const glm::vec2& Widget::pos() const { return m_pos; }
|
||||
glm::vec2 Widget::pos() const { return compute_position(); }
|
||||
const std::string& Widget::id() const { return m_id; }
|
||||
|
||||
bool Widget::handle_key_event(const KeyEvent& e) {
|
||||
@@ -63,6 +145,9 @@ bool Widget::handle_mouse_wheel_event(const MouseWheelEvent& e) {
|
||||
return false;
|
||||
}
|
||||
bool Widget::handle_window_resize_event(const WindowResizeEvent& e) {
|
||||
|
||||
set_window_size(e.width, e.height);
|
||||
|
||||
for (auto it = m_children.rbegin(); it != m_children.rend(); ++it) {
|
||||
if ((*it)->handle_window_resize_event(e)) {
|
||||
return true;
|
||||
|
||||
@@ -11,16 +11,15 @@ WorldUIManager::WorldUIManager(WorldScene& scene) : m_scene(scene) {}
|
||||
WorldUIManager::~WorldUIManager() {}
|
||||
|
||||
void WorldUIManager::init() {
|
||||
auto crosshair = std::make_unique<Image>();
|
||||
auto crosshair = std::make_unique<Image>(nullptr);
|
||||
|
||||
crosshair->set_image("texture/ui/0.png",
|
||||
m_scene.scene_manager().app().texture_manager());
|
||||
auto& renderer = m_scene.scene_manager().app().renderer();
|
||||
|
||||
crosshair->set_scale(3.0f).set_position(
|
||||
renderer.window_width() / 2 - crosshair->width() / 2,
|
||||
renderer.window_height() / 2 - crosshair->height() / 2);
|
||||
|
||||
crosshair->set_window_size(renderer.window_width(),
|
||||
renderer.window_height());
|
||||
crosshair->set_anchor(Anchor::CENTER);
|
||||
crosshair->set_scale(3.0f);
|
||||
m_widgets.try_emplace("crosshair", std::move(crosshair));
|
||||
}
|
||||
void WorldUIManager::update(float dt) {
|
||||
@@ -93,15 +92,6 @@ bool WorldUIManager::handle_mouse_button_event(const MouseButtonEvent& e) {
|
||||
return false;
|
||||
}
|
||||
bool WorldUIManager::handle_window_resize_event(const WindowResizeEvent& e) {
|
||||
auto it = m_widgets.find("crosshair");
|
||||
if (it != m_widgets.end()) {
|
||||
auto* crosshair = dynamic_cast<Image*>(it->second.get());
|
||||
if (crosshair) {
|
||||
crosshair->set_position(e.width / 2.0f - crosshair->width() / 2.0f,
|
||||
e.height / 2.0f -
|
||||
crosshair->height() / 2.0f);
|
||||
}
|
||||
}
|
||||
for (auto& w : m_widgets) {
|
||||
if (w.second->handle_window_resize_event(e)) {
|
||||
return true;
|
||||
|
||||
@@ -73,8 +73,10 @@ bool Window::handle_key_event(const KeyEvent& e) {
|
||||
return true;
|
||||
}
|
||||
if (e.key == Key::ESCAPE && e.action == KeyAction::PRESS) {
|
||||
glfwSetWindowShouldClose(m_window, GLFW_TRUE);
|
||||
return true;
|
||||
if (!m_game_running) {
|
||||
glfwSetWindowShouldClose(m_window, GLFW_TRUE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (e.key == Key::LEFT_ALT && e.action == KeyAction::PRESS) {
|
||||
toggle_mouse_able();
|
||||
@@ -237,6 +239,9 @@ void Window::set_game_running(bool running) {
|
||||
m_mouse_enable = running;
|
||||
toggle_mouse_able();
|
||||
}
|
||||
|
||||
void Window::should_close_window() { glfwSetWindowShouldClose(m_window, true); }
|
||||
|
||||
void Window::imgui_init() {
|
||||
float dpi_scale_x, dpi_scale_y;
|
||||
glfwGetWindowContentScale(m_window, &dpi_scale_x, &dpi_scale_y);
|
||||
|
||||
Reference in New Issue
Block a user