libgui 2.01
libgui is a GUI library for the GameCube, Wii, and Wii U
 
Loading...
Searching...
No Matches
OgcInputDriver.cpp
1/****************************************************************************
2 * Platform Abstraction Layer (OGC driver)
3 * Daryl Borth 2026
4 * OgcInputDriver.cpp
5 *
6 * Wii/GameCube controller management and normalization
7 ***************************************************************************/
8
9#include <gccore.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <cmath>
14#include <ogcsys.h>
15#include <unistd.h>
16#include <wiiuse/wpad.h>
17#include <ogc/conf.h>
18
19#include "OgcInputDriver.h"
20#include "../Platform.h"
21#include "../InputController.h"
22
23#ifdef HW_RVL
24#include "wii/WiiPlatform.h"
25#include "wii/wiidrc.h"
26#endif
27
28static inline float clampf(float v, float lo, float hi) {
29 return (v < lo) ? lo : (v > hi) ? hi : v;
30}
31
32/****************************************************************************
33 * Hardware Mapping Helpers
34 * Translates raw libogc hardware bits to our generic UI masks
35 ***************************************************************************/
36static uint32_t MapPADToGeneric(uint32_t pad_btns) {
37 uint32_t mask = INPUT_BTN_NONE;
38 if (pad_btns & PAD_BUTTON_A) mask |= INPUT_BTN_A;
39 if (pad_btns & PAD_BUTTON_B) mask |= INPUT_BTN_B;
40 if (pad_btns & PAD_BUTTON_X) mask |= INPUT_BTN_X;
41 if (pad_btns & PAD_BUTTON_Y) mask |= INPUT_BTN_Y;
42 if (pad_btns & PAD_BUTTON_UP) mask |= INPUT_BTN_UP;
43 if (pad_btns & PAD_BUTTON_DOWN) mask |= INPUT_BTN_DOWN;
44 if (pad_btns & PAD_BUTTON_LEFT) mask |= INPUT_BTN_LEFT;
45 if (pad_btns & PAD_BUTTON_RIGHT) mask |= INPUT_BTN_RIGHT;
46 if (pad_btns & PAD_BUTTON_START) mask |= INPUT_BTN_PLUS;
47 if (pad_btns & PAD_TRIGGER_L) mask |= INPUT_TRIGGER_L;
48 if (pad_btns & PAD_TRIGGER_R) mask |= INPUT_TRIGGER_R;
49 if (pad_btns & PAD_TRIGGER_Z) mask |= INPUT_TRIGGER_ZR;
50 return mask;
51}
52
53#ifdef HW_RVL
54static uint32_t MapWiimoteToGeneric(uint32_t wpad_btns)
55{
56 uint32_t mask = INPUT_BTN_NONE;
57
58 if (wpad_btns & WPAD_BUTTON_A) mask |= INPUT_BTN_A;
59 if (wpad_btns & WPAD_BUTTON_B) mask |= INPUT_BTN_B;
60 if (wpad_btns & WPAD_BUTTON_1) mask |= INPUT_BTN_1;
61 if (wpad_btns & WPAD_BUTTON_2) mask |= INPUT_BTN_2;
62 if (wpad_btns & WPAD_BUTTON_UP) mask |= INPUT_BTN_UP;
63 if (wpad_btns & WPAD_BUTTON_DOWN) mask |= INPUT_BTN_DOWN;
64 if (wpad_btns & WPAD_BUTTON_LEFT) mask |= INPUT_BTN_LEFT;
65 if (wpad_btns & WPAD_BUTTON_RIGHT) mask |= INPUT_BTN_RIGHT;
66 if (wpad_btns & WPAD_BUTTON_PLUS) mask |= INPUT_BTN_PLUS;
67 if (wpad_btns & WPAD_BUTTON_MINUS) mask |= INPUT_BTN_MINUS;
68 if (wpad_btns & WPAD_BUTTON_HOME) mask |= INPUT_BTN_HOME;
69
70 return mask;
71}
72
73static uint32_t MapNunchukToGeneric(uint32_t wpad_btns)
74{
75 uint32_t mask = INPUT_BTN_NONE;
76
77 if (wpad_btns & WPAD_NUNCHUK_BUTTON_Z) mask |= INPUT_TRIGGER_ZL;
78 if (wpad_btns & WPAD_NUNCHUK_BUTTON_C) mask |= INPUT_TRIGGER_L;
79
80 return mask;
81}
82
83static uint32_t MapClassicToGeneric(uint32_t wpad_btns)
84{
85 uint32_t mask = INPUT_BTN_NONE;
86
87 // Classic Controller inputs (upper 16 bits)
88 if (wpad_btns & WPAD_CLASSIC_BUTTON_A) mask |= INPUT_BTN_A;
89 if (wpad_btns & WPAD_CLASSIC_BUTTON_B) mask |= INPUT_BTN_B;
90 if (wpad_btns & WPAD_CLASSIC_BUTTON_X) mask |= INPUT_BTN_X;
91 if (wpad_btns & WPAD_CLASSIC_BUTTON_Y) mask |= INPUT_BTN_Y;
92 if (wpad_btns & WPAD_CLASSIC_BUTTON_UP) mask |= INPUT_BTN_UP;
93 if (wpad_btns & WPAD_CLASSIC_BUTTON_DOWN) mask |= INPUT_BTN_DOWN;
94 if (wpad_btns & WPAD_CLASSIC_BUTTON_LEFT) mask |= INPUT_BTN_LEFT;
95 if (wpad_btns & WPAD_CLASSIC_BUTTON_RIGHT) mask |= INPUT_BTN_RIGHT;
96 if (wpad_btns & WPAD_CLASSIC_BUTTON_PLUS) mask |= INPUT_BTN_PLUS;
97 if (wpad_btns & WPAD_CLASSIC_BUTTON_MINUS) mask |= INPUT_BTN_MINUS;
98 if (wpad_btns & WPAD_CLASSIC_BUTTON_HOME) mask |= INPUT_BTN_HOME;
99 if (wpad_btns & WPAD_CLASSIC_BUTTON_FULL_L) mask |= INPUT_TRIGGER_L;
100 if (wpad_btns & WPAD_CLASSIC_BUTTON_FULL_R) mask |= INPUT_TRIGGER_R;
101 if (wpad_btns & WPAD_CLASSIC_BUTTON_ZL) mask |= INPUT_TRIGGER_ZL;
102 if (wpad_btns & WPAD_CLASSIC_BUTTON_ZR) mask |= INPUT_TRIGGER_ZR;
103
104 return mask;
105}
106
107static uint32_t MapWiiUGamepadToGeneric(uint32_t drc_btns) {
108 uint32_t mask = INPUT_BTN_NONE;
109 if (drc_btns & WIIDRC_BUTTON_A) mask |= INPUT_BTN_A;
110 if (drc_btns & WIIDRC_BUTTON_B) mask |= INPUT_BTN_B;
111 if (drc_btns & WIIDRC_BUTTON_X) mask |= INPUT_BTN_X;
112 if (drc_btns & WIIDRC_BUTTON_Y) mask |= INPUT_BTN_Y;
113 if (drc_btns & WIIDRC_BUTTON_UP) mask |= INPUT_BTN_UP;
114 if (drc_btns & WIIDRC_BUTTON_DOWN) mask |= INPUT_BTN_DOWN;
115 if (drc_btns & WIIDRC_BUTTON_LEFT) mask |= INPUT_BTN_LEFT;
116 if (drc_btns & WIIDRC_BUTTON_RIGHT) mask |= INPUT_BTN_RIGHT;
117 if (drc_btns & WIIDRC_BUTTON_PLUS) mask |= INPUT_BTN_PLUS;
118 if (drc_btns & WIIDRC_BUTTON_MINUS) mask |= INPUT_BTN_MINUS;
119 if (drc_btns & WIIDRC_BUTTON_HOME) mask |= INPUT_BTN_HOME;
120 if (drc_btns & WIIDRC_BUTTON_L) mask |= INPUT_TRIGGER_L;
121 if (drc_btns & WIIDRC_BUTTON_R) mask |= INPUT_TRIGGER_R;
122 if (drc_btns & WIIDRC_BUTTON_ZL) mask |= INPUT_TRIGGER_ZL;
123 if (drc_btns & WIIDRC_BUTTON_ZR) mask |= INPUT_TRIGGER_ZR;
124 return mask;
125}
126
127/****************************************************************************
128 * Analog Normalization Helpers
129 ***************************************************************************/
130static float NormalizeWPADAnalog(int pos, int min, int max, int center) {
131 if (min == max) return 0.0f;
132
133 // Handle broken 3rd party controller calibration data
134 if ((min >= center) || (max <= center)) {
135 min = 0; max = 64; center = 32; // Generic fallback
136 }
137 int offset = pos - center;
138 if (offset > 0) {
139 return clampf((float)offset / (float)(max - center), 0.0f, 1.0f);
140 } else {
141 return clampf((float)offset / (float)(center - min), -1.0f, 0.0f);
142 }
143}
144#endif
145
146OgcInputDriver::OgcInputDriver() {
147 for (int i = 0; i < 4; i++) {
148 rumbleRequest[i] = continuousRumble[i] = false;
149 menuRumbleFrames[i] = continuousRumbleCount[i] = silenceFrames[i] = menuRumbleGapFrames[i] = 0;
150 }
151}
152
153OgcInputDriver::~OgcInputDriver() {
154 shutdown();
155}
156
157#ifdef HW_RVL
158static void WiimotePowerButtonCallback(s32) { NotifyWiiShutdownRequested(); }
159#endif
160
162 PAD_Init();
163
164 #ifdef HW_RVL
165 SYS_SetPowerCallback(NotifyWiiShutdownRequested);
166
167 WiiDRC_Init();
168 WPAD_Init();
169 WPAD_SetDataFormat(WPAD_CHAN_ALL, WPAD_FMT_BTNS_ACC_IR);
170 WPAD_SetVRes(WPAD_CHAN_ALL, platform->getVideo()->getScreenWidth(), platform->getVideo()->getScreenHeight());
171 WPAD_SetPowerButtonCallback(WiimotePowerButtonCallback);
172 #endif
173
174 InitUserInputControllers();
175}
176
178 for (int i = 0; i < 4; i++) {
179 #ifdef HW_RVL
180 WPAD_Rumble(i, 0);
181 #endif
182 PAD_ControlMotor(i, PAD_MOTOR_STOP);
183 rumbleRequest[i] = continuousRumble[i] = false;
184 menuRumbleFrames[i] = continuousRumbleCount[i] = silenceFrames[i] = menuRumbleGapFrames[i] = 0;
185 }
186}
187
188void OgcInputDriver::setRumble(int channel, bool rumble) {
189 if (channel >= 0 && channel < 4) {
190 rumbleRequest[channel] = rumble;
191 }
192}
193
194void OgcInputDriver::setContinuousRumble(int channel, bool continuous) {
195 if (channel >= 0 && channel < 4) continuousRumble[channel] = continuous;
196}
197
199 #ifdef HW_RVL
200 WPAD_ScanPads();
201 WiiDRC_ScanPads();
202 bool systemRumbleAllowed = (CONF_GetPadMotorMode() != 0);
203 #else
204 bool systemRumbleAllowed = true;
205 #endif
206
207 u32 activeGamecubePads = PAD_ScanPads();
208 bool allowRumble = isRumbleEnabled() && systemRumbleAllowed;
209
210 for(int i = 3; i >= 0; i--) {
211 InputPadData padData;
212
213 bool gamecubeActive = (activeGamecubePads & (1 << i)) != 0;
214
215 if(gamecubeActive) {
216 padData.hw_connected[INPUT_HW_GAMECUBE] = true;
217 padData.hw_buttons_d[INPUT_HW_GAMECUBE] = MapPADToGeneric(PAD_ButtonsDown(i));
218 padData.hw_buttons_h[INPUT_HW_GAMECUBE] = MapPADToGeneric(PAD_ButtonsHeld(i));
219 padData.hw_buttons_r[INPUT_HW_GAMECUBE] = MapPADToGeneric(PAD_ButtonsUp(i));
220 padData.hw_stickX[INPUT_HW_GAMECUBE] = clampf((float)PAD_StickX(i) / 128.0f, -1.0f, 1.0f);
221 padData.hw_stickY[INPUT_HW_GAMECUBE] = clampf((float)PAD_StickY(i) / 128.0f, -1.0f, 1.0f);
222 padData.hw_substickX[INPUT_HW_GAMECUBE] = clampf((float)PAD_SubStickX(i) / 128.0f, -1.0f, 1.0f);
223 padData.hw_substickY[INPUT_HW_GAMECUBE] = clampf((float)PAD_SubStickY(i) / 128.0f, -1.0f, 1.0f);
224 padData.hw_triggerL[INPUT_HW_GAMECUBE] = clampf((float)PAD_TriggerL(i) / 255.0f, 0.0f, 1.0f);
225 padData.hw_triggerR[INPUT_HW_GAMECUBE] = clampf((float)PAD_TriggerR(i) / 255.0f, 0.0f, 1.0f);
226 }
227
228 #ifdef HW_RVL
229 // Process Wiimote and Extensions
230 uint32_t exp_type = WPAD_EXP_NONE;
231
232 if (WPAD_Probe(i, &exp_type) == WPAD_ERR_NONE) {
233 WPADData* wpad = WPAD_Data(i);
234
235 // Always process base Wiimote
236 padData.hw_connected[INPUT_HW_WIIMOTE] = true;
237 padData.battery_level = wpad->battery_level;
238
239 padData.hw_gforceX[INPUT_HW_WIIMOTE] = wpad->gforce.x;
240 padData.hw_gforceY[INPUT_HW_WIIMOTE] = wpad->gforce.y;
241 padData.hw_gforceZ[INPUT_HW_WIIMOTE] = wpad->gforce.z;
242 padData.hw_pitch[INPUT_HW_WIIMOTE] = wpad->orient.pitch;
243 padData.hw_roll[INPUT_HW_WIIMOTE] = wpad->orient.roll;
244 padData.hw_yaw[INPUT_HW_WIIMOTE] = wpad->orient.yaw;
245
246 if (exp_type == WPAD_EXP_NONE) {
247 padData.hw_buttons_d[INPUT_HW_WIIMOTE] = MapWiimoteToGeneric(wpad->btns_d);
248 padData.hw_buttons_h[INPUT_HW_WIIMOTE] = MapWiimoteToGeneric(wpad->btns_h);
249 padData.hw_buttons_r[INPUT_HW_WIIMOTE] = MapWiimoteToGeneric(wpad->btns_u);
250
251 if (wpad->ir.valid) {
252 padData.validPointer = true;
253 padData.isTouch = false;
254 padData.cursor_x = wpad->ir.x;
255 padData.cursor_y = wpad->ir.y;
256 padData.cursor_angle = wpad->ir.angle;
257 }
258
259 controller[i]->setSideways(getWiimoteOrientation() == WIIMOTE_ORIENTATION_HORIZONTAL);
260 }
261 else if (exp_type == WPAD_EXP_NUNCHUK) {
262 padData.hw_buttons_d[INPUT_HW_WIIMOTE] = MapWiimoteToGeneric(wpad->btns_d);
263 padData.hw_buttons_h[INPUT_HW_WIIMOTE] = MapWiimoteToGeneric(wpad->btns_h);
264 padData.hw_buttons_r[INPUT_HW_WIIMOTE] = MapWiimoteToGeneric(wpad->btns_u);
265
266 padData.hw_connected[INPUT_HW_NUNCHUK] = true;
267 padData.hw_buttons_d[INPUT_HW_NUNCHUK] = MapNunchukToGeneric(wpad->btns_d);
268 padData.hw_buttons_h[INPUT_HW_NUNCHUK] = MapNunchukToGeneric(wpad->btns_h);
269 padData.hw_buttons_r[INPUT_HW_NUNCHUK] = MapNunchukToGeneric(wpad->btns_u);
270 joystick_t* js = &wpad->exp.nunchuk.js;
271 padData.hw_stickX[INPUT_HW_NUNCHUK] = NormalizeWPADAnalog(js->pos.x, js->min.x, js->max.x, js->center.x);
272 padData.hw_stickY[INPUT_HW_NUNCHUK] = NormalizeWPADAnalog(js->pos.y, js->min.y, js->max.y, js->center.y);
273
274 padData.hw_gforceX[INPUT_HW_NUNCHUK] = wpad->exp.nunchuk.gforce.x;
275 padData.hw_gforceY[INPUT_HW_NUNCHUK] = wpad->exp.nunchuk.gforce.y;
276 padData.hw_gforceZ[INPUT_HW_NUNCHUK] = wpad->exp.nunchuk.gforce.z;
277 padData.hw_pitch[INPUT_HW_NUNCHUK] = wpad->exp.nunchuk.orient.pitch;
278 padData.hw_roll[INPUT_HW_NUNCHUK] = wpad->exp.nunchuk.orient.roll;
279 padData.hw_yaw[INPUT_HW_NUNCHUK] = wpad->exp.nunchuk.orient.yaw;
280
281 // The Wiimote still points at the sensor bar with a Nunchuk in the other hand
282 if (wpad->ir.valid) {
283 padData.validPointer = true;
284 padData.isTouch = false;
285 padData.cursor_x = wpad->ir.x;
286 padData.cursor_y = wpad->ir.y;
287 padData.cursor_angle = wpad->ir.angle;
288 }
289
290 controller[i]->setSideways(false);
291 }
292 else if (exp_type == WPAD_EXP_CLASSIC) {
293 bool isWUPC = (wpad->exp.classic.type == 2);
294 int hw = isWUPC ? INPUT_HW_WUPC : INPUT_HW_CLASSIC;
295
296 padData.hw_connected[hw] = true;
297 padData.hw_buttons_d[hw] = MapClassicToGeneric(wpad->btns_d);
298 padData.hw_buttons_h[hw] = MapClassicToGeneric(wpad->btns_h);
299 padData.hw_buttons_r[hw] = MapClassicToGeneric(wpad->btns_u);
300
301 joystick_t* ljs = &wpad->exp.classic.ljs;
302 joystick_t* rjs = &wpad->exp.classic.rjs;
303 padData.hw_stickX[hw] = NormalizeWPADAnalog(ljs->pos.x, ljs->min.x, ljs->max.x, ljs->center.x);
304 padData.hw_stickY[hw] = NormalizeWPADAnalog(ljs->pos.y, ljs->min.y, ljs->max.y, ljs->center.y);
305 padData.hw_substickX[hw] = NormalizeWPADAnalog(rjs->pos.x, rjs->min.x, rjs->max.x, rjs->center.x);
306 padData.hw_substickY[hw] = NormalizeWPADAnalog(rjs->pos.y, rjs->min.y, rjs->max.y, rjs->center.y);
307 padData.hw_triggerL[hw] = clampf(wpad->exp.classic.l_shoulder, 0.0f, 1.0f);
308 padData.hw_triggerR[hw] = clampf(wpad->exp.classic.r_shoulder, 0.0f, 1.0f);
309 controller[i]->setSideways(false);
310 }
311 else {
312 controller[i]->setSideways(false);
313 }
314 }
315
316 // Process Wii U Gamepad
317 if(i == 0 && WiiDRC_Inited() && WiiDRC_Connected()) {
318 padData.hw_connected[INPUT_HW_DRC] = true;
319 padData.hw_buttons_d[INPUT_HW_DRC] = MapWiiUGamepadToGeneric(WiiDRC_ButtonsDown());
320 padData.hw_buttons_h[INPUT_HW_DRC] = MapWiiUGamepadToGeneric(WiiDRC_ButtonsHeld());
321 padData.hw_buttons_r[INPUT_HW_DRC] = MapWiiUGamepadToGeneric(WiiDRC_ButtonsUp());
322 padData.hw_stickX[INPUT_HW_DRC] = clampf((float)WiiDRC_lStickX() / 128.0f, -1.0f, 1.0f);
323 padData.hw_stickY[INPUT_HW_DRC] = clampf((float)WiiDRC_lStickY() / 128.0f, -1.0f, 1.0f);
324 padData.hw_substickX[INPUT_HW_DRC] = clampf((float)WiiDRC_rStickX() / 128.0f, -1.0f, 1.0f);
325 padData.hw_substickY[INPUT_HW_DRC] = clampf((float)WiiDRC_rStickY() / 128.0f, -1.0f, 1.0f);
326 }
327 #endif
328
329 // Merge into unified aggregate state for UI Elements
330 for (uint32_t hw = 0; hw < INPUT_HW_MAX; hw++) {
331 if (!padData.hw_connected[hw])
332 continue;
333
334 padData.buttons_d |= padData.hw_buttons_d[hw];
335 padData.buttons_h |= padData.hw_buttons_h[hw];
336 padData.buttons_r |= padData.hw_buttons_r[hw];
337
338 if (std::abs(padData.hw_stickX[hw]) > std::abs(padData.stickX)) padData.stickX = padData.hw_stickX[hw];
339 if (std::abs(padData.hw_stickY[hw]) > std::abs(padData.stickY)) padData.stickY = padData.hw_stickY[hw];
340 if (std::abs(padData.hw_substickX[hw]) > std::abs(padData.substickX)) padData.substickX = padData.hw_substickX[hw];
341 if (std::abs(padData.hw_substickY[hw]) > std::abs(padData.substickY)) padData.substickY = padData.hw_substickY[hw];
342 if (std::abs(padData.hw_gforceX[hw]) > std::abs(padData.gforceX)) padData.gforceX = padData.hw_gforceX[hw];
343 if (std::abs(padData.hw_gforceY[hw]) > std::abs(padData.gforceY)) padData.gforceY = padData.hw_gforceY[hw];
344 if (std::abs(padData.hw_gforceZ[hw]) > std::abs(padData.gforceZ)) padData.gforceZ = padData.hw_gforceZ[hw];
345 if (std::abs(padData.hw_pitch[hw]) > std::abs(padData.pitch)) padData.pitch = padData.hw_pitch[hw];
346 if (std::abs(padData.hw_roll[hw]) > std::abs(padData.roll)) padData.roll = padData.hw_roll[hw];
347 if (std::abs(padData.hw_yaw[hw]) > std::abs(padData.yaw)) padData.yaw = padData.hw_yaw[hw];
348 }
349
350 // Push the finalized, merged payload to the controller abstraction
351 controller[i]->update(padData, platform->getVideo()->getDeltaTime());
352
353 // Menu (hover) rumble: a short tick with an enforced silent gap afterward
354 static constexpr int kMenuRumbleOnFrames = 2; // ~33ms motor-on burst
355 static constexpr int kMenuRumbleGapFrames = 6; // ~100ms enforced silence after a tick
356
357 if (rumbleRequest[i]) {
358 rumbleRequest[i] = false;
359 if (menuRumbleFrames[i] == 0 && menuRumbleGapFrames[i] == 0) {
360 menuRumbleFrames[i] = kMenuRumbleOnFrames;
361 }
362 }
363
364 bool menuWantRumble = menuRumbleFrames[i] > 0;
365
366 if (menuRumbleFrames[i] > 0) {
367 menuRumbleFrames[i]--;
368 if (menuRumbleFrames[i] == 0) menuRumbleGapFrames[i] = kMenuRumbleGapFrames;
369 } else if (menuRumbleGapFrames[i] > 0) {
370 menuRumbleGapFrames[i]--;
371 }
372
373 bool wantRumble = menuWantRumble || continuousRumble[i];
374 bool motorOn = false;
375
376 // Hardware safety: never drive the motor for more than ~70 consecutive
377 // frames; force a short rest (5 frames) before it can run again.
378 if (silenceFrames[i] > 0) {
379 silenceFrames[i]--;
380 continuousRumbleCount[i] = 0;
381 } else {
382 if (wantRumble && allowRumble) {
383 continuousRumbleCount[i]++;
384 if (continuousRumbleCount[i] > 70) {
385 silenceFrames[i] = 5;
386 continuousRumbleCount[i] = 0;
387 } else {
388 motorOn = true;
389 }
390 } else {
391 continuousRumbleCount[i] = 0;
392 }
393 }
394
395 #ifdef HW_RVL
396 WPAD_Rumble(i, motorOn ? 1 : 0);
397 #endif
398
399 if (gamecubeActive) {
400 PAD_ControlMotor(i, motorOn ? PAD_MOTOR_RUMBLE : PAD_MOTOR_STOP);
401 }
402 }
403}
bool isRumbleEnabled() const
Definition InputDriver.h:42
int getWiimoteOrientation() const
Definition InputDriver.h:46
void update() override
Polls the hardware and dispatches InputPadData payloads to the UI.
void shutdown() override
Shuts the controller subsystem down.
void init() override
Initializes the controller subsystem.
void setContinuousRumble(int channel, bool continuous) override
Holds a channel's motor on (or releases it) until changed. Drivers cap an unbroken run and insert a s...
void setRumble(int channel, bool rumble) override
Requests a rumble event on the specified controller channel.
The universal input payload for UI elements.
Definition InputData.h:57
uint32_t buttons_d
Pressed this frame (down)
Definition InputData.h:61
float stickX
Left analog stick X, -1.0 to 1.0.
Definition InputData.h:64
float hw_roll[INPUT_HW_MAX]
Orientation roll, per profile.
Definition InputData.h:100
float gforceY
Accelerometer Y.
Definition InputData.h:69
uint32_t hw_buttons_d[INPUT_HW_MAX]
Buttons pressed this frame, per profile.
Definition InputData.h:86
float substickY
Right analog stick (C-Stick) Y, -1.0 to 1.0.
Definition InputData.h:67
float hw_gforceZ[INPUT_HW_MAX]
Accelerometer Z, per profile.
Definition InputData.h:98
float hw_triggerL[INPUT_HW_MAX]
Analog L trigger / shoulder, 0.0 - 1.0, per profile (GameCube, Classic, WUPC); 0 where the hardware h...
Definition InputData.h:93
float hw_triggerR[INPUT_HW_MAX]
Analog R trigger / shoulder, 0.0 - 1.0, per profile.
Definition InputData.h:94
float hw_stickY[INPUT_HW_MAX]
Left stick Y, per profile.
Definition InputData.h:90
float hw_substickX[INPUT_HW_MAX]
Right stick X, per profile.
Definition InputData.h:91
float pitch
Controller orientation pitch (Wiimote/Nunchuk)
Definition InputData.h:71
uint32_t battery_level
Controller battery level as reported by the backend.
Definition InputData.h:74
float cursor_x
Pointer X on the design canvas (Wiimote IR / GamePad touch)
Definition InputData.h:75
bool hw_connected[INPUT_HW_MAX]
Profile is connected and contributing.
Definition InputData.h:85
bool validPointer
True if the IR pointer or touch is active on screen.
Definition InputData.h:78
float cursor_angle
Pointer rotation (Wiimote roll)
Definition InputData.h:77
float yaw
Controller orientation yaw.
Definition InputData.h:73
bool isTouch
True if input is direct touch (VPad) vs IR pointer.
Definition InputData.h:79
float gforceX
Accelerometer X (Wiimote/Nunchuk/GamePad)
Definition InputData.h:68
float hw_stickX[INPUT_HW_MAX]
Left stick X, per profile.
Definition InputData.h:89
float hw_gforceY[INPUT_HW_MAX]
Accelerometer Y, per profile.
Definition InputData.h:97
float cursor_y
Pointer Y on the design canvas.
Definition InputData.h:76
float hw_gforceX[INPUT_HW_MAX]
Accelerometer X, per profile.
Definition InputData.h:96
float hw_yaw[INPUT_HW_MAX]
Orientation yaw, per profile.
Definition InputData.h:101
uint32_t hw_buttons_h[INPUT_HW_MAX]
Buttons held this frame, per profile.
Definition InputData.h:87
float substickX
Right analog stick (C-Stick) X, -1.0 to 1.0.
Definition InputData.h:66
float hw_pitch[INPUT_HW_MAX]
Orientation pitch, per profile.
Definition InputData.h:99
float roll
Controller orientation roll.
Definition InputData.h:72
float stickY
Left analog stick Y, -1.0 to 1.0.
Definition InputData.h:65
uint32_t buttons_r
Released this frame.
Definition InputData.h:63
float hw_substickY[INPUT_HW_MAX]
Right stick Y, per profile.
Definition InputData.h:92
uint32_t buttons_h
Held this frame.
Definition InputData.h:62
uint32_t hw_buttons_r[INPUT_HW_MAX]
Buttons released this frame, per profile.
Definition InputData.h:88
float gforceZ
Accelerometer Z.
Definition InputData.h:70