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.cpp | |
| parent | 87ef308220addbe4406006ceb802a7364e6f1a05 (diff) | |
| download | meowcraft-92f63bbdbfc214849c203511bbcb1be0a4865588.tar.zst meowcraft-92f63bbdbfc214849c203511bbcb1be0a4865588.zip | |
Proper input system
Diffstat (limited to 'src/Input.cpp')
| -rw-r--r-- | src/Input.cpp | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/src/Input.cpp b/src/Input.cpp new file mode 100644 index 0000000..2362794 --- /dev/null +++ b/src/Input.cpp @@ -0,0 +1,221 @@ +#include "Input.hpp" +#include "ThreadRole.hpp" + +namespace MC { + +Bool Input::s_key_buffer[KeyCount] = { false }; +Bool Input::s_mouse_buffer[MouseCount] = { false }; +Vec2 Input::s_mouse_position = { 0, 0 }; +Input::MouseEventType Input::s_mouse_event_type = MouseEventType::None; + +void Input::register_callbacks(GFX::Window const& window) { + ASSERT_MAIN_THREAD(); + + glfwSetKeyCallback(window.get(), key_callback); + glfwSetCursorPosCallback(window.get(), cursor_position_callback); + glfwSetMouseButtonCallback(window.get(), mouse_button_callback); +} + +// I think this is the Windows default for double click... +#define DOUBLE_PRESS_DELTA_MS 500 + +void Input::update(Time::Timestamp const current_time) { + ASSERT_MAIN_THREAD(); + + std::swap(m_state, m_previous_state); + + for (auto& key : m_double_press->keys) key = false; + for (auto& mouse_button : m_double_press->mouse_buttons) mouse_button = false; + + for (USize i = 0; i < KeyCount; ++i) { + m_state->map.keys[i] = s_key_buffer[i]; + if (key_pressed(m_state, m_previous_state, TO(Key, i))) { + auto previous_release_time = m_last_key_release->keys[i]; + m_double_press->keys[i] = current_time - previous_release_time < DOUBLE_PRESS_DELTA_MS; + m_last_key_release->keys[i] = current_time; + } + } + + for (USize i = 0; i < MouseCount; ++i) { + m_state->map.mouse_buttons[i] = s_mouse_buffer[i]; + if (mouse_button_pressed(m_state, m_previous_state, TO(Mouse, i))) { + auto previous_release_time = m_last_key_release->keys[i]; + m_double_press->keys[i] = current_time - previous_release_time < DOUBLE_PRESS_DELTA_MS; + m_last_key_release->keys[i] = current_time; + } + } + + if (s_mouse_event_type == MouseEventType::First) + m_previous_state->mouse_position = s_mouse_position; + m_state->mouse_position = s_mouse_position; +} + +Bool Input::pressed(Key const key) const { + return key_pressed(m_state, m_previous_state, key); +} + +Bool Input::pressed(Mouse const button) const { + return mouse_button_pressed(m_state, m_previous_state, button); +} + +Bool Input::held(Key const key) const { + return m_state->map.keys[key_value(key)]; +} + +Bool Input::held(Mouse const button) const { + return m_state->map.mouse_buttons[mouse_button_value(button)]; +} + +Bool Input::released(Key const key) const { + return key_released(m_state, m_previous_state, key); +} + +Bool Input::released(Mouse const button) const { + return mouse_button_released(m_state, m_previous_state, button); +} + +Bool Input::double_pressed(Key const key) const { + return m_double_press->keys[key_value(key)]; +} + +Bool Input::double_pressed(Mouse const button) const { + return m_double_press->mouse_buttons[mouse_button_value(button)]; +} + +Vector<2> Input::mouse_position() const { + return m_state->mouse_position; +} + +Vector<2> Input::mouse_movement() const { + return m_state->mouse_position - m_previous_state->mouse_position; +} + +Bool Input::key_pressed( + std::unique_ptr<FrameState> const& current, std::unique_ptr<FrameState> const& previous, Key key +) { + return current->map.keys[key_value(key)] && !previous->map.keys[key_value(key)]; +} + +Bool Input::mouse_button_pressed( + std::unique_ptr<FrameState> const& current, std::unique_ptr<FrameState> const& previous, Mouse mouse +) { + return current->map.mouse_buttons[mouse_button_value(mouse)] && !previous->map.mouse_buttons[mouse_button_value(mouse)]; +} + +Bool Input::key_released( + std::unique_ptr<FrameState> const& current, std::unique_ptr<FrameState> const& previous, Key key +) { + return !current->map.keys[key_value(key)] && previous->map.keys[key_value(key)]; +} + +Bool Input::mouse_button_released( + std::unique_ptr<FrameState> const& current, std::unique_ptr<FrameState> const& previous, Mouse mouse +) { + return !current->map.mouse_buttons[mouse_button_value(mouse)] && previous->map.mouse_buttons[mouse_button_value(mouse)]; +} + +USize Input::key_value(Key key) { + return TO(USize, key); +} + +USize Input::mouse_button_value(Mouse button) { + return TO(USize, button); +} + +Key Input::from_glfw_key(I32 const key) { + switch (key) { + case GLFW_KEY_A: return Key::A; + case GLFW_KEY_B: return Key::B; + case GLFW_KEY_C: return Key::C; + case GLFW_KEY_D: return Key::D; + case GLFW_KEY_E: return Key::E; + case GLFW_KEY_F: return Key::F; + case GLFW_KEY_G: return Key::G; + case GLFW_KEY_H: return Key::H; + case GLFW_KEY_I: return Key::I; + case GLFW_KEY_J: return Key::J; + case GLFW_KEY_K: return Key::K; + case GLFW_KEY_L: return Key::L; + case GLFW_KEY_M: return Key::M; + case GLFW_KEY_N: return Key::N; + case GLFW_KEY_O: return Key::O; + case GLFW_KEY_P: return Key::P; + case GLFW_KEY_Q: return Key::Q; + case GLFW_KEY_R: return Key::R; + case GLFW_KEY_S: return Key::S; + case GLFW_KEY_T: return Key::T; + case GLFW_KEY_U: return Key::U; + case GLFW_KEY_V: return Key::V; + case GLFW_KEY_W: return Key::W; + case GLFW_KEY_X: return Key::X; + case GLFW_KEY_Y: return Key::Y; + case GLFW_KEY_Z: return Key::Z; + case GLFW_KEY_0: return Key::Zero; + case GLFW_KEY_1: return Key::One; + case GLFW_KEY_2: return Key::Two; + case GLFW_KEY_3: return Key::Three; + case GLFW_KEY_4: return Key::Four; + case GLFW_KEY_5: return Key::Five; + case GLFW_KEY_6: return Key::Six; + case GLFW_KEY_7: return Key::Seven; + case GLFW_KEY_8: return Key::Eight; + case GLFW_KEY_9: return Key::Nine; + case GLFW_KEY_ESCAPE: return Key::Escape; + case GLFW_KEY_ENTER: return Key::Enter; + case GLFW_KEY_TAB: return Key::Tab; + case GLFW_KEY_BACKSPACE: return Key::Backspace; + case GLFW_KEY_INSERT: return Key::Insert; + case GLFW_KEY_DELETE: return Key::Delete; + case GLFW_KEY_RIGHT: return Key::Right; + case GLFW_KEY_LEFT: return Key::Left; + case GLFW_KEY_DOWN: return Key::Down; + case GLFW_KEY_UP: return Key::Up; + case GLFW_KEY_LEFT_SHIFT: return Key::LeftShift; + case GLFW_KEY_RIGHT_SHIFT: return Key::RightShift; + case GLFW_KEY_LEFT_CONTROL: return Key::LeftControl; + case GLFW_KEY_RIGHT_CONTROL: return Key::RightControl; + case GLFW_KEY_LEFT_ALT: return Key::LeftAlt; + case GLFW_KEY_RIGHT_ALT: return Key::RightAlt; + case GLFW_KEY_SPACE: return Key::Space; + case GLFW_KEY_F1: return Key::F1; + case GLFW_KEY_F2: return Key::F2; + case GLFW_KEY_F3: return Key::F3; + case GLFW_KEY_F4: return Key::F4; + case GLFW_KEY_F5: return Key::F5; + case GLFW_KEY_F6: return Key::F6; + case GLFW_KEY_F7: return Key::F7; + case GLFW_KEY_F8: return Key::F8; + case GLFW_KEY_F9: return Key::F9; + case GLFW_KEY_F10: return Key::F10; + case GLFW_KEY_F11: return Key::F11; + case GLFW_KEY_F12: return Key::F12; + default: UNREACHABLE("Unknown key."); return TO(Key, 0); + } +} + +Mouse Input::from_glfw_mouse(I32 const button) { + switch (button) { + case GLFW_MOUSE_BUTTON_LEFT: return Mouse::Left; + case GLFW_MOUSE_BUTTON_RIGHT: return Mouse::Right; + case GLFW_MOUSE_BUTTON_MIDDLE: return Mouse::Middle; + default: UNREACHABLE("Unknown mouse button."); return TO(Mouse, 0); + } +} + +void Input::key_callback(GLFWwindow* _window, I32 const key, I32 _scancode, I32 const action, I32 _mods) { + if (action == GLFW_PRESS) s_key_buffer[key_value(from_glfw_key(key))] = true; + else if (action == GLFW_RELEASE) s_key_buffer[key_value(from_glfw_key(key))] = false; +} + +void Input::cursor_position_callback(GLFWwindow* _window, F64 x, F64 y) { + if (s_mouse_event_type == MouseEventType::None) s_mouse_event_type = MouseEventType::First; + else if (s_mouse_event_type == MouseEventType::First) s_mouse_event_type = MouseEventType::Subsequent; + s_mouse_position = { x, y }; +} + +void Input::mouse_button_callback(GLFWwindow* _window, I32 const button, I32 const action, I32 _mods) { + if (action == GLFW_PRESS) s_mouse_buffer[mouse_button_value(from_glfw_mouse(button))] = true; + else if (action == GLFW_RELEASE) s_mouse_buffer[mouse_button_value(from_glfw_mouse(button))] = false; +} + +} |
