diff options
| author | 2021-09-20 16:57:55 -0500 | |
|---|---|---|
| committer | 2021-11-24 20:30:22 -0600 | |
| commit | 4c6f2c2547e1d97f12ebe708fac693a6183bbc45 (patch) | |
| tree | 0abcd35f56088bbf732a92838995a465bae0f0ee /src/input_common/analog_from_button.cpp | |
| parent | input_common: Create input poller and mapping (diff) | |
| download | yuzu-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-x | src/input_common/analog_from_button.cpp | 238 |
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 | |||
| 13 | namespace InputCommon { | ||
| 14 | |||
| 15 | class Analog final : public Input::AnalogDevice { | ||
| 16 | public: | ||
| 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 | |||
| 210 | private: | ||
| 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 | |||
| 224 | std::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 | ||