ADD: Render a simple Button

This commit is contained in:
sebastian 2026-02-12 18:08:55 +01:00
parent 8bc3ae69a8
commit fa85eaf116
11 changed files with 206 additions and 10 deletions

View File

@ -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

View File

@ -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<float>(ch.advance >> 6) *scale;
}
return width;
}
Font::Character Font::getCharacter(char c) const {
unsigned char uc = static_cast<unsigned char>(c);
auto it = characters.find(uc);

View File

@ -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;

View File

@ -0,0 +1,20 @@
//
// Created by sebastian on 12.02.26.
//
#include "UiButton.h"
#include <utility>
#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<GUITexture>(textureID, position, size));
uiRenderBundle.addGUIText(std::make_shared<GUIText>(font, text, uiPositioner.screenSpace));
}

View File

@ -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

View File

@ -7,6 +7,8 @@
#include <memory>
#include <vector>
#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>& guiText) {
guiTexts.push_back(guiText);
}
std::vector<std::shared_ptr<GUIText>> getGUITexts() {
return guiTexts;
}
private:
std::vector<std::shared_ptr<GUITexture>> guiImages;
std::vector<UiText*> texts;
std::vector<std::shared_ptr<GUIText>> guiTexts;
};

View File

@ -74,6 +74,76 @@ void TextRenderer::renderText(const UiText &textToRender) {
}
}
void TextRenderer::renderGuiTexts(const std::vector<std::shared_ptr<GUIText>> &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<float>(ch.bearing.x) * scale;
float ypos = y - static_cast<float>(ch.size.y - ch.bearing.y) * scale;
float w = static_cast<float>(ch.size.x) * scale;
float h = static_cast<float>(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<float>(ch.advance >> 6) * scale;
glBindVertexArray(0);
glDisableVertexAttribArray(0);
}
}
glm::mat4 TextRenderer::calculateOrthographicProjectionMatrix() {
const auto screenWidth = static_cast<float>(Application::getInstance().getWindow().GetWidth());
const auto screenHeight = static_cast<float>(Application::getInstance().getWindow().GetHeight());

View File

@ -20,7 +20,9 @@ public:
void renderText(const UiText &textToRender);
void renderText(const UiText &textToRender) const;
void renderGuiTexts(const std::vector<std::shared_ptr<GUIText>> & texts);
void renderGuiText(const GUIText& text);
private:
TextShader shader;
TextQuadModel textModel;

View File

@ -0,0 +1,26 @@
//
// Created by sebastian on 12.02.26.
//
#include "GUIText.h"
#include <utility>
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;
}

View File

@ -0,0 +1,29 @@
//
// Created by sebastian on 12.02.26.
//
#ifndef DICEWARS_SIEDLER_GUITEXT_H
#define DICEWARS_SIEDLER_GUITEXT_H
#include <string>
#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

View File

@ -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<Font>(myFont);
//auto text = std::make_unique<UiText>(*font, "Hello World!", glm::vec2(0.5f, 0.5f), glm::vec3(1,1,1));
auto text = std::make_unique<UiText>(*font, "Hello World", imageStyle);
rootContainer->addChild(std::move(text));
auto button = std::make_unique<UiButton>(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() {