1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
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;
}
}
|