Add mouse catching and escape systems to app

This commit is contained in:
2025-04-19 19:12:22 +02:00
parent ba6a560129
commit 077191dc10
8 changed files with 63 additions and 93 deletions

View File

@@ -37,7 +37,7 @@ add_library(fever_core
src/input/input.cpp
src/scene/gltf.cpp
src/scene/gltf_loader.cpp
src/util/log.cpp
src/log/log.cpp
src/window/window.cpp
)

View File

@@ -1,19 +1,48 @@
#include <flecs.h>
#include <input/input.h>
#include <iostream>
#include <log/log.h>
#include <window/window.h>
#include <GLFW/glfw3.h>
#include <iostream>
int main()
{
Log::initialize();
flecs::world world;
world.import <Window::WindowModule>();
world.import <Input::InputModule>();
auto window = Window::spawn_window(world);
auto glfw_window = window.get<std::shared_ptr<GLFWwindow>>();
world.import <Input::InputModule>();
world.system<Window::Window, Input::ButtonInput<Input::KeyCode> const>().each(
[](flecs::entity e,
Window::Window,
Input::ButtonInput<Input::KeyCode> const& button_input) {
if (button_input.just_pressed(Input::KeyCode(GLFW_KEY_LEFT_CONTROL))) {
auto glfw_window = e.get<std::shared_ptr<GLFWwindow>>();
auto input_mode = glfwGetInputMode(glfw_window->get(), GLFW_CURSOR);
if (input_mode == GLFW_CURSOR_NORMAL) {
glfwSetInputMode(glfw_window->get(), GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
} else {
glfwSetInputMode(glfw_window->get(), GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
}
});
world.system<Window::Window, Input::ButtonInput<Input::KeyCode> const>().each(
[](flecs::entity e,
Window::Window,
Input::ButtonInput<Input::KeyCode> const& button_input) {
if (button_input.just_pressed(Input::KeyCode(GLFW_KEY_ESCAPE))) {
auto glfw_window = e.get<std::shared_ptr<GLFWwindow>>();
glfwSetWindowShouldClose(glfw_window->get(), GLFW_TRUE);
}
});
while (glfwWindowShouldClose(glfw_window->get()) == GLFW_FALSE) {
glfwPollEvents();

View File

@@ -4,17 +4,19 @@
namespace Input {
static void keyboard_input_observer(KeyboardInput const& keyboard_input);
void keyboard_input_observer(KeyboardInput const& keyboard_input);
template <typename T> void clear_button_input(ButtonInput<T>& state);
InputModule::InputModule(flecs::world& world)
{
world.component<Input::KeyboardInput>();
world.component<Input::MouseButtonInput>();
world.component<Input::MouseMotion>();
world.component<KeyboardInput>();
world.component<MouseButtonInput>();
world.component<MouseMotion>();
world.component<ButtonInput<KeyCode>>();
world.system<ButtonInput<KeyCode>>("ClearButtonInput")
.kind(flecs::PostUpdate)
.each(ButtonInput<KeyCode>::clear_button_input);
.each(clear_button_input<KeyCode>);
world.observer<KeyboardInput>("KeyboardInputObserver")
.event(flecs::OnSet)
@@ -23,7 +25,7 @@ InputModule::InputModule(flecs::world& world)
void keyboard_input_observer(KeyboardInput const& keyboard_input)
{
auto* key_state = keyboard_input.window.get_mut<Input::ButtonInput<Input::KeyCode>>();
auto* key_state = keyboard_input.window.get_mut<ButtonInput<KeyCode>>();
if (keyboard_input.action == static_cast<Input::Action>(GLFW_PRESS)) {
key_state->press(keyboard_input.key_code);
@@ -32,7 +34,7 @@ void keyboard_input_observer(KeyboardInput const& keyboard_input)
}
}
template <typename T> void ButtonInput<T>::clear_button_input(ButtonInput<T>& state)
template <typename T> void clear_button_input(ButtonInput<T>& state)
{
state.just_pressed_keys.clear();
state.just_released_keys.clear();

View File

@@ -45,8 +45,6 @@ public:
auto just_pressed(T input) const -> bool { return just_pressed_keys.contains(input); }
auto just_released(T input) const -> bool { return just_pressed_keys.contains(input); }
static void clear_button_input(ButtonInput<T>& state);
// private:
void press(T input)
{

View File

@@ -1,17 +0,0 @@
#include "log.h"
#include <spdlog/cfg/env.h>
void Log::initialize()
{
spdlog::set_pattern("[%H:%M:%S.%e] [%^%l%$] %v");
#ifndef NDEBUG
spdlog::set_level(spdlog::level::debug);
#else
spdlog::set_level(spdlog::level::warn);
#endif
// Override level when running with environment variable.
spdlog::cfg::load_env_levels();
}

View File

@@ -1,9 +0,0 @@
#pragma once
#include <spdlog/spdlog.h>
namespace Log {
void initialize();
} // namespace Log

View File

@@ -23,6 +23,7 @@ WindowModule::WindowModule(flecs::world& world)
{
glfwInit();
world.component<Window>();
world.component<PrimaryWindow>();
world.component<std::shared_ptr<GLFWwindow>>();
world.component<std::optional<CursorPosition>>();
world.component<LogicalSize>();
@@ -70,13 +71,16 @@ flecs::entity spawn_window(flecs::world& world)
glfwGetFramebufferSize(glfw_window.get(), &framebuffer_width, &framebuffer_height);
glViewport(0, 0, framebuffer_width, framebuffer_height);
flecs::entity window = world.singleton<Window>();
flecs::entity window = world.entity();
window.add<Window>();
window.add<Input::ButtonInput<Input::KeyCode>>();
window.add<std::optional<CursorPosition>>();
window.set<std::shared_ptr<GLFWwindow>>(glfw_window);
window.set<LogicalSize>({window_width, window_height});
window.set<PhysicalSize>({framebuffer_width, framebuffer_height});
world.set<PrimaryWindow>({window});
return window;
}
@@ -88,7 +92,7 @@ static void glfw_error_callback(int error, char const* description)
void window_size_callback(GLFWwindow* glfw_window, int width, int height)
{
auto* world = static_cast<flecs::world*>(glfwGetWindowUserPointer(glfw_window));
flecs::entity window = world->singleton<Window>();
auto window = world->get<PrimaryWindow>()->window;
window.set<LogicalSize>({width, height});
}
@@ -96,7 +100,7 @@ void window_size_callback(GLFWwindow* glfw_window, int width, int height)
void framebuffer_size_callback(GLFWwindow* glfw_window, int width, int height)
{
auto* world = static_cast<flecs::world*>(glfwGetWindowUserPointer(glfw_window));
flecs::entity window = world->singleton<Window>();
auto window = world->get<PrimaryWindow>()->window;
window.set<PhysicalSize>({width, height});
@@ -110,7 +114,9 @@ void key_callback(GLFWwindow* glfw_window,
[[maybe_unused]] int mods)
{
auto* world = static_cast<flecs::world*>(glfwGetWindowUserPointer(glfw_window));
flecs::entity window = world->singleton<Window>();
// Maybe lookup with the glfw pointer instead?
auto window = world->get<PrimaryWindow>()->window;
world->component<Input::KeyboardInput>().set<Input::KeyboardInput>(
{.key_code = static_cast<Input::KeyCode>(key),
@@ -121,7 +127,7 @@ void key_callback(GLFWwindow* glfw_window,
void mouse_cursor_callback(GLFWwindow* glfw_window, double xpos, double ypos)
{
auto* world = static_cast<flecs::world*>(glfwGetWindowUserPointer(glfw_window));
flecs::entity window = world->singleton<Window>();
auto window = world->get<PrimaryWindow>()->window;
auto cursor_position = window.get_mut<std::optional<CursorPosition>>();
bool had_value = cursor_position->has_value();
@@ -140,26 +146,3 @@ void mouse_cursor_callback(GLFWwindow* glfw_window, double xpos, double ypos)
}
} // namespace Window
// void WindowDeprecated::mouse_catching(entt::registry& registry) const
// {
// auto& mouse_catched = registry.ctx().emplace<MouseCatched>(MouseCatched{.catched = false});
// auto const& key_state = registry.ctx().get<Input::ButtonInput<Input::KeyCode>>();
// if (key_state.just_pressed(Input::KeyCode{GLFW_KEY_LEFT_CONTROL})) {
// mouse_catched.catched = !mouse_catched.catched;
// glfwSetInputMode(glfw_window.get(),
// GLFW_CURSOR,
// mouse_catched.catched ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL);
// }
// }
// void WindowDeprecated::close_on_esc(entt::registry& registry) const
// {
// auto const& key_state = registry.ctx().get<Input::ButtonInput<Input::KeyCode>>();
// if (key_state.just_pressed(Input::KeyCode{GLFW_KEY_ESCAPE})) {
// glfwSetWindowShouldClose(glfw_window.get(), GLFW_TRUE);
// }
// }

View File

@@ -1,20 +1,27 @@
#pragma once
#include <entt/entt.hpp>
#include <input/input.h>
#include <flecs.h>
#include <glm/glm.hpp>
#include <input/input.h>
#include <memory>
class GLFWwindow;
namespace Window {
void glfw_init();
struct WindowModule
{
WindowModule(flecs::world& world);
};
struct Window
{};
struct PrimaryWindow
{
flecs::entity window;
};
struct CursorPosition
{
double x;
@@ -33,29 +40,6 @@ struct PhysicalSize
int height;
};
struct WindowModule
{
WindowModule(flecs::world& world);
};
flecs::entity spawn_window(flecs::world& world);
} // namespace Window
class WindowDeprecated
{
public:
[[nodiscard]] auto handle() -> GLFWwindow& { return *glfw_window; }
void mouse_catching(entt::registry& registry) const;
void close_on_esc(entt::registry& registry) const;
private:
static constexpr float MOUSE_SENSITIVITY = 0.15F;
flecs::world* world;
flecs::entity window_entity;
std::shared_ptr<GLFWwindow> glfw_window;
};