From c3dc3c106ccb32911a4a6448f7b21c8beaae0c35 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sat, 29 Dec 2018 16:06:03 -0600 Subject: ControllerEmu: Reorganize stick reshaping code and use it for emu wiimote tilt as well. Also make the tilt mapping indicator pretty. --- .../ControllerEmu/ControlGroup/Tilt.cpp | 90 +++++++++------------- 1 file changed, 36 insertions(+), 54 deletions(-) (limited to 'Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp') diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp index 9221b90243..b00ae5a4c9 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp @@ -17,7 +17,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(Translate, _trans("Forward"))); controls.emplace_back(std::make_unique(Translate, _trans("Backward"))); @@ -26,71 +27,52 @@ Tilt::Tilt(const std::string& name_) : ControlGroup(name_, GroupType::Tilt) controls.emplace_back(std::make_unique(Translate, _trans("Modifier"))); - numeric_settings.emplace_back(std::make_unique(_trans("Dead Zone"), 0, 0, 50)); - numeric_settings.emplace_back(std::make_unique(_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(_trans("Angle"), 0.9, 0, 180)); } -Tilt::StateData Tilt::GetState(const bool step) +Tilt::StateData Tilt::GetState(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); + ControlState y = controls[0]->control_ref->State() - controls[1]->control_ref->State(); + 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 pretty ugly being here. + const auto now = Clock::now(); + const auto ms_since_update = + std::chrono::duration_cast(now - m_last_update).count(); + m_last_update = now; - // circle stick code - ControlState amt = dist / stick_full; - dist += (square_full - 1) * amt * circle; + constexpr int MAX_DEG_PER_SEC = 360 * 2; + const double MAX_STEP = MAX_DEG_PER_SEC / 180.0 * ms_since_update / 1000; - if (m) - dist *= 0.5; + // TODO: Allow wrap around from 1.0 to -1.0 + // (take the fastest route to target) - yy = std::max(-1.0, std::min(1.0, ang_sin * dist)); - xx = std::max(-1.0, std::min(1.0, ang_cos * dist)); + const double diff_x = (target.x - m_tilt.x); + m_tilt.x += std::min(MAX_STEP, std::abs(diff_x)) * ((diff_x < 0) ? -1 : 1); + const double diff_y = (target.y - m_tilt.y); + m_tilt.y += std::min(MAX_STEP, std::abs(diff_y)) * ((diff_y < 0) ? -1 : 1); - // this is kinda silly here - // gui being open will make this happen 2x as fast, o well - - // 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); - - 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); - } + return m_tilt; +} - 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 -- cgit v1.2.3 From 7a00f55cfa6e65e58ebf9f279bfff61f8b0f8c13 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 30 Dec 2018 09:10:32 -0600 Subject: ControllerEmu::Cursor: Add input radius/shape settings to IR Cursor mappings to allow use of round inputs in absolute mode. Make relative input option obey the center/width/height settings. Make the mapping indicator pretty and actually show what the relative/center/w/h settings are doing. --- .../ControllerEmu/ControlGroup/Tilt.cpp | 33 +++++++++++++++------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp') diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp index b00ae5a4c9..998cce17ee 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp @@ -10,6 +10,8 @@ #include #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" @@ -35,10 +37,10 @@ Tilt::Tilt(const std::string& name_) numeric_settings.emplace_back(std::make_unique(_trans("Angle"), 0.9, 0, 180)); } -Tilt::StateData Tilt::GetState(bool adjusted) +Tilt::StateData Tilt::GetReshapableState(bool adjusted) { - ControlState y = controls[0]->control_ref->State() - controls[1]->control_ref->State(); - ControlState x = controls[3]->control_ref->State() - controls[2]->control_ref->State(); + 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(); // Return raw values. (used in UI) if (!adjusted) @@ -49,26 +51,37 @@ Tilt::StateData Tilt::GetState(bool adjusted) // Compute desired tilt: StateData target = Reshape(x, y, modifier); - // Step the simulation. This is pretty ugly being here. + // 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. + + // 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(now - m_last_update).count(); m_last_update = now; - constexpr int MAX_DEG_PER_SEC = 360 * 2; - const double MAX_STEP = MAX_DEG_PER_SEC / 180.0 * ms_since_update / 1000; + const double max_step = MAX_DEG_PER_SEC / 180.0 * ms_since_update / 1000; // TODO: Allow wrap around from 1.0 to -1.0 // (take the fastest route to target) - const double diff_x = (target.x - m_tilt.x); - m_tilt.x += std::min(MAX_STEP, std::abs(diff_x)) * ((diff_x < 0) ? -1 : 1); - const double diff_y = (target.y - m_tilt.y); - m_tilt.y += std::min(MAX_STEP, std::abs(diff_y)) * ((diff_y < 0) ? -1 : 1); + 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); return m_tilt; } +Tilt::StateData Tilt::GetState() +{ + return GetReshapableState(true); +} + ControlState Tilt::GetGateRadiusAtAngle(double ang) const { const ControlState max_tilt_angle = numeric_settings[SETTING_MAX_ANGLE]->GetValue() / 1.8; -- cgit v1.2.3 From 7efa96eda979f5e717813e7c76cefb0720bc239a Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 30 Dec 2018 10:52:45 -0600 Subject: ControllerEmu: code cleanup. --- Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp') diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp index 998cce17ee..2fec9c7bd0 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp @@ -37,7 +37,7 @@ Tilt::Tilt(const std::string& name_) numeric_settings.emplace_back(std::make_unique(_trans("Angle"), 0.9, 0, 180)); } -Tilt::StateData Tilt::GetReshapableState(bool adjusted) +Tilt::ReshapeData Tilt::GetReshapableState(bool adjusted) { 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(); -- cgit v1.2.3