summaryrefslogtreecommitdiff
path: root/src/input_common/input_mapping.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/input_mapping.cpp')
-rw-r--r--src/input_common/input_mapping.cpp207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/input_common/input_mapping.cpp b/src/input_common/input_mapping.cpp
new file mode 100644
index 000000000..6e0024b2d
--- /dev/null
+++ b/src/input_common/input_mapping.cpp
@@ -0,0 +1,207 @@
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/settings.h"
7#include "input_common/input_engine.h"
8#include "input_common/input_mapping.h"
9
10namespace InputCommon {
11
12MappingFactory::MappingFactory() {}
13
14void MappingFactory::BeginMapping(Polling::InputType type) {
15 is_enabled = true;
16 input_type = type;
17 input_queue.Clear();
18 first_axis = -1;
19 second_axis = -1;
20}
21
22[[nodiscard]] const Common::ParamPackage MappingFactory::GetNextInput() {
23 Common::ParamPackage input;
24 input_queue.Pop(input);
25 return input;
26}
27
28void MappingFactory::RegisterInput(const MappingData& data) {
29 if (!is_enabled) {
30 return;
31 }
32 if (!IsDriverValid(data)) {
33 return;
34 }
35
36 switch (input_type) {
37 case Polling::InputType::Button:
38 RegisterButton(data);
39 return;
40 case Polling::InputType::Stick:
41 RegisterStick(data);
42 return;
43 case Polling::InputType::Motion:
44 RegisterMotion(data);
45 return;
46 default:
47 return;
48 }
49}
50
51void MappingFactory::StopMapping() {
52 is_enabled = false;
53 input_type = Polling::InputType::None;
54 input_queue.Clear();
55}
56
57void MappingFactory::RegisterButton(const MappingData& data) {
58 Common::ParamPackage new_input;
59 new_input.Set("engine", data.engine);
60 if (data.pad.guid != Common::UUID{}) {
61 new_input.Set("guid", data.pad.guid.Format());
62 }
63 new_input.Set("port", static_cast<int>(data.pad.port));
64 new_input.Set("pad", static_cast<int>(data.pad.pad));
65
66 switch (data.type) {
67 case EngineInputType::Button:
68 // Workaround for old compatibility
69 if (data.engine == "keyboard") {
70 new_input.Set("code", data.index);
71 break;
72 }
73 new_input.Set("button", data.index);
74 break;
75 case EngineInputType::HatButton:
76 new_input.Set("hat", data.index);
77 new_input.Set("direction", data.hat_name);
78 break;
79 case EngineInputType::Analog:
80 // Ignore mouse axis when mapping buttons
81 if (data.engine == "mouse") {
82 return;
83 }
84 new_input.Set("axis", data.index);
85 new_input.Set("threshold", 0.5f);
86 break;
87 default:
88 return;
89 }
90 input_queue.Push(new_input);
91}
92
93void MappingFactory::RegisterStick(const MappingData& data) {
94 Common::ParamPackage new_input;
95 new_input.Set("engine", data.engine);
96 if (data.pad.guid != Common::UUID{}) {
97 new_input.Set("guid", data.pad.guid.Format());
98 }
99 new_input.Set("port", static_cast<int>(data.pad.port));
100 new_input.Set("pad", static_cast<int>(data.pad.pad));
101
102 // If engine is mouse map the mouse position as a joystick
103 if (data.engine == "mouse") {
104 new_input.Set("axis_x", 0);
105 new_input.Set("axis_y", 1);
106 new_input.Set("threshold", 0.5f);
107 new_input.Set("range", 1.0f);
108 new_input.Set("deadzone", 0.0f);
109 input_queue.Push(new_input);
110 return;
111 }
112
113 switch (data.type) {
114 case EngineInputType::Button:
115 case EngineInputType::HatButton:
116 RegisterButton(data);
117 return;
118 case EngineInputType::Analog:
119 if (first_axis == data.index) {
120 return;
121 }
122 if (first_axis == -1) {
123 first_axis = data.index;
124 return;
125 }
126 new_input.Set("axis_x", first_axis);
127 new_input.Set("axis_y", data.index);
128 new_input.Set("threshold", 0.5f);
129 new_input.Set("range", 0.95f);
130 new_input.Set("deadzone", 0.15f);
131 break;
132 default:
133 return;
134 }
135 input_queue.Push(new_input);
136}
137
138void MappingFactory::RegisterMotion(const MappingData& data) {
139 Common::ParamPackage new_input;
140 new_input.Set("engine", data.engine);
141 if (data.pad.guid != Common::UUID{}) {
142 new_input.Set("guid", data.pad.guid.Format());
143 }
144 new_input.Set("port", static_cast<int>(data.pad.port));
145 new_input.Set("pad", static_cast<int>(data.pad.pad));
146 switch (data.type) {
147 case EngineInputType::Button:
148 case EngineInputType::HatButton:
149 RegisterButton(data);
150 return;
151 case EngineInputType::Analog:
152 if (first_axis == data.index) {
153 return;
154 }
155 if (second_axis == data.index) {
156 return;
157 }
158 if (first_axis == -1) {
159 first_axis = data.index;
160 return;
161 }
162 if (second_axis == -1) {
163 second_axis = data.index;
164 return;
165 }
166 new_input.Set("axis_x", first_axis);
167 new_input.Set("axis_y", second_axis);
168 new_input.Set("axis_z", data.index);
169 new_input.Set("range", 1.0f);
170 new_input.Set("deadzone", 0.20f);
171 break;
172 case EngineInputType::Motion:
173 new_input.Set("motion", data.index);
174 break;
175 default:
176 return;
177 }
178 input_queue.Push(new_input);
179}
180
181bool MappingFactory::IsDriverValid(const MappingData& data) const {
182 // Only port 0 can be mapped on the keyboard
183 if (data.engine == "keyboard" && data.pad.port != 0) {
184 return false;
185 }
186 // To prevent mapping with two devices we disable any UDP except motion
187 if (!Settings::values.enable_udp_controller && data.engine == "cemuhookudp" &&
188 data.type != EngineInputType::Motion) {
189 return false;
190 }
191 // The following drivers don't need to be mapped
192 if (data.engine == "tas") {
193 return false;
194 }
195 if (data.engine == "touch") {
196 return false;
197 }
198 if (data.engine == "touch_from_button") {
199 return false;
200 }
201 if (data.engine == "analog_from_button") {
202 return false;
203 }
204 return true;
205}
206
207} // namespace InputCommon