Port window and input events to flecs

This commit is contained in:
2025-04-19 12:22:22 +02:00
parent e590203234
commit ba6a560129
8 changed files with 158 additions and 167 deletions

View File

@@ -17,7 +17,7 @@ void Flycam::keyboard_movement(entt::registry& registry)
};
auto& movement_context = registry.ctx().emplace<KeyboardMovementContext>();
auto const& key_state = registry.ctx().get<Input::State<Input::KeyCode>>();
auto const& key_state = registry.ctx().get<Input::ButtonInput<Input::KeyCode>>();
auto const& delta_time = registry.ctx().get<Time::Delta>();
auto camera_view =

View File

@@ -1,38 +1,25 @@
#include <input/input.h>
#include <window/window.h>
#include <flecs.h>
#include <input/input.h>
#include <iostream>
#include <window/window.h>
#include <GLFW/glfw3.h>
int main()
{
flecs::world world;
world.import<WindowModule>();
spawn_window(world);
auto window = world.singleton<Window>();
world.import <Window::WindowModule>();
auto window = Window::spawn_window(world);
auto glfw_window = window.get<std::shared_ptr<GLFWwindow>>();
window.observe<Input::KeyInput>([window](Input::KeyInput& key_input) {
auto* key_state = window.get_mut<Input::State<Input::KeyCode>>();
if (key_input.action == static_cast<Input::Action>(GLFW_PRESS)) {
key_state->press(key_input.key_code);
} else if (key_input.action == static_cast<Input::Action>(GLFW_RELEASE)) {
key_state->release(key_input.key_code);
}
});
world.import <Input::InputModule>();
while (glfwWindowShouldClose(glfw_window->get()) == GLFW_FALSE) {
glfwPollEvents();
// X just pressed
auto* keycode= window.get<Input::State<Input::KeyCode>>();
if (keycode->just_pressed(Input::KeyCode{GLFW_KEY_X}))
std::cout << "X was just pressed!\n";
world.progress();
Input::State<Input::KeyCode>::update_state(window);
glfwSwapBuffers(glfw_window->get());
}
}
}

View File

@@ -32,13 +32,13 @@ auto Camera::front_vector(GlobalTransform const& transform) -> glm::vec3
void Camera::aspect_ratio_update(entt::registry& registry)
{
float aspect_ratio = registry.ctx().get<WindowDeprecated::Descriptor>().aspect_ratio;
// float aspect_ratio = registry.ctx().get<WindowDeprecated::Descriptor>().aspect_ratio;
auto camera_view = registry.view<Camera>();
// auto camera_view = registry.view<Camera>();
for (auto [entity, camera] : camera_view.each()) {
// Orthographic projection currently unsupported
auto& camera_perspective = std::get<Perspective>(camera.projection);
camera_perspective.aspect_ratio = aspect_ratio;
}
// for (auto [entity, camera] : camera_view.each()) {
// // Orthographic projection currently unsupported
// auto& camera_perspective = std::get<Perspective>(camera.projection);
// camera_perspective.aspect_ratio = aspect_ratio;
// }
}

View File

@@ -4,36 +4,40 @@
namespace Input {
// void KeyListener::key_event(KeyInput const& key_input_event)
// {
// auto& key_state = registry.ctx().get<State<KeyCode>>();
static void keyboard_input_observer(KeyboardInput const& keyboard_input);
// if (key_input_event.action == static_cast<Action>(GLFW_PRESS)) {
// key_state.press(key_input_event.key_code);
// } else if (key_input_event.action == static_cast<Action>(GLFW_RELEASE)) {
// key_state.release(key_input_event.key_code);
// }
// }
// void CursorListener::cursor_event(MouseMotion const& mouse_motion_event)
// {
// auto& mouse_motion = registry.ctx().get<MouseMotion>();
// mouse_motion.delta += mouse_motion_event.delta;
// }
void reset_mouse_motion(entt::registry& registry)
InputModule::InputModule(flecs::world& world)
{
auto& mouse_motion = registry.ctx().get<MouseMotion>();
mouse_motion = {};
world.component<Input::KeyboardInput>();
world.component<Input::MouseButtonInput>();
world.component<Input::MouseMotion>();
world.system<ButtonInput<KeyCode>>("ClearButtonInput")
.kind(flecs::PostUpdate)
.each(ButtonInput<KeyCode>::clear_button_input);
world.observer<KeyboardInput>("KeyboardInputObserver")
.event(flecs::OnSet)
.each(keyboard_input_observer);
}
template <typename T> void State<T>::update_state(flecs::entity window_entity)
void keyboard_input_observer(KeyboardInput const& keyboard_input)
{
auto* state = window_entity.get_mut<State<T>>();
state->just_pressed_keys.clear();
state->just_released_keys.clear();
auto* key_state = keyboard_input.window.get_mut<Input::ButtonInput<Input::KeyCode>>();
if (keyboard_input.action == static_cast<Input::Action>(GLFW_PRESS)) {
key_state->press(keyboard_input.key_code);
} else if (keyboard_input.action == static_cast<Input::Action>(GLFW_RELEASE)) {
key_state->release(keyboard_input.key_code);
}
}
template class State<KeyCode>;
template <typename T> void ButtonInput<T>::clear_button_input(ButtonInput<T>& state)
{
state.just_pressed_keys.clear();
state.just_released_keys.clear();
}
template class ButtonInput<KeyCode>;
} // namespace Input

View File

@@ -1,14 +1,16 @@
#pragma once
#include "entt/entity/fwd.hpp"
#include <entt/entt.hpp>
#include <flecs.h>
#include <glm/glm.hpp>
#include <set>
#include <utility>
namespace Input {
struct InputModule
{
InputModule(flecs::world& world);
};
enum class KeyCode : int
{
};
@@ -17,10 +19,18 @@ enum class Action : int
{
};
struct KeyInput
struct KeyboardInput
{
KeyCode key_code;
Action action;
flecs::entity window;
};
struct MouseButtonInput
{
KeyCode key_code;
Action action;
flecs::entity window;
};
struct MouseMotion
@@ -28,16 +38,16 @@ struct MouseMotion
glm::vec2 delta{};
};
template <typename T> class State
template <typename T> class ButtonInput
{
public:
auto pressed(T input) const -> bool { return pressed_keys.contains(input); }
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 update_state(flecs::entity window_entity);
static void clear_button_input(ButtonInput<T>& state);
// private:
// private:
void press(T input)
{
if (pressed_keys.insert(input).second) {
@@ -55,23 +65,6 @@ public:
std::set<T> pressed_keys;
std::set<T> just_pressed_keys;
std::set<T> just_released_keys;
friend class KeyListener;
friend class CursorListener;
};
// struct KeyListener
// {
// entt::registry& registry;
// void key_event(KeyInput const& key_input_event);
// };
// struct CursorListener
// {
// entt::registry& registry;
// void cursor_event(MouseMotion const& mouse_motion_event);
// };
void reset_mouse_motion(entt::registry& registry);
}; // namespace Input

View File

@@ -5,14 +5,17 @@
#include <glad/gl.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <spdlog/spdlog.h>
namespace Window {
static constexpr unsigned INIT_WINDOW_WIDTH = 1280;
static constexpr unsigned INIT_WINDOW_HEIGHT = 720;
static constexpr double MOUSE_SENSITIVITY = 0.15;
static void glfw_error_callback(int error, char const* description);
static void framebuffer_size_callback(GLFWwindow* glfw_window, int width, int height);
static void window_size_callback(GLFWwindow* glfw_window, int width, int height);
static void key_callback(GLFWwindow* glfw_window, int key, int scancode, int action, int mods);
static void mouse_cursor_callback(GLFWwindow* glfw_window, double xpos, double ypos);
@@ -21,9 +24,12 @@ WindowModule::WindowModule(flecs::world& world)
glfwInit();
world.component<Window>();
world.component<std::shared_ptr<GLFWwindow>>();
world.component<std::optional<CursorPosition>>();
world.component<LogicalSize>();
world.component<PhysicalSize>();
}
void spawn_window(flecs::world& world)
flecs::entity spawn_window(flecs::world& world)
{
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
@@ -52,17 +58,26 @@ void spawn_window(flecs::world& world)
glfwSetWindowUserPointer(glfw_window.get(), &world);
glfwSetKeyCallback(glfw_window.get(), key_callback);
glfwSetCursorPosCallback(glfw_window.get(), mouse_cursor_callback);
glfwSetWindowSizeCallback(glfw_window.get(), window_size_callback);
glfwSetFramebufferSizeCallback(glfw_window.get(), framebuffer_size_callback);
init_glad();
int width, height;
glfwGetFramebufferSize(glfw_window.get(), &width, &height);
glViewport(0, 0, width, height);
int window_width, window_height;
glfwGetWindowSize(glfw_window.get(), &window_width, &window_height);
int framebuffer_width, framebuffer_height;
glfwGetFramebufferSize(glfw_window.get(), &framebuffer_width, &framebuffer_height);
glViewport(0, 0, framebuffer_width, framebuffer_height);
flecs::entity window = world.singleton<Window>();
window.add<Input::State<Input::KeyCode>>();
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});
return window;
}
static void glfw_error_callback(int error, char const* description)
@@ -70,13 +85,22 @@ static void glfw_error_callback(int error, char const* description)
spdlog::warn("GLFW [{:d}]: {:s}\n", error, 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>();
window.set<LogicalSize>({width, height});
}
void framebuffer_size_callback(GLFWwindow* glfw_window, int width, int height)
{
// auto& window = *static_cast<WindowDeprecated*>(glfwGetWindowUserPointer(glfw_window));
// glViewport(0, 0, width, height);
auto* world = static_cast<flecs::world*>(glfwGetWindowUserPointer(glfw_window));
flecs::entity window = world->singleton<Window>();
// world->event<ResizeEvent>().emit();
// window.event_dispatcher.enqueue<ResizeEvent>();
window.set<PhysicalSize>({width, height});
glViewport(0, 0, width, height);
}
void key_callback(GLFWwindow* glfw_window,
@@ -86,77 +110,56 @@ void key_callback(GLFWwindow* glfw_window,
[[maybe_unused]] int mods)
{
auto* world = static_cast<flecs::world*>(glfwGetWindowUserPointer(glfw_window));
flecs::entity window = world->component<Window>();
flecs::entity window = world->singleton<Window>();
window.emit<Input::KeyInput>(Input::KeyInput{.key_code = static_cast<Input::KeyCode>(key),
.action = static_cast<Input::Action>(action)});
world->component<Input::KeyboardInput>().set<Input::KeyboardInput>(
{.key_code = static_cast<Input::KeyCode>(key),
.action = static_cast<Input::Action>(action),
.window = window});
}
void mouse_cursor_callback(GLFWwindow* glfw_window, double xpos, double ypos)
{
// auto* world = static_cast<flecs::world*>(glfwGetWindowUserPointer(glfw_window));
auto* world = static_cast<flecs::world*>(glfwGetWindowUserPointer(glfw_window));
flecs::entity window = world->singleton<Window>();
// glm::vec2 delta{xpos - window.last_cursor_pos.x, ypos - window.last_cursor_pos.y};
auto cursor_position = window.get_mut<std::optional<CursorPosition>>();
bool had_value = cursor_position->has_value();
// window.last_cursor_pos = {xpos, ypos};
// delta *= MOUSE_SENSITIVITY;
*cursor_position = {xpos, ypos};
// // Check if this is the first VALID mouse event after window being resized
// if (window.first_mouse_input && (delta.x >= std::numeric_limits<double>::epsilon() ||
// delta.y >= std::numeric_limits<double>::epsilon())) {
// window.first_mouse_input = false;
// return;
// }
// Prevent invalid delta events when the cursor position wasn't valid
if (!had_value)
return;
// TODO remove with flecs
// window.event_dispatcher.enqueue<Input::MouseMotion>(Input::MouseMotion{.delta = delta});
glm::vec2 delta{xpos - cursor_position->value().x, ypos - cursor_position->value().y};
delta *= MOUSE_SENSITIVITY;
world->component<Input::MouseMotion>().set<Input::MouseMotion>({delta});
}
auto WindowDeprecated::logical_dimensions() const -> glm::u32vec2
{
int width{};
int height{};
glfwGetWindowSize(glfw_window.get(), &width, &height);
return {width, height};
}
} // namespace Window
auto WindowDeprecated::physical_dimensions() const -> glm::u32vec2
{
int width{};
int height{};
glfwGetFramebufferSize(glfw_window.get(), &width, &height);
return {width, height};
}
// 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>>();
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::State<Input::KeyCode>>();
// if (key_state.just_pressed(Input::KeyCode{GLFW_KEY_LEFT_CONTROL})) {
// mouse_catched.catched = !mouse_catched.catched;
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);
// }
// }
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>>();
void WindowDeprecated::close_on_esc(entt::registry& registry) const
{
auto const& key_state = registry.ctx().get<Input::State<Input::KeyCode>>();
if (key_state.just_pressed(Input::KeyCode{GLFW_KEY_ESCAPE})) {
glfwSetWindowShouldClose(glfw_window.get(), GLFW_TRUE);
}
}
void WindowDeprecated::update_descriptor(entt::registry& registry) const
{
auto dimensions = logical_dimensions();
registry.ctx().erase<Descriptor>();
registry.ctx().emplace<Descriptor>(Descriptor{
.logical_dimensions = dimensions,
.aspect_ratio = static_cast<float>(dimensions.x) / static_cast<float>(dimensions.y)});
}
// if (key_state.just_pressed(Input::KeyCode{GLFW_KEY_ESCAPE})) {
// glfwSetWindowShouldClose(glfw_window.get(), GLFW_TRUE);
// }
// }

View File

@@ -8,39 +8,46 @@
class GLFWwindow;
namespace Window {
void glfw_init();
struct Window{};
struct Window
{};
struct CursorPosition
{
double x;
double y;
};
struct LogicalSize
{
int width;
int height;
};
struct PhysicalSize
{
int width;
int height;
};
struct WindowModule
{
WindowModule(flecs::world& world);
};
void spawn_window(flecs::world& world);
flecs::entity spawn_window(flecs::world& world);
} // namespace Window
class WindowDeprecated
{
public:
struct MouseCatched
{
bool catched = true;
};
struct Descriptor
{
glm::u32vec2 logical_dimensions;
float aspect_ratio{};
};
struct ResizeEvent
{};
[[nodiscard]] auto handle() -> GLFWwindow& { return *glfw_window; }
[[nodiscard]] auto physical_dimensions() const -> glm::u32vec2;
[[nodiscard]] auto logical_dimensions() const -> glm::u32vec2;
void update_descriptor(entt::registry& registry) const;
void mouse_catching(entt::registry& registry) const;
void close_on_esc(entt::registry& registry) const;
@@ -51,7 +58,4 @@ private:
flecs::entity window_entity;
std::shared_ptr<GLFWwindow> glfw_window;
glm::vec2 last_cursor_pos{};
bool first_mouse_input = true;
};

View File

@@ -21,5 +21,5 @@
"fx-gltf",
"flecs"
],
"builtin-baseline": "bc994510d2eb11aac7b43b03f67a7751d5bfe0e4"
"builtin-baseline": "ce613c41372b23b1f51333815feb3edd87ef8a8b"
}