summaryrefslogtreecommitdiff
path: root/src/input_common/analog_from_button.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/analog_from_button.cpp')
-rwxr-xr-xsrc/input_common/analog_from_button.cpp134
1 files changed, 121 insertions, 13 deletions
diff --git a/src/input_common/analog_from_button.cpp b/src/input_common/analog_from_button.cpp
index 6cabdaa3c..40b516f85 100755
--- a/src/input_common/analog_from_button.cpp
+++ b/src/input_common/analog_from_button.cpp
@@ -2,6 +2,11 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <chrono>
6#include <cmath>
7#include <thread>
8#include "common/math_util.h"
9#include "core/settings.h"
5#include "input_common/analog_from_button.h" 10#include "input_common/analog_from_button.h"
6 11
7namespace InputCommon { 12namespace InputCommon {
@@ -11,27 +16,123 @@ public:
11 using Button = std::unique_ptr<Input::ButtonDevice>; 16 using Button = std::unique_ptr<Input::ButtonDevice>;
12 17
13 Analog(Button up_, Button down_, Button left_, Button right_, Button modifier_, 18 Analog(Button up_, Button down_, Button left_, Button right_, Button modifier_,
14 float modifier_scale_) 19 float modifier_scale_, float modifier_angle_)
15 : up(std::move(up_)), down(std::move(down_)), left(std::move(left_)), 20 : up(std::move(up_)), down(std::move(down_)), left(std::move(left_)),
16 right(std::move(right_)), modifier(std::move(modifier_)), 21 right(std::move(right_)), modifier(std::move(modifier_)), modifier_scale(modifier_scale_),
17 modifier_scale(modifier_scale_) {} 22 modifier_angle(modifier_angle_) {
23 update_thread = std::thread(&Analog::UpdateStatus, this);
24 }
25
26 ~Analog() override {
27 update_thread_running = false;
28 if (update_thread.joinable()) {
29 update_thread.join();
30 }
31 }
32
33 void MoveToDirection(bool enable, float to_angle) {
34 if (!enable) {
35 return;
36 }
37 constexpr float TAU = Common::PI * 2.0f;
38 // Use wider angle to ease the transition.
39 constexpr float aperture = TAU * 0.15f;
40 const float top_limit = to_angle + aperture;
41 const float bottom_limit = to_angle - aperture;
42
43 if ((angle > to_angle && angle <= top_limit) ||
44 (angle + TAU > to_angle && angle + TAU <= top_limit)) {
45 angle -= modifier_angle;
46 if (angle < 0) {
47 angle += TAU;
48 }
49 } else if ((angle >= bottom_limit && angle < to_angle) ||
50 (angle - TAU >= bottom_limit && angle - TAU < to_angle)) {
51 angle += modifier_angle;
52 if (angle >= TAU) {
53 angle -= TAU;
54 }
55 } else {
56 angle = to_angle;
57 }
58 }
59
60 void UpdateStatus() {
61 while (update_thread_running) {
62 const float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
63
64 bool r = right->GetStatus();
65 bool l = left->GetStatus();
66 bool u = up->GetStatus();
67 bool d = down->GetStatus();
68
69 // Eliminate contradictory movements
70 if (r && l) {
71 r = false;
72 l = false;
73 }
74 if (u && d) {
75 u = false;
76 d = false;
77 }
78
79 // Move to the right
80 MoveToDirection(r && !u && !d, 0.0f);
81
82 // Move to the upper right
83 MoveToDirection(r && u && !d, Common::PI * 0.25f);
84
85 // Move up
86 MoveToDirection(u && !l && !r, Common::PI * 0.5f);
87
88 // Move to the upper left
89 MoveToDirection(l && u && !d, Common::PI * 0.75f);
90
91 // Move to the left
92 MoveToDirection(l && !u && !d, Common::PI);
93
94 // Move to the bottom left
95 MoveToDirection(l && !u && d, Common::PI * 1.25f);
96
97 // Move down
98 MoveToDirection(d && !l && !r, Common::PI * 1.5f);
99
100 // Move to the bottom right
101 MoveToDirection(r && !u && d, Common::PI * 1.75f);
102
103 // Move if a key is pressed
104 if (r || l || u || d) {
105 amplitude = coef;
106 } else {
107 amplitude = 0;
108 }
109
110 // Delay the update rate to 100hz
111 std::this_thread::sleep_for(std::chrono::milliseconds(10));
112 }
113 }
18 114
19 std::tuple<float, float> GetStatus() const override { 115 std::tuple<float, float> GetStatus() const override {
116 if (Settings::values.emulate_analog_keyboard) {
117 return std::make_tuple(std::cos(angle) * amplitude, std::sin(angle) * amplitude);
118 }
20 constexpr float SQRT_HALF = 0.707106781f; 119 constexpr float SQRT_HALF = 0.707106781f;
21 int x = 0, y = 0; 120 int x = 0, y = 0;
22 121 if (right->GetStatus()) {
23 if (right->GetStatus())
24 ++x; 122 ++x;
25 if (left->GetStatus()) 123 }
124 if (left->GetStatus()) {
26 --x; 125 --x;
27 if (up->GetStatus()) 126 }
127 if (up->GetStatus()) {
28 ++y; 128 ++y;
29 if (down->GetStatus()) 129 }
130 if (down->GetStatus()) {
30 --y; 131 --y;
31 132 }
32 float coef = modifier->GetStatus() ? modifier_scale : 1.0f; 133 const float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
33 return std::make_tuple(x * coef * (y == 0 ? 1.0f : SQRT_HALF), 134 return std::make_tuple(static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF),
34 y * coef * (x == 0 ? 1.0f : SQRT_HALF)); 135 static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF));
35 } 136 }
36 137
37 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { 138 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
@@ -55,6 +156,11 @@ private:
55 Button right; 156 Button right;
56 Button modifier; 157 Button modifier;
57 float modifier_scale; 158 float modifier_scale;
159 float modifier_angle;
160 float angle{};
161 float amplitude{};
162 std::thread update_thread;
163 bool update_thread_running{true};
58}; 164};
59 165
60std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::ParamPackage& params) { 166std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::ParamPackage& params) {
@@ -65,8 +171,10 @@ std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::Para
65 auto right = Input::CreateDevice<Input::ButtonDevice>(params.Get("right", null_engine)); 171 auto right = Input::CreateDevice<Input::ButtonDevice>(params.Get("right", null_engine));
66 auto modifier = Input::CreateDevice<Input::ButtonDevice>(params.Get("modifier", null_engine)); 172 auto modifier = Input::CreateDevice<Input::ButtonDevice>(params.Get("modifier", null_engine));
67 auto modifier_scale = params.Get("modifier_scale", 0.5f); 173 auto modifier_scale = params.Get("modifier_scale", 0.5f);
174 auto modifier_angle = params.Get("modifier_angle", 0.035f);
68 return std::make_unique<Analog>(std::move(up), std::move(down), std::move(left), 175 return std::make_unique<Analog>(std::move(up), std::move(down), std::move(left),
69 std::move(right), std::move(modifier), modifier_scale); 176 std::move(right), std::move(modifier), modifier_scale,
177 modifier_angle);
70} 178}
71 179
72} // namespace InputCommon 180} // namespace InputCommon