mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
Compare commits
17 Commits
v0.1.4
...
80ba6dad89
| Author | SHA1 | Date | |
|---|---|---|---|
| 80ba6dad89 | |||
| acb0b94d7b | |||
| e7082bdbe0 | |||
| f5e53fd13d | |||
| 0cbb353a2a | |||
| e8157ab549 | |||
| 1fa3b9cce8 | |||
| b5e0bb9290 | |||
| 576a2f8072 | |||
| 01c9f61d1c | |||
| 8bbed7b7b9 | |||
| 674c023228 | |||
| d00ada1391 | |||
| cb1eb25e7b | |||
| 5712ba0600 | |||
| 2d28488126 | |||
| 09653c318a |
11
assets/shaders/image_f_shader.glsl
Normal file
11
assets/shaders/image_f_shader.glsl
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 460
|
||||
|
||||
in vec2 tc;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
layout (binding = 0) uniform sampler2D samp;
|
||||
|
||||
void main(void) {
|
||||
color = texture(samp, tc);
|
||||
}
|
||||
14
assets/shaders/image_v_shader.glsl
Normal file
14
assets/shaders/image_v_shader.glsl
Normal file
@@ -0,0 +1,14 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec2 pos;
|
||||
layout (location = 1) in vec2 texCoord;
|
||||
|
||||
out vec2 tc;
|
||||
|
||||
uniform mat4 model_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = proj_matrix * model_matrix * vec4(pos, 0.0, 1.0);
|
||||
tc = texCoord;
|
||||
}
|
||||
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,12 +0,0 @@
|
||||
#version 460
|
||||
|
||||
in vec2 tc;
|
||||
flat in int tex_layer;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
layout (binding = 0) uniform sampler2DArray samp;
|
||||
|
||||
void main(void) {
|
||||
color = texture(samp, vec3(tc, tex_layer));
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec2 pos;
|
||||
layout (location = 1) in vec2 texCoord;
|
||||
layout (location = 2) in float layer;
|
||||
|
||||
out vec2 tc;
|
||||
|
||||
flat out int tex_layer;
|
||||
|
||||
uniform mat4 m_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = proj_matrix * m_matrix * vec4(pos, 0.0, 1.0);
|
||||
tc = texCoord;
|
||||
tex_layer = int(layer);
|
||||
}
|
||||
BIN
assets/texture/ui/button001.png
Normal file
BIN
assets/texture/ui/button001.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 143 B |
@@ -1,27 +1,19 @@
|
||||
#pragma once
|
||||
#include "Cubed/audio/audio_engine.hpp"
|
||||
#include "Cubed/gameplay/client_world.hpp"
|
||||
#include "Cubed/gameplay/network_server.hpp"
|
||||
#include "Cubed/gameplay/server_world.hpp"
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include "Cubed/camera.hpp"
|
||||
#include "Cubed/argument.hpp"
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/dev_panel.hpp"
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/scene/scene_manager.hpp"
|
||||
#include "Cubed/texture_manager.hpp"
|
||||
#include "Cubed/window.hpp"
|
||||
namespace Cubed {
|
||||
|
||||
class App {
|
||||
public:
|
||||
struct Argument {
|
||||
bool is_client = false;
|
||||
int port = 25530;
|
||||
std::string ip{"127.0.0.1"};
|
||||
std::string player{"Unknown"};
|
||||
bool debug_on = true;
|
||||
};
|
||||
|
||||
App();
|
||||
~App();
|
||||
static void cursor_position_callback(GLFWwindow* window, double xpos,
|
||||
@@ -33,6 +25,8 @@ public:
|
||||
static void window_focus_callback(GLFWwindow* window, int focused);
|
||||
static void window_reshape_callback(GLFWwindow* window, int new_width,
|
||||
int new_height);
|
||||
static void framebuffer_size_callback(GLFWwindow* window, int new_width,
|
||||
int new_height);
|
||||
static void mouse_scroll_callback(GLFWwindow* window, double xoffset,
|
||||
double yoffset);
|
||||
static void cursor_enter_callback(GLFWwindow* window, int entered);
|
||||
@@ -43,12 +37,9 @@ public:
|
||||
static float delta_time();
|
||||
static float get_fps();
|
||||
|
||||
Camera& camera();
|
||||
DevPanel& dev_panel();
|
||||
Renderer& renderer();
|
||||
TextureManager& texture_manager();
|
||||
Window& window();
|
||||
ClientWorld& client_world();
|
||||
ServerWorld& server_world();
|
||||
Config& config();
|
||||
const Argument& argument() const;
|
||||
@@ -56,18 +47,17 @@ public:
|
||||
|
||||
private:
|
||||
Config m_game_config;
|
||||
Camera m_camera;
|
||||
|
||||
TextureManager m_texture_manager;
|
||||
NetworkServer m_server;
|
||||
std::shared_ptr<NetworkClient> m_client;
|
||||
AudioEngine m_audio;
|
||||
ClientWorld m_client_world;
|
||||
|
||||
DevPanel m_dev_panel;
|
||||
Renderer m_renderer;
|
||||
|
||||
Window m_window;
|
||||
|
||||
SceneManager m_scene_manager;
|
||||
|
||||
inline static double last_time = glfwGetTime();
|
||||
inline static double current_time = glfwGetTime();
|
||||
inline static double dt = 0.0f;
|
||||
@@ -86,6 +76,8 @@ private:
|
||||
void render();
|
||||
void run();
|
||||
void update();
|
||||
|
||||
void dispatch_event(const Event& e);
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
11
include/Cubed/argument.hpp
Normal file
11
include/Cubed/argument.hpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
namespace Cubed {
|
||||
struct Argument {
|
||||
bool is_client = false;
|
||||
int port = 25530;
|
||||
std::string ip{"127.0.0.1"};
|
||||
std::string player{"Unknown"};
|
||||
bool debug_on = true;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/input/event.hpp"
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <glm/glm.hpp>
|
||||
@@ -28,6 +29,9 @@ private:
|
||||
glm::vec3 camera_collision(glm::vec3 start, glm::vec3 end,
|
||||
float radius = 0.2f);
|
||||
|
||||
bool handle_key_event(const KeyEvent& e);
|
||||
bool handle_mouse_move_event(const MouseMoveEvent& e);
|
||||
|
||||
public:
|
||||
Camera();
|
||||
|
||||
@@ -45,6 +49,7 @@ public:
|
||||
glm::vec3 get_camera_front() const;
|
||||
void change_perspective();
|
||||
bool is_first_person() const;
|
||||
bool handle_event(const Event& e);
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/ui/text.hpp"
|
||||
#include "Cubed/ui/column_layout.hpp"
|
||||
#include "Cubed/ui/label.hpp"
|
||||
#include "Cubed/ui/widget.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -11,14 +13,14 @@ public:
|
||||
static DebugCollector& get();
|
||||
DebugCollector();
|
||||
|
||||
std::unordered_map<std::size_t, Text>& all_texts();
|
||||
|
||||
Text& text(std::string_view name);
|
||||
void report(std::string_view name, std::string_view content);
|
||||
void init_text();
|
||||
void report(const std::string& name, std::string_view content);
|
||||
void init(int width, int height);
|
||||
Widget& get_widget();
|
||||
bool handle_event(const Event& e);
|
||||
|
||||
private:
|
||||
std::unordered_map<std::size_t, Text> m_texts;
|
||||
ColumnLayout m_widget;
|
||||
std::unordered_map<std::string, Label*> m_component;
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -6,8 +6,9 @@
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
class App;
|
||||
class WorldScene;
|
||||
class ClientPlayer;
|
||||
class App;
|
||||
class DevPanel {
|
||||
struct ConfigView {
|
||||
float fov = 70.0f;
|
||||
@@ -32,12 +33,13 @@ class DevPanel {
|
||||
};
|
||||
|
||||
public:
|
||||
DevPanel(App& app);
|
||||
DevPanel(WorldScene& app);
|
||||
void init();
|
||||
void render();
|
||||
|
||||
private:
|
||||
App& m_app;
|
||||
WorldScene& m_world_scene;
|
||||
Config& m_config;
|
||||
ConfigView m_config_view;
|
||||
ClientPlayer* m_player;
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
#include "Cubed/gameplay/game_mode.hpp"
|
||||
#include "Cubed/gameplay/game_time.hpp"
|
||||
#include "Cubed/gameplay/player.hpp"
|
||||
#include "Cubed/input.hpp"
|
||||
#include "Cubed/input/event.hpp"
|
||||
#include "Cubed/input/input.hpp"
|
||||
|
||||
#include <absl/container/flat_hash_set.h>
|
||||
#include <glm/glm.hpp>
|
||||
@@ -23,6 +24,14 @@ public:
|
||||
ClientPlayer(ClientWorld& world);
|
||||
~ClientPlayer();
|
||||
|
||||
bool handle_mouse_button_event(const MouseButtonEvent& e);
|
||||
bool handle_key_event(const KeyEvent& e);
|
||||
bool handle_mouse_wheel_event(const MouseWheelEvent& e);
|
||||
|
||||
void update_front_vec(float offset_x, float offset_y);
|
||||
bool update_player_move_state(Key key, KeyAction action);
|
||||
bool update_scroll(float yoffset);
|
||||
|
||||
void update_chunk_set(const ChunkPosSet& set);
|
||||
const ChunkPosSet& get_chunk_pos_set() const;
|
||||
ChunkPosSet get_chunk_pos_set();
|
||||
@@ -40,9 +49,6 @@ public:
|
||||
void set_player_pos(const glm::vec3& pos);
|
||||
void set_place_block(unsigned id);
|
||||
void update(float delta_time);
|
||||
void update_front_vec(float offset_x, float offset_y);
|
||||
void update_player_move_state(int key, int action);
|
||||
void update_scroll(double yoffset);
|
||||
|
||||
float& max_walk_speed();
|
||||
float& max_run_speed();
|
||||
@@ -52,7 +58,7 @@ public:
|
||||
float& g();
|
||||
float& fly_y_speed();
|
||||
|
||||
unsigned place_block() const;
|
||||
unsigned get_current_block() const;
|
||||
|
||||
void set_gait(Gait gait);
|
||||
GameMode& game_mode();
|
||||
@@ -74,6 +80,7 @@ public:
|
||||
float distance = 4.0f);
|
||||
bool is_underwater() const;
|
||||
void set_underwater(bool u);
|
||||
void place_block(float dt);
|
||||
|
||||
private:
|
||||
using enum GameMode;
|
||||
@@ -83,7 +90,8 @@ private:
|
||||
float m_deceleration = DEFAULT_DECELERATION;
|
||||
float m_g = DEFAULT_G;
|
||||
constexpr static float MAX_SPACE_ON_TIME = 0.3f;
|
||||
|
||||
constexpr static float PLACE_BLOCK_INTERVAL = 0.2f;
|
||||
float m_place_time = PLACE_BLOCK_INTERVAL;
|
||||
std::atomic<float> m_yaw = 0.0f;
|
||||
std::atomic<float> m_pitch = 0.0f;
|
||||
|
||||
@@ -119,6 +127,7 @@ private:
|
||||
|
||||
std::atomic<Gait> m_gait = Gait::STOP;
|
||||
MoveState m_move_state{};
|
||||
MouseState m_mouse_state{};
|
||||
GameMode m_game_mode = CREATIVE;
|
||||
std::optional<LookBlock> m_look_block = std::nullopt;
|
||||
std::string m_name{};
|
||||
@@ -137,11 +146,15 @@ private:
|
||||
|
||||
void update_direction();
|
||||
void update_lookup_block();
|
||||
|
||||
void update_move(float delta_time);
|
||||
|
||||
void update_x_move(glm::vec3& player_pos);
|
||||
void update_y_move(glm::vec3& player_pos);
|
||||
void update_z_move(glm::vec3& player_pos);
|
||||
|
||||
void update_player_chunk();
|
||||
|
||||
void play_walk_sound(float dt);
|
||||
Gait compute_gait() const;
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "Cubed/gameplay/client_player.hpp"
|
||||
#include "Cubed/gameplay/game_time.hpp"
|
||||
#include "Cubed/gameplay/network_client.hpp"
|
||||
#include "Cubed/input/event.hpp"
|
||||
#include "Cubed/tools/cubed_random.hpp"
|
||||
#include "Cubed/tools/priority_thread_pool.hpp"
|
||||
|
||||
@@ -41,14 +42,15 @@ struct PlayerRenderData {
|
||||
Gait gait;
|
||||
float angle;
|
||||
};
|
||||
|
||||
class WorldScene;
|
||||
class ClientWorld {
|
||||
public:
|
||||
ClientWorld(AudioEngine& auido, Config& config);
|
||||
ClientWorld(AudioEngine& auido, Config& config, WorldScene& scene);
|
||||
~ClientWorld();
|
||||
void init(std::string_view player_name,
|
||||
std::shared_ptr<NetworkClient> client);
|
||||
void update(float delta_time);
|
||||
bool handle_event(const Event& e);
|
||||
const std::optional<LookBlock>& get_look_block_pos() const;
|
||||
ClientPlayer& get_player();
|
||||
const ClientPlayer& get_player() const;
|
||||
@@ -97,6 +99,7 @@ public:
|
||||
static AABB get_block_aabb(const glm::ivec3& pos);
|
||||
AudioEngine& get_audio();
|
||||
Config& get_config();
|
||||
WorldScene& world_scene();
|
||||
template <typename Fn>
|
||||
void register_ticktimer(std::string_view id, TickType threshold, Fn&& f) {
|
||||
m_ticktimers.emplace(
|
||||
@@ -133,6 +136,7 @@ private:
|
||||
ChunkHashMap m_chunks;
|
||||
AudioEngine& m_audio;
|
||||
Config& m_config;
|
||||
WorldScene& m_world_scene;
|
||||
std::vector<glm::vec4> m_planes;
|
||||
std::jthread m_client_thread;
|
||||
|
||||
|
||||
61
include/Cubed/input/event.hpp
Normal file
61
include/Cubed/input/event.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/input/key.hpp"
|
||||
#include "Cubed/input/mouse.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
struct MouseMoveEvent {
|
||||
float xpos;
|
||||
float ypos;
|
||||
|
||||
MouseMoveEvent(float x, float y) : xpos(x), ypos(y) {}
|
||||
};
|
||||
|
||||
struct MouseButtonEvent {
|
||||
MouseKey key;
|
||||
KeyAction action;
|
||||
|
||||
MouseButtonEvent(MouseKey k, KeyAction a) : key(k), action(a) {}
|
||||
};
|
||||
|
||||
struct MouseWheelEvent {
|
||||
float offset;
|
||||
|
||||
MouseWheelEvent(float o) : offset(o) {}
|
||||
};
|
||||
|
||||
struct KeyEvent {
|
||||
Key key;
|
||||
KeyAction action;
|
||||
|
||||
KeyEvent(Key k, KeyAction a) : key(k), action(a) {}
|
||||
};
|
||||
|
||||
struct TextInputEvent {
|
||||
std::string text;
|
||||
|
||||
TextInputEvent(std::string t) : text(std::move(t)) {}
|
||||
};
|
||||
|
||||
struct WindowResizeEvent {
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
struct FrameBufferResizeEvent {
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
using Event =
|
||||
std::variant<MouseMoveEvent, MouseButtonEvent, MouseWheelEvent, KeyEvent,
|
||||
TextInputEvent, WindowResizeEvent, FrameBufferResizeEvent>;
|
||||
|
||||
template <class... T> struct Overloaded : T... {
|
||||
using T::operator()...;
|
||||
};
|
||||
template <class... T> Overloaded(T...) -> Overloaded<T...>;
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -18,19 +18,4 @@ struct MouseState {
|
||||
bool right = false;
|
||||
};
|
||||
|
||||
struct KeyState {
|
||||
bool r = false;
|
||||
};
|
||||
|
||||
struct InputState {
|
||||
MoveState move_state;
|
||||
MouseState mouse_state;
|
||||
KeyState key_state;
|
||||
};
|
||||
|
||||
namespace Input {
|
||||
InputState& get_input_state();
|
||||
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
127
include/Cubed/input/key.hpp
Normal file
127
include/Cubed/input/key.hpp
Normal file
@@ -0,0 +1,127 @@
|
||||
#pragma once
|
||||
|
||||
namespace Cubed {
|
||||
enum class Key {
|
||||
// Letter keys
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
K,
|
||||
L,
|
||||
M,
|
||||
N,
|
||||
O,
|
||||
P,
|
||||
Q,
|
||||
R,
|
||||
S,
|
||||
T,
|
||||
U,
|
||||
V,
|
||||
W,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
|
||||
// Digit keys (main keyboard area)
|
||||
DIGIT_0,
|
||||
DIGIT_1,
|
||||
DIGIT_2,
|
||||
DIGIT_3,
|
||||
DIGIT_4,
|
||||
DIGIT_5,
|
||||
DIGIT_6,
|
||||
DIGIT_7,
|
||||
DIGIT_8,
|
||||
DIGIT_9,
|
||||
|
||||
// Function keys
|
||||
F1,
|
||||
F2,
|
||||
F3,
|
||||
F4,
|
||||
F5,
|
||||
F6,
|
||||
F7,
|
||||
F8,
|
||||
F9,
|
||||
F10,
|
||||
F11,
|
||||
F12,
|
||||
|
||||
// Control keys
|
||||
BACKSPACE,
|
||||
TAB,
|
||||
ENTER,
|
||||
ESCAPE,
|
||||
SPACE,
|
||||
CAPS_LOCK,
|
||||
NUM_LOCK,
|
||||
SCROLL_LOCK,
|
||||
|
||||
// Modifier keys
|
||||
LEFT_SHIFT,
|
||||
RIGHT_SHIFT,
|
||||
LEFT_CTRL,
|
||||
RIGHT_CTRL,
|
||||
LEFT_ALT,
|
||||
RIGHT_ALT,
|
||||
LEFT_SUPER,
|
||||
RIGHT_SUPER, // Windows / Command 键
|
||||
|
||||
// Navigation keys
|
||||
INSERT,
|
||||
DELETE,
|
||||
HOME,
|
||||
END,
|
||||
PAGE_UP,
|
||||
PAGE_DOWN,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
UP,
|
||||
DOWN,
|
||||
|
||||
// Lock and system keys
|
||||
PRINT_SCREEN,
|
||||
PAUSE,
|
||||
|
||||
// Main keyboard area symbol keys
|
||||
GRAVE_ACCENT, // `
|
||||
MINUS, // -
|
||||
EQUALS, // =
|
||||
LEFT_BRACKET, // [
|
||||
RIGHT_BRACKET, // ]
|
||||
BACKSLASH, // \ /
|
||||
SEMICOLON, // ;
|
||||
APOSTROPHE, // '
|
||||
COMMA, // ,
|
||||
PERIOD, // .
|
||||
SLASH, // /
|
||||
|
||||
// Numpad area
|
||||
NUMPAD_0,
|
||||
NUMPAD_1,
|
||||
NUMPAD_2,
|
||||
NUMPAD_3,
|
||||
NUMPAD_4,
|
||||
NUMPAD_5,
|
||||
NUMPAD_6,
|
||||
NUMPAD_7,
|
||||
NUMPAD_8,
|
||||
NUMPAD_9,
|
||||
NUMPAD_ADD, // +
|
||||
NUMPAD_SUBTRACT, // -
|
||||
NUMPAD_MULTIPLY, // *
|
||||
NUMPAD_DIVIDE, // /
|
||||
NUMPAD_DECIMAL, // .
|
||||
NUMPAD_ENTER
|
||||
};
|
||||
enum class KeyAction { PRESS, RELEASE, REPEAT };
|
||||
} // namespace Cubed
|
||||
25
include/Cubed/input/mouse.hpp
Normal file
25
include/Cubed/input/mouse.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
enum class MouseKey {
|
||||
LEFT_BUTTON,
|
||||
RIGHT_BUTTON,
|
||||
MIDDLE_BUTTON,
|
||||
|
||||
BACK_BUTTON, // Side button back
|
||||
FORWARD_BUTTON, // Side button forward
|
||||
|
||||
WHEEL_UP,
|
||||
WHEEL_DOWN,
|
||||
WHEEL_LEFT,
|
||||
WHEEL_RIGHT,
|
||||
|
||||
EXTRA_BUTTON_1, // Additional programmable buttons
|
||||
EXTRA_BUTTON_2,
|
||||
EXTRA_BUTTON_3,
|
||||
EXTRA_BUTTON_4,
|
||||
EXTRA_BUTTON_5
|
||||
};
|
||||
|
||||
}
|
||||
@@ -188,13 +188,14 @@ constexpr float CUBE_VER[24] = {0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0,
|
||||
constexpr int OUTLINE_CUBE_INDICES[24] = {0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6,
|
||||
6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7};
|
||||
|
||||
constexpr float SQUARE_VERTICES[6][2] = {
|
||||
{-0.5f, -0.5f}, // bottom left
|
||||
{-0.5f, 0.5f}, // top left
|
||||
{0.5f, 0.5f}, // top right
|
||||
{0.5f, 0.5f}, // top right
|
||||
{0.5f, -0.5f}, // bottom right
|
||||
{-0.5f, -0.5f} // bottom left
|
||||
constexpr float SQUARE_VERTICES_TOP_LEFT[6][2] = {
|
||||
{0.0f, 0.0f}, // top left
|
||||
{0.0f, 1.0f}, // bottom left
|
||||
{1.0f, 1.0f}, // bottom right
|
||||
|
||||
{1.0f, 1.0f}, // bottom right
|
||||
{1.0f, 0.0f}, // top right
|
||||
{0.0f, 0.0f} // top left
|
||||
};
|
||||
|
||||
constexpr float SQUARE_TEXTURE_POS[6][2] = {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <glad/glad.h>
|
||||
|
||||
namespace Cubed {
|
||||
class ClientWorld;
|
||||
class Renderer;
|
||||
class PlayerRenderer {
|
||||
public:
|
||||
@@ -12,8 +13,9 @@ public:
|
||||
PlayerRenderer(Renderer& renderer);
|
||||
~PlayerRenderer();
|
||||
void init();
|
||||
void render(const Shader& shader);
|
||||
void shadow_render(const Shader& shader, glm::mat4& light_matrix);
|
||||
void render(const Shader& shader, ClientWorld& world);
|
||||
void shadow_render(const Shader& shader, glm::mat4& light_matrix,
|
||||
ClientWorld& world);
|
||||
|
||||
private:
|
||||
struct PlayerVertex {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/constants.hpp"
|
||||
#include "Cubed/input/event.hpp"
|
||||
#include "Cubed/primitive_data.hpp"
|
||||
#include "Cubed/render/player_renderer.hpp"
|
||||
#include "Cubed/render/shader_manager.hpp"
|
||||
@@ -9,13 +10,13 @@
|
||||
#include "Cubed/render/vertex_buffer.hpp"
|
||||
#include "Cubed/render/world_renderer.hpp"
|
||||
#include "Cubed/shader.hpp"
|
||||
#include "Cubed/ui/text.hpp"
|
||||
#include "Cubed/ui/image.hpp"
|
||||
#include "Cubed/ui/label.hpp"
|
||||
#include "Cubed/ui/rect.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
namespace Cubed {
|
||||
|
||||
class Camera;
|
||||
class TextureManager;
|
||||
class ClientWorld;
|
||||
class DevPanel;
|
||||
@@ -23,18 +24,23 @@ class Renderer {
|
||||
public:
|
||||
constexpr static int NUM_VAO = 7;
|
||||
|
||||
Renderer(const Camera& camera, ClientWorld& world,
|
||||
const TextureManager& texture_manager, DevPanel& dev_panel,
|
||||
Config& config);
|
||||
Renderer(TextureManager& texture_manager, Config& config);
|
||||
~Renderer();
|
||||
void hot_reload();
|
||||
void init(bool debug_on);
|
||||
const Shader& get_shader(const std::string& name) const;
|
||||
void render();
|
||||
void begin_frame();
|
||||
void end_frame();
|
||||
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();
|
||||
|
||||
void update(float delta_time);
|
||||
void update_fov(float fov);
|
||||
void update_proj_matrix(float aspect, float width, float height);
|
||||
void updata_framebuffer(int width, int height);
|
||||
|
||||
float& ambient_strength();
|
||||
|
||||
bool& discard_transparent();
|
||||
@@ -58,24 +64,23 @@ public:
|
||||
float& underwater_fog_density();
|
||||
float& water_density();
|
||||
|
||||
const Camera& camera() const;
|
||||
const ClientWorld& world() const;
|
||||
ClientWorld& world();
|
||||
const glm::mat4& world_proj_matrix() const;
|
||||
const TextureManager& texture_mamger() const;
|
||||
float delta_time() const;
|
||||
|
||||
float height() const;
|
||||
float width() const;
|
||||
float window_height() const;
|
||||
float window_width() const;
|
||||
float frame_height() const;
|
||||
float frame_width() const;
|
||||
const glm::mat4& p_mat() const;
|
||||
|
||||
const std::vector<VertexArray>& vao() const;
|
||||
void render_dev_panel(DevPanel& dev_panel);
|
||||
|
||||
bool handle_event(const Event& e);
|
||||
|
||||
private:
|
||||
const Camera& m_camera;
|
||||
DevPanel& m_dev_panel;
|
||||
const TextureManager& m_texture_manager;
|
||||
ClientWorld& m_world;
|
||||
TextureManager& m_texture_manager;
|
||||
|
||||
bool m_init = false;
|
||||
|
||||
@@ -84,8 +89,11 @@ private:
|
||||
|
||||
float m_delta_time = 0.0f;
|
||||
|
||||
float m_width = 0.0f;
|
||||
float m_height = 0.0f;
|
||||
float m_frame_width = 0.0f;
|
||||
float m_frame_height = 0.0f;
|
||||
|
||||
float m_window_width = 0.0f;
|
||||
float m_window_height = 0.0f;
|
||||
|
||||
glm::mat4 m_world_proj_matrix;
|
||||
|
||||
@@ -97,14 +105,13 @@ private:
|
||||
std::unique_ptr<VertexBuffer> m_quad_vbo;
|
||||
|
||||
glm::mat4 m_ui_proj_matrix;
|
||||
glm::mat4 m_ui_model_matrix;
|
||||
ShaderManager m_shaders;
|
||||
|
||||
/*
|
||||
0 - quad vao
|
||||
0 - quad vao (center)
|
||||
1 - sky vao
|
||||
2 - outline vao
|
||||
3 - ui vao
|
||||
3 - ui vao (top-left)
|
||||
4 - text vao
|
||||
*/
|
||||
std::vector<VertexArray> m_vao;
|
||||
@@ -112,16 +119,12 @@ private:
|
||||
|
||||
WorldRenderer m_world_renderer;
|
||||
Config& m_config;
|
||||
|
||||
bool handle_window_resize_event(const WindowResizeEvent& e);
|
||||
bool handle_frame_buffer_resize_event(const FrameBufferResizeEvent& e);
|
||||
void updata_framebuffer(int width, int height);
|
||||
void init_quad();
|
||||
void init_text();
|
||||
|
||||
void day_night_calculation();
|
||||
|
||||
void render_sky();
|
||||
void render_text();
|
||||
void render_ui();
|
||||
|
||||
void render_dev_panel();
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -35,6 +35,7 @@ enum TextureFormat : GLenum {
|
||||
RGBA16F = GL_RGBA16F,
|
||||
RED = GL_RED,
|
||||
RGBA = GL_RGBA,
|
||||
R8 = GL_R8,
|
||||
RGB = GL_RGB,
|
||||
RGBA8 = GL_RGBA8,
|
||||
|
||||
@@ -60,12 +61,12 @@ public:
|
||||
|
||||
void tex_image_2d(TextureFormat internalformat, TextureFormat format,
|
||||
GLenum type, const void* data, GLsizei width,
|
||||
GLsizei height, GLint level = 0, GLint border = 0) const;
|
||||
GLsizei height, GLint level = 0, GLint border = 0);
|
||||
|
||||
void tex_image_3d(TextureFormat internalformat, TextureFormat format,
|
||||
GLenum type, const void* data, GLsizei width,
|
||||
GLsizei height, GLsizei depth, GLint level = 0,
|
||||
GLint border = 0) const;
|
||||
GLint border = 0);
|
||||
|
||||
void tex_sub_image_3d(TextureFormat format, GLenum type, const void* data,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
@@ -84,11 +85,14 @@ public:
|
||||
void set_clamp_to_edge(bool r = true, bool s = true, bool t = true) const;
|
||||
|
||||
TextureType type() const;
|
||||
float width() const;
|
||||
float height() const;
|
||||
|
||||
private:
|
||||
GLuint m_id = 0;
|
||||
float m_width = 0;
|
||||
float m_height = 0;
|
||||
const TextureType M_TYPE;
|
||||
|
||||
GLenum get_gl_texture_type() const;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
WorldRenderer& operator=(const WorldRenderer&) = delete;
|
||||
WorldRenderer& operator=(WorldRenderer&&) = delete;
|
||||
void init();
|
||||
void render();
|
||||
void render(ClientWorld& world);
|
||||
void updata_framebuffer(int width, int height);
|
||||
|
||||
float& ambient_strength();
|
||||
@@ -121,27 +121,26 @@ private:
|
||||
|
||||
glm::mat4 view_matrix;
|
||||
|
||||
ClientWorld& m_world;
|
||||
const Camera& m_camera;
|
||||
const TextureManager& m_texture_manager;
|
||||
void day_night_calculation();
|
||||
void day_night_calculation(ClientWorld& world);
|
||||
|
||||
void render_sky();
|
||||
void render_sky(ClientWorld& world);
|
||||
|
||||
void render_world();
|
||||
void render_world(ClientWorld& world);
|
||||
|
||||
void shadow_map_generate();
|
||||
void shadow_map_generate(ClientWorld& world);
|
||||
|
||||
void render_underwater();
|
||||
void render_outline();
|
||||
void render_player();
|
||||
void render_underwater(ClientWorld& world);
|
||||
void render_outline(ClientWorld& world);
|
||||
void render_player(ClientWorld& world);
|
||||
|
||||
void render_normal_block(const glm::mat4& model_mat,
|
||||
const glm::mat4& mv_mat,
|
||||
const glm::mat4& norm_mat);
|
||||
const glm::mat4& mv_mat, const glm::mat4& norm_mat,
|
||||
ClientWorld& world);
|
||||
|
||||
void render_transparent_block(const glm::mat4& mv_mat,
|
||||
const glm::mat4& norm_mat);
|
||||
const glm::mat4& norm_mat,
|
||||
ClientWorld& world);
|
||||
|
||||
glm::vec3 quantize_sun_direction(const glm::vec3& sundir,
|
||||
float angle_step_deg) const;
|
||||
|
||||
28
include/Cubed/scene/main_menu_scene.hpp
Normal file
28
include/Cubed/scene/main_menu_scene.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/scene/scene.hpp"
|
||||
#include "Cubed/ui/main_menu_ui_manager.hpp"
|
||||
namespace Cubed {
|
||||
class SceneManager;
|
||||
class MainMenuScene : public Scene {
|
||||
public:
|
||||
MainMenuScene(const MainMenuScene&) = delete;
|
||||
MainMenuScene(MainMenuScene&&) = delete;
|
||||
MainMenuScene& operator=(const MainMenuScene&) = delete;
|
||||
MainMenuScene& operator=(MainMenuScene&&) = delete;
|
||||
MainMenuScene(SceneManager& scene_manager);
|
||||
~MainMenuScene();
|
||||
|
||||
void update(float dt) override;
|
||||
void render(Renderer& renderer) override;
|
||||
bool handle_event(const Event& e) override;
|
||||
void on_enter() override;
|
||||
void on_leave() override;
|
||||
|
||||
SceneManager& scene_manager();
|
||||
|
||||
private:
|
||||
SceneManager& m_scene_manager;
|
||||
MainMenuUIManager m_ui_manager;
|
||||
};
|
||||
} // namespace Cubed
|
||||
24
include/Cubed/scene/scene.hpp
Normal file
24
include/Cubed/scene/scene.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "Cubed/input/event.hpp"
|
||||
namespace Cubed {
|
||||
class Renderer;
|
||||
|
||||
enum class SceneType { MAIN_MENU, WORLD };
|
||||
|
||||
class Scene {
|
||||
public:
|
||||
Scene() = default;
|
||||
|
||||
Scene(const Scene&) = delete;
|
||||
Scene(Scene&&) = delete;
|
||||
Scene& operator=(const Scene&) = delete;
|
||||
Scene& operator=(Scene&&) = delete;
|
||||
|
||||
virtual ~Scene() = default;
|
||||
virtual void update(float dt) = 0;
|
||||
virtual void render(Renderer& renderer) = 0;
|
||||
virtual bool handle_event(const Event& e) = 0;
|
||||
virtual void on_enter() {};
|
||||
virtual void on_leave() {};
|
||||
};
|
||||
} // namespace Cubed
|
||||
47
include/Cubed/scene/scene_manager.hpp
Normal file
47
include/Cubed/scene/scene_manager.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
#include "Cubed/scene/scene.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
namespace Cubed {
|
||||
class App;
|
||||
class SceneManager {
|
||||
public:
|
||||
SceneManager(const SceneManager&) = delete;
|
||||
SceneManager(SceneManager&&) = delete;
|
||||
SceneManager& operator=(const SceneManager&) = delete;
|
||||
SceneManager& operator=(SceneManager&&) = delete;
|
||||
SceneManager(App& app);
|
||||
~SceneManager();
|
||||
|
||||
void update(float dt);
|
||||
void render(Renderer& renderer);
|
||||
|
||||
bool handle_event(const Event& e);
|
||||
|
||||
void request_change(SceneType type);
|
||||
void request_push(SceneType type);
|
||||
void request_pop();
|
||||
|
||||
App& app();
|
||||
|
||||
private:
|
||||
enum class OperationType { PUSH, POP, CHANGE };
|
||||
struct SceneOperation {
|
||||
OperationType type;
|
||||
std::optional<SceneType> scene;
|
||||
};
|
||||
|
||||
App& m_app;
|
||||
std::vector<std::unique_ptr<Scene>> m_pending_delete_scene;
|
||||
std::optional<SceneOperation> m_operation;
|
||||
std::stack<std::unique_ptr<Scene>> m_scenes;
|
||||
void process_operation();
|
||||
void change(SceneType type);
|
||||
void push(SceneType type);
|
||||
void pop();
|
||||
|
||||
std::unique_ptr<Scene> create_scene(SceneType);
|
||||
};
|
||||
} // namespace Cubed
|
||||
39
include/Cubed/scene/world_scene.hpp
Normal file
39
include/Cubed/scene/world_scene.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include "Cubed/argument.hpp"
|
||||
#include "Cubed/camera.hpp"
|
||||
#include "Cubed/dev_panel.hpp"
|
||||
#include "Cubed/gameplay/client_world.hpp"
|
||||
#include "Cubed/scene/scene.hpp"
|
||||
#include "Cubed/ui/world_ui_manager.hpp"
|
||||
namespace Cubed {
|
||||
class SceneManager;
|
||||
class WorldScene : public Scene {
|
||||
public:
|
||||
WorldScene(const WorldScene&) = delete;
|
||||
WorldScene(WorldScene&&) = delete;
|
||||
WorldScene& operator=(const WorldScene&) = delete;
|
||||
WorldScene& operator=(WorldScene&&) = delete;
|
||||
|
||||
WorldScene(SceneManager& scene_manager);
|
||||
~WorldScene();
|
||||
|
||||
void update(float dt) override;
|
||||
void render(Renderer& renderer) override;
|
||||
bool handle_event(const Event& e) override;
|
||||
void on_enter() override;
|
||||
void on_leave() override;
|
||||
|
||||
Camera& camera();
|
||||
SceneManager& scene_manager();
|
||||
ClientWorld& client_world();
|
||||
|
||||
private:
|
||||
SceneManager& m_scene_manager;
|
||||
DevPanel m_dev_panel;
|
||||
Camera m_camera;
|
||||
std::shared_ptr<NetworkClient> m_client;
|
||||
ClientWorld m_client_world;
|
||||
WorldUIManager m_ui_manager;
|
||||
const Argument& m_argument;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/gameplay/block.hpp"
|
||||
#include "Cubed/input/event.hpp"
|
||||
#include "Cubed/render/texture.hpp"
|
||||
|
||||
#include <glad/glad.h>
|
||||
@@ -15,10 +16,10 @@ private:
|
||||
std::unique_ptr<Texture> m_block_status_array;
|
||||
std::unique_ptr<Texture> m_texture_array;
|
||||
std::unique_ptr<Texture> m_cross_plane_array;
|
||||
std::unique_ptr<Texture> m_ui_array;
|
||||
std::unique_ptr<Texture> m_normal_texture_array;
|
||||
std::unique_ptr<Texture> m_skin;
|
||||
std::vector<std::unique_ptr<Texture>> m_item_textures;
|
||||
std::unordered_map<std::string, std::unique_ptr<Texture>> m_ui_map;
|
||||
GLfloat m_max_aniso = 0.0f;
|
||||
Config& m_config;
|
||||
int m_aniso = 1;
|
||||
@@ -27,7 +28,7 @@ private:
|
||||
void load_block_texture(unsigned block_id);
|
||||
void load_block_item_texture(unsigned id);
|
||||
void load_cross_plane_texture(unsigned id);
|
||||
void load_ui_texture(unsigned id);
|
||||
const Texture* load_image_texture(const std::string& path);
|
||||
void load_pbr_texture(unsigned id);
|
||||
void init_item();
|
||||
void init_block();
|
||||
@@ -35,6 +36,7 @@ private:
|
||||
void init_block_status();
|
||||
void init_skin();
|
||||
void hot_reload();
|
||||
bool handle_key_event(const KeyEvent& e);
|
||||
|
||||
public:
|
||||
TextureManager(Config& config);
|
||||
@@ -44,7 +46,7 @@ public:
|
||||
const Texture* get_block_status_array() const;
|
||||
const Texture* get_texture_array() const;
|
||||
const Texture* get_cross_plane_array() const;
|
||||
const Texture* get_ui_array() const;
|
||||
const Texture* get_image_texture(const std::string& path);
|
||||
const Texture* get_pbr_texture() const;
|
||||
const std::vector<std::unique_ptr<Texture>>& item_textures() const;
|
||||
const Texture* get_skin() const;
|
||||
@@ -54,6 +56,7 @@ public:
|
||||
void need_reload();
|
||||
void update();
|
||||
int max_aniso() const;
|
||||
bool handle_event(const Event& e);
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -22,6 +22,16 @@ struct Character {
|
||||
GLuint advance;
|
||||
};
|
||||
|
||||
struct TextMesh {
|
||||
std::vector<Vertex2D> vertices;
|
||||
|
||||
float width;
|
||||
float height;
|
||||
|
||||
float min_x;
|
||||
float min_y;
|
||||
};
|
||||
|
||||
class Shader;
|
||||
|
||||
class Font {
|
||||
@@ -29,9 +39,7 @@ public:
|
||||
Font();
|
||||
~Font();
|
||||
|
||||
static std::vector<Vertex2D> vertices(const std::string& text,
|
||||
float x = 0.0f, float y = 0.0f,
|
||||
float scale = 1.0f);
|
||||
static TextMesh vertices(const std::string& text);
|
||||
static const Texture* text_texture();
|
||||
static const std::string& font_path();
|
||||
|
||||
|
||||
@@ -3,9 +3,42 @@
|
||||
#include <SOIL2.h>
|
||||
#include <glad/glad.h>
|
||||
#include <string>
|
||||
|
||||
#include <utility>
|
||||
namespace Cubed {
|
||||
|
||||
namespace Tools {
|
||||
void delete_image_data(unsigned char* data);
|
||||
}
|
||||
|
||||
struct ImageData {
|
||||
unsigned char* data = nullptr;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int channels = 0;
|
||||
ImageData(const ImageData&) = delete;
|
||||
ImageData(ImageData&& o) noexcept
|
||||
: data(std::exchange(o.data, nullptr)), width(o.width),
|
||||
height(o.height), channels(o.channels) {}
|
||||
ImageData& operator=(const ImageData&) = delete;
|
||||
ImageData& operator=(ImageData&& o) noexcept {
|
||||
if (this == &o) {
|
||||
return *this;
|
||||
}
|
||||
if (data) {
|
||||
Tools::delete_image_data(data);
|
||||
}
|
||||
data = std::exchange(o.data, nullptr);
|
||||
width = o.width;
|
||||
height = o.height;
|
||||
channels = o.channels;
|
||||
return *this;
|
||||
}
|
||||
ImageData(unsigned char* d, int w, int h, int c)
|
||||
: data(d), width(w), height(h), channels(c) {}
|
||||
ImageData() = default;
|
||||
~ImageData() { Tools::delete_image_data(data); }
|
||||
};
|
||||
|
||||
namespace Tools {
|
||||
GLuint create_shader_program(const std::string& v_shader_path,
|
||||
const std::string& f_shader_path);
|
||||
@@ -13,9 +46,9 @@ void print_shader_log(GLuint shader);
|
||||
void print_program_info(int prog);
|
||||
bool check_opengl_error();
|
||||
std::string read_shader_source(const std::string& file_path);
|
||||
void delete_image_data(unsigned char* data);
|
||||
unsigned char* load_image_data(const std::string& tex_image_path,
|
||||
bool check_exist = true);
|
||||
|
||||
ImageData load_image_data(const std::string& tex_image_path,
|
||||
bool check_exist = true);
|
||||
|
||||
} // namespace Tools
|
||||
|
||||
|
||||
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,
|
||||
};
|
||||
58
include/Cubed/ui/button.hpp
Normal file
58
include/Cubed/ui/button.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/ui/image.hpp"
|
||||
#include "Cubed/ui/label.hpp"
|
||||
#include "Cubed/ui/widget.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace Cubed {
|
||||
class Button : public Widget {
|
||||
public:
|
||||
Button(Widget* parent);
|
||||
|
||||
Button(const Button&) = delete;
|
||||
Button(Button&&) = delete;
|
||||
Button& operator=(const Button&) = delete;
|
||||
Button& operator=(Button&&) = delete;
|
||||
|
||||
void render(Renderer& renderer) override;
|
||||
void update(float dt) override;
|
||||
|
||||
bool handle_mouse_move_event(const MouseMoveEvent& e) override;
|
||||
bool handle_mouse_button_event(const MouseButtonEvent& e) 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;
|
||||
template <typename F> Button& set_clicked(F&& f) {
|
||||
m_clicked = std::forward<F>(f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, typename... Args> T& set_background(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)..., this);
|
||||
T& ref = *w;
|
||||
m_foreground = std::move(w);
|
||||
m_foreground->set_anchor(Anchor::CENTER);
|
||||
return ref;
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void()> m_clicked;
|
||||
std::unique_ptr<Image> m_background;
|
||||
std::unique_ptr<Label> m_foreground;
|
||||
bool m_hovered = false;
|
||||
};
|
||||
} // 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
|
||||
27
include/Cubed/ui/image.hpp
Normal file
27
include/Cubed/ui/image.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/render/texture.hpp"
|
||||
#include "Cubed/ui/widget.hpp"
|
||||
#include "glm/ext/vector_float2.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
class TextureManager;
|
||||
class Image : public Widget {
|
||||
public:
|
||||
Image(Widget* parent);
|
||||
void update(float dt) override;
|
||||
void render(Renderer& renderer) override;
|
||||
|
||||
Image& set_image(const std::string& path, TextureManager& texture_manager);
|
||||
float width() const override;
|
||||
float height() const override;
|
||||
const Texture* texture() const;
|
||||
Image& set_scale(float scale);
|
||||
float scale() const;
|
||||
|
||||
private:
|
||||
const Texture* m_texture = nullptr;
|
||||
glm::vec2 m_pos{0.0f, 0.0f};
|
||||
float m_scale = 1.0f;
|
||||
};
|
||||
} // namespace Cubed
|
||||
48
include/Cubed/ui/label.hpp
Normal file
48
include/Cubed/ui/label.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
#include "Cubed/ui/text.hpp"
|
||||
#include "Cubed/ui/ui_vertex_data.hpp"
|
||||
#include "Cubed/ui/widget.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, Widget* parent);
|
||||
Label(Widget* parent);
|
||||
virtual ~Label() = default;
|
||||
|
||||
Label& set_text(std::string_view text);
|
||||
|
||||
Label& set_color(Color color);
|
||||
Label& set_scale(float scale);
|
||||
virtual void update(float dt) override;
|
||||
virtual void render(Renderer& renderer) override;
|
||||
|
||||
const UIVertexData& data() const;
|
||||
|
||||
const TextStyle& text_style() const;
|
||||
|
||||
float width() const override;
|
||||
float height() const override;
|
||||
float offset_x() const;
|
||||
float offset_y() const;
|
||||
float scale() const;
|
||||
|
||||
protected:
|
||||
virtual void on_update(float dt) override;
|
||||
virtual void on_render(Renderer& renderer) override;
|
||||
|
||||
private:
|
||||
TextStyle m_text;
|
||||
UIVertexData m_data;
|
||||
float m_real_width = 0.0f;
|
||||
float m_real_height = 0.0f;
|
||||
float m_offset_x = 0.0f;
|
||||
float m_offset_y = 0.0f;
|
||||
float m_scale = 1.0f;
|
||||
void update_vertices();
|
||||
};
|
||||
} // namespace Cubed
|
||||
36
include/Cubed/ui/main_menu_ui_manager.hpp
Normal file
36
include/Cubed/ui/main_menu_ui_manager.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/input/event.hpp"
|
||||
#include "Cubed/ui/widget.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
namespace Cubed {
|
||||
class Renderer;
|
||||
class MainMenuScene;
|
||||
class MainMenuUIManager {
|
||||
public:
|
||||
MainMenuUIManager(MainMenuScene& m_scene);
|
||||
MainMenuUIManager(const MainMenuUIManager&) = delete;
|
||||
MainMenuUIManager(MainMenuUIManager&&) = delete;
|
||||
MainMenuUIManager& operator=(const MainMenuUIManager&) = delete;
|
||||
MainMenuUIManager& operator=(MainMenuUIManager&&) = delete;
|
||||
~MainMenuUIManager();
|
||||
|
||||
void init();
|
||||
void render(Renderer& renderer);
|
||||
void update(float dt);
|
||||
|
||||
bool handle_event(const Event& e);
|
||||
|
||||
private:
|
||||
MainMenuScene& m_scene;
|
||||
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);
|
||||
bool handle_mouse_wheel_event(const MouseWheelEvent& e);
|
||||
bool handle_key_event(const KeyEvent& e);
|
||||
};
|
||||
} // namespace Cubed
|
||||
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,8 +1,5 @@
|
||||
#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 <glad/glad.h>
|
||||
@@ -10,46 +7,9 @@
|
||||
#include <string>
|
||||
namespace Cubed {
|
||||
|
||||
class Shader;
|
||||
|
||||
class Text {
|
||||
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();
|
||||
struct TextStyle {
|
||||
std::string text;
|
||||
Color color = Color::WHITE;
|
||||
};
|
||||
|
||||
} // 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
|
||||
61
include/Cubed/ui/widget.hpp
Normal file
61
include/Cubed/ui/widget.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
#include "Cubed/input/event.hpp"
|
||||
#include "Cubed/ui/anchor.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
namespace Cubed {
|
||||
class Renderer;
|
||||
|
||||
class Widget {
|
||||
|
||||
public:
|
||||
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_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 = 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);
|
||||
virtual bool handle_mouse_wheel_event(const MouseWheelEvent& e);
|
||||
virtual bool handle_window_resize_event(const WindowResizeEvent& e);
|
||||
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)..., 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);
|
||||
virtual glm::vec2 compute_position() const;
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<Widget>> m_children;
|
||||
};
|
||||
} // namespace Cubed
|
||||
34
include/Cubed/ui/world_ui_manager.hpp
Normal file
34
include/Cubed/ui/world_ui_manager.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/input/event.hpp"
|
||||
#include "Cubed/ui/widget.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
namespace Cubed {
|
||||
class WorldScene;
|
||||
class WorldUIManager {
|
||||
public:
|
||||
WorldUIManager(const WorldUIManager&) = delete;
|
||||
WorldUIManager(WorldUIManager&&) = delete;
|
||||
WorldUIManager& operator=(const WorldUIManager&) = delete;
|
||||
WorldUIManager& operator=(WorldUIManager&&) = delete;
|
||||
|
||||
WorldUIManager(WorldScene& scene);
|
||||
~WorldUIManager();
|
||||
|
||||
void init();
|
||||
void update(float dt);
|
||||
void render(Renderer& renderer);
|
||||
bool handle_event(const Event& e);
|
||||
|
||||
private:
|
||||
WorldScene& m_scene;
|
||||
std::unordered_map<std::string, std::unique_ptr<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);
|
||||
bool handle_mouse_wheel_event(const MouseWheelEvent& e);
|
||||
bool handle_key_event(const KeyEvent& e);
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -1,15 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/input/event.hpp"
|
||||
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include <GLFW/glfw3.h>
|
||||
namespace Cubed {
|
||||
|
||||
class Camera;
|
||||
class Renderer;
|
||||
class Window {
|
||||
public:
|
||||
Window(Renderer& renderer, Config& config);
|
||||
Window(Config& config);
|
||||
~Window();
|
||||
|
||||
bool is_mouse_enable() const;
|
||||
@@ -17,22 +18,34 @@ public:
|
||||
GLFWwindow* get_glfw_window();
|
||||
void init();
|
||||
void imgui_init();
|
||||
void update_viewport();
|
||||
|
||||
// end of frame to reload!
|
||||
bool handle_event(const Event& e);
|
||||
|
||||
void hot_reload();
|
||||
|
||||
void toggle_fullscreen();
|
||||
void toggle_mouse_able();
|
||||
|
||||
void set_camera(Camera* camera);
|
||||
Camera* camera();
|
||||
|
||||
void set_game_running(bool running);
|
||||
|
||||
void should_close_window();
|
||||
|
||||
private:
|
||||
bool m_mouse_enable = false;
|
||||
bool m_imgui_init = false;
|
||||
float m_aspect;
|
||||
bool m_game_running = false;
|
||||
GLFWwindow* m_window;
|
||||
int m_width;
|
||||
int m_height;
|
||||
Renderer& m_renderer;
|
||||
int m_window_width;
|
||||
int m_window_height;
|
||||
Config& m_config;
|
||||
Camera* m_camera = nullptr;
|
||||
bool handle_key_event(const KeyEvent& e);
|
||||
bool handle_window_resize_event(const WindowResizeEvent& e);
|
||||
bool handle_mouse_button_event(const MouseButtonEvent& e);
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -9,7 +9,6 @@ target_sources(${PROJECT_NAME}
|
||||
gameplay/biome.cpp
|
||||
gameplay/chunk_generator.cpp
|
||||
gameplay/tree.cpp
|
||||
input.cpp
|
||||
render/renderer.cpp
|
||||
shader.cpp
|
||||
texture_manager.cpp
|
||||
@@ -17,7 +16,6 @@ target_sources(${PROJECT_NAME}
|
||||
tools/shader_tools.cpp
|
||||
tools/font.cpp
|
||||
tools/perlin_noise.cpp
|
||||
ui/text.cpp
|
||||
window.cpp
|
||||
gameplay/builders/biome_builder.cpp
|
||||
gameplay/builders/plain_builder.cpp
|
||||
@@ -59,4 +57,16 @@ target_sources(${PROJECT_NAME}
|
||||
render/frame_buffer.cpp
|
||||
render/shader_manager.cpp
|
||||
render/world_renderer.cpp
|
||||
ui/widget.cpp
|
||||
ui/label.cpp
|
||||
ui/ui_vertex_data.cpp
|
||||
ui/image.cpp
|
||||
ui/button.cpp
|
||||
scene/world_scene.cpp
|
||||
scene/scene_manager.cpp
|
||||
ui/world_ui_manager.cpp
|
||||
ui/main_menu_ui_manager.cpp
|
||||
scene/main_menu_scene.cpp
|
||||
ui/column_layout.cpp
|
||||
ui/rect.cpp
|
||||
)
|
||||
551
src/app.cpp
551
src/app.cpp
@@ -1,5 +1,6 @@
|
||||
#include "Cubed/app.hpp"
|
||||
|
||||
#include "Cubed/camera.hpp"
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/debug_collector.hpp"
|
||||
#include "Cubed/tools/arg_parser.hpp"
|
||||
@@ -16,16 +17,10 @@ App::App()
|
||||
|
||||
: m_game_config(ASSETS_PATH "config.toml"),
|
||||
m_texture_manager(m_game_config), m_audio(m_game_config),
|
||||
m_client_world(m_audio, m_game_config), m_dev_panel(*this),
|
||||
m_renderer(m_camera, m_client_world, m_texture_manager, m_dev_panel,
|
||||
m_game_config),
|
||||
m_window(m_renderer, m_game_config) {}
|
||||
m_renderer(m_texture_manager, m_game_config), m_window(m_game_config),
|
||||
m_scene_manager(*this) {}
|
||||
|
||||
App::~App() {
|
||||
if (m_client) {
|
||||
m_client->stop();
|
||||
}
|
||||
}
|
||||
App::~App() {}
|
||||
void App::cursor_position_callback(GLFWwindow* window, double xpos,
|
||||
double ypos) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
@@ -38,7 +33,8 @@ void App::cursor_position_callback(GLFWwindow* window, double xpos,
|
||||
return;
|
||||
}
|
||||
if (!app->m_window.is_mouse_enable()) {
|
||||
app->m_camera.update_cursor_position_camera(xpos, ypos);
|
||||
app->m_scene_manager.handle_event(
|
||||
MouseMoveEvent{static_cast<float>(xpos), static_cast<float>(ypos)});
|
||||
}
|
||||
}
|
||||
void App::init(int argc, char** argv) {
|
||||
@@ -60,6 +56,8 @@ void App::init(int argc, char** argv) {
|
||||
window_focus_callback);
|
||||
glfwSetWindowSizeCallback(m_window.get_glfw_window(),
|
||||
window_reshape_callback);
|
||||
glfwSetFramebufferSizeCallback(m_window.get_glfw_window(),
|
||||
framebuffer_size_callback);
|
||||
glfwSetKeyCallback(m_window.get_glfw_window(), key_callback);
|
||||
glfwSetScrollCallback(m_window.get_glfw_window(), mouse_scroll_callback);
|
||||
glfwSetCursorEnterCallback(m_window.get_glfw_window(),
|
||||
@@ -72,7 +70,6 @@ void App::init(int argc, char** argv) {
|
||||
BlockManager::init();
|
||||
m_renderer.init(m_argument.debug_on);
|
||||
Logger::info("Renderer Init Success");
|
||||
m_window.update_viewport();
|
||||
// MapTable::init_map();
|
||||
m_texture_manager.init_texture();
|
||||
Logger::info("Texture Load Success");
|
||||
@@ -80,16 +77,19 @@ void App::init(int argc, char** argv) {
|
||||
m_server.start_server(m_argument.port);
|
||||
}
|
||||
|
||||
m_client = std::make_shared<NetworkClient>(m_client_world);
|
||||
m_scene_manager.request_push(SceneType::MAIN_MENU);
|
||||
|
||||
m_client->start(m_argument.ip, m_argument.port);
|
||||
// init will send packet
|
||||
m_client_world.init(m_argument.player, m_client);
|
||||
{
|
||||
int w, h;
|
||||
glfwGetWindowSize(m_window.get_glfw_window(), &w, &h);
|
||||
window_reshape_callback(m_window.get_glfw_window(), w, h);
|
||||
}
|
||||
|
||||
Logger::info("World Init Success");
|
||||
|
||||
m_camera.camera_init(&m_client_world.get_player());
|
||||
m_dev_panel.init();
|
||||
{
|
||||
int w, h;
|
||||
glfwGetFramebufferSize(m_window.get_glfw_window(), &w, &h);
|
||||
framebuffer_size_callback(m_window.get_glfw_window(), w, h);
|
||||
}
|
||||
}
|
||||
|
||||
void App::handle_argument(int argc, char** argv) {
|
||||
@@ -179,49 +179,357 @@ void App::key_callback(GLFWwindow* window, int key, int scancode, int action,
|
||||
// ImGui_ImplGlfw_CursorEnterCallback(window,
|
||||
// !app->m_window.is_mouse_enable());
|
||||
if (io.WantCaptureKeyboard && app->m_window.is_mouse_enable()) {
|
||||
if ((key == GLFW_KEY_LEFT_ALT || key == GLFW_KEY_ESCAPE) &&
|
||||
action == GLFW_PRESS) {
|
||||
app->m_window.toggle_mouse_able();
|
||||
app->m_camera.reset_camera();
|
||||
if ((key == GLFW_KEY_LEFT_ALT) && action == GLFW_PRESS) {
|
||||
app->dispatch_event(KeyEvent{Key::LEFT_ALT, KeyAction::PRESS});
|
||||
return;
|
||||
}
|
||||
ImGui_ImplGlfw_KeyCallback(window, key, scancode, action, mods);
|
||||
return;
|
||||
}
|
||||
Key pkey;
|
||||
KeyAction act;
|
||||
switch (key) {
|
||||
// Letter keys
|
||||
case GLFW_KEY_A:
|
||||
pkey = Key::A;
|
||||
break;
|
||||
case GLFW_KEY_B:
|
||||
pkey = Key::B;
|
||||
break;
|
||||
case GLFW_KEY_C:
|
||||
pkey = Key::C;
|
||||
break;
|
||||
case GLFW_KEY_D:
|
||||
pkey = Key::D;
|
||||
break;
|
||||
case GLFW_KEY_E:
|
||||
pkey = Key::E;
|
||||
break;
|
||||
case GLFW_KEY_F:
|
||||
pkey = Key::F;
|
||||
break;
|
||||
case GLFW_KEY_G:
|
||||
pkey = Key::G;
|
||||
break;
|
||||
case GLFW_KEY_H:
|
||||
pkey = Key::H;
|
||||
break;
|
||||
case GLFW_KEY_I:
|
||||
pkey = Key::I;
|
||||
break;
|
||||
case GLFW_KEY_J:
|
||||
pkey = Key::J;
|
||||
break;
|
||||
case GLFW_KEY_K:
|
||||
pkey = Key::K;
|
||||
break;
|
||||
case GLFW_KEY_L:
|
||||
pkey = Key::L;
|
||||
break;
|
||||
case GLFW_KEY_M:
|
||||
pkey = Key::M;
|
||||
break;
|
||||
case GLFW_KEY_N:
|
||||
pkey = Key::N;
|
||||
break;
|
||||
case GLFW_KEY_O:
|
||||
pkey = Key::O;
|
||||
break;
|
||||
case GLFW_KEY_P:
|
||||
pkey = Key::P;
|
||||
break;
|
||||
case GLFW_KEY_Q:
|
||||
if (action == GLFW_PRESS) {
|
||||
}
|
||||
break;
|
||||
case GLFW_KEY_ESCAPE:
|
||||
if (action == GLFW_PRESS) {
|
||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||
}
|
||||
break;
|
||||
case GLFW_KEY_F11:
|
||||
if (action == GLFW_PRESS) {
|
||||
app->m_window.toggle_fullscreen();
|
||||
}
|
||||
pkey = Key::Q;
|
||||
break;
|
||||
case GLFW_KEY_R:
|
||||
if (action == GLFW_PRESS) {
|
||||
app->m_texture_manager.need_reload();
|
||||
}
|
||||
pkey = Key::R;
|
||||
break;
|
||||
case GLFW_KEY_LEFT_ALT:
|
||||
if (action == GLFW_PRESS) {
|
||||
app->m_window.toggle_mouse_able();
|
||||
app->m_camera.reset_camera();
|
||||
}
|
||||
case GLFW_KEY_S:
|
||||
pkey = Key::S;
|
||||
break;
|
||||
case GLFW_KEY_T:
|
||||
pkey = Key::T;
|
||||
break;
|
||||
case GLFW_KEY_U:
|
||||
pkey = Key::U;
|
||||
break;
|
||||
case GLFW_KEY_V:
|
||||
pkey = Key::V;
|
||||
break;
|
||||
case GLFW_KEY_W:
|
||||
pkey = Key::W;
|
||||
break;
|
||||
case GLFW_KEY_X:
|
||||
pkey = Key::X;
|
||||
break;
|
||||
case GLFW_KEY_Y:
|
||||
pkey = Key::Y;
|
||||
break;
|
||||
case GLFW_KEY_Z:
|
||||
pkey = Key::Z;
|
||||
break;
|
||||
|
||||
// Digit keys (main keyboard area)
|
||||
case GLFW_KEY_0:
|
||||
pkey = Key::DIGIT_0;
|
||||
break;
|
||||
case GLFW_KEY_1:
|
||||
pkey = Key::DIGIT_1;
|
||||
break;
|
||||
case GLFW_KEY_2:
|
||||
pkey = Key::DIGIT_2;
|
||||
break;
|
||||
case GLFW_KEY_3:
|
||||
pkey = Key::DIGIT_3;
|
||||
break;
|
||||
case GLFW_KEY_4:
|
||||
pkey = Key::DIGIT_4;
|
||||
break;
|
||||
case GLFW_KEY_5:
|
||||
pkey = Key::DIGIT_5;
|
||||
break;
|
||||
case GLFW_KEY_6:
|
||||
pkey = Key::DIGIT_6;
|
||||
break;
|
||||
case GLFW_KEY_7:
|
||||
pkey = Key::DIGIT_7;
|
||||
break;
|
||||
case GLFW_KEY_8:
|
||||
pkey = Key::DIGIT_8;
|
||||
break;
|
||||
case GLFW_KEY_9:
|
||||
pkey = Key::DIGIT_9;
|
||||
break;
|
||||
|
||||
// Function keys
|
||||
case GLFW_KEY_F1:
|
||||
pkey = Key::F1;
|
||||
break;
|
||||
case GLFW_KEY_F2:
|
||||
pkey = Key::F2;
|
||||
break;
|
||||
case GLFW_KEY_F3:
|
||||
pkey = Key::F3;
|
||||
break;
|
||||
case GLFW_KEY_F4:
|
||||
pkey = Key::F4;
|
||||
break;
|
||||
case GLFW_KEY_F5:
|
||||
if (action == GLFW_PRESS) {
|
||||
app->m_camera.change_perspective();
|
||||
}
|
||||
pkey = Key::F5;
|
||||
break;
|
||||
case GLFW_KEY_F6:
|
||||
pkey = Key::F6;
|
||||
break;
|
||||
case GLFW_KEY_F7:
|
||||
pkey = Key::F7;
|
||||
break;
|
||||
case GLFW_KEY_F8:
|
||||
pkey = Key::F8;
|
||||
break;
|
||||
case GLFW_KEY_F9:
|
||||
pkey = Key::F9;
|
||||
break;
|
||||
case GLFW_KEY_F10:
|
||||
pkey = Key::F10;
|
||||
break;
|
||||
case GLFW_KEY_F11:
|
||||
pkey = Key::F11;
|
||||
break;
|
||||
case GLFW_KEY_F12:
|
||||
pkey = Key::F12;
|
||||
break;
|
||||
|
||||
// Control keys
|
||||
case GLFW_KEY_BACKSPACE:
|
||||
pkey = Key::BACKSPACE;
|
||||
break;
|
||||
case GLFW_KEY_TAB:
|
||||
pkey = Key::TAB;
|
||||
break;
|
||||
case GLFW_KEY_ENTER:
|
||||
pkey = Key::ENTER;
|
||||
break;
|
||||
case GLFW_KEY_ESCAPE:
|
||||
pkey = Key::ESCAPE;
|
||||
break;
|
||||
case GLFW_KEY_SPACE:
|
||||
pkey = Key::SPACE;
|
||||
break;
|
||||
case GLFW_KEY_CAPS_LOCK:
|
||||
pkey = Key::CAPS_LOCK;
|
||||
break;
|
||||
case GLFW_KEY_NUM_LOCK:
|
||||
pkey = Key::NUM_LOCK;
|
||||
break;
|
||||
case GLFW_KEY_SCROLL_LOCK:
|
||||
pkey = Key::SCROLL_LOCK;
|
||||
break;
|
||||
|
||||
// Modifier keys
|
||||
case GLFW_KEY_LEFT_SHIFT:
|
||||
pkey = Key::LEFT_SHIFT;
|
||||
break;
|
||||
case GLFW_KEY_RIGHT_SHIFT:
|
||||
pkey = Key::RIGHT_SHIFT;
|
||||
break;
|
||||
case GLFW_KEY_LEFT_CONTROL:
|
||||
pkey = Key::LEFT_CTRL;
|
||||
break;
|
||||
case GLFW_KEY_RIGHT_CONTROL:
|
||||
pkey = Key::RIGHT_CTRL;
|
||||
break;
|
||||
case GLFW_KEY_LEFT_ALT:
|
||||
pkey = Key::LEFT_ALT;
|
||||
break;
|
||||
case GLFW_KEY_RIGHT_ALT:
|
||||
pkey = Key::RIGHT_ALT;
|
||||
break;
|
||||
case GLFW_KEY_LEFT_SUPER:
|
||||
pkey = Key::LEFT_SUPER;
|
||||
break;
|
||||
case GLFW_KEY_RIGHT_SUPER:
|
||||
pkey = Key::RIGHT_SUPER;
|
||||
break;
|
||||
|
||||
// Navigation keys
|
||||
case GLFW_KEY_INSERT:
|
||||
pkey = Key::INSERT;
|
||||
break;
|
||||
case GLFW_KEY_DELETE:
|
||||
pkey = Key::DELETE;
|
||||
break;
|
||||
case GLFW_KEY_HOME:
|
||||
pkey = Key::HOME;
|
||||
break;
|
||||
case GLFW_KEY_END:
|
||||
pkey = Key::END;
|
||||
break;
|
||||
case GLFW_KEY_PAGE_UP:
|
||||
pkey = Key::PAGE_UP;
|
||||
break;
|
||||
case GLFW_KEY_PAGE_DOWN:
|
||||
pkey = Key::PAGE_DOWN;
|
||||
break;
|
||||
case GLFW_KEY_LEFT:
|
||||
pkey = Key::LEFT;
|
||||
break;
|
||||
case GLFW_KEY_RIGHT:
|
||||
pkey = Key::RIGHT;
|
||||
break;
|
||||
case GLFW_KEY_UP:
|
||||
pkey = Key::UP;
|
||||
break;
|
||||
case GLFW_KEY_DOWN:
|
||||
pkey = Key::DOWN;
|
||||
break;
|
||||
|
||||
// Lock and system keys
|
||||
case GLFW_KEY_PRINT_SCREEN:
|
||||
pkey = Key::PRINT_SCREEN;
|
||||
break;
|
||||
case GLFW_KEY_PAUSE:
|
||||
pkey = Key::PAUSE;
|
||||
break;
|
||||
|
||||
// Main keyboard area symbol keys
|
||||
case GLFW_KEY_GRAVE_ACCENT:
|
||||
pkey = Key::GRAVE_ACCENT;
|
||||
break;
|
||||
case GLFW_KEY_MINUS:
|
||||
pkey = Key::MINUS;
|
||||
break;
|
||||
case GLFW_KEY_EQUAL:
|
||||
pkey = Key::EQUALS;
|
||||
break;
|
||||
case GLFW_KEY_LEFT_BRACKET:
|
||||
pkey = Key::LEFT_BRACKET;
|
||||
break;
|
||||
case GLFW_KEY_RIGHT_BRACKET:
|
||||
pkey = Key::RIGHT_BRACKET;
|
||||
break;
|
||||
case GLFW_KEY_BACKSLASH:
|
||||
pkey = Key::BACKSLASH;
|
||||
break;
|
||||
case GLFW_KEY_SEMICOLON:
|
||||
pkey = Key::SEMICOLON;
|
||||
break;
|
||||
case GLFW_KEY_APOSTROPHE:
|
||||
pkey = Key::APOSTROPHE;
|
||||
break;
|
||||
case GLFW_KEY_COMMA:
|
||||
pkey = Key::COMMA;
|
||||
break;
|
||||
case GLFW_KEY_PERIOD:
|
||||
pkey = Key::PERIOD;
|
||||
break;
|
||||
case GLFW_KEY_SLASH:
|
||||
pkey = Key::SLASH;
|
||||
break;
|
||||
|
||||
// Numpad area
|
||||
case GLFW_KEY_KP_0:
|
||||
pkey = Key::NUMPAD_0;
|
||||
break;
|
||||
case GLFW_KEY_KP_1:
|
||||
pkey = Key::NUMPAD_1;
|
||||
break;
|
||||
case GLFW_KEY_KP_2:
|
||||
pkey = Key::NUMPAD_2;
|
||||
break;
|
||||
case GLFW_KEY_KP_3:
|
||||
pkey = Key::NUMPAD_3;
|
||||
break;
|
||||
case GLFW_KEY_KP_4:
|
||||
pkey = Key::NUMPAD_4;
|
||||
break;
|
||||
case GLFW_KEY_KP_5:
|
||||
pkey = Key::NUMPAD_5;
|
||||
break;
|
||||
case GLFW_KEY_KP_6:
|
||||
pkey = Key::NUMPAD_6;
|
||||
break;
|
||||
case GLFW_KEY_KP_7:
|
||||
pkey = Key::NUMPAD_7;
|
||||
break;
|
||||
case GLFW_KEY_KP_8:
|
||||
pkey = Key::NUMPAD_8;
|
||||
break;
|
||||
case GLFW_KEY_KP_9:
|
||||
pkey = Key::NUMPAD_9;
|
||||
break;
|
||||
case GLFW_KEY_KP_ADD:
|
||||
pkey = Key::NUMPAD_ADD;
|
||||
break;
|
||||
case GLFW_KEY_KP_SUBTRACT:
|
||||
pkey = Key::NUMPAD_SUBTRACT;
|
||||
break;
|
||||
case GLFW_KEY_KP_MULTIPLY:
|
||||
pkey = Key::NUMPAD_MULTIPLY;
|
||||
break;
|
||||
case GLFW_KEY_KP_DIVIDE:
|
||||
pkey = Key::NUMPAD_DIVIDE;
|
||||
break;
|
||||
case GLFW_KEY_KP_DECIMAL:
|
||||
pkey = Key::NUMPAD_DECIMAL;
|
||||
break;
|
||||
case GLFW_KEY_KP_ENTER:
|
||||
pkey = Key::NUMPAD_ENTER;
|
||||
break;
|
||||
|
||||
default:
|
||||
Logger::error("Unknown Key {}", key);
|
||||
return;
|
||||
}
|
||||
|
||||
app->m_client_world.get_player().update_player_move_state(key, action);
|
||||
if (action == GLFW_PRESS) {
|
||||
act = KeyAction::PRESS;
|
||||
} else if (action == GLFW_RELEASE) {
|
||||
act = KeyAction::RELEASE;
|
||||
} else {
|
||||
act = KeyAction::REPEAT;
|
||||
}
|
||||
|
||||
app->dispatch_event(KeyEvent{pkey, act});
|
||||
}
|
||||
|
||||
void App::mouse_button_callback(GLFWwindow* window, int button, int action,
|
||||
@@ -233,30 +541,46 @@ void App::mouse_button_callback(GLFWwindow* window, int button, int action,
|
||||
ImGui_ImplGlfw_MouseButtonCallback(window, button, action, mods);
|
||||
return;
|
||||
}
|
||||
MouseKey key;
|
||||
KeyAction act;
|
||||
switch (button) {
|
||||
case GLFW_MOUSE_BUTTON_LEFT:
|
||||
if (action == GLFW_PRESS) {
|
||||
if (app->m_window.is_mouse_enable()) {
|
||||
app->m_window.toggle_mouse_able();
|
||||
app->m_camera.reset_camera();
|
||||
break;
|
||||
;
|
||||
}
|
||||
Input::get_input_state().mouse_state.left = true;
|
||||
}
|
||||
if (action == GLFW_RELEASE) {
|
||||
Input::get_input_state().mouse_state.left = false;
|
||||
}
|
||||
key = MouseKey::LEFT_BUTTON;
|
||||
break;
|
||||
case GLFW_MOUSE_BUTTON_RIGHT:
|
||||
if (action == GLFW_PRESS) {
|
||||
Input::get_input_state().mouse_state.right = true;
|
||||
}
|
||||
if (action == GLFW_RELEASE) {
|
||||
Input::get_input_state().mouse_state.right = false;
|
||||
}
|
||||
key = MouseKey::RIGHT_BUTTON;
|
||||
break;
|
||||
case GLFW_MOUSE_BUTTON_MIDDLE:
|
||||
key = MouseKey::MIDDLE_BUTTON;
|
||||
break;
|
||||
case GLFW_MOUSE_BUTTON_4:
|
||||
key = MouseKey::BACK_BUTTON;
|
||||
break;
|
||||
case GLFW_MOUSE_BUTTON_5:
|
||||
key = MouseKey::FORWARD_BUTTON;
|
||||
break;
|
||||
case GLFW_MOUSE_BUTTON_6:
|
||||
key = MouseKey::EXTRA_BUTTON_1;
|
||||
break;
|
||||
case GLFW_MOUSE_BUTTON_7:
|
||||
key = MouseKey::EXTRA_BUTTON_2;
|
||||
break;
|
||||
case GLFW_MOUSE_BUTTON_8:
|
||||
key = MouseKey::EXTRA_BUTTON_3;
|
||||
break;
|
||||
default:
|
||||
Logger::error("Unknown Mouse Button {}", button);
|
||||
return;
|
||||
}
|
||||
if (action == GLFW_PRESS) {
|
||||
act = KeyAction::PRESS;
|
||||
} else if (action == GLFW_RELEASE) {
|
||||
act = KeyAction::RELEASE;
|
||||
} else {
|
||||
act = KeyAction::REPEAT;
|
||||
}
|
||||
|
||||
app->dispatch_event(MouseButtonEvent{key, act});
|
||||
}
|
||||
|
||||
void App::window_focus_callback(GLFWwindow* window, int focused) {
|
||||
@@ -268,17 +592,29 @@ void App::window_focus_callback(GLFWwindow* window, int focused) {
|
||||
return;
|
||||
}
|
||||
if (focused) {
|
||||
app->m_camera.reset_camera();
|
||||
auto camera = app->m_window.camera();
|
||||
if (camera) {
|
||||
camera->reset_camera();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void App::window_reshape_callback(GLFWwindow* window, int, int) {
|
||||
void App::window_reshape_callback(GLFWwindow* window, int width, int height) {
|
||||
|
||||
App* app = static_cast<App*>(glfwGetWindowUserPointer(window));
|
||||
ASSERT_MSG(app, "nullptr");
|
||||
app->m_window.update_viewport();
|
||||
}
|
||||
|
||||
app->dispatch_event(WindowResizeEvent{width, height});
|
||||
|
||||
Logger::info("Window Reshape W: {} H: {}", width, height);
|
||||
}
|
||||
void App::framebuffer_size_callback(GLFWwindow* window, int width, int height) {
|
||||
App* app = static_cast<App*>(glfwGetWindowUserPointer(window));
|
||||
ASSERT_MSG(app, "nullptr");
|
||||
app->dispatch_event(FrameBufferResizeEvent{width, height});
|
||||
|
||||
Logger::info("Frame Buffer Reshape W: {} H: {}", width, height);
|
||||
}
|
||||
void App::mouse_scroll_callback(GLFWwindow* window, double xoffset,
|
||||
double yoffset) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
@@ -289,8 +625,7 @@ void App::mouse_scroll_callback(GLFWwindow* window, double xoffset,
|
||||
ImGui_ImplGlfw_ScrollCallback(window, xoffset, yoffset);
|
||||
return;
|
||||
}
|
||||
auto& player = app->m_client_world.get_player();
|
||||
player.update_scroll(yoffset);
|
||||
app->dispatch_event(MouseWheelEvent(static_cast<float>(yoffset)));
|
||||
}
|
||||
|
||||
void App::cursor_enter_callback(GLFWwindow* window, int entered) {
|
||||
@@ -318,8 +653,9 @@ void App::render() {
|
||||
ImGui_ImplGlfw_Sleep(10);
|
||||
return;
|
||||
}
|
||||
m_renderer.render();
|
||||
|
||||
m_renderer.begin_frame();
|
||||
m_scene_manager.render(m_renderer);
|
||||
m_renderer.end_frame();
|
||||
glfwSwapBuffers(m_window.get_glfw_window());
|
||||
}
|
||||
|
||||
@@ -327,20 +663,37 @@ void App::run() {
|
||||
|
||||
last_time = glfwGetTime();
|
||||
while (!glfwWindowShouldClose(m_window.get_glfw_window())) {
|
||||
if (m_client_world.is_receive_exit()) {
|
||||
break;
|
||||
}
|
||||
// if (m_client_world.is_receive_exit()) {
|
||||
// break;
|
||||
// }
|
||||
update();
|
||||
render();
|
||||
}
|
||||
m_client_world.request_exit();
|
||||
|
||||
if (!m_argument.is_client) {
|
||||
m_server.server_world().stop();
|
||||
}
|
||||
}
|
||||
static Gait player_gait = Gait::WALK;
|
||||
// static Gait player_gait = Gait::WALK;
|
||||
void App::update() {
|
||||
glfwPollEvents();
|
||||
{
|
||||
int w, h;
|
||||
glfwGetFramebufferSize(m_window.get_glfw_window(), &w, &h);
|
||||
|
||||
if (w != m_renderer.frame_width() || h != m_renderer.frame_height()) {
|
||||
dispatch_event(FrameBufferResizeEvent{w, h});
|
||||
}
|
||||
}
|
||||
{
|
||||
int w, h;
|
||||
glfwGetWindowSize(m_window.get_glfw_window(), &w, &h);
|
||||
|
||||
if (w != m_renderer.window_width() || h != m_renderer.window_height()) {
|
||||
dispatch_event(WindowResizeEvent{w, h});
|
||||
}
|
||||
}
|
||||
|
||||
current_time = glfwGetTime();
|
||||
dt = current_time - last_time;
|
||||
last_time = current_time;
|
||||
@@ -359,23 +712,30 @@ void App::update() {
|
||||
std::format("RSS: {}mb", Tools::get_current_rss() / (1024 * 1024)));
|
||||
}
|
||||
m_texture_manager.update();
|
||||
m_client_world.update(dt);
|
||||
m_camera.update_move_camera();
|
||||
const auto& player = m_client_world.get_player();
|
||||
if (player_gait != player.get_gait()) {
|
||||
player_gait = player.get_gait();
|
||||
float fov = m_game_config.get("player.fov", 70.0f);
|
||||
if (player_gait == Gait::WALK) {
|
||||
m_renderer.update_fov(fov);
|
||||
}
|
||||
if (player_gait == Gait::RUN) {
|
||||
m_renderer.update_fov(fov + 5.0f);
|
||||
}
|
||||
}
|
||||
m_audio.update_listener(m_camera.get_camera_pos(),
|
||||
m_camera.get_camera_front(), glm::vec3(0, 1, 0));
|
||||
|
||||
m_audio.update();
|
||||
DebugCollector::get().get_widget().update(dt);
|
||||
m_renderer.update(dt);
|
||||
|
||||
m_scene_manager.update(dt);
|
||||
}
|
||||
|
||||
void App::dispatch_event(const Event& e) {
|
||||
if (m_window.handle_event(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_texture_manager.handle_event(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_renderer.handle_event(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_scene_manager.handle_event(e)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int App::start_cubed_application(int argc, char** argv) {
|
||||
@@ -401,14 +761,11 @@ float App::delta_time() { return dt; }
|
||||
|
||||
float App::get_fps() { return fps; }
|
||||
|
||||
Camera& App::camera() { return m_camera; }
|
||||
DevPanel& App::dev_panel() { return m_dev_panel; }
|
||||
Renderer& App::renderer() { return m_renderer; }
|
||||
TextureManager& App::texture_manager() { return m_texture_manager; }
|
||||
Window& App::window() { return m_window; }
|
||||
ClientWorld& App::client_world() { return m_client_world; }
|
||||
ServerWorld& App::server_world() { return m_server.server_world(); }
|
||||
Config& App::config() { return m_game_config; }
|
||||
const App::Argument& App::argument() const { return m_argument; }
|
||||
const Argument& App::argument() const { return m_argument; }
|
||||
AudioEngine& App::audio() { return m_audio; }
|
||||
} // namespace Cubed
|
||||
@@ -115,6 +115,32 @@ bool Camera::is_first_person() const {
|
||||
return m_perspective == Perspective::FIRST_PERSON;
|
||||
}
|
||||
|
||||
bool Camera::handle_event(const Event& e) {
|
||||
return std::visit(
|
||||
Overloaded{[this](const MouseMoveEvent& e) {
|
||||
if (handle_mouse_move_event(e)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
[](const MouseButtonEvent&) { return false; },
|
||||
[](const MouseWheelEvent&) { return false; },
|
||||
[this](const KeyEvent& e) {
|
||||
if (handle_key_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[](const TextInputEvent&) { return false; },
|
||||
[](const WindowResizeEvent&) { return false; },
|
||||
[](const FrameBufferResizeEvent&) { return false; }
|
||||
|
||||
} // namespace Cubed
|
||||
,
|
||||
e);
|
||||
}
|
||||
|
||||
glm::vec3 Camera::camera_collision(glm::vec3 start, glm::vec3 end,
|
||||
float radius) {
|
||||
constexpr float STEP = 0.05f;
|
||||
@@ -136,4 +162,20 @@ glm::vec3 Camera::camera_collision(glm::vec3 start, glm::vec3 end,
|
||||
return end;
|
||||
}
|
||||
|
||||
bool Camera::handle_key_event(const KeyEvent& e) {
|
||||
if (e.key == Key::LEFT_ALT && e.action == KeyAction::PRESS) {
|
||||
reset_camera();
|
||||
return true;
|
||||
}
|
||||
if (e.key == Key::F5 && e.action == KeyAction::PRESS) {
|
||||
change_perspective();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Camera::handle_mouse_move_event(const MouseMoveEvent& e) {
|
||||
update_cursor_position_camera(e.xpos, e.ypos);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -1,101 +1,150 @@
|
||||
#include "Cubed/debug_collector.hpp"
|
||||
|
||||
#include "Cubed/tools/cubed_hash.hpp"
|
||||
#include "Cubed/tools/system_info.hpp"
|
||||
#include "version.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
DebugCollector::DebugCollector() {}
|
||||
DebugCollector::DebugCollector() : m_widget(nullptr) {}
|
||||
|
||||
DebugCollector& DebugCollector::get() {
|
||||
static DebugCollector instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void DebugCollector::init_text() {
|
||||
Text version_text("version");
|
||||
Text fps_text("fps");
|
||||
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");
|
||||
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.position(0.0f, 100.0f)
|
||||
.scale(0.8f)
|
||||
.color(Color::WHITE)
|
||||
.text(version);
|
||||
fps_text.position(0.0f, 50.0f).text("FPS: 0");
|
||||
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");
|
||||
os_text.scale(0.8f).position(0.0f, 250.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_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(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(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(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(SCALE);
|
||||
if (Tools::get_os_version(os)) {
|
||||
os_text.text("OS: " + os);
|
||||
os_text.set_text("OS: " + os);
|
||||
Logger::info("System: {}", os);
|
||||
} else {
|
||||
os_text.text("OS: Unknown");
|
||||
os_text.set_text("OS: Unknown");
|
||||
}
|
||||
cpu_text.text("CPU: " + Tools::get_cpu_info())
|
||||
.scale(0.7f)
|
||||
.position(0.0f, 350.0f);
|
||||
m_component.try_emplace(os_text.id(), &os_text);
|
||||
|
||||
// cpu
|
||||
auto& cpu_text = m_widget.add_child<Label>("cpu");
|
||||
cpu_text.set_text("CPU: " + Tools::get_cpu_info()).set_scale(SCALE);
|
||||
m_component.try_emplace(cpu_text.id(), &cpu_text);
|
||||
|
||||
// gpu
|
||||
auto& gpu_text = m_widget.add_child<Label>("gpu");
|
||||
gpu_text
|
||||
.text(std::string{"GPU: "} +
|
||||
reinterpret_cast<const char*>(glGetString(GL_RENDERER)))
|
||||
.scale(0.7f)
|
||||
.position(0.0f, 400.0f);
|
||||
.set_text(std::string{"GPU: "} +
|
||||
reinterpret_cast<const char*>(glGetString(GL_RENDERER)))
|
||||
.set_scale(SCALE);
|
||||
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
|
||||
.text("OpenGL: " + std::to_string(GLVersion.major) + "." +
|
||||
std::to_string(GLVersion.minor))
|
||||
.scale(0.7f)
|
||||
.position(0.0f, 450.0f);
|
||||
biome_text.text("Biome: ").scale(0.8f).position(0.0f, 500.0f);
|
||||
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)});
|
||||
m_texts.insert({fps_text.uuid(), std::move(fps_text)});
|
||||
m_texts.insert({player_pos_text.uuid(), std::move(player_pos_text)});
|
||||
m_texts.insert(
|
||||
{rendered_chunk_text.uuid(), std::move(rendered_chunk_text)});
|
||||
m_texts.insert({os_text.uuid(), std::move(os_text)});
|
||||
m_texts.insert({rss_text.uuid(), std::move(rss_text)});
|
||||
m_texts.insert({cpu_text.uuid(), std::move(cpu_text)});
|
||||
m_texts.insert({gpu_text.uuid(), std::move(gpu_text)});
|
||||
m_texts.insert(
|
||||
{opengl_version_text.uuid(), std::move(opengl_version_text)});
|
||||
m_texts.insert({biome_text.uuid(), std::move(biome_text)});
|
||||
m_texts.insert({speed_text.uuid(), std::move(speed_text)});
|
||||
.set_text("OpenGL: " + std::to_string(GLVersion.major) + "." +
|
||||
std::to_string(GLVersion.minor))
|
||||
.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(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(SCALE);
|
||||
m_component.try_emplace(speed_text.id(), &speed_text);
|
||||
}
|
||||
|
||||
std::unordered_map<std::size_t, Text>& DebugCollector::all_texts() {
|
||||
return m_texts;
|
||||
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);
|
||||
}
|
||||
|
||||
Text& DebugCollector::text(std::string_view name) {
|
||||
std::size_t id = HASH::str(name);
|
||||
auto it = m_texts.find(id);
|
||||
ASSERT_MSG(it != m_texts.end(), "Can't Find Text");
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void DebugCollector::report(std::string_view name, std::string_view content) {
|
||||
auto& t = text(name);
|
||||
t.text(content);
|
||||
void DebugCollector::report(const std::string& name, std::string_view content) {
|
||||
auto t = m_component.find(name);
|
||||
if (t == m_component.end()) {
|
||||
return;
|
||||
}
|
||||
if (!t->second) {
|
||||
return;
|
||||
}
|
||||
t->second->set_text(content);
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Cubed/gameplay/cave_path.hpp"
|
||||
#include "Cubed/gameplay/client_player.hpp"
|
||||
#include "Cubed/gameplay/river.path.hpp"
|
||||
#include "Cubed/scene/world_scene.hpp"
|
||||
#include "Cubed/tools/log.hpp"
|
||||
|
||||
#include <imgui.h>
|
||||
@@ -46,10 +47,12 @@ constexpr float DELTA_ANGLE_MAX = 30.0f;
|
||||
constexpr int PATH_STEP_MIN = 1;
|
||||
constexpr int PATH_STEP_MAX = 1000;
|
||||
|
||||
DevPanel::DevPanel(App& app) : m_app(app), m_config(app.config()) {}
|
||||
DevPanel::DevPanel(WorldScene& world_scene)
|
||||
: m_app(world_scene.scene_manager().app()), m_world_scene(world_scene),
|
||||
m_config(m_app.config()) {}
|
||||
|
||||
void DevPanel::init() {
|
||||
m_player = &m_app.client_world().get_player();
|
||||
m_player = &m_world_scene.client_world().get_player();
|
||||
update_config_view();
|
||||
update_player_profile();
|
||||
}
|
||||
@@ -383,7 +386,7 @@ void DevPanel::show_settings_tab_item() {
|
||||
128)) {
|
||||
m_config.set("world.rendering_distance",
|
||||
m_config_view.rendering_distance);
|
||||
m_app.client_world().hot_reload();
|
||||
m_world_scene.client_world().hot_reload();
|
||||
}
|
||||
if (ImGui::Checkbox("Fullscreen", &m_config_view.fullscreen)) {
|
||||
m_config.set("window.fullscreen", m_config_view.fullscreen);
|
||||
@@ -551,20 +554,23 @@ void DevPanel::show_server_world_table_bar() {
|
||||
}
|
||||
void DevPanel::show_client_world_table_bar() {
|
||||
|
||||
static int rendering_distance = m_app.client_world().rendering_distance();
|
||||
static int rendering_distance =
|
||||
m_world_scene.client_world().rendering_distance();
|
||||
if (ImGui::SliderInt("Render Distance", &rendering_distance, 2, 128)) {
|
||||
m_app.client_world().rendering_distance(rendering_distance);
|
||||
m_world_scene.client_world().rendering_distance(rendering_distance);
|
||||
// Config::get().set("world.rendering_distance", rendering_distance);
|
||||
}
|
||||
if (ImGui::Button("Rebuild World")) {
|
||||
m_app.client_world().rebuild_world();
|
||||
m_world_scene.client_world().rebuild_world();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Spawn Point")) {
|
||||
m_player->set_player_pos({0.0f, 255.0f, 0.0f});
|
||||
}
|
||||
ImGui::Text("Chunk Task Id %d", m_app.client_world().get_chunk_task_id());
|
||||
ImGui::Text("Client World Chunk %d", m_app.client_world().chunk_size());
|
||||
ImGui::Text("Chunk Task Id %d",
|
||||
m_world_scene.client_world().get_chunk_task_id());
|
||||
ImGui::Text("Client World Chunk %d",
|
||||
m_world_scene.client_world().chunk_size());
|
||||
}
|
||||
|
||||
void DevPanel::show_player_tab_item() {
|
||||
@@ -649,7 +655,7 @@ void DevPanel::show_items_tab_item() {
|
||||
if (ImGui::BeginTabItem("item")) {
|
||||
ImGui::Text("Place Block ");
|
||||
ImGui::SameLine();
|
||||
auto& place_texture = textures[m_player->place_block()];
|
||||
auto& place_texture = textures[m_player->get_current_block()];
|
||||
if (place_texture) {
|
||||
ImGui::Image(static_cast<ImTextureID>(
|
||||
static_cast<intptr_t>(place_texture->id())),
|
||||
|
||||
@@ -132,7 +132,7 @@ void ClientPlayer::update(float delta_time) {
|
||||
m_gait = compute_gait();
|
||||
update_move(delta_time);
|
||||
update_lookup_block();
|
||||
|
||||
place_block(delta_time);
|
||||
DebugCollector::get().report("player_pos",
|
||||
std::format("x: {:.2f} y: {:.2f} z: {:.2f}",
|
||||
m_player_pos.x, m_player_pos.y,
|
||||
@@ -141,48 +141,42 @@ void ClientPlayer::update(float delta_time) {
|
||||
DebugCollector::get().report("speed",
|
||||
std::format("Speed: {:.2} m/s", m_xz_speed));
|
||||
}
|
||||
void ClientPlayer::update_player_move_state(int key, int action) {
|
||||
switch (key) {
|
||||
case GLFW_KEY_W:
|
||||
if (action == GLFW_PRESS) {
|
||||
bool ClientPlayer::update_player_move_state(Key key, KeyAction action) {
|
||||
if (key == Key::W) {
|
||||
if (action == KeyAction::PRESS) {
|
||||
m_move_state.forward = true;
|
||||
}
|
||||
if (action == GLFW_RELEASE) {
|
||||
if (action == KeyAction::RELEASE) {
|
||||
m_move_state.forward = false;
|
||||
|
||||
m_sprinting = false;
|
||||
}
|
||||
break;
|
||||
case GLFW_KEY_S:
|
||||
if (action == GLFW_PRESS) {
|
||||
} else if (key == Key::S) {
|
||||
if (action == KeyAction::PRESS) {
|
||||
m_move_state.back = true;
|
||||
}
|
||||
if (action == GLFW_RELEASE) {
|
||||
if (action == KeyAction::RELEASE) {
|
||||
m_move_state.back = false;
|
||||
}
|
||||
break;
|
||||
case GLFW_KEY_A:
|
||||
if (action == GLFW_PRESS) {
|
||||
} else if (key == Key::A) {
|
||||
if (action == KeyAction::PRESS) {
|
||||
m_move_state.left = true;
|
||||
}
|
||||
if (action == GLFW_RELEASE) {
|
||||
if (action == KeyAction::RELEASE) {
|
||||
m_move_state.left = false;
|
||||
}
|
||||
break;
|
||||
case GLFW_KEY_D:
|
||||
if (action == GLFW_PRESS) {
|
||||
} else if (key == Key::D) {
|
||||
if (action == KeyAction::PRESS) {
|
||||
m_move_state.right = true;
|
||||
}
|
||||
if (action == GLFW_RELEASE) {
|
||||
if (action == KeyAction::RELEASE) {
|
||||
m_move_state.right = false;
|
||||
}
|
||||
break;
|
||||
case GLFW_KEY_SPACE:
|
||||
if (action == GLFW_PRESS) {
|
||||
} else if (key == Key::SPACE) {
|
||||
if (action == KeyAction::PRESS) {
|
||||
m_move_state.up = true;
|
||||
if (space_on) {
|
||||
if (m_game_mode == CREATIVE) {
|
||||
is_fly = !is_fly ? true : false;
|
||||
is_fly = !is_fly;
|
||||
m_y_speed = 0.0f;
|
||||
}
|
||||
space_on = false;
|
||||
@@ -191,35 +185,39 @@ void ClientPlayer::update_player_move_state(int key, int action) {
|
||||
space_on = true;
|
||||
}
|
||||
}
|
||||
if (action == GLFW_RELEASE) {
|
||||
if (action == KeyAction::RELEASE) {
|
||||
m_move_state.up = false;
|
||||
}
|
||||
break;
|
||||
case GLFW_KEY_LEFT_SHIFT:
|
||||
if (action == GLFW_PRESS) {
|
||||
} else if (key == Key::LEFT_SHIFT) {
|
||||
if (action == KeyAction::PRESS) {
|
||||
m_move_state.down = true;
|
||||
}
|
||||
if (action == GLFW_RELEASE) {
|
||||
if (action == KeyAction::RELEASE) {
|
||||
m_move_state.down = false;
|
||||
}
|
||||
break;
|
||||
case GLFW_KEY_LEFT_CONTROL:
|
||||
if (action == GLFW_PRESS) {
|
||||
} else if (key == Key::LEFT_CTRL) {
|
||||
if (action == KeyAction::PRESS) {
|
||||
m_sprinting = true;
|
||||
}
|
||||
break;
|
||||
case GLFW_KEY_F4:
|
||||
if (action == GLFW_PRESS) {
|
||||
/*
|
||||
if (action == KeyAction::RELEASE) {
|
||||
m_sprinting = false;
|
||||
}*/
|
||||
} else if (key == Key::F4) {
|
||||
if (action == KeyAction::PRESS) {
|
||||
if (m_game_mode == CREATIVE) {
|
||||
change_mode(SPECTATOR);
|
||||
} else {
|
||||
change_mode(CREATIVE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_moving = m_move_state.forward || m_move_state.back || m_move_state.left ||
|
||||
m_move_state.right;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientPlayer::update_front_vec(float offset_x, float offset_y) {
|
||||
@@ -275,28 +273,34 @@ void ClientPlayer::update_lookup_block() {
|
||||
} else {
|
||||
m_look_block = std::nullopt;
|
||||
}
|
||||
}
|
||||
void ClientPlayer::place_block(float dt) {
|
||||
|
||||
if (m_look_block != std::nullopt) {
|
||||
if (Input::get_input_state().mouse_state.left) {
|
||||
if (m_world.is_solid(m_look_block->pos)) {
|
||||
m_world.report_block_change(m_look_block->pos, 0);
|
||||
}
|
||||
Input::get_input_state().mouse_state.left = false;
|
||||
if (m_look_block == std::nullopt) {
|
||||
return;
|
||||
}
|
||||
m_place_time += dt;
|
||||
if (m_place_time < PLACE_BLOCK_INTERVAL) {
|
||||
|
||||
return;
|
||||
}
|
||||
m_place_time = 0.0f;
|
||||
if (m_mouse_state.left) {
|
||||
if (m_world.is_solid(m_look_block->pos)) {
|
||||
m_world.report_block_change(m_look_block->pos, 0);
|
||||
}
|
||||
if (Input::get_input_state().mouse_state.right) {
|
||||
glm::ivec3 near_pos = m_look_block->pos + m_look_block->normal;
|
||||
if (!m_world.is_solid(near_pos)) {
|
||||
AABB block_box = ClientWorld::get_block_aabb(near_pos);
|
||||
AABB player_box = get_aabb(get_player_pos());
|
||||
if (!player_box.intersects(block_box)) {
|
||||
m_world.report_block_change(near_pos, m_place_block);
|
||||
}
|
||||
}
|
||||
if (m_mouse_state.right) {
|
||||
glm::ivec3 near_pos = m_look_block->pos + m_look_block->normal;
|
||||
if (!m_world.is_solid(near_pos)) {
|
||||
AABB block_box = ClientWorld::get_block_aabb(near_pos);
|
||||
AABB player_box = get_aabb(get_player_pos());
|
||||
if (!player_box.intersects(block_box)) {
|
||||
m_world.report_block_change(near_pos, m_place_block);
|
||||
}
|
||||
Input::get_input_state().mouse_state.right = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientPlayer::update_move(float delta_time) {
|
||||
// if frame rate less than 1 frame per second, don't update
|
||||
if (delta_time > 1.0f) {
|
||||
@@ -523,7 +527,7 @@ Gait ClientPlayer::compute_gait() const {
|
||||
return Gait::WALK;
|
||||
}
|
||||
|
||||
void ClientPlayer::update_scroll(double yoffset) {
|
||||
bool ClientPlayer::update_scroll(float yoffset) {
|
||||
if (m_game_mode == SPECTATOR) {
|
||||
if (yoffset > 0) {
|
||||
if (m_max_speed < 500.0f) {
|
||||
@@ -548,6 +552,47 @@ void ClientPlayer::update_scroll(double yoffset) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientPlayer::handle_mouse_button_event(const MouseButtonEvent& e) {
|
||||
if (e.action == KeyAction::PRESS) {
|
||||
if (e.key == MouseKey::LEFT_BUTTON) {
|
||||
m_mouse_state.left = true;
|
||||
m_place_time = PLACE_BLOCK_INTERVAL;
|
||||
return true;
|
||||
}
|
||||
if (e.key == MouseKey::RIGHT_BUTTON) {
|
||||
m_mouse_state.right = true;
|
||||
m_place_time = PLACE_BLOCK_INTERVAL;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (e.action == KeyAction::RELEASE) {
|
||||
if (e.key == MouseKey::LEFT_BUTTON) {
|
||||
m_mouse_state.left = false;
|
||||
return true;
|
||||
}
|
||||
if (e.key == MouseKey::RIGHT_BUTTON) {
|
||||
m_mouse_state.right = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ClientPlayer::handle_key_event(const KeyEvent& e) {
|
||||
if (update_player_move_state(e.key, e.action)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool ClientPlayer::handle_mouse_wheel_event(const MouseWheelEvent& e) {
|
||||
if (update_scroll(e.offset)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClientPlayer::update_chunk_set(const ChunkPosSet& set) {
|
||||
@@ -573,7 +618,7 @@ float& ClientPlayer::acceleration() { return m_acceleration; }
|
||||
float& ClientPlayer::deceleration() { return m_deceleration; }
|
||||
float& ClientPlayer::g() { return m_g; }
|
||||
float& ClientPlayer::fly_y_speed() { return m_fly_y_speed; }
|
||||
unsigned ClientPlayer::place_block() const { return m_place_block; };
|
||||
unsigned ClientPlayer::get_current_block() const { return m_place_block; };
|
||||
void ClientPlayer::set_gait(Gait gait) { m_gait = gait; }
|
||||
GameMode& ClientPlayer::game_mode() { return m_game_mode; }
|
||||
ClientWorld& ClientPlayer::get_world() { return m_world; }
|
||||
|
||||
@@ -21,8 +21,8 @@ struct ChunkRenderData {
|
||||
};
|
||||
} // namespace
|
||||
|
||||
ClientWorld::ClientWorld(AudioEngine& auido, Config& config)
|
||||
: m_player(*this), m_audio(auido), m_config(config) {}
|
||||
ClientWorld::ClientWorld(AudioEngine& auido, Config& config, WorldScene& scene)
|
||||
: m_player(*this), m_audio(auido), m_config(config), m_world_scene(scene) {}
|
||||
|
||||
ClientWorld::~ClientWorld() {
|
||||
m_client->close();
|
||||
@@ -718,6 +718,7 @@ AABB ClientWorld::get_block_aabb(const glm::ivec3& pos) {
|
||||
|
||||
AudioEngine& ClientWorld::get_audio() { return m_audio; }
|
||||
Config& ClientWorld::get_config() { return m_config; }
|
||||
WorldScene& ClientWorld::world_scene() { return m_world_scene; }
|
||||
|
||||
void ClientWorld::request_exit() {
|
||||
if (m_receive_exit) {
|
||||
@@ -905,6 +906,36 @@ void ClientWorld::update(float delta_time) {
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientWorld::handle_event(const Event& e) {
|
||||
return std::visit(
|
||||
Overloaded{[this](const MouseButtonEvent& e) {
|
||||
if (m_player.handle_mouse_button_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[](const MouseMoveEvent&) { return false; },
|
||||
[this](const MouseWheelEvent& e) {
|
||||
if (m_player.handle_mouse_wheel_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[this](const KeyEvent& e) {
|
||||
if (m_player.handle_key_event(e)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
[](const TextInputEvent&) { return false; },
|
||||
[](const WindowResizeEvent&) { return false; },
|
||||
[](const FrameBufferResizeEvent&) { return false; }
|
||||
|
||||
},
|
||||
e);
|
||||
}
|
||||
|
||||
glm::vec3 ClientWorld::sunlight_dir() const {
|
||||
float altitude = sin((m_day_tick - 6 * PER_HOUR) /
|
||||
static_cast<float>(DAY_TIME / 2) * std::numbers::pi) *
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#include "Cubed/input.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
static InputState input_state;
|
||||
|
||||
namespace Input {
|
||||
|
||||
InputState& get_input_state() { return input_state; }
|
||||
|
||||
} // namespace Input
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "Cubed/gameplay/client_world.hpp"
|
||||
#include "Cubed/primitive_data.hpp"
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/scene/world_scene.hpp"
|
||||
#include "Cubed/texture_manager.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
@@ -188,24 +189,24 @@ void PlayerRenderer::init() {
|
||||
m_inited = true;
|
||||
}
|
||||
|
||||
void PlayerRenderer::render(const Shader& shader) {
|
||||
void PlayerRenderer::render(const Shader& shader, ClientWorld& world) {
|
||||
if (!m_inited) {
|
||||
Logger::error("Player Renderer isn't init");
|
||||
return;
|
||||
}
|
||||
auto& m_camera = m_renderer.camera();
|
||||
auto& m_world = m_renderer.world();
|
||||
auto& m_player = m_world.get_player();
|
||||
glm::mat4 m_v_mat = m_camera.get_camera_lookat();
|
||||
|
||||
auto& camera = world.world_scene().camera();
|
||||
auto& m_player = world.get_player();
|
||||
glm::mat4 m_v_mat = camera.get_camera_lookat();
|
||||
glm::mat4 m_p_mat = m_renderer.world_proj_matrix();
|
||||
|
||||
auto& players = m_world.render_player_data();
|
||||
auto& players = world.render_player_data();
|
||||
shader.set_loc("proj_matrix", m_p_mat);
|
||||
|
||||
for (auto& player : players) {
|
||||
|
||||
if (player.uuid == m_player.get_uuid()) {
|
||||
if (m_camera.is_first_person()) {
|
||||
if (camera.is_first_person()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -302,15 +303,15 @@ void PlayerRenderer::render(const Shader& shader) {
|
||||
}
|
||||
|
||||
void PlayerRenderer::shadow_render(const Shader& shader,
|
||||
glm::mat4& light_matrix) {
|
||||
glm::mat4& light_matrix,
|
||||
ClientWorld& world) {
|
||||
if (!m_inited) {
|
||||
Logger::error("Player Renderer isn't init");
|
||||
return;
|
||||
}
|
||||
shader.use();
|
||||
shader.set_loc("lightSpaceMatrix", light_matrix);
|
||||
auto& m_world = m_renderer.world();
|
||||
auto& players = m_world.render_player_data();
|
||||
auto& players = world.render_player_data();
|
||||
|
||||
for (auto& player : players) {
|
||||
glm::mat4 model(1.0f);
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
|
||||
#include "Cubed/camera.hpp"
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/debug_collector.hpp"
|
||||
#include "Cubed/dev_panel.hpp"
|
||||
#include "Cubed/gameplay/client_player.hpp"
|
||||
#include "Cubed/gameplay/client_world.hpp"
|
||||
#include "Cubed/primitive_data.hpp"
|
||||
#include "Cubed/render/renderer_constants.hpp"
|
||||
#include "Cubed/texture_manager.hpp"
|
||||
@@ -19,12 +16,9 @@
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
Renderer::Renderer(const Camera& camera, ClientWorld& world,
|
||||
const TextureManager& texture_manager, DevPanel& dev_panel,
|
||||
Config& config)
|
||||
: m_camera(camera), m_dev_panel(dev_panel),
|
||||
m_texture_manager(texture_manager), m_world(world),
|
||||
m_world_renderer(*this), m_config(config) {}
|
||||
Renderer::Renderer(TextureManager& texture_manager, Config& config)
|
||||
: m_texture_manager(texture_manager), m_world_renderer(*this),
|
||||
m_config(config) {}
|
||||
|
||||
Renderer::~Renderer() {
|
||||
if (m_init) {
|
||||
@@ -99,8 +93,9 @@ void Renderer::init(bool debug_on) {
|
||||
m_vao[3].bind();
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
Vertex2D vex{SQUARE_VERTICES[i][0], SQUARE_VERTICES[i][1],
|
||||
SQUARE_TEXTURE_POS[i][0], SQUARE_TEXTURE_POS[i][1], 0};
|
||||
Vertex2D vex{SQUARE_VERTICES_TOP_LEFT[i][0],
|
||||
SQUARE_VERTICES_TOP_LEFT[i][1], SQUARE_TEXTURE_POS[i][0],
|
||||
SQUARE_TEXTURE_POS[i][1], 0};
|
||||
m_ui.emplace_back(vex);
|
||||
}
|
||||
m_ui_vbo->buffer_data(m_ui.data(), m_ui.size() * sizeof(Vertex2D));
|
||||
@@ -119,6 +114,7 @@ void Renderer::init(bool debug_on) {
|
||||
|
||||
VertexArray::unbind();
|
||||
VertexBuffer::unbind();
|
||||
|
||||
m_init = true;
|
||||
}
|
||||
|
||||
@@ -139,63 +135,93 @@ 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::render() {
|
||||
void Renderer::begin_frame() {
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
// clear screen
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
void Renderer::end_frame() {}
|
||||
|
||||
m_world_renderer.render();
|
||||
void Renderer::begin_render_ui() {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
render_ui();
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
void Renderer::end_render_ui() { glEnable(GL_DEPTH_TEST); }
|
||||
|
||||
render_text();
|
||||
|
||||
render_dev_panel();
|
||||
void Renderer::render_world(ClientWorld& world) {
|
||||
m_world_renderer.render(world);
|
||||
}
|
||||
|
||||
void Renderer::render_text() {
|
||||
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");
|
||||
|
||||
shader.use();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
shader.set_loc("projection", m_ui_proj_matrix);
|
||||
|
||||
auto& texts = DebugCollector::get().all_texts();
|
||||
for (auto& t : texts) {
|
||||
t.second.render(shader);
|
||||
}
|
||||
Font::text_texture()->bind(0);
|
||||
auto& data = label.data();
|
||||
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));
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
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);
|
||||
}
|
||||
|
||||
void Renderer::render_ui() {
|
||||
const auto& shader = get_shader("ui");
|
||||
void Renderer::render_image(const Image& image) {
|
||||
if (!image.texture()) {
|
||||
Logger::error("Image id {} not set image!", image.id());
|
||||
return;
|
||||
}
|
||||
const auto& shader = get_shader("image");
|
||||
shader.use();
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
shader.set_loc("m_matrix", m_ui_model_matrix);
|
||||
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.height(), 1.0f));
|
||||
shader.set_loc("model_matrix", model_matrix);
|
||||
shader.set_loc("proj_matrix", m_ui_proj_matrix);
|
||||
|
||||
m_vao[3].bind();
|
||||
m_texture_manager.get_ui_array()->bind(0);
|
||||
|
||||
image.texture()->bind(0);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
Tools::check_opengl_error();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void Renderer::update(float delta_time) { m_delta_time = delta_time; }
|
||||
@@ -207,20 +233,6 @@ void Renderer::update_fov(float fov) {
|
||||
glm::perspective(glm::radians(fov), m_aspect, NEAR_PLANE, FAR_PLANE);
|
||||
}
|
||||
|
||||
void Renderer::update_proj_matrix(float aspect, float width, float height) {
|
||||
m_aspect = aspect;
|
||||
|
||||
m_world_proj_matrix =
|
||||
glm::perspective(glm::radians(m_fov), aspect, NEAR_PLANE, FAR_PLANE);
|
||||
|
||||
m_ui_proj_matrix = glm::ortho(0.0f, width, height, 0.0f, -1.0f, 1.0f);
|
||||
// scale and then translate
|
||||
m_ui_model_matrix =
|
||||
glm::translate(glm::mat4(1.0f),
|
||||
glm::vec3(width / 2.0f, height / 2.0f, 0.0)) *
|
||||
glm::scale(glm::mat4(1.0f), glm::vec3(50.0f, 50.0f, 1.0f));
|
||||
}
|
||||
|
||||
void Renderer::updata_framebuffer(int width, int height) {
|
||||
if (width <= 0 || height <= 0)
|
||||
return;
|
||||
@@ -228,18 +240,55 @@ void Renderer::updata_framebuffer(int width, int height) {
|
||||
m_world_renderer.updata_framebuffer(width, height);
|
||||
|
||||
FrameBuffer::unbind();
|
||||
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
}
|
||||
|
||||
void Renderer::render_dev_panel() {
|
||||
|
||||
void Renderer::render_dev_panel(DevPanel& dev_panel) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
m_dev_panel.render();
|
||||
dev_panel.render();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
bool Renderer::handle_event(const Event& e) {
|
||||
return std::visit(Overloaded{[](const MouseMoveEvent&) { return false; },
|
||||
[](const MouseButtonEvent&) { return false; },
|
||||
[](const MouseWheelEvent&) { return false; },
|
||||
[](const KeyEvent&) { return false; },
|
||||
[](const TextInputEvent&) { return false; },
|
||||
[this](const WindowResizeEvent& e) {
|
||||
handle_window_resize_event(e);
|
||||
return false;
|
||||
},
|
||||
[this](const FrameBufferResizeEvent& e) {
|
||||
handle_frame_buffer_resize_event(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
},
|
||||
e);
|
||||
}
|
||||
bool Renderer::handle_window_resize_event(const WindowResizeEvent& e) {
|
||||
m_window_width = static_cast<float>(e.width);
|
||||
m_window_height = static_cast<float>(e.height);
|
||||
m_ui_proj_matrix =
|
||||
glm::ortho(0.0f, m_window_width, m_window_height, 0.0f, -1.0f, 1.0f);
|
||||
return false;
|
||||
}
|
||||
bool Renderer::handle_frame_buffer_resize_event(
|
||||
const FrameBufferResizeEvent& e) {
|
||||
int frame_height = e.height;
|
||||
int frame_width = e.width;
|
||||
m_frame_width = static_cast<float>(e.width);
|
||||
m_frame_height = static_cast<float>(e.height);
|
||||
m_aspect = m_frame_width / m_frame_height;
|
||||
glViewport(0, 0, frame_width, frame_height);
|
||||
m_world_proj_matrix =
|
||||
glm::perspective(glm::radians(m_fov), m_aspect, NEAR_PLANE, FAR_PLANE);
|
||||
updata_framebuffer(frame_width, frame_height);
|
||||
return false;
|
||||
}
|
||||
|
||||
float& Renderer::ambient_strength() {
|
||||
return m_world_renderer.ambient_strength();
|
||||
}
|
||||
@@ -277,9 +326,6 @@ float& Renderer::underwater_fog_density() {
|
||||
}
|
||||
float& Renderer::water_density() { return m_world_renderer.water_density(); }
|
||||
|
||||
const Camera& Renderer::camera() const { return m_camera; }
|
||||
const ClientWorld& Renderer::world() const { return m_world; }
|
||||
ClientWorld& Renderer::world() { return m_world; }
|
||||
const glm::mat4& Renderer::world_proj_matrix() const {
|
||||
return m_world_proj_matrix;
|
||||
}
|
||||
@@ -289,8 +335,10 @@ const TextureManager& Renderer::texture_mamger() const {
|
||||
|
||||
float Renderer::delta_time() const { return m_delta_time; }
|
||||
|
||||
float Renderer::height() const { return m_height; }
|
||||
float Renderer::width() const { return m_width; }
|
||||
float Renderer::window_height() const { return m_window_height; }
|
||||
float Renderer::window_width() const { return m_window_width; }
|
||||
float Renderer::frame_height() const { return m_frame_height; }
|
||||
float Renderer::frame_width() const { return m_frame_width; }
|
||||
const glm::mat4& Renderer::p_mat() const { return m_world_proj_matrix; }
|
||||
const std::vector<VertexArray>& Renderer::vao() const { return m_vao; }
|
||||
} // namespace Cubed
|
||||
@@ -13,8 +13,8 @@ void ShaderManager::init() {
|
||||
"shaders/outline_f_shader.glsl");
|
||||
register_shader("sky", "shaders/sky_v_shader.glsl",
|
||||
"shaders/sky_f_shader.glsl");
|
||||
register_shader("ui", "shaders/ui_v_shader.glsl",
|
||||
"shaders/ui_f_shader.glsl");
|
||||
register_shader("image", "shaders/image_v_shader.glsl",
|
||||
"shaders/image_f_shader.glsl");
|
||||
register_shader("text", "shaders/text_v_shader.glsl",
|
||||
"shaders/text_f_shader.glsl");
|
||||
register_shader("under_water", "shaders/under_water_v_shader.glsl",
|
||||
@@ -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,
|
||||
|
||||
@@ -48,8 +48,10 @@ void Texture::parameterfv(TexturePname pname, const float* param) const {
|
||||
}
|
||||
void Texture::tex_image_2d(TextureFormat internalformat, TextureFormat format,
|
||||
GLenum type, const void* data, GLsizei width,
|
||||
GLsizei height, GLint level, GLint border) const {
|
||||
GLsizei height, GLint level, GLint border) {
|
||||
bind();
|
||||
m_width = static_cast<float>(width);
|
||||
m_height = static_cast<float>(height);
|
||||
glTexImage2D(get_gl_texture_type(), level,
|
||||
std::to_underlying(internalformat), width, height, border,
|
||||
std::to_underlying(format), type, data);
|
||||
@@ -58,8 +60,10 @@ void Texture::tex_image_2d(TextureFormat internalformat, TextureFormat format,
|
||||
void Texture::tex_image_3d(TextureFormat internalformat, TextureFormat format,
|
||||
GLenum type, const void* data, GLsizei width,
|
||||
GLsizei height, GLsizei depth, GLint level,
|
||||
GLint border) const {
|
||||
GLint border) {
|
||||
bind();
|
||||
m_width = static_cast<float>(width);
|
||||
m_height = static_cast<float>(height);
|
||||
glTexImage3D(get_gl_texture_type(), level,
|
||||
std::to_underlying(internalformat), width, height, depth,
|
||||
border, std::to_underlying(format), type, data);
|
||||
@@ -135,7 +139,8 @@ void Texture::set_clamp_to_edge(bool r, bool s, bool t) const {
|
||||
}
|
||||
|
||||
TextureType Texture::type() const { return M_TYPE; }
|
||||
|
||||
float Texture::width() const { return m_width; }
|
||||
float Texture::height() const { return m_height; }
|
||||
void Texture::unbind() {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
#include "Cubed/gameplay/client_world.hpp"
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/render/renderer_constants.hpp"
|
||||
#include "Cubed/scene/world_scene.hpp"
|
||||
#include "Cubed/texture_manager.hpp"
|
||||
#include "Cubed/tools/math_tools.hpp"
|
||||
namespace Cubed {
|
||||
WorldRenderer::WorldRenderer(Renderer& renderer)
|
||||
: m_renderer(renderer), m_player_renderer(renderer),
|
||||
m_world(renderer.world()), m_camera(renderer.camera()),
|
||||
m_texture_manager(renderer.texture_mamger()) {}
|
||||
WorldRenderer::~WorldRenderer() {
|
||||
m_accum_texture.reset();
|
||||
@@ -30,21 +30,21 @@ WorldRenderer::~WorldRenderer() {
|
||||
|
||||
void WorldRenderer::init() { m_player_renderer.init(); }
|
||||
|
||||
void WorldRenderer::render() {
|
||||
void WorldRenderer::render(ClientWorld& world) {
|
||||
// update view matrix;
|
||||
view_matrix = m_renderer.camera().get_camera_lookat();
|
||||
view_matrix = world.world_scene().camera().get_camera_lookat();
|
||||
|
||||
m_world_fbo->bind();
|
||||
// clear world framebuffer
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
day_night_calculation();
|
||||
day_night_calculation(world);
|
||||
|
||||
render_sky();
|
||||
render_world();
|
||||
render_outline();
|
||||
render_player();
|
||||
render_sky(world);
|
||||
render_world(world);
|
||||
render_outline(world);
|
||||
render_player(world);
|
||||
|
||||
FrameBuffer::unbind();
|
||||
|
||||
@@ -55,13 +55,13 @@ void WorldRenderer::render() {
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
render_underwater();
|
||||
render_underwater(world);
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
}
|
||||
|
||||
void WorldRenderer::day_night_calculation() {
|
||||
void WorldRenderer::day_night_calculation(ClientWorld& world) {
|
||||
|
||||
m_parallel_light.sundir = glm::normalize(m_renderer.world().sunlight_dir());
|
||||
m_parallel_light.sundir = glm::normalize(world.sunlight_dir());
|
||||
m_parallel_light.sun_height = (-m_parallel_light.sundir).y;
|
||||
m_parallel_light.lightdir = m_parallel_light.sundir;
|
||||
|
||||
@@ -92,7 +92,9 @@ void WorldRenderer::day_night_calculation() {
|
||||
m_ambient_strength = glm::mix(0.45f, 0.25f, day_factor);
|
||||
}
|
||||
|
||||
void WorldRenderer::render_sky() {
|
||||
void WorldRenderer::render_sky(ClientWorld& world) {
|
||||
|
||||
auto& camera = world.world_scene().camera();
|
||||
|
||||
glm::vec3 zenith = {0.20f, 0.45f, 0.95f};
|
||||
|
||||
@@ -142,9 +144,8 @@ void WorldRenderer::render_sky() {
|
||||
|
||||
sky_shader.use();
|
||||
|
||||
glm::mat4 model_mat =
|
||||
glm::translate(glm::mat4(1.0f),
|
||||
m_camera.get_camera_pos() - glm::vec3(0.5f, 0.5f, 0.5f));
|
||||
glm::mat4 model_mat = glm::translate(
|
||||
glm::mat4(1.0f), camera.get_camera_pos() - glm::vec3(0.5f, 0.5f, 0.5f));
|
||||
|
||||
glm::mat4 mv_mat = view_matrix * model_mat;
|
||||
|
||||
@@ -195,25 +196,27 @@ void WorldRenderer::render_sky() {
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
};
|
||||
// draw sun
|
||||
glm::vec3 sun_pos = m_camera.get_camera_pos() +
|
||||
normalize(-m_world.sunlight_dir()) * (FAR_PLANE * 0.9f);
|
||||
glm::vec3 sun_pos =
|
||||
camera.get_camera_pos() +
|
||||
normalize(-m_parallel_light.sundir) * (FAR_PLANE * 0.9f);
|
||||
billboard_drawer(sun_pos, SUN_SIZE, SUN_COLOR);
|
||||
|
||||
// draw moon
|
||||
|
||||
glm::vec3 moon_pos = m_camera.get_camera_pos() +
|
||||
normalize(m_world.sunlight_dir()) * (FAR_PLANE * 0.9f);
|
||||
glm::vec3 moon_pos =
|
||||
camera.get_camera_pos() +
|
||||
normalize(m_parallel_light.sundir) * (FAR_PLANE * 0.9f);
|
||||
billboard_drawer(moon_pos, MOON_SIZE, MOON_COLOR);
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
|
||||
void WorldRenderer::render_world() {
|
||||
void WorldRenderer::render_world(ClientWorld& world) {
|
||||
|
||||
// shader map
|
||||
|
||||
auto m_height = m_renderer.height();
|
||||
auto m_width = m_renderer.width();
|
||||
auto height = m_renderer.frame_height();
|
||||
auto width = m_renderer.frame_width();
|
||||
|
||||
glm::mat4 model_mat =
|
||||
glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
|
||||
@@ -223,22 +226,22 @@ void WorldRenderer::render_world() {
|
||||
glm::mat4 norm_mat = glm::transpose(glm::inverse(mv_mat));
|
||||
|
||||
if (m_shader_on) {
|
||||
shadow_map_generate();
|
||||
shadow_map_generate(world);
|
||||
}
|
||||
|
||||
m_world_fbo->bind();
|
||||
|
||||
glCullFace(GL_BACK);
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
glViewport(0, 0, width, height);
|
||||
|
||||
render_normal_block(model_mat, mv_mat, norm_mat);
|
||||
render_normal_block(model_mat, mv_mat, norm_mat, world);
|
||||
|
||||
// copy depth buffer
|
||||
m_world_fbo->bind(FrameBufferType::READ_FRAMEBUFFER);
|
||||
|
||||
m_oit_fbo->bind(FrameBufferType::DRAW_FRAMEBUFFER);
|
||||
|
||||
glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width, m_height,
|
||||
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
|
||||
GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
m_oit_fbo->bind(FrameBufferType::DRAW_FRAMEBUFFER);
|
||||
|
||||
@@ -256,14 +259,14 @@ void WorldRenderer::render_world() {
|
||||
glBlendFunci(0, GL_ONE, GL_ONE);
|
||||
|
||||
glBlendFunci(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
|
||||
render_transparent_block(mv_mat, norm_mat);
|
||||
render_transparent_block(mv_mat, norm_mat, world);
|
||||
}
|
||||
|
||||
void WorldRenderer::render_outline() {
|
||||
void WorldRenderer::render_outline(ClientWorld& world) {
|
||||
const auto& shader = m_renderer.get_shader("outline");
|
||||
shader.use();
|
||||
|
||||
const auto& block_pos = m_renderer.world().get_look_block_pos();
|
||||
const auto& block_pos = world.get_look_block_pos();
|
||||
|
||||
if (block_pos != std::nullopt) {
|
||||
|
||||
@@ -285,24 +288,24 @@ void WorldRenderer::render_outline() {
|
||||
}
|
||||
}
|
||||
|
||||
void WorldRenderer::shadow_map_generate() {
|
||||
void WorldRenderer::shadow_map_generate(ClientWorld& world) {
|
||||
float texels_per_unit = 0.0f;
|
||||
const auto& lightdir = m_parallel_light.lightdir;
|
||||
|
||||
auto m_delta_time = m_renderer.delta_time();
|
||||
|
||||
auto& camera = world.world_scene().camera();
|
||||
// shader map
|
||||
glm::mat4& light_space_matrix = m_parallel_light.light_space_matrix;
|
||||
|
||||
auto& m_render_snapshots = m_world.render_snapshots();
|
||||
auto& camera_pos = m_camera.get_camera_pos();
|
||||
auto& m_render_snapshots = world.render_snapshots();
|
||||
auto& camera_pos = camera.get_camera_pos();
|
||||
|
||||
const auto& depth_shader = m_renderer.get_shader("depth_shader");
|
||||
|
||||
depth_shader.use();
|
||||
|
||||
glm::vec3 cam_pos = m_camera.get_camera_pos();
|
||||
glm::vec3 cam_fwd = m_camera.get_camera_front();
|
||||
glm::vec3 cam_pos = camera.get_camera_pos();
|
||||
glm::vec3 cam_fwd = camera.get_camera_front();
|
||||
float half_extent = 128.0f;
|
||||
|
||||
glm::vec3 center = cam_pos + cam_fwd * (half_extent * 0.5f);
|
||||
@@ -389,13 +392,13 @@ void WorldRenderer::shadow_map_generate() {
|
||||
}
|
||||
// player
|
||||
auto& player_shadow = m_renderer.get_shader("player_depth");
|
||||
m_player_renderer.shadow_render(player_shadow, light_space_matrix);
|
||||
m_player_renderer.shadow_render(player_shadow, light_space_matrix, world);
|
||||
}
|
||||
|
||||
void WorldRenderer::render_underwater() {
|
||||
void WorldRenderer::render_underwater(ClientWorld& world) {
|
||||
|
||||
const auto& shader = m_renderer.get_shader("under_water");
|
||||
|
||||
auto& camera = world.world_scene().camera();
|
||||
shader.use();
|
||||
|
||||
auto& m_vao = m_renderer.vao();
|
||||
@@ -406,10 +409,10 @@ void WorldRenderer::render_underwater() {
|
||||
|
||||
shader.set_loc("u_sceneTexture", 0);
|
||||
shader.set_loc("u_time", static_cast<float>(glfwGetTime()));
|
||||
shader.set_loc("u_underwater", m_camera.is_under_water());
|
||||
shader.set_loc("u_underwater", camera.is_under_water());
|
||||
shader.set_loc("u_waterColor", glm::vec3(0.1f, 0.25f, 0.35f));
|
||||
shader.set_loc("u_fogDensity", m_underwater_fog_density);
|
||||
shader.set_loc("cameraPos", m_camera.get_camera_pos());
|
||||
shader.set_loc("cameraPos", camera.get_camera_pos());
|
||||
shader.set_loc("sunDir", -m_parallel_light.sundir);
|
||||
shader.set_loc("waterDensity", m_water_density);
|
||||
shader.set_loc("InverseViewProjection",
|
||||
@@ -427,13 +430,14 @@ void WorldRenderer::render_underwater() {
|
||||
|
||||
void WorldRenderer::render_normal_block(const glm::mat4& model_mat,
|
||||
const glm::mat4& mv_mat,
|
||||
const glm::mat4& norm_mat) {
|
||||
const glm::mat4& norm_mat,
|
||||
ClientWorld& world) {
|
||||
|
||||
// shader map
|
||||
glm::mat4& light_space_matrix = m_parallel_light.light_space_matrix;
|
||||
|
||||
auto& m_render_snapshots = m_world.render_snapshots();
|
||||
auto& camera_pos = m_camera.get_camera_pos();
|
||||
auto& camera = world.world_scene().camera();
|
||||
auto& m_render_snapshots = world.render_snapshots();
|
||||
auto& camera_pos = camera.get_camera_pos();
|
||||
|
||||
const auto& lightdir = m_parallel_light.lightdir;
|
||||
|
||||
@@ -467,14 +471,14 @@ void WorldRenderer::render_normal_block(const glm::mat4& model_mat,
|
||||
normal_block_shader.set_loc("maxRadius", m_max_radius);
|
||||
normal_block_shader.set_loc("samples", m_samples);
|
||||
normal_block_shader.set_loc("specularStrength", m_specular_strength);
|
||||
normal_block_shader.set_loc("cameraPos", m_camera.get_camera_pos());
|
||||
normal_block_shader.set_loc("cameraPos", camera.get_camera_pos());
|
||||
normal_block_shader.set_loc("flipY", m_flip_y);
|
||||
normal_block_shader.set_loc("renderDistance", m_world.rendering_distance());
|
||||
normal_block_shader.set_loc("renderDistance", world.rendering_distance());
|
||||
normal_block_shader.set_loc("skyColor", m_sky_uniform.sky_top);
|
||||
|
||||
glm::mat4 mvp_mat = proj_mat * mv_mat;
|
||||
|
||||
auto& m_planes = m_world.planes();
|
||||
auto& m_planes = world.planes();
|
||||
|
||||
Math::extract_frustum_planes(mvp_mat, m_planes);
|
||||
|
||||
@@ -545,10 +549,11 @@ void WorldRenderer::render_normal_block(const glm::mat4& model_mat,
|
||||
}
|
||||
|
||||
void WorldRenderer::render_transparent_block(const glm::mat4& mv_mat,
|
||||
const glm::mat4& norm_mat) {
|
||||
|
||||
auto& m_render_snapshots = m_world.render_snapshots();
|
||||
const glm::mat4& norm_mat,
|
||||
ClientWorld& world) {
|
||||
|
||||
auto& m_render_snapshots = world.render_snapshots();
|
||||
auto& camera = world.world_scene().camera();
|
||||
const auto& lightdir = m_parallel_light.lightdir;
|
||||
glm::vec3 light_dir_view =
|
||||
glm::normalize(glm::mat3(view_matrix) * lightdir);
|
||||
@@ -573,11 +578,11 @@ void WorldRenderer::render_transparent_block(const glm::mat4& mv_mat,
|
||||
accum_shader.use();
|
||||
|
||||
set_accum_loc(accum_shader);
|
||||
accum_shader.set_loc("cameraPos", m_camera.get_camera_pos());
|
||||
accum_shader.set_loc("cameraPos", camera.get_camera_pos());
|
||||
|
||||
m_texture_manager.get_texture_array()->bind(0);
|
||||
|
||||
auto& m_planes = m_world.planes();
|
||||
auto& m_planes = world.planes();
|
||||
|
||||
for (const auto& snapshot : m_render_snapshots) {
|
||||
if (!snapshot) {
|
||||
@@ -619,7 +624,7 @@ void WorldRenderer::render_transparent_block(const glm::mat4& mv_mat,
|
||||
water_shader.set_loc("cloudWhiteMix", m_sky_uniform.cloud_white_mix);
|
||||
water_shader.set_loc("cloudThresholdLow", m_cloud_threshold_low);
|
||||
water_shader.set_loc("cloudThresholdHigh", m_cloud_threshold_high);
|
||||
water_shader.set_loc("underwater", m_camera.is_under_water());
|
||||
water_shader.set_loc("underwater", camera.is_under_water());
|
||||
water_shader.set_loc("refractStrength", m_refract_strength);
|
||||
water_shader.set_loc("enablePerturb", m_water_perturb);
|
||||
water_shader.set_loc("enableDepthFade", m_water_depth_fade);
|
||||
@@ -670,7 +675,7 @@ void WorldRenderer::render_transparent_block(const glm::mat4& mv_mat,
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void WorldRenderer::render_player() {
|
||||
void WorldRenderer::render_player(ClientWorld& world) {
|
||||
auto& shader = m_renderer.get_shader("player");
|
||||
shader.use();
|
||||
glm::vec3 light_dir_view =
|
||||
@@ -692,7 +697,7 @@ void WorldRenderer::render_player() {
|
||||
// shader.set_loc("skyColor", m_sky_uniform.sky_top);
|
||||
|
||||
m_depth_map_texture->bind(0);
|
||||
m_player_renderer.render(shader);
|
||||
m_player_renderer.render(shader, world);
|
||||
}
|
||||
|
||||
glm::vec3 WorldRenderer::quantize_sun_direction(const glm::vec3& lightdir,
|
||||
|
||||
21
src/scene/main_menu_scene.cpp
Normal file
21
src/scene/main_menu_scene.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "Cubed/scene/main_menu_scene.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
MainMenuScene::MainMenuScene(SceneManager& scene_manager)
|
||||
: m_scene_manager(scene_manager), m_ui_manager(*this) {}
|
||||
MainMenuScene::~MainMenuScene() {}
|
||||
|
||||
void MainMenuScene::update(float dt) { m_ui_manager.update(dt); }
|
||||
void MainMenuScene::render(Renderer& renderer) {
|
||||
m_ui_manager.render(renderer);
|
||||
}
|
||||
bool MainMenuScene::handle_event(const Event& e) {
|
||||
if (m_ui_manager.handle_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void MainMenuScene::on_enter() { m_ui_manager.init(); }
|
||||
void MainMenuScene::on_leave() {}
|
||||
SceneManager& MainMenuScene::scene_manager() { return m_scene_manager; }
|
||||
} // namespace Cubed
|
||||
99
src/scene/scene_manager.cpp
Normal file
99
src/scene/scene_manager.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#include "Cubed/scene/scene_manager.hpp"
|
||||
|
||||
#include "Cubed/scene/main_menu_scene.hpp"
|
||||
#include "Cubed/scene/world_scene.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
SceneManager::SceneManager(App& app) : m_app(app) {}
|
||||
SceneManager::~SceneManager() {}
|
||||
|
||||
void SceneManager::update(float dt) {
|
||||
m_pending_delete_scene.clear();
|
||||
process_operation();
|
||||
if (!m_scenes.empty()) {
|
||||
m_scenes.top()->update(dt);
|
||||
}
|
||||
}
|
||||
void SceneManager::render(Renderer& renderer) {
|
||||
if (m_scenes.empty()) {
|
||||
return;
|
||||
}
|
||||
m_scenes.top()->render(renderer);
|
||||
}
|
||||
|
||||
bool SceneManager::handle_event(const Event& e) {
|
||||
if (m_scenes.empty()) {
|
||||
return false;
|
||||
}
|
||||
return m_scenes.top()->handle_event(e);
|
||||
}
|
||||
|
||||
void SceneManager::request_change(SceneType type) {
|
||||
ASSERT(!m_operation.has_value());
|
||||
m_operation = {OperationType::CHANGE, type};
|
||||
}
|
||||
void SceneManager::request_push(SceneType type) {
|
||||
ASSERT(!m_operation.has_value());
|
||||
m_operation = {OperationType::PUSH, type};
|
||||
}
|
||||
void SceneManager::request_pop() {
|
||||
ASSERT(!m_operation.has_value());
|
||||
m_operation = {OperationType::POP, std::nullopt};
|
||||
}
|
||||
|
||||
void SceneManager::process_operation() {
|
||||
while (m_operation) {
|
||||
auto op = std::move(*m_operation);
|
||||
m_operation.reset();
|
||||
|
||||
switch (op.type) {
|
||||
case OperationType::PUSH:
|
||||
push(*op.scene);
|
||||
break;
|
||||
case OperationType::POP:
|
||||
pop();
|
||||
break;
|
||||
case OperationType::CHANGE:
|
||||
change(*op.scene);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SceneManager::change(SceneType type) {
|
||||
if (!m_scenes.empty()) {
|
||||
pop();
|
||||
}
|
||||
|
||||
push(type);
|
||||
}
|
||||
void SceneManager::push(SceneType type) {
|
||||
auto scene = create_scene(type);
|
||||
scene->on_enter();
|
||||
m_scenes.push(std::move(scene));
|
||||
}
|
||||
void SceneManager::pop() {
|
||||
if (m_scenes.empty()) {
|
||||
return;
|
||||
}
|
||||
auto scene = std::move(m_scenes.top());
|
||||
m_scenes.pop();
|
||||
scene->on_leave();
|
||||
m_pending_delete_scene.push_back(std::move(scene));
|
||||
}
|
||||
|
||||
std::unique_ptr<Scene> SceneManager::create_scene(SceneType type) {
|
||||
switch (type) {
|
||||
case SceneType::WORLD:
|
||||
return std::make_unique<WorldScene>(*this);
|
||||
case SceneType::MAIN_MENU:
|
||||
return std::make_unique<MainMenuScene>(*this);
|
||||
}
|
||||
|
||||
std::string err = std::format("Unknown Scene");
|
||||
ASSERT_MSG(false, err);
|
||||
throw std::runtime_error(err);
|
||||
}
|
||||
|
||||
App& SceneManager::app() { return m_app; }
|
||||
} // namespace Cubed
|
||||
88
src/scene/world_scene.cpp
Normal file
88
src/scene/world_scene.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "Cubed/scene/world_scene.hpp"
|
||||
|
||||
#include "Cubed/app.hpp"
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/scene/scene_manager.hpp"
|
||||
namespace Cubed {
|
||||
WorldScene::WorldScene(SceneManager& scene_manager)
|
||||
: m_scene_manager(scene_manager), m_dev_panel(*this),
|
||||
m_client_world(scene_manager.app().audio(), scene_manager.app().config(),
|
||||
*this),
|
||||
m_ui_manager(*this), m_argument(scene_manager.app().argument()) {}
|
||||
|
||||
WorldScene::~WorldScene() {
|
||||
if (m_client) {
|
||||
m_client->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void WorldScene::update(float dt) {
|
||||
m_client_world.update(dt);
|
||||
m_camera.update_move_camera();
|
||||
m_client_world.get_audio().update_listener(m_camera.get_camera_pos(),
|
||||
m_camera.get_camera_front(),
|
||||
glm::vec3(0, 1, 0));
|
||||
|
||||
/*
|
||||
const auto& player = m_client_world.get_player();
|
||||
if (player_gait != player.get_gait()) {
|
||||
player_gait = player.get_gait();
|
||||
float fov = m_client_world.get("player.fov", 70.0f);
|
||||
if (player_gait == Gait::WALK) {
|
||||
m_renderer.update_fov(fov);
|
||||
}
|
||||
if (player_gait == Gait::RUN) {
|
||||
m_renderer.update_fov(fov + 5.0f);
|
||||
}
|
||||
}*/
|
||||
m_ui_manager.update(dt);
|
||||
}
|
||||
|
||||
void WorldScene::render(Renderer& renderer) {
|
||||
|
||||
renderer.render_world(m_client_world);
|
||||
|
||||
renderer.render_dev_panel(m_dev_panel);
|
||||
|
||||
m_ui_manager.render(renderer);
|
||||
}
|
||||
bool WorldScene::handle_event(const Event& e) {
|
||||
if (m_ui_manager.handle_event(e)) {
|
||||
return true;
|
||||
}
|
||||
if (m_camera.handle_event(e)) {
|
||||
return true;
|
||||
}
|
||||
// world event needs to be processed last
|
||||
if (m_client_world.handle_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void WorldScene::on_enter() {
|
||||
|
||||
m_client = std::make_shared<NetworkClient>(m_client_world);
|
||||
|
||||
m_client->start(m_argument.ip, m_argument.port);
|
||||
// init will send packet
|
||||
m_client_world.init(m_argument.player, m_client);
|
||||
|
||||
Logger::info("World Init Success");
|
||||
m_camera.camera_init(&m_client_world.get_player());
|
||||
m_scene_manager.app().window().set_camera(&m_camera);
|
||||
m_dev_panel.init();
|
||||
m_ui_manager.init();
|
||||
|
||||
m_scene_manager.app().window().set_game_running(true);
|
||||
}
|
||||
void WorldScene::on_leave() {
|
||||
m_client_world.request_exit();
|
||||
|
||||
m_scene_manager.app().window().set_camera(nullptr);
|
||||
m_scene_manager.app().window().set_game_running(false);
|
||||
}
|
||||
|
||||
Camera& WorldScene::camera() { return m_camera; }
|
||||
SceneManager& WorldScene::scene_manager() { return m_scene_manager; }
|
||||
ClientWorld& WorldScene::client_world() { return m_client_world; }
|
||||
} // namespace Cubed
|
||||
@@ -11,7 +11,6 @@ constexpr int BLOCK_SIZE = 16;
|
||||
constexpr int BLOCK_NORMAL_SIZE = 128;
|
||||
constexpr int CROSS_PLANE_SIZE = 16;
|
||||
constexpr int BLOCK_ITEM_SIZE = 16;
|
||||
constexpr int UI_SIZE = 16;
|
||||
constexpr int BLOCK_STATUS_SIZE = 16;
|
||||
constexpr int SKIN_SIZE = 64;
|
||||
|
||||
@@ -58,7 +57,13 @@ const Texture* TextureManager::get_texture_array() const {
|
||||
const Texture* TextureManager::get_cross_plane_array() const {
|
||||
return m_cross_plane_array.get();
|
||||
}
|
||||
const Texture* TextureManager::get_ui_array() const { return m_ui_array.get(); }
|
||||
const Texture* TextureManager::get_image_texture(const std::string& path) {
|
||||
auto it = m_ui_map.find(path);
|
||||
if (it != m_ui_map.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
return load_image_texture(path);
|
||||
}
|
||||
|
||||
const Texture* TextureManager::get_pbr_texture() const {
|
||||
return m_normal_texture_array.get();
|
||||
@@ -77,15 +82,11 @@ void TextureManager::load_block_status(unsigned id) {
|
||||
|
||||
std::string path = "texture/status/" + std::to_string(id) + ".png";
|
||||
|
||||
unsigned char* image_data = nullptr;
|
||||
|
||||
image_data = (Tools::load_image_data(path));
|
||||
auto image_data = (Tools::load_image_data(path));
|
||||
|
||||
m_block_status_array->tex_sub_image_3d(
|
||||
TextureFormat::RGBA, GL_UNSIGNED_BYTE, image_data, 0, 0, id,
|
||||
TextureFormat::RGBA, GL_UNSIGNED_BYTE, image_data.data, 0, 0, id,
|
||||
BLOCK_STATUS_SIZE, BLOCK_STATUS_SIZE);
|
||||
|
||||
Tools::delete_image_data(image_data);
|
||||
}
|
||||
|
||||
void TextureManager::load_block_texture(unsigned id) {
|
||||
@@ -101,7 +102,7 @@ void TextureManager::load_block_texture(unsigned id) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char* image_data[6];
|
||||
std::array<ImageData, 6> image_data;
|
||||
|
||||
std::string block_texture_path = "texture/block/" + name;
|
||||
image_data[0] = (Tools::load_image_data(block_texture_path + "/front.png"));
|
||||
@@ -114,10 +115,9 @@ void TextureManager::load_block_texture(unsigned id) {
|
||||
Tools::check_opengl_error();
|
||||
for (int i = 0; i < 6; i++) {
|
||||
m_texture_array->tex_sub_image_3d(TextureFormat::RGBA, GL_UNSIGNED_BYTE,
|
||||
image_data[i], 0, 0, id * 6 + i,
|
||||
image_data[i].data, 0, 0, id * 6 + i,
|
||||
BLOCK_SIZE, BLOCK_SIZE);
|
||||
Tools::check_opengl_error();
|
||||
Tools::delete_image_data(image_data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,41 +127,43 @@ void TextureManager::load_block_item_texture(unsigned id) {
|
||||
std::string name{BlockManager::name_form_id(id)};
|
||||
|
||||
std::string path = "texture/item/block/" + name + ".png";
|
||||
unsigned char* data = nullptr;
|
||||
data = Tools::load_image_data(path);
|
||||
|
||||
auto data = Tools::load_image_data(path);
|
||||
std::unique_ptr<Texture> texture =
|
||||
std::make_unique<Texture>(TextureType::TEXTURE_2D);
|
||||
texture->tex_image_2d(TextureFormat::RGBA8, TextureFormat::RGBA,
|
||||
GL_UNSIGNED_BYTE, data, BLOCK_ITEM_SIZE,
|
||||
GL_UNSIGNED_BYTE, data.data, BLOCK_ITEM_SIZE,
|
||||
BLOCK_ITEM_SIZE);
|
||||
|
||||
texture->set_nearest();
|
||||
texture->set_clamp_to_border();
|
||||
|
||||
m_item_textures.push_back(std::move(texture));
|
||||
Tools::delete_image_data(data);
|
||||
}
|
||||
|
||||
void TextureManager::load_cross_plane_texture(unsigned id) {
|
||||
std::string path =
|
||||
"texture/block/" + BlockManager::name_form_id(id) + "/cross.png";
|
||||
unsigned char* image_data = Tools::load_image_data(path);
|
||||
auto image_data = Tools::load_image_data(path);
|
||||
m_cross_plane_array->tex_sub_image_3d(TextureFormat::RGBA, GL_UNSIGNED_BYTE,
|
||||
image_data, 0, 0,
|
||||
image_data.data, 0, 0,
|
||||
BlockManager::cross_plane_index(id),
|
||||
CROSS_PLANE_SIZE, CROSS_PLANE_SIZE);
|
||||
Tools::delete_image_data(image_data);
|
||||
}
|
||||
|
||||
void TextureManager::load_ui_texture(unsigned id) {
|
||||
ASSERT_MSG(id < MAX_UI_NUM, "Exceed the max ui sum limit");
|
||||
const Texture* TextureManager::load_image_texture(const std::string& path) {
|
||||
|
||||
std::string path = "texture/ui/" + std::to_string(id) + ".png";
|
||||
unsigned char* image_data = nullptr;
|
||||
image_data = (Tools::load_image_data(path));
|
||||
m_ui_array->tex_sub_image_3d(TextureFormat::RGBA, GL_UNSIGNED_BYTE,
|
||||
image_data, 0, 0, id, UI_SIZE, UI_SIZE);
|
||||
Tools::delete_image_data(image_data);
|
||||
auto image_data = (Tools::load_image_data(path));
|
||||
std::unique_ptr<Texture> image =
|
||||
std::make_unique<Texture>(TextureType::TEXTURE_2D);
|
||||
image->tex_image_2d(RGBA, RGBA, GL_UNSIGNED_BYTE, image_data.data,
|
||||
image_data.width, image_data.height);
|
||||
image->set_nearest();
|
||||
auto [it, inserted] = m_ui_map.try_emplace(path, std::move(image));
|
||||
if (!inserted) {
|
||||
Logger::error("Path {} already exist!", path);
|
||||
}
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
void TextureManager::load_pbr_texture(unsigned id) {
|
||||
@@ -177,7 +179,7 @@ void TextureManager::load_pbr_texture(unsigned id) {
|
||||
|
||||
std::string path = "normal/block/" + BlockManager::name_form_id(id);
|
||||
|
||||
unsigned char* image_data[6];
|
||||
std::array<ImageData, 6> image_data;
|
||||
|
||||
image_data[0] = (Tools::load_image_data(path + "/front_n.png", false));
|
||||
image_data[1] = (Tools::load_image_data(path + "/right_n.png", false));
|
||||
@@ -187,7 +189,7 @@ void TextureManager::load_pbr_texture(unsigned id) {
|
||||
image_data[5] = (Tools::load_image_data(path + "/base_n.png", false));
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
unsigned char* data = image_data[i];
|
||||
unsigned char* data = image_data[i].data;
|
||||
bool is_fallback = false;
|
||||
if (!data) {
|
||||
is_fallback = true;
|
||||
@@ -200,7 +202,6 @@ void TextureManager::load_pbr_texture(unsigned id) {
|
||||
if (is_fallback) {
|
||||
delete[] data;
|
||||
} else {
|
||||
Tools::delete_image_data(image_data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -242,26 +243,16 @@ void TextureManager::init_block() {
|
||||
|
||||
Logger::info("Block Texture Load Success");
|
||||
}
|
||||
void TextureManager::init_ui() {
|
||||
m_ui_array = std::make_unique<Texture>(TextureType::TEXTURE_2D_ARRAY);
|
||||
m_ui_array->tex_image_3d(TextureFormat::RGBA, TextureFormat::RGBA,
|
||||
GL_UNSIGNED_BYTE, nullptr, UI_SIZE, UI_SIZE,
|
||||
MAX_UI_NUM);
|
||||
for (int i = 0; i < MAX_UI_NUM; i++) {
|
||||
load_ui_texture(i);
|
||||
}
|
||||
|
||||
m_ui_array->set_nearest();
|
||||
}
|
||||
void TextureManager::init_ui() {}
|
||||
|
||||
void TextureManager::init_skin() {
|
||||
m_skin = std::make_unique<Texture>(TextureType::TEXTURE_2D);
|
||||
std::string path = "texture/skin/player001.png";
|
||||
unsigned char* image_data = nullptr;
|
||||
image_data = (Tools::load_image_data(path));
|
||||
|
||||
auto image_data = (Tools::load_image_data(path));
|
||||
m_skin->tex_image_2d(TextureFormat::RGBA, TextureFormat::RGBA,
|
||||
GL_UNSIGNED_BYTE, image_data, SKIN_SIZE, SKIN_SIZE);
|
||||
Tools::delete_image_data(image_data);
|
||||
GL_UNSIGNED_BYTE, image_data.data, SKIN_SIZE,
|
||||
SKIN_SIZE);
|
||||
m_skin->set_nearest_and_minpmap();
|
||||
m_skin->set_aniso(m_aniso);
|
||||
}
|
||||
@@ -314,4 +305,31 @@ void TextureManager::hot_reload() {
|
||||
|
||||
int TextureManager::max_aniso() const { return static_cast<int>(m_max_aniso); }
|
||||
|
||||
bool TextureManager::handle_event(const Event& e) {
|
||||
return std::visit(
|
||||
Overloaded{[](const MouseMoveEvent&) { return false; },
|
||||
[](const MouseButtonEvent&) { return false; },
|
||||
[](const MouseWheelEvent&) { return false; },
|
||||
[this](const KeyEvent& e) {
|
||||
if (handle_key_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[](const TextInputEvent&) { return false; },
|
||||
[](const WindowResizeEvent&) { return false; },
|
||||
[](const FrameBufferResizeEvent&) { return false; }
|
||||
|
||||
},
|
||||
e);
|
||||
}
|
||||
|
||||
bool TextureManager::handle_key_event(const KeyEvent& e) {
|
||||
if (e.key == Key::R && e.action == KeyAction::PRESS) {
|
||||
need_reload();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
} // namespace Cubed
|
||||
@@ -38,9 +38,9 @@ void Font::load_character(char8_t c) {
|
||||
static_cast<int>(c), width, height);
|
||||
|
||||
Character character = {
|
||||
glm::vec2{0.0f, 0.0f},
|
||||
glm::vec2{static_cast<float>(width) / m_texture_width,
|
||||
static_cast<float>(height) / m_texture_height},
|
||||
glm::vec2{0.5f / m_texture_width, 0.5f / m_texture_height},
|
||||
glm::vec2{(width - 0.5f) / m_texture_width,
|
||||
(height - 0.5f) / m_texture_height},
|
||||
glm::ivec2(m_face->glyph->bitmap.width, m_face->glyph->bitmap.rows),
|
||||
glm::ivec2(m_face->glyph->bitmap_left, m_face->glyph->bitmap_top),
|
||||
static_cast<GLuint>(m_face->glyph->advance.x)};
|
||||
@@ -51,7 +51,7 @@ void Font::load_character(char8_t c) {
|
||||
void Font::setup_font_character() {
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
m_text_texture = std::make_unique<Texture>(TextureType::TEXTURE_2D_ARRAY);
|
||||
m_text_texture->tex_image_3d(TextureFormat::RED, TextureFormat::RED,
|
||||
m_text_texture->tex_image_3d(TextureFormat::R8, TextureFormat::RED,
|
||||
GL_UNSIGNED_BYTE, nullptr, m_texture_width,
|
||||
m_texture_height, MAX_CHARACTER);
|
||||
|
||||
@@ -62,24 +62,39 @@ void Font::setup_font_character() {
|
||||
m_text_texture->set_clamp_to_edge(false, true, true);
|
||||
}
|
||||
|
||||
std::vector<Vertex2D> Font::vertices(const std::string& text, float x, float y,
|
||||
float scale) {
|
||||
TextMesh Font::vertices(const std::string& text) {
|
||||
static Font font;
|
||||
|
||||
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_y = 0.0f;
|
||||
|
||||
for (char8_t c : text) {
|
||||
auto it = font.m_characters.find(c);
|
||||
if (it == font.m_characters.end()) {
|
||||
Logger::error("Can't find character {}", static_cast<char>(c));
|
||||
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;
|
||||
float h = ch.size.y * scale;
|
||||
Character& ch = it->second;
|
||||
|
||||
float xpos = pen_x + ch.bearing.x;
|
||||
float ypos = pen_y - ch.bearing.y;
|
||||
|
||||
float w = ch.size.x;
|
||||
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,
|
||||
static_cast<float>(c));
|
||||
@@ -87,6 +102,7 @@ std::vector<Vertex2D> Font::vertices(const std::string& text, float x, float y,
|
||||
static_cast<float>(c));
|
||||
vertices.emplace_back(xpos + w, ypos, ch.uv_max.x, ch.uv_min.y,
|
||||
static_cast<float>(c));
|
||||
|
||||
vertices.emplace_back(xpos, ypos + h, ch.uv_min.x, ch.uv_max.y,
|
||||
static_cast<float>(c));
|
||||
vertices.emplace_back(xpos + w, ypos, ch.uv_max.x, ch.uv_min.y,
|
||||
@@ -94,10 +110,15 @@ 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,
|
||||
static_cast<float>(c));
|
||||
|
||||
x += (ch.advance >> 6) * scale;
|
||||
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(); }
|
||||
|
||||
@@ -174,8 +174,7 @@ void delete_image_data(unsigned char* data) {
|
||||
SOIL_free_image_data(data);
|
||||
}
|
||||
|
||||
unsigned char* load_image_data(const std::string& tex_image_path,
|
||||
bool check_exist) {
|
||||
ImageData load_image_data(const std::string& tex_image_path, bool check_exist) {
|
||||
fs::path path = ASSETS_PATH + tex_image_path;
|
||||
if (check_exist) {
|
||||
ASSERT_MSG(fs::is_regular_file(path), path.c_str());
|
||||
@@ -193,7 +192,7 @@ unsigned char* load_image_data(const std::string& tex_image_path,
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
return {data, width, height, channels};
|
||||
}
|
||||
|
||||
} // namespace Tools
|
||||
|
||||
72
src/ui/button.cpp
Normal file
72
src/ui/button.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "Cubed/ui/button.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
Button::Button(Widget* parent) : Widget(parent) {}
|
||||
|
||||
void Button::update(float dt) {
|
||||
if (m_background) {
|
||||
m_background->update(dt);
|
||||
}
|
||||
if (m_foreground) {
|
||||
m_foreground->update(dt);
|
||||
}
|
||||
}
|
||||
|
||||
void Button::render(Renderer& renderer) {
|
||||
if (m_background) {
|
||||
m_background->render(renderer);
|
||||
}
|
||||
if (m_foreground) {
|
||||
m_foreground->render(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
bool Button::handle_mouse_move_event(const MouseMoveEvent& e) {
|
||||
auto pos = m_background->pos();
|
||||
|
||||
if (e.xpos >= pos.x && e.xpos <= pos.x + width() && e.ypos >= pos.y &&
|
||||
e.ypos <= pos.y + height()) {
|
||||
m_hovered = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
m_hovered = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
bool Button::handle_mouse_button_event(const MouseButtonEvent& e) {
|
||||
if (e.action == KeyAction::PRESS && e.key == MouseKey::LEFT_BUTTON) {
|
||||
if (m_hovered && m_clicked) {
|
||||
m_clicked();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Button& Button::set_scale(float scale) {
|
||||
m_background->set_scale(scale);
|
||||
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(); }
|
||||
|
||||
float Button::width() const { return m_background->width(); }
|
||||
float Button::height() const { return m_background->height(); }
|
||||
|
||||
} // namespace Cubed
|
||||
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
|
||||
39
src/ui/image.cpp
Normal file
39
src/ui/image.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "Cubed/ui/image.hpp"
|
||||
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/texture_manager.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
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,
|
||||
TextureManager& texture_manager) {
|
||||
m_texture = texture_manager.get_image_texture(path);
|
||||
return *this;
|
||||
}
|
||||
Image& Image::set_scale(float scale) {
|
||||
m_scale = scale;
|
||||
return *this;
|
||||
}
|
||||
float Image::scale() const { return m_scale; }
|
||||
float Image::height() const {
|
||||
if (!m_texture) {
|
||||
Logger::error("Image id {} not set image!", m_id);
|
||||
return 0.0f;
|
||||
}
|
||||
return m_texture->height() * m_scale;
|
||||
}
|
||||
|
||||
float Image::width() const {
|
||||
if (!m_texture) {
|
||||
Logger::error("Image id {} not set image!", m_id);
|
||||
return 0.0f;
|
||||
}
|
||||
return m_texture->width() * m_scale;
|
||||
}
|
||||
|
||||
const Texture* Image::texture() const { return m_texture; }
|
||||
|
||||
} // namespace Cubed
|
||||
50
src/ui/label.cpp
Normal file
50
src/ui/label.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "Cubed/ui/label.hpp"
|
||||
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/tools/font.hpp"
|
||||
namespace Cubed {
|
||||
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();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Label& Label::set_color(Color color) {
|
||||
m_text.color = color;
|
||||
return *this;
|
||||
}
|
||||
Label& Label::set_scale(float scale) {
|
||||
m_scale = scale;
|
||||
return *this;
|
||||
}
|
||||
void Label::update(float dt) { on_update(dt); }
|
||||
|
||||
void Label::on_update(float dt) { (void)dt; }
|
||||
|
||||
void Label::render(Renderer& renderer) { on_render(renderer); }
|
||||
|
||||
void Label::on_render(Renderer& renderer) { renderer.render_lable(*this); }
|
||||
|
||||
void Label::update_vertices() {
|
||||
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_real_width = textmesh.width;
|
||||
m_real_height = textmesh.height;
|
||||
|
||||
m_data.update_sum();
|
||||
m_data.upload();
|
||||
}
|
||||
|
||||
const UIVertexData& Label::data() const { return m_data; }
|
||||
const TextStyle& Label::text_style() const { return m_text; }
|
||||
float Label::width() const { return m_real_width * m_scale; }
|
||||
float Label::height() const { return m_real_height * m_scale; }
|
||||
float Label::offset_x() const { return m_offset_x; }
|
||||
float Label::offset_y() const { return m_offset_y; }
|
||||
float Label::scale() const { return m_scale; }
|
||||
} // namespace Cubed
|
||||
145
src/ui/main_menu_ui_manager.cpp
Normal file
145
src/ui/main_menu_ui_manager.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
#include "Cubed/ui/main_menu_ui_manager.hpp"
|
||||
|
||||
#include "Cubed/app.hpp"
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#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) {}
|
||||
MainMenuUIManager::~MainMenuUIManager() {}
|
||||
|
||||
void MainMenuUIManager::init() {
|
||||
|
||||
auto rect = std::make_unique<Rect>(nullptr);
|
||||
|
||||
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());
|
||||
|
||||
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>();
|
||||
|
||||
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();
|
||||
|
||||
m_root_widget->render(renderer);
|
||||
|
||||
renderer.end_render_ui();
|
||||
}
|
||||
bool MainMenuUIManager::handle_event(const Event& e) {
|
||||
return std::visit(
|
||||
Overloaded{[this](const MouseMoveEvent& e) {
|
||||
if (handle_mouse_move_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[this](const MouseButtonEvent& e) {
|
||||
if (handle_mouse_button_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[this](const MouseWheelEvent& e) {
|
||||
if (handle_mouse_wheel_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[this](const KeyEvent& e) {
|
||||
if (handle_key_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[](const TextInputEvent&) { return false; },
|
||||
[this](const WindowResizeEvent& e) {
|
||||
handle_window_resize_event(e);
|
||||
return false;
|
||||
},
|
||||
[](const FrameBufferResizeEvent&) { return false; }
|
||||
|
||||
},
|
||||
e);
|
||||
}
|
||||
bool MainMenuUIManager::handle_mouse_move_event(const MouseMoveEvent& e) {
|
||||
if (m_root_widget->handle_mouse_move_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool MainMenuUIManager::handle_mouse_button_event(const MouseButtonEvent& e) {
|
||||
|
||||
if (m_root_widget->handle_mouse_button_event(e)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool MainMenuUIManager::handle_window_resize_event(const WindowResizeEvent& e) {
|
||||
|
||||
if (m_root_widget->handle_window_resize_event(e)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool MainMenuUIManager::handle_mouse_wheel_event(const MouseWheelEvent& e) {
|
||||
|
||||
if (m_root_widget->handle_mouse_wheel_event(e)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool MainMenuUIManager::handle_key_event(const KeyEvent& e) {
|
||||
|
||||
if (m_root_widget->handle_key_event(e)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
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,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, 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));
|
||||
|
||||
VertexArray::unbind();
|
||||
VertexBuffer::unbind();
|
||||
|
||||
// Release memory
|
||||
m_vertices.clear();
|
||||
}
|
||||
|
||||
void UIVertexData::update_sum() { m_sum = m_vertices.size(); }
|
||||
|
||||
} // namespace Cubed
|
||||
166
src/ui/widget.cpp
Normal file
166
src/ui/widget.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
#include "Cubed/ui/widget.hpp"
|
||||
|
||||
#include "Cubed/tools/log.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
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);
|
||||
|
||||
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) {}
|
||||
void Widget::on_render(Renderer&) {}
|
||||
|
||||
std::vector<std::unique_ptr<Widget>>& Widget::children() { return m_children; }
|
||||
|
||||
const std::vector<std::unique_ptr<Widget>>& Widget::children() const {
|
||||
return m_children;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
for (auto it = m_children.rbegin(); it != m_children.rend(); ++it) {
|
||||
if ((*it)->handle_key_event(e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool Widget::handle_mouse_button_event(const MouseButtonEvent& e) {
|
||||
for (auto it = m_children.rbegin(); it != m_children.rend(); ++it) {
|
||||
if ((*it)->handle_mouse_button_event(e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Widget::handle_mouse_wheel_event(const MouseWheelEvent& e) {
|
||||
for (auto it = m_children.rbegin(); it != m_children.rend(); ++it) {
|
||||
if ((*it)->handle_mouse_wheel_event(e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Widget::handle_mouse_move_event(const MouseMoveEvent& e) {
|
||||
for (auto it = m_children.rbegin(); it != m_children.rend(); ++it) {
|
||||
if ((*it)->handle_mouse_move_event(e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace Cubed
|
||||
120
src/ui/world_ui_manager.cpp
Normal file
120
src/ui/world_ui_manager.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#include "Cubed/ui/world_ui_manager.hpp"
|
||||
|
||||
#include "Cubed/app.hpp"
|
||||
#include "Cubed/debug_collector.hpp"
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/scene/scene_manager.hpp"
|
||||
#include "Cubed/scene/world_scene.hpp"
|
||||
namespace Cubed {
|
||||
|
||||
WorldUIManager::WorldUIManager(WorldScene& scene) : m_scene(scene) {}
|
||||
WorldUIManager::~WorldUIManager() {}
|
||||
|
||||
void WorldUIManager::init() {
|
||||
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_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) {
|
||||
|
||||
for (auto& w : m_widgets) {
|
||||
w.second->update(dt);
|
||||
}
|
||||
}
|
||||
void WorldUIManager::render(Renderer& renderer) {
|
||||
renderer.begin_render_ui();
|
||||
|
||||
auto& widget = DebugCollector::get().get_widget();
|
||||
widget.render(renderer);
|
||||
for (auto& widget : m_widgets) {
|
||||
widget.second->render(renderer);
|
||||
}
|
||||
|
||||
renderer.end_render_ui();
|
||||
}
|
||||
bool WorldUIManager::handle_event(const Event& e) {
|
||||
return std::visit(
|
||||
Overloaded{[this](const MouseMoveEvent& e) {
|
||||
if (handle_mouse_move_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[this](const MouseButtonEvent& e) {
|
||||
if (handle_mouse_button_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[this](const MouseWheelEvent& e) {
|
||||
if (handle_mouse_wheel_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[this](const KeyEvent& e) {
|
||||
if (handle_key_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[](const TextInputEvent&) { return false; },
|
||||
[this](const WindowResizeEvent& e) {
|
||||
handle_window_resize_event(e);
|
||||
return false;
|
||||
},
|
||||
[](const FrameBufferResizeEvent&) { return false; }
|
||||
|
||||
},
|
||||
e);
|
||||
}
|
||||
bool WorldUIManager::handle_mouse_move_event(const MouseMoveEvent& e) {
|
||||
for (auto& w : m_widgets) {
|
||||
if (w.second->handle_mouse_move_event(e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool WorldUIManager::handle_mouse_button_event(const MouseButtonEvent& e) {
|
||||
for (auto& w : m_widgets) {
|
||||
if (w.second->handle_mouse_button_event(e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool WorldUIManager::handle_window_resize_event(const WindowResizeEvent& e) {
|
||||
for (auto& w : m_widgets) {
|
||||
if (w.second->handle_window_resize_event(e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool WorldUIManager::handle_mouse_wheel_event(const MouseWheelEvent& e) {
|
||||
for (auto& w : m_widgets) {
|
||||
if (w.second->handle_mouse_wheel_event(e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool WorldUIManager::handle_key_event(const KeyEvent& e) {
|
||||
for (auto& w : m_widgets) {
|
||||
if (w.second->handle_key_event(e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
108
src/window.cpp
108
src/window.cpp
@@ -1,6 +1,6 @@
|
||||
#include "Cubed/window.hpp"
|
||||
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/camera.hpp"
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
#include "Cubed/tools/font.hpp"
|
||||
#include "Cubed/tools/log.hpp"
|
||||
@@ -14,8 +14,7 @@ namespace Cubed {
|
||||
static int windowed_xpos = 0, windowed_ypos = 0;
|
||||
static int windowed_width = 800, windowed_height = 600;
|
||||
|
||||
Window::Window(Renderer& renderer, Config& config)
|
||||
: m_renderer(renderer), m_config(config) {}
|
||||
Window::Window(Config& config) : m_config(config) {}
|
||||
|
||||
Window::~Window() {
|
||||
if (m_imgui_init) {
|
||||
@@ -41,14 +40,66 @@ const GLFWwindow* Window::get_glfw_window() const { return m_window; }
|
||||
|
||||
GLFWwindow* Window::get_glfw_window() { return m_window; }
|
||||
|
||||
void Window::update_viewport() {
|
||||
glfwGetFramebufferSize(m_window, &m_width, &m_height);
|
||||
m_aspect = (float)m_width / (float)m_height;
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
m_renderer.update_proj_matrix(m_aspect, m_width, m_height);
|
||||
m_renderer.updata_framebuffer(m_width, m_height);
|
||||
m_config.set("window.width", windowed_width);
|
||||
m_config.set("window.height", windowed_height);
|
||||
bool Window::handle_event(const Event& e) {
|
||||
return std::visit(
|
||||
Overloaded{[](const MouseMoveEvent&) { return false; },
|
||||
[this](const MouseButtonEvent& e) {
|
||||
if (handle_mouse_button_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[](const MouseWheelEvent&) { return false; },
|
||||
[this](const KeyEvent& e) {
|
||||
if (handle_key_event(e)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[](const TextInputEvent&) { return false; },
|
||||
[this](const WindowResizeEvent& e) {
|
||||
handle_window_resize_event(e);
|
||||
return false;
|
||||
},
|
||||
[](const FrameBufferResizeEvent&) { return false; }
|
||||
|
||||
},
|
||||
e);
|
||||
}
|
||||
|
||||
bool Window::handle_key_event(const KeyEvent& e) {
|
||||
if (e.key == Key::F11 && e.action == KeyAction::PRESS) {
|
||||
toggle_fullscreen();
|
||||
return true;
|
||||
}
|
||||
if (e.key == Key::ESCAPE && e.action == KeyAction::PRESS) {
|
||||
if (!m_game_running) {
|
||||
glfwSetWindowShouldClose(m_window, GLFW_TRUE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (e.key == Key::LEFT_ALT && e.action == KeyAction::PRESS) {
|
||||
toggle_mouse_able();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Window::handle_window_resize_event(const WindowResizeEvent& e) {
|
||||
m_window_height = e.height;
|
||||
m_window_width = e.width;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Window::handle_mouse_button_event(const MouseButtonEvent& e) {
|
||||
if (e.key == MouseKey::LEFT_BUTTON && e.action == KeyAction::PRESS) {
|
||||
if (is_mouse_enable()) {
|
||||
toggle_mouse_able();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Window::init() {
|
||||
@@ -60,15 +111,18 @@ void Window::init() {
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
|
||||
m_width = m_config.get("window.width", 800);
|
||||
m_height = m_config.get("window.height", 600);
|
||||
|
||||
m_window_width = m_config.get("window.width", 800);
|
||||
m_window_height = m_config.get("window.height", 600);
|
||||
|
||||
if (m_config.get("window.fullscreen", false)) {
|
||||
GLFWmonitor* primary_monitor = glfwGetPrimaryMonitor();
|
||||
const GLFWvidmode* mode = glfwGetVideoMode(primary_monitor);
|
||||
m_window = glfwCreateWindow(mode->width, mode->height, "Cubed",
|
||||
primary_monitor, NULL);
|
||||
} else {
|
||||
m_window = glfwCreateWindow(m_width, m_height, "Cubed", NULL, NULL);
|
||||
m_window = glfwCreateWindow(m_window_width, m_window_height, "Cubed",
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(m_window);
|
||||
@@ -77,8 +131,10 @@ void Window::init() {
|
||||
} else {
|
||||
glfwSwapInterval(0);
|
||||
}
|
||||
if (m_game_running) {
|
||||
glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
}
|
||||
|
||||
glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
if (glfwRawMouseMotionSupported()) {
|
||||
glfwSetInputMode(m_window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
|
||||
} else {
|
||||
@@ -121,12 +177,13 @@ void Window::hot_reload() {
|
||||
Logger::error("Can't Find Monitor");
|
||||
}
|
||||
}
|
||||
update_viewport();
|
||||
if (!m_mouse_enable) {
|
||||
glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
} else {
|
||||
glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
}
|
||||
m_config.set("window.width", windowed_width);
|
||||
m_config.set("window.height", windowed_height);
|
||||
}
|
||||
|
||||
void Window::toggle_fullscreen() {
|
||||
@@ -148,10 +205,14 @@ void Window::toggle_fullscreen() {
|
||||
GL_DONT_CARE);
|
||||
m_config.set("window.fullscreen", true);
|
||||
}
|
||||
update_viewport();
|
||||
m_config.set("window.width", windowed_width);
|
||||
m_config.set("window.height", windowed_height);
|
||||
}
|
||||
|
||||
void Window::toggle_mouse_able() {
|
||||
if (!m_game_running) {
|
||||
m_mouse_enable = true;
|
||||
}
|
||||
// auto& io = ImGui::GetIO();
|
||||
if (m_mouse_enable) {
|
||||
// io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
|
||||
@@ -166,7 +227,20 @@ void Window::toggle_mouse_able() {
|
||||
glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
m_mouse_enable = true;
|
||||
}
|
||||
|
||||
if (m_camera) {
|
||||
m_camera->reset_camera();
|
||||
}
|
||||
}
|
||||
void Window::set_camera(Camera* camera) { m_camera = camera; }
|
||||
Camera* Window::camera() { return m_camera; }
|
||||
void Window::set_game_running(bool running) {
|
||||
m_game_running = 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;
|
||||
|
||||
Reference in New Issue
Block a user