feat: add hotbar system with ItemStack and RowLayout

This commit is contained in:
2026-07-21 14:51:03 +08:00
parent 51f36e3dfc
commit 3b529cb9a4
22 changed files with 214 additions and 55 deletions

View File

@@ -5,6 +5,7 @@
#include "Cubed/gameplay/chunk_pos.hpp" #include "Cubed/gameplay/chunk_pos.hpp"
#include "Cubed/gameplay/game_mode.hpp" #include "Cubed/gameplay/game_mode.hpp"
#include "Cubed/gameplay/game_time.hpp" #include "Cubed/gameplay/game_time.hpp"
#include "Cubed/gameplay/item_stack.hpp"
#include "Cubed/gameplay/player.hpp" #include "Cubed/gameplay/player.hpp"
#include "Cubed/input/event.hpp" #include "Cubed/input/event.hpp"
#include "Cubed/input/input.hpp" #include "Cubed/input/input.hpp"
@@ -18,6 +19,7 @@ namespace Cubed {
class ClientWorld; class ClientWorld;
class ClientPlayer { class ClientPlayer {
public: public:
static constexpr size_t HOTBAR_SUM = 10;
static constexpr float WALK_SOUND_INTERVAL = 0.45f; static constexpr float WALK_SOUND_INTERVAL = 0.45f;
static constexpr float RUN_SOUND_INTERVAL = 0.3f; static constexpr float RUN_SOUND_INTERVAL = 0.3f;
using ChunkPosSet = absl::flat_hash_set<ChunkPos, ChunkPos::Hash>; using ChunkPosSet = absl::flat_hash_set<ChunkPos, ChunkPos::Hash>;
@@ -47,7 +49,6 @@ public:
void change_mode(GameMode mode); void change_mode(GameMode mode);
void reload_config(); void reload_config();
void set_player_pos(const glm::vec3& pos); void set_player_pos(const glm::vec3& pos);
void set_place_block(unsigned id);
void update(float delta_time); void update(float delta_time);
float& max_walk_speed(); float& max_walk_speed();
@@ -58,7 +59,7 @@ public:
float& g(); float& g();
float& fly_y_speed(); float& fly_y_speed();
unsigned get_current_block() const; const ItemStack& get_current_itemstack() const;
void set_gait(Gait gait); void set_gait(Gait gait);
GameMode& game_mode(); GameMode& game_mode();
@@ -82,6 +83,8 @@ public:
void set_underwater(bool u); void set_underwater(bool u);
void place_block(float dt); void place_block(float dt);
std::span<const ItemStack, HOTBAR_SUM> get_hotbar() const;
private: private:
using enum GameMode; using enum GameMode;
float m_max_walk_speed = DEFAULT_MAX_WALK_SPEED; float m_max_walk_speed = DEFAULT_MAX_WALK_SPEED;
@@ -89,12 +92,13 @@ private:
float m_acceleration = DEFAULT_ACCELERATION; float m_acceleration = DEFAULT_ACCELERATION;
float m_deceleration = DEFAULT_DECELERATION; float m_deceleration = DEFAULT_DECELERATION;
float m_g = DEFAULT_G; float m_g = DEFAULT_G;
constexpr static float MAX_SPACE_ON_TIME = 0.3f; static constexpr float MAX_SPACE_ON_TIME = 0.3f;
constexpr static float PLACE_BLOCK_INTERVAL = 0.2f; static constexpr float PLACE_BLOCK_INTERVAL = 0.2f;
float m_place_time = PLACE_BLOCK_INTERVAL; float m_place_time = PLACE_BLOCK_INTERVAL;
std::atomic<float> m_yaw = 0.0f; std::atomic<float> m_yaw = 0.0f;
std::atomic<float> m_pitch = 0.0f; std::atomic<float> m_pitch = 0.0f;
std::array<ItemStack, HOTBAR_SUM> m_hotbar;
float m_sensitivity = 0.15f; float m_sensitivity = 0.15f;
float m_max_speed = m_max_walk_speed; float m_max_speed = m_max_walk_speed;
@@ -108,7 +112,7 @@ private:
float m_xz_speed = 0.0f; float m_xz_speed = 0.0f;
unsigned m_place_block = 1; int m_current_hotbar = 0;
bool m_moving = false; bool m_moving = false;
bool m_sprinting = false; bool m_sprinting = false;

View File

@@ -0,0 +1,8 @@
#pragma once
#include "Cubed/gameplay/block.hpp"
namespace Cubed {
struct ItemStack {
BlockType type = 0;
size_t sum = 0;
};
} // namespace Cubed

View File

@@ -48,7 +48,7 @@ public:
const Texture* get_cross_plane_array() const; const Texture* get_cross_plane_array() const;
const Texture* get_image_texture(const std::string& path); const Texture* get_image_texture(const std::string& path);
const Texture* get_pbr_texture() const; const Texture* get_pbr_texture() const;
const std::vector<std::unique_ptr<Texture>>& item_textures() const; const std::vector<std::unique_ptr<Texture>>& get_item_textures() const;
const Texture* get_skin() const; const Texture* get_skin() const;
void init_texture(); void init_texture();

View File

@@ -12,9 +12,6 @@ public:
ColumnLayout& operator=(ColumnLayout&&) = delete; ColumnLayout& operator=(ColumnLayout&&) = delete;
ColumnLayout(Widget* parent); ColumnLayout(Widget* parent);
~ColumnLayout(); ~ColumnLayout();
void update(float dt) override;
float width() const override; float width() const override;
float height() const override; float height() const override;
@@ -29,5 +26,7 @@ private:
float m_content_height = 0.0f; float m_content_height = 0.0f;
float m_content_width = 0.0f; float m_content_width = 0.0f;
ColumnLayoutAnchor m_layout_anchor = ColumnLayoutAnchor::CENTER; ColumnLayoutAnchor m_layout_anchor = ColumnLayoutAnchor::CENTER;
void on_update(float dt) override;
}; };
} // namespace Cubed } // namespace Cubed

View File

@@ -13,8 +13,13 @@ public:
Image& operator=(const Image&) = delete; Image& operator=(const Image&) = delete;
Image& operator=(Image&&) = delete; Image& operator=(Image&&) = delete;
Image(Widget* parent); Image(Widget* parent);
// If you need to set width and height to the material's size, pass true,
Image& set_image(const std::string& path, TextureManager& texture_manager); // If you set fill parent, please pass false.
Image& set_image(const std::string& path, TextureManager& texture_manager,
bool change_size);
// If you need to set width and height to the material's size, pass true
// If you set fill parent, please pass false.
Image& set_texture(const Texture* texture, bool change_size);
float width() const override; float width() const override;
float height() const override; float height() const override;
const Texture* texture() const; const Texture* texture() const;

View File

@@ -0,0 +1,22 @@
#pragma once
#include "Cubed/ui/widget.hpp"
namespace Cubed {
class RowLayout : public Widget {
public:
RowLayout(Widget* parent);
~RowLayout();
float width() const override;
float height() const override;
RowLayout& set_spacing(int spacing);
void layout();
private:
int m_spacing = 0;
float m_content_height = 0.0f;
float m_content_width = 0.0f;
void on_update(float dt) override;
};
} // namespace Cubed

View File

@@ -2,6 +2,7 @@
#include "Cubed/ui/chat_box.hpp" #include "Cubed/ui/chat_box.hpp"
#include "Cubed/ui/image.hpp" #include "Cubed/ui/image.hpp"
#include "Cubed/ui/row_layout.hpp"
#include "Cubed/ui/ui_manager.hpp" #include "Cubed/ui/ui_manager.hpp"
#include "Cubed/ui/widget.hpp" #include "Cubed/ui/widget.hpp"
@@ -26,10 +27,14 @@ public:
private: private:
bool handle_key_event(const KeyEvent& e) override; bool handle_key_event(const KeyEvent& e) override;
void update_hotbar();
WorldScene& m_scene; WorldScene& m_scene;
ChatBox* m_chat_box = nullptr; ChatBox* m_chat_box = nullptr;
Image* m_mircophone = nullptr; Image* m_mircophone = nullptr;
Label* m_disbable_voice = nullptr; Label* m_disbable_voice = nullptr;
RowLayout* m_hotbar = nullptr;
std::vector<Image*> m_hotbar_items;
}; };
} // namespace Cubed } // namespace Cubed

View File

@@ -89,4 +89,5 @@ target_sources(${PROJECT_NAME}
audio/audio_recording.cpp audio/audio_recording.cpp
audio/audio_stream_source.cpp audio/audio_stream_source.cpp
tools/sensitive_filter.cpp tools/sensitive_filter.cpp
ui/row_layout.cpp
) )

View File

@@ -126,8 +126,6 @@ void ClientPlayer::reload_config() {
} }
void ClientPlayer::set_player_pos(const glm::vec3& pos) { m_player_pos = pos; } void ClientPlayer::set_player_pos(const glm::vec3& pos) { m_player_pos = pos; }
void ClientPlayer::set_place_block(unsigned id) { m_place_block = id; }
void ClientPlayer::update(float delta_time) { void ClientPlayer::update(float delta_time) {
m_gait = compute_gait(); m_gait = compute_gait();
update_move(delta_time); update_move(delta_time);
@@ -207,6 +205,26 @@ bool ClientPlayer::update_player_move_state(Key key, KeyAction action) {
change_mode(CREATIVE); change_mode(CREATIVE);
} }
} }
} else if (key == Key::NUMPAD_1 || key == Key::DIGIT_1) {
m_current_hotbar = 0;
} else if (key == Key::NUMPAD_2 || key == Key::DIGIT_2) {
m_current_hotbar = 1;
} else if (key == Key::NUMPAD_3 || key == Key::DIGIT_3) {
m_current_hotbar = 2;
} else if (key == Key::NUMPAD_4 || key == Key::DIGIT_4) {
m_current_hotbar = 3;
} else if (key == Key::NUMPAD_5 || key == Key::DIGIT_5) {
m_current_hotbar = 4;
} else if (key == Key::NUMPAD_6 || key == Key::DIGIT_6) {
m_current_hotbar = 5;
} else if (key == Key::NUMPAD_7 || key == Key::DIGIT_7) {
m_current_hotbar = 6;
} else if (key == Key::NUMPAD_8 || key == Key::DIGIT_8) {
m_current_hotbar = 7;
} else if (key == Key::NUMPAD_9 || key == Key::DIGIT_9) {
m_current_hotbar = 8;
} else if (key == Key::NUMPAD_0 || key == Key::DIGIT_0) {
m_current_hotbar = 9;
} else { } else {
return false; return false;
} }
@@ -287,16 +305,25 @@ void ClientPlayer::place_block(float dt) {
} }
} }
if (m_mouse_state.right) { if (m_mouse_state.right) {
glm::ivec3 near_pos = m_look_block->pos + m_look_block->normal; auto type = m_hotbar[m_current_hotbar].type;
if (!m_world.is_solid(near_pos)) { if (type != 0) {
AABB block_box = ClientWorld::get_block_aabb(near_pos); glm::ivec3 near_pos = m_look_block->pos + m_look_block->normal;
AABB player_box = get_aabb(get_player_pos()); if (!m_world.is_solid(near_pos)) {
if (!player_box.intersects(block_box)) { AABB block_box = ClientWorld::get_block_aabb(near_pos);
m_world.report_block_change(near_pos, m_place_block); AABB player_box = get_aabb(get_player_pos());
if (!player_box.intersects(block_box)) {
m_world.report_block_change(near_pos, type);
}
} }
} }
} }
} }
std::span<const ItemStack, ClientPlayer::HOTBAR_SUM>
ClientPlayer::get_hotbar() const {
return m_hotbar;
}
void ClientPlayer::update_move(float delta_time) { void ClientPlayer::update_move(float delta_time) {
// if frame rate less than 1 frame per second, don't update // if frame rate less than 1 frame per second, don't update
if (delta_time > 1.0f) { if (delta_time > 1.0f) {
@@ -537,14 +564,14 @@ bool ClientPlayer::update_scroll(float yoffset) {
} }
if (m_game_mode == CREATIVE) { if (m_game_mode == CREATIVE) {
if (yoffset < 0) { if (yoffset < 0) {
m_place_block += 1; m_current_hotbar += 1;
if (m_place_block >= BlockManager::sums()) { if (m_current_hotbar >= 10) {
m_place_block = 1; m_current_hotbar = 0;
} }
} else { } else {
m_place_block -= 1; m_current_hotbar -= 1;
if (m_place_block <= 0) { if (m_current_hotbar < 0) {
m_place_block = BlockManager::sums() - 1; m_current_hotbar = 0;
} }
} }
} }
@@ -615,7 +642,9 @@ float& ClientPlayer::acceleration() { return m_acceleration; }
float& ClientPlayer::deceleration() { return m_deceleration; } float& ClientPlayer::deceleration() { return m_deceleration; }
float& ClientPlayer::g() { return m_g; } float& ClientPlayer::g() { return m_g; }
float& ClientPlayer::fly_y_speed() { return m_fly_y_speed; } float& ClientPlayer::fly_y_speed() { return m_fly_y_speed; }
unsigned ClientPlayer::get_current_block() const { return m_place_block; }; const ItemStack& ClientPlayer::get_current_itemstack() const {
return m_hotbar[m_current_hotbar];
};
void ClientPlayer::set_gait(Gait gait) { m_gait = gait; } void ClientPlayer::set_gait(Gait gait) { m_gait = gait; }
GameMode& ClientPlayer::game_mode() { return m_game_mode; } GameMode& ClientPlayer::game_mode() { return m_game_mode; }
ClientWorld& ClientPlayer::get_world() { return m_world; } ClientWorld& ClientPlayer::get_world() { return m_world; }
@@ -662,6 +691,10 @@ void ClientPlayer::init(std::string_view name) {
audio.play_3d(sound, m_player_pos); audio.play_3d(sound, m_player_pos);
Logger::debug("Player block {} walk sound", name); Logger::debug("Player block {} walk sound", name);
}); });
for (int i = 0; i < 10; i++) {
m_hotbar[i].type = i;
}
} }
bool ClientPlayer::is_underwater() const { return m_underwater; } bool ClientPlayer::is_underwater() const { return m_underwater; }

View File

@@ -7,10 +7,10 @@
#include "Cubed/tools/shader_tools.hpp" #include "Cubed/tools/shader_tools.hpp"
namespace { namespace {
constexpr int BLOCK_SIZE = 512; constexpr int BLOCK_SIZE = 16;
constexpr int BLOCK_NORMAL_SIZE = 128; constexpr int BLOCK_NORMAL_SIZE = 128;
constexpr int CROSS_PLANE_SIZE = 16; constexpr int CROSS_PLANE_SIZE = 16;
constexpr int BLOCK_ITEM_SIZE = 16; constexpr int BLOCK_ITEM_SIZE = 512;
constexpr int BLOCK_STATUS_SIZE = 16; constexpr int BLOCK_STATUS_SIZE = 16;
constexpr int SKIN_SIZE = 64; constexpr int SKIN_SIZE = 64;
@@ -70,7 +70,7 @@ const Texture* TextureManager::get_pbr_texture() const {
} }
const std::vector<std::unique_ptr<Texture>>& const std::vector<std::unique_ptr<Texture>>&
TextureManager::item_textures() const { TextureManager::get_item_textures() const {
return m_item_textures; return m_item_textures;
} }
@@ -136,7 +136,6 @@ void TextureManager::load_block_item_texture(unsigned id) {
BLOCK_ITEM_SIZE); BLOCK_ITEM_SIZE);
texture->set_nearest(); texture->set_nearest();
texture->set_clamp_to_border();
m_item_textures.push_back(std::move(texture)); m_item_textures.push_back(std::move(texture));
} }

View File

@@ -93,7 +93,7 @@ Button& Button::set_height(float height) {
Button& Button::set_background_image(const std::string& path, Button& Button::set_background_image(const std::string& path,
TextureManager& texture_manager) { TextureManager& texture_manager) {
m_background->set_image(path, texture_manager); m_background->set_image(path, texture_manager, false);
return *this; return *this;
} }

View File

@@ -6,10 +6,7 @@ ColumnLayout::ColumnLayout(Widget* parent) : Widget(parent) {
} }
ColumnLayout::~ColumnLayout() {} ColumnLayout::~ColumnLayout() {}
void ColumnLayout::update(float dt) { void ColumnLayout::on_update(float) { layout(); }
Widget::update(dt);
layout();
}
float ColumnLayout::width() const { return m_content_width; } float ColumnLayout::width() const { return m_content_width; }
float ColumnLayout::height() const { return m_content_height; } float ColumnLayout::height() const { return m_content_height; }

View File

@@ -18,7 +18,7 @@ void CreditsUI::init() {
auto image = std::make_unique<Image>(nullptr); auto image = std::make_unique<Image>(nullptr);
image image
->set_image("texture/ui/background.png", ->set_image("texture/ui/background.png",
m_scene.scene_manager().app().texture_manager()) m_scene.scene_manager().app().texture_manager(), false)
.set_anchor(Anchor::TOP_LEFT) .set_anchor(Anchor::TOP_LEFT)
.set_window_size(renderer.window_width(), renderer.window_height()) .set_window_size(renderer.window_width(), renderer.window_height())
.set_fill_parent(true); .set_fill_parent(true);

View File

@@ -15,7 +15,7 @@ void ErrorUI::init() {
bi->set_window_size(renderer.window_width(), renderer.window_height()); bi->set_window_size(renderer.window_width(), renderer.window_height());
bi->set_anchor(Anchor::TOP_LEFT); bi->set_anchor(Anchor::TOP_LEFT);
bi->set_image("texture/ui/background.png", texture_manager); bi->set_image("texture/ui/background.png", texture_manager, false);
bi->set_fill_parent(true); bi->set_fill_parent(true);
auto& rect = bi->add_child<Rect>(); auto& rect = bi->add_child<Rect>();

View File

@@ -18,7 +18,7 @@ void HostGameUI::init() {
bi->set_window_size(renderer.window_width(), renderer.window_height()); bi->set_window_size(renderer.window_width(), renderer.window_height());
bi->set_anchor(Anchor::TOP_LEFT); bi->set_anchor(Anchor::TOP_LEFT);
bi->set_image("texture/ui/background.png", texture_manager); bi->set_image("texture/ui/background.png", texture_manager, false);
bi->set_fill_parent(true); bi->set_fill_parent(true);
auto& rect = bi->add_child<Rect>(); auto& rect = bi->add_child<Rect>();
@@ -50,7 +50,7 @@ void HostGameUI::init() {
text_seed.set_show_text(tr("hostgame.world_seed")); text_seed.set_show_text(tr("hostgame.world_seed"));
text_seed.set_app(&m_scene.scene_manager().app()); text_seed.set_app(&m_scene.scene_manager().app());
std::unique_ptr<Image> back = std::make_unique<Image>(&text_seed); std::unique_ptr<Image> back = std::make_unique<Image>(&text_seed);
back->set_image(DEFAULT_TEXT_FIELD_IMAGE, texture_manager) back->set_image(DEFAULT_TEXT_FIELD_IMAGE, texture_manager, false)
.set_fill_parent(true); .set_fill_parent(true);
text_seed.set_background(std::move(back)); text_seed.set_background(std::move(back));
text_seed.set_on_finish([this, &text_seed]() { text_seed.set_on_finish([this, &text_seed]() {
@@ -72,7 +72,7 @@ void HostGameUI::init() {
{ {
auto& text_port = layout.add_child<TextField>(); auto& text_port = layout.add_child<TextField>();
std::unique_ptr<Image> back = std::make_unique<Image>(&text_port); std::unique_ptr<Image> back = std::make_unique<Image>(&text_port);
back->set_image(DEFAULT_TEXT_FIELD_IMAGE, texture_manager) back->set_image(DEFAULT_TEXT_FIELD_IMAGE, texture_manager, false)
.set_fill_parent(true); .set_fill_parent(true);
text_port.set_background(std::move(back)); text_port.set_background(std::move(back));
text_port.set_show_text(tr("hostgame.port")); text_port.set_show_text(tr("hostgame.port"));

View File

@@ -7,17 +7,43 @@ namespace Cubed {
Image::Image(Widget* parent) : Widget(parent) {} Image::Image(Widget* parent) : Widget(parent) {}
void Image::on_render(Renderer& renderer) { void Image::on_render(Renderer& renderer) {
renderer.render_image(*this); if (m_texture) {
renderer.render_image(*this);
}
Widget::on_render(renderer); Widget::on_render(renderer);
} }
void Image::on_update(float dt) { Widget::on_update(dt); } void Image::on_update(float dt) { Widget::on_update(dt); }
Image& Image::set_image(const std::string& path, Image& Image::set_image(const std::string& path,
TextureManager& texture_manager) { TextureManager& texture_manager, bool change_size) {
if (m_fill_parent && change_size) {
Logger::warn("Fill Parent is True don't change size");
}
m_texture = texture_manager.get_image_texture(path); m_texture = texture_manager.get_image_texture(path);
m_width = m_texture->width(); if (change_size) {
m_height = m_texture->height(); m_width = m_texture->width();
m_height = m_texture->height();
}
return *this; return *this;
} }
Image& Image::set_texture(const Texture* texture, bool change_size) {
if (m_fill_parent && change_size) {
Logger::warn("Fill Parent is True don't change size");
}
m_texture = texture;
if (change_size) {
if (m_texture) {
m_width = m_texture->width();
m_height = m_texture->height();
} else {
m_width = 0;
m_height = 0;
}
}
return *this;
}
Image& Image::set_scale(float scale) { Image& Image::set_scale(float scale) {
m_scale = scale; m_scale = scale;
return *this; return *this;
@@ -25,7 +51,7 @@ Image& Image::set_scale(float scale) {
float Image::scale() const { return m_scale; } float Image::scale() const { return m_scale; }
float Image::height() const { float Image::height() const {
if (!m_texture) { if (!m_texture) {
Logger::error("Image not set image!"); // Logger::error("Image not set image!");
return 0.0f; return 0.0f;
} }
if (m_fill_height || m_fill_parent) { if (m_fill_height || m_fill_parent) {
@@ -36,7 +62,7 @@ float Image::height() const {
float Image::width() const { float Image::width() const {
if (!m_texture) { if (!m_texture) {
Logger::error("Image not set image!"); // Logger::error("Image not set image!");
return 0.0f; return 0.0f;
} }
if (m_fill_parent || m_fill_width) { if (m_fill_parent || m_fill_width) {

View File

@@ -16,7 +16,7 @@ void JoinGameUI::init() {
bi->set_window_size(renderer.window_width(), renderer.window_height()); bi->set_window_size(renderer.window_width(), renderer.window_height());
bi->set_anchor(Anchor::TOP_LEFT); bi->set_anchor(Anchor::TOP_LEFT);
bi->set_image("texture/ui/background.png", texture_manager); bi->set_image("texture/ui/background.png", texture_manager, false);
bi->set_fill_parent(true); bi->set_fill_parent(true);
auto& rect = bi->add_child<Rect>(); auto& rect = bi->add_child<Rect>();
@@ -47,7 +47,7 @@ void JoinGameUI::init() {
auto& text_ip = layout.add_child<TextField>(); auto& text_ip = layout.add_child<TextField>();
text_ip.set_show_text(tr("joingame.server_ip")); text_ip.set_show_text(tr("joingame.server_ip"));
std::unique_ptr<Image> back = std::make_unique<Image>(&text_ip); std::unique_ptr<Image> back = std::make_unique<Image>(&text_ip);
back->set_image(DEFAULT_TEXT_FIELD_IMAGE, texture_manager) back->set_image(DEFAULT_TEXT_FIELD_IMAGE, texture_manager, false)
.set_fill_parent(true); .set_fill_parent(true);
text_ip.set_background(std::move(back)); text_ip.set_background(std::move(back));
text_ip.set_app(&m_scene.scene_manager().app()); text_ip.set_app(&m_scene.scene_manager().app());

View File

@@ -20,7 +20,7 @@ void MainMenuUIManager::init() {
auto& texture_manager = m_scene.scene_manager().app().texture_manager(); auto& texture_manager = m_scene.scene_manager().app().texture_manager();
image->set_fill_parent(true); image->set_fill_parent(true);
image->set_anchor(Anchor::TOP_LEFT); image->set_anchor(Anchor::TOP_LEFT);
image->set_image("texture/ui/background.png", texture_manager); image->set_image("texture/ui/background.png", texture_manager, false);
auto& renderer = m_scene.scene_manager().app().renderer(); auto& renderer = m_scene.scene_manager().app().renderer();
image->set_window_size(renderer.window_width(), renderer.window_height()); image->set_window_size(renderer.window_width(), renderer.window_height());

26
src/ui/row_layout.cpp Normal file
View File

@@ -0,0 +1,26 @@
#include "Cubed/ui/row_layout.hpp"
namespace Cubed {
RowLayout::RowLayout(Widget* parent) : Widget(parent) {}
RowLayout::~RowLayout() {}
void RowLayout::on_update(float) { layout(); }
float RowLayout::width() const { return m_content_width; }
float RowLayout::height() const { return m_content_height; }
RowLayout& RowLayout::set_spacing(int spacing) {
m_spacing = spacing;
return *this;
}
void RowLayout::layout() {
auto& children = Widget::children();
int x = 0;
for (auto& child : children) {
child->set_anchor(Anchor::TOP_LEFT);
child->set_offset({x, 0});
x += child->width() + m_spacing;
m_content_height = std::max(m_content_height, child->height());
}
m_content_width = children.empty() ? 0 : (x - m_spacing);
}
} // namespace Cubed

View File

@@ -20,7 +20,7 @@ void SettingsUI::init() {
bi->set_window_size(renderer.window_width(), renderer.window_height()); bi->set_window_size(renderer.window_width(), renderer.window_height());
bi->set_anchor(Anchor::TOP_LEFT); bi->set_anchor(Anchor::TOP_LEFT);
bi->set_image("texture/ui/background.png", texture_manager); bi->set_image("texture/ui/background.png", texture_manager, false);
bi->set_fill_parent(true); bi->set_fill_parent(true);
auto& rect = bi->add_child<Rect>(); auto& rect = bi->add_child<Rect>();

View File

@@ -107,12 +107,12 @@ Slider& Slider::set_slider_text(const std::string& key,
} }
Slider& Slider::set_track_image(const std::string& path, Slider& Slider::set_track_image(const std::string& path,
TextureManager& texture_manager) { TextureManager& texture_manager) {
m_track->set_image(path, texture_manager); m_track->set_image(path, texture_manager, false);
return *this; return *this;
} }
Slider& Slider::set_thumb_image(const std::string& path, Slider& Slider::set_thumb_image(const std::string& path,
TextureManager& texture_manager) { TextureManager& texture_manager) {
m_thumb->set_image(path, texture_manager); m_thumb->set_image(path, texture_manager, true);
return *this; return *this;
} }

View File

@@ -24,7 +24,7 @@ void WorldUIManager::init() {
auto& texture_manager = m_scene.scene_manager().app().texture_manager(); auto& texture_manager = m_scene.scene_manager().app().texture_manager();
auto& crosshair = m_root_widget->add_child<Image>(); auto& crosshair = m_root_widget->add_child<Image>();
crosshair.set_image("texture/ui/0.png", texture_manager); crosshair.set_image("texture/ui/0.png", texture_manager, true);
crosshair.set_anchor(Anchor::CENTER); crosshair.set_anchor(Anchor::CENTER);
crosshair.set_scale(3.0f); crosshair.set_scale(3.0f);
@@ -57,7 +57,7 @@ void WorldUIManager::init() {
}); });
m_chat_box = &chat_box; m_chat_box = &chat_box;
auto& microphone = m_root_widget->add_child<Image>(); auto& microphone = m_root_widget->add_child<Image>();
microphone.set_image("texture/ui/microphone.png", texture_manager) microphone.set_image("texture/ui/microphone.png", texture_manager, true)
.set_scale(5.0f) .set_scale(5.0f)
.set_anchor(Anchor::BOTTOM_RIGHT) .set_anchor(Anchor::BOTTOM_RIGHT)
.set_visible(false); .set_visible(false);
@@ -70,6 +70,21 @@ void WorldUIManager::init() {
.set_offset({0, -5}); .set_offset({0, -5});
disbale_voice.set_anchor(Anchor::BOTTOM_RIGHT).set_visible(false); disbale_voice.set_anchor(Anchor::BOTTOM_RIGHT).set_visible(false);
m_disbable_voice = &disbale_voice; m_disbable_voice = &disbale_voice;
{
auto& hotbar = m_root_widget->add_child<RowLayout>();
hotbar.set_anchor(Anchor::BOTTOM_CENTER);
m_hotbar = &hotbar;
for (size_t i = 0; i < ClientPlayer::HOTBAR_SUM; ++i) {
auto& bg = hotbar.add_child<Image>();
bg.set_image("texture/ui/slot.png", texture_manager, true);
bg.set_scale(5.0f);
auto& item = bg.add_child<Image>();
item.set_fill_parent(true).set_anchor(Anchor::CENTER);
m_hotbar_items.emplace_back(&item);
}
update_hotbar();
}
} }
void WorldUIManager::render(Renderer& renderer) { void WorldUIManager::render(Renderer& renderer) {
renderer.begin_render_ui(); renderer.begin_render_ui();
@@ -94,6 +109,8 @@ void WorldUIManager::update(float dt) {
m_mircophone->set_visible(false); m_mircophone->set_visible(false);
m_disbable_voice->set_visible(false); m_disbable_voice->set_visible(false);
} }
update_hotbar();
} }
void WorldUIManager::set_chatting(bool chantting, bool send) { void WorldUIManager::set_chatting(bool chantting, bool send) {
@@ -111,4 +128,21 @@ bool WorldUIManager::handle_key_event(const KeyEvent& e) {
return UIManager::handle_key_event(e); return UIManager::handle_key_event(e);
} }
void WorldUIManager::update_hotbar() {
if (!m_hotbar) {
return;
}
auto& texture_manager = m_scene.scene_manager().app().texture_manager();
auto& item_texture = texture_manager.get_item_textures();
auto hotbar = m_scene.client_world().get_player().get_hotbar();
for (size_t i = 0; i < ClientPlayer::HOTBAR_SUM; ++i) {
auto type = hotbar[i].type;
if (type == 0) {
m_hotbar_items[i]->set_texture(nullptr, false);
} else {
m_hotbar_items[i]->set_texture(item_texture[type].get(), false);
}
}
}
} // namespace Cubed } // namespace Cubed