mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
Merge pull request #7806 from jordan-woyak/wiimote-emu-swing-improve
WiimoteEmu: Reimplement tilt/swing/camera/orientation data using matrix math.
This commit is contained in:
@ -18,6 +18,7 @@
|
||||
#include "InputCommon/ControlReference/ControlReference.h"
|
||||
#include "InputCommon/ControllerEmu/Control/Control.h"
|
||||
#include "InputCommon/ControllerEmu/ControlGroup/Cursor.h"
|
||||
#include "InputCommon/ControllerEmu/ControlGroup/Force.h"
|
||||
#include "InputCommon/ControllerEmu/ControlGroup/MixedTriggers.h"
|
||||
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
|
||||
#include "InputCommon/ControllerInterface/Device.h"
|
||||
@ -45,16 +46,19 @@ const QColor STICK_GATE_COLOR = Qt::lightGray;
|
||||
const QColor C_STICK_GATE_COLOR = Qt::yellow;
|
||||
const QColor CURSOR_TV_COLOR = 0xaed6f1;
|
||||
const QColor TILT_GATE_COLOR = 0xa2d9ce;
|
||||
const QColor SWING_GATE_COLOR = 0xcea2d9;
|
||||
|
||||
constexpr int INPUT_DOT_RADIUS = 2;
|
||||
|
||||
constexpr int INDICATOR_UPDATE_FREQ = 30;
|
||||
|
||||
MappingIndicator::MappingIndicator(ControllerEmu::ControlGroup* group) : m_group(group)
|
||||
{
|
||||
setMinimumHeight(128);
|
||||
|
||||
const auto timer = new QTimer(this);
|
||||
connect(timer, &QTimer::timeout, this, [this] { repaint(); });
|
||||
timer->start(1000 / 30);
|
||||
timer->start(1000 / INDICATOR_UPDATE_FREQ);
|
||||
}
|
||||
|
||||
namespace
|
||||
@ -250,7 +254,19 @@ void MappingIndicator::DrawReshapableInput(ControllerEmu::ReshapableInput& stick
|
||||
// We should probably hold the mutex for UI updates.
|
||||
Settings::Instance().SetControllerStateNeeded(true);
|
||||
const auto raw_coord = stick.GetReshapableState(false);
|
||||
const auto adj_coord = stick.GetReshapableState(true);
|
||||
|
||||
Common::DVec2 adj_coord;
|
||||
if (is_tilt)
|
||||
{
|
||||
WiimoteEmu::EmulateTilt(&m_motion_state, static_cast<ControllerEmu::Tilt*>(&stick),
|
||||
1.f / INDICATOR_UPDATE_FREQ);
|
||||
adj_coord = Common::DVec2{-m_motion_state.angle.y, m_motion_state.angle.x} / MathUtil::PI;
|
||||
}
|
||||
else
|
||||
{
|
||||
adj_coord = stick.GetReshapableState(true);
|
||||
}
|
||||
|
||||
Settings::Instance().SetControllerStateNeeded(false);
|
||||
|
||||
UpdateCalibrationWidget(raw_coord);
|
||||
@ -408,6 +424,100 @@ void MappingIndicator::DrawMixedTriggers()
|
||||
}
|
||||
}
|
||||
|
||||
void MappingIndicator::DrawForce(ControllerEmu::Force& force)
|
||||
{
|
||||
const QColor gate_brush_color = SWING_GATE_COLOR;
|
||||
const QColor gate_pen_color = gate_brush_color.darker(125);
|
||||
|
||||
// TODO: This SetControllerStateNeeded interface leaks input into the game
|
||||
// We should probably hold the mutex for UI updates.
|
||||
Settings::Instance().SetControllerStateNeeded(true);
|
||||
const auto raw_coord = force.GetState(false);
|
||||
WiimoteEmu::EmulateSwing(&m_motion_state, &force, 1.f / INDICATOR_UPDATE_FREQ);
|
||||
const auto& adj_coord = m_motion_state.position;
|
||||
Settings::Instance().SetControllerStateNeeded(false);
|
||||
|
||||
UpdateCalibrationWidget({raw_coord.x, raw_coord.y});
|
||||
|
||||
// Bounding box size:
|
||||
const double scale = height() / 2.5;
|
||||
|
||||
QPainter p(this);
|
||||
p.translate(width() / 2, height() / 2);
|
||||
|
||||
// Bounding box.
|
||||
p.setBrush(BBOX_BRUSH_COLOR);
|
||||
p.setPen(BBOX_PEN_COLOR);
|
||||
p.drawRect(-scale - 1, -scale - 1, scale * 2 + 1, scale * 2 + 1);
|
||||
|
||||
// UI y-axis is opposite that of stick.
|
||||
p.scale(1.0, -1.0);
|
||||
|
||||
// Enable AA after drawing bounding box.
|
||||
p.setRenderHint(QPainter::Antialiasing, true);
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
|
||||
if (IsCalibrating())
|
||||
{
|
||||
DrawCalibration(p, {raw_coord.x, raw_coord.y});
|
||||
return;
|
||||
}
|
||||
|
||||
// Deadzone for Z (forward/backward):
|
||||
const double deadzone = force.numeric_settings[force.SETTING_DEADZONE]->GetValue();
|
||||
if (deadzone > 0.0)
|
||||
{
|
||||
p.setPen(DEADZONE_COLOR);
|
||||
p.setBrush(DEADZONE_BRUSH);
|
||||
p.drawRect(QRectF(-scale, -deadzone * scale, scale * 2, deadzone * scale * 2));
|
||||
}
|
||||
|
||||
// Raw Z:
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(RAW_INPUT_COLOR);
|
||||
p.drawRect(
|
||||
QRectF(-scale, raw_coord.z * scale - INPUT_DOT_RADIUS / 2, scale * 2, INPUT_DOT_RADIUS));
|
||||
|
||||
// Adjusted Z:
|
||||
if (adj_coord.y)
|
||||
{
|
||||
p.setBrush(ADJ_INPUT_COLOR);
|
||||
p.drawRect(
|
||||
QRectF(-scale, adj_coord.y * -scale - INPUT_DOT_RADIUS / 2, scale * 2, INPUT_DOT_RADIUS));
|
||||
}
|
||||
|
||||
// Draw "gate" shape.
|
||||
p.setPen(gate_pen_color);
|
||||
p.setBrush(gate_brush_color);
|
||||
p.drawPolygon(GetPolygonFromRadiusGetter(
|
||||
[&force](double ang) { return force.GetGateRadiusAtAngle(ang); }, scale));
|
||||
|
||||
// Deadzone.
|
||||
p.setPen(DEADZONE_COLOR);
|
||||
p.setBrush(DEADZONE_BRUSH);
|
||||
p.drawPolygon(GetPolygonFromRadiusGetter(
|
||||
[&force](double ang) { return force.GetDeadzoneRadiusAtAngle(ang); }, scale));
|
||||
|
||||
// Input shape.
|
||||
p.setPen(INPUT_SHAPE_PEN);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.drawPolygon(GetPolygonFromRadiusGetter(
|
||||
[&force](double ang) { return force.GetInputRadiusAtAngle(ang); }, scale));
|
||||
|
||||
// Raw stick position.
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(RAW_INPUT_COLOR);
|
||||
p.drawEllipse(QPointF{raw_coord.x, raw_coord.y} * scale, INPUT_DOT_RADIUS, INPUT_DOT_RADIUS);
|
||||
|
||||
// Adjusted position:
|
||||
if (adj_coord.x || adj_coord.z)
|
||||
{
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(ADJ_INPUT_COLOR);
|
||||
p.drawEllipse(QPointF{-adj_coord.x, adj_coord.z} * scale, INPUT_DOT_RADIUS, INPUT_DOT_RADIUS);
|
||||
}
|
||||
}
|
||||
|
||||
void MappingIndicator::paintEvent(QPaintEvent*)
|
||||
{
|
||||
switch (m_group->type)
|
||||
@ -422,6 +532,9 @@ void MappingIndicator::paintEvent(QPaintEvent*)
|
||||
case ControllerEmu::GroupType::MixedTriggers:
|
||||
DrawMixedTriggers();
|
||||
break;
|
||||
case ControllerEmu::GroupType::Force:
|
||||
DrawForce(*static_cast<ControllerEmu::Force*>(m_group));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <QToolButton>
|
||||
#include <QWidget>
|
||||
|
||||
#include "Core/HW/WiimoteEmu/Dynamics.h"
|
||||
#include "InputCommon/ControllerEmu/StickGate.h"
|
||||
|
||||
namespace ControllerEmu
|
||||
@ -14,6 +15,7 @@ namespace ControllerEmu
|
||||
class Control;
|
||||
class ControlGroup;
|
||||
class Cursor;
|
||||
class Force;
|
||||
class NumericSetting;
|
||||
} // namespace ControllerEmu
|
||||
|
||||
@ -34,6 +36,7 @@ private:
|
||||
void DrawCursor(ControllerEmu::Cursor& cursor);
|
||||
void DrawReshapableInput(ControllerEmu::ReshapableInput& stick);
|
||||
void DrawMixedTriggers();
|
||||
void DrawForce(ControllerEmu::Force&);
|
||||
void DrawCalibration(QPainter& p, Common::DVec2 point);
|
||||
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
@ -43,6 +46,8 @@ private:
|
||||
|
||||
ControllerEmu::ControlGroup* const m_group;
|
||||
CalibrationWidget* m_calibration_widget{};
|
||||
|
||||
WiimoteEmu::MotionState m_motion_state{};
|
||||
};
|
||||
|
||||
class CalibrationWidget : public QToolButton
|
||||
|
@ -77,11 +77,13 @@ QGroupBox* MappingWidget::CreateGroupBox(const QString& name, ControllerEmu::Con
|
||||
const bool need_indicator = group->type == ControllerEmu::GroupType::Cursor ||
|
||||
group->type == ControllerEmu::GroupType::Stick ||
|
||||
group->type == ControllerEmu::GroupType::Tilt ||
|
||||
group->type == ControllerEmu::GroupType::MixedTriggers;
|
||||
group->type == ControllerEmu::GroupType::MixedTriggers ||
|
||||
group->type == ControllerEmu::GroupType::Force;
|
||||
|
||||
const bool need_calibration = group->type == ControllerEmu::GroupType::Cursor ||
|
||||
group->type == ControllerEmu::GroupType::Stick ||
|
||||
group->type == ControllerEmu::GroupType::Tilt;
|
||||
group->type == ControllerEmu::GroupType::Tilt ||
|
||||
group->type == ControllerEmu::GroupType::Force;
|
||||
|
||||
for (auto& control : group->controls)
|
||||
{
|
||||
|
Reference in New Issue
Block a user