feat: reimplement input system
This commit is contained in:
parent
21e9933a42
commit
d69315c6aa
8 changed files with 432 additions and 283 deletions
|
@ -1,2 +1,4 @@
|
|||
add_library_module(input input.cpp)
|
||||
target_link_libraries(input PUBLIC surface math imgui::imgui logger)
|
||||
add_library_module(input system.cpp)
|
||||
target_link_libraries(input PUBLIC surface math logger)
|
||||
|
||||
add_test_module(input system.test.cpp)
|
||||
|
|
|
@ -1,159 +0,0 @@
|
|||
#include <imgui.h>
|
||||
#include <input/input.hpp>
|
||||
#include <logger/logger.hpp>
|
||||
|
||||
namespace lt {
|
||||
|
||||
Input::Input(): m_mouse_position {}, m_mouse_delta {}
|
||||
|
||||
{
|
||||
restart_input_state();
|
||||
}
|
||||
|
||||
void Input::receive_user_interface_events_impl(bool receive, bool toggle /* = false */)
|
||||
{
|
||||
m_user_interface_events = toggle ? !m_user_interface_events : receive;
|
||||
}
|
||||
|
||||
void Input::receieve_game_events_impl(bool receive, bool toggle /*= false*/)
|
||||
{
|
||||
auto prev = m_game_events;
|
||||
m_game_events = toggle ? !m_user_interface_events : receive;
|
||||
|
||||
if (m_game_events != prev)
|
||||
{
|
||||
restart_input_state();
|
||||
}
|
||||
}
|
||||
|
||||
void Input::restart_input_state()
|
||||
{
|
||||
m_keyboad_keys.fill(false);
|
||||
m_mouse_buttons.fill(false);
|
||||
|
||||
m_mouse_position = math::vec2(0.0f);
|
||||
m_mouse_delta = math::vec2(0.0f);
|
||||
m_mouse_wheel_delta = 0.0f;
|
||||
}
|
||||
|
||||
void Input::on_event(const Event &inputEvent)
|
||||
{
|
||||
auto &io = ImGui::GetIO();
|
||||
switch (inputEvent.get_event_type())
|
||||
{
|
||||
//** MOUSE_EVENTS **//
|
||||
case EventType::MouseMoved:
|
||||
{
|
||||
const auto &event = dynamic_cast<const MouseMovedEvent &>(inputEvent);
|
||||
|
||||
if (m_game_events)
|
||||
{
|
||||
m_mouse_delta = event.get_position() - m_mouse_position;
|
||||
m_mouse_position = event.get_position();
|
||||
}
|
||||
|
||||
if (m_user_interface_events)
|
||||
{
|
||||
io.MousePos = ImVec2(event.get_x(), event.get_y());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
case EventType::ButtonPressed:
|
||||
{
|
||||
const auto &event = dynamic_cast<const ButtonPressedEvent &>(inputEvent);
|
||||
|
||||
if (m_game_events)
|
||||
{
|
||||
m_mouse_buttons[event.get_button()] = true;
|
||||
}
|
||||
|
||||
if (m_user_interface_events)
|
||||
{
|
||||
io.MouseDown[event.get_button()] = true;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
case EventType::ButtonReleased:
|
||||
{
|
||||
const auto &event = dynamic_cast<const ButtonReleasedEvent &>(inputEvent);
|
||||
|
||||
if (m_game_events)
|
||||
{
|
||||
m_mouse_buttons[event.get_button()] = false;
|
||||
}
|
||||
|
||||
if (m_user_interface_events)
|
||||
{
|
||||
io.MouseDown[event.get_button()] = false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
case EventType::WheelScrolled:
|
||||
{
|
||||
const auto &event = dynamic_cast<const WheelScrolledEvent &>(inputEvent);
|
||||
|
||||
if (m_game_events)
|
||||
{
|
||||
m_mouse_wheel_delta = event.get_offset();
|
||||
}
|
||||
|
||||
if (m_user_interface_events)
|
||||
{
|
||||
io.MouseWheel = event.get_offset();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
//** KEYBOARD_EVENTS **//
|
||||
case EventType::KeyPressed:
|
||||
{
|
||||
const auto &event = dynamic_cast<const KeyPressedEvent &>(inputEvent);
|
||||
|
||||
if (m_game_events)
|
||||
{
|
||||
m_keyboad_keys[event.get_key()] = true;
|
||||
}
|
||||
|
||||
if (m_user_interface_events)
|
||||
{
|
||||
// io.AddKeyEvent(event.get_key(), true);
|
||||
// if (event.get_key() == Key::BackSpace)
|
||||
// io.AddInputCharacter(Key::BackSpace);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
case EventType::KeyReleased:
|
||||
{
|
||||
const auto &event = dynamic_cast<const KeyReleasedEvent &>(inputEvent);
|
||||
|
||||
if (m_game_events)
|
||||
{
|
||||
m_keyboad_keys[event.get_key()] = false;
|
||||
}
|
||||
|
||||
if (m_user_interface_events)
|
||||
{
|
||||
// io.AddKeyEvent(event.get_key(), false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
case EventType::SetChar:
|
||||
{
|
||||
if (m_user_interface_events)
|
||||
{
|
||||
const auto &event = dynamic_cast<const SetCharEvent &>(inputEvent);
|
||||
io.AddInputCharacter(event.get_character());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
default: log_trc("Dropped event");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace lt
|
|
@ -1,5 +1,138 @@
|
|||
#include <input/components.hpp>
|
||||
#include <input/system.hpp>
|
||||
|
||||
namespace lt::input {
|
||||
|
||||
template<class... Ts>
|
||||
struct overloads: Ts...
|
||||
{
|
||||
using Ts::operator()...;
|
||||
};
|
||||
|
||||
System::System(Ref<ecs::Registry> registry): m_registry(std::move(registry))
|
||||
{
|
||||
ensure(m_registry, "Failed to initialize input system: null registry");
|
||||
}
|
||||
|
||||
auto System::tick() -> bool
|
||||
{
|
||||
m_registry->view<surface::SurfaceComponent>().each([&](const entt::entity,
|
||||
surface::SurfaceComponent &surface) {
|
||||
for (const auto &event : surface.peek_events())
|
||||
{
|
||||
handle_event(event);
|
||||
}
|
||||
});
|
||||
|
||||
m_registry->view<InputComponent>().each([&](const entt::entity, InputComponent &input) {
|
||||
// TODO(Light): instead of iterating over all actions each frame,
|
||||
// make a list of "dirty" actions to reset
|
||||
// and a surface_input->input_action mapping to get to action through input
|
||||
// instead of brute-force checking all of them.
|
||||
for (auto &action : input.m_actions)
|
||||
{
|
||||
auto code = action.trigger.mapped_keycode;
|
||||
if (code < m_keys.size() && m_keys[code])
|
||||
{
|
||||
if (action.state == InputAction::State::triggered)
|
||||
{
|
||||
action.state = InputAction::State::active;
|
||||
}
|
||||
else if (action.state == InputAction::State::inactive)
|
||||
{
|
||||
action.state = InputAction::State::triggered;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
action.state = InputAction::State::inactive;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void System::on_register()
|
||||
{
|
||||
}
|
||||
|
||||
void System::on_unregister()
|
||||
{
|
||||
}
|
||||
|
||||
void System::handle_event(const surface::SurfaceComponent::Event &event)
|
||||
{
|
||||
const auto visitor = overloads {
|
||||
[this](const surface::ClosedEvent &) { on_surface_lost_focus(); },
|
||||
[this](const surface::LostFocusEvent &) { on_surface_lost_focus(); },
|
||||
[this](const surface::KeyPressedEvent &event) { on_key_press(event); },
|
||||
[this](const surface::KeyReleasedEvent &event) { on_key_release(event); },
|
||||
[this](const surface::MouseMovedEvent &event) { on_pointer_move(event); },
|
||||
[this](const surface::ButtonPressedEvent &event) { on_button_press(event); },
|
||||
[this](const surface::ButtonReleasedEvent &event) { on_button_release(event); },
|
||||
[this](auto) {},
|
||||
};
|
||||
|
||||
std::visit(visitor, event);
|
||||
}
|
||||
|
||||
void System::on_surface_lost_focus()
|
||||
{
|
||||
for (auto &key : m_keys)
|
||||
{
|
||||
key = false;
|
||||
}
|
||||
|
||||
for (auto &button : m_buttons)
|
||||
{
|
||||
button = false;
|
||||
}
|
||||
}
|
||||
|
||||
void System::on_key_press(const lt::surface::KeyPressedEvent &event)
|
||||
{
|
||||
if (event.get_key() > m_keys.size())
|
||||
{
|
||||
log_dbg(
|
||||
"Key code larger than key container size, implement platform-dependant "
|
||||
"key-code-mapping!"
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_keys[event.get_key()] = true;
|
||||
}
|
||||
|
||||
void System::on_key_release(const lt::surface::KeyReleasedEvent &event)
|
||||
{
|
||||
if (event.get_key() > m_keys.size())
|
||||
{
|
||||
log_dbg(
|
||||
"Key code larger than key container size, implement platform-dependant "
|
||||
"key-code-mapping!"
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_keys[event.get_key()] = false;
|
||||
}
|
||||
|
||||
void System::on_pointer_move(const lt::surface::MouseMovedEvent &event)
|
||||
{
|
||||
m_pointer_position = event.get_position();
|
||||
}
|
||||
|
||||
void System::on_button_press(const lt::surface::ButtonPressedEvent &event)
|
||||
{
|
||||
m_buttons[event.get_button()] = true;
|
||||
}
|
||||
|
||||
void System::on_button_release(const lt::surface::ButtonReleasedEvent &event)
|
||||
{
|
||||
m_buttons[event.get_button()] = false;
|
||||
}
|
||||
|
||||
} // namespace lt::input
|
||||
|
|
169
modules/input/private/system.test.cpp
Normal file
169
modules/input/private/system.test.cpp
Normal file
|
@ -0,0 +1,169 @@
|
|||
#include <ecs/entity.hpp>
|
||||
#include <input/components.hpp>
|
||||
#include <input/system.hpp>
|
||||
#include <test/test.hpp>
|
||||
|
||||
// NOLINTBEGIN
|
||||
using namespace lt;
|
||||
using input::InputComponent;
|
||||
using input::System;
|
||||
using std::ignore;
|
||||
using test::Case;
|
||||
using test::expect_eq;
|
||||
using test::expect_false;
|
||||
using test::expect_ne;
|
||||
using test::expect_not_nullptr;
|
||||
using test::expect_throw;
|
||||
using test::Suite;
|
||||
// NOLINTEND
|
||||
|
||||
class Fixture
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] auto registry() -> Ref<ecs::Registry>
|
||||
{
|
||||
return m_registry;
|
||||
}
|
||||
|
||||
auto add_input_component() -> ecs::Entity
|
||||
{
|
||||
auto entity = m_registry->create_entity("");
|
||||
entity.add_component<InputComponent>();
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
auto add_surface_component() -> ecs::Entity
|
||||
{
|
||||
auto entity = m_registry->create_entity("");
|
||||
entity.add_component<surface::SurfaceComponent>(surface::SurfaceComponent::CreateInfo {});
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
private:
|
||||
Ref<ecs::Registry> m_registry = create_ref<ecs::Registry>();
|
||||
};
|
||||
|
||||
Suite raii = [] {
|
||||
Case { "happy path won't throw" } = [&] {
|
||||
System { Fixture {}.registry() };
|
||||
};
|
||||
|
||||
Case { "many won't freeze/throw" } = [&] {
|
||||
auto fixture = Fixture {};
|
||||
for (auto idx : std::views::iota(0, 10'000))
|
||||
{
|
||||
ignore = System { fixture.registry() };
|
||||
}
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
expect_throw([] { ignore = System { {} }; });
|
||||
};
|
||||
};
|
||||
|
||||
Suite system_events = [] {
|
||||
Case { "on_register won't throw" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
|
||||
system.on_register();
|
||||
expect_eq(fixture.registry()->view<InputComponent>().size(), 0);
|
||||
};
|
||||
|
||||
Case { "on_unregister won't throw" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
|
||||
system.on_register();
|
||||
system.on_unregister();
|
||||
expect_eq(fixture.registry()->view<InputComponent>().size(), 0);
|
||||
};
|
||||
};
|
||||
|
||||
Suite registry_events = [] {
|
||||
Case { "on_construct<InputComnent>" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
|
||||
const auto &entity = fixture.add_input_component();
|
||||
expect_eq(fixture.registry()->view<InputComponent>().size(), 1);
|
||||
};
|
||||
|
||||
Case { "on_destrroy<InputComponent>" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = create_scope<System>(fixture.registry());
|
||||
|
||||
auto entity_a = fixture.add_input_component();
|
||||
auto entity_b = fixture.add_input_component();
|
||||
expect_eq(fixture.registry()->view<InputComponent>().size(), 2);
|
||||
|
||||
entity_a.remove_component<InputComponent>();
|
||||
expect_eq(fixture.registry()->view<InputComponent>().size(), 1);
|
||||
|
||||
system.reset();
|
||||
expect_eq(fixture.registry()->view<InputComponent>().size(), 1);
|
||||
|
||||
entity_b.remove_component<InputComponent>();
|
||||
expect_eq(fixture.registry()->view<InputComponent>().size(), 0);
|
||||
};
|
||||
};
|
||||
|
||||
Suite tick = [] {
|
||||
Case { "Empty tick won't throw" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
|
||||
expect_false(system.tick());
|
||||
};
|
||||
|
||||
Case { "Tick triggers input action" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
|
||||
auto &surface = fixture.add_surface_component().get_component<surface::SurfaceComponent>();
|
||||
auto &input = fixture.add_input_component().get_component<InputComponent>();
|
||||
|
||||
auto action_key = input.add_action(
|
||||
{
|
||||
.name { "test" },
|
||||
.trigger = { .mapped_keycode = 69 },
|
||||
}
|
||||
);
|
||||
|
||||
expect_eq(input.get_action(action_key).state, input::InputAction::State::inactive);
|
||||
system.tick();
|
||||
expect_eq(input.get_action(action_key).state, input::InputAction::State::inactive);
|
||||
|
||||
surface.push_event(surface::KeyPressedEvent(69));
|
||||
system.tick();
|
||||
expect_eq(input.get_action(action_key).state, input::InputAction::State::triggered);
|
||||
|
||||
system.tick();
|
||||
expect_eq(input.get_action(action_key).state, input::InputAction::State::inactive);
|
||||
|
||||
system.tick();
|
||||
system.tick();
|
||||
system.tick();
|
||||
expect_eq(input.get_action(action_key).state, input::InputAction::State::inactive);
|
||||
|
||||
surface.push_event(surface::KeyPressedEvent(69));
|
||||
system.tick();
|
||||
};
|
||||
|
||||
Case { "Tick triggers" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
|
||||
auto &surface = fixture.add_surface_component().get_component<surface::SurfaceComponent>();
|
||||
auto &input = fixture.add_input_component().get_component<InputComponent>();
|
||||
|
||||
auto action_key = input.add_action(
|
||||
{
|
||||
.name { "test" },
|
||||
.trigger = { .mapped_keycode = 69 },
|
||||
}
|
||||
);
|
||||
};
|
||||
};
|
57
modules/input/public/components.hpp
Normal file
57
modules/input/public/components.hpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace lt::input {
|
||||
|
||||
struct Trigger
|
||||
{
|
||||
uint32_t mapped_keycode;
|
||||
};
|
||||
|
||||
struct InputAction
|
||||
{
|
||||
using Key = size_t;
|
||||
|
||||
enum class State : uint8_t
|
||||
{
|
||||
inactive,
|
||||
active,
|
||||
triggered,
|
||||
cancelled,
|
||||
};
|
||||
|
||||
std::string name;
|
||||
|
||||
State state;
|
||||
|
||||
Trigger trigger;
|
||||
};
|
||||
|
||||
class InputComponent
|
||||
{
|
||||
public:
|
||||
InputComponent() = default;
|
||||
|
||||
auto add_action(InputAction action) -> size_t
|
||||
{
|
||||
m_actions.emplace_back(std::move(action));
|
||||
return m_actions.size() - 1;
|
||||
}
|
||||
|
||||
auto get_action(auto idx) -> const InputAction &
|
||||
{
|
||||
return m_actions[idx];
|
||||
}
|
||||
|
||||
private:
|
||||
friend class System;
|
||||
|
||||
void push_event()
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<InputAction> m_actions;
|
||||
};
|
||||
|
||||
} // namespace lt::input
|
44
modules/input/public/events.hpp
Normal file
44
modules/input/public/events.hpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
#pragma once
|
||||
|
||||
#include <math/vec2.hpp>
|
||||
|
||||
namespace lt::input {
|
||||
|
||||
class AnalogEvent
|
||||
{
|
||||
public:
|
||||
AnalogEvent(uint32_t input_code, math::uvec2 pointer_position)
|
||||
: m_input_code(input_code)
|
||||
, m_pointer_position(pointer_position)
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_code() const -> uint32_t
|
||||
{
|
||||
return m_input_code;
|
||||
};
|
||||
|
||||
[[nodiscard]] auto get_pointer_position() const -> math::uvec2
|
||||
{
|
||||
return m_pointer_position;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto to_string() const -> std::string
|
||||
{
|
||||
auto stream = std::stringstream {};
|
||||
const auto &[x, y] = m_pointer_position;
|
||||
stream << "input::AnalogEvent: " << m_input_code << " @ " << x << ", " << y;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t m_input_code;
|
||||
|
||||
math::uvec2 m_pointer_position;
|
||||
};
|
||||
|
||||
class AxisEvent
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace lt::input
|
|
@ -1,80 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <math/vec2.hpp>
|
||||
|
||||
namespace lt {
|
||||
|
||||
class Event;
|
||||
|
||||
class Input
|
||||
{
|
||||
public:
|
||||
static auto instance() -> Input &
|
||||
{
|
||||
static auto instance = Input {};
|
||||
return instance;
|
||||
}
|
||||
|
||||
static void receive_user_interface_events(bool receive, bool toggle = false)
|
||||
{
|
||||
instance().receive_user_interface_events_impl(receive, toggle);
|
||||
}
|
||||
|
||||
static void receive_game_events(bool receive, bool toggle = false)
|
||||
{
|
||||
instance().receieve_game_events_impl(receive, toggle);
|
||||
}
|
||||
|
||||
static auto get_keyboard_key(int code) -> bool
|
||||
{
|
||||
return instance().m_keyboad_keys[code];
|
||||
}
|
||||
|
||||
static auto get_mouse_button(int code) -> bool
|
||||
{
|
||||
return instance().m_mouse_buttons[code];
|
||||
}
|
||||
|
||||
static auto get_mouse_position(int /*code*/) -> const math::vec2 &
|
||||
{
|
||||
return instance().m_mouse_position;
|
||||
}
|
||||
|
||||
void on_event(const Event &inputEvent);
|
||||
|
||||
[[nodiscard]] auto is_receiving_input_events() const -> bool
|
||||
{
|
||||
return m_user_interface_events;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_receiving_game_events() const -> bool
|
||||
{
|
||||
return m_game_events;
|
||||
}
|
||||
|
||||
private:
|
||||
Input();
|
||||
|
||||
void receive_user_interface_events_impl(bool receive, bool toggle = false);
|
||||
|
||||
void receieve_game_events_impl(bool receive, bool toggle = false);
|
||||
|
||||
void restart_input_state();
|
||||
|
||||
std::array<bool, 348> m_keyboad_keys {};
|
||||
|
||||
std::array<bool, 8> m_mouse_buttons {};
|
||||
|
||||
math::vec2 m_mouse_position;
|
||||
|
||||
math::vec2 m_mouse_delta;
|
||||
|
||||
float m_mouse_wheel_delta {};
|
||||
|
||||
bool m_user_interface_events { true };
|
||||
|
||||
bool m_game_events { true };
|
||||
};
|
||||
|
||||
} // namespace lt
|
|
@ -1,63 +1,46 @@
|
|||
#pragma once
|
||||
|
||||
#include <surface/system.hpp>
|
||||
#include <app/system.hpp>
|
||||
#include <ecs/scene.hpp>
|
||||
#include <surface/components.hpp>
|
||||
#include <surface/events/keyboard.hpp>
|
||||
#include <surface/events/mouse.hpp>
|
||||
|
||||
namespace lt::input {
|
||||
|
||||
template<class... Ts>
|
||||
struct overloads: Ts...
|
||||
{
|
||||
using Ts::operator()...;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @note If this system is attached, it will always consume the input events f rom surface.
|
||||
* Therefore if you want any input detection mechanism, callbacks should be setup with this
|
||||
* system and not directly with surface.
|
||||
*/
|
||||
class System
|
||||
class System: public app::ISystem
|
||||
{
|
||||
public:
|
||||
System(lt::surface::System &surface_system)
|
||||
{
|
||||
surface_system.add_event_listener([this](auto &&event) {
|
||||
return handle_event(std::forward<decltype(event)>(event));
|
||||
});
|
||||
};
|
||||
System(Ref<ecs::Registry> registry);
|
||||
|
||||
auto tick() -> bool override;
|
||||
|
||||
void on_register() override;
|
||||
|
||||
void on_unregister() override;
|
||||
|
||||
private:
|
||||
auto handle_event(const lt::surface::System::Event &event) -> bool
|
||||
{
|
||||
const auto visitor = overloads {
|
||||
[this](const lt::surface::KeyPressedEvent &event) {
|
||||
m_keys[event.get_key()] = true;
|
||||
return true;
|
||||
},
|
||||
void handle_event(const surface::SurfaceComponent::Event &event);
|
||||
|
||||
[](const lt::surface::KeyRepeatEvent &) { return false; },
|
||||
void on_surface_lost_focus();
|
||||
|
||||
[](const lt::surface::KeyReleasedEvent &) { return false; },
|
||||
void on_key_press(const lt::surface::KeyPressedEvent &event);
|
||||
|
||||
[](const lt::surface::KeySetCharEvent &) { return false; },
|
||||
void on_key_release(const lt::surface::KeyReleasedEvent &event);
|
||||
|
||||
[](const lt::surface::MouseMovedEvent &) { return false; },
|
||||
void on_pointer_move(const lt::surface::MouseMovedEvent &event);
|
||||
|
||||
[](const lt::surface::WheelScrolledEvent &) { return false; },
|
||||
void on_button_press(const lt::surface::ButtonPressedEvent &event);
|
||||
|
||||
[](const lt::surface::ButtonPressedEvent &) { return false; },
|
||||
void on_button_release(const lt::surface::ButtonReleasedEvent &event);
|
||||
|
||||
[](const lt::surface::ButtonReleasedEvent &) { return false; },
|
||||
|
||||
[](const auto &) { return false; },
|
||||
};
|
||||
|
||||
return std::visit(visitor, event);
|
||||
}
|
||||
|
||||
void setup_callbacks(GLFWwindow *handle);
|
||||
Ref<ecs::Registry> m_registry;
|
||||
|
||||
std::array<bool, 512> m_keys {};
|
||||
|
||||
std::array<bool, 512> m_buttons {};
|
||||
|
||||
math::vec2 m_pointer_position;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue