Fx2D
A C++20 2D rigid-body physics engine
Loading...
Searching...
No Matches
Input.h
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <cstddef>
5#include <cstdint>
6
7#include "Fx2D/Math.h"
8
9// Renderer-agnostic input state, so headless and windowed builds share one interface.
10// A renderer fills it each frame; headless callers inject through the producer API.
11
12// clang-format off
13enum class FxKey : uint8_t {
14 Unknown = 0,
15 A, B, C, D, E, F, G, H, I, J, K, L, M,
16 N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
18 Left, Right, Up, Down,
21 F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
22 Count
23};
24// clang-format on
25
26enum class FxMouseButton : uint8_t { Left = 0, Right, Middle, Count };
27
28class FxInput {
29 public:
30 static constexpr size_t kKeyCount = static_cast<size_t>(FxKey::Count);
31 static constexpr size_t kButtonCount = static_cast<size_t>(FxMouseButton::Count);
32
33 // ---------------------------------------------------------------- consumer API
34
35 // Held down right now; what continuous control wants.
36 bool key_down(FxKey key) const { return m_keys[index(key)]; }
37 // Went down since the last frame. Edges last a whole frame, which may span several
38 // physics steps, so key_down() is safer for anything that must not repeat.
39 bool key_pressed(FxKey key) const { return m_keys[index(key)] && !m_prev_keys[index(key)]; }
40 bool key_released(FxKey key) const { return !m_keys[index(key)] && m_prev_keys[index(key)]; }
41
42 bool mouse_down(FxMouseButton button) const { return m_buttons[index(button)]; }
43 bool mouse_pressed(FxMouseButton button) const {
44 return m_buttons[index(button)] && !m_prev_buttons[index(button)];
45 }
46 bool mouse_released(FxMouseButton button) const {
47 return !m_buttons[index(button)] && m_prev_buttons[index(button)];
48 }
49
50 // Cursor in scene units, the same frame entity poses live in.
51 const FxVec2f& mouse_position() const { return m_mouse_world; }
52 // Cursor in pixels, origin at the top-left of the window.
53 const FxVec2f& mouse_screen_position() const { return m_mouse_screen; }
54 // World-unit movement since the previous frame.
55 FxVec2f mouse_delta() const { return m_mouse_world - m_prev_mouse_world; }
56 // Scroll wheel movement this frame; positive is away from the user.
57 float wheel_delta() const { return m_wheel_delta; }
58
59 // False until something feeds this, distinguishing "no key held" from "no keyboard".
60 bool available() const { return m_available; }
61
62 // ---------------------------------------------------------------- producer API
63
64 // Rolls current state into previous so edges describe the frame about to be set.
65 // Call once per frame, before the set_* calls.
66 void begin_frame() {
67 m_prev_keys = m_keys;
68 m_prev_buttons = m_buttons;
69 m_prev_mouse_world = m_mouse_world;
70 m_wheel_delta = 0.0f;
71 m_available = true;
72 }
73
74 void set_key(FxKey key, bool down) { m_keys[index(key)] = down; }
75 void set_mouse_button(FxMouseButton button, bool down) { m_buttons[index(button)] = down; }
76 void set_mouse_position(const FxVec2f& world, const FxVec2f& screen) {
77 m_mouse_world = world;
78 m_mouse_screen = screen;
79 }
80 void set_wheel_delta(float delta) { m_wheel_delta = delta; }
81
82 // Drops held keys and buttons but stays available; for when the UI takes focus.
83 void release_all() {
84 m_keys.fill(false);
85 m_buttons.fill(false);
86 }
87
88 // Full reset, including availability.
89 void clear() {
90 m_keys.fill(false);
91 m_prev_keys.fill(false);
92 m_buttons.fill(false);
93 m_prev_buttons.fill(false);
94 m_mouse_world = {0.0f, 0.0f};
95 m_prev_mouse_world = {0.0f, 0.0f};
96 m_mouse_screen = {0.0f, 0.0f};
97 m_wheel_delta = 0.0f;
98 m_available = false;
99 }
100
101 private:
102 static size_t index(FxKey key) {
103 const size_t i = static_cast<size_t>(key);
104 return i < kKeyCount ? i : 0; // out-of-range folds onto Unknown, never out of bounds
105 }
106 static size_t index(FxMouseButton button) {
107 const size_t i = static_cast<size_t>(button);
108 return i < kButtonCount ? i : 0;
109 }
110
111 std::array<bool, kKeyCount> m_keys{};
112 std::array<bool, kKeyCount> m_prev_keys{};
113 std::array<bool, kButtonCount> m_buttons{};
114 std::array<bool, kButtonCount> m_prev_buttons{};
115 FxVec2f m_mouse_world{0.0f, 0.0f};
116 FxVec2f m_prev_mouse_world{0.0f, 0.0f};
117 FxVec2f m_mouse_screen{0.0f, 0.0f};
118 float m_wheel_delta = 0.0f;
119 bool m_available = false;
120};
FxMouseButton
Definition Input.h:26
FxKey
Definition Input.h:13
@ RightShift
@ LeftShift
@ Backspace
@ RightAlt
@ RightCtrl
@ LeftCtrl
Input state read by gameplay code or injected by a headless producer.
Definition Input.h:28
void set_wheel_delta(float delta)
Definition Input.h:80
void begin_frame()
Definition Input.h:66
const FxVec2f & mouse_position() const
Definition Input.h:51
bool available() const
Definition Input.h:60
bool key_released(FxKey key) const
Definition Input.h:40
static constexpr size_t kKeyCount
Definition Input.h:30
void set_key(FxKey key, bool down)
Definition Input.h:74
void set_mouse_position(const FxVec2f &world, const FxVec2f &screen)
Definition Input.h:76
bool key_down(FxKey key) const
Definition Input.h:36
void clear()
Definition Input.h:89
bool mouse_released(FxMouseButton button) const
Definition Input.h:46
bool key_pressed(FxKey key) const
Definition Input.h:39
float wheel_delta() const
Definition Input.h:57
void release_all()
Definition Input.h:83
bool mouse_down(FxMouseButton button) const
Definition Input.h:42
const FxVec2f & mouse_screen_position() const
Definition Input.h:53
void set_mouse_button(FxMouseButton button, bool down)
Definition Input.h:75
static constexpr size_t kButtonCount
Definition Input.h:31
bool mouse_pressed(FxMouseButton button) const
Definition Input.h:43
FxVec2f mouse_delta() const
Definition Input.h:55
Single-precision 2D vector.
Definition Math.h:47