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