From 5923f53ce4bcd0cadb1c21d4aa0b2e21c3890f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 25 Apr 2026 08:24:42 +0200 Subject: [PATCH] ADD: Main Menu Buttons + Quit Game Event --- CMakeLists.txt | 1 + assets/ui/btn/background.png | Bin 0 -> 32045 bytes src/engine/core/Application.cpp | 5 ++ src/engine/core/Window.h | 1 + .../gui/uiComponent/ClickableUiComponent.cpp | 1 - src/engine/platform/glfw/GLFWWindow.cpp | 6 ++ src/engine/platform/glfw/GLFWWindow.h | 1 + .../renderer/components/UiRenderBundle.h | 1 + src/game/scenes/main/MainMenu.cpp | 1 + src/game/scenes/main/MainMenu.h | 1 - src/game/scenes/main/MainUiLayer.cpp | 53 ++++++++++++++++++ src/game/scenes/main/MainUiLayer.h | 4 +- src/game/scenes/main/events/QuitEvent.h | 11 ++++ 13 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 assets/ui/btn/background.png create mode 100644 src/game/scenes/main/events/QuitEvent.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 87b4e6e..2f9ec57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -325,6 +325,7 @@ if(BUILD_GAME) src/game/scenes/main/MainMenu.h src/game/scenes/main/MainUiLayer.cpp src/game/scenes/main/MainUiLayer.h + src/game/scenes/main/events/QuitEvent.h ) target_compile_options(Dicewars_Siedler PRIVATE -Wall diff --git a/assets/ui/btn/background.png b/assets/ui/btn/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f5032b574f56c85847d55932bc1d624d187c7db2 GIT binary patch literal 32045 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 mouse = std::make_unique(*window); stateManager = std::make_unique(StateRegistry::get().empty, StateRegistry::get().game); + + EventBus::getInstance().subscribe([this](const QuitEvent& e) { + window->close(); + }); } Application::~Application() diff --git a/src/engine/core/Window.h b/src/engine/core/Window.h index 0de59a1..3f2bcb2 100644 --- a/src/engine/core/Window.h +++ b/src/engine/core/Window.h @@ -31,6 +31,7 @@ public: static Window* Create(const WindowProps& props); virtual bool shouldClose() const = 0; + virtual void close() const = 0; }; diff --git a/src/engine/core/gui/uiComponent/ClickableUiComponent.cpp b/src/engine/core/gui/uiComponent/ClickableUiComponent.cpp index 57c8833..5fd5625 100644 --- a/src/engine/core/gui/uiComponent/ClickableUiComponent.cpp +++ b/src/engine/core/gui/uiComponent/ClickableUiComponent.cpp @@ -30,7 +30,6 @@ void ClickableUiComponent::checkMouseButton(MouseButton button, Mouse &mouse) { void ClickableUiComponent::onUpdate(float dt) { if (blocked) return; - checkMouseOver(); if (mousedOver) { checkClicks(); diff --git a/src/engine/platform/glfw/GLFWWindow.cpp b/src/engine/platform/glfw/GLFWWindow.cpp index 3d100c8..5fd14b3 100644 --- a/src/engine/platform/glfw/GLFWWindow.cpp +++ b/src/engine/platform/glfw/GLFWWindow.cpp @@ -7,6 +7,7 @@ #include #include "../../core/events/EventBus.h" +#include "spdlog/spdlog.h" static bool s_GLFWINITIALIZED = false; @@ -26,6 +27,11 @@ GLFWWindow::~GLFWWindow() Shutdown(); } +void GLFWWindow::close() const { + spdlog::info("Closing window"); + glfwSetWindowShouldClose(m_Window, true); +} + void GLFWWindow::Init(const WindowProps& props) { m_Data.Title = props.Title; diff --git a/src/engine/platform/glfw/GLFWWindow.h b/src/engine/platform/glfw/GLFWWindow.h index 050d3ad..704ae01 100644 --- a/src/engine/platform/glfw/GLFWWindow.h +++ b/src/engine/platform/glfw/GLFWWindow.h @@ -29,6 +29,7 @@ public: bool shouldClose() const override; void* GetNativeWindow() const override { return m_Window; } + void close() const override; private: void Init(const WindowProps& props); diff --git a/src/engine/renderer/components/UiRenderBundle.h b/src/engine/renderer/components/UiRenderBundle.h index 123fe58..d781925 100644 --- a/src/engine/renderer/components/UiRenderBundle.h +++ b/src/engine/renderer/components/UiRenderBundle.h @@ -8,6 +8,7 @@ #include #include "../model/GUIText.h" +#include "spdlog/spdlog.h" class UiText; #include "../model/GUITexture.h" diff --git a/src/game/scenes/main/MainMenu.cpp b/src/game/scenes/main/MainMenu.cpp index 74099cd..a348a1c 100644 --- a/src/game/scenes/main/MainMenu.cpp +++ b/src/game/scenes/main/MainMenu.cpp @@ -19,5 +19,6 @@ void MainMenu::onExit() { std::vector MainMenu::getRequiredAssets() { std::vector requests; requests.emplace_back(TextureRequest("mainCover", "assets/background.png")); + requests.emplace_back(TextureRequest("btn_background", "assets/ui/btn/background.png")); return requests; } diff --git a/src/game/scenes/main/MainMenu.h b/src/game/scenes/main/MainMenu.h index 0043bba..54eb78e 100644 --- a/src/game/scenes/main/MainMenu.h +++ b/src/game/scenes/main/MainMenu.h @@ -6,7 +6,6 @@ #define MAINMENU_H #include "../../../engine/core/scenes/Scene.h" - class MainMenu: public Scene { public: void onEnter() override; diff --git a/src/game/scenes/main/MainUiLayer.cpp b/src/game/scenes/main/MainUiLayer.cpp index c2c9f40..27a2d6a 100644 --- a/src/game/scenes/main/MainUiLayer.cpp +++ b/src/game/scenes/main/MainUiLayer.cpp @@ -3,12 +3,59 @@ // #include "MainUiLayer.h" + +#include "../../../engine/core/EngineTime.h" +#include "../../../engine/core/gui/uiComponent/UiButton.h" #include "../../../engine/renderer/loader/AssetManager.h" +#include "events/QuitEvent.h" void MainUiLayer::onAttach() { + AssetManager::loadUiTheme("default", "assets/ui/uiTheme.json"); //Todo: Move to AssetLoader + rootContainer = std::make_unique(); rootContainer->setBackgroundTexture(AssetManager::getTexture("mainCover")->getTextureID()); + LayoutStyle btnStyle; + btnStyle.margin.top = SizeValue(0.3, SizeUnit::Percent); + btnStyle.margin.left = SizeValue(0.05, SizeUnit::Percent); + btnStyle.width = SizeValue(350, SizeUnit::Pixels); + btnStyle.height = SizeValue(90, SizeUnit::Pixels); + + rootContainer->addChild(std::make_unique(AssetManager::getTexture("btn_background")->getTextureID(), "Play", + *AssetManager::getUiTheme("default")->large, btnStyle)); + + LayoutStyle btnStyle2; + btnStyle2.margin.top = SizeValue(15, SizeUnit::Pixels); + btnStyle2.margin.left = SizeValue(0.05, SizeUnit::Percent); + btnStyle2.width = SizeValue(350, SizeUnit::Pixels); + btnStyle2.height = SizeValue(90, SizeUnit::Pixels); + + rootContainer->addChild(std::make_unique(AssetManager::getTexture("btn_background")->getTextureID(), "New Game", + *AssetManager::getUiTheme("default")->large, btnStyle2)); + + LayoutStyle btnStyle3; + btnStyle3.margin.top = SizeValue(15, SizeUnit::Pixels); + btnStyle3.margin.left = SizeValue(0.05, SizeUnit::Percent); + btnStyle3.width = SizeValue(350, SizeUnit::Pixels); + btnStyle3.height = SizeValue(90, SizeUnit::Pixels); + rootContainer->addChild(std::make_unique(AssetManager::getTexture("btn_background")->getTextureID(), "Settings", + *AssetManager::getUiTheme("default")->large, btnStyle3)); + + LayoutStyle btnStyle4; + btnStyle4.margin.top = SizeValue(15, SizeUnit::Pixels); + btnStyle4.margin.left = SizeValue(0.05, SizeUnit::Percent); + btnStyle4.width = SizeValue(350, SizeUnit::Pixels); + btnStyle4.height = SizeValue(90, SizeUnit::Pixels); + auto quitButton = rootContainer->addChild(std::make_unique(AssetManager::getTexture("btn_background")->getTextureID(), "Quit", + *AssetManager::getUiTheme("default")->large, btnStyle4)); + + quitButton->addMouseListener([this](const MouseEventData& eventData) { + if (eventData.isCompleteClick(MouseButton::LEFT)) { + spdlog::info("Quit Button clicked"); + EventBus::getInstance().emit(QuitEvent{}); + } + }); + } void MainUiLayer::onDetach() { @@ -23,9 +70,15 @@ void MainUiLayer::onRender() { auto guis = renderBundle.getGUITextures(); guiRenderer->render(guis); + + const auto renderTexts = renderBundle.getGUITexts(); + textRenderer->renderGuiTexts(renderTexts, static_cast(Application::getInstance().getWindow().GetWidth()), + static_cast(Application::getInstance().getWindow().GetHeight())); } void MainUiLayer::onUpdate() { Dimensions rootParent {0.0, 0.0, 1.0, 1.0f}; rootContainer->uiPositioner.compute(rootParent); + + rootContainer->update(EngineTime::deltaTime); } diff --git a/src/game/scenes/main/MainUiLayer.h b/src/game/scenes/main/MainUiLayer.h index 6c65adc..788b666 100644 --- a/src/game/scenes/main/MainUiLayer.h +++ b/src/game/scenes/main/MainUiLayer.h @@ -8,16 +8,18 @@ #include "../../../engine/renderer/GUIRenderer.h" #include "../../../engine/renderer/loader/Loader.h" #include "../../../engine/core/gui/uiMain/UiContainer.h" +#include "../../../engine/renderer/TextRenderer.h" class MainUiLayer: public Layer { public: - MainUiLayer(): guiRenderer(std::make_unique(Loader::instance())) {} + MainUiLayer(): guiRenderer(std::make_unique(Loader::instance())), textRenderer(std::make_unique()) {} void onAttach() override; void onDetach() override; void onRender() override; void onUpdate() override; private: std::unique_ptr guiRenderer; + std::unique_ptr textRenderer; std::unique_ptr rootContainer; }; diff --git a/src/game/scenes/main/events/QuitEvent.h b/src/game/scenes/main/events/QuitEvent.h new file mode 100644 index 0000000..d48ae19 --- /dev/null +++ b/src/game/scenes/main/events/QuitEvent.h @@ -0,0 +1,11 @@ +// +// Created by sebastian on 25.04.26. +// + +#ifndef QUITEVENT_H +#define QUITEVENT_H +struct QuitEvent { + +}; + +#endif //QUITEVENT_H