From 0894c5615e9e74bac95c4009170eb877959de8ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Mon, 20 Apr 2026 12:39:31 +0200 Subject: [PATCH] ADD: Configurable UITheme, closes #14 --- CMakeLists.txt | 1 + assets/ui/uiTheme.json | 10 +++++ src/engine/core/gui/text/UiTheme.h | 16 ++++++++ src/engine/renderer/loader/AssetManager.cpp | 39 +++++++++++++++++++ src/engine/renderer/loader/AssetManager.h | 6 +++ src/game/UILayer.cpp | 14 +++---- src/game/ui/components/UiInventoryContainer.h | 5 +-- src/game/ui/components/UiRessourceWidget.cpp | 8 ++-- src/game/ui/components/UiRessourceWidget.h | 2 +- .../buildingMenu/UiBuildingMenuButton.h | 4 -- .../factorys/RessourceWidgetFactory.cpp | 4 +- .../factorys/RessourceWidgetFactory.h | 2 +- 12 files changed, 88 insertions(+), 23 deletions(-) create mode 100644 assets/ui/uiTheme.json create mode 100644 src/engine/core/gui/text/UiTheme.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 34c0c7b..3199a26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -291,6 +291,7 @@ if(BUILD_GAME) src/engine/core/gui/uiComponent/layout/LayoutEngine.h src/engine/renderer/config/MinimapConfig.h src/engine/core/Types.h + src/engine/core/gui/text/UiTheme.h ) target_compile_options(Dicewars_Siedler PRIVATE -Wall diff --git a/assets/ui/uiTheme.json b/assets/ui/uiTheme.json new file mode 100644 index 0000000..fd1334c --- /dev/null +++ b/assets/ui/uiTheme.json @@ -0,0 +1,10 @@ +{ + "font": { + "path": "/usr/share/fonts/TTF/DejaVuSans.ttf", + "sizes": { + "small": 18, + "medium": 28, + "large": 48 + } + } +} \ No newline at end of file diff --git a/src/engine/core/gui/text/UiTheme.h b/src/engine/core/gui/text/UiTheme.h new file mode 100644 index 0000000..dc55a59 --- /dev/null +++ b/src/engine/core/gui/text/UiTheme.h @@ -0,0 +1,16 @@ +// +// Created by sebastian on 20.04.26. +// + +#ifndef UITHEME_H +#define UITHEME_H +#include + +#include "Font.h" + +struct UiTheme { + std::unique_ptr small; + std::unique_ptr medium; + std::unique_ptr large; +}; +#endif //UITHEME_H diff --git a/src/engine/renderer/loader/AssetManager.cpp b/src/engine/renderer/loader/AssetManager.cpp index 8ea8518..a66fd66 100644 --- a/src/engine/renderer/loader/AssetManager.cpp +++ b/src/engine/renderer/loader/AssetManager.cpp @@ -84,6 +84,45 @@ std::shared_ptr AssetManager::getTexture(const std::string &name) return textures.at(name); } +std::shared_ptr AssetManager::getUiTheme(const std::string &themeName) { + assert(uiThemes.contains(themeName) && "Theme not found!"); + return uiThemes.at(themeName); +} + +std::shared_ptr AssetManager::loadUiTheme(const std::string &themeName, const std::string &themePath) { + if (!uiThemes.contains(themeName)) { + json themeConfiguration = readJsonFile(themePath); + if (themeConfiguration.contains("font")) { + auto fontData = themeConfiguration["font"]; + if (fontData.contains("path") && fontData.contains("sizes")) { + auto fontSizes = fontData["sizes"]; + if (fontSizes.contains("small") && fontSizes.contains("medium") && fontSizes.contains("large")) { + std::string fontPath = fontData["path"].get(); + auto theme = std::make_shared( + std::make_unique(fontPath, fontSizes["small"]), + std::make_unique(fontPath, fontSizes["medium"]), + std::make_unique(fontPath, fontSizes["large"]) + ); + uiThemes[themeName] = theme; + return theme; + } else { + std::cerr << "Required Font sizes not found in theme configuration!" << std::endl; + return nullptr; + } + } else { + std::cerr << "Required Font path not found in theme configuration!" << std::endl; + return nullptr; + } + } else { + std::cerr << "Required Font configuration not found in theme configuration!" << std::endl; + return nullptr; + } + } else { + return uiThemes[themeName]; + } +} + + json AssetManager::readJsonFile(const std::string &path) { if (fs::exists(path)) { diff --git a/src/engine/renderer/loader/AssetManager.h b/src/engine/renderer/loader/AssetManager.h index d0aa552..95dca62 100644 --- a/src/engine/renderer/loader/AssetManager.h +++ b/src/engine/renderer/loader/AssetManager.h @@ -10,9 +10,12 @@ #include "json.hpp" #include "../model/TexturedModel.h" #include "Loader.h" +#include "../../core/gui/text/UiTheme.h" #include "../model/ModelStages.h" +class Font; + class AssetManager { public: static std::shared_ptr loadModel(const std::string& name, const std::string& objPath, const std::string& texturePath, Loader& loader); @@ -23,10 +26,13 @@ public: static std::shared_ptr getModelStageConfiguration(const std::string& modelName, const std::string& stageName); static std::shared_ptr loadTexture(const std::string &name, const std::string &texturePath, Loader &loader); static std::shared_ptr getTexture(const std::string& texturePath); + static std::shared_ptr getUiTheme(const std::string& themeName); + static std::shared_ptr loadUiTheme(const std::string& themeName, const std::string& themePath); private: static inline std::unordered_map> models; static inline std::unordered_map> modelsWithStages; static inline std::unordered_map> textures; + static inline std::unordered_map> uiThemes; static nlohmann::json readJsonFile(const std::string &path); }; diff --git a/src/game/UILayer.cpp b/src/game/UILayer.cpp index 28a90d2..4a89654 100644 --- a/src/game/UILayer.cpp +++ b/src/game/UILayer.cpp @@ -9,6 +9,7 @@ #include "../engine/core/Application.h" #include "../engine/core/gui/text/Font.h" +#include "../engine/core/gui/text/UiTheme.h" #include "../engine/core/gui/uiComponent/UiButton.h" #include "../engine/core/gui/uiComponent/UiImage.h" #include "../engine/core/gui/uiComponent/UiText.h" @@ -49,15 +50,10 @@ void UILayer::onAttach() { rootContainer->getLayoutStyle().flexDirection = FlexDirection::Column; rootContainer->getLayoutStyle().justifyContent = JustifyContent::SpaceBetween; - Font myFont("/usr/share/fonts/TTF/DejaVuSans.ttf", 48); - font = std::make_unique(myFont); + AssetManager::loadUiTheme("default", "assets/ui/uiTheme.json"); - //rootContainer->addChild(std::move(button)); - smallFont =std::make_unique("/usr/share/fonts/TTF/DejaVuSans.ttf", 18); - mediumFont = std::make_unique("/usr/share/fonts/TTF/DejaVuSans.ttf", 28); - - auto inventoryContainer = std::make_unique(*smallFont); + auto inventoryContainer = std::make_unique(); inventoryContainer->addRessource("wood_icon", "background", 0, RessourceType::WOOD); inventoryContainer->addRessource("stone_icon","background", 0, RessourceType::STONE); @@ -81,7 +77,7 @@ void UILayer::onAttach() { turnStyle.margin.left = {20.f, SizeUnit::Pixels}; // Abstand zum Inventory turnStyle.margin.top = {10.f, SizeUnit::Pixels}; - auto turnLabel = std::make_unique(*mediumFont, "Runde: 1", turnStyle, glm::vec3(1,1,1)); + auto turnLabel = std::make_unique(*AssetManager::getUiTheme("default")->medium, "Runde: 1", turnStyle, glm::vec3(1,1,1)); turnText = rootContainer->addChild(std::move(turnLabel)); // NOLINT EventBus::getInstance().subscribe([this](const TurnChangedEvent& event) { @@ -104,7 +100,7 @@ void UILayer::onAttach() { style.margin.top = {10.f, SizeUnit::Pixels}; style.margin.left = {20.f, SizeUnit::Pixels}; - auto buildingMenuContainer = std::make_unique(*smallFont); + auto buildingMenuContainer = std::make_unique(*AssetManager::getUiTheme("default")->small); buildingMenuContainer->addBuildingMenuBtnCallback([](UiBuildingMenuButtonClickEvent e) { if (e.originalEventData.isClick(MouseButton::LEFT)) { EventBus::getInstance().emit(BuildingTypeSelectEvent{e.buildingType}); diff --git a/src/game/ui/components/UiInventoryContainer.h b/src/game/ui/components/UiInventoryContainer.h index 166858d..9aa9765 100644 --- a/src/game/ui/components/UiInventoryContainer.h +++ b/src/game/ui/components/UiInventoryContainer.h @@ -13,7 +13,7 @@ // UiInventoryContainer.h class UiInventoryContainer : public UiComponent { public: - UiInventoryContainer(Font& font) : font(font) { + UiInventoryContainer() { LayoutStyle containerStyle; containerStyle.width = SizeValue(0.3f, SizeUnit::Percent); containerStyle.height = SizeValue(80.f, SizeUnit::Pixels); @@ -26,7 +26,7 @@ public: void addRessource(const std::string& iconName, const std::string& textureName, int amount, RessourceType widgetID) { float marginLeft = (widgets.empty()) ? 0.0f : 10.0f; - auto widget = RessourceWidgetFactory::create(iconName, textureName, amount, font, marginLeft); + auto widget = RessourceWidgetFactory::create(iconName, textureName, amount, marginLeft); widgets.emplace(widgetID, widget.get()); addChild(std::move(widget)); } @@ -41,7 +41,6 @@ protected: void onCollectRenderData(UiRenderBundle &uiRenderBundle) override; private: - Font& font; std::unordered_map widgets; }; diff --git a/src/game/ui/components/UiRessourceWidget.cpp b/src/game/ui/components/UiRessourceWidget.cpp index fc31fb0..9e0f1bd 100644 --- a/src/game/ui/components/UiRessourceWidget.cpp +++ b/src/game/ui/components/UiRessourceWidget.cpp @@ -4,13 +4,15 @@ #include "UiRessourceWidget.h" +#include "../../../engine/core/gui/text/UiTheme.h" #include "../../../engine/core/gui/uiComponent/UiText.h" +#include "../../../engine/renderer/loader/AssetManager.h" -UiRessourceWidget::UiRessourceWidget(GLuint iconTextureID, GLuint backgroundID, int amount, Font &font, const LayoutStyle &containerStyle, - LayoutStyle &iconStyle, LayoutStyle &textStyle) : UiComponent(containerStyle) { +UiRessourceWidget::UiRessourceWidget(GLuint iconTextureID, GLuint backgroundID, int amount, const LayoutStyle &containerStyle, + LayoutStyle &iconStyle, LayoutStyle &textStyle) : UiComponent(containerStyle) { icon = addChild(std::make_unique(iconTextureID, backgroundID, iconStyle)); //NOLINT - text = addChild(std::make_unique(font, std::to_string(amount), textStyle)); //NOLINT + text = addChild(std::make_unique(*AssetManager::getUiTheme("default")->small, std::to_string(amount), textStyle)); //NOLINT } void UiRessourceWidget::setAmount(int newAmount) { diff --git a/src/game/ui/components/UiRessourceWidget.h b/src/game/ui/components/UiRessourceWidget.h index b9d42f6..ed8f41b 100644 --- a/src/game/ui/components/UiRessourceWidget.h +++ b/src/game/ui/components/UiRessourceWidget.h @@ -13,7 +13,7 @@ class UiRessourceWidget : public UiComponent { public: - UiRessourceWidget(GLuint iconTextureID, GLuint backgroundID, int amount, Font &font, + UiRessourceWidget(GLuint iconTextureID, GLuint backgroundID, int amount, const LayoutStyle &containerStyle, LayoutStyle &iconStyle, LayoutStyle &textStyle); diff --git a/src/game/ui/components/buildingMenu/UiBuildingMenuButton.h b/src/game/ui/components/buildingMenu/UiBuildingMenuButton.h index efdd4ab..05452ef 100644 --- a/src/game/ui/components/buildingMenu/UiBuildingMenuButton.h +++ b/src/game/ui/components/buildingMenu/UiBuildingMenuButton.h @@ -39,8 +39,6 @@ public: if (buildingType == BuildingType::FOREST_HUT) { BuildingDefinition def = BuildingConfig::get(BuildingType::FOREST_HUT); - - } for (const auto& [resourceTye, costs] : BuildingConfig::get(buildingType).resourceCosts) { @@ -52,8 +50,6 @@ public: addChild(std::move(costContainer)); } - - visualStyles[UiEventType::NONE] = {1.0f, glm::vec3(0.0f), 0.0f}; visualStyles[UiEventType::MOUSE_OVER] = {1.15f, glm::vec3(0.0f), 0.0f}; visualStyles[UiEventType::MOUSE_CLICK] = {1.0f, glm::vec3(0.3f, 0.6f, 1.0f), 0.15f}; diff --git a/src/game/ui/components/factorys/RessourceWidgetFactory.cpp b/src/game/ui/components/factorys/RessourceWidgetFactory.cpp index a42dabc..7476596 100644 --- a/src/game/ui/components/factorys/RessourceWidgetFactory.cpp +++ b/src/game/ui/components/factorys/RessourceWidgetFactory.cpp @@ -7,7 +7,7 @@ #include "../../../../engine/renderer/loader/AssetManager.h" #include "../../../../engine/renderer/loader/Loader.h" -std::unique_ptr RessourceWidgetFactory::create(const std::string &iconName, const std::string& textureName, int amount, Font &font, float marginLeft) { +std::unique_ptr RessourceWidgetFactory::create(const std::string &iconName, const std::string& textureName, int amount, float marginLeft) { LayoutStyle iconStyle; iconStyle.width = SizeValue(40.f, SizeUnit::Pixels); iconStyle.height = SizeValue(40.f,SizeUnit::Pixels); @@ -30,7 +30,7 @@ std::unique_ptr RessourceWidgetFactory::create(const std::str GLuint textureID =AssetManager::getTexture(iconName)->getTextureID();; GLuint backgroundTextureID = AssetManager::getTexture(textureName)->getTextureID(); return std::make_unique(textureID, backgroundTextureID, - amount, font, containerStyle, iconStyle, textStyle + amount, containerStyle, iconStyle, textStyle ); } diff --git a/src/game/ui/components/factorys/RessourceWidgetFactory.h b/src/game/ui/components/factorys/RessourceWidgetFactory.h index 97de505..efad0c6 100644 --- a/src/game/ui/components/factorys/RessourceWidgetFactory.h +++ b/src/game/ui/components/factorys/RessourceWidgetFactory.h @@ -12,7 +12,7 @@ class Font; class RessourceWidgetFactory { public: - static std::unique_ptr create(const std::string &iconName, const std::string &textureName, int amount, Font &font, float marginLeft = 0.0); + static std::unique_ptr create(const std::string &iconName, const std::string &textureName, int amount, float marginLeft = 0.0); };