diff options
| author | Jordan Woyak <jordan.woyak@gmail.com> | 2018-12-30 09:10:32 -0600 |
|---|---|---|
| committer | Jordan Woyak <jordan.woyak@gmail.com> | 2018-12-30 09:10:32 -0600 |
| commit | 7a00f55cfa6e65e58ebf9f279bfff61f8b0f8c13 (patch) | |
| tree | bbc75a8d0c7ce88f86cfc1d1f00cec15e68980ce /Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp | |
| parent | 247fa8c628d9f780831140006e69ee3af2f42f2d (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.cpp | 147 |
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 |
