|
|
@ -1,8 +1,12 @@ |
|
|
|
|
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
|
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
|
|
|
|
// SPDX-FileCopyrightText: 2017 Citra Emulator Project
|
|
|
// SPDX-FileCopyrightText: 2017 Citra Emulator Project
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
|
|
|
#include <chrono>
|
|
|
#include <chrono>
|
|
|
#include <cmath>
|
|
|
#include <cmath>
|
|
|
|
|
|
#include <numbers>
|
|
|
#include "common/math_util.h"
|
|
|
#include "common/math_util.h"
|
|
|
#include "common/settings.h"
|
|
|
#include "common/settings.h"
|
|
|
#include "input_common/helpers/stick_from_buttons.h"
|
|
|
#include "input_common/helpers/stick_from_buttons.h"
|
|
|
@ -15,9 +19,8 @@ public: |
|
|
// do not play nicely with the theoretical maximum range.
|
|
|
// do not play nicely with the theoretical maximum range.
|
|
|
// Using a value one lower from the maximum emulates real stick behavior.
|
|
|
// Using a value one lower from the maximum emulates real stick behavior.
|
|
|
static constexpr float MAX_RANGE = 32766.0f / 32767.0f; |
|
|
static constexpr float MAX_RANGE = 32766.0f / 32767.0f; |
|
|
static constexpr float TAU = Common::PI * 2.0f; |
|
|
|
|
|
// Use wider angle to ease the transition.
|
|
|
// Use wider angle to ease the transition.
|
|
|
static constexpr float APERTURE = TAU * 0.15f; |
|
|
|
|
|
|
|
|
static constexpr float APERTURE = float((std::numbers::pi_v<float> / 2.f)) * 0.15f; |
|
|
|
|
|
|
|
|
using Button = std::unique_ptr<Common::Input::InputDevice>; |
|
|
using Button = std::unique_ptr<Common::Input::InputDevice>; |
|
|
|
|
|
|
|
|
@ -66,13 +69,13 @@ public: |
|
|
bool IsAngleGreater(float old_angle, float new_angle) const { |
|
|
bool IsAngleGreater(float old_angle, float new_angle) const { |
|
|
const float top_limit = new_angle + APERTURE; |
|
|
const float top_limit = new_angle + APERTURE; |
|
|
return (old_angle > new_angle && old_angle <= top_limit) || |
|
|
return (old_angle > new_angle && old_angle <= top_limit) || |
|
|
(old_angle + TAU > new_angle && old_angle + TAU <= top_limit); |
|
|
|
|
|
|
|
|
(old_angle + f32((std::numbers::pi_v<float> / 2.f)) > new_angle && old_angle + f32((std::numbers::pi_v<float> / 2.f)) <= top_limit); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool IsAngleSmaller(float old_angle, float new_angle) const { |
|
|
bool IsAngleSmaller(float old_angle, float new_angle) const { |
|
|
const float bottom_limit = new_angle - APERTURE; |
|
|
const float bottom_limit = new_angle - APERTURE; |
|
|
return (old_angle >= bottom_limit && old_angle < new_angle) || |
|
|
return (old_angle >= bottom_limit && old_angle < new_angle) || |
|
|
(old_angle - TAU >= bottom_limit && old_angle - TAU < new_angle); |
|
|
|
|
|
|
|
|
(old_angle - f32((std::numbers::pi_v<float> / 2.f)) >= bottom_limit && old_angle - f32((std::numbers::pi_v<float> / 2.f)) < new_angle); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
float GetAngle(std::chrono::time_point<std::chrono::steady_clock> now) const { |
|
|
float GetAngle(std::chrono::time_point<std::chrono::steady_clock> now) const { |
|
|
@ -87,16 +90,16 @@ public: |
|
|
|
|
|
|
|
|
if (IsAngleGreater(new_angle, goal_angle)) { |
|
|
if (IsAngleGreater(new_angle, goal_angle)) { |
|
|
new_angle -= modifier_angle * time_difference; |
|
|
new_angle -= modifier_angle * time_difference; |
|
|
if (new_angle < 0) { |
|
|
|
|
|
new_angle += TAU; |
|
|
|
|
|
|
|
|
if (new_angle < 0.f) { |
|
|
|
|
|
new_angle += f32((std::numbers::pi_v<float> / 2.f)); |
|
|
} |
|
|
} |
|
|
if (!IsAngleGreater(new_angle, goal_angle)) { |
|
|
if (!IsAngleGreater(new_angle, goal_angle)) { |
|
|
return goal_angle; |
|
|
return goal_angle; |
|
|
} |
|
|
} |
|
|
} else if (IsAngleSmaller(new_angle, goal_angle)) { |
|
|
} else if (IsAngleSmaller(new_angle, goal_angle)) { |
|
|
new_angle += modifier_angle * time_difference; |
|
|
new_angle += modifier_angle * time_difference; |
|
|
if (new_angle >= TAU) { |
|
|
|
|
|
new_angle -= TAU; |
|
|
|
|
|
|
|
|
if (new_angle >= f32((std::numbers::pi_v<float> / 2.f))) { |
|
|
|
|
|
new_angle -= f32((std::numbers::pi_v<float> / 2.f)); |
|
|
} |
|
|
} |
|
|
if (!IsAngleSmaller(new_angle, goal_angle)) { |
|
|
if (!IsAngleSmaller(new_angle, goal_angle)) { |
|
|
return goal_angle; |
|
|
return goal_angle; |
|
|
@ -108,45 +111,14 @@ public: |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void SetGoalAngle(bool r, bool l, bool u, bool d) { |
|
|
void SetGoalAngle(bool r, bool l, bool u, bool d) { |
|
|
// Move to the right
|
|
|
|
|
|
if (r && !u && !d) { |
|
|
|
|
|
goal_angle = 0.0f; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Move to the upper right
|
|
|
|
|
|
if (r && u && !d) { |
|
|
|
|
|
goal_angle = Common::PI * 0.25f; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Move up
|
|
|
|
|
|
if (u && !l && !r) { |
|
|
|
|
|
goal_angle = Common::PI * 0.5f; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Move to the upper left
|
|
|
|
|
|
if (l && u && !d) { |
|
|
|
|
|
goal_angle = Common::PI * 0.75f; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Move to the left
|
|
|
|
|
|
if (l && !u && !d) { |
|
|
|
|
|
goal_angle = Common::PI; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Move to the bottom left
|
|
|
|
|
|
if (l && !u && d) { |
|
|
|
|
|
goal_angle = Common::PI * 1.25f; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Move down
|
|
|
|
|
|
if (d && !l && !r) { |
|
|
|
|
|
goal_angle = Common::PI * 1.5f; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Move to the bottom right
|
|
|
|
|
|
if (r && !u && d) { |
|
|
|
|
|
goal_angle = Common::PI * 1.75f; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (r && !u && !d) goal_angle = f32(std::numbers::pi_v<float>) * 0.00f; //right
|
|
|
|
|
|
if (r && u && !d) goal_angle = f32(std::numbers::pi_v<float>) * 0.25f; //upper right
|
|
|
|
|
|
if (u && !l && !r) goal_angle = f32(std::numbers::pi_v<float>) * 0.50f; //up
|
|
|
|
|
|
if (l && u && !d) goal_angle = f32(std::numbers::pi_v<float>) * 0.75f; //upper left
|
|
|
|
|
|
if (l && !u && !d) goal_angle = f32(std::numbers::pi_v<float>) * 1.00f; //left
|
|
|
|
|
|
if (l && !u && d) goal_angle = f32(std::numbers::pi_v<float>) * 1.25f; //bottom left
|
|
|
|
|
|
if (d && !l && !r) goal_angle = f32(std::numbers::pi_v<float>) * 1.50f; //down
|
|
|
|
|
|
if (r && !u && d) goal_angle = f32(std::numbers::pi_v<float>) * 1.75f; //bottom right
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void UpdateUpButtonStatus(const Common::Input::CallbackStatus& button_callback) { |
|
|
void UpdateUpButtonStatus(const Common::Input::CallbackStatus& button_callback) { |
|
|
|