feat(main_menu): add exit button and refactor layout with ColumnLayout

- Add `should_close_window()` method to force window close from UI.
- Replace standalone button with ColumnLayout for proper centering.
- Add "Exit" button that calls `should_close_window()`.
- Update ESC key handling to only close window when game is not running.
- Fix ColumnLayout to respect parent's anchor instead of hardcoded TOP_LEFT.
- Remove unused parameter name in Image::update for consistency.
This commit is contained in:
2026-07-13 18:15:34 +08:00
parent e7082bdbe0
commit acb0b94d7b
5 changed files with 45 additions and 19 deletions

View File

@@ -16,7 +16,7 @@ void ColumnLayout::layout() {
int y = 0;
for (auto& child : children) {
child->set_offset({0, y});
child->set_anchor(Anchor::TOP_LEFT);
child->set_anchor(m_anchor);
y += child->height() + m_spacing;
}
}

View File

@@ -5,7 +5,7 @@
namespace Cubed {
Image::Image(Widget* parent) : Widget(parent) {}
void Image::update(float dt) { (void)dt; }
void Image::update(float) {}
void Image::render(Renderer& renderer) { renderer.render_image(*this); }
Image& Image::set_image(const std::string& path,

View File

@@ -5,29 +5,48 @@
#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& renderer = m_scene.scene_manager().app().renderer();
auto layout = std::make_unique<ColumnLayout>(nullptr);
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 start_game_button = std::make_unique<Button>(nullptr);
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& 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_window_size(
m_scene.scene_manager().app().renderer().window_width(),
m_scene.scene_manager().app().renderer().window_height());
start_game_button->set_clicked(
[this]() { m_scene.scene_manager().request_push(SceneType::WORLD); });
start_game_button->set_scale(3.0f);
start_game_button->set_anchor(Anchor::CENTER);
m_widgets.try_emplace("start game", std::move(start_game_button));
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("main menu layout", std::move(layout));
}
void MainMenuUIManager::update(float dt) {

View File

@@ -73,8 +73,10 @@ bool Window::handle_key_event(const KeyEvent& e) {
return true;
}
if (e.key == Key::ESCAPE && e.action == KeyAction::PRESS) {
glfwSetWindowShouldClose(m_window, GLFW_TRUE);
return true;
if (!m_game_running) {
glfwSetWindowShouldClose(m_window, GLFW_TRUE);
return true;
}
}
if (e.key == Key::LEFT_ALT && e.action == KeyAction::PRESS) {
toggle_mouse_able();
@@ -237,6 +239,9 @@ void Window::set_game_running(bool running) {
m_mouse_enable = running;
toggle_mouse_able();
}
void Window::should_close_window() { glfwSetWindowShouldClose(m_window, true); }
void Window::imgui_init() {
float dpi_scale_x, dpi_scale_y;
glfwGetWindowContentScale(m_window, &dpi_scale_x, &dpi_scale_y);