diff options
| author | Mel <einebeere@gmail.com> | 2024-02-15 11:33:11 +0100 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2024-02-15 11:34:28 +0100 |
| commit | 92f63bbdbfc214849c203511bbcb1be0a4865588 (patch) | |
| tree | d82e1b31e583b5cc9538f61cad696dab5dbd84dc /src/Input.hpp | |
| parent | 87ef308220addbe4406006ceb802a7364e6f1a05 (diff) | |
| download | meowcraft-92f63bbdbfc214849c203511bbcb1be0a4865588.tar.zst meowcraft-92f63bbdbfc214849c203511bbcb1be0a4865588.zip | |
Proper input system
Diffstat (limited to 'src/Input.hpp')
| -rw-r--r-- | src/Input.hpp | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/src/Input.hpp b/src/Input.hpp new file mode 100644 index 0000000..683ee55 --- /dev/null +++ b/src/Input.hpp @@ -0,0 +1,116 @@ +#pragma once + +#include "Time.hpp" +#include "Common/Casts.hpp" +#include "Common/Sizes.hpp" +#include "Common/Pure.hpp" +#include "GFX/Window.hpp" +#include "Math/Vector.hpp" + +namespace MC { + +// TODO: Add some more keys. +// TODO: I think some of these keys are "modifiers" under GLFW, and should be handled differently. +enum class Key { + A, B, C, D, E, F, G, H, I, J, K, L, M, + N, O, P, Q, R, S, T, U, V, W, X, Y, Z, + Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine, + Escape, Enter, Tab, Backspace, Insert, Delete, Right, Left, Down, Up, + LeftShift, RightShift, LeftControl, RightControl, LeftAlt, RightAlt, + Space, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, +}; + +constexpr USize KeyCount = 65; +static_assert(KeyCount == TO(USize, Key::F12) + 1, "Key count mismatch."); + +enum class Mouse { + Left, Right, Middle, +}; + +constexpr USize MouseCount = 3; +static_assert(MouseCount == TO(USize, Mouse::Middle) + 1, "Mouse count mismatch."); + +// The simple input system. +// All methods are thread safe, except the initial registration of the input callbacks +// and the state update. Both must be called from the main thread. +class Input { +public: + explicit Input() = default; + + // Registers the input callbacks for the given window. + // This function must be called from the main thread. + static void register_callbacks(GFX::Window const& window); + + // Updates the input state from the callback buffers. + // This function must be called from the main thread. + void update(Time::Timestamp current_time); + + // Returns true if the key was pressed during the last frame. + PURE Bool pressed(Key key) const; + // Returns true if the mouse button was pressed during the last frame. + PURE Bool pressed(Mouse button) const; + + // Returns true if the key is currently held down. + PURE Bool held(Key key) const; + // Returns true if the mouse button is currently held down. + PURE Bool held(Mouse button) const; + + // Returns true if the key was released during the last frame. + PURE Bool released(Key key) const; + // Returns true if the mouse button was released during the last frame. + PURE Bool released(Mouse button) const; + + // Returns true if the key was double pressed during the last frame. + // A double press is defined as two presses within a certain time frame. + PURE Bool double_pressed(Key key) const; + // Returns true if the mouse button was double pressed during the last frame. + // A double press is defined as two presses within a certain time frame. + PURE Bool double_pressed(Mouse button) const; + + // Returns the position of the mouse cursor in the window. + PURE Vector<2> mouse_position() const; + + // Returns the change in the position of the mouse cursor since the last frame. + PURE Vector<2> mouse_movement() const; + +private: + template <typename T> + struct ButtonMap { + T keys[KeyCount] = { 0 }; + T mouse_buttons[MouseCount] = { 0 }; + }; + + struct FrameState { + ButtonMap<Bool> map; + Vec2 mouse_position = { 0, 0 }; + }; + + std::unique_ptr<FrameState> m_state = std::make_unique<FrameState>(); + std::unique_ptr<FrameState> m_previous_state = std::make_unique<FrameState>(); + + std::unique_ptr<ButtonMap<Time::Timestamp>> m_last_key_release = std::make_unique<ButtonMap<Time::Timestamp>>(); + std::unique_ptr<ButtonMap<Bool>> m_double_press = std::make_unique<ButtonMap<Bool>>(); + + static Bool key_pressed(std::unique_ptr<FrameState> const& current, std::unique_ptr<FrameState> const& previous, Key key); + static Bool mouse_button_pressed(std::unique_ptr<FrameState> const& current, std::unique_ptr<FrameState> const& previous, Mouse mouse); + static Bool key_released(std::unique_ptr<FrameState> const& current, std::unique_ptr<FrameState> const& previous, Key key); + static Bool mouse_button_released(std::unique_ptr<FrameState> const& current, std::unique_ptr<FrameState> const& previous, Mouse mouse); + + static Bool s_key_buffer[KeyCount]; + static Bool s_mouse_buffer[MouseCount]; + static Vec2 s_mouse_position; + enum class MouseEventType { None, First, Subsequent }; + static MouseEventType s_mouse_event_type; + + static USize key_value(Key key); + static USize mouse_button_value(Mouse button); + + static Key from_glfw_key(I32 key); + static Mouse from_glfw_mouse(I32 button); + + static void key_callback(GLFWwindow* _window, I32 key, I32 _scancode, I32 action, I32 _mods); + static void cursor_position_callback(GLFWwindow* _window, F64 x, F64 y); + static void mouse_button_callback(GLFWwindow* _window, I32 button, I32 action, I32 _mods); +}; + +} |
