summaryrefslogtreecommitdiff
path: root/src/input_common/input_engine.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_engine.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_engine.cpp')
-rw-r--r--src/input_common/input_engine.cpp362
1 files changed, 362 insertions, 0 deletions
diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp
new file mode 100644
index 000000000..9c17ca4f7
--- /dev/null
+++ b/src/input_common/input_engine.cpp
@@ -0,0 +1,362 @@
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/logging/log.h"
6#include "common/param_package.h"
7#include "input_common/input_engine.h"
8
9namespace InputCommon {
10
11void InputEngine::PreSetController(const PadIdentifier& identifier) {
12 std::lock_guard lock{mutex};
13 controller_list.try_emplace(identifier);
14}
15
16void InputEngine::PreSetButton(const PadIdentifier& identifier, int button) {
17 std::lock_guard lock{mutex};
18 ControllerData& controller = controller_list.at(identifier);
19 controller.buttons.try_emplace(button, false);
20}
21
22void InputEngine::PreSetHatButton(const PadIdentifier& identifier, int button) {
23 std::lock_guard lock{mutex};
24 ControllerData& controller = controller_list.at(identifier);
25 controller.hat_buttons.try_emplace(button, u8{0});
26}
27
28void InputEngine::PreSetAxis(const PadIdentifier& identifier, int axis) {
29 std::lock_guard lock{mutex};
30 ControllerData& controller = controller_list.at(identifier);
31 controller.axes.try_emplace(axis, 0.0f);
32}
33
34void InputEngine::PreSetMotion(const PadIdentifier& identifier, int motion) {
35 std::lock_guard lock{mutex};
36 ControllerData& controller = controller_list.at(identifier);
37 controller.motions.try_emplace(motion);
38}
39
40void InputEngine::SetButton(const PadIdentifier& identifier, int button, bool value) {
41 {
42 std::lock_guard lock{mutex};
43 ControllerData& controller = controller_list.at(identifier);
44 if (!configuring) {
45 controller.buttons.insert_or_assign(button, value);
46 }
47 }
48 TriggerOnButtonChange(identifier, button, value);
49}
50
51void InputEngine::SetHatButton(const PadIdentifier& identifier, int button, u8 value) {
52 {
53 std::lock_guard lock{mutex};
54 ControllerData& controller = controller_list.at(identifier);
55 if (!configuring) {
56 controller.hat_buttons.insert_or_assign(button, value);
57 }
58 }
59 TriggerOnHatButtonChange(identifier, button, value);
60}
61
62void InputEngine::SetAxis(const PadIdentifier& identifier, int axis, f32 value) {
63 {
64 std::lock_guard lock{mutex};
65 ControllerData& controller = controller_list.at(identifier);
66 if (!configuring) {
67 controller.axes.insert_or_assign(axis, value);
68 }
69 }
70 TriggerOnAxisChange(identifier, axis, value);
71}
72
73void InputEngine::SetBattery(const PadIdentifier& identifier, BatteryLevel value) {
74 {
75 std::lock_guard lock{mutex};
76 ControllerData& controller = controller_list.at(identifier);
77 if (!configuring) {
78 controller.battery = value;
79 }
80 }
81 TriggerOnBatteryChange(identifier, value);
82}
83
84void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value) {
85 {
86 std::lock_guard lock{mutex};
87 ControllerData& controller = controller_list.at(identifier);
88 if (!configuring) {
89 controller.motions.insert_or_assign(motion, value);
90 }
91 }
92 TriggerOnMotionChange(identifier, motion, value);
93}
94
95bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const {
96 std::lock_guard lock{mutex};
97 const auto controller_iter = controller_list.find(identifier);
98 if (controller_iter == controller_list.cend()) {
99 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.Format(),
100 identifier.pad, identifier.port);
101 return false;
102 }
103 const ControllerData& controller = controller_iter->second;
104 const auto button_iter = controller.buttons.find(button);
105 if (button_iter == controller.buttons.cend()) {
106 LOG_ERROR(Input, "Invalid button {}", button);
107 return false;
108 }
109 return button_iter->second;
110}
111
112bool InputEngine::GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const {
113 std::lock_guard lock{mutex};
114 const auto controller_iter = controller_list.find(identifier);
115 if (controller_iter == controller_list.cend()) {
116 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.Format(),
117 identifier.pad, identifier.port);
118 return false;
119 }
120 const ControllerData& controller = controller_iter->second;
121 const auto hat_iter = controller.hat_buttons.find(button);
122 if (hat_iter == controller.hat_buttons.cend()) {
123 LOG_ERROR(Input, "Invalid hat button {}", button);
124 return false;
125 }
126 return (hat_iter->second & direction) != 0;
127}
128
129f32 InputEngine::GetAxis(const PadIdentifier& identifier, int axis) const {
130 std::lock_guard lock{mutex};
131 const auto controller_iter = controller_list.find(identifier);
132 if (controller_iter == controller_list.cend()) {
133 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.Format(),
134 identifier.pad, identifier.port);
135 return 0.0f;
136 }
137 const ControllerData& controller = controller_iter->second;
138 const auto axis_iter = controller.axes.find(axis);
139 if (axis_iter == controller.axes.cend()) {
140 LOG_ERROR(Input, "Invalid axis {}", axis);
141 return 0.0f;
142 }
143 return axis_iter->second;
144}
145
146BatteryLevel InputEngine::GetBattery(const PadIdentifier& identifier) const {
147 std::lock_guard lock{mutex};
148 const auto controller_iter = controller_list.find(identifier);
149 if (controller_iter == controller_list.cend()) {
150 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.Format(),
151 identifier.pad, identifier.port);
152 return BatteryLevel::Charging;
153 }
154 const ControllerData& controller = controller_iter->second;
155 return controller.battery;
156}
157
158BasicMotion InputEngine::GetMotion(const PadIdentifier& identifier, int motion) const {
159 std::lock_guard lock{mutex};
160 const auto controller_iter = controller_list.find(identifier);
161 if (controller_iter == controller_list.cend()) {
162 LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.Format(),
163 identifier.pad, identifier.port);
164 return {};
165 }
166 const ControllerData& controller = controller_iter->second;
167 return controller.motions.at(motion);
168}
169
170void InputEngine::ResetButtonState() {
171 for (const auto& controller : controller_list) {
172 for (const auto& button : controller.second.buttons) {
173 SetButton(controller.first, button.first, false);
174 }
175 for (const auto& button : controller.second.hat_buttons) {
176 SetHatButton(controller.first, button.first, false);
177 }
178 }
179}
180
181void InputEngine::ResetAnalogState() {
182 for (const auto& controller : controller_list) {
183 for (const auto& axis : controller.second.axes) {
184 SetAxis(controller.first, axis.first, 0.0);
185 }
186 }
187}
188
189void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value) {
190 std::lock_guard lock{mutex_callback};
191 for (const auto& poller_pair : callback_list) {
192 const InputIdentifier& poller = poller_pair.second;
193 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Button, button)) {
194 continue;
195 }
196 if (poller.callback.on_change) {
197 poller.callback.on_change();
198 }
199 }
200 if (!configuring || !mapping_callback.on_data) {
201 return;
202 }
203
204 PreSetButton(identifier, button);
205 if (value == GetButton(identifier, button)) {
206 return;
207 }
208 mapping_callback.on_data(MappingData{
209 .engine = GetEngineName(),
210 .pad = identifier,
211 .type = EngineInputType::Button,
212 .index = button,
213 .button_value = value,
214 });
215}
216
217void InputEngine::TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value) {
218 std::lock_guard lock{mutex_callback};
219 for (const auto& poller_pair : callback_list) {
220 const InputIdentifier& poller = poller_pair.second;
221 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::HatButton, button)) {
222 continue;
223 }
224 if (poller.callback.on_change) {
225 poller.callback.on_change();
226 }
227 }
228 if (!configuring || !mapping_callback.on_data) {
229 return;
230 }
231 for (std::size_t index = 1; index < 0xff; index <<= 1) {
232 bool button_value = (value & index) != 0;
233 if (button_value == GetHatButton(identifier, button, static_cast<u8>(index))) {
234 continue;
235 }
236 mapping_callback.on_data(MappingData{
237 .engine = GetEngineName(),
238 .pad = identifier,
239 .type = EngineInputType::HatButton,
240 .index = button,
241 .hat_name = GetHatButtonName(static_cast<u8>(index)),
242 });
243 }
244}
245
246void InputEngine::TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value) {
247 std::lock_guard lock{mutex_callback};
248 for (const auto& poller_pair : callback_list) {
249 const InputIdentifier& poller = poller_pair.second;
250 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Analog, axis)) {
251 continue;
252 }
253 if (poller.callback.on_change) {
254 poller.callback.on_change();
255 }
256 }
257 if (!configuring || !mapping_callback.on_data) {
258 return;
259 }
260 if (std::abs(value - GetAxis(identifier, axis)) < 0.5f) {
261 return;
262 }
263 mapping_callback.on_data(MappingData{
264 .engine = GetEngineName(),
265 .pad = identifier,
266 .type = EngineInputType::Analog,
267 .index = axis,
268 .axis_value = value,
269 });
270}
271
272void InputEngine::TriggerOnBatteryChange(const PadIdentifier& identifier,
273 [[maybe_unused]] BatteryLevel value) {
274 std::lock_guard lock{mutex_callback};
275 for (const auto& poller_pair : callback_list) {
276 const InputIdentifier& poller = poller_pair.second;
277 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Battery, 0)) {
278 continue;
279 }
280 if (poller.callback.on_change) {
281 poller.callback.on_change();
282 }
283 }
284}
285
286void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int motion,
287 const BasicMotion& value) {
288 std::lock_guard lock{mutex_callback};
289 for (const auto& poller_pair : callback_list) {
290 const InputIdentifier& poller = poller_pair.second;
291 if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Motion, motion)) {
292 continue;
293 }
294 if (poller.callback.on_change) {
295 poller.callback.on_change();
296 }
297 }
298 if (!configuring || !mapping_callback.on_data) {
299 return;
300 }
301 if (std::abs(value.gyro_x) < 0.6f && std::abs(value.gyro_y) < 0.6f &&
302 std::abs(value.gyro_z) < 0.6f) {
303 return;
304 }
305 mapping_callback.on_data(MappingData{
306 .engine = GetEngineName(),
307 .pad = identifier,
308 .type = EngineInputType::Motion,
309 .index = motion,
310 .motion_value = value,
311 });
312}
313
314bool InputEngine::IsInputIdentifierEqual(const InputIdentifier& input_identifier,
315 const PadIdentifier& identifier, EngineInputType type,
316 int index) const {
317 if (input_identifier.type != type) {
318 return false;
319 }
320 if (input_identifier.index != index) {
321 return false;
322 }
323 if (input_identifier.identifier != identifier) {
324 return false;
325 }
326 return true;
327}
328
329void InputEngine::BeginConfiguration() {
330 configuring = true;
331}
332
333void InputEngine::EndConfiguration() {
334 configuring = false;
335}
336
337const std::string& InputEngine::GetEngineName() const {
338 return input_engine;
339}
340
341int InputEngine::SetCallback(InputIdentifier input_identifier) {
342 std::lock_guard lock{mutex_callback};
343 callback_list.insert_or_assign(last_callback_key, std::move(input_identifier));
344 return last_callback_key++;
345}
346
347void InputEngine::SetMappingCallback(MappingCallback callback) {
348 std::lock_guard lock{mutex_callback};
349 mapping_callback = std::move(callback);
350}
351
352void InputEngine::DeleteCallback(int key) {
353 std::lock_guard lock{mutex_callback};
354 const auto& iterator = callback_list.find(key);
355 if (iterator == callback_list.end()) {
356 LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
357 return;
358 }
359 callback_list.erase(iterator);
360}
361
362} // namespace InputCommon