mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-05-14 23:22:39 +00:00
InputCommon: Add "Dead Zone" setting to raw gyro inputs.
This commit is contained in:
parent
2d6a72e941
commit
82a3aa5ff6
3 changed files with 88 additions and 39 deletions
|
@ -754,33 +754,34 @@ void AccelerometerMappingIndicator::paintEvent(QPaintEvent*)
|
|||
p.setBrush(Qt::NoBrush);
|
||||
p.drawEllipse(QPointF{}, scale * SPHERE_SIZE, scale * SPHERE_SIZE);
|
||||
|
||||
// Red dot upright target.
|
||||
p.setPen(QPen(GetAdjustedInputColor(), INPUT_DOT_RADIUS / 2));
|
||||
p.drawEllipse(QPointF{0, SPHERE_INDICATOR_DIST} * scale, INPUT_DOT_RADIUS, INPUT_DOT_RADIUS);
|
||||
p.setPen(Qt::NoPen);
|
||||
|
||||
// Red dot.
|
||||
const auto point = rotation * Common::Vec3{0, 0, SPHERE_INDICATOR_DIST};
|
||||
if (point.y > 0 || Common::Vec2(point.x, point.z).Length() > SPHERE_SIZE)
|
||||
{
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(GetAdjustedInputColor());
|
||||
p.drawEllipse(QPointF(point.x, point.z) * scale, INPUT_DOT_RADIUS, INPUT_DOT_RADIUS);
|
||||
}
|
||||
|
||||
// Blue dot target.
|
||||
p.setPen(QPen(Qt::blue, INPUT_DOT_RADIUS / 2));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.drawEllipse(QPointF{0, -SPHERE_INDICATOR_DIST} * scale, INPUT_DOT_RADIUS, INPUT_DOT_RADIUS);
|
||||
|
||||
// Blue dot.
|
||||
const auto point2 = -point;
|
||||
if (point2.y > 0 || Common::Vec2(point2.x, point2.z).Length() > SPHERE_SIZE)
|
||||
{
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(Qt::blue);
|
||||
p.drawEllipse(QPointF(point2.x, point2.z) * scale, INPUT_DOT_RADIUS, INPUT_DOT_RADIUS);
|
||||
}
|
||||
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
// Red dot upright target.
|
||||
p.setPen(QPen(GetAdjustedInputColor(), INPUT_DOT_RADIUS / 2));
|
||||
p.drawEllipse(QPointF{0, SPHERE_INDICATOR_DIST} * scale, INPUT_DOT_RADIUS, INPUT_DOT_RADIUS);
|
||||
|
||||
// Blue dot target.
|
||||
p.setPen(QPen(Qt::blue, INPUT_DOT_RADIUS / 2));
|
||||
p.drawEllipse(QPointF{0, -SPHERE_INDICATOR_DIST} * scale, INPUT_DOT_RADIUS, INPUT_DOT_RADIUS);
|
||||
|
||||
// Only draw g-force text if acceleration data is present.
|
||||
if (!accel_state.has_value())
|
||||
return;
|
||||
|
@ -802,6 +803,7 @@ GyroMappingIndicator::GyroMappingIndicator(ControllerEmu::IMUGyroscope* group)
|
|||
void GyroMappingIndicator::paintEvent(QPaintEvent*)
|
||||
{
|
||||
const auto gyro_state = m_gyro_group.GetState();
|
||||
const auto raw_gyro_state = m_gyro_group.GetRawState();
|
||||
const auto angular_velocity = gyro_state.value_or(Common::Vec3{});
|
||||
|
||||
m_state *= Common::Matrix33::FromQuaternion(angular_velocity.x / -INDICATOR_UPDATE_FREQ / 2,
|
||||
|
@ -810,8 +812,8 @@ void GyroMappingIndicator::paintEvent(QPaintEvent*)
|
|||
|
||||
// Reset orientation when stable for a bit:
|
||||
constexpr u32 STABLE_RESET_STEPS = INDICATOR_UPDATE_FREQ;
|
||||
// This works well with my DS4 but a potentially noisy device might not behave.
|
||||
const bool is_stable = angular_velocity.Length() < MathUtil::TAU / 30;
|
||||
// Consider device stable when data (with deadzone applied) is zero.
|
||||
const bool is_stable = !angular_velocity.LengthSquared();
|
||||
|
||||
if (!is_stable)
|
||||
m_stable_steps = 0;
|
||||
|
@ -839,10 +841,39 @@ void GyroMappingIndicator::paintEvent(QPaintEvent*)
|
|||
p.setRenderHint(QPainter::Antialiasing, true);
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
|
||||
// Deadzone.
|
||||
if (const auto deadzone_value = m_gyro_group.GetDeadzone(); deadzone_value)
|
||||
{
|
||||
static constexpr auto DEADZONE_DRAW_SIZE = 1 - SPHERE_SIZE;
|
||||
static constexpr auto DEADZONE_DRAW_BOTTOM = 1;
|
||||
|
||||
p.setPen(GetDeadZonePen());
|
||||
p.setBrush(GetDeadZoneBrush());
|
||||
p.scale(-1.0, 1.0);
|
||||
p.drawRect(-scale, DEADZONE_DRAW_BOTTOM * scale, scale * 2, -scale * DEADZONE_DRAW_SIZE);
|
||||
p.scale(-1.0, 1.0);
|
||||
|
||||
if (gyro_state.has_value())
|
||||
{
|
||||
const auto max_velocity = std::max(
|
||||
{std::abs(raw_gyro_state.x), std::abs(raw_gyro_state.y), std::abs(raw_gyro_state.z)});
|
||||
const auto max_velocity_line_y =
|
||||
std::min(max_velocity / deadzone_value * DEADZONE_DRAW_SIZE - DEADZONE_DRAW_BOTTOM, 1.0);
|
||||
p.setPen(QPen(GetRawInputColor(), INPUT_DOT_RADIUS));
|
||||
p.drawLine(-scale, max_velocity_line_y * -scale, scale, max_velocity_line_y * -scale);
|
||||
|
||||
// Sphere background.
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(GetBBoxBrush());
|
||||
p.drawEllipse(QPointF{}, scale * SPHERE_SIZE, scale * SPHERE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
// Sphere dots.
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(GetRawInputColor());
|
||||
|
||||
GenerateFibonacciSphere(SPHERE_POINT_COUNT, [&, this](const Common::Vec3& point) {
|
||||
GenerateFibonacciSphere(SPHERE_POINT_COUNT, [&](const Common::Vec3& point) {
|
||||
const auto pt = rotation * point;
|
||||
|
||||
if (pt.y > 0)
|
||||
|
@ -850,49 +881,36 @@ void GyroMappingIndicator::paintEvent(QPaintEvent*)
|
|||
});
|
||||
|
||||
// Sphere outline.
|
||||
p.setPen(GetRawInputColor());
|
||||
p.setPen(is_stable ? GetRawInputColor() : GetAdjustedInputColor());
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.drawEllipse(QPointF{}, scale * SPHERE_SIZE, scale * SPHERE_SIZE);
|
||||
|
||||
// Red dot upright target.
|
||||
p.setPen(QPen(GetAdjustedInputColor(), INPUT_DOT_RADIUS / 2));
|
||||
p.drawEllipse(QPointF{0, -SPHERE_INDICATOR_DIST} * scale, INPUT_DOT_RADIUS, INPUT_DOT_RADIUS);
|
||||
p.setPen(Qt::NoPen);
|
||||
|
||||
// Red dot.
|
||||
const auto point = rotation * Common::Vec3{0, 0, -SPHERE_INDICATOR_DIST};
|
||||
if (point.y > 0 || Common::Vec2(point.x, point.z).Length() > SPHERE_SIZE)
|
||||
{
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(GetAdjustedInputColor());
|
||||
p.drawEllipse(QPointF(point.x, point.z) * scale, INPUT_DOT_RADIUS, INPUT_DOT_RADIUS);
|
||||
}
|
||||
|
||||
// Blue dot target.
|
||||
p.setPen(QPen(Qt::blue, INPUT_DOT_RADIUS / 2));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.drawEllipse(QPointF{}, INPUT_DOT_RADIUS, INPUT_DOT_RADIUS);
|
||||
|
||||
// Blue dot.
|
||||
const auto point2 = rotation * Common::Vec3{0, SPHERE_INDICATOR_DIST, 0};
|
||||
if (point2.y > 0 || Common::Vec2(point2.x, point2.z).Length() > SPHERE_SIZE)
|
||||
{
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(Qt::blue);
|
||||
p.drawEllipse(QPointF(point2.x, point2.z) * scale, INPUT_DOT_RADIUS, INPUT_DOT_RADIUS);
|
||||
}
|
||||
|
||||
// Only draw text if data is present.
|
||||
if (!gyro_state.has_value())
|
||||
return;
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
// Angle of red dot from starting position.
|
||||
const auto angle = std::acos(point.Normalized().Dot({0, 0, -1}));
|
||||
// Red dot upright target.
|
||||
p.setPen(QPen(GetAdjustedInputColor(), INPUT_DOT_RADIUS / 2));
|
||||
p.drawEllipse(QPointF{0, -SPHERE_INDICATOR_DIST} * scale, INPUT_DOT_RADIUS, INPUT_DOT_RADIUS);
|
||||
|
||||
// Angle text:
|
||||
p.setPen(GetTextColor());
|
||||
p.drawText(QRectF(-2, 0, scale, scale), Qt::AlignBottom | Qt::AlignRight,
|
||||
// i18n: "°" is the symbol for degrees (angular measurement).
|
||||
QString::fromStdString(fmt::format("{:.2f} °", angle / MathUtil::TAU * 360)));
|
||||
// Blue dot target.
|
||||
p.setPen(QPen(Qt::blue, INPUT_DOT_RADIUS / 2));
|
||||
p.drawEllipse(QPointF{}, INPUT_DOT_RADIUS, INPUT_DOT_RADIUS);
|
||||
}
|
||||
|
||||
void MappingIndicator::DrawCalibration(QPainter& p, Common::DVec2 point)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue