summaryrefslogtreecommitdiff
path: root/src/input_common/analog_from_button.cpp
diff options
context:
space:
mode:
authorGravatar german772021-09-20 16:57:55 -0500
committerGravatar Narr the Reg2021-11-24 20:30:22 -0600
commit4c6f2c2547e1d97f12ebe708fac693a6183bbc45 (patch)
tree0abcd35f56088bbf732a92838995a465bae0f0ee /src/input_common/analog_from_button.cpp
parentinput_common: Create input poller and mapping (diff)
downloadyuzu-4c6f2c2547e1d97f12ebe708fac693a6183bbc45.tar.gz
yuzu-4c6f2c2547e1d97f12ebe708fac693a6183bbc45.tar.xz
yuzu-4c6f2c2547e1d97f12ebe708fac693a6183bbc45.zip
input_common: Move touch and analog from button. Move udp protocol
Diffstat (limited to 'src/input_common/analog_from_button.cpp')
-rwxr-xr-xsrc/input_common/analog_from_button.cpp238
1 files changed, 0 insertions, 238 deletions
diff --git a/src/input_common/analog_from_button.cpp b/src/input_common/analog_from_button.cpp
deleted file mode 100755
index 2fafd077f..000000000
--- a/src/input_common/analog_from_button.cpp
+++ /dev/null
@@ -1,238 +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 <atomic>
6#include <chrono>
7#include <cmath>
8#include <thread>
9#include "common/math_util.h"
10#include "common/settings.h"
11#include "input_common/analog_from_button.h"
12
13namespace InputCommon {
14
15class Analog final : public Input::AnalogDevice {
16public:
17 using Button = std::unique_ptr<Input::ButtonDevice>;
18
19 Analog(Button up_, Button down_, Button left_, Button right_, Button modifier_,
20 float modifier_scale_, float modifier_angle_)
21 : up(std::move(up_)), down(std::move(down_)), left(std::move(left_)),
22 right(std::move(right_)), modifier(std::move(modifier_)), modifier_scale(modifier_scale_),
23 modifier_angle(modifier_angle_) {
24 Input::InputCallback<bool> callbacks{
25 [this]([[maybe_unused]] bool status) { UpdateStatus(); }};
26 up->SetCallback(callbacks);
27 down->SetCallback(callbacks);
28 left->SetCallback(callbacks);
29 right->SetCallback(callbacks);
30 modifier->SetCallback(callbacks);
31 }
32
33 bool IsAngleGreater(float old_angle, float new_angle) const {
34 constexpr float TAU = Common::PI * 2.0f;
35 // Use wider angle to ease the transition.
36 constexpr float aperture = TAU * 0.15f;
37 const float top_limit = new_angle + aperture;
38 return (old_angle > new_angle && old_angle <= top_limit) ||
39 (old_angle + TAU > new_angle && old_angle + TAU <= top_limit);
40 }
41
42 bool IsAngleSmaller(float old_angle, float new_angle) const {
43 constexpr float TAU = Common::PI * 2.0f;
44 // Use wider angle to ease the transition.
45 constexpr float aperture = TAU * 0.15f;
46 const float bottom_limit = new_angle - aperture;
47 return (old_angle >= bottom_limit && old_angle < new_angle) ||
48 (old_angle - TAU >= bottom_limit && old_angle - TAU < new_angle);
49 }
50
51 float GetAngle(std::chrono::time_point<std::chrono::steady_clock> now) const {
52 constexpr float TAU = Common::PI * 2.0f;
53 float new_angle = angle;
54
55 auto time_difference = static_cast<float>(
56 std::chrono::duration_cast<std::chrono::microseconds>(now - last_update).count());
57 time_difference /= 1000.0f * 1000.0f;
58 if (time_difference > 0.5f) {
59 time_difference = 0.5f;
60 }
61
62 if (IsAngleGreater(new_angle, goal_angle)) {
63 new_angle -= modifier_angle * time_difference;
64 if (new_angle < 0) {
65 new_angle += TAU;
66 }
67 if (!IsAngleGreater(new_angle, goal_angle)) {
68 return goal_angle;
69 }
70 } else if (IsAngleSmaller(new_angle, goal_angle)) {
71 new_angle += modifier_angle * time_difference;
72 if (new_angle >= TAU) {
73 new_angle -= TAU;
74 }
75 if (!IsAngleSmaller(new_angle, goal_angle)) {
76 return goal_angle;
77 }
78 } else {
79 return goal_angle;
80 }
81 return new_angle;
82 }
83
84 void SetGoalAngle(bool r, bool l, bool u, bool d) {
85 // Move to the right
86 if (r && !u && !d) {
87 goal_angle = 0.0f;
88 }
89
90 // Move to the upper right
91 if (r && u && !d) {
92 goal_angle = Common::PI * 0.25f;
93 }
94
95 // Move up
96 if (u && !l && !r) {
97 goal_angle = Common::PI * 0.5f;
98 }
99
100 // Move to the upper left
101 if (l && u && !d) {
102 goal_angle = Common::PI * 0.75f;
103 }
104
105 // Move to the left
106 if (l && !u && !d) {
107 goal_angle = Common::PI;
108 }
109
110 // Move to the bottom left
111 if (l && !u && d) {
112 goal_angle = Common::PI * 1.25f;
113 }
114
115 // Move down
116 if (d && !l && !r) {
117 goal_angle = Common::PI * 1.5f;
118 }
119
120 // Move to the bottom right
121 if (r && !u && d) {
122 goal_angle = Common::PI * 1.75f;
123 }
124 }
125
126 void UpdateStatus() {
127 const float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
128
129 bool r = right->GetStatus();
130 bool l = left->GetStatus();
131 bool u = up->GetStatus();
132 bool d = down->GetStatus();
133
134 // Eliminate contradictory movements
135 if (r && l) {
136 r = false;
137 l = false;
138 }
139 if (u && d) {
140 u = false;
141 d = false;
142 }
143
144 // Move if a key is pressed
145 if (r || l || u || d) {
146 amplitude = coef;
147 } else {
148 amplitude = 0;
149 }
150
151 const auto now = std::chrono::steady_clock::now();
152 const auto time_difference = static_cast<u64>(
153 std::chrono::duration_cast<std::chrono::milliseconds>(now - last_update).count());
154
155 if (time_difference < 10) {
156 // Disable analog mode if inputs are too fast
157 SetGoalAngle(r, l, u, d);
158 angle = goal_angle;
159 } else {
160 angle = GetAngle(now);
161 SetGoalAngle(r, l, u, d);
162 }
163
164 last_update = now;
165 }
166
167 std::tuple<float, float> GetStatus() const override {
168 if (Settings::values.emulate_analog_keyboard) {
169 const auto now = std::chrono::steady_clock::now();
170 float angle_ = GetAngle(now);
171 return std::make_tuple(std::cos(angle_) * amplitude, std::sin(angle_) * amplitude);
172 }
173 constexpr float SQRT_HALF = 0.707106781f;
174 int x = 0, y = 0;
175 if (right->GetStatus()) {
176 ++x;
177 }
178 if (left->GetStatus()) {
179 --x;
180 }
181 if (up->GetStatus()) {
182 ++y;
183 }
184 if (down->GetStatus()) {
185 --y;
186 }
187 const float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
188 return std::make_tuple(static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF),
189 static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF));
190 }
191
192 Input::AnalogProperties GetAnalogProperties() const override {
193 return {modifier_scale, 1.0f, 0.5f};
194 }
195
196 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
197 switch (direction) {
198 case Input::AnalogDirection::RIGHT:
199 return right->GetStatus();
200 case Input::AnalogDirection::LEFT:
201 return left->GetStatus();
202 case Input::AnalogDirection::UP:
203 return up->GetStatus();
204 case Input::AnalogDirection::DOWN:
205 return down->GetStatus();
206 }
207 return false;
208 }
209
210private:
211 Button up;
212 Button down;
213 Button left;
214 Button right;
215 Button modifier;
216 float modifier_scale;
217 float modifier_angle;
218 float angle{};
219 float goal_angle{};
220 float amplitude{};
221 std::chrono::time_point<std::chrono::steady_clock> last_update;
222};
223
224std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::ParamPackage& params) {
225 const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
226 auto up = Input::CreateDevice<Input::ButtonDevice>(params.Get("up", null_engine));
227 auto down = Input::CreateDevice<Input::ButtonDevice>(params.Get("down", null_engine));
228 auto left = Input::CreateDevice<Input::ButtonDevice>(params.Get("left", null_engine));
229 auto right = Input::CreateDevice<Input::ButtonDevice>(params.Get("right", null_engine));
230 auto modifier = Input::CreateDevice<Input::ButtonDevice>(params.Get("modifier", null_engine));
231 auto modifier_scale = params.Get("modifier_scale", 0.5f);
232 auto modifier_angle = params.Get("modifier_angle", 5.5f);
233 return std::make_unique<Analog>(std::move(up), std::move(down), std::move(left),
234 std::move(right), std::move(modifier), modifier_scale,
235 modifier_angle);
236}
237
238} // namespace InputCommon