summaryrefslogtreecommitdiff
path: root/src/input_common/input_poller.cpp
diff options
context:
space:
mode:
authorGravatar Feng Chen2021-12-18 13:57:14 +0800
committerGravatar GitHub2021-12-18 13:57:14 +0800
commite49184e6069a9d791d2df3c1958f5c4b1187e124 (patch)
treeb776caf722e0be0e680f67b0ad0842628162ef1c /src/input_common/input_poller.cpp
parentImplement convert legacy to generic (diff)
parentMerge pull request #7570 from ameerj/favorites-expanded (diff)
downloadyuzu-e49184e6069a9d791d2df3c1958f5c4b1187e124.tar.gz
yuzu-e49184e6069a9d791d2df3c1958f5c4b1187e124.tar.xz
yuzu-e49184e6069a9d791d2df3c1958f5c4b1187e124.zip
Merge branch 'yuzu-emu:master' into convert_legacy
Diffstat (limited to 'src/input_common/input_poller.cpp')
-rw-r--r--src/input_common/input_poller.cpp970
1 files changed, 970 insertions, 0 deletions
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
new file mode 100644
index 000000000..7b370335f
--- /dev/null
+++ b/src/input_common/input_poller.cpp
@@ -0,0 +1,970 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included
4
5#include "common/common_types.h"
6#include "common/input.h"
7
8#include "input_common/input_engine.h"
9#include "input_common/input_poller.h"
10
11namespace InputCommon {
12
13class DummyInput final : public Common::Input::InputDevice {
14public:
15 explicit DummyInput() = default;
16};
17
18class InputFromButton final : public Common::Input::InputDevice {
19public:
20 explicit InputFromButton(PadIdentifier identifier_, int button_, bool toggle_, bool inverted_,
21 InputEngine* input_engine_)
22 : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_),
23 input_engine(input_engine_) {
24 UpdateCallback engine_callback{[this]() { OnChange(); }};
25 const InputIdentifier input_identifier{
26 .identifier = identifier,
27 .type = EngineInputType::Button,
28 .index = button,
29 .callback = engine_callback,
30 };
31 last_button_value = false;
32 callback_key = input_engine->SetCallback(input_identifier);
33 }
34
35 ~InputFromButton() override {
36 input_engine->DeleteCallback(callback_key);
37 }
38
39 Common::Input::ButtonStatus GetStatus() const {
40 return {
41 .value = input_engine->GetButton(identifier, button),
42 .inverted = inverted,
43 .toggle = toggle,
44 };
45 }
46
47 void ForceUpdate() override {
48 const Common::Input::CallbackStatus status{
49 .type = Common::Input::InputType::Button,
50 .button_status = GetStatus(),
51 };
52
53 last_button_value = status.button_status.value;
54 TriggerOnChange(status);
55 }
56
57 void OnChange() {
58 const Common::Input::CallbackStatus status{
59 .type = Common::Input::InputType::Button,
60 .button_status = GetStatus(),
61 };
62
63 if (status.button_status.value != last_button_value) {
64 last_button_value = status.button_status.value;
65 TriggerOnChange(status);
66 }
67 }
68
69private:
70 const PadIdentifier identifier;
71 const int button;
72 const bool toggle;
73 const bool inverted;
74 int callback_key;
75 bool last_button_value;
76 InputEngine* input_engine;
77};
78
79class InputFromHatButton final : public Common::Input::InputDevice {
80public:
81 explicit InputFromHatButton(PadIdentifier identifier_, int button_, u8 direction_, bool toggle_,
82 bool inverted_, InputEngine* input_engine_)
83 : identifier(identifier_), button(button_), direction(direction_), toggle(toggle_),
84 inverted(inverted_), input_engine(input_engine_) {
85 UpdateCallback engine_callback{[this]() { OnChange(); }};
86 const InputIdentifier input_identifier{
87 .identifier = identifier,
88 .type = EngineInputType::HatButton,
89 .index = button,
90 .callback = engine_callback,
91 };
92 last_button_value = false;
93 callback_key = input_engine->SetCallback(input_identifier);
94 }
95
96 ~InputFromHatButton() override {
97 input_engine->DeleteCallback(callback_key);
98 }
99
100 Common::Input::ButtonStatus GetStatus() const {
101 return {
102 .value = input_engine->GetHatButton(identifier, button, direction),
103 .inverted = inverted,
104 .toggle = toggle,
105 };
106 }
107
108 void ForceUpdate() override {
109 const Common::Input::CallbackStatus status{
110 .type = Common::Input::InputType::Button,
111 .button_status = GetStatus(),
112 };
113
114 last_button_value = status.button_status.value;
115 TriggerOnChange(status);
116 }
117
118 void OnChange() {
119 const Common::Input::CallbackStatus status{
120 .type = Common::Input::InputType::Button,
121 .button_status = GetStatus(),
122 };
123
124 if (status.button_status.value != last_button_value) {
125 last_button_value = status.button_status.value;
126 TriggerOnChange(status);
127 }
128 }
129
130private:
131 const PadIdentifier identifier;
132 const int button;
133 const u8 direction;
134 const bool toggle;
135 const bool inverted;
136 int callback_key;
137 bool last_button_value;
138 InputEngine* input_engine;
139};
140
141class InputFromStick final : public Common::Input::InputDevice {
142public:
143 explicit InputFromStick(PadIdentifier identifier_, int axis_x_, int axis_y_,
144 Common::Input::AnalogProperties properties_x_,
145 Common::Input::AnalogProperties properties_y_,
146 InputEngine* input_engine_)
147 : identifier(identifier_), axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_),
148 properties_y(properties_y_),
149 input_engine(input_engine_), invert_axis_y{input_engine_->GetEngineName() == "sdl"} {
150 UpdateCallback engine_callback{[this]() { OnChange(); }};
151 const InputIdentifier x_input_identifier{
152 .identifier = identifier,
153 .type = EngineInputType::Analog,
154 .index = axis_x,
155 .callback = engine_callback,
156 };
157 const InputIdentifier y_input_identifier{
158 .identifier = identifier,
159 .type = EngineInputType::Analog,
160 .index = axis_y,
161 .callback = engine_callback,
162 };
163 last_axis_x_value = 0.0f;
164 last_axis_y_value = 0.0f;
165 callback_key_x = input_engine->SetCallback(x_input_identifier);
166 callback_key_y = input_engine->SetCallback(y_input_identifier);
167 }
168
169 ~InputFromStick() override {
170 input_engine->DeleteCallback(callback_key_x);
171 input_engine->DeleteCallback(callback_key_y);
172 }
173
174 Common::Input::StickStatus GetStatus() const {
175 Common::Input::StickStatus status;
176 status.x = {
177 .raw_value = input_engine->GetAxis(identifier, axis_x),
178 .properties = properties_x,
179 };
180 status.y = {
181 .raw_value = input_engine->GetAxis(identifier, axis_y),
182 .properties = properties_y,
183 };
184 // This is a workaround too keep compatibility with old yuzu versions. Vertical axis is
185 // inverted on SDL compared to Nintendo
186 if (invert_axis_y) {
187 status.y.raw_value = -status.y.raw_value;
188 }
189 return status;
190 }
191
192 void ForceUpdate() override {
193 const Common::Input::CallbackStatus status{
194 .type = Common::Input::InputType::Stick,
195 .stick_status = GetStatus(),
196 };
197
198 last_axis_x_value = status.stick_status.x.raw_value;
199 last_axis_y_value = status.stick_status.y.raw_value;
200 TriggerOnChange(status);
201 }
202
203 void OnChange() {
204 const Common::Input::CallbackStatus status{
205 .type = Common::Input::InputType::Stick,
206 .stick_status = GetStatus(),
207 };
208
209 if (status.stick_status.x.raw_value != last_axis_x_value ||
210 status.stick_status.y.raw_value != last_axis_y_value) {
211 last_axis_x_value = status.stick_status.x.raw_value;
212 last_axis_y_value = status.stick_status.y.raw_value;
213 TriggerOnChange(status);
214 }
215 }
216
217private:
218 const PadIdentifier identifier;
219 const int axis_x;
220 const int axis_y;
221 const Common::Input::AnalogProperties properties_x;
222 const Common::Input::AnalogProperties properties_y;
223 int callback_key_x;
224 int callback_key_y;
225 float last_axis_x_value;
226 float last_axis_y_value;
227 InputEngine* input_engine;
228 const bool invert_axis_y;
229};
230
231class InputFromTouch final : public Common::Input::InputDevice {
232public:
233 explicit InputFromTouch(PadIdentifier identifier_, int touch_id_, int button_, bool toggle_,
234 bool inverted_, int axis_x_, int axis_y_,
235 Common::Input::AnalogProperties properties_x_,
236 Common::Input::AnalogProperties properties_y_,
237 InputEngine* input_engine_)
238 : identifier(identifier_), touch_id(touch_id_), button(button_), toggle(toggle_),
239 inverted(inverted_), axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_),
240 properties_y(properties_y_), input_engine(input_engine_) {
241 UpdateCallback engine_callback{[this]() { OnChange(); }};
242 const InputIdentifier button_input_identifier{
243 .identifier = identifier,
244 .type = EngineInputType::Button,
245 .index = button,
246 .callback = engine_callback,
247 };
248 const InputIdentifier x_input_identifier{
249 .identifier = identifier,
250 .type = EngineInputType::Analog,
251 .index = axis_x,
252 .callback = engine_callback,
253 };
254 const InputIdentifier y_input_identifier{
255 .identifier = identifier,
256 .type = EngineInputType::Analog,
257 .index = axis_y,
258 .callback = engine_callback,
259 };
260 last_axis_x_value = 0.0f;
261 last_axis_y_value = 0.0f;
262 last_button_value = false;
263 callback_key_button = input_engine->SetCallback(button_input_identifier);
264 callback_key_x = input_engine->SetCallback(x_input_identifier);
265 callback_key_y = input_engine->SetCallback(y_input_identifier);
266 }
267
268 ~InputFromTouch() override {
269 input_engine->DeleteCallback(callback_key_button);
270 input_engine->DeleteCallback(callback_key_x);
271 input_engine->DeleteCallback(callback_key_y);
272 }
273
274 Common::Input::TouchStatus GetStatus() const {
275 Common::Input::TouchStatus status;
276 status.id = touch_id;
277 status.pressed = {
278 .value = input_engine->GetButton(identifier, button),
279 .inverted = inverted,
280 .toggle = toggle,
281 };
282 status.x = {
283 .raw_value = input_engine->GetAxis(identifier, axis_x),
284 .properties = properties_x,
285 };
286 status.y = {
287 .raw_value = input_engine->GetAxis(identifier, axis_y),
288 .properties = properties_y,
289 };
290 return status;
291 }
292
293 void OnChange() {
294 const Common::Input::CallbackStatus status{
295 .type = Common::Input::InputType::Touch,
296 .touch_status = GetStatus(),
297 };
298
299 if (status.touch_status.x.raw_value != last_axis_x_value ||
300 status.touch_status.y.raw_value != last_axis_y_value ||
301 status.touch_status.pressed.value != last_button_value) {
302 last_axis_x_value = status.touch_status.x.raw_value;
303 last_axis_y_value = status.touch_status.y.raw_value;
304 last_button_value = status.touch_status.pressed.value;
305 TriggerOnChange(status);
306 }
307 }
308
309private:
310 const PadIdentifier identifier;
311 const int touch_id;
312 const int button;
313 const bool toggle;
314 const bool inverted;
315 const int axis_x;
316 const int axis_y;
317 const Common::Input::AnalogProperties properties_x;
318 const Common::Input::AnalogProperties properties_y;
319 int callback_key_button;
320 int callback_key_x;
321 int callback_key_y;
322 bool last_button_value;
323 float last_axis_x_value;
324 float last_axis_y_value;
325 InputEngine* input_engine;
326};
327
328class InputFromTrigger final : public Common::Input::InputDevice {
329public:
330 explicit InputFromTrigger(PadIdentifier identifier_, int button_, bool toggle_, bool inverted_,
331 int axis_, Common::Input::AnalogProperties properties_,
332 InputEngine* input_engine_)
333 : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_),
334 axis(axis_), properties(properties_), input_engine(input_engine_) {
335 UpdateCallback engine_callback{[this]() { OnChange(); }};
336 const InputIdentifier button_input_identifier{
337 .identifier = identifier,
338 .type = EngineInputType::Button,
339 .index = button,
340 .callback = engine_callback,
341 };
342 const InputIdentifier axis_input_identifier{
343 .identifier = identifier,
344 .type = EngineInputType::Analog,
345 .index = axis,
346 .callback = engine_callback,
347 };
348 last_axis_value = 0.0f;
349 last_button_value = false;
350 callback_key_button = input_engine->SetCallback(button_input_identifier);
351 axis_callback_key = input_engine->SetCallback(axis_input_identifier);
352 }
353
354 ~InputFromTrigger() override {
355 input_engine->DeleteCallback(callback_key_button);
356 input_engine->DeleteCallback(axis_callback_key);
357 }
358
359 Common::Input::TriggerStatus GetStatus() const {
360 const Common::Input::AnalogStatus analog_status{
361 .raw_value = input_engine->GetAxis(identifier, axis),
362 .properties = properties,
363 };
364 const Common::Input::ButtonStatus button_status{
365 .value = input_engine->GetButton(identifier, button),
366 .inverted = inverted,
367 .toggle = toggle,
368 };
369 return {
370 .analog = analog_status,
371 .pressed = button_status,
372 };
373 }
374
375 void OnChange() {
376 const Common::Input::CallbackStatus status{
377 .type = Common::Input::InputType::Trigger,
378 .trigger_status = GetStatus(),
379 };
380
381 if (status.trigger_status.analog.raw_value != last_axis_value ||
382 status.trigger_status.pressed.value != last_button_value) {
383 last_axis_value = status.trigger_status.analog.raw_value;
384 last_button_value = status.trigger_status.pressed.value;
385 TriggerOnChange(status);
386 }
387 }
388
389private:
390 const PadIdentifier identifier;
391 const int button;
392 const bool toggle;
393 const bool inverted;
394 const int axis;
395 const Common::Input::AnalogProperties properties;
396 int callback_key_button;
397 int axis_callback_key;
398 bool last_button_value;
399 float last_axis_value;
400 InputEngine* input_engine;
401};
402
403class InputFromAnalog final : public Common::Input::InputDevice {
404public:
405 explicit InputFromAnalog(PadIdentifier identifier_, int axis_,
406 Common::Input::AnalogProperties properties_,
407 InputEngine* input_engine_)
408 : identifier(identifier_), axis(axis_), properties(properties_),
409 input_engine(input_engine_) {
410 UpdateCallback engine_callback{[this]() { OnChange(); }};
411 const InputIdentifier input_identifier{
412 .identifier = identifier,
413 .type = EngineInputType::Analog,
414 .index = axis,
415 .callback = engine_callback,
416 };
417 last_axis_value = 0.0f;
418 callback_key = input_engine->SetCallback(input_identifier);
419 }
420
421 ~InputFromAnalog() override {
422 input_engine->DeleteCallback(callback_key);
423 }
424
425 Common::Input::AnalogStatus GetStatus() const {
426 return {
427 .raw_value = input_engine->GetAxis(identifier, axis),
428 .properties = properties,
429 };
430 }
431
432 void OnChange() {
433 const Common::Input::CallbackStatus status{
434 .type = Common::Input::InputType::Analog,
435 .analog_status = GetStatus(),
436 };
437
438 if (status.analog_status.raw_value != last_axis_value) {
439 last_axis_value = status.analog_status.raw_value;
440 TriggerOnChange(status);
441 }
442 }
443
444private:
445 const PadIdentifier identifier;
446 const int axis;
447 const Common::Input::AnalogProperties properties;
448 int callback_key;
449 float last_axis_value;
450 InputEngine* input_engine;
451};
452
453class InputFromBattery final : public Common::Input::InputDevice {
454public:
455 explicit InputFromBattery(PadIdentifier identifier_, InputEngine* input_engine_)
456 : identifier(identifier_), input_engine(input_engine_) {
457 UpdateCallback engine_callback{[this]() { OnChange(); }};
458 const InputIdentifier input_identifier{
459 .identifier = identifier,
460 .type = EngineInputType::Battery,
461 .index = 0,
462 .callback = engine_callback,
463 };
464 last_battery_value = Common::Input::BatteryStatus::Charging;
465 callback_key = input_engine->SetCallback(input_identifier);
466 }
467
468 ~InputFromBattery() override {
469 input_engine->DeleteCallback(callback_key);
470 }
471
472 Common::Input::BatteryStatus GetStatus() const {
473 return static_cast<Common::Input::BatteryLevel>(input_engine->GetBattery(identifier));
474 }
475
476 void ForceUpdate() override {
477 const Common::Input::CallbackStatus status{
478 .type = Common::Input::InputType::Battery,
479 .battery_status = GetStatus(),
480 };
481
482 last_battery_value = status.battery_status;
483 TriggerOnChange(status);
484 }
485
486 void OnChange() {
487 const Common::Input::CallbackStatus status{
488 .type = Common::Input::InputType::Battery,
489 .battery_status = GetStatus(),
490 };
491
492 if (status.battery_status != last_battery_value) {
493 last_battery_value = status.battery_status;
494 TriggerOnChange(status);
495 }
496 }
497
498private:
499 const PadIdentifier identifier;
500 int callback_key;
501 Common::Input::BatteryStatus last_battery_value;
502 InputEngine* input_engine;
503};
504
505class InputFromMotion final : public Common::Input::InputDevice {
506public:
507 explicit InputFromMotion(PadIdentifier identifier_, int motion_sensor_,
508 InputEngine* input_engine_)
509 : identifier(identifier_), motion_sensor(motion_sensor_), input_engine(input_engine_) {
510 UpdateCallback engine_callback{[this]() { OnChange(); }};
511 const InputIdentifier input_identifier{
512 .identifier = identifier,
513 .type = EngineInputType::Motion,
514 .index = motion_sensor,
515 .callback = engine_callback,
516 };
517 callback_key = input_engine->SetCallback(input_identifier);
518 }
519
520 ~InputFromMotion() override {
521 input_engine->DeleteCallback(callback_key);
522 }
523
524 Common::Input::MotionStatus GetStatus() const {
525 const auto basic_motion = input_engine->GetMotion(identifier, motion_sensor);
526 Common::Input::MotionStatus status{};
527 const Common::Input::AnalogProperties properties = {
528 .deadzone = 0.001f,
529 .range = 1.0f,
530 .offset = 0.0f,
531 };
532 status.accel.x = {.raw_value = basic_motion.accel_x, .properties = properties};
533 status.accel.y = {.raw_value = basic_motion.accel_y, .properties = properties};
534 status.accel.z = {.raw_value = basic_motion.accel_z, .properties = properties};
535 status.gyro.x = {.raw_value = basic_motion.gyro_x, .properties = properties};
536 status.gyro.y = {.raw_value = basic_motion.gyro_y, .properties = properties};
537 status.gyro.z = {.raw_value = basic_motion.gyro_z, .properties = properties};
538 status.delta_timestamp = basic_motion.delta_timestamp;
539 return status;
540 }
541
542 void OnChange() {
543 const Common::Input::CallbackStatus status{
544 .type = Common::Input::InputType::Motion,
545 .motion_status = GetStatus(),
546 };
547
548 TriggerOnChange(status);
549 }
550
551private:
552 const PadIdentifier identifier;
553 const int motion_sensor;
554 int callback_key;
555 InputEngine* input_engine;
556};
557
558class InputFromAxisMotion final : public Common::Input::InputDevice {
559public:
560 explicit InputFromAxisMotion(PadIdentifier identifier_, int axis_x_, int axis_y_, int axis_z_,
561 Common::Input::AnalogProperties properties_x_,
562 Common::Input::AnalogProperties properties_y_,
563 Common::Input::AnalogProperties properties_z_,
564 InputEngine* input_engine_)
565 : identifier(identifier_), axis_x(axis_x_), axis_y(axis_y_), axis_z(axis_z_),
566 properties_x(properties_x_), properties_y(properties_y_), properties_z(properties_z_),
567 input_engine(input_engine_) {
568 UpdateCallback engine_callback{[this]() { OnChange(); }};
569 const InputIdentifier x_input_identifier{
570 .identifier = identifier,
571 .type = EngineInputType::Analog,
572 .index = axis_x,
573 .callback = engine_callback,
574 };
575 const InputIdentifier y_input_identifier{
576 .identifier = identifier,
577 .type = EngineInputType::Analog,
578 .index = axis_y,
579 .callback = engine_callback,
580 };
581 const InputIdentifier z_input_identifier{
582 .identifier = identifier,
583 .type = EngineInputType::Analog,
584 .index = axis_z,
585 .callback = engine_callback,
586 };
587 last_axis_x_value = 0.0f;
588 last_axis_y_value = 0.0f;
589 last_axis_z_value = 0.0f;
590 callback_key_x = input_engine->SetCallback(x_input_identifier);
591 callback_key_y = input_engine->SetCallback(y_input_identifier);
592 callback_key_z = input_engine->SetCallback(z_input_identifier);
593 }
594
595 ~InputFromAxisMotion() override {
596 input_engine->DeleteCallback(callback_key_x);
597 input_engine->DeleteCallback(callback_key_y);
598 input_engine->DeleteCallback(callback_key_z);
599 }
600
601 Common::Input::MotionStatus GetStatus() const {
602 Common::Input::MotionStatus status{};
603 status.gyro.x = {
604 .raw_value = input_engine->GetAxis(identifier, axis_x),
605 .properties = properties_x,
606 };
607 status.gyro.y = {
608 .raw_value = input_engine->GetAxis(identifier, axis_y),
609 .properties = properties_y,
610 };
611 status.gyro.z = {
612 .raw_value = input_engine->GetAxis(identifier, axis_z),
613 .properties = properties_z,
614 };
615 status.delta_timestamp = 5000;
616 status.force_update = true;
617 return status;
618 }
619
620 void ForceUpdate() override {
621 const Common::Input::CallbackStatus status{
622 .type = Common::Input::InputType::Motion,
623 .motion_status = GetStatus(),
624 };
625
626 last_axis_x_value = status.motion_status.gyro.x.raw_value;
627 last_axis_y_value = status.motion_status.gyro.y.raw_value;
628 last_axis_z_value = status.motion_status.gyro.z.raw_value;
629 TriggerOnChange(status);
630 }
631
632 void OnChange() {
633 const Common::Input::CallbackStatus status{
634 .type = Common::Input::InputType::Motion,
635 .motion_status = GetStatus(),
636 };
637
638 if (status.motion_status.gyro.x.raw_value != last_axis_x_value ||
639 status.motion_status.gyro.y.raw_value != last_axis_y_value ||
640 status.motion_status.gyro.z.raw_value != last_axis_z_value) {
641 last_axis_x_value = status.motion_status.gyro.x.raw_value;
642 last_axis_y_value = status.motion_status.gyro.y.raw_value;
643 last_axis_z_value = status.motion_status.gyro.z.raw_value;
644 TriggerOnChange(status);
645 }
646 }
647
648private:
649 const PadIdentifier identifier;
650 const int axis_x;
651 const int axis_y;
652 const int axis_z;
653 const Common::Input::AnalogProperties properties_x;
654 const Common::Input::AnalogProperties properties_y;
655 const Common::Input::AnalogProperties properties_z;
656 int callback_key_x;
657 int callback_key_y;
658 int callback_key_z;
659 float last_axis_x_value;
660 float last_axis_y_value;
661 float last_axis_z_value;
662 InputEngine* input_engine;
663};
664
665class OutputFromIdentifier final : public Common::Input::OutputDevice {
666public:
667 explicit OutputFromIdentifier(PadIdentifier identifier_, InputEngine* input_engine_)
668 : identifier(identifier_), input_engine(input_engine_) {}
669
670 void SetLED(const Common::Input::LedStatus& led_status) override {
671 input_engine->SetLeds(identifier, led_status);
672 }
673
674 Common::Input::VibrationError SetVibration(
675 const Common::Input::VibrationStatus& vibration_status) override {
676 return input_engine->SetRumble(identifier, vibration_status);
677 }
678
679 Common::Input::PollingError SetPollingMode(Common::Input::PollingMode polling_mode) override {
680 return input_engine->SetPollingMode(identifier, polling_mode);
681 }
682
683private:
684 const PadIdentifier identifier;
685 InputEngine* input_engine;
686};
687
688std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateButtonDevice(
689 const Common::ParamPackage& params) {
690 const PadIdentifier identifier = {
691 .guid = Common::UUID{params.Get("guid", "")},
692 .port = static_cast<std::size_t>(params.Get("port", 0)),
693 .pad = static_cast<std::size_t>(params.Get("pad", 0)),
694 };
695
696 const auto button_id = params.Get("button", 0);
697 const auto keyboard_key = params.Get("code", 0);
698 const auto toggle = params.Get("toggle", false);
699 const auto inverted = params.Get("inverted", false);
700 input_engine->PreSetController(identifier);
701 input_engine->PreSetButton(identifier, button_id);
702 input_engine->PreSetButton(identifier, keyboard_key);
703 if (keyboard_key != 0) {
704 return std::make_unique<InputFromButton>(identifier, keyboard_key, toggle, inverted,
705 input_engine.get());
706 }
707 return std::make_unique<InputFromButton>(identifier, button_id, toggle, inverted,
708 input_engine.get());
709}
710
711std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateHatButtonDevice(
712 const Common::ParamPackage& params) {
713 const PadIdentifier identifier = {
714 .guid = Common::UUID{params.Get("guid", "")},
715 .port = static_cast<std::size_t>(params.Get("port", 0)),
716 .pad = static_cast<std::size_t>(params.Get("pad", 0)),
717 };
718
719 const auto button_id = params.Get("hat", 0);
720 const auto direction = input_engine->GetHatButtonId(params.Get("direction", ""));
721 const auto toggle = params.Get("toggle", false);
722 const auto inverted = params.Get("inverted", false);
723
724 input_engine->PreSetController(identifier);
725 input_engine->PreSetHatButton(identifier, button_id);
726 return std::make_unique<InputFromHatButton>(identifier, button_id, direction, toggle, inverted,
727 input_engine.get());
728}
729
730std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateStickDevice(
731 const Common::ParamPackage& params) {
732 const auto deadzone = std::clamp(params.Get("deadzone", 0.15f), 0.0f, 1.0f);
733 const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f);
734 const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f);
735 const PadIdentifier identifier = {
736 .guid = Common::UUID{params.Get("guid", "")},
737 .port = static_cast<std::size_t>(params.Get("port", 0)),
738 .pad = static_cast<std::size_t>(params.Get("pad", 0)),
739 };
740
741 const auto axis_x = params.Get("axis_x", 0);
742 const Common::Input::AnalogProperties properties_x = {
743 .deadzone = deadzone,
744 .range = range,
745 .threshold = threshold,
746 .offset = std::clamp(params.Get("offset_x", 0.0f), -1.0f, 1.0f),
747 .inverted = params.Get("invert_x", "+") == "-",
748 };
749
750 const auto axis_y = params.Get("axis_y", 1);
751 const Common::Input::AnalogProperties properties_y = {
752 .deadzone = deadzone,
753 .range = range,
754 .threshold = threshold,
755 .offset = std::clamp(params.Get("offset_y", 0.0f), -1.0f, 1.0f),
756 .inverted = params.Get("invert_y", "+") != "+",
757 };
758 input_engine->PreSetController(identifier);
759 input_engine->PreSetAxis(identifier, axis_x);
760 input_engine->PreSetAxis(identifier, axis_y);
761 return std::make_unique<InputFromStick>(identifier, axis_x, axis_y, properties_x, properties_y,
762 input_engine.get());
763}
764
765std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateAnalogDevice(
766 const Common::ParamPackage& params) {
767 const PadIdentifier identifier = {
768 .guid = Common::UUID{params.Get("guid", "")},
769 .port = static_cast<std::size_t>(params.Get("port", 0)),
770 .pad = static_cast<std::size_t>(params.Get("pad", 0)),
771 };
772
773 const auto axis = params.Get("axis", 0);
774 const Common::Input::AnalogProperties properties = {
775 .deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f),
776 .range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f),
777 .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f),
778 .offset = std::clamp(params.Get("offset", 0.0f), -1.0f, 1.0f),
779 .inverted = params.Get("invert", "+") == "-",
780 };
781 input_engine->PreSetController(identifier);
782 input_engine->PreSetAxis(identifier, axis);
783 return std::make_unique<InputFromAnalog>(identifier, axis, properties, input_engine.get());
784}
785
786std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTriggerDevice(
787 const Common::ParamPackage& params) {
788 const PadIdentifier identifier = {
789 .guid = Common::UUID{params.Get("guid", "")},
790 .port = static_cast<std::size_t>(params.Get("port", 0)),
791 .pad = static_cast<std::size_t>(params.Get("pad", 0)),
792 };
793
794 const auto button = params.Get("button", 0);
795 const auto toggle = params.Get("toggle", false);
796 const auto inverted = params.Get("inverted", false);
797
798 const auto axis = params.Get("axis", 0);
799 const Common::Input::AnalogProperties properties = {
800 .deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f),
801 .range = std::clamp(params.Get("range", 1.0f), 0.25f, 2.50f),
802 .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f),
803 .offset = std::clamp(params.Get("offset", 0.0f), -1.0f, 1.0f),
804 .inverted = params.Get("invert", false) != 0,
805 };
806 input_engine->PreSetController(identifier);
807 input_engine->PreSetAxis(identifier, axis);
808 input_engine->PreSetButton(identifier, button);
809 return std::make_unique<InputFromTrigger>(identifier, button, toggle, inverted, axis,
810 properties, input_engine.get());
811}
812
813std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTouchDevice(
814 const Common::ParamPackage& params) {
815 const auto touch_id = params.Get("touch_id", 0);
816 const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
817 const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f);
818 const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f);
819 const PadIdentifier identifier = {
820 .guid = Common::UUID{params.Get("guid", "")},
821 .port = static_cast<std::size_t>(params.Get("port", 0)),
822 .pad = static_cast<std::size_t>(params.Get("pad", 0)),
823 };
824
825 const auto button = params.Get("button", 0);
826 const auto toggle = params.Get("toggle", false);
827 const auto inverted = params.Get("inverted", false);
828
829 const auto axis_x = params.Get("axis_x", 0);
830 const Common::Input::AnalogProperties properties_x = {
831 .deadzone = deadzone,
832 .range = range,
833 .threshold = threshold,
834 .offset = std::clamp(params.Get("offset_x", 0.0f), -1.0f, 1.0f),
835 .inverted = params.Get("invert_x", "+") == "-",
836 };
837
838 const auto axis_y = params.Get("axis_y", 1);
839 const Common::Input::AnalogProperties properties_y = {
840 .deadzone = deadzone,
841 .range = range,
842 .threshold = threshold,
843 .offset = std::clamp(params.Get("offset_y", 0.0f), -1.0f, 1.0f),
844 .inverted = params.Get("invert_y", false) != 0,
845 };
846 input_engine->PreSetController(identifier);
847 input_engine->PreSetAxis(identifier, axis_x);
848 input_engine->PreSetAxis(identifier, axis_y);
849 input_engine->PreSetButton(identifier, button);
850 return std::make_unique<InputFromTouch>(identifier, touch_id, button, toggle, inverted, axis_x,
851 axis_y, properties_x, properties_y, input_engine.get());
852}
853
854std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateBatteryDevice(
855 const Common::ParamPackage& params) {
856 const PadIdentifier identifier = {
857 .guid = Common::UUID{params.Get("guid", "")},
858 .port = static_cast<std::size_t>(params.Get("port", 0)),
859 .pad = static_cast<std::size_t>(params.Get("pad", 0)),
860 };
861
862 input_engine->PreSetController(identifier);
863 return std::make_unique<InputFromBattery>(identifier, input_engine.get());
864}
865
866std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateMotionDevice(
867 Common::ParamPackage params) {
868 const PadIdentifier identifier = {
869 .guid = Common::UUID{params.Get("guid", "")},
870 .port = static_cast<std::size_t>(params.Get("port", 0)),
871 .pad = static_cast<std::size_t>(params.Get("pad", 0)),
872 };
873
874 if (params.Has("motion")) {
875 const auto motion_sensor = params.Get("motion", 0);
876 input_engine->PreSetController(identifier);
877 input_engine->PreSetMotion(identifier, motion_sensor);
878 return std::make_unique<InputFromMotion>(identifier, motion_sensor, input_engine.get());
879 }
880
881 const auto deadzone = std::clamp(params.Get("deadzone", 0.15f), 0.0f, 1.0f);
882 const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f);
883 const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f);
884
885 const auto axis_x = params.Get("axis_x", 0);
886 const Common::Input::AnalogProperties properties_x = {
887 .deadzone = deadzone,
888 .range = range,
889 .threshold = threshold,
890 .offset = std::clamp(params.Get("offset_x", 0.0f), -1.0f, 1.0f),
891 .inverted = params.Get("invert_x", "+") == "-",
892 };
893
894 const auto axis_y = params.Get("axis_y", 1);
895 const Common::Input::AnalogProperties properties_y = {
896 .deadzone = deadzone,
897 .range = range,
898 .threshold = threshold,
899 .offset = std::clamp(params.Get("offset_y", 0.0f), -1.0f, 1.0f),
900 .inverted = params.Get("invert_y", "+") != "+",
901 };
902
903 const auto axis_z = params.Get("axis_z", 1);
904 const Common::Input::AnalogProperties properties_z = {
905 .deadzone = deadzone,
906 .range = range,
907 .threshold = threshold,
908 .offset = std::clamp(params.Get("offset_z", 0.0f), -1.0f, 1.0f),
909 .inverted = params.Get("invert_z", "+") != "+",
910 };
911 input_engine->PreSetController(identifier);
912 input_engine->PreSetAxis(identifier, axis_x);
913 input_engine->PreSetAxis(identifier, axis_y);
914 input_engine->PreSetAxis(identifier, axis_z);
915 return std::make_unique<InputFromAxisMotion>(identifier, axis_x, axis_y, axis_z, properties_x,
916 properties_y, properties_z, input_engine.get());
917}
918
919InputFactory::InputFactory(std::shared_ptr<InputEngine> input_engine_)
920 : input_engine(std::move(input_engine_)) {}
921
922std::unique_ptr<Common::Input::InputDevice> InputFactory::Create(
923 const Common::ParamPackage& params) {
924 if (params.Has("battery")) {
925 return CreateBatteryDevice(params);
926 }
927 if (params.Has("button") && params.Has("axis")) {
928 return CreateTriggerDevice(params);
929 }
930 if (params.Has("button") && params.Has("axis_x") && params.Has("axis_y")) {
931 return CreateTouchDevice(params);
932 }
933 if (params.Has("button") || params.Has("code")) {
934 return CreateButtonDevice(params);
935 }
936 if (params.Has("hat")) {
937 return CreateHatButtonDevice(params);
938 }
939 if (params.Has("axis_x") && params.Has("axis_y") && params.Has("axis_z")) {
940 return CreateMotionDevice(params);
941 }
942 if (params.Has("motion")) {
943 return CreateMotionDevice(params);
944 }
945 if (params.Has("axis_x") && params.Has("axis_y")) {
946 return CreateStickDevice(params);
947 }
948 if (params.Has("axis")) {
949 return CreateAnalogDevice(params);
950 }
951 LOG_ERROR(Input, "Invalid parameters given");
952 return std::make_unique<DummyInput>();
953}
954
955OutputFactory::OutputFactory(std::shared_ptr<InputEngine> input_engine_)
956 : input_engine(std::move(input_engine_)) {}
957
958std::unique_ptr<Common::Input::OutputDevice> OutputFactory::Create(
959 const Common::ParamPackage& params) {
960 const PadIdentifier identifier = {
961 .guid = Common::UUID{params.Get("guid", "")},
962 .port = static_cast<std::size_t>(params.Get("port", 0)),
963 .pad = static_cast<std::size_t>(params.Get("pad", 0)),
964 };
965
966 input_engine->PreSetController(identifier);
967 return std::make_unique<OutputFromIdentifier>(identifier, input_engine.get());
968}
969
970} // namespace InputCommon