ADD: Ui can now block inputs for tile highlight system

This commit is contained in:
sebastian 2026-02-15 14:17:11 +01:00
parent 285af0ae47
commit 16b4747175
32 changed files with 759 additions and 12 deletions

View File

@ -215,6 +215,27 @@ add_executable(Dicewars_Siedler src/main.cpp
src/engine/renderer/model/GuiTextureBuilder.h src/engine/renderer/model/GuiTextureBuilder.h
src/game/ui/components/UiBuildingMenuContainer.cpp src/game/ui/components/UiBuildingMenuContainer.cpp
src/game/ui/components/UiBuildingMenuContainer.h src/game/ui/components/UiBuildingMenuContainer.h
src/engine/core/inputsOutputs/stateControl/states/IState.cpp
src/engine/core/inputsOutputs/stateControl/states/IState.h
src/engine/core/inputsOutputs/stateControl/InputUser.cpp
src/engine/core/inputsOutputs/stateControl/InputUser.h
src/engine/core/inputsOutputs/inputs/Keyboard.cpp
src/engine/core/inputsOutputs/inputs/Keyboard.h
src/engine/core/inputsOutputs/inputs/Mouse.cpp
src/engine/core/inputsOutputs/inputs/Mouse.h
src/engine/core/inputsOutputs/inputs/MouseButton.h
src/engine/core/inputsOutputs/stateControl/RegisteredUsers.cpp
src/engine/core/inputsOutputs/stateControl/RegisteredUsers.h
src/engine/core/inputsOutputs/stateControl/StateManager.cpp
src/engine/core/inputsOutputs/stateControl/StateManager.h
src/engine/core/inputsOutputs/stateControl/states/State.cpp
src/engine/core/inputsOutputs/stateControl/states/State.h
src/engine/core/inputsOutputs/stateControl/states/EmptyState.cpp
src/engine/core/inputsOutputs/stateControl/states/EmptyState.h
src/engine/core/inputsOutputs/stateControl/inputUser/GameInputUser.cpp
src/engine/core/inputsOutputs/stateControl/inputUser/GameInputUser.h
src/engine/core/inputsOutputs/stateControl/StateRegistry.cpp
src/engine/core/inputsOutputs/stateControl/StateRegistry.h
) )
target_compile_options(Dicewars_Siedler PRIVATE target_compile_options(Dicewars_Siedler PRIVATE

View File

@ -7,6 +7,9 @@
#include "EngineTime.h" #include "EngineTime.h"
#include "../layer/Layer.h" #include "../layer/Layer.h"
#include "../platform/glfw/InputManager.h" #include "../platform/glfw/InputManager.h"
#include "inputsOutputs/stateControl/StateRegistry.h"
#include "inputsOutputs/stateControl/states/EmptyState.h"
#include "inputsOutputs/stateControl/states/State.h"
Application* Application::instance = nullptr; Application* Application::instance = nullptr;
@ -16,7 +19,7 @@ void Application::updateTime() {
EngineTime::totalTime += EngineTime::deltaTime; EngineTime::totalTime += EngineTime::deltaTime;
lastFrame = now; lastFrame = now;
printf("Frametime: %f\n", EngineTime::deltaTime); // printf("Frametime: %f\n", EngineTime::deltaTime);
} }
void Application::pushLayer(Layer* layer) { void Application::pushLayer(Layer* layer) {
@ -35,6 +38,9 @@ Application::Application()
window_props.VSync = true; window_props.VSync = true;
window.reset(Window::Create(window_props)); window.reset(Window::Create(window_props));
keyboard = std::make_unique<Keyboard>(*window);
mouse = std::make_unique<Mouse>(*window);
stateManager = std::make_unique<StateManager>(StateRegistry::get().empty, StateRegistry::get().game);
} }
Application::~Application() Application::~Application()
@ -51,6 +57,10 @@ void Application::run() {
} }
window->OnUpdate(); window->OnUpdate();
InputManager::update(); InputManager::update();
mouse->update();
keyboard->update();
stateManager->updateState();
} }
} }

View File

@ -9,6 +9,10 @@
#include "Window.h" #include "Window.h"
#include "events/EventBus.h" #include "events/EventBus.h"
#include "inputsOutputs/inputs/Keyboard.h"
#include "inputsOutputs/inputs/Mouse.h"
#include "inputsOutputs/stateControl/StateManager.h"
#include "inputsOutputs/stateControl/states/State.h"
class Layer; class Layer;
@ -25,6 +29,11 @@ public:
static Application& getInstance(); static Application& getInstance();
[[nodiscard]] Window& getWindow() const {return *window;} [[nodiscard]] Window& getWindow() const {return *window;}
EventBus& getEventBus() {return eventBus;} EventBus& getEventBus() {return eventBus;}
std::unique_ptr<Keyboard> keyboard;
std::unique_ptr<Mouse> mouse;
std::unique_ptr<StateManager> stateManager;
std::shared_ptr<GameState> gameState;
private: private:
bool running = true; bool running = true;
std::unique_ptr<Window> window; std::unique_ptr<Window> window;

View File

@ -38,9 +38,9 @@ void UiButton::onCollectRenderData(UiRenderBundle &uiRenderBundle) {
VisualStyle UiButton::getVisualStyle() const { VisualStyle UiButton::getVisualStyle() const {
switch (state) { switch (state) {
case UiState::PRESSED: case UiElementState::PRESSED:
return {1.0f, glm::vec3(0.3, 0.6, 1.0), 0.15f}; return {1.0f, glm::vec3(0.3, 0.6, 1.0), 0.15f};
case UiState::HOVERED: case UiElementState::HOVERED:
return {1.15f, glm::vec3(0.0f), 0.0f}; return {1.15f, glm::vec3(0.0f), 0.0f};
default: default:
return {}; return {};

View File

@ -59,15 +59,15 @@ void UiComponent::onUpdate(float) {
bool releasedFrame = InputManager::isMouseButtonReleased(GLFW_MOUSE_BUTTON_LEFT); bool releasedFrame = InputManager::isMouseButtonReleased(GLFW_MOUSE_BUTTON_LEFT);
if (pressedThisFrame) { if (pressedThisFrame) {
state = UiState::PRESSED; state = UiElementState::PRESSED;
} else if (releasedFrame) { } else if (releasedFrame) {
if (state == UiState::PRESSED && hoveredNow) { if (state == UiElementState::PRESSED && hoveredNow) {
onClick(); onClick();
} }
state = hoveredNow ? UiState::HOVERED : UiState::NORMAL; state = hoveredNow ? UiElementState::HOVERED : UiElementState::NORMAL;
} else { } else {
if (state != UiState::PRESSED) if (state != UiElementState::PRESSED)
state = hoveredNow ? UiState::HOVERED : UiState::NORMAL; state = hoveredNow ? UiElementState::HOVERED : UiElementState::NORMAL;
} }
} }

View File

@ -11,7 +11,7 @@
#include "UiRenderBundle.h" #include "UiRenderBundle.h"
#include "../../../renderer/model/GUITexture.h" #include "../../../renderer/model/GUITexture.h"
enum class UiState { enum class UiElementState {
NORMAL, HOVERED, PRESSED NORMAL, HOVERED, PRESSED
}; };
@ -38,13 +38,13 @@ public:
uiPositioner.setLayout(style); uiPositioner.setLayout(style);
} }
[[nodiscard]] bool isHovered() const { return state == UiState::HOVERED; } [[nodiscard]] bool isHovered() const { return state == UiElementState::HOVERED; }
virtual void onClick() {}; virtual void onClick() {};
UiComponent* getChildAtIndex(size_t t) const; UiComponent* getChildAtIndex(size_t t) const;
protected: protected:
bool visible = true; bool visible = true;
UiState state = UiState::NORMAL; UiElementState state = UiElementState::NORMAL;
virtual void onUpdate(float ); virtual void onUpdate(float );
virtual void onCollectRenderData(UiRenderBundle& uiRenderBundle) {} virtual void onCollectRenderData(UiRenderBundle& uiRenderBundle) {}

View File

@ -0,0 +1,68 @@
//
// Created by sebastian on 15.02.26.
//
#include "Keyboard.h"
#include "../../Window.h"
#include "../../Application.h"
#include <GLFW/glfw3.h>
Keyboard::Keyboard(Window &window) {
addKeyListener(window);
addTextListener(window);
}
void Keyboard::update() {
keysPressedThisFrame.clear();
keysReleasedThisFrame.clear();
keysRepeatedThisFrame.clear();
charsThisFrame.clear();
}
bool Keyboard::isKeyDown(int key) {
return keysDown.contains(key);
}
const std::vector<int> & Keyboard::getCharsThisFrame() {
return charsThisFrame;
}
bool Keyboard::keyPressEvent(int key) {
return keysPressedThisFrame.contains(key);
}
bool Keyboard::keyPressEvent(int key, bool checkRepeats) {
return keysPressedThisFrame.contains(key) || (checkRepeats && keysRepeatedThisFrame.contains(key));
}
bool Keyboard::keyReleaseEvent(int key) {
return keysReleasedThisFrame.contains(key);
}
void Keyboard::addTextListener(Window &window) {
glfwSetCharCallback(static_cast<GLFWwindow *>(window.GetNativeWindow()), [](GLFWwindow *window, const unsigned int key) {
Application::getInstance().keyboard->charsThisFrame.push_back(static_cast<int>(key));
});
}
void Keyboard::addKeyListener(Window &window) {
glfwSetKeyCallback(static_cast<GLFWwindow *>(window.GetNativeWindow()), [](GLFWwindow *window, int key, int scancode, int action, int mods) {
if (action == GLFW_PRESS) {
Application::getInstance().keyboard->reportKeyPress(key);
} else if (action == GLFW_RELEASE) {
Application::getInstance().keyboard->reportKeyRelease(key);
} else if (action == GLFW_REPEAT) {
Application::getInstance().keyboard->keysRepeatedThisFrame.insert(key);
}
});
}
void Keyboard::reportKeyPress(int key) {
keysDown.insert(key);
keysPressedThisFrame.insert(key);
}
void Keyboard::reportKeyRelease(int key) {
keysDown.erase(key);
keysReleasedThisFrame.insert(key);
}

View File

@ -0,0 +1,38 @@
//
// Created by sebastian on 15.02.26.
//
#ifndef DICEWARS_SIEDLER_KEYBOARD_H
#define DICEWARS_SIEDLER_KEYBOARD_H
#include <unordered_set>
#include <vector>
class Window;
class Keyboard {
public:
explicit Keyboard(Window& window);
void update();
bool isKeyDown(int key);
const std::vector<int>& getCharsThisFrame();
bool keyPressEvent(int key);
bool keyPressEvent(int key, bool checkRepeats);
bool keyReleaseEvent(int key);
private:
std::unordered_set<int> keysPressedThisFrame;
std::unordered_set<int> keysRepeatedThisFrame;
std::unordered_set<int> keysReleasedThisFrame;
std::unordered_set<int> keysDown;
std::vector<int> charsThisFrame;
static void addTextListener(Window& window);
static void addKeyListener(Window& window);
void reportKeyPress(int key);
void reportKeyRelease(int key);
};
#endif //DICEWARS_SIEDLER_KEYBOARD_H

View File

@ -0,0 +1,107 @@
//
// Created by sebastian on 15.02.26.
//
#include "Mouse.h"
#include "../../Window.h"
#include "../../Application.h"
#include <GLFW/glfw3.h>
Mouse::Mouse(Window &window) {
addMoveListener(window);
addScrollListener(window);
addClickListener(window);
}
bool Mouse::isButtonDown(MouseButton button) {
return buttonsDown.contains(MouseButtonToInt(button));
}
bool Mouse::isClickEvent(MouseButton button) {
return buttonsClickedThisFrame.contains(MouseButtonToInt(button));
}
bool Mouse::isReleaseEvent(MouseButton button) {
return buttonsReleasedThisFrame.contains(MouseButtonToInt(button));
}
float Mouse::getX() {
return x;
}
float Mouse::getY() {
return y;
}
float Mouse::getDX() {
return dx;
}
float Mouse::getDY() {
return dy;
}
float Mouse::getScroll() {
return scroll;
}
void Mouse::update() {
buttonsClickedThisFrame.clear();
buttonsReleasedThisFrame.clear();
updateDetlas();
scroll = 0.0f;
}
void Mouse::reportButtonClick(int button) {
buttonsDown.insert(button);
buttonsClickedThisFrame.insert(button);
}
void Mouse::reportButtonRelease(int button) {
buttonsDown.erase(button);
buttonsReleasedThisFrame.insert(button);
}
void Mouse::updateDetlas() {
dx = x - lastX;
dy = y - lastY;
lastX = x;
lastY = y;
}
void Mouse::addMoveListener(Window &window) {
glfwSetCursorPosCallback(static_cast<GLFWwindow *>(window.GetNativeWindow()), [](GLFWwindow *window, double xpos, double ypos) {
Application::getInstance().mouse->x = static_cast<float>(xpos / Application::getInstance().getWindow().GetWidth() );
Application::getInstance().mouse->y = static_cast<float>(ypos / Application::getInstance().getWindow().GetHeight());
});
}
void Mouse::addScrollListener(Window &window) {
glfwSetScrollCallback(static_cast<GLFWwindow *>(window.GetNativeWindow()), [](GLFWwindow *window, double xoff, double yoff) {
Application::getInstance().mouse->scroll = static_cast<float>(yoff);
});
}
void Mouse::addClickListener(Window &window) {
glfwSetMouseButtonCallback(static_cast<GLFWwindow *>(window.GetNativeWindow()), [](GLFWwindow *window, int button, int action, int mods) {
if (action == GLFW_PRESS) {
Application::getInstance().mouse->reportButtonClick(button);
} else if (action == GLFW_RELEASE) {
Application::getInstance().mouse->reportButtonRelease(button);
}
});
}
int 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

@ -0,0 +1,47 @@
//
// Created by sebastian on 15.02.26.
//
#ifndef DICEWARS_SIEDLER_MOUSE_H
#define DICEWARS_SIEDLER_MOUSE_H
#include <unordered_set>
#include "MouseButton.h"
class Window;
class Mouse {
public:
explicit Mouse(Window& window);
bool isButtonDown(MouseButton button);
bool isClickEvent(MouseButton button);
bool isReleaseEvent(MouseButton button);
float getX();
float getY();
float getDX();
float getDY();
float getScroll();
void update();
private:
std::unordered_set<int> buttonsDown;
std::unordered_set<int> buttonsClickedThisFrame;
std::unordered_set<int> buttonsReleasedThisFrame;
float x, y;
float dx, dy;
float scroll;
float lastX, lastY;
void reportButtonClick(int button);
void reportButtonRelease(int button);
void updateDetlas();
static void addMoveListener(Window& window);
static void addScrollListener(Window& window);
static void addClickListener(Window& window);
static int MouseButtonToInt(MouseButton button);
};
#endif //DICEWARS_SIEDLER_MOUSE_H

View File

@ -0,0 +1,14 @@
//
// Created by sebastian on 15.02.26.
//
#ifndef DICEWARS_SIEDLER_MOUSEBUTTON_H
#define DICEWARS_SIEDLER_MOUSEBUTTON_H
enum class MouseButton {
LEFT,
RIGHT,
MIDDLE
};
#endif //DICEWARS_SIEDLER_MOUSEBUTTON_H

View File

@ -0,0 +1,5 @@
//
// Created by sebastian on 15.02.26.
//
#include "InputUser.h"

View File

@ -0,0 +1,29 @@
//
// Created by sebastian on 15.02.26.
//
#ifndef DICEWARS_SIEDLER_INPUTUSER_H
#define DICEWARS_SIEDLER_INPUTUSER_H
#include "../inputs/Keyboard.h"
class Mouse;
class InputUser {
protected:
bool mouseEnabled = true;
bool keyboardEnabled = true;
public:
virtual ~InputUser() = default;
void enableKeyboard(bool enable) {keyboardEnabled = enable;}
void enableMouse(bool enable) {mouseEnabled = enable;}
bool isKeyboardEnabled() const {return keyboardEnabled;}
bool isMouseEnabled() const {return mouseEnabled;}
bool isFullyEnabled() const {return keyboardEnabled && mouseEnabled;}
};
#endif //DICEWARS_SIEDLER_INPUTUSER_H

View File

@ -0,0 +1,54 @@
//
// Created by sebastian on 15.02.26.
//
#include "RegisteredUsers.h"
void RegisteredUsers::registerMouseUser(IState *state, InputUser* user) {
registerInputUser(state, user, registeredMouseUsers);
}
void RegisteredUsers::registerKeyboardUser(IState *state, InputUser *user) {
registerInputUser(state, user, registeredKeyboardUsers);
}
void RegisteredUsers::registerUser(IState *state, InputUser *user) {
registerInputUser(state, user, registeredKeyboardUsers);
registerInputUser(state, user, registeredMouseUsers);
}
void RegisteredUsers::initState(IState *state) {
enableMouseUsers(state, true);
enableKeyboardUsers(state, true);
}
void RegisteredUsers::endState(IState *state) {
enableMouseUsers(state, false);
enableKeyboardUsers(state, false);
}
void RegisteredUsers::registerInputUser(IState *state, InputUser* user,
std::unordered_map<IState *, std::unordered_set<InputUser*>> &registeredUsers) {
registeredUsers[state].insert(user);
}
void RegisteredUsers::enableMouseUsers(IState *state, bool enable) {
auto it = registeredMouseUsers.find(state);
if (it == registeredMouseUsers.end())
return;
for (InputUser *user : it->second) {
user->enableMouse(enable);
}
}
void RegisteredUsers::enableKeyboardUsers(IState *state, bool enable) {
auto it = registeredKeyboardUsers.find(state);
if (it == registeredKeyboardUsers.end())
return;
for (InputUser *user : it->second) {
user->enableKeyboard(enable);
}
}

View File

@ -0,0 +1,32 @@
//
// Created by sebastian on 15.02.26.
//
#ifndef DICEWARS_SIEDLER_REGISTEREDUSERS_H
#define DICEWARS_SIEDLER_REGISTEREDUSERS_H
#include <unordered_map>
#include <unordered_set>
#include "InputUser.h"
#include "states/IState.h"
class RegisteredUsers {
public:
void registerMouseUser(IState* state, InputUser* user);
void registerKeyboardUser(IState* state, InputUser* user);
void registerUser(IState* state, InputUser* user);
void initState(IState* state);
void endState(IState* state);
private:
std::unordered_map<IState*, std::unordered_set<InputUser*>> registeredMouseUsers;
std::unordered_map<IState*, std::unordered_set<InputUser*>> registeredKeyboardUsers;
static void registerInputUser(IState* state, InputUser* user, std::unordered_map<IState*, std::unordered_set<InputUser*>>& registeredUsers);
void enableMouseUsers(IState* state, bool enable);
void enableKeyboardUsers(IState* state, bool enable);
};
#endif //DICEWARS_SIEDLER_REGISTEREDUSERS_H

View File

@ -0,0 +1,76 @@
//
// Created by sebastian on 15.02.26.
//
#include "StateManager.h"
#include <algorithm>
#include <utility>
void StateManager::suggestState(std::shared_ptr<IState> state, bool waitForEndRequest) {
QueuedState queuedState(state, waitForEndRequest);
sortStateIntoQueue(queuedState);
}
void StateManager::endState(std::shared_ptr<IState> state) {
queuedStates.erase(std::remove_if(queuedStates.begin(), queuedStates.end(), [&](const QueuedState &queuedState) {
return queuedState.state == state;
}), queuedStates.end());
}
void StateManager::updateState() {
auto nextState = getNextState();
cleanQueue();
if (currentState == nextState) {
return;
}
switchState(nextState);
}
void StateManager::registerUser(InputUser *user, std::initializer_list<std::shared_ptr<IState>> states) {
for (auto& state : states) {
registeredUsers.registerUser(state.get(), user);
}
}
void StateManager::registerKeyboardUser(InputUser *user, std::initializer_list<std::shared_ptr<IState>> states) {
for (auto& state : states) {
registeredUsers.registerKeyboardUser(state.get(), user);
}
}
void StateManager::registerMouseUser(InputUser *user, std::initializer_list<std::shared_ptr<IState>> states) {
for (auto& state : states) {
registeredUsers.registerMouseUser(state.get(), user);
}
}
void StateManager::sortStateIntoQueue(const QueuedState &queued_state) {
auto it = std::ranges::find_if(queuedStates,
[&](const QueuedState &s) {
return s.state->getPriority() > queued_state.state->getPriority();
});
queuedStates.insert(it, queued_state);
}
std::shared_ptr<IState> StateManager::getNextState() {
if (queuedStates.empty()) {
return defaultState;
}
return queuedStates.front().state;
}
void StateManager::cleanQueue() {
queuedStates.erase(
std::remove_if(queuedStates.begin(), queuedStates.end(),
[](const QueuedState& s) { return !s.waitForEndRequest; }),
queuedStates.end()
);
}
void StateManager::switchState(std::shared_ptr<IState> newState) {
registeredUsers.endState(currentState.get());
currentState = std::move(newState);
registeredUsers.initState(currentState.get());
}

View File

@ -0,0 +1,47 @@
//
// Created by sebastian on 15.02.26.
//
#ifndef DICEWARS_SIEDLER_STATEMANAGER_H
#define DICEWARS_SIEDLER_STATEMANAGER_H
#include <memory>
#include <utility>
#include "states/IState.h"
#include "RegisteredUsers.h"
class StateManager {
public:
StateManager(std::shared_ptr<IState> defaultState, std::shared_ptr<IState> initialState) : defaultState(defaultState), currentState(initialState) {
suggestState(initialState, true);
};
void suggestState(std::shared_ptr<IState> state, bool waitForEndRequest);
void endState(std::shared_ptr<IState> state);
std::shared_ptr<IState> getCurrentState() const {return currentState;}
void updateState();
void registerUser(InputUser* user, std::initializer_list<std::shared_ptr<IState>> states);
void registerKeyboardUser(InputUser* user, std::initializer_list<std::shared_ptr<IState>> states);
void registerMouseUser(InputUser* user, std::initializer_list<std::shared_ptr<IState>> states);
private:
struct QueuedState {
std::shared_ptr<IState> state;
bool waitForEndRequest;
};
std::shared_ptr<IState> defaultState;
std::shared_ptr<IState> currentState;
RegisteredUsers registeredUsers;
std::vector<QueuedState> queuedStates;
void sortStateIntoQueue(const QueuedState& queued_state);
std::shared_ptr<IState> getNextState();
void cleanQueue();
void switchState(std::shared_ptr<IState> newState);
};
#endif //DICEWARS_SIEDLER_STATEMANAGER_H

View File

@ -0,0 +1,5 @@
//
// Created by sebastian on 15.02.26.
//
#include "StateRegistry.h"

View File

@ -0,0 +1,37 @@
//
// Created by sebastian on 15.02.26.
//
#ifndef DICEWARS_SIEDLER_STATEREGISTRY_H
#define DICEWARS_SIEDLER_STATEREGISTRY_H
#include <memory>
#include "states/EmptyState.h"
#include "states/State.h"
class StateRegistry {
public:
static StateRegistry& get() {
static StateRegistry instance;
return instance;
}
std::shared_ptr<GameState> game;
std::shared_ptr<EmptyState> empty;
std::shared_ptr<UiState> uiState;
private:
StateRegistry() {
game = std::make_shared<GameState>();
empty = std::make_shared<EmptyState>();
uiState = std::make_shared<UiState>();
}
// Keine Kopien erlaubt
StateRegistry(const StateRegistry&) = delete;
StateRegistry& operator=(const StateRegistry&) = delete;
};
#endif //DICEWARS_SIEDLER_STATEREGISTRY_H

View File

@ -0,0 +1,5 @@
//
// Created by sebastian on 15.02.26.
//
#include "GameInputUser.h"

View File

@ -0,0 +1,41 @@
//
// Created by sebastian on 15.02.26.
//
#ifndef DICEWARS_SIEDLER_GAMEINPUTUSER_H
#define DICEWARS_SIEDLER_GAMEINPUTUSER_H
#include "../InputUser.h"
#include "../../../Application.h"
#include "../../../../../game/hexWorld/ecs/systems/TileHighlightSystem.h"
class GameInputUser : public InputUser {
public:
GameInputUser(TileHighlightSystem& highlightSystem,
EntityManager& em,
MousePicker& picker,
Camera& camera,
GameMode& gameMode)
: highlightSystem(highlightSystem),
em(em),
picker(picker),
camera(camera),
gameMode(gameMode) {}
void update() {
if (!isMouseEnabled()) {
return;
}
highlightSystem.update(em, picker, camera, gameMode);
}
private:
TileHighlightSystem& highlightSystem;
EntityManager& em;
MousePicker& picker;
Camera& camera;
GameMode& gameMode;
};
#endif //DICEWARS_SIEDLER_GAMEINPUTUSER_H

View File

@ -0,0 +1,5 @@
//
// Created by sebastian on 15.02.26.
//
#include "EmptyState.h"

View File

@ -0,0 +1,17 @@
//
// Created by sebastian on 15.02.26.
//
#ifndef DICEWARS_SIEDLER_EMPTYSTATE_H
#define DICEWARS_SIEDLER_EMPTYSTATE_H
#include <limits>
#include "IState.h"
class EmptyState : public IState{
int getPriority() override { return std::numeric_limits<int>::max(); }
};
#endif //DICEWARS_SIEDLER_EMPTYSTATE_H

View File

@ -0,0 +1,5 @@
//
// Created by sebastian on 15.02.26.
//
#include "IState.h"

View File

@ -0,0 +1,17 @@
//
// Created by sebastian on 15.02.26.
//
#ifndef DICEWARS_SIEDLER_ISTATE_H
#define DICEWARS_SIEDLER_ISTATE_H
class IState {
public:
virtual ~IState() = default;
virtual int getPriority() = 0;
};
#endif //DICEWARS_SIEDLER_ISTATE_H

View File

@ -0,0 +1,5 @@
//
// Created by sebastian on 15.02.26.
//
#include "State.h"

View File

@ -0,0 +1,26 @@
//
// Created by sebastian on 15.02.26.
//
#ifndef DICEWARS_SIEDLER_STATE_H
#define DICEWARS_SIEDLER_STATE_H
#include "IState.h"
class GameState : public IState {
public:
int getPriority() override { return 10; }
};
class UiState : public IState {
public:
int getPriority() override { return 5; }
};
class ModalState : public IState {
public:
int getPriority() override { return 0; } // höchste Priorität
};
#endif //DICEWARS_SIEDLER_STATE_H

View File

@ -9,6 +9,7 @@
#include "../engine/core/animations/AnimationSystem.h" #include "../engine/core/animations/AnimationSystem.h"
#include "../engine/core/ECS/ModelStateComponent.h" #include "../engine/core/ECS/ModelStateComponent.h"
#include "../engine/core/ECS/WorldSpriteComponent.h" #include "../engine/core/ECS/WorldSpriteComponent.h"
#include "../engine/core/inputsOutputs/stateControl/StateRegistry.h"
#include "../engine/platform/glfw/InputManager.h" #include "../engine/platform/glfw/InputManager.h"
#include "../engine/renderer/Renderer.h" #include "../engine/renderer/Renderer.h"
#include "../engine/renderer/loader/OBJLoader.h" #include "../engine/renderer/loader/OBJLoader.h"
@ -66,6 +67,9 @@ void GameLayer::onAttach()
events.subscribe<TurnChangedEvent>([this](const TurnChangedEvent& event) { events.subscribe<TurnChangedEvent>([this](const TurnChangedEvent& event) {
ProducingSystem::onTurnEnded(*entityManager); ProducingSystem::onTurnEnded(*entityManager);
}); });
gameInputUser = std::make_unique<GameInputUser>(*tileHighlightSystem, *entityManager, *mousePicker, *camera, *gameMode);
Application::getInstance().stateManager->registerMouseUser(gameInputUser.get(), {StateRegistry::get().game});
} }
void GameLayer::onDetach() void GameLayer::onDetach()
@ -100,7 +104,11 @@ void GameLayer::onUpdate()
AnimationSystem::update(*entityManager, EngineTime::totalTime); AnimationSystem::update(*entityManager, EngineTime::totalTime);
camera->move(moveDir, 0.5f); camera->move(moveDir, 0.5f);
tileHighlightSystem->update(*entityManager, *mousePicker, *camera, *gameMode); if (gameInputUser->isMouseEnabled()) {
tileHighlightSystem->update(*entityManager, *mousePicker, *camera, *gameMode);
} else {
tileHighlightSystem->reset(*entityManager);
}
buildingPlacementSystem->update(*entityManager, *gameMode, 0, *turnState); buildingPlacementSystem->update(*entityManager, *gameMode, 0, *turnState);
CollectResourceSystem::update(*entityManager, *gameMode); CollectResourceSystem::update(*entityManager, *gameMode);
RenderSystem::render(*entityManager, *renderer); RenderSystem::render(*entityManager, *renderer);

View File

@ -5,6 +5,7 @@
#ifndef DICEWARS_SIEDLER_GAMELAYER_H #ifndef DICEWARS_SIEDLER_GAMELAYER_H
#define DICEWARS_SIEDLER_GAMELAYER_H #define DICEWARS_SIEDLER_GAMELAYER_H
#include "../engine/core/ECS/RenderSystem.h" #include "../engine/core/ECS/RenderSystem.h"
#include "../engine/core/inputsOutputs/stateControl/inputUser/GameInputUser.h"
#include "../engine/layer/Layer.h" #include "../engine/layer/Layer.h"
#include "../engine/platform/glfw/MousePicker.h" #include "../engine/platform/glfw/MousePicker.h"
#include "../engine/renderer/Renderer.h" #include "../engine/renderer/Renderer.h"
@ -48,6 +49,8 @@ private:
std::unique_ptr<TurnSystem> turnSystem = std::make_unique<TurnSystem>(); std::unique_ptr<TurnSystem> turnSystem = std::make_unique<TurnSystem>();
std::unique_ptr<TurnState> turnState = std::make_unique<TurnState>(); std::unique_ptr<TurnState> turnState = std::make_unique<TurnState>();
std::unique_ptr<GameInputUser> gameInputUser;
EntityID testEntity; EntityID testEntity;
}; };

View File

@ -12,6 +12,7 @@
#include "../engine/core/gui/uiComponent/UiButton.h" #include "../engine/core/gui/uiComponent/UiButton.h"
#include "../engine/core/gui/uiComponent/UiImage.h" #include "../engine/core/gui/uiComponent/UiImage.h"
#include "../engine/core/gui/uiComponent/UiText.h" #include "../engine/core/gui/uiComponent/UiText.h"
#include "../engine/core/inputsOutputs/stateControl/StateRegistry.h"
#include "../engine/renderer/loader/AssetManager.h" #include "../engine/renderer/loader/AssetManager.h"
#include "../engine/renderer/loader/Loader.h" #include "../engine/renderer/loader/Loader.h"
#include "../engine/renderer/model/GUITexture.h" #include "../engine/renderer/model/GUITexture.h"
@ -139,6 +140,11 @@ void UILayer::onUpdate() {
auto renderTexts = renderBundle.getGUITexts(); auto renderTexts = renderBundle.getGUITexts();
textRenderer->renderGuiTexts(renderTexts); textRenderer->renderGuiTexts(renderTexts);
if (rootContainer->isMouseOver(Application::getInstance().mouse->getX(), Application::getInstance().mouse->getY())) {
Application::getInstance().stateManager->suggestState(StateRegistry::get().uiState, false);
} else {
Application::getInstance().stateManager->suggestState(StateRegistry::get().game, false);
}
} }
void UILayer::onDetach() { void UILayer::onDetach() {

View File

@ -42,6 +42,15 @@ void TileHighlightSystem::update(EntityManager &entityManager, const MousePicker
} }
} }
void TileHighlightSystem::reset(EntityManager &entityManager) {
for (EntityID entityID : entityManager.getAllEntities()) {
auto tileRenderComponent = entityManager.getComponent<TileRenderComponent>(entityID);
if (tileRenderComponent) {
tileRenderComponent->isHighlighted = false;
}
}
}
bool TileHighlightSystem::intersectTile(const glm::vec3 &rayOrigin, const glm::vec3 &rayDirection, glm::vec3 worldPos, float hexRadius, glm::vec3& intersectionPoint) { bool TileHighlightSystem::intersectTile(const glm::vec3 &rayOrigin, const glm::vec3 &rayDirection, glm::vec3 worldPos, float hexRadius, glm::vec3& intersectionPoint) {
float t = -rayOrigin.y / rayDirection.y; float t = -rayOrigin.y / rayDirection.y;
if (t < 0) return false; if (t < 0) return false;

View File

@ -13,6 +13,7 @@ class Camera;
class TileHighlightSystem { class TileHighlightSystem {
public: public:
void update(EntityManager &entityManager, const MousePicker &picker, const Camera &camera, GameMode& gameMode); void update(EntityManager &entityManager, const MousePicker &picker, const Camera &camera, GameMode& gameMode);
void reset(EntityManager& entityManager);
private: private:
bool intersectTile(const glm::vec3 & rayOrigin, const glm::vec3 & rayDirection, glm::vec3 worldPos, float hexRadius, glm::vec3 &interectionPoint); bool intersectTile(const glm::vec3 & rayOrigin, const glm::vec3 & rayDirection, glm::vec3 worldPos, float hexRadius, glm::vec3 &interectionPoint);
}; };