summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp')
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp99
1 files changed, 47 insertions, 52 deletions
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp
index 9221b90243..2fec9c7bd0 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp
@@ -10,6 +10,8 @@
#include <string>
#include "Common/Common.h"
+#include "Common/MathUtil.h"
+
#include "InputCommon/ControlReference/ControlReference.h"
#include "InputCommon/ControllerEmu/Control/Control.h"
#include "InputCommon/ControllerEmu/Control/Input.h"
@@ -17,7 +19,8 @@
namespace ControllerEmu
{
-Tilt::Tilt(const std::string& name_) : ControlGroup(name_, GroupType::Tilt)
+Tilt::Tilt(const std::string& name_)
+ : ReshapableInput(name_, name_, GroupType::Tilt), m_last_update(Clock::now())
{
controls.emplace_back(std::make_unique<Input>(Translate, _trans("Forward")));
controls.emplace_back(std::make_unique<Input>(Translate, _trans("Backward")));
@@ -26,71 +29,63 @@ Tilt::Tilt(const std::string& name_) : ControlGroup(name_, GroupType::Tilt)
controls.emplace_back(std::make_unique<Input>(Translate, _trans("Modifier")));
- numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50));
- numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Circle Stick"), 0));
+ // Set default input radius to the full 1.0 (no resizing)
+ // Set default input shape to a square (no reshaping)
+ // Max deadzone to 50%
+ AddReshapingSettings(1.0, 0.5, 50);
+
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Angle"), 0.9, 0, 180));
}
-Tilt::StateData Tilt::GetState(const bool step)
+Tilt::ReshapeData Tilt::GetReshapableState(bool adjusted)
{
- // this is all a mess
-
- ControlState yy = controls[0]->control_ref->State() - controls[1]->control_ref->State();
- ControlState xx = controls[3]->control_ref->State() - controls[2]->control_ref->State();
-
- ControlState deadzone = numeric_settings[0]->GetValue();
- ControlState circle = numeric_settings[1]->GetValue();
- auto const angle = numeric_settings[2]->GetValue() / 1.8;
- ControlState m = controls[4]->control_ref->State();
-
- // deadzone / circle stick code
- // this section might be all wrong, but its working good enough, I think
-
- ControlState ang = atan2(yy, xx);
- ControlState ang_sin = sin(ang);
- ControlState ang_cos = cos(ang);
+ const ControlState y = controls[0]->control_ref->State() - controls[1]->control_ref->State();
+ const ControlState x = controls[3]->control_ref->State() - controls[2]->control_ref->State();
- // the amt a full square stick would have at current angle
- ControlState square_full =
- std::min(ang_sin ? 1 / fabs(ang_sin) : 2, ang_cos ? 1 / fabs(ang_cos) : 2);
+ // Return raw values. (used in UI)
+ if (!adjusted)
+ return {x, y};
- // the amt a full stick would have that was (user setting circular) at current angle
- // I think this is more like a pointed circle rather than a rounded square like it should be
- ControlState stick_full = (square_full * (1 - circle)) + (circle);
+ const ControlState modifier = controls[4]->control_ref->State();
- ControlState dist = sqrt(xx * xx + yy * yy);
+ // Compute desired tilt:
+ StateData target = Reshape(x, y, modifier);
- // dead zone code
- dist = std::max(0.0, dist - deadzone * stick_full);
- dist /= (1 - deadzone);
+ // Step the simulation. This is somewhat ugly being here.
+ // We should be able to GetState without changing state.
+ // State should be stored outside of this object inside the wiimote,
+ // and separately inside the UI.
- // circle stick code
- ControlState amt = dist / stick_full;
- dist += (square_full - 1) * amt * circle;
+ // We're using system time rather than ticks to step this.
+ // I don't think that's too horrible as we can consider this part of user input.
+ // And at least the Mapping UI will behave sanely this way.
+ // TODO: when state is moved outside of this class have a separate Step()
+ // function that takes a ms_passed argument
+ const auto now = Clock::now();
+ const auto ms_since_update =
+ std::chrono::duration_cast<std::chrono::milliseconds>(now - m_last_update).count();
+ m_last_update = now;
- if (m)
- dist *= 0.5;
+ const double max_step = MAX_DEG_PER_SEC / 180.0 * ms_since_update / 1000;
- yy = std::max(-1.0, std::min(1.0, ang_sin * dist));
- xx = std::max(-1.0, std::min(1.0, ang_cos * dist));
+ // TODO: Allow wrap around from 1.0 to -1.0
+ // (take the fastest route to target)
- // this is kinda silly here
- // gui being open will make this happen 2x as fast, o well
+ m_tilt.x += MathUtil::Clamp(target.x - m_tilt.x, -max_step, max_step);
+ m_tilt.y += MathUtil::Clamp(target.y - m_tilt.y, -max_step, max_step);
- // silly
- if (step)
- {
- if (xx > m_tilt.x)
- m_tilt.x = std::min(m_tilt.x + 0.1, xx);
- else if (xx < m_tilt.x)
- m_tilt.x = std::max(m_tilt.x - 0.1, xx);
+ return m_tilt;
+}
- if (yy > m_tilt.y)
- m_tilt.y = std::min(m_tilt.y + 0.1, yy);
- else if (yy < m_tilt.y)
- m_tilt.y = std::max(m_tilt.y - 0.1, yy);
- }
+Tilt::StateData Tilt::GetState()
+{
+ return GetReshapableState(true);
+}
- return {m_tilt.x * angle, m_tilt.y * angle};
+ControlState Tilt::GetGateRadiusAtAngle(double ang) const
+{
+ const ControlState max_tilt_angle = numeric_settings[SETTING_MAX_ANGLE]->GetValue() / 1.8;
+ return SquareStickGate(max_tilt_angle).GetRadiusAtAngle(ang);
}
+
} // namespace ControllerEmu