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