summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp
diff options
context:
space:
mode:
authorJordan Woyak <jordan.woyak@gmail.com>2018-12-30 09:10:32 -0600
committerJordan Woyak <jordan.woyak@gmail.com>2018-12-30 09:10:32 -0600
commit7a00f55cfa6e65e58ebf9f279bfff61f8b0f8c13 (patch)
treebbc75a8d0c7ce88f86cfc1d1f00cec15e68980ce /Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp
parent247fa8c628d9f780831140006e69ee3af2f42f2d (diff)
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.
Diffstat (limited to 'Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp')
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp147
1 files changed, 90 insertions, 57 deletions
diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp
index b0633ec6a5..fc373f647c 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp
+++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp
@@ -21,7 +21,8 @@
namespace ControllerEmu
{
-Cursor::Cursor(const std::string& name_) : ControlGroup(name_, GroupType::Cursor)
+Cursor::Cursor(const std::string& name_)
+ : ReshapableInput(name_, name_, GroupType::Cursor), m_last_update(Clock::now())
{
for (auto& named_direction : named_directions)
controls.emplace_back(std::make_unique<Input>(Translate, named_direction));
@@ -31,89 +32,121 @@ Cursor::Cursor(const std::string& name_) : ControlGroup(name_, GroupType::Cursor
controls.emplace_back(std::make_unique<Input>(Translate, _trans("Hide")));
controls.emplace_back(std::make_unique<Input>(Translate, _trans("Recenter")));
+ // Default shape is a 1.0 square (no resizing/reshaping):
+ AddReshapingSettings(1.0, 0.5, 50);
+
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Center"), 0.5));
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Width"), 0.5));
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Height"), 0.5));
- numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 20));
+
boolean_settings.emplace_back(std::make_unique<BooleanSetting>(_trans("Relative Input"), false));
boolean_settings.emplace_back(std::make_unique<BooleanSetting>(_trans("Auto-Hide"), false));
}
-Cursor::StateData Cursor::GetState(const bool adjusted)
+ReshapableInput::ReshapeData Cursor::GetReshapableState(bool adjusted)
{
- const ControlState zz = controls[4]->control_ref->State() - controls[5]->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)
+ return {x, y};
+
+ return Reshape(x, y, 0.0);
+}
- // silly being here
- if (zz > m_state.z)
- m_state.z = std::min(m_state.z + 0.1, zz);
- else if (zz < m_state.z)
- m_state.z = std::max(m_state.z - 0.1, zz);
+ControlState Cursor::GetGateRadiusAtAngle(double ang) const
+{
+ // TODO: Change this to 0.5 and adjust the math,
+ // so pointer doesn't have to be clamped to the configured width/height?
+ return SquareStickGate(1.0).GetRadiusAtAngle(ang);
+}
- StateData result;
- result.z = m_state.z;
+Cursor::StateData Cursor::GetState(const bool adjusted)
+{
+ ControlState z = controls[4]->control_ref->State() - controls[5]->control_ref->State();
- if (m_autohide_timer > -1)
+ if (!adjusted)
{
- --m_autohide_timer;
+ const auto raw_input = GetReshapableState(false);
+
+ return {raw_input.x, raw_input.y, z};
}
- ControlState yy = controls[0]->control_ref->State() - controls[1]->control_ref->State();
- ControlState xx = controls[3]->control_ref->State() - controls[2]->control_ref->State();
+ const auto input = GetReshapableState(true);
- const ControlState deadzone = numeric_settings[3]->GetValue();
+ // TODO: Using system time is ugly.
+ // Kill this after state is moved into wiimote rather than this class.
+ 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;
- // reset auto-hide timer
- if (std::abs(m_prev_xx - xx) > deadzone || std::abs(m_prev_yy - yy) > deadzone)
- {
- m_autohide_timer = TIMER_VALUE;
- }
+ const double max_step = STEP_PER_SEC / 1000.0 * ms_since_update;
+ const double max_z_step = STEP_Z_PER_SEC / 1000.0 * ms_since_update;
- // hide
- const bool autohide = boolean_settings[1]->GetValue() && m_autohide_timer < 0;
- if (controls[6]->control_ref->State() > 0.5 || autohide)
- {
- result.x = 10000;
- result.y = 0;
- }
- else
- {
- // adjust cursor according to settings
- if (adjusted)
- {
- xx *= (numeric_settings[1]->GetValue() * 2);
- yy *= (numeric_settings[2]->GetValue() * 2);
- yy += (numeric_settings[0]->GetValue() - 0.5);
- }
+ // Apply deadzone to z:
+ const ControlState deadzone = numeric_settings[SETTING_DEADZONE]->GetValue();
+ z = std::copysign(std::max(0.0, std::abs(z) - deadzone) / (1.0 - deadzone), z);
+
+ // Smooth out z movement:
+ // FYI: Not using relative input for Z.
+ m_state.z += MathUtil::Clamp(z - m_state.z, -max_z_step, max_z_step);
- // relative input
- if (boolean_settings[0]->GetValue())
+ // Relative input:
+ if (boolean_settings[0]->GetValue())
+ {
+ // Recenter:
+ if (controls[7]->control_ref->State() > BUTTON_THRESHOLD)
{
- // deadzone to avoid the cursor slowly drifting
- if (std::abs(xx) > deadzone)
- m_state.x = MathUtil::Clamp(m_state.x + xx * SPEED_MULTIPLIER, -1.0, 1.0);
- if (std::abs(yy) > deadzone)
- m_state.y = MathUtil::Clamp(m_state.y + yy * SPEED_MULTIPLIER, -1.0, 1.0);
-
- // recenter
- if (controls[7]->control_ref->State() > 0.5)
- {
- m_state.x = 0.0;
- m_state.y = 0.0;
- }
+ m_state.x = 0.0;
+ m_state.y = 0.0;
}
else
{
- m_state.x = xx;
- m_state.y = yy;
+ m_state.x = MathUtil::Clamp(m_state.x + input.x * max_step, -1.0, 1.0);
+ m_state.y = MathUtil::Clamp(m_state.y + input.y * max_step, -1.0, 1.0);
}
+ }
+ // Absolute input:
+ else
+ {
+ m_state.x = input.x;
+ m_state.y = input.y;
+ }
+
+ StateData result = m_state;
+
+ // Adjust cursor according to settings:
+ result.x *= (numeric_settings[SETTING_WIDTH]->GetValue() * 2);
+ result.y *= (numeric_settings[SETTING_HEIGHT]->GetValue() * 2);
+ result.y += (numeric_settings[SETTING_CENTER]->GetValue() - 0.5);
+
+ const bool autohide = boolean_settings[1]->GetValue();
- result.x = m_state.x;
- result.y = m_state.y;
+ // Auto-hide timer:
+ // TODO: should Z movement reset this?
+ if (!autohide || std::abs(m_prev_result.x - result.x) > AUTO_HIDE_DEADZONE ||
+ std::abs(m_prev_result.y - result.y) > AUTO_HIDE_DEADZONE)
+ {
+ m_auto_hide_timer = AUTO_HIDE_MS;
+ }
+ else if (m_auto_hide_timer)
+ {
+ m_auto_hide_timer -= std::min<int>(ms_since_update, m_auto_hide_timer);
}
- m_prev_xx = xx;
- m_prev_yy = yy;
+ m_prev_result = result;
+
+ // If auto-hide time is up or hide button is held:
+ if (!m_auto_hide_timer || controls[6]->control_ref->State() > BUTTON_THRESHOLD)
+ {
+ // TODO: Use NaN or something:
+ result.x = 10000;
+ result.y = 0;
+ }
return result;
}
+
} // namespace ControllerEmu