ASW Lib
A.D.S. Games SDL Wrapper Library. A library targeted at Allegro4 users who want to switch to SDL3 and use modern c++.
Loading...
Searching...
No Matches
input.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cmath>
5#include <type_traits>
6#include <unordered_map>
7#include <vector>
8
11#include "./asw/modules/log.h"
12
13namespace {
16 std::array<bool, asw::input::NUM_CONTROLLER_BUTTONS> pressed { false };
17 std::array<bool, asw::input::NUM_CONTROLLER_BUTTONS> released { false };
18 std::array<bool, asw::input::NUM_CONTROLLER_BUTTONS> down { false };
19
20 bool any_pressed { false };
21 int last_pressed { -1 };
22 float dead_zone { 0.25F };
23
24 std::array<float, asw::input::NUM_CONTROLLER_AXES> axis { 0 };
25
26 SDL_Gamepad* gamepad { nullptr };
27 std::string name;
28};
29
32std::array<SDL_Cursor*, asw::input::NUM_CURSORS> cursors { nullptr };
33
37std::vector<ControllerState> controller { };
38
42std::vector<std::string> slot_owner { };
43
45float default_dead_zone { 0.25F };
46
48std::unordered_map<SDL_JoystickID, uint32_t> controller_id_map { };
49
52std::string text_input;
54
56float rescale_dead_zone(float magnitude, float dead_zone)
57{
58 if (magnitude <= dead_zone) {
59 return 0.0F;
60 }
61
62 return std::min((magnitude - dead_zone) / (1.0F - dead_zone), 1.0F);
63}
64
67{
68 const bool left = stick == asw::input::ControllerStick::Left;
69 const auto x_axis
71 const auto y_axis
73
74 const asw::Vec2<float> raw(
75 cont.axis[static_cast<int>(x_axis)], cont.axis[static_cast<int>(y_axis)]);
76 const float magnitude = std::hypot(raw.x, raw.y);
77 const float scaled = rescale_dead_zone(magnitude, cont.dead_zone);
78
79 if (scaled == 0.0F) {
80 return { 0.0F, 0.0F };
81 }
82
83 return raw * (scaled / magnitude);
84}
85
88{
91
92 switch (axis) {
93 case ControllerAxis::LeftX:
94 return read_stick(cont, ControllerStick::Left).x;
95 case ControllerAxis::LeftY:
96 return read_stick(cont, ControllerStick::Left).y;
97 case ControllerAxis::RightX:
98 return read_stick(cont, ControllerStick::Right).x;
99 case ControllerAxis::RightY:
100 return read_stick(cont, ControllerStick::Right).y;
101 default: {
102 const float value = cont.axis[static_cast<int>(axis)];
103 return std::copysign(rescale_dead_zone(std::abs(value), cont.dead_zone), value);
104 }
105 }
106}
107
109template <typename Pred> bool any_controller(uint32_t index, Pred pred)
110{
111 if (index == asw::input::ANY_CONTROLLER) {
112 return std::any_of(controller.begin(), controller.end(), pred);
113 }
114
115 return index < controller.size() && pred(controller[index]);
116}
117
120template <typename Action> bool each_controller(uint32_t index, Action action)
121{
122 if (index == asw::input::ANY_CONTROLLER) {
123 // No short circuit, every controller gets the action
124 bool any = false;
125 for (auto& cont : controller) {
126 any = action(cont) || any;
127 }
128 return any;
129 }
130
131 return index < controller.size() && action(controller[index]);
132}
133
135uint16_t to_motor_intensity(float intensity)
136{
137 // NaN fails the clamp and would be undefined behaviour to convert
138 if (std::isnan(intensity)) {
139 return 0;
140 }
141
142 return static_cast<uint16_t>(std::clamp(intensity, 0.0F, 1.0F) * UINT16_MAX);
143}
144
146bool has_capability(const ControllerState& cont, const char* property)
147{
148 return SDL_GetBooleanProperty(SDL_GetGamepadProperties(cont.gamepad), property, false);
149}
150
154std::string pad_identity(SDL_JoystickID id, SDL_Gamepad* pad)
155{
156 if (const char* serial = SDL_GetGamepadSerial(pad); serial != nullptr && *serial != '\0') {
157 return std::string("serial:") + serial;
158 }
159
160 std::array<char, 33> guid { };
161 SDL_GUIDToString(SDL_GetGamepadGUIDForID(id), guid.data(), static_cast<int>(guid.size()));
162 return std::string("guid:") + guid.data();
163}
164
165bool slot_empty(std::size_t index)
166{
167 return index >= controller.size() || controller[index].gamepad == nullptr;
168}
169
171std::size_t pick_slot(const std::string& identity)
172{
173 // The slot this pad had before, if no other pad has taken it
174 for (std::size_t i = 0; i < slot_owner.size(); ++i) {
175 if (slot_owner[i] == identity && slot_empty(i)) {
176 return i;
177 }
178 }
179
180 // A gap no unplugged pad is waiting for, then any gap
181 for (std::size_t i = 0; i < controller.size(); ++i) {
182 if (slot_empty(i) && (i >= slot_owner.size() || slot_owner[i].empty())) {
183 return i;
184 }
185 }
186 for (std::size_t i = 0; i < controller.size(); ++i) {
187 if (slot_empty(i)) {
188 return i;
189 }
190 }
191
192 return controller.size();
193}
194} // namespace
195
200
205
206const std::string& asw::input::get_text_input()
207{
208 return text_input;
209}
210
211void asw::input::_append_text(const char* text)
212{
213 text_input += text;
214}
215
217{
218 for (auto& cursor : cursors) {
219 if (cursor != nullptr) {
220 SDL_DestroyCursor(cursor);
221 cursor = nullptr;
222 }
223 }
224}
225
227{
228 auto& k_state = keyboard;
229 auto& m_state = mouse;
230
231 // Clear key state
232 k_state.any_pressed = false;
233 k_state.last_pressed = -1;
234
235 for (auto& pressed : k_state.pressed) {
236 pressed = false;
237 }
238
239 for (auto& released : k_state.released) {
240 released = false;
241 }
242
243 for (auto& repeated : k_state.repeated) {
244 repeated = false;
245 }
246
247 // Clear mouse state
248 m_state.any_pressed = false;
249 m_state.last_pressed = -1;
250 m_state.change = { 0.0F, 0.0F };
251 m_state.z = 0;
252
253 for (auto& pressed : m_state.pressed) {
254 pressed = false;
255 }
256
257 for (auto& released : m_state.released) {
258 released = false;
259 }
260
261 // Clear text input
262 text_input.clear();
263
264 // Clear controller state
265 for (auto& cont : controller) {
266 cont.any_pressed = false;
267 cont.last_pressed = -1;
268
269 for (auto& button : cont.pressed) {
270 button = false;
271 }
272
273 for (auto& button : cont.released) {
274 button = false;
275 }
276 }
277}
278
279// ---- MOUSE ----
280//
281
283{
284 const auto index = static_cast<size_t>(button);
285 return index < mouse.down.size() && mouse.down[index];
286}
287
289{
290 const auto index = static_cast<size_t>(button);
291 return index < mouse.pressed.size() && mouse.pressed[index];
292}
293
295{
296 const auto index = static_cast<size_t>(button);
297 return index < mouse.released.size() && mouse.released[index];
298}
299
301{
302 auto cursor_int = static_cast<uint32_t>(cursor);
303
304 if (cursor_int >= cursors.size()) {
305 return;
306 }
307
308 if (cursors[cursor_int] == nullptr) {
309 cursors[cursor_int] = SDL_CreateSystemCursor(static_cast<SDL_SystemCursor>(cursor_int));
310 }
311
312 SDL_SetCursor(cursors[cursor_int]);
313}
314
316{
317 if (visible) {
318 SDL_ShowCursor();
319 } else {
320 SDL_HideCursor();
321 }
322}
323
324namespace {
325// Window the simulated event belongs to, so render scaling is applied to it
327{
328 auto* window = asw::display::get_window();
329 return window != nullptr ? SDL_GetWindowID(window) : 0;
330}
331
332// Each event struct is filled on its own and then assigned into the union, so
333// the member written is the active one
334
336{
337 SDL_KeyboardEvent key_event { };
338 key_event.type = down ? SDL_EVENT_KEY_DOWN : SDL_EVENT_KEY_UP;
339 key_event.windowID = simulated_window_id();
340 key_event.scancode
341 = static_cast<SDL_Scancode>(static_cast<std::underlying_type_t<asw::input::Key>>(key));
342 key_event.down = down;
343
344 SDL_Event e { };
345 e.key = key_event;
346 SDL_PushEvent(&e);
347}
348
350{
351 SDL_MouseButtonEvent button_event { };
352 button_event.type = down ? SDL_EVENT_MOUSE_BUTTON_DOWN : SDL_EVENT_MOUSE_BUTTON_UP;
353 button_event.windowID = simulated_window_id();
354 button_event.button = static_cast<uint8_t>(
355 static_cast<std::underlying_type_t<asw::input::MouseButton>>(button));
356 button_event.down = down;
357 button_event.clicks = 1;
358
359 // SDL events carry window coordinates, the mouse position is in render
360 // coordinates
361 button_event.x = mouse.position.x;
362 button_event.y = mouse.position.y;
363 if (auto* renderer = asw::display::get_renderer(); renderer != nullptr) {
364 SDL_RenderCoordinatesToWindow(
365 renderer, mouse.position.x, mouse.position.y, &button_event.x, &button_event.y);
366 }
367
368 SDL_Event e { };
369 e.button = button_event;
370 SDL_PushEvent(&e);
371}
372} // namespace
373
378
383
385{
386 // Core converts motion from window to render coordinates, so go the
387 // other way here
388 auto window_pos = position;
389 auto window_prev = mouse.position;
390 if (auto* renderer = asw::display::get_renderer(); renderer != nullptr) {
391 SDL_RenderCoordinatesToWindow(
392 renderer, position.x, position.y, &window_pos.x, &window_pos.y);
393 SDL_RenderCoordinatesToWindow(
394 renderer, mouse.position.x, mouse.position.y, &window_prev.x, &window_prev.y);
395 }
396
397 SDL_MouseMotionEvent motion { };
398 motion.type = SDL_EVENT_MOUSE_MOTION;
399 motion.windowID = simulated_window_id();
400 motion.x = window_pos.x;
401 motion.y = window_pos.y;
402 motion.xrel = window_pos.x - window_prev.x;
403 motion.yrel = window_pos.y - window_prev.y;
404
405 SDL_Event e { };
406 e.motion = motion;
407 SDL_PushEvent(&e);
408}
409
414
419
420// ---- KEYBOARD ----
421//
422
424{
425 return keyboard.down[static_cast<int>(key)];
426}
427
429{
430 return keyboard.pressed[static_cast<int>(key)];
431}
432
434{
435 const auto index = static_cast<int>(key);
436 return keyboard.pressed[index] || keyboard.repeated[index];
437}
438
440{
441 return keyboard.released[static_cast<int>(key)];
442}
443
444// ---- CONTROLLER ----
445//
446
448{
449 const auto b = static_cast<int>(button);
450 return any_controller(index, [b](const ControllerState& cont) { return cont.down[b]; });
451}
452
454{
455 const auto b = static_cast<int>(button);
456 return any_controller(index, [b](const ControllerState& cont) { return cont.pressed[b]; });
457}
458
460{
461 const auto b = static_cast<int>(button);
462 return any_controller(index, [b](const ControllerState& cont) { return cont.released[b]; });
463}
464
466{
467 if (index != ANY_CONTROLLER) {
468 return index < controller.size() ? read_axis(controller[index], axis) : 0.0F;
469 }
470
471 float furthest = 0.0F;
472 for (const auto& cont : controller) {
473 const float value = read_axis(cont, axis);
474 if (std::abs(value) > std::abs(furthest)) {
475 furthest = value;
476 }
477 }
478
479 return furthest;
480}
481
483{
484 if (index != ANY_CONTROLLER) {
485 return index < controller.size() ? read_stick(controller[index], stick)
486 : Vec2<float>(0.0F, 0.0F);
487 }
488
489 Vec2<float> furthest(0.0F, 0.0F);
490 for (const auto& cont : controller) {
491 const auto value = read_stick(cont, stick);
492 if (std::hypot(value.x, value.y) > std::hypot(furthest.x, furthest.y)) {
493 furthest = value;
494 }
495 }
496
497 return furthest;
498}
499
500void asw::input::set_controller_dead_zone(uint32_t index, float dead_zone)
501{
502 // Below 1 so rescaling never divides by zero
503 dead_zone = std::clamp(dead_zone, 0.0F, 0.99F);
504
505 if (index == ANY_CONTROLLER) {
506 // Pads connected later start with this dead zone too
507 default_dead_zone = dead_zone;
508 for (auto& cont : controller) {
509 cont.dead_zone = dead_zone;
510 }
511 return;
512 }
513
514 if (index >= controller.size()) {
515 return;
516 }
517
518 controller[index].dead_zone = dead_zone;
519}
520
522 uint32_t index, float low_frequency, float high_frequency, uint32_t duration_ms)
523{
524 const auto low = to_motor_intensity(low_frequency);
525 const auto high = to_motor_intensity(high_frequency);
526
527 return each_controller(index, [&](const ControllerState& cont) {
528 return SDL_RumbleGamepad(cont.gamepad, low, high, duration_ms);
529 });
530}
531
533 uint32_t index, float left, float right, uint32_t duration_ms)
534{
535 const auto left_intensity = to_motor_intensity(left);
536 const auto right_intensity = to_motor_intensity(right);
537
538 return each_controller(index, [&](const ControllerState& cont) {
539 return SDL_RumbleGamepadTriggers(
540 cont.gamepad, left_intensity, right_intensity, duration_ms);
541 });
542}
543
545{
546 return any_controller(index, [](const ControllerState& cont) {
547 return has_capability(cont, SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN);
548 });
549}
550
552{
553 return any_controller(index, [](const ControllerState& cont) {
554 return has_capability(cont, SDL_PROP_GAMEPAD_CAP_TRIGGER_RUMBLE_BOOLEAN);
555 });
556}
557
562
564{
565 return static_cast<int>(controller.size());
566}
567
569{
570 return index < controller.size() && controller[index].gamepad != nullptr;
571}
572
573std::string asw::input::get_controller_name(uint32_t index)
574{
575 if (index >= controller.size()) {
576 return "";
577 }
578
579 return controller.at(index).name;
580}
581
583
584void asw::input::_key_down(SDL_Scancode scancode, bool repeat)
585{
586 // Repeats do not count as a new press, so held keys do not retrigger
587 // get_key_down()
588 if (repeat) {
589 keyboard.repeated[scancode] = true;
590 keyboard.down[scancode] = true;
591 return;
592 }
593
594 keyboard.pressed[scancode] = true;
595 keyboard.down[scancode] = true;
596 keyboard.any_pressed = true;
597 keyboard.last_pressed = scancode;
599}
600
601void asw::input::_key_up(SDL_Scancode scancode)
602{
603 keyboard.released[scancode] = true;
604 keyboard.down[scancode] = false;
605}
606
608{
609 // Mice with many side buttons can report numbers past the ones we track
610 if (button >= mouse.pressed.size()) {
611 return;
612 }
613
614 const auto button_int = static_cast<int>(button);
615 mouse.pressed[button_int] = true;
616 mouse.down[button_int] = true;
617 mouse.any_pressed = true;
618 mouse.last_pressed = button_int;
620}
621
623{
624 if (button >= mouse.released.size()) {
625 return;
626 }
627
628 const auto button_int = static_cast<int>(button);
629 mouse.released[button_int] = true;
630 mouse.down[button_int] = false;
631}
632
633void asw::input::_mouse_motion(float x, float y, float delta_x, float delta_y)
634{
635 mouse.position.x = x;
636 mouse.position.y = y;
637 // Several motion events can arrive in one frame, so add them up
638 mouse.change.x += delta_x;
639 mouse.change.y += delta_y;
641}
642
643void asw::input::_mouse_wheel(float delta_z)
644{
645 mouse.z += delta_z;
646}
647
648void asw::input::_controller_added(SDL_JoystickID id)
649{
650 if (!SDL_IsGamepad(id)) {
651 asw::log::warn("Failed to open gamepad: {}", id);
652 return;
653 }
654
655 auto* opened = SDL_OpenGamepad(id);
656 if (opened == nullptr) {
657 asw::log::warn("Failed to open gamepad: {}", id);
658 return;
659 }
660
661 // A pad plugged back in gets its old slot, others fill the first gap
662 std::string identity = pad_identity(id, opened);
663 const std::size_t index = pick_slot(identity);
664 if (index >= controller.size()) {
665 controller.resize(index + 1);
666 }
667 if (index >= slot_owner.size()) {
668 slot_owner.resize(index + 1);
669 }
670 slot_owner[index] = std::move(identity);
671
672 auto& new_controller = controller[index];
673 new_controller = ControllerState { };
674 new_controller.gamepad = opened;
675 new_controller.dead_zone = default_dead_zone;
676 const char* name = SDL_GetGamepadName(opened);
677 new_controller.name = name != nullptr ? name : "";
678 controller_id_map[id] = static_cast<uint32_t>(index);
679
680 asw::log::info("Gamepad added: {} (ID: {}, index: {})", new_controller.name, id, index);
681}
682
683void asw::input::_controller_removed(SDL_JoystickID id)
684{
685 const auto it = controller_id_map.find(id);
686 if (it == controller_id_map.end()) {
687 return;
688 }
689
690 // Empty the slot but keep it, so the other pads keep their indexes
691 const auto index = it->second;
692 controller_id_map.erase(it);
693 if (controller[index].gamepad != nullptr) {
694 SDL_CloseGamepad(controller[index].gamepad);
695 }
696 controller[index] = ControllerState { };
697
698 // Drop empty slots at the end. slot_owner keeps them, so the pad can
699 // still get its slot back.
700 while (!controller.empty() && controller.back().gamepad == nullptr) {
701 controller.pop_back();
702 }
703}
704
705void asw::input::_controller_axis_motion(SDL_JoystickID id, uint32_t axis, float value)
706{
707 const auto it = controller_id_map.find(id);
708 if (it == controller_id_map.end()) {
709 return;
710 }
711
712 const auto index = it->second;
713 if (index >= controller.size() || axis >= asw::input::NUM_CONTROLLER_AXES) {
714 return;
715 }
716
717 controller[index].axis[axis] = value / 32768.0F; // Normalize to [-1, 1]
718
719 if (read_axis(controller[index], static_cast<asw::input::ControllerAxis>(axis)) != 0.0F) {
721 }
722}
723
724void asw::input::_controller_button_down(SDL_JoystickID id, uint32_t button)
725{
726 const auto it = controller_id_map.find(id);
727 if (it == controller_id_map.end()) {
728 return;
729 }
730
731 const auto index = it->second;
732 if (index >= controller.size()) {
733 return;
734 }
735
736 controller[index].pressed[button] = true;
737 controller[index].down[button] = true;
738 controller[index].any_pressed = true;
739 controller[index].last_pressed = button;
741}
742
743void asw::input::_controller_button_up(SDL_JoystickID id, uint32_t button)
744{
745 const auto it = controller_id_map.find(id);
746 if (it == controller_id_map.end()) {
747 return;
748 }
749
750 const auto index = it->second;
751 if (index >= controller.size()) {
752 return;
753 }
754
755 controller[index].released[button] = true;
756 controller[index].down[button] = false;
757}
Action binding system for the ASW library.
A 2D vector in space.
Definition geometry.h:27
T y
The y component of the vector.
Definition geometry.h:280
T x
The x component of the vector.
Definition geometry.h:277
Display and window routines for the ASW library.
Input module for the ASW library.
Structured logging system.
bool any_controller(uint32_t index, Pred pred)
Check a button on one controller, or on any when index is ANY_CONTROLLER.
Definition input.cpp:109
std::string pad_identity(SDL_JoystickID id, SDL_Gamepad *pad)
What tells a pad apart when it is plugged back in: its serial number, or its model when it has none....
Definition input.cpp:154
uint16_t to_motor_intensity(float intensity)
Convert an intensity between 0 and 1 to SDL's motor range.
Definition input.cpp:135
bool has_capability(const ControllerState &cont, const char *property)
Read a boolean capability from a controller's properties.
Definition input.cpp:146
struct ControllerState { std::array< bool, asw::input::NUM_CONTROLLER_BUTTONS > pressed { false }; std::array< bool, asw::input::NUM_CONTROLLER_BUTTONS > released { false }; std::array< bool, asw::input::NUM_CONTROLLER_BUTTONS > down { false }; bool any_pressed { false }; int last_pressed { -1 }; float dead_zone { 0.25F }; std::array< float, asw::input::NUM_CONTROLLER_AXES > axis { 0 }; SDL_Gamepad *gamepad { nullptr }; std::string name;} ControllerState
Data structure for controller state, including button states and axis values.
Definition input.cpp:15
asw::Vec2< float > read_stick(const ControllerState &cont, asw::input::ControllerStick stick)
Read a stick with a radial dead zone.
Definition input.cpp:66
std::vector< ControllerState > controller
Global controller state. A slot stays at its index while its pad is unplugged, and the pad gets it ba...
Definition input.cpp:37
float read_axis(const ControllerState &cont, asw::input::ControllerAxis axis)
Read one axis with the dead zone applied.
Definition input.cpp:87
void push_simulated_key(asw::input::Key key, bool down)
Definition input.cpp:335
std::unordered_map< SDL_JoystickID, uint32_t > controller_id_map
Map of SDL_JoystickID to controller index in the controller vector.
Definition input.cpp:48
asw::input::MouseState mouse
Definition input.cpp:51
std::size_t pick_slot(const std::string &identity)
Pick the slot for a pad that just connected.
Definition input.cpp:171
bool slot_empty(std::size_t index)
Definition input.cpp:165
float default_dead_zone
Dead zone given to pads when they connect.
Definition input.cpp:45
asw::input::KeyState keyboard
Definition input.cpp:50
std::vector< std::string > slot_owner
The pad each slot last held, by pad_identity(). Kept after the pad is unplugged and after its slot is...
Definition input.cpp:42
bool each_controller(uint32_t index, Action action)
Run an action on one controller, or on all when index is ANY_CONTROLLER.
Definition input.cpp:120
void push_simulated_mouse_button(asw::input::MouseButton button, bool down)
Definition input.cpp:349
std::array< SDL_Cursor *, asw::input::NUM_CURSORS > cursors
Active cursor stores the current active cursor. It is updated by the core.
Definition input.cpp:32
SDL_WindowID simulated_window_id()
Definition input.cpp:326
asw::input::InputDevice last_device
Definition input.cpp:53
float rescale_dead_zone(float magnitude, float dead_zone)
Rescale a value past the dead zone so it starts from zero.
Definition input.cpp:56
asw::Renderer * get_renderer()
Get the SDL renderer.
Definition display.cpp:139
asw::Window * get_window()
Get the SDL window.
Definition display.cpp:144
void _mouse_button_up(uint8_t button)
Mouse button up hook.
Definition input.cpp:622
bool get_controller_button_up(uint32_t index, asw::input::ControllerButton button)
Check if a controller button was released since the last update.
Definition input.cpp:459
void _shutdown()
Free cached cursors. Called by asw::core::shutdown().
Definition input.cpp:216
bool get_controller_button_down(uint32_t index, asw::input::ControllerButton button)
Check if a controller button was pressed since the last update.
Definition input.cpp:453
bool get_key(asw::input::Key key)
Check if a key is down.
Definition input.cpp:423
void _mouse_button_down(uint8_t button)
Mouse button down hook.
Definition input.cpp:607
InputDevice get_last_device()
Get the device the player used most recently.
Definition input.cpp:558
void set_cursor_visible(bool visible)
Show or hide the mouse cursor, for games that draw their own.
Definition input.cpp:315
bool is_controller_connected(uint32_t index)
Check if a controller is connected at an index.
Definition input.cpp:568
bool get_controller_button(uint32_t index, asw::input::ControllerButton button)
Check if a controller button is down.
Definition input.cpp:447
struct KeyState { std::array< bool, NUM_KEYS > pressed { false }; std::array< bool, NUM_KEYS > released { false }; std::array< bool, NUM_KEYS > down { false }; std::array< bool, NUM_KEYS > repeated { false }; bool any_pressed { false }; int last_pressed { -1 };} KeyState
Keyboard state stores the current state of the keyboard. It is updated by the core.
Definition input.h:352
CursorId
System cursor Ids.
Definition input.h:280
void _key_up(SDL_Scancode scancode)
Key up hook.
Definition input.cpp:601
void simulate_key_down(asw::input::Key key)
Simulate a key being pressed.
Definition input.cpp:374
Vec2< float > get_controller_stick(uint32_t index, asw::input::ControllerStick stick)
Get the position of a controller stick with the dead zone applied.
Definition input.cpp:482
std::string get_controller_name(uint32_t index)
Get the name of a controller.
Definition input.cpp:573
void set_cursor(asw::input::CursorId cursor)
Change cursor.
Definition input.cpp:300
void _controller_removed(SDL_JoystickID id)
Controller removed hook.
Definition input.cpp:683
void simulate_mouse_button_down(asw::input::MouseButton button)
Simulate a mouse button being pressed.
Definition input.cpp:410
void simulate_mouse_button_up(asw::input::MouseButton button)
Simulate a mouse button being released.
Definition input.cpp:415
void simulate_key_up(asw::input::Key key)
Simulate a key being released.
Definition input.cpp:379
bool get_key_up(asw::input::Key key)
Check if a key was released since the last update.
Definition input.cpp:439
InputDevice
Device the player used most recently.
Definition input.h:512
void reset()
Reset all input states. Called by the core.
Definition input.cpp:226
const KeyState & get_keyboard()
Get the current keyboard state.
Definition input.cpp:196
bool rumble_controller(uint32_t index, float low_frequency, float high_frequency, uint32_t duration_ms)
Rumble a controller's main motors.
Definition input.cpp:521
void set_controller_dead_zone(uint32_t index, float dead_zone)
Set the joystick deadzone for a controller.
Definition input.cpp:500
bool get_key_down(asw::input::Key key)
Check if a key was pressed since the last update.
Definition input.cpp:428
void _mouse_wheel(float delta_z)
Mouse wheel hook.
Definition input.cpp:643
Key
Enumeration of keys in the ASW library.
Definition input.h:38
bool get_key_repeat(asw::input::Key key)
Check if a key was pressed or auto-repeated since the last update.
Definition input.cpp:433
int get_controller_count()
Get the number of controller slots.
Definition input.cpp:563
void simulate_mouse_move(const asw::Vec2< float > &position)
Simulate the mouse moving.
Definition input.cpp:384
constexpr uint32_t ANY_CONTROLLER
Pass as a controller index to read every connected controller.
Definition input.h:503
const MouseState & get_mouse()
Get the current mouse state.
Definition input.cpp:201
void _key_down(SDL_Scancode scancode, bool repeat=false)
Key down hook.
Definition input.cpp:584
ControllerStick
Analog sticks on a game controller.
Definition input.h:506
bool get_mouse_button(asw::input::MouseButton button)
Check if a mouse button is down.
Definition input.cpp:282
constexpr int NUM_CONTROLLER_AXES
Number of axes on a game controller.
Definition input.h:485
void _controller_axis_motion(SDL_JoystickID id, uint32_t axis, float value)
Axis moved hook.
Definition input.cpp:705
bool controller_has_trigger_rumble(uint32_t index)
Check if a controller supports trigger rumble.
Definition input.cpp:551
ControllerButton
Mappings from SDL game controller buttons to ASW buttons.
Definition input.h:459
bool controller_has_rumble(uint32_t index)
Check if a controller supports rumble.
Definition input.cpp:544
float get_controller_axis(uint32_t index, asw::input::ControllerAxis axis)
Get the value of a controller axis with the dead zone applied.
Definition input.cpp:465
bool get_mouse_button_up(asw::input::MouseButton button)
Check if a mouse button was released since the last update.
Definition input.cpp:294
void _controller_added(SDL_JoystickID id)
Controller added hook.
Definition input.cpp:648
bool get_mouse_button_down(asw::input::MouseButton button)
Check if a mouse button was pressed since the last update.
Definition input.cpp:288
bool rumble_controller_triggers(uint32_t index, float left, float right, uint32_t duration_ms)
Rumble a controller's trigger motors.
Definition input.cpp:532
void _append_text(const char *text)
Event Hooks.
Definition input.cpp:211
MouseButton
Enumeration of mouse buttons in the ASW library.
Definition input.h:28
const std::string & get_text_input()
Get the text input received this frame.
Definition input.cpp:206
void _controller_button_down(SDL_JoystickID id, uint32_t button)
Button down hook.
Definition input.cpp:724
void _controller_button_up(SDL_JoystickID id, uint32_t button)
Button up hook.
Definition input.cpp:743
struct MouseState { bool any_pressed { false }; int last_pressed { -1 }; Vec2< float > change { 0.0F, 0.0F }; Vec2< float > position { 0.0F, 0.0F }; float z { 0.0F }; std::array< bool, NUM_MOUSE_BUTTONS > pressed { false }; std::array< bool, NUM_MOUSE_BUTTONS > released { false }; std::array< bool, NUM_MOUSE_BUTTONS > down { false };} MouseState
Mouse state stores the current state of the mouse. It is updated by the core.
Definition input.h:306
ControllerAxis
Mappings from SDL game controller axes to ASW axes.
Definition input.h:488
void _mouse_motion(float x, float y, float delta_x, float delta_y)
Mouse motion hook.
Definition input.cpp:633
void info(const std::string &message)
Log an info message.
Definition log.cpp:186
void warn(const std::string &message)
Log a warning message.
Definition log.cpp:191