summaryrefslogtreecommitdiff
path: root/src/input_common/mouse/mouse_poller.cpp
diff options
context:
space:
mode:
authorGravatar Levi2021-01-10 22:09:56 -0700
committerGravatar Levi2021-01-10 22:09:56 -0700
commit7a3c884e39fccfbb498b855080bffabc9ce2e7f1 (patch)
tree5056f9406dec188439cb0deb87603498243a9412 /src/input_common/mouse/mouse_poller.cpp
parentMore forgetting... duh (diff)
parentMerge pull request #5229 from Morph1984/fullscreen-opt (diff)
downloadyuzu-7a3c884e39fccfbb498b855080bffabc9ce2e7f1.tar.gz
yuzu-7a3c884e39fccfbb498b855080bffabc9ce2e7f1.tar.xz
yuzu-7a3c884e39fccfbb498b855080bffabc9ce2e7f1.zip
Merge remote-tracking branch 'upstream/master' into int-flags
Diffstat (limited to 'src/input_common/mouse/mouse_poller.cpp')
-rw-r--r--src/input_common/mouse/mouse_poller.cpp274
1 files changed, 274 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..508eb0c7d
--- /dev/null
+++ b/src/input_common/mouse/mouse_poller.cpp
@@ -0,0 +1,274 @@
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 <mutex>
6#include <utility>
7
8#include "common/threadsafe_queue.h"
9#include "input_common/mouse/mouse_input.h"
10#include "input_common/mouse/mouse_poller.h"
11
12namespace InputCommon {
13
14class MouseButton final : public Input::ButtonDevice {
15public:
16 explicit MouseButton(u32 button_, const MouseInput::Mouse* mouse_input_)
17 : button(button_), mouse_input(mouse_input_) {}
18
19 bool GetStatus() const override {
20 return mouse_input->GetMouseState(button).pressed;
21 }
22
23private:
24 const u32 button;
25 const MouseInput::Mouse* mouse_input;
26};
27
28MouseButtonFactory::MouseButtonFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
29 : mouse_input(std::move(mouse_input_)) {}
30
31std::unique_ptr<Input::ButtonDevice> MouseButtonFactory::Create(
32 const Common::ParamPackage& params) {
33 const auto button_id = params.Get("button", 0);
34
35 return std::make_unique<MouseButton>(button_id, mouse_input.get());
36}
37
38Common::ParamPackage MouseButtonFactory::GetNextInput() const {
39 MouseInput::MouseStatus pad;
40 Common::ParamPackage params;
41 auto& queue = mouse_input->GetMouseQueue();
42 while (queue.Pop(pad)) {
43 // This while loop will break on the earliest detected button
44 if (pad.button != MouseInput::MouseButton::Undefined) {
45 params.Set("engine", "mouse");
46 params.Set("button", static_cast<u16>(pad.button));
47 return params;
48 }
49 }
50 return params;
51}
52
53void MouseButtonFactory::BeginConfiguration() {
54 polling = true;
55 mouse_input->BeginConfiguration();
56}
57
58void MouseButtonFactory::EndConfiguration() {
59 polling = false;
60 mouse_input->EndConfiguration();
61}
62
63class MouseAnalog final : public Input::AnalogDevice {
64public:
65 explicit MouseAnalog(u32 port_, u32 axis_x_, u32 axis_y_, bool invert_x_, bool invert_y_,
66 float deadzone_, float range_, const MouseInput::Mouse* mouse_input_)
67 : button(port_), axis_x(axis_x_), axis_y(axis_y_), invert_x(invert_x_), invert_y(invert_y_),
68 deadzone(deadzone_), range(range_), mouse_input(mouse_input_) {}
69
70 float GetAxis(u32 axis) const {
71 std::lock_guard lock{mutex};
72 const auto axis_value =
73 static_cast<float>(mouse_input->GetMouseState(button).axis.at(axis));
74 return axis_value / (100.0f * range);
75 }
76
77 std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const {
78 float x = GetAxis(analog_axis_x);
79 float y = GetAxis(analog_axis_y);
80 if (invert_x) {
81 x = -x;
82 }
83 if (invert_y) {
84 y = -y;
85 }
86
87 // Make sure the coordinates are in the unit circle,
88 // otherwise normalize it.
89 float r = x * x + y * y;
90 if (r > 1.0f) {
91 r = std::sqrt(r);
92 x /= r;
93 y /= r;
94 }
95
96 return {x, y};
97 }
98
99 std::tuple<float, float> GetStatus() const override {
100 const auto [x, y] = GetAnalog(axis_x, axis_y);
101 const float r = std::sqrt((x * x) + (y * y));
102 if (r > deadzone) {
103 return {x / r * (r - deadzone) / (1 - deadzone),
104 y / r * (r - deadzone) / (1 - deadzone)};
105 }
106 return {0.0f, 0.0f};
107 }
108
109private:
110 const u32 button;
111 const u32 axis_x;
112 const u32 axis_y;
113 const bool invert_x;
114 const bool invert_y;
115 const float deadzone;
116 const float range;
117 const MouseInput::Mouse* mouse_input;
118 mutable std::mutex mutex;
119};
120
121/// An analog device factory that creates analog devices from GC Adapter
122MouseAnalogFactory::MouseAnalogFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
123 : mouse_input(std::move(mouse_input_)) {}
124
125/**
126 * Creates analog device from joystick axes
127 * @param params contains parameters for creating the device:
128 * - "port": the nth gcpad on the adapter
129 * - "axis_x": the index of the axis to be bind as x-axis
130 * - "axis_y": the index of the axis to be bind as y-axis
131 */
132std::unique_ptr<Input::AnalogDevice> MouseAnalogFactory::Create(
133 const Common::ParamPackage& params) {
134 const auto port = static_cast<u32>(params.Get("port", 0));
135 const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
136 const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
137 const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
138 const auto range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
139 const std::string invert_x_value = params.Get("invert_x", "+");
140 const std::string invert_y_value = params.Get("invert_y", "+");
141 const bool invert_x = invert_x_value == "-";
142 const bool invert_y = invert_y_value == "-";
143
144 return std::make_unique<MouseAnalog>(port, axis_x, axis_y, invert_x, invert_y, deadzone, range,
145 mouse_input.get());
146}
147
148void MouseAnalogFactory::BeginConfiguration() {
149 polling = true;
150 mouse_input->BeginConfiguration();
151}
152
153void MouseAnalogFactory::EndConfiguration() {
154 polling = false;
155 mouse_input->EndConfiguration();
156}
157
158Common::ParamPackage MouseAnalogFactory::GetNextInput() const {
159 MouseInput::MouseStatus pad;
160 Common::ParamPackage params;
161 auto& queue = mouse_input->GetMouseQueue();
162 while (queue.Pop(pad)) {
163 // This while loop will break on the earliest detected button
164 if (pad.button != MouseInput::MouseButton::Undefined) {
165 params.Set("engine", "mouse");
166 params.Set("port", static_cast<u16>(pad.button));
167 params.Set("axis_x", 0);
168 params.Set("axis_y", 1);
169 params.Set("invert_x", "+");
170 params.Set("invert_y", "+");
171 return params;
172 }
173 }
174 return params;
175}
176
177class MouseMotion final : public Input::MotionDevice {
178public:
179 explicit MouseMotion(u32 button_, const MouseInput::Mouse* mouse_input_)
180 : button(button_), mouse_input(mouse_input_) {}
181
182 Input::MotionStatus GetStatus() const override {
183 return mouse_input->GetMouseState(button).motion;
184 }
185
186private:
187 const u32 button;
188 const MouseInput::Mouse* mouse_input;
189};
190
191MouseMotionFactory::MouseMotionFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
192 : mouse_input(std::move(mouse_input_)) {}
193
194std::unique_ptr<Input::MotionDevice> MouseMotionFactory::Create(
195 const Common::ParamPackage& params) {
196 const auto button_id = params.Get("button", 0);
197
198 return std::make_unique<MouseMotion>(button_id, mouse_input.get());
199}
200
201Common::ParamPackage MouseMotionFactory::GetNextInput() const {
202 MouseInput::MouseStatus pad;
203 Common::ParamPackage params;
204 auto& queue = mouse_input->GetMouseQueue();
205 while (queue.Pop(pad)) {
206 // This while loop will break on the earliest detected button
207 if (pad.button != MouseInput::MouseButton::Undefined) {
208 params.Set("engine", "mouse");
209 params.Set("button", static_cast<u16>(pad.button));
210 return params;
211 }
212 }
213 return params;
214}
215
216void MouseMotionFactory::BeginConfiguration() {
217 polling = true;
218 mouse_input->BeginConfiguration();
219}
220
221void MouseMotionFactory::EndConfiguration() {
222 polling = false;
223 mouse_input->EndConfiguration();
224}
225
226class MouseTouch final : public Input::TouchDevice {
227public:
228 explicit MouseTouch(u32 button_, const MouseInput::Mouse* mouse_input_)
229 : button(button_), mouse_input(mouse_input_) {}
230
231 Input::TouchStatus GetStatus() const override {
232 return mouse_input->GetMouseState(button).touch;
233 }
234
235private:
236 const u32 button;
237 const MouseInput::Mouse* mouse_input;
238};
239
240MouseTouchFactory::MouseTouchFactory(std::shared_ptr<MouseInput::Mouse> mouse_input_)
241 : mouse_input(std::move(mouse_input_)) {}
242
243std::unique_ptr<Input::TouchDevice> MouseTouchFactory::Create(const Common::ParamPackage& params) {
244 const auto button_id = params.Get("button", 0);
245
246 return std::make_unique<MouseTouch>(button_id, mouse_input.get());
247}
248
249Common::ParamPackage MouseTouchFactory::GetNextInput() const {
250 MouseInput::MouseStatus pad;
251 Common::ParamPackage params;
252 auto& queue = mouse_input->GetMouseQueue();
253 while (queue.Pop(pad)) {
254 // This while loop will break on the earliest detected button
255 if (pad.button != MouseInput::MouseButton::Undefined) {
256 params.Set("engine", "mouse");
257 params.Set("button", static_cast<u16>(pad.button));
258 return params;
259 }
260 }
261 return params;
262}
263
264void MouseTouchFactory::BeginConfiguration() {
265 polling = true;
266 mouse_input->BeginConfiguration();
267}
268
269void MouseTouchFactory::EndConfiguration() {
270 polling = false;
271 mouse_input->EndConfiguration();
272}
273
274} // namespace InputCommon