summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Narr the Reg2022-11-05 10:39:03 -0600
committerGravatar german772022-11-19 08:44:33 -0600
commit38c48cf8d896f28f7424b28265110c34f69d2369 (patch)
tree5777e9fafc1ec4182068daa8d7a0ab9630d1ee40 /src
parentMerge pull request #9226 from Kelebek1/regs_regression (diff)
downloadyuzu-38c48cf8d896f28f7424b28265110c34f69d2369.tar.gz
yuzu-38c48cf8d896f28f7424b28265110c34f69d2369.tar.xz
yuzu-38c48cf8d896f28f7424b28265110c34f69d2369.zip
core: hid: Implement true multitouch support
Diffstat (limited to 'src')
-rw-r--r--src/core/hid/emulated_console.cpp94
-rw-r--r--src/core/hid/emulated_console.h15
-rw-r--r--src/core/hid/input_converter.cpp3
-rw-r--r--src/input_common/helpers/touch_from_buttons.cpp9
-rw-r--r--src/input_common/input_poller.cpp18
5 files changed, 93 insertions, 46 deletions
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index aac45907d..fb7e5802a 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -19,27 +19,26 @@ void EmulatedConsole::ReloadFromSettings() {
19} 19}
20 20
21void EmulatedConsole::SetTouchParams() { 21void EmulatedConsole::SetTouchParams() {
22 // TODO(german77): Support any number of fingers
23 std::size_t index = 0; 22 std::size_t index = 0;
24 23
25 // Hardcode mouse, touchscreen and cemuhook parameters 24 // We can't use mouse as touch if native mouse is enabled
26 if (!Settings::values.mouse_enabled) { 25 if (!Settings::values.mouse_enabled) {
27 // We can't use mouse as touch if native mouse is enabled
28 touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"}; 26 touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"};
29 } 27 }
30 28
31 touch_params[index++] = 29 touch_params[index++] =
32 Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0,touch_id:0"}; 30 Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536"};
33 touch_params[index++] = 31 touch_params[index++] =
34 Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1,touch_id:1"}; 32 Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072"};
35 touch_params[index++] = 33
36 Common::ParamPackage{"engine:touch,axis_x:4,axis_y:5,button:2,touch_id:2"}; 34 for (int i = 0; i < static_cast<int>(MaxActiveTouchInputs); i++) {
37 touch_params[index++] = 35 Common::ParamPackage touchscreen_param{};
38 Common::ParamPackage{"engine:touch,axis_x:6,axis_y:7,button:3,touch_id:3"}; 36 touchscreen_param.Set("engine", "touch");
39 touch_params[index++] = 37 touchscreen_param.Set("axis_x", i * 2);
40 Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536,touch_id:0"}; 38 touchscreen_param.Set("axis_y", (i * 2) + 1);
41 touch_params[index++] = 39 touchscreen_param.Set("button", i);
42 Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072,touch_id:1"}; 40 touch_params[index++] = touchscreen_param;
41 }
43 42
44 const auto button_index = 43 const auto button_index =
45 static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue()); 44 static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue());
@@ -47,7 +46,7 @@ void EmulatedConsole::SetTouchParams() {
47 46
48 // Map the rest of the fingers from touch from button configuration 47 // Map the rest of the fingers from touch from button configuration
49 for (const auto& config_entry : touch_buttons) { 48 for (const auto& config_entry : touch_buttons) {
50 if (index >= touch_params.size()) { 49 if (index >= MaxTouchDevices) {
51 continue; 50 continue;
52 } 51 }
53 Common::ParamPackage params{config_entry}; 52 Common::ParamPackage params{config_entry};
@@ -60,7 +59,6 @@ void EmulatedConsole::SetTouchParams() {
60 touch_button_params.Set("button", params.Serialize()); 59 touch_button_params.Set("button", params.Serialize());
61 touch_button_params.Set("x", x); 60 touch_button_params.Set("x", x);
62 touch_button_params.Set("y", y); 61 touch_button_params.Set("y", y);
63 touch_button_params.Set("touch_id", static_cast<int>(index));
64 touch_params[index] = touch_button_params; 62 touch_params[index] = touch_button_params;
65 index++; 63 index++;
66 } 64 }
@@ -178,12 +176,38 @@ void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) {
178} 176}
179 177
180void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index) { 178void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index) {
181 if (index >= console.touch_values.size()) { 179 if (index >= MaxTouchDevices) {
182 return; 180 return;
183 } 181 }
184 std::unique_lock lock{mutex}; 182 std::unique_lock lock{mutex};
185 183
186 console.touch_values[index] = TransformToTouch(callback); 184 const auto touch_input = TransformToTouch(callback);
185 auto touch_index = GetIndexFromFingerId(index);
186 bool is_new_input = false;
187
188 if (!touch_index.has_value() && touch_input.pressed.value) {
189 touch_index = GetNextFreeIndex();
190 is_new_input = true;
191 }
192
193 // No free entries or invalid state. Ignore input
194 if (!touch_index.has_value()) {
195 return;
196 }
197
198 auto& touch_value = console.touch_values[touch_index.value()];
199
200 if (is_new_input) {
201 touch_value.pressed.value = true;
202 touch_value.id = static_cast<u32>(index);
203 }
204
205 touch_value.x = touch_input.x;
206 touch_value.y = touch_input.y;
207
208 if (!touch_input.pressed.value) {
209 touch_value.pressed.value = false;
210 }
187 211
188 if (is_configuring) { 212 if (is_configuring) {
189 lock.unlock(); 213 lock.unlock();
@@ -191,11 +215,15 @@ void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, st
191 return; 215 return;
192 } 216 }
193 217
194 // TODO(german77): Remap touch id in sequential order 218 // Touch outside allowed range. Ignore input
195 console.touch_state[index] = { 219 if (touch_index.value() >= MaxActiveTouchInputs) {
196 .position = {console.touch_values[index].x.value, console.touch_values[index].y.value}, 220 return;
197 .id = static_cast<u32>(console.touch_values[index].id), 221 }
198 .pressed = console.touch_values[index].pressed.value, 222
223 console.touch_state[touch_index.value()] = {
224 .position = {touch_value.x.value, touch_value.y.value},
225 .id = static_cast<u32>(touch_index.value()),
226 .pressed = touch_input.pressed.value,
199 }; 227 };
200 228
201 lock.unlock(); 229 lock.unlock();
@@ -222,6 +250,28 @@ TouchFingerState EmulatedConsole::GetTouch() const {
222 return console.touch_state; 250 return console.touch_state;
223} 251}
224 252
253std::optional<std::size_t> EmulatedConsole::GetIndexFromFingerId(std::size_t finger_id) const {
254 for (std::size_t index = 0; index < MaxTouchDevices; ++index) {
255 const auto& finger = console.touch_values[index];
256 if (!finger.pressed.value) {
257 continue;
258 }
259 if (finger.id == static_cast<int>(finger_id)) {
260 return index;
261 }
262 }
263 return std::nullopt;
264}
265
266std::optional<std::size_t> EmulatedConsole::GetNextFreeIndex() const {
267 for (std::size_t index = 0; index < MaxTouchDevices; ++index) {
268 if (!console.touch_values[index].pressed.value) {
269 return index;
270 }
271 }
272 return std::nullopt;
273}
274
225void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) { 275void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) {
226 std::scoped_lock lock{callback_mutex}; 276 std::scoped_lock lock{callback_mutex};
227 for (const auto& poller_pair : callback_list) { 277 for (const auto& poller_pair : callback_list) {
diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h
index 1c510cd19..697ecd2d6 100644
--- a/src/core/hid/emulated_console.h
+++ b/src/core/hid/emulated_console.h
@@ -7,6 +7,7 @@
7#include <functional> 7#include <functional>
8#include <memory> 8#include <memory>
9#include <mutex> 9#include <mutex>
10#include <optional>
10#include <unordered_map> 11#include <unordered_map>
11 12
12#include "common/common_funcs.h" 13#include "common/common_funcs.h"
@@ -20,6 +21,8 @@
20#include "core/hid/motion_input.h" 21#include "core/hid/motion_input.h"
21 22
22namespace Core::HID { 23namespace Core::HID {
24static constexpr std::size_t MaxTouchDevices = 32;
25static constexpr std::size_t MaxActiveTouchInputs = 16;
23 26
24struct ConsoleMotionInfo { 27struct ConsoleMotionInfo {
25 Common::Input::MotionStatus raw_status{}; 28 Common::Input::MotionStatus raw_status{};
@@ -27,13 +30,13 @@ struct ConsoleMotionInfo {
27}; 30};
28 31
29using ConsoleMotionDevices = std::unique_ptr<Common::Input::InputDevice>; 32using ConsoleMotionDevices = std::unique_ptr<Common::Input::InputDevice>;
30using TouchDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, 16>; 33using TouchDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, MaxTouchDevices>;
31 34
32using ConsoleMotionParams = Common::ParamPackage; 35using ConsoleMotionParams = Common::ParamPackage;
33using TouchParams = std::array<Common::ParamPackage, 16>; 36using TouchParams = std::array<Common::ParamPackage, MaxTouchDevices>;
34 37
35using ConsoleMotionValues = ConsoleMotionInfo; 38using ConsoleMotionValues = ConsoleMotionInfo;
36using TouchValues = std::array<Common::Input::TouchStatus, 16>; 39using TouchValues = std::array<Common::Input::TouchStatus, MaxTouchDevices>;
37 40
38struct TouchFinger { 41struct TouchFinger {
39 u64 last_touch{}; 42 u64 last_touch{};
@@ -55,7 +58,7 @@ struct ConsoleMotion {
55 bool is_at_rest{}; 58 bool is_at_rest{};
56}; 59};
57 60
58using TouchFingerState = std::array<TouchFinger, 16>; 61using TouchFingerState = std::array<TouchFinger, MaxActiveTouchInputs>;
59 62
60struct ConsoleStatus { 63struct ConsoleStatus {
61 // Data from input_common 64 // Data from input_common
@@ -166,6 +169,10 @@ private:
166 */ 169 */
167 void SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index); 170 void SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index);
168 171
172 std::optional<std::size_t> GetIndexFromFingerId(std::size_t finger_id) const;
173
174 std::optional<std::size_t> GetNextFreeIndex() const;
175
169 /** 176 /**
170 * Triggers a callback that something has changed on the console status 177 * Triggers a callback that something has changed on the console status
171 * @param type Input type of the event to trigger 178 * @param type Input type of the event to trigger
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index 5d8b75b50..502692875 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -200,9 +200,6 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus&
200 x = std::clamp(x, 0.0f, 1.0f); 200 x = std::clamp(x, 0.0f, 1.0f);
201 y = std::clamp(y, 0.0f, 1.0f); 201 y = std::clamp(y, 0.0f, 1.0f);
202 202
203 // Limit id to maximum number of fingers
204 status.id = std::clamp(status.id, 0, 16);
205
206 if (status.pressed.inverted) { 203 if (status.pressed.inverted) {
207 status.pressed.value = !status.pressed.value; 204 status.pressed.value = !status.pressed.value;
208 } 205 }
diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp
index da4a3dca5..003a38da5 100644
--- a/src/input_common/helpers/touch_from_buttons.cpp
+++ b/src/input_common/helpers/touch_from_buttons.cpp
@@ -10,8 +10,8 @@ namespace InputCommon {
10class TouchFromButtonDevice final : public Common::Input::InputDevice { 10class TouchFromButtonDevice final : public Common::Input::InputDevice {
11public: 11public:
12 using Button = std::unique_ptr<Common::Input::InputDevice>; 12 using Button = std::unique_ptr<Common::Input::InputDevice>;
13 TouchFromButtonDevice(Button button_, int touch_id_, float x_, float y_) 13 TouchFromButtonDevice(Button button_, float x_, float y_)
14 : button(std::move(button_)), touch_id(touch_id_), x(x_), y(y_) { 14 : button(std::move(button_)), x(x_), y(y_) {
15 last_button_value = false; 15 last_button_value = false;
16 button->SetCallback({ 16 button->SetCallback({
17 .on_change = 17 .on_change =
@@ -34,7 +34,6 @@ public:
34 .pressed = button_status, 34 .pressed = button_status,
35 .x = {}, 35 .x = {},
36 .y = {}, 36 .y = {},
37 .id = touch_id,
38 }; 37 };
39 status.x.properties = properties; 38 status.x.properties = properties;
40 status.y.properties = properties; 39 status.y.properties = properties;
@@ -62,7 +61,6 @@ public:
62private: 61private:
63 Button button; 62 Button button;
64 bool last_button_value; 63 bool last_button_value;
65 const int touch_id;
66 const float x; 64 const float x;
67 const float y; 65 const float y;
68 const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false}; 66 const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
@@ -73,10 +71,9 @@ std::unique_ptr<Common::Input::InputDevice> TouchFromButton::Create(
73 const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize(); 71 const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
74 auto button = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>( 72 auto button = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
75 params.Get("button", null_engine)); 73 params.Get("button", null_engine));
76 const auto touch_id = params.Get("touch_id", 0);
77 const float x = params.Get("x", 0.0f) / 1280.0f; 74 const float x = params.Get("x", 0.0f) / 1280.0f;
78 const float y = params.Get("y", 0.0f) / 720.0f; 75 const float y = params.Get("y", 0.0f) / 720.0f;
79 return std::make_unique<TouchFromButtonDevice>(std::move(button), touch_id, x, y); 76 return std::make_unique<TouchFromButtonDevice>(std::move(button), x, y);
80} 77}
81 78
82} // namespace InputCommon 79} // namespace InputCommon
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
index 4ac182147..fb8be42e2 100644
--- a/src/input_common/input_poller.cpp
+++ b/src/input_common/input_poller.cpp
@@ -229,13 +229,12 @@ private:
229 229
230class InputFromTouch final : public Common::Input::InputDevice { 230class InputFromTouch final : public Common::Input::InputDevice {
231public: 231public:
232 explicit InputFromTouch(PadIdentifier identifier_, int touch_id_, int button_, bool toggle_, 232 explicit InputFromTouch(PadIdentifier identifier_, int button_, bool toggle_, bool inverted_,
233 bool inverted_, int axis_x_, int axis_y_, 233 int axis_x_, int axis_y_, Common::Input::AnalogProperties properties_x_,
234 Common::Input::AnalogProperties properties_x_,
235 Common::Input::AnalogProperties properties_y_, 234 Common::Input::AnalogProperties properties_y_,
236 InputEngine* input_engine_) 235 InputEngine* input_engine_)
237 : identifier(identifier_), touch_id(touch_id_), button(button_), toggle(toggle_), 236 : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_),
238 inverted(inverted_), axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_), 237 axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_),
239 properties_y(properties_y_), input_engine(input_engine_) { 238 properties_y(properties_y_), input_engine(input_engine_) {
240 UpdateCallback engine_callback{[this]() { OnChange(); }}; 239 UpdateCallback engine_callback{[this]() { OnChange(); }};
241 const InputIdentifier button_input_identifier{ 240 const InputIdentifier button_input_identifier{
@@ -271,8 +270,7 @@ public:
271 } 270 }
272 271
273 Common::Input::TouchStatus GetStatus() const { 272 Common::Input::TouchStatus GetStatus() const {
274 Common::Input::TouchStatus status; 273 Common::Input::TouchStatus status{};
275 status.id = touch_id;
276 status.pressed = { 274 status.pressed = {
277 .value = input_engine->GetButton(identifier, button), 275 .value = input_engine->GetButton(identifier, button),
278 .inverted = inverted, 276 .inverted = inverted,
@@ -307,7 +305,6 @@ public:
307 305
308private: 306private:
309 const PadIdentifier identifier; 307 const PadIdentifier identifier;
310 const int touch_id;
311 const int button; 308 const int button;
312 const bool toggle; 309 const bool toggle;
313 const bool inverted; 310 const bool inverted;
@@ -919,7 +916,6 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTriggerDevice(
919 916
920std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTouchDevice( 917std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTouchDevice(
921 const Common::ParamPackage& params) { 918 const Common::ParamPackage& params) {
922 const auto touch_id = params.Get("touch_id", 0);
923 const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f); 919 const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
924 const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f); 920 const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f);
925 const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f); 921 const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f);
@@ -954,8 +950,8 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTouchDevice(
954 input_engine->PreSetAxis(identifier, axis_x); 950 input_engine->PreSetAxis(identifier, axis_x);
955 input_engine->PreSetAxis(identifier, axis_y); 951 input_engine->PreSetAxis(identifier, axis_y);
956 input_engine->PreSetButton(identifier, button); 952 input_engine->PreSetButton(identifier, button);
957 return std::make_unique<InputFromTouch>(identifier, touch_id, button, toggle, inverted, axis_x, 953 return std::make_unique<InputFromTouch>(identifier, button, toggle, inverted, axis_x, axis_y,
958 axis_y, properties_x, properties_y, input_engine.get()); 954 properties_x, properties_y, input_engine.get());
959} 955}
960 956
961std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateBatteryDevice( 957std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateBatteryDevice(