summaryrefslogtreecommitdiff
path: root/src/core/hid/emulated_console.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/core/hid/emulated_console.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/core/hid/emulated_console.cpp')
-rw-r--r--src/core/hid/emulated_console.cpp232
1 files changed, 232 insertions, 0 deletions
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
new file mode 100644
index 000000000..685ec080c
--- /dev/null
+++ b/src/core/hid/emulated_console.cpp
@@ -0,0 +1,232 @@
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/settings.h"
6#include "core/hid/emulated_console.h"
7#include "core/hid/input_converter.h"
8
9namespace Core::HID {
10EmulatedConsole::EmulatedConsole() = default;
11
12EmulatedConsole::~EmulatedConsole() = default;
13
14void EmulatedConsole::ReloadFromSettings() {
15 // Using first motion device from player 1. No need to assign any unique config at the moment
16 const auto& player = Settings::values.players.GetValue()[0];
17 motion_params = Common::ParamPackage(player.motions[0]);
18
19 ReloadInput();
20}
21
22void EmulatedConsole::SetTouchParams() {
23 // TODO(german77): Support any number of fingers
24 std::size_t index = 0;
25
26 // Hardcode mouse, touchscreen and cemuhook parameters
27 if (!Settings::values.mouse_enabled) {
28 // We can't use mouse as touch if native mouse is enabled
29 touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"};
30 }
31 touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0"};
32 touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1"};
33 touch_params[index++] =
34 Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536"};
35 touch_params[index++] =
36 Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072"};
37
38 const auto button_index =
39 static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue());
40 const auto& touch_buttons = Settings::values.touch_from_button_maps[button_index].buttons;
41
42 // Map the rest of the fingers from touch from button configuration
43 for (const auto& config_entry : touch_buttons) {
44 if (index >= touch_params.size()) {
45 continue;
46 }
47 Common::ParamPackage params{config_entry};
48 Common::ParamPackage touch_button_params;
49 const int x = params.Get("x", 0);
50 const int y = params.Get("y", 0);
51 params.Erase("x");
52 params.Erase("y");
53 touch_button_params.Set("engine", "touch_from_button");
54 touch_button_params.Set("button", params.Serialize());
55 touch_button_params.Set("x", x);
56 touch_button_params.Set("y", y);
57 touch_button_params.Set("touch_id", static_cast<int>(index));
58 touch_params[index] = touch_button_params;
59 index++;
60 }
61}
62
63void EmulatedConsole::ReloadInput() {
64 // If you load any device here add the equivalent to the UnloadInput() function
65 SetTouchParams();
66
67 motion_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(motion_params);
68 if (motion_devices) {
69 motion_devices->SetCallback({
70 .on_change =
71 [this](const Common::Input::CallbackStatus& callback) { SetMotion(callback); },
72 });
73 }
74
75 // Unique index for identifying touch device source
76 std::size_t index = 0;
77 for (auto& touch_device : touch_devices) {
78 touch_device = Common::Input::CreateDevice<Common::Input::InputDevice>(touch_params[index]);
79 if (!touch_device) {
80 continue;
81 }
82 touch_device->SetCallback({
83 .on_change =
84 [this, index](const Common::Input::CallbackStatus& callback) {
85 SetTouch(callback, index);
86 },
87 });
88 index++;
89 }
90}
91
92void EmulatedConsole::UnloadInput() {
93 motion_devices.reset();
94 for (auto& touch : touch_devices) {
95 touch.reset();
96 }
97}
98
99void EmulatedConsole::EnableConfiguration() {
100 is_configuring = true;
101 SaveCurrentConfig();
102}
103
104void EmulatedConsole::DisableConfiguration() {
105 is_configuring = false;
106}
107
108bool EmulatedConsole::IsConfiguring() const {
109 return is_configuring;
110}
111
112void EmulatedConsole::SaveCurrentConfig() {
113 if (!is_configuring) {
114 return;
115 }
116}
117
118void EmulatedConsole::RestoreConfig() {
119 if (!is_configuring) {
120 return;
121 }
122 ReloadFromSettings();
123}
124
125Common::ParamPackage EmulatedConsole::GetMotionParam() const {
126 return motion_params;
127}
128
129void EmulatedConsole::SetMotionParam(Common::ParamPackage param) {
130 motion_params = param;
131 ReloadInput();
132}
133
134void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) {
135 std::lock_guard lock{mutex};
136 auto& raw_status = console.motion_values.raw_status;
137 auto& emulated = console.motion_values.emulated;
138
139 raw_status = TransformToMotion(callback);
140 emulated.SetAcceleration(Common::Vec3f{
141 raw_status.accel.x.value,
142 raw_status.accel.y.value,
143 raw_status.accel.z.value,
144 });
145 emulated.SetGyroscope(Common::Vec3f{
146 raw_status.gyro.x.value,
147 raw_status.gyro.y.value,
148 raw_status.gyro.z.value,
149 });
150 emulated.UpdateRotation(raw_status.delta_timestamp);
151 emulated.UpdateOrientation(raw_status.delta_timestamp);
152
153 if (is_configuring) {
154 TriggerOnChange(ConsoleTriggerType::Motion);
155 return;
156 }
157
158 auto& motion = console.motion_state;
159 motion.accel = emulated.GetAcceleration();
160 motion.gyro = emulated.GetGyroscope();
161 motion.rotation = emulated.GetGyroscope();
162 motion.orientation = emulated.GetOrientation();
163 motion.quaternion = emulated.GetQuaternion();
164 motion.is_at_rest = !emulated.IsMoving(motion_sensitivity);
165
166 TriggerOnChange(ConsoleTriggerType::Motion);
167}
168
169void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index) {
170 if (index >= console.touch_values.size()) {
171 return;
172 }
173 std::lock_guard lock{mutex};
174
175 console.touch_values[index] = TransformToTouch(callback);
176
177 if (is_configuring) {
178 TriggerOnChange(ConsoleTriggerType::Touch);
179 return;
180 }
181
182 // TODO(german77): Remap touch id in sequential order
183 console.touch_state[index] = {
184 .position = {console.touch_values[index].x.value, console.touch_values[index].y.value},
185 .id = static_cast<u32>(console.touch_values[index].id),
186 .pressed = console.touch_values[index].pressed.value,
187 };
188
189 TriggerOnChange(ConsoleTriggerType::Touch);
190}
191
192ConsoleMotionValues EmulatedConsole::GetMotionValues() const {
193 return console.motion_values;
194}
195
196TouchValues EmulatedConsole::GetTouchValues() const {
197 return console.touch_values;
198}
199
200ConsoleMotion EmulatedConsole::GetMotion() const {
201 return console.motion_state;
202}
203
204TouchFingerState EmulatedConsole::GetTouch() const {
205 return console.touch_state;
206}
207
208void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) {
209 for (const auto& poller_pair : callback_list) {
210 const ConsoleUpdateCallback& poller = poller_pair.second;
211 if (poller.on_change) {
212 poller.on_change(type);
213 }
214 }
215}
216
217int EmulatedConsole::SetCallback(ConsoleUpdateCallback update_callback) {
218 std::lock_guard lock{mutex};
219 callback_list.insert_or_assign(last_callback_key, update_callback);
220 return last_callback_key++;
221}
222
223void EmulatedConsole::DeleteCallback(int key) {
224 std::lock_guard lock{mutex};
225 const auto& iterator = callback_list.find(key);
226 if (iterator == callback_list.end()) {
227 LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
228 return;
229 }
230 callback_list.erase(iterator);
231}
232} // namespace Core::HID