ADD: Basic UI

This commit is contained in:
sebastian 2026-08-02 21:04:34 +02:00
parent 7d9b31fe12
commit c6d1fd8910
11 changed files with 126 additions and 3 deletions

View File

@ -156,6 +156,8 @@ add_library(Engine STATIC
engine/src/ecs/standardComponents/PickableComponent.h engine/src/ecs/standardComponents/PickableComponent.h
engine/src/ecs/systems/PickingSystem.cpp engine/src/ecs/systems/PickingSystem.cpp
engine/src/ecs/systems/PickingSystem.h engine/src/ecs/systems/PickingSystem.h
engine/src/ui/ImGuiContext.cpp
engine/src/ui/ImGuiContext.h
) )
target_include_directories(Engine PUBLIC engine/src) target_include_directories(Engine PUBLIC engine/src)
target_link_libraries(Engine PUBLIC OpenGL::GL glfw glad glm::glm imgui spdlog::spdlog tinyobjloader stb_image) target_link_libraries(Engine PUBLIC OpenGL::GL glfw glad glm::glm imgui spdlog::spdlog tinyobjloader stb_image)

View File

@ -28,6 +28,10 @@ namespace engine {
lastTime = currentTime; lastTime = currentTime;
m_window->pollEvents(); m_window->pollEvents();
m_keyboard.update();
m_mouse.update();
m_imguiContext.beginFrame();
onUpdate(deltaTime); onUpdate(deltaTime);
@ -35,6 +39,7 @@ namespace engine {
onRender(); onRender();
m_imguiContext.endFrame();
m_window->swapBuffers(); m_window->swapBuffers();
} }
} }

View File

@ -8,11 +8,13 @@
#include <string> #include <string>
#include "EngineConfig.h" #include "EngineConfig.h"
#include "Window.h" #include "Window.h"
#include "inputsOutputs/context/InputContextStack.h" #include "inputsOutputs/context/InputContextStack.h"
#include "inputsOutputs/inputs/Keyboard.h" #include "inputsOutputs/inputs/Keyboard.h"
#include "inputsOutputs/inputs/Mouse.h" #include "inputsOutputs/inputs/Mouse.h"
#include "layer/SceneManager.h" #include "layer/SceneManager.h"
#include "ui/ImGuiContext.h"
namespace engine { namespace engine {
@ -38,6 +40,7 @@ namespace engine {
Keyboard m_keyboard{*m_window}; // braucht Window& im Konstruktor Keyboard m_keyboard{*m_window}; // braucht Window& im Konstruktor
Mouse m_mouse{*m_window}; Mouse m_mouse{*m_window};
SceneManager m_sceneManager{m_inputContextStack}; SceneManager m_sceneManager{m_inputContextStack};
ImGuiContext m_imguiContext{*m_window}; // neu
}; };

View File

@ -4,6 +4,7 @@
#include "Keyboard.h" #include "Keyboard.h"
#include "imgui_impl_glfw.h"
#include "core/Window.h" #include "core/Window.h"
#include "GLFW/glfw3.h" #include "GLFW/glfw3.h"
@ -42,6 +43,7 @@ bool engine::Keyboard::keyReleaseEvent(const int key) const {
void engine::Keyboard::addTextListener(Window &window) { void engine::Keyboard::addTextListener(Window &window) {
glfwSetCharCallback(window.getHandle(), [](GLFWwindow* handle, unsigned int key) { glfwSetCharCallback(window.getHandle(), [](GLFWwindow* handle, unsigned int key) {
ImGui_ImplGlfw_CharCallback(handle, key);
auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle)); auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle));
if (!target || !target->keyboard) return; if (!target || !target->keyboard) return;
@ -51,6 +53,7 @@ void engine::Keyboard::addTextListener(Window &window) {
void engine::Keyboard::addKeyListener(Window &window) { void engine::Keyboard::addKeyListener(Window &window) {
glfwSetKeyCallback(window.getHandle(), [](GLFWwindow* handle, int key, int scancode, int action, int mods) { glfwSetKeyCallback(window.getHandle(), [](GLFWwindow* handle, int key, int scancode, int action, int mods) {
ImGui_ImplGlfw_KeyCallback(handle, key, scancode, action, mods);
auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle)); auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle));
if (!target || !target->keyboard) return; if (!target || !target->keyboard) return;

View File

@ -4,6 +4,7 @@
#include "Mouse.h" #include "Mouse.h"
#include "imgui_impl_glfw.h"
#include "core/Window.h" #include "core/Window.h"
#include "GLFW/glfw3.h" #include "GLFW/glfw3.h"
@ -77,6 +78,8 @@ void engine::Mouse::updateDetlas() {
void engine::Mouse::addMoveListener(Window &window) { void engine::Mouse::addMoveListener(Window &window) {
glfwSetCursorPosCallback(window.getHandle(), [](GLFWwindow* handle, double xPos, double yPos) { glfwSetCursorPosCallback(window.getHandle(), [](GLFWwindow* handle, double xPos, double yPos) {
ImGui_ImplGlfw_CursorPosCallback(handle, xPos, yPos);
auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle)); auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle));
if (!target || !target->mouse) return; if (!target || !target->mouse) return;
@ -89,6 +92,8 @@ void engine::Mouse::addMoveListener(Window &window) {
void engine::Mouse::addScrollListener(Window &window) { void engine::Mouse::addScrollListener(Window &window) {
glfwSetScrollCallback(window.getHandle(), [](GLFWwindow* handle, double xoff, double yoff) { glfwSetScrollCallback(window.getHandle(), [](GLFWwindow* handle, double xoff, double yoff) {
ImGui_ImplGlfw_ScrollCallback(handle, xoff, yoff);
auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle)); auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle));
if (target && target->mouse) target->mouse->scroll = static_cast<float>(yoff); if (target && target->mouse) target->mouse->scroll = static_cast<float>(yoff);
}); });
@ -96,6 +101,8 @@ void engine::Mouse::addScrollListener(Window &window) {
void engine::Mouse::addClickListener(Window &window) { void engine::Mouse::addClickListener(Window &window) {
glfwSetMouseButtonCallback(window.getHandle(), [](GLFWwindow* handle, int button, int action, int mods) { glfwSetMouseButtonCallback(window.getHandle(), [](GLFWwindow* handle, int button, int action, int mods) {
ImGui_ImplGlfw_MouseButtonCallback(handle, button, action, mods);
auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle)); auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle));
if (!target || !target->mouse) return; if (!target || !target->mouse) return;
@ -103,3 +110,13 @@ void engine::Mouse::addClickListener(Window &window) {
else if (action == GLFW_RELEASE) target->mouse->reportButtonRelease(button); else if (action == GLFW_RELEASE) target->mouse->reportButtonRelease(button);
}); });
} }
int engine::Mouse::MouseButtonToInt(MouseButton button) {
int glfwButton = 0;
switch (button) {
case MouseButton::LEFT: glfwButton = GLFW_MOUSE_BUTTON_LEFT; break;
case MouseButton::RIGHT: glfwButton = GLFW_MOUSE_BUTTON_RIGHT; break;
case MouseButton::MIDDLE: glfwButton = GLFW_MOUSE_BUTTON_MIDDLE; break;
}
return glfwButton;
}

View File

@ -44,8 +44,7 @@ namespace engine {
static void addScrollListener(Window& window); static void addScrollListener(Window& window);
static void addClickListener(Window& window); static void addClickListener(Window& window);
static int MouseButtonToInt(MouseButton button) { static int MouseButtonToInt(MouseButton button);
}
}; };
} }

View File

@ -0,0 +1,36 @@
//
// Created by sebastian on 02.08.26.
//
#include "ImGuiContext.h"
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
engine::ImGuiContext::ImGuiContext(Window &window) {
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGui::StyleColorsDark();
ImGui::GetIO().IniFilename = nullptr; // keine imgui.ini neben der exe, optional
ImGui_ImplGlfw_InitForOpenGL(window.getHandle(), /* install_callbacks = */ false);
ImGui_ImplOpenGL3_Init("#version 460");
}
engine::ImGuiContext::~ImGuiContext() {
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
}
void engine::ImGuiContext::beginFrame() const {
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
}
void engine::ImGuiContext::endFrame() const {
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}

View File

@ -0,0 +1,26 @@
//
// Created by sebastian on 02.08.26.
//
#ifndef COLORRACE_IMGUICONTEXT_H
#define COLORRACE_IMGUICONTEXT_H
#pragma once
#include "core/Window.h"
namespace engine {
class ImGuiContext {
public:
explicit ImGuiContext(Window& window);
~ImGuiContext();
ImGuiContext(const ImGuiContext&) = delete;
ImGuiContext& operator=(const ImGuiContext&) = delete;
void beginFrame() const;
void endFrame() const;
};
}
#endif //COLORRACE_IMGUICONTEXT_H

View File

@ -30,6 +30,29 @@ void GameLayer::onDetachImpl() {
} }
void GameLayer::renderHud() {
const auto& state = m_gameMode->getState();
bool isMyTurn = m_gameMode->getCurrentPlayer() == m_localPlayer;
ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver);
ImGui::Begin("Ludo", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize);
ImGui::Text("Am Zug: %s", toString(m_gameMode->getColorOf(m_gameMode->getCurrentPlayer())).data());
ImGui::Text("Wuerfel: %d", state.getDiceValue());
ImGui::BeginDisabled(!isMyTurn || state.getPhase() != ludo::TurnPhase::AwaitingRoll);
if (ImGui::Button("Wuerfeln")) {
m_gameMode->sendCommand(ludo::RollDiceCommand{m_localPlayer});
}
if (!m_lastEventMessage.empty()) ImGui::Text("%s", m_lastEventMessage.c_str());
ImGui::EndDisabled();
ImGui::End();
}
void GameLayer::onUpdate(float deltaTime) { void GameLayer::onUpdate(float deltaTime) {
Layer::onUpdate(deltaTime); Layer::onUpdate(deltaTime);
m_cameraController->update(getKeyboard(), *m_camera, deltaTime); m_cameraController->update(getKeyboard(), *m_camera, deltaTime);
@ -39,6 +62,9 @@ void GameLayer::onUpdate(float deltaTime) {
if constexpr (std::is_same_v<T, ludo::PieceMovedEvent>) { if constexpr (std::is_same_v<T, ludo::PieceMovedEvent>) {
m_piecePresenter.onPieceMoved(e, m_gameMode->getState()); m_piecePresenter.onPieceMoved(e, m_gameMode->getState());
} }
if constexpr (std::is_same_v<T, ludo::DiceRolledEvent>) {
m_lastEventMessage = std::format("Wuerfel geworfen: {}", e.diceValue);
}
// DiceRolledEvent/TurnChangedEvent -> ImGui-State aktualisieren // DiceRolledEvent/TurnChangedEvent -> ImGui-State aktualisieren
}, event); }, event);
} }
@ -58,4 +84,6 @@ void GameLayer::onRender() {
MeshRenderSystem meshRenderSystem; MeshRenderSystem meshRenderSystem;
meshRenderSystem.update(m_entityRegistry, m_renderQueue); meshRenderSystem.update(m_entityRegistry, m_renderQueue);
m_renderer->render(m_renderQueue, *m_camera, *m_pointLight); m_renderer->render(m_renderQueue, *m_camera, *m_pointLight);
renderHud();
} }

View File

@ -44,6 +44,9 @@ private:
engine::PlayerID m_localPlayer = 0; engine::PlayerID m_localPlayer = 0;
std::shared_ptr<ludo::LudoGameMode> m_gameMode; std::shared_ptr<ludo::LudoGameMode> m_gameMode;
engine::PickingSystem m_pickingSystem; engine::PickingSystem m_pickingSystem;
std::string m_lastEventMessage;
void renderHud();
}; };

View File

@ -21,6 +21,7 @@ namespace ludo {
[[nodiscard]] const LudoGameState& getState() const override { return m_gameState; } [[nodiscard]] const LudoGameState& getState() const override { return m_gameState; }
[[nodiscard]] PlayerColor getColorOf(engine::PlayerID playerID) const;
private: private:
struct MoveResult { struct MoveResult {
int fromPosition; int fromPosition;
@ -33,7 +34,7 @@ namespace ludo {
void handle(const RollDiceCommand &command); void handle(const RollDiceCommand &command);
[[nodiscard]] PlayerColor getColorOf(engine::PlayerID playerID) const;
void handle(const MovePieceCommand &command); void handle(const MovePieceCommand &command);
void finishTurn(); void finishTurn();