mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
InputCommon: Clean up how numeric settings are handled. Add units of measure to UI. Eliminate hidden magic values of the IR cursor.
This commit is contained in:
@ -11,7 +11,6 @@
|
||||
#include "InputCommon/ControllerEmu/Control/Control.h"
|
||||
#include "InputCommon/ControllerEmu/ControlGroup/Attachments.h"
|
||||
#include "InputCommon/ControllerEmu/ControllerEmu.h"
|
||||
#include "InputCommon/ControllerEmu/Setting/BooleanSetting.h"
|
||||
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
|
||||
|
||||
namespace ControllerEmu
|
||||
@ -27,30 +26,26 @@ ControlGroup::ControlGroup(const std::string& name_, const std::string& ui_name_
|
||||
{
|
||||
}
|
||||
|
||||
void ControlGroup::AddDeadzoneSetting(SettingValue<double>* value, double maximum_deadzone)
|
||||
{
|
||||
AddSetting(value,
|
||||
{_trans("Dead Zone"),
|
||||
// i18n: The percent symbol.
|
||||
_trans("%"),
|
||||
// i18n: Refers to the dead-zone setting of gamepad inputs.
|
||||
_trans("Input strength to ignore.")},
|
||||
0, 0, maximum_deadzone);
|
||||
}
|
||||
|
||||
ControlGroup::~ControlGroup() = default;
|
||||
|
||||
void ControlGroup::LoadConfig(IniFile::Section* sec, const std::string& defdev,
|
||||
const std::string& base)
|
||||
{
|
||||
std::string group(base + name + "/");
|
||||
const std::string group(base + name + "/");
|
||||
|
||||
// settings
|
||||
for (auto& s : numeric_settings)
|
||||
{
|
||||
if (s->m_type == SettingType::VIRTUAL)
|
||||
continue;
|
||||
|
||||
sec->Get(group + s->m_name, &s->m_value, s->m_default_value * 100);
|
||||
s->m_value /= 100;
|
||||
}
|
||||
|
||||
for (auto& s : boolean_settings)
|
||||
{
|
||||
if (s->m_type == SettingType::VIRTUAL)
|
||||
continue;
|
||||
|
||||
sec->Get(group + s->m_name, &s->m_value, s->m_default_value);
|
||||
}
|
||||
for (auto& setting : numeric_settings)
|
||||
setting->LoadFromIni(*sec, group);
|
||||
|
||||
for (auto& c : controls)
|
||||
{
|
||||
@ -92,23 +87,10 @@ void ControlGroup::LoadConfig(IniFile::Section* sec, const std::string& defdev,
|
||||
void ControlGroup::SaveConfig(IniFile::Section* sec, const std::string& defdev,
|
||||
const std::string& base)
|
||||
{
|
||||
std::string group(base + name + "/");
|
||||
const std::string group(base + name + "/");
|
||||
|
||||
for (auto& s : numeric_settings)
|
||||
{
|
||||
if (s->m_type == SettingType::VIRTUAL)
|
||||
continue;
|
||||
|
||||
sec->Set(group + s->m_name, s->m_value * 100.0, s->m_default_value * 100.0);
|
||||
}
|
||||
|
||||
for (auto& s : boolean_settings)
|
||||
{
|
||||
if (s->m_type == SettingType::VIRTUAL)
|
||||
continue;
|
||||
|
||||
sec->Set(group + s->m_name, s->m_value, s->m_default_value);
|
||||
}
|
||||
for (auto& setting : numeric_settings)
|
||||
setting->SaveToIni(*sec, group);
|
||||
|
||||
for (auto& c : controls)
|
||||
{
|
||||
|
@ -13,10 +13,17 @@
|
||||
|
||||
namespace ControllerEmu
|
||||
{
|
||||
class BooleanSetting;
|
||||
class Control;
|
||||
|
||||
class NumericSettingBase;
|
||||
struct NumericSettingDetails;
|
||||
|
||||
template <typename T>
|
||||
class NumericSetting;
|
||||
|
||||
template <typename T>
|
||||
class SettingValue;
|
||||
|
||||
enum class GroupType
|
||||
{
|
||||
Other,
|
||||
@ -46,12 +53,22 @@ public:
|
||||
|
||||
void SetControlExpression(int index, const std::string& expression);
|
||||
|
||||
template <typename T>
|
||||
void AddSetting(SettingValue<T>* value, const NumericSettingDetails& details,
|
||||
std::common_type_t<T> default_value, std::common_type_t<T> min_value = {},
|
||||
std::common_type_t<T> max_value = T(100))
|
||||
{
|
||||
numeric_settings.emplace_back(
|
||||
std::make_unique<NumericSetting<T>>(value, details, default_value, min_value, max_value));
|
||||
}
|
||||
|
||||
void AddDeadzoneSetting(SettingValue<double>* value, double maximum_deadzone);
|
||||
|
||||
const std::string name;
|
||||
const std::string ui_name;
|
||||
const GroupType type;
|
||||
|
||||
std::vector<std::unique_ptr<Control>> controls;
|
||||
std::vector<std::unique_ptr<NumericSetting>> numeric_settings;
|
||||
std::vector<std::unique_ptr<BooleanSetting>> boolean_settings;
|
||||
std::vector<std::unique_ptr<NumericSettingBase>> numeric_settings;
|
||||
};
|
||||
} // namespace ControllerEmu
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "InputCommon/ControllerEmu/Control/Control.h"
|
||||
#include "InputCommon/ControllerEmu/Control/Input.h"
|
||||
#include "InputCommon/ControllerEmu/ControllerEmu.h"
|
||||
#include "InputCommon/ControllerEmu/Setting/BooleanSetting.h"
|
||||
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
|
||||
|
||||
namespace ControllerEmu
|
||||
@ -32,12 +31,36 @@ Cursor::Cursor(const std::string& name_)
|
||||
controls.emplace_back(std::make_unique<Input>(Translate, _trans("Hide")));
|
||||
controls.emplace_back(std::make_unique<Input>(Translate, _trans("Recenter")));
|
||||
|
||||
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));
|
||||
// Default values are optimized for "Super Mario Galaxy 2".
|
||||
// This seems to be acceptable for a good number of games.
|
||||
|
||||
boolean_settings.emplace_back(std::make_unique<BooleanSetting>(_trans("Relative Input"), false));
|
||||
boolean_settings.emplace_back(std::make_unique<BooleanSetting>(_trans("Auto-Hide"), false));
|
||||
AddSetting(&m_vertical_offset_setting,
|
||||
// i18n: Refers to a positional offset applied to an emulated wiimote.
|
||||
{_trans("Vertical Offset"),
|
||||
// i18n: The symbol/abbreviation for centimeters.
|
||||
_trans("cm")},
|
||||
10, -100, 100);
|
||||
|
||||
AddSetting(&m_yaw_setting,
|
||||
// i18n: Refers to an amount of rotational movement about the "yaw" axis.
|
||||
{_trans("Total Yaw"),
|
||||
// i18n: The symbol/abbreviation for degrees (unit of angular measure).
|
||||
_trans("°"),
|
||||
// i18n: Refers to emulated wii remote movements.
|
||||
_trans("Total rotation about the yaw axis.")},
|
||||
15, 0, 180);
|
||||
|
||||
AddSetting(&m_pitch_setting,
|
||||
// i18n: Refers to an amount of rotational movement about the "pitch" axis.
|
||||
{_trans("Total Pitch"),
|
||||
// i18n: The symbol/abbreviation for degrees (unit of angular measure).
|
||||
_trans("°"),
|
||||
// i18n: Refers to emulated wii remote movements.
|
||||
_trans("Total rotation about the pitch axis.")},
|
||||
15, 0, 180);
|
||||
|
||||
AddSetting(&m_relative_setting, {_trans("Relative Input")}, false);
|
||||
AddSetting(&m_autohide_setting, {_trans("Auto-Hide")}, false);
|
||||
}
|
||||
|
||||
Cursor::ReshapeData Cursor::GetReshapableState(bool adjusted)
|
||||
@ -81,7 +104,7 @@ Cursor::StateData Cursor::GetState(const bool adjusted)
|
||||
const double max_z_step = STEP_Z_PER_SEC / 1000.0 * ms_since_update;
|
||||
|
||||
// Apply deadzone to z:
|
||||
const ControlState deadzone = numeric_settings[SETTING_DEADZONE]->GetValue();
|
||||
const ControlState deadzone = GetDeadzonePercentage();
|
||||
z = std::copysign(std::max(0.0, std::abs(z) - deadzone) / (1.0 - deadzone), z);
|
||||
|
||||
// Smooth out z movement:
|
||||
@ -89,7 +112,7 @@ Cursor::StateData Cursor::GetState(const bool adjusted)
|
||||
m_state.z += MathUtil::Clamp(z - m_state.z, -max_z_step, max_z_step);
|
||||
|
||||
// Relative input:
|
||||
if (boolean_settings[0]->GetValue())
|
||||
if (m_relative_setting.GetValue())
|
||||
{
|
||||
// Recenter:
|
||||
if (controls[7]->control_ref->State() > BUTTON_THRESHOLD)
|
||||
@ -112,12 +135,7 @@ Cursor::StateData Cursor::GetState(const bool adjusted)
|
||||
|
||||
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();
|
||||
const bool autohide = m_autohide_setting.GetValue();
|
||||
|
||||
// Auto-hide timer:
|
||||
// TODO: should Z movement reset this?
|
||||
@ -144,4 +162,19 @@ Cursor::StateData Cursor::GetState(const bool adjusted)
|
||||
return result;
|
||||
}
|
||||
|
||||
ControlState Cursor::GetTotalYaw() const
|
||||
{
|
||||
return m_yaw_setting.GetValue() * MathUtil::TAU / 360;
|
||||
}
|
||||
|
||||
ControlState Cursor::GetTotalPitch() const
|
||||
{
|
||||
return m_pitch_setting.GetValue() * MathUtil::TAU / 360;
|
||||
}
|
||||
|
||||
ControlState Cursor::GetVerticalOffset() const
|
||||
{
|
||||
return m_vertical_offset_setting.GetValue() / 100;
|
||||
}
|
||||
|
||||
} // namespace ControllerEmu
|
||||
|
@ -22,13 +22,6 @@ public:
|
||||
ControlState z{};
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SETTING_CENTER = ReshapableInput::SETTING_COUNT,
|
||||
SETTING_WIDTH,
|
||||
SETTING_HEIGHT,
|
||||
};
|
||||
|
||||
explicit Cursor(const std::string& name);
|
||||
|
||||
ReshapeData GetReshapableState(bool adjusted) final override;
|
||||
@ -36,6 +29,15 @@ public:
|
||||
|
||||
StateData GetState(bool adjusted);
|
||||
|
||||
// Yaw movement in radians.
|
||||
ControlState GetTotalYaw() const;
|
||||
|
||||
// Pitch movement in radians.
|
||||
ControlState GetTotalPitch() const;
|
||||
|
||||
// Vertical offset in meters.
|
||||
ControlState GetVerticalOffset() const;
|
||||
|
||||
private:
|
||||
// This is used to reduce the cursor speed for relative input
|
||||
// to something that makes sense with the default range.
|
||||
@ -59,5 +61,12 @@ private:
|
||||
|
||||
using Clock = std::chrono::steady_clock;
|
||||
Clock::time_point m_last_update;
|
||||
|
||||
SettingValue<double> m_yaw_setting;
|
||||
SettingValue<double> m_pitch_setting;
|
||||
SettingValue<double> m_vertical_offset_setting;
|
||||
|
||||
SettingValue<bool> m_relative_setting;
|
||||
SettingValue<bool> m_autohide_setting;
|
||||
};
|
||||
} // namespace ControllerEmu
|
||||
|
@ -25,15 +25,30 @@ Force::Force(const std::string& name_) : ReshapableInput(name_, name_, GroupType
|
||||
controls.emplace_back(std::make_unique<Input>(Translate, _trans("Forward")));
|
||||
controls.emplace_back(std::make_unique<Input>(Translate, _trans("Backward")));
|
||||
|
||||
// Maximum swing movement (centimeters).
|
||||
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Distance"), 0.25, 1, 100));
|
||||
AddSetting(&m_distance_setting,
|
||||
{_trans("Distance"),
|
||||
// i18n: The symbol/abbreviation for centimeters.
|
||||
_trans("cm"),
|
||||
// i18n: Refering to emulated wii remote swing movement.
|
||||
_trans("Distance of travel from neutral position.")},
|
||||
25, 0, 100);
|
||||
|
||||
// Maximum jerk (m/s^3).
|
||||
// i18n: "Jerk" as it relates to physics. The time derivative of acceleration.
|
||||
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Jerk"), 5.0, 1, 1000));
|
||||
AddSetting(&m_jerk_setting,
|
||||
// i18n: "Jerk" as it relates to physics. The time derivative of acceleration.
|
||||
{_trans("Jerk"),
|
||||
// i18n: The symbol/abbreviation for meters per second to the 3rd power.
|
||||
_trans("m/s³"),
|
||||
// i18n: Refering to emulated wii remote swing movement.
|
||||
_trans("Maximum change in acceleration.")},
|
||||
500, 1, 1000);
|
||||
|
||||
// Angle of twist applied at the extremities of the swing (degrees).
|
||||
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Angle"), 0.45, 0, 180));
|
||||
AddSetting(&m_angle_setting,
|
||||
{_trans("Angle"),
|
||||
// i18n: The symbol/abbreviation for degrees (unit of angular measure).
|
||||
_trans("°"),
|
||||
// i18n: Refering to emulated wii remote swing movement.
|
||||
_trans("Rotation applied at extremities of swing.")},
|
||||
45, 0, 180);
|
||||
}
|
||||
|
||||
Force::ReshapeData Force::GetReshapableState(bool adjusted)
|
||||
@ -56,7 +71,7 @@ Force::StateData Force::GetState(bool adjusted)
|
||||
if (adjusted)
|
||||
{
|
||||
// Apply deadzone to z.
|
||||
const ControlState deadzone = numeric_settings[SETTING_DEADZONE]->GetValue();
|
||||
const ControlState deadzone = GetDeadzonePercentage();
|
||||
z = std::copysign(std::max(0.0, std::abs(z) - deadzone) / (1.0 - deadzone), z);
|
||||
}
|
||||
|
||||
@ -66,22 +81,22 @@ Force::StateData Force::GetState(bool adjusted)
|
||||
ControlState Force::GetGateRadiusAtAngle(double) const
|
||||
{
|
||||
// Just a circle of the configured distance:
|
||||
return numeric_settings[SETTING_DISTANCE]->GetValue();
|
||||
return GetMaxDistance();
|
||||
}
|
||||
|
||||
ControlState Force::GetMaxJerk() const
|
||||
{
|
||||
return numeric_settings[SETTING_JERK]->GetValue() * 100;
|
||||
return m_jerk_setting.GetValue();
|
||||
}
|
||||
|
||||
ControlState Force::GetTwistAngle() const
|
||||
{
|
||||
return numeric_settings[SETTING_ANGLE]->GetValue() * MathUtil::TAU / 3.60;
|
||||
return m_angle_setting.GetValue() * MathUtil::TAU / 360;
|
||||
}
|
||||
|
||||
ControlState Force::GetMaxDistance() const
|
||||
{
|
||||
return numeric_settings[SETTING_DISTANCE]->GetValue();
|
||||
return m_distance_setting.GetValue() / 100;
|
||||
}
|
||||
|
||||
ControlState Force::GetDefaultInputRadiusAtAngle(double) const
|
||||
|
@ -36,11 +36,8 @@ public:
|
||||
ControlState GetMaxDistance() const;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
SETTING_DISTANCE = ReshapableInput::SETTING_COUNT,
|
||||
SETTING_JERK,
|
||||
SETTING_ANGLE,
|
||||
};
|
||||
SettingValue<double> m_distance_setting;
|
||||
SettingValue<double> m_jerk_setting;
|
||||
SettingValue<double> m_angle_setting;
|
||||
};
|
||||
} // namespace ControllerEmu
|
||||
|
@ -14,22 +14,28 @@
|
||||
|
||||
#include "InputCommon/ControlReference/ControlReference.h"
|
||||
#include "InputCommon/ControllerEmu/Control/Control.h"
|
||||
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
|
||||
|
||||
namespace ControllerEmu
|
||||
{
|
||||
MixedTriggers::MixedTriggers(const std::string& name_)
|
||||
: ControlGroup(name_, GroupType::MixedTriggers)
|
||||
{
|
||||
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Threshold"), 0.9));
|
||||
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0.0, 0, 25));
|
||||
AddSetting(&m_threshold_setting,
|
||||
{_trans("Threshold"),
|
||||
// i18n: The percent symbol.
|
||||
_trans("%"),
|
||||
// i18n: Refers to the "threshold" setting for pressure sensitive gamepad inputs.
|
||||
_trans("Input strength required for activation.")},
|
||||
90, 0, 100);
|
||||
|
||||
AddDeadzoneSetting(&m_deadzone_setting, 25);
|
||||
}
|
||||
|
||||
void MixedTriggers::GetState(u16* const digital, const u16* bitmasks, ControlState* analog,
|
||||
bool adjusted) const
|
||||
{
|
||||
const ControlState threshold = numeric_settings[SETTING_THRESHOLD]->GetValue();
|
||||
ControlState deadzone = numeric_settings[SETTING_DEADZONE]->GetValue();
|
||||
const ControlState threshold = GetThreshold();
|
||||
ControlState deadzone = GetDeadzone();
|
||||
|
||||
// Return raw values. (used in UI)
|
||||
if (!adjusted)
|
||||
@ -63,12 +69,12 @@ void MixedTriggers::GetState(u16* const digital, const u16* bitmasks, ControlSta
|
||||
|
||||
ControlState MixedTriggers::GetDeadzone() const
|
||||
{
|
||||
return numeric_settings[SETTING_DEADZONE]->GetValue();
|
||||
return m_deadzone_setting.GetValue() / 100;
|
||||
}
|
||||
|
||||
ControlState MixedTriggers::GetThreshold() const
|
||||
{
|
||||
return numeric_settings[SETTING_THRESHOLD]->GetValue();
|
||||
return m_threshold_setting.GetValue() / 100;
|
||||
}
|
||||
|
||||
} // namespace ControllerEmu
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <string>
|
||||
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
|
||||
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
|
||||
#include "InputCommon/ControllerInterface/Device.h"
|
||||
|
||||
namespace ControllerEmu
|
||||
@ -22,10 +23,7 @@ public:
|
||||
ControlState GetThreshold() const;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
SETTING_THRESHOLD,
|
||||
SETTING_DEADZONE,
|
||||
};
|
||||
SettingValue<double> m_threshold_setting;
|
||||
SettingValue<double> m_deadzone_setting;
|
||||
};
|
||||
} // namespace ControllerEmu
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "InputCommon/ControlReference/ControlReference.h"
|
||||
#include "InputCommon/ControllerEmu/Control/Control.h"
|
||||
#include "InputCommon/ControllerEmu/Control/Input.h"
|
||||
#include "InputCommon/ControllerEmu/Setting/BooleanSetting.h"
|
||||
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
|
||||
#include "VideoCommon/OnScreenDisplay.h"
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "InputCommon/ControllerEmu/Control/Control.h"
|
||||
#include "InputCommon/ControllerEmu/Control/Input.h"
|
||||
#include "InputCommon/ControllerEmu/ControllerEmu.h"
|
||||
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
|
||||
|
||||
namespace ControllerEmu
|
||||
{
|
||||
@ -23,7 +22,7 @@ Slider::Slider(const std::string& name_, const std::string& ui_name_)
|
||||
controls.emplace_back(std::make_unique<Input>(Translate, _trans("Left")));
|
||||
controls.emplace_back(std::make_unique<Input>(Translate, _trans("Right")));
|
||||
|
||||
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50));
|
||||
AddDeadzoneSetting(&m_deadzone_setting, 50);
|
||||
}
|
||||
|
||||
Slider::Slider(const std::string& name_) : Slider(name_, name_)
|
||||
@ -32,7 +31,7 @@ Slider::Slider(const std::string& name_) : Slider(name_, name_)
|
||||
|
||||
Slider::StateData Slider::GetState()
|
||||
{
|
||||
const ControlState deadzone = numeric_settings[0]->GetValue();
|
||||
const ControlState deadzone = m_deadzone_setting.GetValue() / 100;
|
||||
const ControlState state = controls[1]->control_ref->State() - controls[0]->control_ref->State();
|
||||
|
||||
if (fabs(state) > deadzone)
|
||||
|
@ -5,7 +5,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
|
||||
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
|
||||
#include "InputCommon/ControllerInterface/Device.h"
|
||||
|
||||
namespace ControllerEmu
|
||||
@ -22,5 +24,8 @@ public:
|
||||
explicit Slider(const std::string& name_);
|
||||
|
||||
StateData GetState();
|
||||
|
||||
private:
|
||||
SettingValue<double> m_deadzone_setting;
|
||||
};
|
||||
} // namespace ControllerEmu
|
||||
|
@ -24,7 +24,13 @@ Tilt::Tilt(const std::string& name_) : ReshapableInput(name_, name_, GroupType::
|
||||
|
||||
controls.emplace_back(std::make_unique<Input>(Translate, _trans("Modifier")));
|
||||
|
||||
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Angle"), 0.9, 0, 180));
|
||||
AddSetting(&m_max_angle_setting,
|
||||
{_trans("Angle"),
|
||||
// i18n: The symbol/abbreviation for degrees (unit of angular measure).
|
||||
_trans("°"),
|
||||
// i18n: Refers to emulated wii remote movement.
|
||||
_trans("Maximum tilt angle.")},
|
||||
90, 0, 180);
|
||||
}
|
||||
|
||||
Tilt::ReshapeData Tilt::GetReshapableState(bool adjusted)
|
||||
@ -48,7 +54,7 @@ Tilt::StateData Tilt::GetState()
|
||||
|
||||
ControlState Tilt::GetGateRadiusAtAngle(double ang) const
|
||||
{
|
||||
const ControlState max_tilt_angle = numeric_settings[SETTING_MAX_ANGLE]->GetValue() / 1.8;
|
||||
const ControlState max_tilt_angle = m_max_angle_setting.GetValue() / 180;
|
||||
return SquareStickGate(max_tilt_angle).GetRadiusAtAngle(ang);
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
|
||||
#include "InputCommon/ControllerEmu/StickGate.h"
|
||||
#include "InputCommon/ControllerInterface/Device.h"
|
||||
|
||||
@ -28,9 +29,6 @@ public:
|
||||
StateData GetState();
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
SETTING_MAX_ANGLE = ReshapableInput::SETTING_COUNT,
|
||||
};
|
||||
SettingValue<double> m_max_angle_setting;
|
||||
};
|
||||
} // namespace ControllerEmu
|
||||
|
@ -18,13 +18,13 @@ namespace ControllerEmu
|
||||
{
|
||||
Triggers::Triggers(const std::string& name_) : ControlGroup(name_, GroupType::Triggers)
|
||||
{
|
||||
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50));
|
||||
AddDeadzoneSetting(&m_deadzone_setting, 50);
|
||||
}
|
||||
|
||||
Triggers::StateData Triggers::GetState()
|
||||
{
|
||||
const size_t trigger_count = controls.size();
|
||||
const ControlState deadzone = numeric_settings[0]->GetValue();
|
||||
const ControlState deadzone = m_deadzone_setting.GetValue() / 100;
|
||||
|
||||
StateData result(trigger_count);
|
||||
for (size_t i = 0; i < trigger_count; ++i)
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
|
||||
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
|
||||
#include "InputCommon/ControllerInterface/Device.h"
|
||||
|
||||
namespace ControllerEmu
|
||||
@ -26,5 +27,8 @@ public:
|
||||
explicit Triggers(const std::string& name);
|
||||
|
||||
StateData GetState();
|
||||
|
||||
private:
|
||||
SettingValue<double> m_deadzone_setting;
|
||||
};
|
||||
} // namespace ControllerEmu
|
||||
|
@ -1,38 +0,0 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "InputCommon/ControllerEmu/Setting/BooleanSetting.h"
|
||||
|
||||
namespace ControllerEmu
|
||||
{
|
||||
BooleanSetting::BooleanSetting(const std::string& setting_name, const std::string& ui_name,
|
||||
const bool default_value, const SettingType setting_type,
|
||||
const bool exclusive)
|
||||
: m_type(setting_type), m_name(setting_name), m_ui_name(ui_name),
|
||||
m_default_value(default_value), m_value(default_value), m_exclusive(exclusive)
|
||||
{
|
||||
}
|
||||
|
||||
BooleanSetting::BooleanSetting(const std::string& setting_name, const bool default_value,
|
||||
const SettingType setting_type, const bool exclusive)
|
||||
: BooleanSetting(setting_name, setting_name, default_value, setting_type, exclusive)
|
||||
{
|
||||
}
|
||||
|
||||
bool BooleanSetting::GetValue() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
bool BooleanSetting::IsExclusive() const
|
||||
{
|
||||
return m_exclusive;
|
||||
}
|
||||
|
||||
void BooleanSetting::SetValue(bool value)
|
||||
{
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
} // namespace ControllerEmu
|
@ -1,38 +0,0 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "InputCommon/ControllerEmu/Setting/Setting.h"
|
||||
#include "InputCommon/ControllerInterface/Device.h"
|
||||
|
||||
namespace ControllerEmu
|
||||
{
|
||||
class BooleanSetting
|
||||
{
|
||||
public:
|
||||
BooleanSetting(const std::string& setting_name, const std::string& ui_name,
|
||||
const bool default_value, const SettingType setting_type = SettingType::NORMAL,
|
||||
const bool exclusive = false);
|
||||
BooleanSetting(const std::string& setting_name, const bool default_value,
|
||||
const SettingType setting_type = SettingType::NORMAL,
|
||||
const bool exclusive = false);
|
||||
|
||||
bool GetValue() const;
|
||||
void SetValue(bool value);
|
||||
bool IsExclusive() const;
|
||||
|
||||
const SettingType m_type;
|
||||
const std::string m_name;
|
||||
const std::string m_ui_name;
|
||||
const bool m_default_value;
|
||||
bool m_value;
|
||||
|
||||
private:
|
||||
const bool m_exclusive;
|
||||
};
|
||||
|
||||
} // namespace ControllerEmu
|
@ -6,20 +6,35 @@
|
||||
|
||||
namespace ControllerEmu
|
||||
{
|
||||
NumericSetting::NumericSetting(const std::string& setting_name, const ControlState default_value,
|
||||
const u32 low, const u32 high, const SettingType setting_type)
|
||||
: m_type(setting_type), m_name(setting_name), m_default_value(default_value), m_low(low),
|
||||
m_high(high), m_value(default_value)
|
||||
NumericSettingBase::NumericSettingBase(const NumericSettingDetails& details) : m_details(details)
|
||||
{
|
||||
}
|
||||
|
||||
ControlState NumericSetting::GetValue() const
|
||||
const char* NumericSettingBase::GetUIName() const
|
||||
{
|
||||
return m_value;
|
||||
return m_details.ui_name;
|
||||
}
|
||||
void NumericSetting::SetValue(ControlState value)
|
||||
|
||||
const char* NumericSettingBase::GetUISuffix() const
|
||||
{
|
||||
m_value = value;
|
||||
return m_details.ui_suffix;
|
||||
}
|
||||
|
||||
const char* NumericSettingBase::GetUIDescription() const
|
||||
{
|
||||
return m_details.ui_description;
|
||||
}
|
||||
|
||||
template <>
|
||||
SettingType NumericSetting<double>::GetType() const
|
||||
{
|
||||
return SettingType::Double;
|
||||
}
|
||||
|
||||
template <>
|
||||
SettingType NumericSetting<bool>::GetType() const
|
||||
{
|
||||
return SettingType::Bool;
|
||||
}
|
||||
|
||||
} // namespace ControllerEmu
|
||||
|
@ -4,29 +4,127 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "InputCommon/ControllerEmu/Setting/Setting.h"
|
||||
#include "Common/IniFile.h"
|
||||
#include "InputCommon/ControllerInterface/Device.h"
|
||||
|
||||
namespace ControllerEmu
|
||||
{
|
||||
class NumericSetting
|
||||
enum class SettingType
|
||||
{
|
||||
Double,
|
||||
Bool,
|
||||
};
|
||||
|
||||
struct NumericSettingDetails
|
||||
{
|
||||
NumericSettingDetails(const char* const _ini_name, const char* const _ui_suffix = nullptr,
|
||||
const char* const _ui_description = nullptr,
|
||||
const char* const _ui_name = nullptr)
|
||||
: ini_name(_ini_name), ui_suffix(_ui_suffix), ui_description(_ui_description),
|
||||
ui_name(_ui_name ? _ui_name : _ini_name)
|
||||
{
|
||||
}
|
||||
|
||||
// The name used in ini files.
|
||||
const char* const ini_name;
|
||||
|
||||
// A string applied to the number in the UI (unit of measure).
|
||||
const char* const ui_suffix;
|
||||
|
||||
// Detailed description of the setting.
|
||||
const char* const ui_description;
|
||||
|
||||
// The name used in the UI (if different from ini file).
|
||||
const char* const ui_name;
|
||||
};
|
||||
|
||||
class NumericSettingBase
|
||||
{
|
||||
public:
|
||||
NumericSetting(const std::string& setting_name, const ControlState default_value,
|
||||
const u32 low = 0, const u32 high = 100,
|
||||
const SettingType setting_type = SettingType::NORMAL);
|
||||
NumericSettingBase(const NumericSettingDetails& details);
|
||||
|
||||
ControlState GetValue() const;
|
||||
void SetValue(ControlState value);
|
||||
const SettingType m_type;
|
||||
const std::string m_name;
|
||||
const ControlState m_default_value;
|
||||
const u32 m_low;
|
||||
const u32 m_high;
|
||||
ControlState m_value;
|
||||
virtual ~NumericSettingBase() = default;
|
||||
|
||||
virtual void LoadFromIni(const IniFile::Section& section, const std::string& group_name) = 0;
|
||||
virtual void SaveToIni(IniFile::Section& section, const std::string& group_name) const = 0;
|
||||
|
||||
virtual SettingType GetType() const = 0;
|
||||
|
||||
const char* GetUIName() const;
|
||||
const char* GetUISuffix() const;
|
||||
const char* GetUIDescription() const;
|
||||
|
||||
protected:
|
||||
NumericSettingDetails m_details;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class SettingValue;
|
||||
|
||||
template <typename T>
|
||||
class NumericSetting : public NumericSettingBase
|
||||
{
|
||||
public:
|
||||
using ValueType = T;
|
||||
|
||||
static_assert(std::is_same<ValueType, double>() || std::is_same<ValueType, bool>(),
|
||||
"NumericSetting is only implemented for double and bool.");
|
||||
|
||||
NumericSetting(SettingValue<ValueType>* value, const NumericSettingDetails& details,
|
||||
ValueType default_value, ValueType min_value, ValueType max_value)
|
||||
: NumericSettingBase(details), m_value(*value), m_default_value(default_value),
|
||||
m_min_value(min_value), m_max_value(max_value)
|
||||
{
|
||||
}
|
||||
|
||||
void LoadFromIni(const IniFile::Section& section, const std::string& group_name) override
|
||||
{
|
||||
ValueType value;
|
||||
section.Get(group_name + m_details.ini_name, &value, m_default_value);
|
||||
SetValue(value);
|
||||
}
|
||||
|
||||
void SaveToIni(IniFile::Section& section, const std::string& group_name) const override
|
||||
{
|
||||
section.Set(group_name + m_details.ini_name, GetValue(), m_default_value);
|
||||
}
|
||||
|
||||
ValueType GetValue() const { return m_value.GetValue(); }
|
||||
void SetValue(ValueType value) { m_value.SetValue(value); }
|
||||
|
||||
ValueType GetDefaultValue() const { return m_default_value; }
|
||||
ValueType GetMinValue() const { return m_min_value; }
|
||||
ValueType GetMaxValue() const { return m_max_value; }
|
||||
|
||||
SettingType GetType() const override;
|
||||
|
||||
private:
|
||||
SettingValue<ValueType>& m_value;
|
||||
|
||||
const ValueType m_default_value;
|
||||
const ValueType m_min_value;
|
||||
const ValueType m_max_value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class SettingValue
|
||||
{
|
||||
using ValueType = T;
|
||||
|
||||
friend class NumericSetting<T>;
|
||||
|
||||
public:
|
||||
ValueType GetValue() const { return m_value; }
|
||||
|
||||
private:
|
||||
void SetValue(ValueType value) { m_value = value; }
|
||||
|
||||
// Values are R/W by both UI and CPU threads.
|
||||
std::atomic<ValueType> m_value;
|
||||
};
|
||||
|
||||
} // namespace ControllerEmu
|
||||
|
@ -1,15 +0,0 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ControllerEmu
|
||||
{
|
||||
enum class SettingType
|
||||
{
|
||||
NORMAL, // normal settings are saved to configuration files
|
||||
VIRTUAL, // virtual settings are not saved at all
|
||||
};
|
||||
|
||||
} // namespace ControllerEmu
|
@ -100,13 +100,13 @@ std::optional<u32> SquareStickGate::GetIdealCalibrationSampleCount() const
|
||||
ReshapableInput::ReshapableInput(std::string name, std::string ui_name, GroupType type)
|
||||
: ControlGroup(std::move(name), std::move(ui_name), type)
|
||||
{
|
||||
numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50));
|
||||
AddDeadzoneSetting(&m_deadzone_setting, 50);
|
||||
}
|
||||
|
||||
ControlState ReshapableInput::GetDeadzoneRadiusAtAngle(double angle) const
|
||||
{
|
||||
// FYI: deadzone is scaled by input radius which allows the shape to match.
|
||||
return GetInputRadiusAtAngle(angle) * numeric_settings[SETTING_DEADZONE]->GetValue();
|
||||
return GetInputRadiusAtAngle(angle) * GetDeadzonePercentage();
|
||||
}
|
||||
|
||||
ControlState ReshapableInput::GetInputRadiusAtAngle(double angle) const
|
||||
@ -120,6 +120,11 @@ ControlState ReshapableInput::GetInputRadiusAtAngle(double angle) const
|
||||
return GetCalibrationDataRadiusAtAngle(m_calibration, angle);
|
||||
}
|
||||
|
||||
ControlState ReshapableInput::GetDeadzonePercentage() const
|
||||
{
|
||||
return m_deadzone_setting.GetValue() / 100;
|
||||
}
|
||||
|
||||
ControlState ReshapableInput::GetCalibrationDataRadiusAtAngle(const CalibrationData& data,
|
||||
double angle)
|
||||
{
|
||||
@ -267,7 +272,7 @@ ReshapableInput::ReshapeData ReshapableInput::Reshape(ControlState x, ControlSta
|
||||
}
|
||||
|
||||
// Apply deadzone as a percentage of the user-defined calibration shape/size:
|
||||
const ControlState deadzone = numeric_settings[SETTING_DEADZONE]->GetValue();
|
||||
const ControlState deadzone = GetDeadzonePercentage();
|
||||
dist = std::max(0.0, dist - deadzone) / (1.0 - deadzone);
|
||||
|
||||
// Scale to the gate shape/radius:
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "InputCommon/ControlReference/ControlReference.h"
|
||||
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
|
||||
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
|
||||
|
||||
namespace ControllerEmu
|
||||
{
|
||||
@ -77,16 +78,12 @@ public:
|
||||
|
||||
using ReshapeData = Common::DVec2;
|
||||
|
||||
enum
|
||||
{
|
||||
SETTING_DEADZONE,
|
||||
SETTING_COUNT,
|
||||
};
|
||||
|
||||
// Angle is in radians and should be non-negative
|
||||
ControlState GetDeadzoneRadiusAtAngle(double angle) const;
|
||||
ControlState GetInputRadiusAtAngle(double angle) const;
|
||||
|
||||
ControlState GetDeadzonePercentage() const;
|
||||
|
||||
virtual ControlState GetGateRadiusAtAngle(double angle) const = 0;
|
||||
virtual ReshapeData GetReshapableState(bool adjusted) = 0;
|
||||
virtual ControlState GetDefaultInputRadiusAtAngle(double ang) const;
|
||||
@ -108,6 +105,7 @@ private:
|
||||
void SaveConfig(IniFile::Section*, const std::string&, const std::string&) override;
|
||||
|
||||
CalibrationData m_calibration;
|
||||
SettingValue<double> m_deadzone_setting;
|
||||
};
|
||||
|
||||
} // namespace ControllerEmu
|
||||
|
Reference in New Issue
Block a user