summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/frontend/input.h9
-rw-r--r--src/input_common/CMakeLists.txt6
-rw-r--r--src/input_common/main.cpp73
-rw-r--r--src/input_common/main.h41
-rw-r--r--src/input_common/motion_emu.cpp179
-rw-r--r--src/input_common/motion_emu.h46
-rw-r--r--src/input_common/mouse/mouse_input.cpp125
-rw-r--r--src/input_common/mouse/mouse_input.h99
-rw-r--r--src/input_common/mouse/mouse_poller.cpp261
-rw-r--r--src/input_common/mouse/mouse_poller.h109
-rw-r--r--src/yuzu/bootmanager.cpp26
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp87
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.cpp8
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp1
14 files changed, 793 insertions, 277 deletions
diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h
index 25ac5af46..93251e3aa 100644
--- a/src/core/frontend/input.h
+++ b/src/core/frontend/input.h
@@ -161,10 +161,15 @@ using MotionStatus = std::tuple<Common::Vec3<float>, Common::Vec3<float>, Common
161using MotionDevice = InputDevice<MotionStatus>; 161using MotionDevice = InputDevice<MotionStatus>;
162 162
163/** 163/**
164 * A touch device is an input device that returns a tuple of two floats and a bool. The floats are 164 * A touch status is an object that returns a tuple of two floats and a bool. The floats are
165 * x and y coordinates in the range 0.0 - 1.0, and the bool indicates whether it is pressed. 165 * x and y coordinates in the range 0.0 - 1.0, and the bool indicates whether it is pressed.
166 */ 166 */
167using TouchDevice = InputDevice<std::tuple<float, float, bool>>; 167using TouchStatus = std::tuple<float, float, bool>;
168
169/**
170 * A touch device is an input device that returns a touch status object
171 */
172using TouchDevice = InputDevice<TouchStatus>;
168 173
169/** 174/**
170 * A mouse device is an input device that returns a tuple of two floats and four ints. 175 * A mouse device is an input device that returns a tuple of two floats and four ints.
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 7b39a38c1..1619e5e4e 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -5,8 +5,6 @@ add_library(input_common STATIC
5 keyboard.h 5 keyboard.h
6 main.cpp 6 main.cpp
7 main.h 7 main.h
8 motion_emu.cpp
9 motion_emu.h
10 motion_from_button.cpp 8 motion_from_button.cpp
11 motion_from_button.h 9 motion_from_button.h
12 motion_input.cpp 10 motion_input.cpp
@@ -19,6 +17,10 @@ add_library(input_common STATIC
19 gcadapter/gc_adapter.h 17 gcadapter/gc_adapter.h
20 gcadapter/gc_poller.cpp 18 gcadapter/gc_poller.cpp
21 gcadapter/gc_poller.h 19 gcadapter/gc_poller.h
20 mouse/mouse_input.cpp
21 mouse/mouse_input.h
22 mouse/mouse_poller.cpp
23 mouse/mouse_poller.h
22 sdl/sdl.cpp 24 sdl/sdl.cpp
23 sdl/sdl.h 25 sdl/sdl.h
24 udp/client.cpp 26 udp/client.cpp
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index e59ad4ff5..880ea73b8 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -10,8 +10,9 @@
10#include "input_common/gcadapter/gc_poller.h" 10#include "input_common/gcadapter/gc_poller.h"
11#include "input_common/keyboard.h" 11#include "input_common/keyboard.h"
12#include "input_common/main.h" 12#include "input_common/main.h"
13#include "input_common/motion_emu.h"
14#include "input_common/motion_from_button.h" 13#include "input_common/motion_from_button.h"
14#include "input_common/mouse/mouse_input.h"
15#include "input_common/mouse/mouse_poller.h"
15#include "input_common/touch_from_button.h" 16#include "input_common/touch_from_button.h"
16#include "input_common/udp/client.h" 17#include "input_common/udp/client.h"
17#include "input_common/udp/udp.h" 18#include "input_common/udp/udp.h"
@@ -37,8 +38,6 @@ struct InputSubsystem::Impl {
37 std::make_shared<AnalogFromButton>()); 38 std::make_shared<AnalogFromButton>());
38 Input::RegisterFactory<Input::MotionDevice>("keyboard", 39 Input::RegisterFactory<Input::MotionDevice>("keyboard",
39 std::make_shared<MotionFromButton>()); 40 std::make_shared<MotionFromButton>());
40 motion_emu = std::make_shared<MotionEmu>();
41 Input::RegisterFactory<Input::MotionDevice>("motion_emu", motion_emu);
42 Input::RegisterFactory<Input::TouchDevice>("touch_from_button", 41 Input::RegisterFactory<Input::TouchDevice>("touch_from_button",
43 std::make_shared<TouchFromButtonFactory>()); 42 std::make_shared<TouchFromButtonFactory>());
44 43
@@ -51,6 +50,16 @@ struct InputSubsystem::Impl {
51 Input::RegisterFactory<Input::MotionDevice>("cemuhookudp", udpmotion); 50 Input::RegisterFactory<Input::MotionDevice>("cemuhookudp", udpmotion);
52 udptouch = std::make_shared<UDPTouchFactory>(udp); 51 udptouch = std::make_shared<UDPTouchFactory>(udp);
53 Input::RegisterFactory<Input::TouchDevice>("cemuhookudp", udptouch); 52 Input::RegisterFactory<Input::TouchDevice>("cemuhookudp", udptouch);
53
54 mouse = std::make_shared<MouseInput::Mouse>();
55 mousebuttons = std::make_shared<MouseButtonFactory>(mouse);
56 Input::RegisterFactory<Input::ButtonDevice>("mouse", mousebuttons);
57 mouseanalog = std::make_shared<MouseAnalogFactory>(mouse);
58 Input::RegisterFactory<Input::AnalogDevice>("mouse", mouseanalog);
59 mousemotion = std::make_shared<MouseMotionFactory>(mouse);
60 Input::RegisterFactory<Input::MotionDevice>("mouse", mousemotion);
61 mousetouch = std::make_shared<MouseTouchFactory>(mouse);
62 Input::RegisterFactory<Input::TouchDevice>("mouse", mousetouch);
54 } 63 }
55 64
56 void Shutdown() { 65 void Shutdown() {
@@ -58,8 +67,6 @@ struct InputSubsystem::Impl {
58 Input::UnregisterFactory<Input::MotionDevice>("keyboard"); 67 Input::UnregisterFactory<Input::MotionDevice>("keyboard");
59 keyboard.reset(); 68 keyboard.reset();
60 Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button"); 69 Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button");
61 Input::UnregisterFactory<Input::MotionDevice>("motion_emu");
62 motion_emu.reset();
63 Input::UnregisterFactory<Input::TouchDevice>("touch_from_button"); 70 Input::UnregisterFactory<Input::TouchDevice>("touch_from_button");
64#ifdef HAVE_SDL2 71#ifdef HAVE_SDL2
65 sdl.reset(); 72 sdl.reset();
@@ -77,6 +84,16 @@ struct InputSubsystem::Impl {
77 84
78 udpmotion.reset(); 85 udpmotion.reset();
79 udptouch.reset(); 86 udptouch.reset();
87
88 Input::UnregisterFactory<Input::ButtonDevice>("mouse");
89 Input::UnregisterFactory<Input::AnalogDevice>("mouse");
90 Input::UnregisterFactory<Input::MotionDevice>("mouse");
91 Input::UnregisterFactory<Input::TouchDevice>("mouse");
92
93 mousebuttons.reset();
94 mouseanalog.reset();
95 mousemotion.reset();
96 mousetouch.reset();
80 } 97 }
81 98
82 [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const { 99 [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const {
@@ -140,7 +157,6 @@ struct InputSubsystem::Impl {
140 } 157 }
141 158
142 std::shared_ptr<Keyboard> keyboard; 159 std::shared_ptr<Keyboard> keyboard;
143 std::shared_ptr<MotionEmu> motion_emu;
144#ifdef HAVE_SDL2 160#ifdef HAVE_SDL2
145 std::unique_ptr<SDL::State> sdl; 161 std::unique_ptr<SDL::State> sdl;
146#endif 162#endif
@@ -149,8 +165,13 @@ struct InputSubsystem::Impl {
149 std::shared_ptr<GCVibrationFactory> gcvibration; 165 std::shared_ptr<GCVibrationFactory> gcvibration;
150 std::shared_ptr<UDPMotionFactory> udpmotion; 166 std::shared_ptr<UDPMotionFactory> udpmotion;
151 std::shared_ptr<UDPTouchFactory> udptouch; 167 std::shared_ptr<UDPTouchFactory> udptouch;
168 std::shared_ptr<MouseButtonFactory> mousebuttons;
169 std::shared_ptr<MouseAnalogFactory> mouseanalog;
170 std::shared_ptr<MouseMotionFactory> mousemotion;
171 std::shared_ptr<MouseTouchFactory> mousetouch;
152 std::shared_ptr<CemuhookUDP::Client> udp; 172 std::shared_ptr<CemuhookUDP::Client> udp;
153 std::shared_ptr<GCAdapter::Adapter> gcadapter; 173 std::shared_ptr<GCAdapter::Adapter> gcadapter;
174 std::shared_ptr<MouseInput::Mouse> mouse;
154}; 175};
155 176
156InputSubsystem::InputSubsystem() : impl{std::make_unique<Impl>()} {} 177InputSubsystem::InputSubsystem() : impl{std::make_unique<Impl>()} {}
@@ -173,12 +194,12 @@ const Keyboard* InputSubsystem::GetKeyboard() const {
173 return impl->keyboard.get(); 194 return impl->keyboard.get();
174} 195}
175 196
176MotionEmu* InputSubsystem::GetMotionEmu() { 197MouseInput::Mouse* InputSubsystem::GetMouse() {
177 return impl->motion_emu.get(); 198 return impl->mouse.get();
178} 199}
179 200
180const MotionEmu* InputSubsystem::GetMotionEmu() const { 201const MouseInput::Mouse* InputSubsystem::GetMouse() const {
181 return impl->motion_emu.get(); 202 return impl->mouse.get();
182} 203}
183 204
184std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const { 205std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const {
@@ -229,6 +250,38 @@ const UDPTouchFactory* InputSubsystem::GetUDPTouch() const {
229 return impl->udptouch.get(); 250 return impl->udptouch.get();
230} 251}
231 252
253MouseButtonFactory* InputSubsystem::GetMouseButtons() {
254 return impl->mousebuttons.get();
255}
256
257const MouseButtonFactory* InputSubsystem::GetMouseButtons() const {
258 return impl->mousebuttons.get();
259}
260
261MouseAnalogFactory* InputSubsystem::GetMouseAnalogs() {
262 return impl->mouseanalog.get();
263}
264
265const MouseAnalogFactory* InputSubsystem::GetMouseAnalogs() const {
266 return impl->mouseanalog.get();
267}
268
269MouseMotionFactory* InputSubsystem::GetMouseMotions() {
270 return impl->mousemotion.get();
271}
272
273const MouseMotionFactory* InputSubsystem::GetMouseMotions() const {
274 return impl->mousemotion.get();
275}
276
277MouseTouchFactory* InputSubsystem::GetMouseTouch() {
278 return impl->mousetouch.get();
279}
280
281const MouseTouchFactory* InputSubsystem::GetMouseTouch() const {
282 return impl->mousetouch.get();
283}
284
232void InputSubsystem::ReloadInputDevices() { 285void InputSubsystem::ReloadInputDevices() {
233 if (!impl->udp) { 286 if (!impl->udp) {
234 return; 287 return;
diff --git a/src/input_common/main.h b/src/input_common/main.h
index dded3f1ef..5d6f26385 100644
--- a/src/input_common/main.h
+++ b/src/input_common/main.h
@@ -25,6 +25,10 @@ namespace Settings::NativeMotion {
25enum Values : int; 25enum Values : int;
26} 26}
27 27
28namespace MouseInput {
29class Mouse;
30}
31
28namespace InputCommon { 32namespace InputCommon {
29namespace Polling { 33namespace Polling {
30 34
@@ -56,8 +60,11 @@ class GCAnalogFactory;
56class GCButtonFactory; 60class GCButtonFactory;
57class UDPMotionFactory; 61class UDPMotionFactory;
58class UDPTouchFactory; 62class UDPTouchFactory;
63class MouseButtonFactory;
64class MouseAnalogFactory;
65class MouseMotionFactory;
66class MouseTouchFactory;
59class Keyboard; 67class Keyboard;
60class MotionEmu;
61 68
62/** 69/**
63 * Given a ParamPackage for a Device returned from `GetInputDevices`, attempt to get the default 70 * Given a ParamPackage for a Device returned from `GetInputDevices`, attempt to get the default
@@ -90,11 +97,11 @@ public:
90 /// Retrieves the underlying keyboard device. 97 /// Retrieves the underlying keyboard device.
91 [[nodiscard]] const Keyboard* GetKeyboard() const; 98 [[nodiscard]] const Keyboard* GetKeyboard() const;
92 99
93 /// Retrieves the underlying motion emulation factory. 100 /// Retrieves the underlying mouse device.
94 [[nodiscard]] MotionEmu* GetMotionEmu(); 101 [[nodiscard]] MouseInput::Mouse* GetMouse();
95 102
96 /// Retrieves the underlying motion emulation factory. 103 /// Retrieves the underlying mouse device.
97 [[nodiscard]] const MotionEmu* GetMotionEmu() const; 104 [[nodiscard]] const MouseInput::Mouse* GetMouse() const;
98 105
99 /** 106 /**
100 * Returns all available input devices that this Factory can create a new device with. 107 * Returns all available input devices that this Factory can create a new device with.
@@ -137,6 +144,30 @@ public:
137 /// Retrieves the underlying udp touch handler. 144 /// Retrieves the underlying udp touch handler.
138 [[nodiscard]] const UDPTouchFactory* GetUDPTouch() const; 145 [[nodiscard]] const UDPTouchFactory* GetUDPTouch() const;
139 146
147 /// Retrieves the underlying GameCube button handler.
148 [[nodiscard]] MouseButtonFactory* GetMouseButtons();
149
150 /// Retrieves the underlying GameCube button handler.
151 [[nodiscard]] const MouseButtonFactory* GetMouseButtons() const;
152
153 /// Retrieves the underlying udp touch handler.
154 [[nodiscard]] MouseAnalogFactory* GetMouseAnalogs();
155
156 /// Retrieves the underlying udp touch handler.
157 [[nodiscard]] const MouseAnalogFactory* GetMouseAnalogs() const;
158
159 /// Retrieves the underlying udp motion handler.
160 [[nodiscard]] MouseMotionFactory* GetMouseMotions();
161
162 /// Retrieves the underlying udp motion handler.
163 [[nodiscard]] const MouseMotionFactory* GetMouseMotions() const;
164
165 /// Retrieves the underlying udp touch handler.
166 [[nodiscard]] MouseTouchFactory* GetMouseTouch();
167
168 /// Retrieves the underlying udp touch handler.
169 [[nodiscard]] const MouseTouchFactory* GetMouseTouch() const;
170
140 /// Reloads the input devices 171 /// Reloads the input devices
141 void ReloadInputDevices(); 172 void ReloadInputDevices();
142 173
diff --git a/src/input_common/motion_emu.cpp b/src/input_common/motion_emu.cpp
deleted file mode 100644
index d4da5596b..000000000
--- a/src/input_common/motion_emu.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <chrono>
7#include <mutex>
8#include <thread>
9#include <tuple>
10#include "common/math_util.h"
11#include "common/quaternion.h"
12#include "common/thread.h"
13#include "common/vector_math.h"
14#include "input_common/motion_emu.h"
15
16namespace InputCommon {
17
18// Implementation class of the motion emulation device
19class MotionEmuDevice {
20public:
21 explicit MotionEmuDevice(int update_millisecond_, float sensitivity_)
22 : update_millisecond(update_millisecond_),
23 update_duration(std::chrono::duration_cast<std::chrono::steady_clock::duration>(
24 std::chrono::milliseconds(update_millisecond))),
25 sensitivity(sensitivity_), motion_emu_thread(&MotionEmuDevice::MotionEmuThread, this) {}
26
27 ~MotionEmuDevice() {
28 if (motion_emu_thread.joinable()) {
29 shutdown_event.Set();
30 motion_emu_thread.join();
31 }
32 }
33
34 void BeginTilt(int x, int y) {
35 mouse_origin = Common::MakeVec(x, y);
36 is_tilting = true;
37 }
38
39 void Tilt(int x, int y) {
40 if (!is_tilting) {
41 return;
42 }
43
44 std::lock_guard guard{tilt_mutex};
45 const auto mouse_move = Common::MakeVec(x, y) - mouse_origin;
46 if (mouse_move.x == 0 && mouse_move.y == 0) {
47 tilt_angle = 0;
48 } else {
49 tilt_direction = mouse_move.Cast<float>();
50 tilt_angle =
51 std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f, Common::PI * 0.5f);
52 }
53 }
54
55 void EndTilt() {
56 std::lock_guard guard{tilt_mutex};
57 tilt_angle = 0;
58 is_tilting = false;
59 }
60
61 Input::MotionStatus GetStatus() {
62 std::lock_guard guard{status_mutex};
63 return status;
64 }
65
66private:
67 const int update_millisecond;
68 const std::chrono::steady_clock::duration update_duration;
69 const float sensitivity;
70
71 Common::Vec2<int> mouse_origin;
72
73 std::mutex tilt_mutex;
74 Common::Vec2<float> tilt_direction;
75 float tilt_angle = 0;
76
77 bool is_tilting = false;
78
79 Common::Event shutdown_event;
80
81 Input::MotionStatus status;
82 std::mutex status_mutex;
83
84 // Note: always keep the thread declaration at the end so that other objects are initialized
85 // before this!
86 std::thread motion_emu_thread;
87
88 void MotionEmuThread() {
89 auto update_time = std::chrono::steady_clock::now();
90 Common::Quaternion<float> q = Common::MakeQuaternion(Common::Vec3<float>(), 0);
91
92 while (!shutdown_event.WaitUntil(update_time)) {
93 update_time += update_duration;
94 const Common::Quaternion<float> old_q = q;
95
96 {
97 std::lock_guard guard{tilt_mutex};
98
99 // Find the quaternion describing current 3DS tilting
100 q = Common::MakeQuaternion(
101 Common::MakeVec(-tilt_direction.y, 0.0f, tilt_direction.x), tilt_angle);
102 }
103
104 const auto inv_q = q.Inverse();
105
106 // Set the gravity vector in world space
107 auto gravity = Common::MakeVec(0.0f, -1.0f, 0.0f);
108
109 // Find the angular rate vector in world space
110 auto angular_rate = ((q - old_q) * inv_q).xyz * 2;
111 angular_rate *= static_cast<float>(1000 / update_millisecond) / Common::PI * 180.0f;
112
113 // Transform the two vectors from world space to 3DS space
114 gravity = QuaternionRotate(inv_q, gravity);
115 angular_rate = QuaternionRotate(inv_q, angular_rate);
116
117 // TODO: Calculate the correct rotation vector and orientation matrix
118 const auto matrix4x4 = q.ToMatrix();
119 const auto rotation = Common::MakeVec(0.0f, 0.0f, 0.0f);
120 const std::array orientation{
121 Common::Vec3f(matrix4x4[0], matrix4x4[1], -matrix4x4[2]),
122 Common::Vec3f(matrix4x4[4], matrix4x4[5], -matrix4x4[6]),
123 Common::Vec3f(-matrix4x4[8], -matrix4x4[9], matrix4x4[10]),
124 };
125
126 // Update the sensor state
127 {
128 std::lock_guard guard{status_mutex};
129 status = std::make_tuple(gravity, angular_rate, rotation, orientation);
130 }
131 }
132 }
133};
134
135// Interface wrapper held by input receiver as a unique_ptr. It holds the implementation class as
136// a shared_ptr, which is also observed by the factory class as a weak_ptr. In this way the factory
137// can forward all the inputs to the implementation only when it is valid.
138class MotionEmuDeviceWrapper : public Input::MotionDevice {
139public:
140 explicit MotionEmuDeviceWrapper(int update_millisecond, float sensitivity) {
141 device = std::make_shared<MotionEmuDevice>(update_millisecond, sensitivity);
142 }
143
144 Input::MotionStatus GetStatus() const override {
145 return device->GetStatus();
146 }
147
148 std::shared_ptr<MotionEmuDevice> device;
149};
150
151std::unique_ptr<Input::MotionDevice> MotionEmu::Create(const Common::ParamPackage& params) {
152 const int update_period = params.Get("update_period", 100);
153 const float sensitivity = params.Get("sensitivity", 0.01f);
154 auto device_wrapper = std::make_unique<MotionEmuDeviceWrapper>(update_period, sensitivity);
155 // Previously created device is disconnected here. Having two motion devices for 3DS is not
156 // expected.
157 current_device = device_wrapper->device;
158 return device_wrapper;
159}
160
161void MotionEmu::BeginTilt(int x, int y) {
162 if (auto ptr = current_device.lock()) {
163 ptr->BeginTilt(x, y);
164 }
165}
166
167void MotionEmu::Tilt(int x, int y) {
168 if (auto ptr = current_device.lock()) {
169 ptr->Tilt(x, y);
170 }
171}
172
173void MotionEmu::EndTilt() {
174 if (auto ptr = current_device.lock()) {
175 ptr->EndTilt();
176 }
177}
178
179} // namespace InputCommon
diff --git a/src/input_common/motion_emu.h b/src/input_common/motion_emu.h
deleted file mode 100644
index 7a7e22467..000000000
--- a/src/input_common/motion_emu.h
+++ /dev/null
@@ -1,46 +0,0 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/frontend/input.h"
8
9namespace InputCommon {
10
11class MotionEmuDevice;
12
13class MotionEmu : public Input::Factory<Input::MotionDevice> {
14public:
15 /**
16 * Creates a motion device emulated from mouse input
17 * @param params contains parameters for creating the device:
18 * - "update_period": update period in milliseconds
19 * - "sensitivity": the coefficient converting mouse movement to tilting angle
20 */
21 std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override;
22
23 /**
24 * Signals that a motion sensor tilt has begun.
25 * @param x the x-coordinate of the cursor
26 * @param y the y-coordinate of the cursor
27 */
28 void BeginTilt(int x, int y);
29
30 /**
31 * Signals that a motion sensor tilt is occurring.
32 * @param x the x-coordinate of the cursor
33 * @param y the y-coordinate of the cursor
34 */
35 void Tilt(int x, int y);
36
37 /**
38 * Signals that a motion sensor tilt has ended.
39 */
40 void EndTilt();
41
42private:
43 std::weak_ptr<MotionEmuDevice> current_device;
44};
45
46} // namespace InputCommon
diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp
new file mode 100644
index 000000000..3f4264caa
--- /dev/null
+++ b/src/input_common/mouse/mouse_input.cpp
@@ -0,0 +1,125 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2+
3// Refer to the license.txt file included.
4
5#include "common/logging/log.h"
6#include "common/math_util.h"
7#include "common/param_package.h"
8#include "input_common/mouse/mouse_input.h"
9
10namespace MouseInput {
11
12Mouse::Mouse() {
13 update_thread = std::thread(&Mouse::UpdateThread, this);
14}
15
16Mouse::~Mouse() {
17 update_thread_running = false;
18 if (update_thread.joinable()) {
19 update_thread.join();
20 }
21}
22
23void Mouse::UpdateThread() {
24 constexpr int update_time = 10;
25 while (update_thread_running) {
26 for (MouseInfo& info : mouse_info) {
27 Common::Vec3f angular_direction = {-info.tilt_direction.y, 0.0f,
28 -info.tilt_direction.x};
29
30 info.motion.SetGyroscope(angular_direction * info.tilt_speed);
31 info.motion.UpdateRotation(update_time * 1000);
32 info.motion.UpdateOrientation(update_time * 1000);
33 info.tilt_speed = 0;
34 info.data.motion = info.motion.GetMotion();
35 }
36 if (configuring) {
37 UpdateYuzuSettings();
38 }
39 std::this_thread::sleep_for(std::chrono::milliseconds(update_time));
40 }
41}
42
43void Mouse::UpdateYuzuSettings() {
44 MouseStatus pad_status{};
45 if (buttons != 0) {
46 pad_status.button = last_button;
47 mouse_queue.Push(pad_status);
48 }
49}
50
51void Mouse::PressButton(int x, int y, int button_) {
52 if (button_ >= static_cast<int>(mouse_info.size())) {
53 return;
54 }
55
56 int button = 1 << button_;
57 buttons |= static_cast<u16>(button);
58 last_button = static_cast<MouseButton>(button_);
59
60 mouse_info[button_].mouse_origin = Common::MakeVec(x, y);
61 mouse_info[button_].last_mouse_position = Common::MakeVec(x, y);
62 mouse_info[button_].data.pressed = true;
63}
64
65void Mouse::MouseMove(int x, int y) {
66 for (MouseInfo& info : mouse_info) {
67 if (info.data.pressed) {
68 auto mouse_move = Common::MakeVec(x, y) - info.mouse_origin;
69 auto mouse_change = Common::MakeVec(x, y) - info.last_mouse_position;
70 info.last_mouse_position = Common::MakeVec(x, y);
71 info.data.axis = {mouse_move.x, -mouse_move.y};
72
73 if (mouse_change.x == 0 && mouse_change.y == 0) {
74 info.tilt_speed = 0;
75 } else {
76 info.tilt_direction = mouse_change.Cast<float>();
77 info.tilt_speed = info.tilt_direction.Normalize() * info.sensitivity;
78 }
79 }
80 }
81}
82
83void Mouse::ReleaseButton(int button_) {
84 if (button_ >= static_cast<int>(mouse_info.size())) {
85 return;
86 }
87
88 int button = 1 << button_;
89 buttons &= static_cast<u16>(0xFF - button);
90
91 mouse_info[button_].tilt_speed = 0;
92 mouse_info[button_].data.pressed = false;
93 mouse_info[button_].data.axis = {0, 0};
94}
95
96void Mouse::BeginConfiguration() {
97 buttons = 0;
98 last_button = MouseButton::Undefined;
99 mouse_queue.Clear();
100 configuring = true;
101}
102
103void Mouse::EndConfiguration() {
104 buttons = 0;
105 last_button = MouseButton::Undefined;
106 mouse_queue.Clear();
107 configuring = false;
108}
109
110Common::SPSCQueue<MouseStatus>& Mouse::GetMouseQueue() {
111 return mouse_queue;
112}
113
114const Common::SPSCQueue<MouseStatus>& Mouse::GetMouseQueue() const {
115 return mouse_queue;
116}
117
118MouseData& Mouse::GetMouseState(std::size_t button) {
119 return mouse_info[button].data;
120}
121
122const MouseData& Mouse::GetMouseState(std::size_t button) const {
123 return mouse_info[button].data;
124}
125} // namespace MouseInput
diff --git a/src/input_common/mouse/mouse_input.h b/src/input_common/mouse/mouse_input.h
new file mode 100644
index 000000000..761663334
--- /dev/null
+++ b/src/input_common/mouse/mouse_input.h
@@ -0,0 +1,99 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <algorithm>
8#include <functional>
9#include <mutex>
10#include <thread>
11#include <unordered_map>
12#include "common/common_types.h"
13#include "common/threadsafe_queue.h"
14#include "core/frontend/input.h"
15#include "input_common/main.h"
16#include "input_common/motion_input.h"
17
18namespace MouseInput {
19
20enum class MouseButton {
21 Left,
22 Wheel,
23 Right,
24 Foward,
25 Backward,
26 Undefined,
27};
28
29struct MouseStatus {
30 MouseButton button{MouseButton::Undefined};
31};
32
33struct MouseData {
34 bool pressed{};
35 std::array<int, 2> axis{};
36 Input::MotionStatus motion{};
37 Input::TouchStatus touch{};
38};
39
40class Mouse {
41public:
42 Mouse();
43 ~Mouse();
44
45 /// Used for polling
46 void BeginConfiguration();
47 void EndConfiguration();
48
49 /**
50 * Signals that a button is pressed.
51 * @param x the x-coordinate of the cursor
52 * @param y the y-coordinate of the cursor
53 * @param button the button pressed
54 */
55 void PressButton(int x, int y, int button_);
56
57 /**
58 * Signals that mouse has moved.
59 * @param x the x-coordinate of the cursor
60 * @param y the y-coordinate of the cursor
61 */
62 void MouseMove(int x, int y);
63
64 /**
65 * Signals that a motion sensor tilt has ended.
66 */
67 void ReleaseButton(int button_);
68
69 [[nodiscard]] Common::SPSCQueue<MouseStatus>& GetMouseQueue();
70 [[nodiscard]] const Common::SPSCQueue<MouseStatus>& GetMouseQueue() const;
71
72 [[nodiscard]] MouseData& GetMouseState(std::size_t button);
73 [[nodiscard]] const MouseData& GetMouseState(std::size_t button) const;
74
75private:
76 void UpdateThread();
77 void UpdateYuzuSettings();
78
79 struct MouseInfo {
80 InputCommon::MotionInput motion{0.0f, 0.0f, 0.0f};
81 Common::Vec2<int> mouse_origin;
82 Common::Vec2<int> last_mouse_position;
83 bool is_tilting = false;
84 float sensitivity{0.120f};
85
86 float tilt_speed = 0;
87 Common::Vec2<float> tilt_direction;
88 MouseData data;
89 };
90
91 u16 buttons{};
92 std::thread update_thread;
93 MouseButton last_button{MouseButton::Undefined};
94 std::array<MouseInfo, 5> mouse_info;
95 Common::SPSCQueue<MouseStatus> mouse_queue;
96 bool configuring{false};
97 bool update_thread_running{true};
98};
99} // namespace MouseInput
diff --git a/src/input_common/mouse/mouse_poller.cpp b/src/input_common/mouse/mouse_poller.cpp
new file mode 100644
index 000000000..6213f3dbd
--- /dev/null
+++ b/src/input_common/mouse/mouse_poller.cpp
@@ -0,0 +1,261 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <atomic>
6#include <list>
7#include <mutex>
8#include <utility>
9#include "common/assert.h"
10#include "common/threadsafe_queue.h"
11#include "input_common/mouse/mouse_input.h"
12#include "input_common/mouse/mouse_poller.h"
13
14namespace InputCommon {
15
16class MouseButton final : public Input::ButtonDevice {
17public:
18 explicit MouseButton(u32 button_, const MouseInput::Mouse* mouse_input_)
19 : button(button_), mouse_input(mouse_input_) {}
20
21 bool GetStatus() const override {
22 return mouse_input->GetMouseState(button).pressed;
23 }
24
25private:
26 const u32 button;
27 const MouseInput::Mouse* mouse_input;
28};
29
30MouseButtonFactory::MouseButtonFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
31 : mouse_input(std::move(mouse_input_)) {}
32
33std::unique_ptr<Input::ButtonDevice> MouseButtonFactory::Create(
34 const Common::ParamPackage& params) {
35 const auto button_id = params.Get("button", 0);
36
37 return std::make_unique<MouseButton>(button_id, mouse_input.get());
38}
39
40Common::ParamPackage MouseButtonFactory::GetNextInput() const {
41 MouseInput::MouseStatus pad;
42 Common::ParamPackage params;
43 auto& queue = mouse_input->GetMouseQueue();
44 while (queue.Pop(pad)) {
45 // This while loop will break on the earliest detected button
46 if (pad.button != MouseInput::MouseButton::Undefined) {
47 params.Set("engine", "mouse");
48 params.Set("button", static_cast<u16>(pad.button));
49 return params;
50 }
51 }
52 return params;
53}
54
55void MouseButtonFactory::BeginConfiguration() {
56 polling = true;
57 mouse_input->BeginConfiguration();
58}
59
60void MouseButtonFactory::EndConfiguration() {
61 polling = false;
62 mouse_input->EndConfiguration();
63}
64
65class MouseAnalog final : public Input::AnalogDevice {
66public:
67 explicit MouseAnalog(u32 port_, u32 axis_x_, u32 axis_y_, float deadzone_, float range_,
68 const MouseInput::Mouse* mouse_input_)
69 : button(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), range(range_),
70 mouse_input(mouse_input_) {}
71
72 float GetAxis(u32 axis) const {
73 std::lock_guard lock{mutex};
74 const auto axis_value =
75 static_cast<float>(mouse_input->GetMouseState(button).axis.at(axis));
76 return axis_value / (100.0f * range);
77 }
78
79 std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const {
80 float x = GetAxis(analog_axis_x);
81 float y = GetAxis(analog_axis_y);
82
83 // Make sure the coordinates are in the unit circle,
84 // otherwise normalize it.
85 float r = x * x + y * y;
86 if (r > 1.0f) {
87 r = std::sqrt(r);
88 x /= r;
89 y /= r;
90 }
91
92 return {x, y};
93 }
94
95 std::tuple<float, float> GetStatus() const override {
96 const auto [x, y] = GetAnalog(axis_x, axis_y);
97 const float r = std::sqrt((x * x) + (y * y));
98 if (r > deadzone) {
99 return {x / r * (r - deadzone) / (1 - deadzone),
100 y / r * (r - deadzone) / (1 - deadzone)};
101 }
102 return {0.0f, 0.0f};
103 }
104
105private:
106 const u32 button;
107 const u32 axis_x;
108 const u32 axis_y;
109 const float deadzone;
110 const float range;
111 const MouseInput::Mouse* mouse_input;
112 mutable std::mutex mutex;
113};
114
115/// An analog device factory that creates analog devices from GC Adapter
116MouseAnalogFactory::MouseAnalogFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
117 : mouse_input(std::move(mouse_input_)) {}
118
119/**
120 * Creates analog device from joystick axes
121 * @param params contains parameters for creating the device:
122 * - "port": the nth gcpad on the adapter
123 * - "axis_x": the index of the axis to be bind as x-axis
124 * - "axis_y": the index of the axis to be bind as y-axis
125 */
126std::unique_ptr<Input::AnalogDevice> MouseAnalogFactory::Create(
127 const Common::ParamPackage& params) {
128 const auto port = static_cast<u32>(params.Get("port", 0));
129 const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
130 const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
131 const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
132 const auto range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
133
134 return std::make_unique<MouseAnalog>(port, axis_x, axis_y, deadzone, range, mouse_input.get());
135}
136
137void MouseAnalogFactory::BeginConfiguration() {
138 polling = true;
139 mouse_input->BeginConfiguration();
140}
141
142void MouseAnalogFactory::EndConfiguration() {
143 polling = false;
144 mouse_input->EndConfiguration();
145}
146
147Common::ParamPackage MouseAnalogFactory::GetNextInput() const {
148 MouseInput::MouseStatus pad;
149 Common::ParamPackage params;
150 auto& queue = mouse_input->GetMouseQueue();
151 while (queue.Pop(pad)) {
152 // This while loop will break on the earliest detected button
153 if (pad.button != MouseInput::MouseButton::Undefined) {
154 params.Set("engine", "mouse");
155 params.Set("port", static_cast<u16>(pad.button));
156 params.Set("axis_x", 0);
157 params.Set("axis_y", 1);
158 return params;
159 }
160 }
161 return params;
162}
163
164class MouseMotion final : public Input::MotionDevice {
165public:
166 explicit MouseMotion(u32 button_, const MouseInput::Mouse* mouse_input_)
167 : button(button_), mouse_input(mouse_input_) {}
168
169 Input::MotionStatus GetStatus() const override {
170 return mouse_input->GetMouseState(button).motion;
171 }
172
173private:
174 const u32 button;
175 const MouseInput::Mouse* mouse_input;
176};
177
178MouseMotionFactory::MouseMotionFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
179 : mouse_input(std::move(mouse_input_)) {}
180
181std::unique_ptr<Input::MotionDevice> MouseMotionFactory::Create(
182 const Common::ParamPackage& params) {
183 const auto button_id = params.Get("button", 0);
184
185 return std::make_unique<MouseMotion>(button_id, mouse_input.get());
186}
187
188Common::ParamPackage MouseMotionFactory::GetNextInput() const {
189 MouseInput::MouseStatus pad;
190 Common::ParamPackage params;
191 auto& queue = mouse_input->GetMouseQueue();
192 while (queue.Pop(pad)) {
193 // This while loop will break on the earliest detected button
194 if (pad.button != MouseInput::MouseButton::Undefined) {
195 params.Set("engine", "mouse");
196 params.Set("button", static_cast<u16>(pad.button));
197 return params;
198 }
199 }
200 return params;
201}
202
203void MouseMotionFactory::BeginConfiguration() {
204 polling = true;
205 mouse_input->BeginConfiguration();
206}
207
208void MouseMotionFactory::EndConfiguration() {
209 polling = false;
210 mouse_input->EndConfiguration();
211}
212
213class MouseTouch final : public Input::TouchDevice {
214public:
215 explicit MouseTouch(u32 button_, const MouseInput::Mouse* mouse_input_)
216 : button(button_), mouse_input(mouse_input_) {}
217
218 Input::TouchStatus GetStatus() const override {
219 return mouse_input->GetMouseState(button).touch;
220 }
221
222private:
223 const u32 button;
224 const MouseInput::Mouse* mouse_input;
225};
226
227MouseTouchFactory::MouseTouchFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
228 : mouse_input(std::move(mouse_input_)) {}
229
230std::unique_ptr<Input::TouchDevice> MouseTouchFactory::Create(const Common::ParamPackage& params) {
231 const auto button_id = params.Get("button", 0);
232
233 return std::make_unique<MouseTouch>(button_id, mouse_input.get());
234}
235
236Common::ParamPackage MouseTouchFactory::GetNextInput() const {
237 MouseInput::MouseStatus pad;
238 Common::ParamPackage params;
239 auto& queue = mouse_input->GetMouseQueue();
240 while (queue.Pop(pad)) {
241 // This while loop will break on the earliest detected button
242 if (pad.button != MouseInput::MouseButton::Undefined) {
243 params.Set("engine", "mouse");
244 params.Set("button", static_cast<u16>(pad.button));
245 return params;
246 }
247 }
248 return params;
249}
250
251void MouseTouchFactory::BeginConfiguration() {
252 polling = true;
253 mouse_input->BeginConfiguration();
254}
255
256void MouseTouchFactory::EndConfiguration() {
257 polling = false;
258 mouse_input->EndConfiguration();
259}
260
261} // namespace InputCommon
diff --git a/src/input_common/mouse/mouse_poller.h b/src/input_common/mouse/mouse_poller.h
new file mode 100644
index 000000000..cf331293b
--- /dev/null
+++ b/src/input_common/mouse/mouse_poller.h
@@ -0,0 +1,109 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include "core/frontend/input.h"
9#include "input_common/mouse/mouse_input.h"
10
11namespace InputCommon {
12
13/**
14 * A button device factory representing a mouse. It receives mouse events and forward them
15 * to all button devices it created.
16 */
17class MouseButtonFactory final : public Input::Factory<Input::ButtonDevice> {
18public:
19 explicit MouseButtonFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_);
20
21 /**
22 * Creates a button device from a button press
23 * @param params contains parameters for creating the device:
24 * - "code": the code of the key to bind with the button
25 */
26 std::unique_ptr<Input::ButtonDevice> Create(const Common::ParamPackage& params) override;
27
28 Common::ParamPackage GetNextInput() const;
29
30 /// For device input configuration/polling
31 void BeginConfiguration();
32 void EndConfiguration();
33
34 bool IsPolling() const {
35 return polling;
36 }
37
38private:
39 std::shared_ptr<MouseInput::Mouse> mouse_input;
40 bool polling = false;
41};
42
43/// An analog device factory that creates analog devices from mouse
44class MouseAnalogFactory final : public Input::Factory<Input::AnalogDevice> {
45public:
46 explicit MouseAnalogFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_);
47
48 std::unique_ptr<Input::AnalogDevice> Create(const Common::ParamPackage& params) override;
49
50 Common::ParamPackage GetNextInput() const;
51
52 /// For device input configuration/polling
53 void BeginConfiguration();
54 void EndConfiguration();
55
56 bool IsPolling() const {
57 return polling;
58 }
59
60private:
61 std::shared_ptr<MouseInput::Mouse> mouse_input;
62 bool polling = false;
63};
64
65/// A motion device factory that creates motion devices from mouse
66class MouseMotionFactory final : public Input::Factory<Input::MotionDevice> {
67public:
68 explicit MouseMotionFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_);
69
70 std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override;
71
72 Common::ParamPackage GetNextInput() const;
73
74 /// For device input configuration/polling
75 void BeginConfiguration();
76 void EndConfiguration();
77
78 bool IsPolling() const {
79 return polling;
80 }
81
82private:
83 std::shared_ptr<MouseInput::Mouse> mouse_input;
84 bool polling = false;
85};
86
87/// An touch device factory that creates touch devices from mouse
88class MouseTouchFactory final : public Input::Factory<Input::TouchDevice> {
89public:
90 explicit MouseTouchFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_);
91
92 std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override;
93
94 Common::ParamPackage GetNextInput() const;
95
96 /// For device input configuration/polling
97 void BeginConfiguration();
98 void EndConfiguration();
99
100 bool IsPolling() const {
101 return polling;
102 }
103
104private:
105 std::shared_ptr<MouseInput::Mouse> mouse_input;
106 bool polling = false;
107};
108
109} // namespace InputCommon
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index d62b0efc2..d239ffbbd 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -35,7 +35,7 @@
35#include "core/settings.h" 35#include "core/settings.h"
36#include "input_common/keyboard.h" 36#include "input_common/keyboard.h"
37#include "input_common/main.h" 37#include "input_common/main.h"
38#include "input_common/motion_emu.h" 38#include "input_common/mouse/mouse_input.h"
39#include "video_core/renderer_base.h" 39#include "video_core/renderer_base.h"
40#include "video_core/video_core.h" 40#include "video_core/video_core.h"
41#include "yuzu/bootmanager.h" 41#include "yuzu/bootmanager.h"
@@ -382,23 +382,19 @@ void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
382} 382}
383 383
384void GRenderWindow::mousePressEvent(QMouseEvent* event) { 384void GRenderWindow::mousePressEvent(QMouseEvent* event) {
385 if (!Settings::values.touchscreen.enabled) {
386 input_subsystem->GetKeyboard()->PressKey(event->button());
387 return;
388 }
389
390 // Touch input is handled in TouchBeginEvent 385 // Touch input is handled in TouchBeginEvent
391 if (event->source() == Qt::MouseEventSynthesizedBySystem) { 386 if (event->source() == Qt::MouseEventSynthesizedBySystem) {
392 return; 387 return;
393 } 388 }
394 389
395 auto pos = event->pos(); 390 auto pos = event->pos();
391 const auto [x, y] = ScaleTouch(pos);
392 input_subsystem->GetMouse()->PressButton(x, y, event->button());
393
396 if (event->button() == Qt::LeftButton) { 394 if (event->button() == Qt::LeftButton) {
397 const auto [x, y] = ScaleTouch(pos);
398 this->TouchPressed(x, y); 395 this->TouchPressed(x, y);
399 } else if (event->button() == Qt::RightButton) {
400 input_subsystem->GetMotionEmu()->BeginTilt(pos.x(), pos.y());
401 } 396 }
397
402 QWidget::mousePressEvent(event); 398 QWidget::mousePressEvent(event);
403} 399}
404 400
@@ -410,26 +406,22 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
410 406
411 auto pos = event->pos(); 407 auto pos = event->pos();
412 const auto [x, y] = ScaleTouch(pos); 408 const auto [x, y] = ScaleTouch(pos);
409 input_subsystem->GetMouse()->MouseMove(x, y);
413 this->TouchMoved(x, y); 410 this->TouchMoved(x, y);
414 input_subsystem->GetMotionEmu()->Tilt(pos.x(), pos.y()); 411
415 QWidget::mouseMoveEvent(event); 412 QWidget::mouseMoveEvent(event);
416} 413}
417 414
418void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) { 415void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
419 if (!Settings::values.touchscreen.enabled) {
420 input_subsystem->GetKeyboard()->ReleaseKey(event->button());
421 return;
422 }
423
424 // Touch input is handled in TouchEndEvent 416 // Touch input is handled in TouchEndEvent
425 if (event->source() == Qt::MouseEventSynthesizedBySystem) { 417 if (event->source() == Qt::MouseEventSynthesizedBySystem) {
426 return; 418 return;
427 } 419 }
428 420
421 input_subsystem->GetMouse()->ReleaseButton(event->button());
422
429 if (event->button() == Qt::LeftButton) { 423 if (event->button() == Qt::LeftButton) {
430 this->TouchReleased(); 424 this->TouchReleased();
431 } else if (event->button() == Qt::RightButton) {
432 input_subsystem->GetMotionEmu()->EndTilt();
433 } 425 }
434} 426}
435 427
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 72640f5e7..87440a013 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -19,6 +19,7 @@
19#include "core/hle/service/sm/sm.h" 19#include "core/hle/service/sm/sm.h"
20#include "input_common/gcadapter/gc_poller.h" 20#include "input_common/gcadapter/gc_poller.h"
21#include "input_common/main.h" 21#include "input_common/main.h"
22#include "input_common/mouse/mouse_poller.h"
22#include "input_common/udp/udp.h" 23#include "input_common/udp/udp.h"
23#include "ui_configure_input_player.h" 24#include "ui_configure_input_player.h"
24#include "yuzu/configuration/config.h" 25#include "yuzu/configuration/config.h"
@@ -186,6 +187,14 @@ QString ButtonToText(const Common::ParamPackage& param) {
186 return {}; 187 return {};
187 } 188 }
188 189
190 if (param.Get("engine", "") == "mouse") {
191 if (param.Has("button")) {
192 const QString button_str = QString::number(int(param.Get("button", 0)));
193 return QObject::tr("Click %1").arg(button_str);
194 }
195 return GetKeyName(param.Get("code", 0));
196 }
197
189 return QObject::tr("[unknown]"); 198 return QObject::tr("[unknown]");
190} 199}
191 200
@@ -237,6 +246,26 @@ QString AnalogToText(const Common::ParamPackage& param, const std::string& dir)
237 246
238 return {}; 247 return {};
239 } 248 }
249
250 if (param.Get("engine", "") == "mouse") {
251 if (dir == "modifier") {
252 return QObject::tr("[unused]");
253 }
254
255 if (dir == "left" || dir == "right") {
256 const QString axis_x_str = QString::fromStdString(param.Get("axis_x", ""));
257
258 return QObject::tr("Mouse %1").arg(axis_x_str);
259 }
260
261 if (dir == "up" || dir == "down") {
262 const QString axis_y_str = QString::fromStdString(param.Get("axis_y", ""));
263
264 return QObject::tr("Mouse %1").arg(axis_y_str);
265 }
266
267 return {};
268 }
240 return QObject::tr("[unknown]"); 269 return QObject::tr("[unknown]");
241} 270}
242} // namespace 271} // namespace
@@ -532,6 +561,34 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
532 return; 561 return;
533 } 562 }
534 } 563 }
564 if (input_subsystem->GetMouseButtons()->IsPolling()) {
565 params = input_subsystem->GetMouseButtons()->GetNextInput();
566 if (params.Has("engine") && IsInputAcceptable(params)) {
567 SetPollingResult(params, false);
568 return;
569 }
570 }
571 if (input_subsystem->GetMouseAnalogs()->IsPolling()) {
572 params = input_subsystem->GetMouseAnalogs()->GetNextInput();
573 if (params.Has("engine") && IsInputAcceptable(params)) {
574 SetPollingResult(params, false);
575 return;
576 }
577 }
578 if (input_subsystem->GetMouseMotions()->IsPolling()) {
579 params = input_subsystem->GetMouseMotions()->GetNextInput();
580 if (params.Has("engine") && IsInputAcceptable(params)) {
581 SetPollingResult(params, false);
582 return;
583 }
584 }
585 if (input_subsystem->GetMouseTouch()->IsPolling()) {
586 params = input_subsystem->GetMouseTouch()->GetNextInput();
587 if (params.Has("engine") && IsInputAcceptable(params)) {
588 SetPollingResult(params, false);
589 return;
590 }
591 }
535 for (auto& poller : device_pollers) { 592 for (auto& poller : device_pollers) {
536 params = poller->GetNextInput(); 593 params = poller->GetNextInput();
537 if (params.Has("engine") && IsInputAcceptable(params)) { 594 if (params.Has("engine") && IsInputAcceptable(params)) {
@@ -809,8 +866,9 @@ void ConfigureInputPlayer::UpdateUI() {
809 866
810 int slider_value; 867 int slider_value;
811 auto& param = analogs_param[analog_id]; 868 auto& param = analogs_param[analog_id];
812 const bool is_controller = 869 const bool is_controller = param.Get("engine", "") == "sdl" ||
813 param.Get("engine", "") == "sdl" || param.Get("engine", "") == "gcpad"; 870 param.Get("engine", "") == "gcpad" ||
871 param.Get("engine", "") == "mouse";
814 872
815 if (is_controller) { 873 if (is_controller) {
816 if (!param.Has("deadzone")) { 874 if (!param.Has("deadzone")) {
@@ -1050,6 +1108,16 @@ void ConfigureInputPlayer::HandleClick(
1050 input_subsystem->GetUDPMotions()->BeginConfiguration(); 1108 input_subsystem->GetUDPMotions()->BeginConfiguration();
1051 } 1109 }
1052 1110
1111 if (type == InputCommon::Polling::DeviceType::Button) {
1112 input_subsystem->GetMouseButtons()->BeginConfiguration();
1113 } else if (type == InputCommon::Polling::DeviceType::AnalogPreferred) {
1114 input_subsystem->GetMouseAnalogs()->BeginConfiguration();
1115 } else if (type == InputCommon::Polling::DeviceType::Motion) {
1116 input_subsystem->GetMouseMotions()->BeginConfiguration();
1117 } else {
1118 input_subsystem->GetMouseTouch()->BeginConfiguration();
1119 }
1120
1053 timeout_timer->start(2500); // Cancel after 2.5 seconds 1121 timeout_timer->start(2500); // Cancel after 2.5 seconds
1054 poll_timer->start(50); // Check for new inputs every 50ms 1122 poll_timer->start(50); // Check for new inputs every 50ms
1055} 1123}
@@ -1069,6 +1137,11 @@ void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params,
1069 1137
1070 input_subsystem->GetUDPMotions()->EndConfiguration(); 1138 input_subsystem->GetUDPMotions()->EndConfiguration();
1071 1139
1140 input_subsystem->GetMouseButtons()->EndConfiguration();
1141 input_subsystem->GetMouseAnalogs()->EndConfiguration();
1142 input_subsystem->GetMouseMotions()->EndConfiguration();
1143 input_subsystem->GetMouseTouch()->EndConfiguration();
1144
1072 if (!abort) { 1145 if (!abort) {
1073 (*input_setter)(params); 1146 (*input_setter)(params);
1074 } 1147 }
@@ -1100,15 +1173,7 @@ void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) {
1100 return; 1173 return;
1101 } 1174 }
1102 1175
1103 if (want_keyboard_mouse) { 1176 input_subsystem->GetMouse()->PressButton(0, 0, event->button());
1104 SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->button())},
1105 false);
1106 } else {
1107 // We don't want any mouse buttons, so don't stop polling
1108 return;
1109 }
1110
1111 SetPollingResult({}, true);
1112} 1177}
1113 1178
1114void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { 1179void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
index 521209622..72ec25c99 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
@@ -9,7 +9,7 @@
9#include "core/perf_stats.h" 9#include "core/perf_stats.h"
10#include "input_common/keyboard.h" 10#include "input_common/keyboard.h"
11#include "input_common/main.h" 11#include "input_common/main.h"
12#include "input_common/motion_emu.h" 12#include "input_common/mouse/mouse_input.h"
13#include "input_common/sdl/sdl.h" 13#include "input_common/sdl/sdl.h"
14#include "yuzu_cmd/emu_window/emu_window_sdl2.h" 14#include "yuzu_cmd/emu_window/emu_window_sdl2.h"
15 15
@@ -30,7 +30,7 @@ EmuWindow_SDL2::~EmuWindow_SDL2() {
30 30
31void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { 31void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
32 TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); 32 TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0));
33 input_subsystem->GetMotionEmu()->Tilt(x, y); 33 input_subsystem->GetMouse()->MouseMove(x, y);
34} 34}
35 35
36void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { 36void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
@@ -42,9 +42,9 @@ void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
42 } 42 }
43 } else if (button == SDL_BUTTON_RIGHT) { 43 } else if (button == SDL_BUTTON_RIGHT) {
44 if (state == SDL_PRESSED) { 44 if (state == SDL_PRESSED) {
45 input_subsystem->GetMotionEmu()->BeginTilt(x, y); 45 input_subsystem->GetMouse()->PressButton(x, y, button);
46 } else { 46 } else {
47 input_subsystem->GetMotionEmu()->EndTilt(); 47 input_subsystem->GetMouse()->ReleaseButton(button);
48 } 48 }
49 } 49 }
50} 50}
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
index 5f35233b5..a103b04bd 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
@@ -17,7 +17,6 @@
17#include "core/settings.h" 17#include "core/settings.h"
18#include "input_common/keyboard.h" 18#include "input_common/keyboard.h"
19#include "input_common/main.h" 19#include "input_common/main.h"
20#include "input_common/motion_emu.h"
21#include "video_core/renderer_base.h" 20#include "video_core/renderer_base.h"
22#include "yuzu_cmd/emu_window/emu_window_sdl2_gl.h" 21#include "yuzu_cmd/emu_window/emu_window_sdl2_gl.h"
23 22