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/systems/PickingSystem.cpp
engine/src/ecs/systems/PickingSystem.h
engine/src/ui/ImGuiContext.cpp
engine/src/ui/ImGuiContext.h
)
target_include_directories(Engine PUBLIC engine/src)
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;
m_window->pollEvents();
m_keyboard.update();
m_mouse.update();
m_imguiContext.beginFrame();
onUpdate(deltaTime);
@ -35,6 +39,7 @@ namespace engine {
onRender();
m_imguiContext.endFrame();
m_window->swapBuffers();
}
}

View File

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

View File

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

View File

@ -4,6 +4,7 @@
#include "Mouse.h"
#include "imgui_impl_glfw.h"
#include "core/Window.h"
#include "GLFW/glfw3.h"
@ -77,6 +78,8 @@ void engine::Mouse::updateDetlas() {
void engine::Mouse::addMoveListener(Window &window) {
glfwSetCursorPosCallback(window.getHandle(), [](GLFWwindow* handle, double xPos, double yPos) {
ImGui_ImplGlfw_CursorPosCallback(handle, xPos, yPos);
auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle));
if (!target || !target->mouse) return;
@ -89,6 +92,8 @@ void engine::Mouse::addMoveListener(Window &window) {
void engine::Mouse::addScrollListener(Window &window) {
glfwSetScrollCallback(window.getHandle(), [](GLFWwindow* handle, double xoff, double yoff) {
ImGui_ImplGlfw_ScrollCallback(handle, xoff, yoff);
auto* target = static_cast<Window::CallbackTarget*>(glfwGetWindowUserPointer(handle));
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) {
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));
if (!target || !target->mouse) return;
@ -103,3 +110,13 @@ void engine::Mouse::addClickListener(Window &window) {
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 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) {
Layer::onUpdate(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>) {
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
}, event);
}
@ -58,4 +84,6 @@ void GameLayer::onRender() {
MeshRenderSystem meshRenderSystem;
meshRenderSystem.update(m_entityRegistry, m_renderQueue);
m_renderer->render(m_renderQueue, *m_camera, *m_pointLight);
renderHud();
}

View File

@ -44,6 +44,9 @@ private:
engine::PlayerID m_localPlayer = 0;
std::shared_ptr<ludo::LudoGameMode> m_gameMode;
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]] PlayerColor getColorOf(engine::PlayerID playerID) const;
private:
struct MoveResult {
int fromPosition;
@ -33,7 +34,7 @@ namespace ludo {
void handle(const RollDiceCommand &command);
[[nodiscard]] PlayerColor getColorOf(engine::PlayerID playerID) const;
void handle(const MovePieceCommand &command);
void finishTurn();