From fa85eaf116f334d2de2dfb234d6e235ac402dc2f Mon Sep 17 00:00:00 2001 From: sebastian Date: Thu, 12 Feb 2026 18:08:55 +0100 Subject: [PATCH] ADD: Render a simple Button --- CMakeLists.txt | 4 ++ src/engine/core/gui/text/Font.cpp | 9 +++ src/engine/core/gui/text/Font.h | 2 + src/engine/core/gui/uiComponent/UiButton.cpp | 20 ++++++ src/engine/core/gui/uiComponent/UiButton.h | 26 +++++++ .../core/gui/uiComponent/UiRenderBundle.h | 11 +++ src/engine/renderer/TextRenderer.cpp | 70 +++++++++++++++++++ src/engine/renderer/TextRenderer.h | 4 +- src/engine/renderer/model/GUIText.cpp | 26 +++++++ src/engine/renderer/model/GUIText.h | 29 ++++++++ src/game/UILayer.cpp | 15 ++-- 11 files changed, 206 insertions(+), 10 deletions(-) create mode 100644 src/engine/core/gui/uiComponent/UiButton.cpp create mode 100644 src/engine/core/gui/uiComponent/UiButton.h create mode 100644 src/engine/renderer/model/GUIText.cpp create mode 100644 src/engine/renderer/model/GUIText.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d28a3d2..4321675 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,6 +143,10 @@ add_executable(Dicewars_Siedler src/main.cpp src/engine/renderer/model/TextQuadModel.cpp src/engine/renderer/model/TextQuadModel.h src/engine/core/gui/uiComponent/layout/LayoutStyle.h + src/engine/core/gui/uiComponent/UiButton.cpp + src/engine/core/gui/uiComponent/UiButton.h + src/engine/renderer/model/GUIText.cpp + src/engine/renderer/model/GUIText.h ) target_include_directories(Dicewars_Siedler PRIVATE diff --git a/src/engine/core/gui/text/Font.cpp b/src/engine/core/gui/text/Font.cpp index d90f6b1..a2d979d 100644 --- a/src/engine/core/gui/text/Font.cpp +++ b/src/engine/core/gui/text/Font.cpp @@ -53,6 +53,15 @@ Font::Font(const std::string &fontPath, unsigned int fontSize) { FT_Done_FreeType(ft); } +float Font::getTextWidth(const std::string &text, float scale) const { + float width = 0.0f; + for (char c : text) { + const Character& ch = getCharacter(c); + width += static_cast(ch.advance >> 6) *scale; + } + return width; +} + Font::Character Font::getCharacter(char c) const { unsigned char uc = static_cast(c); auto it = characters.find(uc); diff --git a/src/engine/core/gui/text/Font.h b/src/engine/core/gui/text/Font.h index 5439c58..0d68f35 100644 --- a/src/engine/core/gui/text/Font.h +++ b/src/engine/core/gui/text/Font.h @@ -19,6 +19,8 @@ public: Font(const std::string& fontPath, unsigned int fontSize); ~Font() = default; + float getTextWidth(const std::string &text, float scale) const; + struct Character { GLuint textureID; glm::ivec2 size; diff --git a/src/engine/core/gui/uiComponent/UiButton.cpp b/src/engine/core/gui/uiComponent/UiButton.cpp new file mode 100644 index 0000000..d0166e5 --- /dev/null +++ b/src/engine/core/gui/uiComponent/UiButton.cpp @@ -0,0 +1,20 @@ +// +// Created by sebastian on 12.02.26. +// + +#include "UiButton.h" + +#include + +#include "UiText.h" + +UiButton::UiButton(const GLuint textureID, std::string label, Font &font, const LayoutStyle &style): textureID(textureID), text(std::move(label)), font(font), UiComponent(style) { +} + +void UiButton::onCollectRenderData(UiRenderBundle &uiRenderBundle) { + glm::vec2 position = glm::vec2(uiPositioner.screenSpace.x, uiPositioner.screenSpace.y); + glm::vec2 size = glm::vec2(uiPositioner.screenSpace.width, uiPositioner.screenSpace.height); + + uiRenderBundle.addGUITexture(std::make_shared(textureID, position, size)); + uiRenderBundle.addGUIText(std::make_shared(font, text, uiPositioner.screenSpace)); +} diff --git a/src/engine/core/gui/uiComponent/UiButton.h b/src/engine/core/gui/uiComponent/UiButton.h new file mode 100644 index 0000000..23648b1 --- /dev/null +++ b/src/engine/core/gui/uiComponent/UiButton.h @@ -0,0 +1,26 @@ +// +// Created by sebastian on 12.02.26. +// + +#ifndef DICEWARS_SIEDLER_UIBUTTON_H +#define DICEWARS_SIEDLER_UIBUTTON_H +#include "UiComponent.h" + + +class Font; + +class UiButton : public UiComponent{ +public: + UiButton(GLuint textureID, std::string label, Font& font, const LayoutStyle& style); + +protected: + void onCollectRenderData(UiRenderBundle &uiRenderBundle) override; + +private: + std::string text; + Font& font; + GLuint textureID; +}; + + +#endif //DICEWARS_SIEDLER_UIBUTTON_H \ No newline at end of file diff --git a/src/engine/core/gui/uiComponent/UiRenderBundle.h b/src/engine/core/gui/uiComponent/UiRenderBundle.h index 409611c..e3841e1 100644 --- a/src/engine/core/gui/uiComponent/UiRenderBundle.h +++ b/src/engine/core/gui/uiComponent/UiRenderBundle.h @@ -7,6 +7,8 @@ #include #include +#include "../../../renderer/model/GUIText.h" + class UiText; #include "../../../renderer/model/GUITexture.h" @@ -29,9 +31,18 @@ public: return texts; } + void addGUIText(const std::shared_ptr& guiText) { + guiTexts.push_back(guiText); + } + + std::vector> getGUITexts() { + return guiTexts; + } + private: std::vector> guiImages; std::vector texts; + std::vector> guiTexts; }; diff --git a/src/engine/renderer/TextRenderer.cpp b/src/engine/renderer/TextRenderer.cpp index 44213c0..679964f 100644 --- a/src/engine/renderer/TextRenderer.cpp +++ b/src/engine/renderer/TextRenderer.cpp @@ -74,6 +74,76 @@ void TextRenderer::renderText(const UiText &textToRender) { } } +void TextRenderer::renderGuiTexts(const std::vector> &texts) { + shader.start(); + shader.loadProjectionMatrix(calculateOrthographicProjectionMatrix()); + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + for (const auto &text : texts) { + renderGuiText(*text); + } + glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + shader.stop(); +} + +void TextRenderer::renderGuiText(const GUIText &text) { + const Font& font = text.getFont(); + float scale = 1.0f; + + float screenWidth = Application::getInstance().getWindow().GetWidth(); + float screenHeight = Application::getInstance().getWindow().GetHeight(); + + float x = text.getPosition().x * screenWidth; + float y = (1.f - text.getPosition().y) * screenHeight; + + float textWidth = font.getTextWidth(text.getText(), scale); + float textHeight = font.getLineHeight(); + + // Zentrieren + x += (text.getSize().x * screenWidth - textWidth) * 0.5f; + y -= (text.getSize().y * screenHeight - textHeight) * 0.5f; + + + shader.loadTextColor(glm::vec3(1.0f)); + for (char c : text.getText()) { + const Font::Character& ch = font.getCharacter(c); + + float xpos = x + static_cast(ch.bearing.x) * scale; + float ypos = y - static_cast(ch.size.y - ch.bearing.y) * scale; + + float w = static_cast(ch.size.x) * scale; + float h = static_cast(ch.size.y) * scale; + + float vertices[6][4] = { + { xpos, ypos + h, 0.0f, 0.0f }, + { xpos, ypos, 0.0f, 1.0f }, + { xpos + w, ypos, 1.0f, 1.0f }, + + { xpos, ypos + h, 0.0f, 0.0f }, + { xpos + w, ypos, 1.0f, 1.0f }, + { xpos + w, ypos + h, 1.0f, 0.0f } + }; + + glBindVertexArray(textModel.vaoID); + glEnableVertexAttribArray(0); + + glBindTexture(GL_TEXTURE_2D, ch.textureID); + + + glBindBuffer(GL_ARRAY_BUFFER, textModel.vboID); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); + + glDrawArrays(GL_TRIANGLES, 0, 6); + + x+= static_cast(ch.advance >> 6) * scale; + + glBindVertexArray(0); + glDisableVertexAttribArray(0); + } +} + glm::mat4 TextRenderer::calculateOrthographicProjectionMatrix() { const auto screenWidth = static_cast(Application::getInstance().getWindow().GetWidth()); const auto screenHeight = static_cast(Application::getInstance().getWindow().GetHeight()); diff --git a/src/engine/renderer/TextRenderer.h b/src/engine/renderer/TextRenderer.h index 300e8d5..f0daefe 100644 --- a/src/engine/renderer/TextRenderer.h +++ b/src/engine/renderer/TextRenderer.h @@ -20,7 +20,9 @@ public: void renderText(const UiText &textToRender); - void renderText(const UiText &textToRender) const; + void renderGuiTexts(const std::vector> & texts); + void renderGuiText(const GUIText& text); + private: TextShader shader; TextQuadModel textModel; diff --git a/src/engine/renderer/model/GUIText.cpp b/src/engine/renderer/model/GUIText.cpp new file mode 100644 index 0000000..7506479 --- /dev/null +++ b/src/engine/renderer/model/GUIText.cpp @@ -0,0 +1,26 @@ +// +// Created by sebastian on 12.02.26. +// + +#include "GUIText.h" + +#include + +GUIText::GUIText(Font &font, std::string text, Dimensions &d): font(font), text(std::move(text)), d(d) { +} + +glm::vec2 GUIText::getPosition() const { + return {d.x, d.y}; +} + +glm::vec2 GUIText::getSize() const { + return {d.width, d.height}; +} + +Font & GUIText::getFont() const { + return font; +} + +std::string GUIText::getText() const { + return text; +} diff --git a/src/engine/renderer/model/GUIText.h b/src/engine/renderer/model/GUIText.h new file mode 100644 index 0000000..bffa6a3 --- /dev/null +++ b/src/engine/renderer/model/GUIText.h @@ -0,0 +1,29 @@ +// +// Created by sebastian on 12.02.26. +// + +#ifndef DICEWARS_SIEDLER_GUITEXT_H +#define DICEWARS_SIEDLER_GUITEXT_H +#include + +#include "../../core/gui/uiComponent/Dimensions.h" +#include "glm/vec2.hpp" + + +class Font; + +class GUIText { +public: + GUIText(Font& font, std::string text, Dimensions& d); + [[nodiscard]] glm::vec2 getPosition() const; + [[nodiscard]] glm::vec2 getSize() const; + [[nodiscard]] Font& getFont() const; + [[nodiscard]] std::string getText() const; +private: + Font& font; + const std::string text; + const Dimensions& d; +}; + + +#endif //DICEWARS_SIEDLER_GUITEXT_H \ No newline at end of file diff --git a/src/game/UILayer.cpp b/src/game/UILayer.cpp index 8a0fb2b..0d4c694 100644 --- a/src/game/UILayer.cpp +++ b/src/game/UILayer.cpp @@ -5,6 +5,7 @@ #include "UILayer.h" #include "../engine/core/gui/text/Font.h" +#include "../engine/core/gui/uiComponent/UiButton.h" #include "../engine/core/gui/uiComponent/UiImage.h" #include "../engine/core/gui/uiComponent/UiText.h" #include "../engine/renderer/loader/Loader.h" @@ -45,19 +46,13 @@ void UILayer::onAttach() { Loader::instance().loadTextureFromFile("assets/textures/texture.png").getTextureID(), imageStyle ); - rootContainer->addChild(std::move(image)); - rootContainer->addChild(std::move(image2)); - //rootContainer->addChild(std::move(image3)); - - Font myFont("/usr/share/fonts/TTF/DejaVuSans.ttf", 48); font = std::make_unique(myFont); //auto text = std::make_unique(*font, "Hello World!", glm::vec2(0.5f, 0.5f), glm::vec3(1,1,1)); - auto text = std::make_unique(*font, "Hello World", imageStyle); - - rootContainer->addChild(std::move(text)); + auto button = std::make_unique(Loader::instance().loadTextureFromFile("assets/textures/texture.png").getTextureID(), "Button", *font, imageStyle); + rootContainer->addChild(std::move(button)); } void UILayer::onUpdate() { @@ -74,9 +69,11 @@ void UILayer::onUpdate() { guiRenderer->render(guis); auto texts = renderBundle.getTexts(); - textRenderer->renderTexts(texts); + auto renderTexts = renderBundle.getGUITexts(); + textRenderer->renderGuiTexts(renderTexts); + } void UILayer::onDetach() {