summaryrefslogtreecommitdiff
path: root/src/input_common/analog_from_button.cpp
diff options
context:
space:
mode:
authorGravatar german2020-11-07 09:48:11 -0600
committerGravatar german2020-11-08 09:15:33 -0600
commit70df449d0aa86e8c9a5a9ff9c0611709071bcd1b (patch)
treec95cef5d1e7100de23a3784ddef06291368e36b8 /src/input_common/analog_from_button.cpp
parentMerge pull request #4888 from lioncash/unicorn-remove (diff)
downloadyuzu-70df449d0aa86e8c9a5a9ff9c0611709071bcd1b.tar.gz
yuzu-70df449d0aa86e8c9a5a9ff9c0611709071bcd1b.tar.xz
yuzu-70df449d0aa86e8c9a5a9ff9c0611709071bcd1b.zip
Allow to dial any angle with digital joystick
Diffstat (limited to 'src/input_common/analog_from_button.cpp')
-rwxr-xr-xsrc/input_common/analog_from_button.cpp122
1 files changed, 103 insertions, 19 deletions
diff --git a/src/input_common/analog_from_button.cpp b/src/input_common/analog_from_button.cpp
index 74744d7f3..71a2e4031 100755
--- a/src/input_common/analog_from_button.cpp
+++ b/src/input_common/analog_from_button.cpp
@@ -2,6 +2,10 @@
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"
5#include "input_common/analog_from_button.h" 9#include "input_common/analog_from_button.h"
6 10
7namespace InputCommon { 11namespace InputCommon {
@@ -11,31 +15,104 @@ public:
11 using Button = std::unique_ptr<Input::ButtonDevice>; 15 using Button = std::unique_ptr<Input::ButtonDevice>;
12 16
13 Analog(Button up_, Button down_, Button left_, Button right_, Button modifier_, 17 Analog(Button up_, Button down_, Button left_, Button right_, Button modifier_,
14 float modifier_scale_) 18 float modifier_scale_, float modifier_angle_)
15 : up(std::move(up_)), down(std::move(down_)), left(std::move(left_)), 19 : up(std::move(up_)), down(std::move(down_)), left(std::move(left_)),
16 right(std::move(right_)), modifier(std::move(modifier_)), 20 right(std::move(right_)), modifier(std::move(modifier_)), modifier_scale(modifier_scale_),
17 modifier_scale(modifier_scale_) {} 21 modifier_angle(modifier_angle_) {
18 22 update_thread = std::thread(&Analog::UpdateStatus, this);
19 std::tuple<float, float> GetStatus() const override { 23 }
20 constexpr float SQRT_HALF = 0.707106781f;
21 int x = 0, y = 0;
22 24
23 if (right->GetStatus()) { 25 ~Analog() override {
24 ++x; 26 update_thread_running = false;
27 if (update_thread.joinable()) {
28 update_thread.join();
25 } 29 }
26 if (left->GetStatus()) { 30 }
27 --x; 31
32 void MoveToDirection(bool enable, float to_angle) {
33 if (!enable) {
34 return;
28 } 35 }
29 if (up->GetStatus()) { 36 constexpr float TAU = Common::PI * 2.0f;
30 ++y; 37 // Use wider angle to ease the transition.
38 constexpr float aperture = TAU * 0.15f;
39 const float top_limit = to_angle + aperture;
40 const float bottom_limit = to_angle - aperture;
41
42 if ((angle > to_angle && angle <= top_limit) ||
43 (angle + TAU > to_angle && angle + TAU <= top_limit)) {
44 angle -= modifier_angle;
45 if (angle < 0) {
46 angle += TAU;
47 }
48 } else if ((angle >= bottom_limit && angle < to_angle) ||
49 (angle - TAU >= bottom_limit && angle - TAU < to_angle)) {
50 angle += modifier_angle;
51 if (angle >= TAU) {
52 angle -= TAU;
53 }
54 } else {
55 angle = to_angle;
31 } 56 }
32 if (down->GetStatus()) { 57 }
33 --y; 58
59 void UpdateStatus() {
60 while (update_thread_running) {
61 const float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
62
63 bool r = right->GetStatus();
64 bool l = left->GetStatus();
65 bool u = up->GetStatus();
66 bool d = down->GetStatus();
67
68 // Eliminate contradictory movements
69 if (r && l) {
70 r = false;
71 l = false;
72 }
73 if (u && d) {
74 u = false;
75 d = false;
76 }
77
78 // Move to the right
79 MoveToDirection(r && !u && !d, 0.0f);
80
81 // Move to the upper right
82 MoveToDirection(r && u && !d, Common::PI * 0.25f);
83
84 // Move up
85 MoveToDirection(u && !l && !r, Common::PI * 0.5f);
86
87 // Move to the upper left
88 MoveToDirection(l && u && !d, Common::PI * 0.75f);
89
90 // Move to the left
91 MoveToDirection(l && !u && !d, Common::PI);
92
93 // Move to the bottom left
94 MoveToDirection(l && !u && d, Common::PI * 1.25f);
95
96 // Move down
97 MoveToDirection(d && !l && !r, Common::PI * 1.5f);
98
99 // Move to the bottom right
100 MoveToDirection(r && !u && d, Common::PI * 1.75f);
101
102 // Move if a key is pressed
103 if (r || l || u || d) {
104 amplitude = coef;
105 } else {
106 amplitude = 0;
107 }
108
109 // Delay the update rate to 100hz
110 std::this_thread::sleep_for(std::chrono::milliseconds(10));
34 } 111 }
112 }
35 113
36 const float coef = modifier->GetStatus() ? modifier_scale : 1.0f; 114 std::tuple<float, float> GetStatus() const override {
37 return std::make_tuple(static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF), 115 return std::make_tuple(std::cos(angle) * amplitude, std::sin(angle) * amplitude);
38 static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF));
39 } 116 }
40 117
41 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { 118 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
@@ -59,6 +136,11 @@ private:
59 Button right; 136 Button right;
60 Button modifier; 137 Button modifier;
61 float modifier_scale; 138 float modifier_scale;
139 float modifier_angle;
140 float angle{};
141 float amplitude{};
142 std::thread update_thread;
143 bool update_thread_running{true};
62}; 144};
63 145
64std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::ParamPackage& params) { 146std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::ParamPackage& params) {
@@ -69,8 +151,10 @@ std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::Para
69 auto right = Input::CreateDevice<Input::ButtonDevice>(params.Get("right", null_engine)); 151 auto right = Input::CreateDevice<Input::ButtonDevice>(params.Get("right", null_engine));
70 auto modifier = Input::CreateDevice<Input::ButtonDevice>(params.Get("modifier", null_engine)); 152 auto modifier = Input::CreateDevice<Input::ButtonDevice>(params.Get("modifier", null_engine));
71 auto modifier_scale = params.Get("modifier_scale", 0.5f); 153 auto modifier_scale = params.Get("modifier_scale", 0.5f);
154 auto modifier_angle = params.Get("modifier_angle", 0.035f);
72 return std::make_unique<Analog>(std::move(up), std::move(down), std::move(left), 155 return std::make_unique<Analog>(std::move(up), std::move(down), std::move(left),
73 std::move(right), std::move(modifier), modifier_scale); 156 std::move(right), std::move(modifier), modifier_scale,
157 modifier_angle);
74} 158}
75 159
76} // namespace InputCommon 160} // namespace InputCommon