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