diff --git a/.idea/Dicewars-Siedler.iml b/.idea/Dicewars-Siedler.iml
index f08604b..4c94235 100644
--- a/.idea/Dicewars-Siedler.iml
+++ b/.idea/Dicewars-Siedler.iml
@@ -1,2 +1,2 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/.idea/editor.xml b/.idea/editor.xml
index c4b56b6..5e7b172 100644
--- a/.idea/editor.xml
+++ b/.idea/editor.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d00ccfc..408214d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -117,6 +117,15 @@ add_executable(Dicewars_Siedler src/main.cpp
src/game/UILayer.h
src/engine/renderer/shaders/GUIShader.cpp
src/engine/renderer/shaders/GUIShader.h
+ src/engine/core/gui/uiComponent/UiComponent.cpp
+ src/engine/core/gui/uiComponent/UiComponent.h
+ src/engine/core/gui/uiComponent/Dimensions.h
+ src/engine/core/gui/uiComponent/UiPositioner.cpp
+ src/engine/core/gui/uiComponent/UiPositioner.h
+ src/engine/core/gui/uiMain/UiContainer.cpp
+ src/engine/core/gui/uiMain/UiContainer.h
+ src/engine/core/gui/uiComponent/UiImage.cpp
+ src/engine/core/gui/uiComponent/UiImage.h
)
target_include_directories(Dicewars_Siedler PRIVATE
diff --git a/src/engine/core/gui/uiComponent/Dimensions.h b/src/engine/core/gui/uiComponent/Dimensions.h
new file mode 100644
index 0000000..b9e2308
--- /dev/null
+++ b/src/engine/core/gui/uiComponent/Dimensions.h
@@ -0,0 +1,24 @@
+//
+// Created by sebastian on 10.02.26.
+//
+
+#ifndef DICEWARS_SIEDLER_DIMENSIONS_H
+#define DICEWARS_SIEDLER_DIMENSIONS_H
+
+struct Dimensions {
+ float x, y;
+ float width, height;
+
+ void set(const float x, const float y, const float width, const float height) {
+ this->x = x;
+ this->y = y;
+ this->width = width;
+ this->height = height;
+ }
+
+ [[nodiscard]] bool contains(const float testX, const float testY) const {
+ return testX >= x && testX <= x + width && testY >= y && testY <= y + height;
+ }
+};
+
+#endif //DICEWARS_SIEDLER_DIMENSIONS_H
\ No newline at end of file
diff --git a/src/engine/core/gui/uiComponent/UiComponent.cpp b/src/engine/core/gui/uiComponent/UiComponent.cpp
new file mode 100644
index 0000000..3affbfa
--- /dev/null
+++ b/src/engine/core/gui/uiComponent/UiComponent.cpp
@@ -0,0 +1,44 @@
+//
+// Created by sebastian on 10.02.26.
+//
+
+#include "UiComponent.h"
+
+void UiComponent::addChild(std::unique_ptr child) {
+ child->parent = this;
+ child->uiPositioner.compute(this->uiPositioner.screenSpace);
+ children.emplace_back(std::move(child));
+}
+
+void UiComponent::setVisible(const bool v) {
+ this->visible = v;
+}
+
+bool UiComponent::isVisible() const {
+ return visible;
+}
+
+void UiComponent::update(float delta) {
+ if (!visible) return;
+
+ onUpdate(delta);
+
+ for (const auto &child : children) {
+ child->update(delta);
+ }
+}
+
+void UiComponent::collectRenderData(std::vector &guiTextures) {
+ if (!visible) return;
+
+ onCollectRenderData(guiTextures);
+
+ for (const auto &child : children) {
+ child->collectRenderData(guiTextures);
+ }
+}
+
+bool UiComponent::isMouseOver(float mouseX, float mouseY) {
+ if (!visible) return false;
+ return uiPositioner.screenSpace.contains(mouseX, mouseY);
+}
diff --git a/src/engine/core/gui/uiComponent/UiComponent.h b/src/engine/core/gui/uiComponent/UiComponent.h
new file mode 100644
index 0000000..7f3cf53
--- /dev/null
+++ b/src/engine/core/gui/uiComponent/UiComponent.h
@@ -0,0 +1,38 @@
+//
+// Created by sebastian on 10.02.26.
+//
+
+#ifndef DICEWARS_SIEDLER_UICOMPONENT_H
+#define DICEWARS_SIEDLER_UICOMPONENT_H
+#include
+#include
+
+#include "UiPositioner.h"
+#include "../../../renderer/model/GUITexture.h"
+
+
+class UiComponent {
+public:
+ UiComponent() : uiPositioner(*this) {};
+ virtual ~UiComponent() = default;
+ void addChild(std::unique_ptr child);
+ void setVisible(bool visible);
+ [[nodiscard]] bool isVisible() const;
+ void update(float delta);
+ void collectRenderData(std::vector& guiTextures);
+ virtual bool isMouseOver(float mouseX, float mouseY);
+ UiComponent* parent = nullptr;
+ UiPositioner uiPositioner;
+protected:
+
+ std::vector> children;
+
+ bool visible = true;
+
+ virtual void onUpdate(float /*delta*/) {}
+ virtual void onCollectRenderData(std::vector&) {}
+
+};
+
+
+#endif //DICEWARS_SIEDLER_UICOMPONENT_H
\ No newline at end of file
diff --git a/src/engine/core/gui/uiComponent/UiImage.cpp b/src/engine/core/gui/uiComponent/UiImage.cpp
new file mode 100644
index 0000000..eae240d
--- /dev/null
+++ b/src/engine/core/gui/uiComponent/UiImage.cpp
@@ -0,0 +1,11 @@
+//
+// Created by sebastian on 10.02.26.
+//
+
+#include "UiImage.h"
+
+void UiImage::onCollectRenderData(std::vector &gui_textures) {
+ if (!visible) return;
+ Dimensions dims = uiPositioner.screenSpace;
+ gui_textures.emplace_back(textureID, glm::vec2(dims.x, dims.y), glm::vec2(dims.width, dims.height));
+}
diff --git a/src/engine/core/gui/uiComponent/UiImage.h b/src/engine/core/gui/uiComponent/UiImage.h
new file mode 100644
index 0000000..d51b7fe
--- /dev/null
+++ b/src/engine/core/gui/uiComponent/UiImage.h
@@ -0,0 +1,25 @@
+//
+// Created by sebastian on 10.02.26.
+//
+
+#ifndef DICEWARS_SIEDLER_UIIMAGE_H
+#define DICEWARS_SIEDLER_UIIMAGE_H
+#include "UiComponent.h"
+
+
+class UiImage : public UiComponent {
+public:
+ UiImage(GLuint textureID, const glm::vec2& relativePos, const glm::vec2& relativeSize) : textureID(textureID) {
+ uiPositioner.setRelativePos(relativePos);
+ uiPositioner.setRelativeSize(relativeSize);
+ };
+
+protected:
+ void onCollectRenderData(std::vector &) override;
+
+private:
+ GLuint textureID;
+};
+
+
+#endif //DICEWARS_SIEDLER_UIIMAGE_H
\ No newline at end of file
diff --git a/src/engine/core/gui/uiComponent/UiPositioner.cpp b/src/engine/core/gui/uiComponent/UiPositioner.cpp
new file mode 100644
index 0000000..49ec3bf
--- /dev/null
+++ b/src/engine/core/gui/uiComponent/UiPositioner.cpp
@@ -0,0 +1,28 @@
+//
+// Created by sebastian on 10.02.26.
+//
+
+#include "UiPositioner.h"
+
+#include "UiComponent.h"
+
+void UiPositioner::compute(const Dimensions &parent) {
+ screenSpace.x = parent.x + relativePos.x * parent.width;
+ screenSpace.y = parent.y + relativePos.y * parent.height;
+ screenSpace.width = relativeSize.x * parent.width;
+ screenSpace.height = relativeSize.y * parent.height;
+}
+
+void UiPositioner::setRelativePos(const glm::vec2 &pos) {
+ relativePos = pos;
+ if (uiComponent.parent) {
+ compute(uiComponent.parent->uiPositioner.screenSpace);
+ }
+}
+
+void UiPositioner::setRelativeSize(const glm::vec2 &size) {
+ relativeSize = size;
+ if (uiComponent.parent) {
+ compute(uiComponent.parent->uiPositioner.screenSpace);
+ }
+}
diff --git a/src/engine/core/gui/uiComponent/UiPositioner.h b/src/engine/core/gui/uiComponent/UiPositioner.h
new file mode 100644
index 0000000..96f8439
--- /dev/null
+++ b/src/engine/core/gui/uiComponent/UiPositioner.h
@@ -0,0 +1,34 @@
+//
+// Created by sebastian on 10.02.26.
+//
+
+#ifndef DICEWARS_SIEDLER_UIPOSITIONER_H
+#define DICEWARS_SIEDLER_UIPOSITIONER_H
+#include "Dimensions.h"
+#include
+class UiComponent; // forward declaration
+
+class UiPositioner {
+public:
+ Dimensions screenSpace = Dimensions();
+ explicit UiPositioner(UiComponent& uiComponent)
+ : uiComponent(uiComponent),
+ relativePos(0.0f, 0.0f),
+ relativeSize(1.0f, 1.0f)
+ {}
+
+
+
+ void compute(const Dimensions& parentDimensions);
+
+ void setRelativePos(const glm::vec2& pos);
+ void setRelativeSize(const glm::vec2& size);
+
+private:
+ UiComponent& uiComponent;
+ glm::vec2 relativePos; // [0..1] relative to parent
+ glm::vec2 relativeSize; // [0..1] relative to parent
+};
+
+
+#endif //DICEWARS_SIEDLER_UIPOSITIONER_H
\ No newline at end of file
diff --git a/src/engine/core/gui/uiMain/UiContainer.cpp b/src/engine/core/gui/uiMain/UiContainer.cpp
new file mode 100644
index 0000000..c664f84
--- /dev/null
+++ b/src/engine/core/gui/uiMain/UiContainer.cpp
@@ -0,0 +1,25 @@
+//
+// Created by sebastian on 10.02.26.
+//
+
+#include "UiContainer.h"
+
+UiContainer::UiContainer(){
+ uiPositioner.screenSpace.set(0.f, 0.f, 1.f, 1.f);
+}
+
+bool UiContainer::isMouseOver(float mouseX, float mouseY) {
+ for (const auto &child : children) {
+ if (child->isMouseOver(mouseX, mouseY)) return true;
+ }
+ return false;
+}
+
+void UiContainer::onUpdate(float x) {
+
+}
+
+void UiContainer::onCollectRenderData(std::vector &gui_textures) {
+
+}
+
diff --git a/src/engine/core/gui/uiMain/UiContainer.h b/src/engine/core/gui/uiMain/UiContainer.h
new file mode 100644
index 0000000..b7e62b5
--- /dev/null
+++ b/src/engine/core/gui/uiMain/UiContainer.h
@@ -0,0 +1,19 @@
+//
+// Created by sebastian on 10.02.26.
+//
+
+#ifndef DICEWARS_SIEDLER_UICONTAINER_H
+#define DICEWARS_SIEDLER_UICONTAINER_H
+#include "../uiComponent/UiComponent.h"
+
+
+class UiContainer : public UiComponent {
+public:
+ UiContainer();
+ bool isMouseOver(float mouseX, float mouseY) override;
+ void onUpdate(float) override;
+ void onCollectRenderData(std::vector &) override;
+};
+
+
+#endif //DICEWARS_SIEDLER_UICONTAINER_H
\ No newline at end of file
diff --git a/src/game/UILayer.cpp b/src/game/UILayer.cpp
index d293d12..d69b36a 100644
--- a/src/game/UILayer.cpp
+++ b/src/game/UILayer.cpp
@@ -4,6 +4,7 @@
#include "UILayer.h"
+#include "../engine/core/gui/uiComponent/UiImage.h"
#include "../engine/renderer/loader/Loader.h"
#include "../engine/renderer/model/GUITexture.h"
@@ -15,13 +16,25 @@ UILayer::UILayer() {
void UILayer::onAttach() {
Layer::onAttach();
- ModelTexture modelTexture = Loader::instance().loadTextureFromFile("assets/textures/texture.png");
- guiTextures.emplace_back(modelTexture.getTextureID(), glm::vec2(0.5f, 0.5f), glm::vec2(0.5f));
+
+ rootContainer = std::make_unique();
+
+ auto image = std::make_unique(
+ Loader::instance().loadTextureFromFile("assets/textures/texture.png").getTextureID(),
+ glm::vec2(0.5f, 0.5f), glm::vec2(0.5f)
+ );
+ rootContainer->addChild(std::move(image));
}
void UILayer::onUpdate() {
Layer::onUpdate();
+ std::vector guiTextures;
+ if (rootContainer) {
+ rootContainer->collectRenderData(guiTextures);
+ }
+
+ printf("Found UI Textures: %lu\n", guiTextures.size());
guiRenderer->render(guiTextures);
}
diff --git a/src/game/UILayer.h b/src/game/UILayer.h
index fddb7bb..ab8d01a 100644
--- a/src/game/UILayer.h
+++ b/src/game/UILayer.h
@@ -6,6 +6,7 @@
#define UILAYER_H
#include
+#include "../engine/core/gui/uiMain/UiContainer.h"
#include "../engine/layer/Layer.h"
#include "../engine/renderer/GUIRenderer.h"
@@ -13,7 +14,8 @@
class UILayer : public Layer{
private:
std::unique_ptr guiRenderer;
- std::vector guiTextures;
+
+ std::unique_ptr rootContainer;
public:
UILayer();
void onAttach() override;