A 3D game engine from scratch.
1// (c) 2020 Vlad-Stefan Harbuz <vlad@vladh.net>
2
3#include "../src_external/pstr.h"
4#include "logs.hpp"
5#include "input.hpp"
6
7
8input::State *input::state = nullptr;
9
10
11char *
12input::get_text_input()
13{
14 return input::state->text_input;
15}
16
17
18bool
19input::is_cursor_enabled()
20{
21 return input::state->is_cursor_enabled;
22}
23
24
25void
26input::set_is_cursor_enabled(bool val)
27{
28 input::state->is_cursor_enabled = val;
29}
30
31
32bool
33input::is_text_input_enabled()
34{
35 return input::state->is_text_input_enabled;
36}
37
38
39v2
40input::get_mouse_offset()
41{
42 return input::state->mouse_offset;
43}
44
45
46v2
47input::get_mouse_3d_offset()
48{
49 return input::state->mouse_3d_offset;
50}
51
52
53void
54input::update_mouse_button(int button, int action, int mods)
55{
56 bool new_state = (action == GLFW_PRESS);
57 if (new_state != input::state->mouse_button_states[button]) {
58 input::state->mouse_button_states[button] = new_state;
59 input::state->n_mouse_button_state_changes_this_frame[button]++;
60 }
61}
62
63
64bool
65input::is_mouse_button_down(int button)
66{
67 return input::state->mouse_button_states[button];
68}
69
70
71bool
72input::is_mouse_button_up(int button)
73{
74 return !is_mouse_button_down(button);
75}
76
77
78bool
79input::is_mouse_button_now_down(int button)
80{
81 return is_mouse_button_down(button) &&
82 input::state->n_mouse_button_state_changes_this_frame[button] > 0;
83}
84
85
86bool
87input::is_mouse_button_now_up(int button)
88{
89 return is_mouse_button_up(button) &&
90 input::state->n_mouse_button_state_changes_this_frame[button] > 0;
91}
92
93
94void
95input::update_mouse(v2 new_mouse_pos)
96{
97 if (!input::state->have_ever_gotten_mouse_pos) {
98 input::state->mouse_pos = new_mouse_pos;
99 input::state->have_ever_gotten_mouse_pos = true;
100 }
101
102 input::state->mouse_offset = new_mouse_pos - input::state->mouse_pos;
103 input::state->mouse_3d_offset =
104 input::state->mouse_offset * (f32)input::state->mouse_3d_sensitivity;
105 input::state->mouse_pos = new_mouse_pos;
106}
107
108
109void
110input::clear_text_input()
111{
112 pstr_clear(input::state->text_input);
113}
114
115
116void
117input::enable_text_input()
118{
119 input::state->is_text_input_enabled = true;
120 clear_text_input();
121}
122
123
124void
125input::disable_text_input()
126{
127 input::state->is_text_input_enabled = false;
128 clear_text_input();
129}
130
131
132void
133input::do_text_input_backspace()
134{
135 size_t text_input_length = strlen(input::state->text_input);
136 if (text_input_length == 0) {
137 return;
138 }
139 input::state->text_input[text_input_length - 1] = '\0';
140}
141
142
143void
144input::update_text_input(u32 codepoint)
145{
146 if (!input::state->is_text_input_enabled) {
147 return;
148 }
149 char poor_smashed_ascii_character = (char)codepoint;
150 size_t text_input_length = strlen(input::state->text_input);
151
152 if (text_input_length + 1 >= MAX_TEXT_INPUT_LENGTH - 1) {
153 logs::error("Can't add another character to text_input, it's full.");
154 return;
155 }
156
157 input::state->text_input[text_input_length] = poor_smashed_ascii_character;
158 input::state->text_input[text_input_length + 1] = '\0';
159}
160
161
162void
163input::update_keys(int key, int scancode, int action, int mods)
164{
165 bool new_state = (action == GLFW_PRESS || action == GLFW_REPEAT);
166 if (new_state != input::state->key_states[key]) {
167 input::state->key_states[key] = new_state;
168 input::state->n_key_state_changes_this_frame[key]++;
169 }
170}
171
172
173bool
174input::is_key_down(int key)
175{
176 return input::state->key_states[key];
177}
178
179
180bool
181input::is_key_up(int key)
182{
183 return !is_key_down(key);
184}
185
186
187bool
188input::is_key_now_down(int key)
189{
190 return is_key_down(key) && input::state->n_key_state_changes_this_frame[key] > 0;
191}
192
193
194bool
195input::is_key_now_up(int key)
196{
197 return is_key_up(key) && input::state->n_key_state_changes_this_frame[key] > 0;
198}
199
200
201bool
202input::is_mouse_in_bb(v2 topleft, v2 bottomright)
203{
204 return input::state->mouse_pos.x > topleft.x &&
205 input::state->mouse_pos.x < bottomright.x &&
206 input::state->mouse_pos.y > topleft.y &&
207 input::state->mouse_pos.y < bottomright.y;
208}
209
210
211void
212input::set_cursor(GLFWcursor *new_cursor)
213{
214 if (input::state->current_cursor == new_cursor) {
215 return;
216 }
217 input::state->current_cursor = new_cursor;
218 glfwSetCursor(input::state->window, new_cursor);
219}
220
221
222void
223input::set_cursor(CursorType type)
224{
225 if (type == input::CursorType::none) {
226 return;
227 } else if (type == input::CursorType::arrow) {
228 set_cursor(input::state->arrow_cursor);
229 } else if (type == input::CursorType::ibeam) {
230 set_cursor(input::state->ibeam_cursor);
231 } else if (type == input::CursorType::crosshair) {
232 set_cursor(input::state->crosshair_cursor);
233 } else if (type == input::CursorType::hand) {
234 set_cursor(input::state->hand_cursor);
235 } else if (type == input::CursorType::hresize) {
236 set_cursor(input::state->hresize_cursor);
237 } else if (type == input::CursorType::vresize) {
238 set_cursor(input::state->vresize_cursor);
239 } else {
240 logs::fatal("Unknown cursor type");
241 }
242}
243
244
245void
246input::reset_n_mouse_button_state_changes_this_frame()
247{
248 memset(input::state->n_mouse_button_state_changes_this_frame,
249 0, sizeof(input::state->n_mouse_button_state_changes_this_frame));
250}
251
252
253void
254input::reset_n_key_state_changes_this_frame()
255{
256 memset(input::state->n_key_state_changes_this_frame,
257 0, sizeof(input::state->n_key_state_changes_this_frame));
258}
259
260
261void
262input::init(input::State *input_state, GLFWwindow *window)
263{
264 input::state = input_state;
265 input::state->window = window;
266 input::state->mouse_3d_sensitivity = 0.1f;
267 input::state->arrow_cursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
268 input::state->ibeam_cursor = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
269 input::state->crosshair_cursor = glfwCreateStandardCursor(GLFW_CROSSHAIR_CURSOR);
270 input::state->hand_cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
271 input::state->hresize_cursor = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
272 input::state->vresize_cursor = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR);
273}