Skip to main content

GamepadState.ixx File

Representation of current gamepad input state. More...

Included Headers

#include <algorithm> #include <helios/helios_config.h> #include <helios.util.log.LogManager> #include <helios.util.log.Logger> #include <helios.math.types>

Namespaces Index

namespacehelios
namespaceinput

Input handling and management. More...

namespacegamepad

Gamepad input handling and configuration. More...

Classes Index

classGamepadState

A lightweight class for transferring the state of a Gamepad. More...

Macro Definitions Index

#defineHELIOS_LOG_SCOPE   "helios::input::gamepad::GamepadState"

Description

Representation of current gamepad input state.

Macro Definitions

HELIOS_LOG_SCOPE

#define HELIOS_LOG_SCOPE   "helios::input::gamepad::GamepadState"

Definition at line 17 of file GamepadState.ixx.

17#define HELIOS_LOG_SCOPE "helios::input::gamepad::GamepadState"

File Listing

The file content with the documentation metadata removed is:

1/**
2 * @file GamepadState.ixx
3 * @brief Representation of current gamepad input state.
4 */
5module;
6
7#include <algorithm>
8#include <helios/helios_config.h>
9
10export module helios.input.gamepad.GamepadState;
11
12import helios.math.types;
13import helios.util.log.Logger;
14import helios.util.log.LogManager;
15
16
17#define HELIOS_LOG_SCOPE "helios::input::gamepad::GamepadState"
18export namespace helios::input::gamepad {
19
20 /**
21 * @brief A lightweight class for transferring the state of a Gamepad.
22 *
23 * This class models a reusable object representing the input state of a gamepad.
24 * The input state of a gamepad consists of the state of the left and right trigger,
25 * ranging from [0, 1], where 1 means fully pressed and 0 means not pressed at all.
26 *
27 * Similarly, a GamepadState provides information about the left and the right
28 * gamepad axes. Both the x- and the y-axis range from [-1, 1]. For the x-axis,
29 * the following holds:
30 * - 0 => not moved at all
31 * - -1 => moved all the way to the left
32 * - 1 => moved all the way to the right
33 *
34 * For the y-axis the positive direction corresponds to "up" and the negative
35 * direction corresponds to "down".
36 *
37 * Updating the values is done by calling `updateAxes` on this object.
38 *
39 * For convenient access of the axes in 2D coordinates, the class provides accessors
40 * to the sticks' axes in `vec2f` form.
41 *
42 * Button states are generally represented with boolean values, i.e. true for pressed,
43 * otherwise false.
44 *
45 * @note Implementations must account for joystick drift: achieving exactly 0
46 * for x/y when no human input occurred is rare. Consider applying a dead zone
47 * when processing the GamepadState. Axis values are individually clipped to [-1.0, 1.0],
48 * but the magnitude of the resulting (x, y) vector may exceed 1.0. Applications should
49 * normalize input vectors where appropriate and possibly offer calibration.
50 *
51 * This implementation is inspired by the GLFW gamepad input model.
52 * @see https://www.glfw.org/docs/latest/input_guide.html#joystick
53 */
55
56 private:
57 /**
58 * @brief Shared logger instance for all GamepadState objects.
59 */
61
62
63 /**
64 * @brief State of the A button (true if pressed).
65 */
66 bool buttonA_ = false;
67
68 /**
69 * @brief State of the B button (true if pressed).
70 */
71 bool buttonB_ = false;
72
73 /**
74 * @brief State of the X button (true if pressed).
75 */
76 bool buttonX_ = false;
77
78 /**
79 * @brief State of the Y button (true if pressed).
80 */
81 bool buttonY_ = false;
82
83 /**
84 * @brief State of the Start button (true if pressed).
85 */
86 bool buttonStart_ = false;
87
88 /**
89 * @brief State of the Back button (true if pressed).
90 */
91 bool buttonBack_ = false;
92
93 /**
94 * @brief State of the Guide button (true if pressed).
95 */
96 bool buttonGuide_ = false;
97
98 /**
99 * @brief State of the left bumper button (true if pressed).
100 */
101 bool buttonLeftBumper_ = false;
102
103 /**
104 * @brief State of the right bumper button (true if pressed).
105 */
106 bool buttonRightBumper_ = false;
107
108 /**
109 * @brief State of the left thumbstick button (true if pressed).
110 */
111 bool buttonLeftThumb_ = false;
112
113 /**
114 * @brief State of the right thumbstick button (true if pressed).
115 */
116 bool buttonRightThumb_ = false;
117
118 /**
119 * @brief State of the D-pad up button (true if pressed).
120 */
121 bool buttonDpadUp_ = false;
122
123 /**
124 * @brief State of the D-pad right button (true if pressed).
125 */
126 bool buttonDpadRight_ = false;
127
128 /**
129 * @brief State of the D-pad down button (true if pressed).
130 */
131 bool buttonDpadDown_ = false;
132
133 /**
134 * @brief State of the D-pad left button (true if pressed).
135 */
136 bool buttonDpadLeft_ = false;
137
138 /**
139 * @brief Flag to indicate if the cached vec2f members need to be recalculated.
140 */
141 mutable bool needsUpdate_ = true;
142
143 /**
144 * @brief Raw float value of the left stick's x-axis.
145 */
146 float axisLeftX_{};
147
148 /**
149 * @brief Raw float value of the left stick's y-axis.
150 */
151 float axisLeftY_{};
152
153 /**
154 * @brief Raw float value of the right stick's x-axis.
155 */
156 float axisRightX_{};
157
158 /**
159 * @brief Raw float value of the right stick's y-axis.
160 */
161 float axisRightY_{};
162
163 /**
164 * @brief Raw float value of the left trigger.
165 */
166 float triggerLeft_{};
167
168 /**
169 * @brief Raw float value of the right trigger.
170 */
171 float triggerRight_{};
172
173 /**
174 * @brief Cached vec2f representation of the left stick (x, y).
175 */
176 mutable helios::math::vec2f left_;
177
178 /**
179 * @brief Cached vec2f representation of the right stick (x, y).
180 */
181 mutable helios::math::vec2f right_;
182
183 /**
184 * @brief Cached vec2f representation of the triggers (left, right).
185 */
186 mutable helios::math::vec2f trigger_;
187
188 /**
189 * @brief Internal method to update the cached vec2f representations.
190 * This method should be called when the current values of the axes are queried
191 * in vec2f form and `needsUpdate_` evaluates to `true`.
192 */
193 void update() const noexcept {
194 left_ = helios::math::vec2f(axisLeftX_, axisLeftY_);
195 right_ = helios::math::vec2f(axisRightX_, axisRightY_);
196 trigger_ = helios::math::vec2f(triggerLeft_, triggerRight_);
197
198 needsUpdate_ = false;
199 }
200
201 public:
202 ~GamepadState() = default;
203
204 /**
205 * @brief Default constructor.
206 *
207 * Initializes all the values with 0.0f.
208 */
209 GamepadState() = default;
210
211 /**
212 * @brief Creates a new GamepadState object.
213 *
214 * Delegates to `updateAxes` for value initialization.
215 *
216 * @see updateAxes
217 */
218 explicit GamepadState(
219 float axisLeftX, float axisLeftY, float axisRightX,
220 float axisRightY, float triggerLeft, float triggerRight,
221
222 bool buttonA, bool buttonB, bool buttonX, bool buttonY,
223 bool buttonStart, bool buttonBack, bool buttonGuide,
227
228 ) noexcept {
230 axisLeftX, axisLeftY, axisRightX, axisRightY, triggerLeft, triggerRight,
231
235 }
236
237
238 /**
239 * @brief Updates the axes and button states of this GamepadState object.
240 *
241 * This method updates raw axis and trigger values and stores the boolean
242 * state of all standard gamepad buttons. Float parameters are asserted to
243 * be in their expected ranges and then clamped.
244 *
245 * For the sticks' range [-1, 1] the following holds:
246 * -1 means moved all the way left/down, 0 means not moved at all, 1 means moved all the way right/up.
247 *
248 * For the triggers' range of [0, 1] the following holds:
249 * 0 means not pressed, 1 means fully pressed.
250 *
251 * @param axisLeftX The x-axis of the left stick, expected in [-1, 1].
252 * @param axisLeftY The y-axis of the left stick, expected in [-1, 1].
253 * @param axisRightX The x-axis of the right stick, expected in [-1, 1].
254 * @param axisRightY The y-axis of the right stick, expected in [-1, 1].
255 * @param triggerLeft The left trigger value, expected in [0, 1].
256 * @param triggerRight The right trigger value, expected in [0, 1].
257 * @param buttonA True if the A button is pressed.
258 * @param buttonB True if the B button is pressed.
259 * @param buttonX True if the X button is pressed.
260 * @param buttonY True if the Y button is pressed.
261 * @param buttonStart True if the Start button is pressed.
262 * @param buttonBack True if the Back button is pressed.
263 * @param buttonGuide True if the Guide (platform) button is pressed.
264 * @param buttonLeftBumper True if the left bumper is pressed.
265 * @param buttonRightBumper True if the right bumper is pressed.
266 * @param buttonLeftThumb True if the left thumbstick button is pressed.
267 * @param buttonRightThumb True if the right thumbstick button is pressed.
268 * @param buttonDpadUp True if the D-pad Up button is pressed.
269 * @param buttonDpadRight True if the D-pad Right button is pressed.
270 * @param buttonDpadDown True if the D-pad Down button is pressed.
271 * @param buttonDpadLeft True if the D-pad Left button is pressed.
272 */
274 float axisLeftX, float axisLeftY, float axisRightX, float axisRightY,
275 float triggerLeft, float triggerRight,
276
277 bool buttonA, bool buttonB, bool buttonX, bool buttonY,
278 bool buttonStart, bool buttonBack, bool buttonGuide,
282 ) noexcept {
283
284 #ifdef HELIOS_DEBUG
285 if(axisLeftX < -1.0f || axisLeftX > 1.0f) {
286 logger_.warn("axisLeftX is out of bounds.");
287 }
288 if(axisLeftY < -1.0f || axisLeftY > 1.0f) {
289 logger_.warn("axisLeftY is out of bounds.");
290 }
291 if(axisRightX < -1.0f || axisRightX > 1.0f) {
292 logger_.warn("axisRightX is out of bounds.");
293 }
294 if(axisRightY < -1.0f || axisRightY > 1.0f) {
295 logger_.warn("axisRightY is out of bounds.");
296 }
298 logger_.warn("triggerLeft is out of bounds.");
299 }
301 logger_.warn("triggerRight is out of bounds.");
302 }
303 #endif
304
305 axisLeftX_ = std::clamp(axisLeftX, -1.0f, 1.0f);
306 axisLeftY_ = std::clamp(axisLeftY, -1.0f, 1.0f);
307 axisRightX_ = std::clamp(axisRightX, -1.0f, 1.0f);
308 axisRightY_ = std::clamp(axisRightY, -1.0f, 1.0f);
309 triggerLeft_ = std::clamp(triggerLeft, 0.0f, 1.0f);
310 triggerRight_ = std::clamp(triggerRight, 0.0f, 1.0f);
311
312 buttonA_ = buttonA;
313 buttonB_ = buttonB;
314 buttonX_ = buttonX;
315 buttonY_ = buttonY;
316 buttonStart_ = buttonStart;
317 buttonBack_ = buttonBack;
318 buttonGuide_ = buttonGuide;
319 buttonLeftBumper_ = buttonLeftBumper;
320 buttonRightBumper_ = buttonRightBumper;
321 buttonLeftThumb_ = buttonLeftThumb;
322 buttonRightThumb_ = buttonRightThumb;
323 buttonDpadUp_ = buttonDpadUp;
324 buttonDpadRight_ = buttonDpadRight;
325 buttonDpadDown_ = buttonDpadDown;
326 buttonDpadLeft_ = buttonDpadLeft;
327
328 needsUpdate_ = true;
329 }
330
331 /**
332 * @brief Returns the current value of the left stick's x-axis.
333 *
334 * @return float value in the range [-1, 1]
335 */
336 [[nodiscard]] float leftX() const noexcept {
337 return axisLeftX_;
338 }
339
340
341 /**
342 * @brief Returns the current value of the left stick's y-axis.
343 *
344 * @return float value in the range [-1, 1]
345 */
346 [[nodiscard]] float leftY() const noexcept {
347 return axisLeftY_;
348 }
349
350
351 /**
352 * @brief Returns the current value of the right stick's x-axis.
353 *
354 * @return float value in the range [-1, 1]
355 */
356 [[nodiscard]] float rightX() const noexcept {
357 return axisRightX_;
358 }
359
360
361 /**
362 * @brief Returns the current value of the right stick's y-axis.
363 *
364 * @return float value in the range [-1, 1]
365 */
366 [[nodiscard]] float rightY() const noexcept {
367 return axisRightY_;
368 }
369
370
371 /**
372 * @brief Returns the current value of the left trigger.
373 *
374 * @return float value in the range [0, 1]
375 */
376 [[nodiscard]] float triggerLeft() const noexcept {
377 return triggerLeft_;
378 }
379
380
381 /**
382 * @brief Returns the current value of the right trigger.
383 *
384 * @return float value in the range [0, 1]
385 */
386 [[nodiscard]] float triggerRight() const noexcept {
387 return triggerRight_;
388 }
389
390
391 /**
392 * @brief Returns the state of the left stick as a helios::math::vec2f.
393 *
394 * @return A helios::math::vec2f, with the first component being the x-axis, the second component the y-axis.
395 */
396 [[nodiscard]] helios::math::vec2f left() const noexcept {
397 if (needsUpdate_) {
398 update();
399 }
400 return left_;
401 }
402
403
404 /**
405 * @brief Returns the state of the right stick as a helios::math::vec2f.
406 *
407 * @return A helios::math::vec2f, with the first component being the x-axis, the second component the y-axis.
408 */
409 [[nodiscard]] helios::math::vec2f right() const noexcept {
410 if (needsUpdate_) {
411 update();
412 }
413 return right_;
414 }
415
416
417 /**
418 * @brief Returns the state of the triggers as a helios::math::vec2f.
419 *
420 * @return A helios::math::vec2f, with the first component being the left trigger-axis,
421 * the second component the right trigger-axis.
422 */
423 [[nodiscard]] helios::math::vec2f trigger() const noexcept {
424 if (needsUpdate_) {
425 update();
426 }
427 return trigger_;
428 }
429
430
431 /**
432 * @brief Returns true when the A button is pressed.
433 * @return true if pressed, false otherwise.
434 */
435 [[nodiscard]] bool buttonA() const noexcept {
436 return buttonA_;
437 };
438
439
440 /**
441 * @brief Returns true when the B button is pressed.
442 * @return true if pressed, false otherwise.
443 */
444 [[nodiscard]] bool buttonB() const noexcept {
445 return buttonB_;
446 };
447
448
449 /**
450 * @brief Returns true when the X button is pressed.
451 * @return true if pressed, false otherwise.
452 */
453 [[nodiscard]] bool buttonX() const noexcept {
454 return buttonX_;
455 };
456
457
458 /**
459 * @brief Returns true when the Y button is pressed.
460 * @return true if pressed, false otherwise.
461 */
462 [[nodiscard]] bool buttonY() const noexcept {
463 return buttonY_;
464 };
465
466
467 /**
468 * @brief Returns true when the Start button is pressed.
469 * @return true if pressed, false otherwise.
470 */
471 [[nodiscard]] bool buttonStart() const noexcept {
472 return buttonStart_;
473 };
474
475
476 /**
477 * @brief Returns true when the Back button is pressed.
478 * @return true if pressed, false otherwise.
479 */
480 [[nodiscard]] bool buttonBack() const noexcept {
481 return buttonBack_;
482 };
483
484
485 /**
486 * @brief Returns true when the Guide button is pressed.
487 * @return true if pressed, false otherwise.
488 */
489 [[nodiscard]] bool buttonGuide() const noexcept {
490 return buttonGuide_;
491 };
492
493
494 /**
495 * @brief Returns true when the left bumper is pressed.
496 * @return true if pressed, false otherwise.
497 */
498 [[nodiscard]] bool buttonLeftBumper() const noexcept {
499 return buttonLeftBumper_;
500 };
501
502
503 /**
504 * @brief Returns true when the right bumper is pressed.
505 * @return true if pressed, false otherwise.
506 */
507 [[nodiscard]] bool buttonRightBumper() const noexcept {
508 return buttonRightBumper_;
509 };
510
511
512 /**
513 * @brief Returns true when the left thumbstick button is pressed.
514 * @return true if pressed, false otherwise.
515 */
516 [[nodiscard]] bool buttonLeftThumb() const noexcept {
517 return buttonLeftThumb_;
518 };
519
520
521 /**
522 * @brief Returns true when the right thumbstick button is pressed.
523 * @return true if pressed, false otherwise.
524 */
525 [[nodiscard]] bool buttonRightThumb() const noexcept {
526 return buttonRightThumb_;
527 };
528
529
530 /**
531 * @brief Returns true when the D-pad Up button is pressed.
532 * @return true if pressed, false otherwise.
533 */
534 [[nodiscard]] bool buttonDpadUp() const noexcept {
535 return buttonDpadUp_;
536 };
537
538
539 /**
540 * @brief Returns true when the D-pad Right button is pressed.
541 * @return true if pressed, false otherwise.
542 */
543 [[nodiscard]] bool buttonDpadRight() const noexcept {
544 return buttonDpadRight_;
545 };
546
547
548 /**
549 * @brief Returns true when the D-pad Down button is pressed.
550 * @return true if pressed, false otherwise.
551 */
552 [[nodiscard]] bool buttonDpadDown() const noexcept {
553 return buttonDpadDown_;
554 };
555
556
557 /**
558 * @brief Returns true when the D-pad Left button is pressed.
559 * @return true if pressed, false otherwise.
560 */
561 [[nodiscard]] bool buttonDpadLeft() const noexcept {
562 return buttonDpadLeft_;
563 };
564 };
565
566
567} // namespace helios::input

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.