summaryrefslogtreecommitdiff
path: root/src/input_common/gcadapter/gc_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/gcadapter/gc_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/gcadapter/gc_poller.cpp')
-rw-r--r--src/input_common/gcadapter/gc_poller.cpp226
1 files changed, 142 insertions, 84 deletions
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp
index 92e9e8e89..9670bdeb2 100644
--- a/src/input_common/gcadapter/gc_poller.cpp
+++ b/src/input_common/gcadapter/gc_poller.cpp
@@ -15,36 +15,35 @@ namespace InputCommon {
15 15
16class GCButton final : public Input::ButtonDevice { 16class GCButton final : public Input::ButtonDevice {
17public: 17public:
18 explicit GCButton(int port_, int button_, const GCAdapter::Adapter* adapter) 18 explicit GCButton(u32 port_, s32 button_, const GCAdapter::Adapter* adapter)
19 : port(port_), button(button_), gcadapter(adapter) {} 19 : port(port_), button(button_), gcadapter(adapter) {}
20 20
21 ~GCButton() override; 21 ~GCButton() override;
22 22
23 bool GetStatus() const override { 23 bool GetStatus() const override {
24 if (gcadapter->DeviceConnected(port)) { 24 if (gcadapter->DeviceConnected(port)) {
25 return gcadapter->GetPadState()[port].buttons.at(button); 25 return (gcadapter->GetPadState(port).buttons & button) != 0;
26 } 26 }
27 return false; 27 return false;
28 } 28 }
29 29
30private: 30private:
31 const int port; 31 const u32 port;
32 const int button; 32 const s32 button;
33 const GCAdapter::Adapter* gcadapter; 33 const GCAdapter::Adapter* gcadapter;
34}; 34};
35 35
36class GCAxisButton final : public Input::ButtonDevice { 36class GCAxisButton final : public Input::ButtonDevice {
37public: 37public:
38 explicit GCAxisButton(int port_, int axis_, float threshold_, bool trigger_if_greater_, 38 explicit GCAxisButton(u32 port_, u32 axis_, float threshold_, bool trigger_if_greater_,
39 const GCAdapter::Adapter* adapter) 39 const GCAdapter::Adapter* adapter)
40 : port(port_), axis(axis_), threshold(threshold_), trigger_if_greater(trigger_if_greater_), 40 : port(port_), axis(axis_), threshold(threshold_), trigger_if_greater(trigger_if_greater_),
41 gcadapter(adapter), 41 gcadapter(adapter) {}
42 origin_value(static_cast<float>(adapter->GetOriginValue(port_, axis_))) {}
43 42
44 bool GetStatus() const override { 43 bool GetStatus() const override {
45 if (gcadapter->DeviceConnected(port)) { 44 if (gcadapter->DeviceConnected(port)) {
46 const float current_axis_value = gcadapter->GetPadState()[port].axes.at(axis); 45 const float current_axis_value = gcadapter->GetPadState(port).axis_values.at(axis);
47 const float axis_value = (current_axis_value - origin_value) / 128.0f; 46 const float axis_value = current_axis_value / 128.0f;
48 if (trigger_if_greater) { 47 if (trigger_if_greater) {
49 // TODO: Might be worthwile to set a slider for the trigger threshold. It is 48 // TODO: Might be worthwile to set a slider for the trigger threshold. It is
50 // currently always set to 0.5 in configure_input_player.cpp ZL/ZR HandleClick 49 // currently always set to 0.5 in configure_input_player.cpp ZL/ZR HandleClick
@@ -56,12 +55,11 @@ public:
56 } 55 }
57 56
58private: 57private:
59 const int port; 58 const u32 port;
60 const int axis; 59 const u32 axis;
61 float threshold; 60 float threshold;
62 bool trigger_if_greater; 61 bool trigger_if_greater;
63 const GCAdapter::Adapter* gcadapter; 62 const GCAdapter::Adapter* gcadapter;
64 const float origin_value;
65}; 63};
66 64
67GCButtonFactory::GCButtonFactory(std::shared_ptr<GCAdapter::Adapter> adapter_) 65GCButtonFactory::GCButtonFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
@@ -70,10 +68,10 @@ GCButtonFactory::GCButtonFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
70GCButton::~GCButton() = default; 68GCButton::~GCButton() = default;
71 69
72std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::ParamPackage& params) { 70std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::ParamPackage& params) {
73 const int button_id = params.Get("button", 0); 71 const auto button_id = params.Get("button", 0);
74 const int port = params.Get("port", 0); 72 const auto port = static_cast<u32>(params.Get("port", 0));
75 73
76 constexpr int PAD_STICK_ID = static_cast<u16>(GCAdapter::PadButton::PAD_STICK); 74 constexpr s32 PAD_STICK_ID = static_cast<s32>(GCAdapter::PadButton::Stick);
77 75
78 // button is not an axis/stick button 76 // button is not an axis/stick button
79 if (button_id != PAD_STICK_ID) { 77 if (button_id != PAD_STICK_ID) {
@@ -98,7 +96,6 @@ std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::Param
98 adapter.get()); 96 adapter.get());
99 } 97 }
100 98
101 UNREACHABLE();
102 return nullptr; 99 return nullptr;
103} 100}
104 101
@@ -106,32 +103,25 @@ Common::ParamPackage GCButtonFactory::GetNextInput() const {
106 Common::ParamPackage params; 103 Common::ParamPackage params;
107 GCAdapter::GCPadStatus pad; 104 GCAdapter::GCPadStatus pad;
108 auto& queue = adapter->GetPadQueue(); 105 auto& queue = adapter->GetPadQueue();
109 for (std::size_t port = 0; port < queue.size(); ++port) { 106 while (queue.Pop(pad)) {
110 while (queue[port].Pop(pad)) { 107 // This while loop will break on the earliest detected button
111 // This while loop will break on the earliest detected button 108 params.Set("engine", "gcpad");
112 params.Set("engine", "gcpad"); 109 params.Set("port", static_cast<s32>(pad.port));
113 params.Set("port", static_cast<int>(port)); 110 if (pad.button != GCAdapter::PadButton::Undefined) {
114 for (const auto& button : GCAdapter::PadButtonArray) { 111 params.Set("button", static_cast<u16>(pad.button));
115 const u16 button_value = static_cast<u16>(button); 112 }
116 if (pad.button & button_value) {
117 params.Set("button", button_value);
118 break;
119 }
120 }
121 113
122 // For Axis button implementation 114 // For Axis button implementation
123 if (pad.axis != GCAdapter::PadAxes::Undefined) { 115 if (pad.axis != GCAdapter::PadAxes::Undefined) {
124 params.Set("axis", static_cast<u8>(pad.axis)); 116 params.Set("axis", static_cast<u8>(pad.axis));
125 params.Set("button", static_cast<u16>(GCAdapter::PadButton::PAD_STICK)); 117 params.Set("button", static_cast<u16>(GCAdapter::PadButton::Stick));
126 if (pad.axis_value > 128) { 118 params.Set("threshold", "0.25");
127 params.Set("direction", "+"); 119 if (pad.axis_value > 0) {
128 params.Set("threshold", "0.25"); 120 params.Set("direction", "+");
129 } else { 121 } else {
130 params.Set("direction", "-"); 122 params.Set("direction", "-");
131 params.Set("threshold", "-0.25");
132 }
133 break;
134 } 123 }
124 break;
135 } 125 }
136 } 126 }
137 return params; 127 return params;
@@ -149,26 +139,30 @@ void GCButtonFactory::EndConfiguration() {
149 139
150class GCAnalog final : public Input::AnalogDevice { 140class GCAnalog final : public Input::AnalogDevice {
151public: 141public:
152 GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_, 142 explicit GCAnalog(u32 port_, u32 axis_x_, u32 axis_y_, bool invert_x_, bool invert_y_,
153 const GCAdapter::Adapter* adapter, float range_) 143 float deadzone_, float range_, const GCAdapter::Adapter* adapter)
154 : port(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), gcadapter(adapter), 144 : port(port_), axis_x(axis_x_), axis_y(axis_y_), invert_x(invert_x_), invert_y(invert_y_),
155 origin_value_x(static_cast<float>(adapter->GetOriginValue(port_, axis_x_))), 145 deadzone(deadzone_), range(range_), gcadapter(adapter) {}
156 origin_value_y(static_cast<float>(adapter->GetOriginValue(port_, axis_y_))), 146
157 range(range_) {} 147 float GetAxis(u32 axis) const {
158
159 float GetAxis(int axis) const {
160 if (gcadapter->DeviceConnected(port)) { 148 if (gcadapter->DeviceConnected(port)) {
161 std::lock_guard lock{mutex}; 149 std::lock_guard lock{mutex};
162 const auto origin_value = axis % 2 == 0 ? origin_value_x : origin_value_y; 150 const auto axis_value =
163 return (gcadapter->GetPadState()[port].axes.at(axis) - origin_value) / (100.0f * range); 151 static_cast<float>(gcadapter->GetPadState(port).axis_values.at(axis));
152 return (axis_value) / (100.0f * range);
164 } 153 }
165 return 0.0f; 154 return 0.0f;
166 } 155 }
167 156
168 std::pair<float, float> GetAnalog(int axis_x, int axis_y) const { 157 std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const {
169 float x = GetAxis(axis_x); 158 float x = GetAxis(analog_axis_x);
170 float y = GetAxis(axis_y); 159 float y = GetAxis(analog_axis_y);
171 160 if (invert_x) {
161 x = -x;
162 }
163 if (invert_y) {
164 y = -y;
165 }
172 // Make sure the coordinates are in the unit circle, 166 // Make sure the coordinates are in the unit circle,
173 // otherwise normalize it. 167 // otherwise normalize it.
174 float r = x * x + y * y; 168 float r = x * x + y * y;
@@ -208,14 +202,14 @@ public:
208 } 202 }
209 203
210private: 204private:
211 const int port; 205 const u32 port;
212 const int axis_x; 206 const u32 axis_x;
213 const int axis_y; 207 const u32 axis_y;
208 const bool invert_x;
209 const bool invert_y;
214 const float deadzone; 210 const float deadzone;
215 const GCAdapter::Adapter* gcadapter;
216 const float origin_value_x;
217 const float origin_value_y;
218 const float range; 211 const float range;
212 const GCAdapter::Adapter* gcadapter;
219 mutable std::mutex mutex; 213 mutable std::mutex mutex;
220}; 214};
221 215
@@ -231,13 +225,18 @@ GCAnalogFactory::GCAnalogFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
231 * - "axis_y": the index of the axis to be bind as y-axis 225 * - "axis_y": the index of the axis to be bind as y-axis
232 */ 226 */
233std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::ParamPackage& params) { 227std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::ParamPackage& params) {
234 const int port = params.Get("port", 0); 228 const auto port = static_cast<u32>(params.Get("port", 0));
235 const int axis_x = params.Get("axis_x", 0); 229 const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
236 const int axis_y = params.Get("axis_y", 1); 230 const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
237 const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f); 231 const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
238 const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f); 232 const auto range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f);
239 233 const std::string invert_x_value = params.Get("invert_x", "+");
240 return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get(), range); 234 const std::string invert_y_value = params.Get("invert_y", "+");
235 const bool invert_x = invert_x_value == "-";
236 const bool invert_y = invert_y_value == "-";
237
238 return std::make_unique<GCAnalog>(port, axis_x, axis_y, invert_x, invert_y, deadzone, range,
239 adapter.get());
241} 240}
242 241
243void GCAnalogFactory::BeginConfiguration() { 242void GCAnalogFactory::BeginConfiguration() {
@@ -252,31 +251,51 @@ void GCAnalogFactory::EndConfiguration() {
252 251
253Common::ParamPackage GCAnalogFactory::GetNextInput() { 252Common::ParamPackage GCAnalogFactory::GetNextInput() {
254 GCAdapter::GCPadStatus pad; 253 GCAdapter::GCPadStatus pad;
254 Common::ParamPackage params;
255 auto& queue = adapter->GetPadQueue(); 255 auto& queue = adapter->GetPadQueue();
256 for (std::size_t port = 0; port < queue.size(); ++port) { 256 while (queue.Pop(pad)) {
257 while (queue[port].Pop(pad)) { 257 if (pad.button != GCAdapter::PadButton::Undefined) {
258 if (pad.axis == GCAdapter::PadAxes::Undefined || 258 params.Set("engine", "gcpad");
259 std::abs((pad.axis_value - 128.0f) / 128.0f) < 0.1) { 259 params.Set("port", static_cast<s32>(pad.port));
260 continue; 260 params.Set("button", static_cast<u16>(pad.button));
261 } 261 return params;
262 // An analog device needs two axes, so we need to store the axis for later and wait for 262 }
263 // a second input event. The axes also must be from the same joystick. 263 if (pad.axis == GCAdapter::PadAxes::Undefined ||
264 const u8 axis = static_cast<u8>(pad.axis); 264 std::abs(static_cast<float>(pad.axis_value) / 128.0f) < 0.1f) {
265 if (analog_x_axis == -1) { 265 continue;
266 analog_x_axis = axis; 266 }
267 controller_number = static_cast<int>(port); 267 // An analog device needs two axes, so we need to store the axis for later and wait for
268 } else if (analog_y_axis == -1 && analog_x_axis != axis && 268 // a second input event. The axes also must be from the same joystick.
269 controller_number == static_cast<int>(port)) { 269 const u8 axis = static_cast<u8>(pad.axis);
270 analog_y_axis = axis; 270 if (axis == 0 || axis == 1) {
271 } 271 analog_x_axis = 0;
272 analog_y_axis = 1;
273 controller_number = static_cast<s32>(pad.port);
274 break;
275 }
276 if (axis == 2 || axis == 3) {
277 analog_x_axis = 2;
278 analog_y_axis = 3;
279 controller_number = static_cast<s32>(pad.port);
280 break;
281 }
282
283 if (analog_x_axis == -1) {
284 analog_x_axis = axis;
285 controller_number = static_cast<s32>(pad.port);
286 } else if (analog_y_axis == -1 && analog_x_axis != axis &&
287 controller_number == static_cast<s32>(pad.port)) {
288 analog_y_axis = axis;
289 break;
272 } 290 }
273 } 291 }
274 Common::ParamPackage params;
275 if (analog_x_axis != -1 && analog_y_axis != -1) { 292 if (analog_x_axis != -1 && analog_y_axis != -1) {
276 params.Set("engine", "gcpad"); 293 params.Set("engine", "gcpad");
277 params.Set("port", controller_number); 294 params.Set("port", controller_number);
278 params.Set("axis_x", analog_x_axis); 295 params.Set("axis_x", analog_x_axis);
279 params.Set("axis_y", analog_y_axis); 296 params.Set("axis_y", analog_y_axis);
297 params.Set("invert_x", "+");
298 params.Set("invert_y", "+");
280 analog_x_axis = -1; 299 analog_x_axis = -1;
281 analog_y_axis = -1; 300 analog_y_axis = -1;
282 controller_number = -1; 301 controller_number = -1;
@@ -285,4 +304,43 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() {
285 return params; 304 return params;
286} 305}
287 306
307class GCVibration final : public Input::VibrationDevice {
308public:
309 explicit GCVibration(u32 port_, GCAdapter::Adapter* adapter)
310 : port(port_), gcadapter(adapter) {}
311
312 u8 GetStatus() const override {
313 return gcadapter->RumblePlay(port, 0);
314 }
315
316 bool SetRumblePlay(f32 amp_low, [[maybe_unused]] f32 freq_low, f32 amp_high,
317 [[maybe_unused]] f32 freq_high) const override {
318 const auto mean_amplitude = (amp_low + amp_high) * 0.5f;
319 const auto processed_amplitude =
320 static_cast<u8>((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8);
321
322 return gcadapter->RumblePlay(port, processed_amplitude);
323 }
324
325private:
326 const u32 port;
327 GCAdapter::Adapter* gcadapter;
328};
329
330/// An vibration device factory that creates vibration devices from GC Adapter
331GCVibrationFactory::GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
332 : adapter(std::move(adapter_)) {}
333
334/**
335 * Creates a vibration device from a joystick
336 * @param params contains parameters for creating the device:
337 * - "port": the nth gcpad on the adapter
338 */
339std::unique_ptr<Input::VibrationDevice> GCVibrationFactory::Create(
340 const Common::ParamPackage& params) {
341 const auto port = static_cast<u32>(params.Get("port", 0));
342
343 return std::make_unique<GCVibration>(port, adapter.get());
344}
345
288} // namespace InputCommon 346} // namespace InputCommon