summaryrefslogtreecommitdiff
path: root/src/input_common/mouse/mouse_poller.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/mouse/mouse_poller.cpp')
-rw-r--r--src/input_common/mouse/mouse_poller.cpp261
1 files changed, 261 insertions, 0 deletions
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