mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Merge pull request #8643 from jordan-woyak/mapping-race-fix
InputCommon/DolphinQt: Mapping related race fixes and cleanups.
This commit is contained in:
@@ -544,7 +544,7 @@ void InputStateDelegate::paint(QPainter* painter, const QStyleOptionViewItem& op
|
||||
rect.setWidth(rect.width() * std::clamp(state, 0.0, 1.0));
|
||||
|
||||
// Create a temporary indicator object to retreive color constants.
|
||||
MappingIndicator indicator(nullptr);
|
||||
MappingIndicator indicator;
|
||||
|
||||
painter->save();
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,7 @@ class Control;
|
||||
class ControlGroup;
|
||||
class Cursor;
|
||||
class Force;
|
||||
class MixedTriggers;
|
||||
} // namespace ControllerEmu
|
||||
|
||||
class QPainter;
|
||||
@@ -29,10 +30,6 @@ class CalibrationWidget;
|
||||
class MappingIndicator : public QWidget
|
||||
{
|
||||
public:
|
||||
explicit MappingIndicator(ControllerEmu::ControlGroup* group);
|
||||
|
||||
void SetCalibrationWidget(CalibrationWidget* widget);
|
||||
|
||||
QPen GetBBoxPen() const;
|
||||
QBrush GetBBoxBrush() const;
|
||||
QColor GetRawInputColor() const;
|
||||
@@ -41,66 +38,145 @@ public:
|
||||
QColor GetAdjustedInputColor() const;
|
||||
QColor GetDeadZoneColor() const;
|
||||
QPen GetDeadZonePen() const;
|
||||
QBrush GetDeadZoneBrush() const;
|
||||
QBrush GetDeadZoneBrush(QPainter&) const;
|
||||
QColor GetTextColor() const;
|
||||
QColor GetAltTextColor() const;
|
||||
void AdjustGateColor(QColor*);
|
||||
|
||||
protected:
|
||||
double GetScale() const;
|
||||
|
||||
WiimoteEmu::MotionState m_motion_state{};
|
||||
virtual void Draw() {}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
class SquareIndicator : public MappingIndicator
|
||||
{
|
||||
protected:
|
||||
SquareIndicator();
|
||||
|
||||
qreal GetContentsScale() const;
|
||||
void DrawBoundingBox(QPainter&);
|
||||
void TransformPainter(QPainter&);
|
||||
};
|
||||
|
||||
class ReshapableInputIndicator : public SquareIndicator
|
||||
{
|
||||
public:
|
||||
void SetCalibrationWidget(CalibrationWidget* widget);
|
||||
|
||||
protected:
|
||||
void DrawReshapableInput(ControllerEmu::ReshapableInput& group, QColor gate_color,
|
||||
std::optional<ControllerEmu::ReshapableInput::ReshapeData> adj_coord);
|
||||
|
||||
virtual void DrawUnderGate(QPainter&) {}
|
||||
|
||||
bool IsCalibrating() const;
|
||||
|
||||
void DrawCalibration(QPainter& p, Common::DVec2 point);
|
||||
void UpdateCalibrationWidget(Common::DVec2 point);
|
||||
|
||||
ControllerEmu::ControlGroup* const m_group;
|
||||
private:
|
||||
CalibrationWidget* m_calibration_widget{};
|
||||
};
|
||||
|
||||
class ShakeMappingIndicator : public MappingIndicator
|
||||
class AnalogStickIndicator : public ReshapableInputIndicator
|
||||
{
|
||||
public:
|
||||
explicit ShakeMappingIndicator(ControllerEmu::Shake* group);
|
||||
|
||||
void DrawShake();
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
explicit AnalogStickIndicator(ControllerEmu::ReshapableInput& stick) : m_group(stick) {}
|
||||
|
||||
private:
|
||||
std::deque<ControllerEmu::Shake::StateData> m_position_samples;
|
||||
int m_grid_line_position = 0;
|
||||
void Draw() override;
|
||||
|
||||
ControllerEmu::Shake& m_shake_group;
|
||||
ControllerEmu::ReshapableInput& m_group;
|
||||
};
|
||||
|
||||
class AccelerometerMappingIndicator : public MappingIndicator
|
||||
class TiltIndicator : public ReshapableInputIndicator
|
||||
{
|
||||
public:
|
||||
explicit AccelerometerMappingIndicator(ControllerEmu::IMUAccelerometer* group);
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
explicit TiltIndicator(ControllerEmu::Tilt& tilt) : m_group(tilt) {}
|
||||
|
||||
private:
|
||||
void Draw() override;
|
||||
|
||||
ControllerEmu::Tilt& m_group;
|
||||
WiimoteEmu::MotionState m_motion_state{};
|
||||
};
|
||||
|
||||
class CursorIndicator : public ReshapableInputIndicator
|
||||
{
|
||||
public:
|
||||
explicit CursorIndicator(ControllerEmu::Cursor& cursor) : m_cursor_group(cursor) {}
|
||||
|
||||
private:
|
||||
void Draw() override;
|
||||
|
||||
ControllerEmu::Cursor& m_cursor_group;
|
||||
};
|
||||
|
||||
class MixedTriggersIndicator : public MappingIndicator
|
||||
{
|
||||
public:
|
||||
explicit MixedTriggersIndicator(ControllerEmu::MixedTriggers& triggers);
|
||||
|
||||
private:
|
||||
void Draw() override;
|
||||
|
||||
ControllerEmu::MixedTriggers& m_group;
|
||||
};
|
||||
|
||||
class SwingIndicator : public ReshapableInputIndicator
|
||||
{
|
||||
public:
|
||||
explicit SwingIndicator(ControllerEmu::Force& swing) : m_swing_group(swing) {}
|
||||
|
||||
private:
|
||||
void Draw() override;
|
||||
|
||||
void DrawUnderGate(QPainter& p) override;
|
||||
|
||||
ControllerEmu::Force& m_swing_group;
|
||||
WiimoteEmu::MotionState m_motion_state{};
|
||||
};
|
||||
|
||||
class ShakeMappingIndicator : public SquareIndicator
|
||||
{
|
||||
public:
|
||||
explicit ShakeMappingIndicator(ControllerEmu::Shake& shake) : m_shake_group(shake) {}
|
||||
|
||||
private:
|
||||
void Draw() override;
|
||||
|
||||
ControllerEmu::Shake& m_shake_group;
|
||||
WiimoteEmu::MotionState m_motion_state{};
|
||||
std::deque<ControllerEmu::Shake::StateData> m_position_samples;
|
||||
int m_grid_line_position = 0;
|
||||
};
|
||||
|
||||
class AccelerometerMappingIndicator : public SquareIndicator
|
||||
{
|
||||
public:
|
||||
explicit AccelerometerMappingIndicator(ControllerEmu::IMUAccelerometer& accel)
|
||||
: m_accel_group(accel)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
void Draw() override;
|
||||
|
||||
ControllerEmu::IMUAccelerometer& m_accel_group;
|
||||
};
|
||||
|
||||
class GyroMappingIndicator : public MappingIndicator
|
||||
class GyroMappingIndicator : public SquareIndicator
|
||||
{
|
||||
public:
|
||||
explicit GyroMappingIndicator(ControllerEmu::IMUGyroscope* group);
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
explicit GyroMappingIndicator(ControllerEmu::IMUGyroscope& gyro) : m_gyro_group(gyro) {}
|
||||
|
||||
private:
|
||||
void Draw() override;
|
||||
|
||||
ControllerEmu::IMUGyroscope& m_gyro_group;
|
||||
Common::Matrix33 m_state;
|
||||
Common::Matrix33 m_state = Common::Matrix33::Identity();
|
||||
Common::Vec3 m_previous_velocity = {};
|
||||
u32 m_stable_steps = 0;
|
||||
};
|
||||
@@ -108,7 +184,7 @@ private:
|
||||
class CalibrationWidget : public QToolButton
|
||||
{
|
||||
public:
|
||||
CalibrationWidget(ControllerEmu::ReshapableInput& input, MappingIndicator& indicator);
|
||||
CalibrationWidget(ControllerEmu::ReshapableInput& input, ReshapableInputIndicator& indicator);
|
||||
|
||||
void Update(Common::DVec2 point);
|
||||
|
||||
@@ -123,7 +199,7 @@ private:
|
||||
void SetupActions();
|
||||
|
||||
ControllerEmu::ReshapableInput& m_input;
|
||||
MappingIndicator& m_indicator;
|
||||
ReshapableInputIndicator& m_indicator;
|
||||
QAction* m_completion_action;
|
||||
ControllerEmu::ReshapableInput::CalibrationData m_calibration_data;
|
||||
QTimer* m_informative_timer;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "InputCommon/ControlReference/ControlReference.h"
|
||||
#include "InputCommon/ControllerEmu/Control/Control.h"
|
||||
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
|
||||
#include "InputCommon/ControllerEmu/ControlGroup/MixedTriggers.h"
|
||||
#include "InputCommon/ControllerEmu/ControllerEmu.h"
|
||||
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
|
||||
#include "InputCommon/ControllerEmu/StickGate.h"
|
||||
@@ -52,52 +53,66 @@ QGroupBox* MappingWidget::CreateGroupBox(const QString& name, ControllerEmu::Con
|
||||
|
||||
group_box->setLayout(form_layout);
|
||||
|
||||
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::Force ||
|
||||
group->type == ControllerEmu::GroupType::IMUAccelerometer ||
|
||||
group->type == ControllerEmu::GroupType::IMUGyroscope ||
|
||||
group->type == ControllerEmu::GroupType::Shake;
|
||||
MappingIndicator* indicator = nullptr;
|
||||
|
||||
const bool need_calibration = group->type == ControllerEmu::GroupType::Cursor ||
|
||||
group->type == ControllerEmu::GroupType::Stick ||
|
||||
group->type == ControllerEmu::GroupType::Tilt ||
|
||||
group->type == ControllerEmu::GroupType::Force;
|
||||
|
||||
if (need_indicator)
|
||||
switch (group->type)
|
||||
{
|
||||
MappingIndicator* indicator;
|
||||
case ControllerEmu::GroupType::Shake:
|
||||
indicator = new ShakeMappingIndicator(*static_cast<ControllerEmu::Shake*>(group));
|
||||
break;
|
||||
|
||||
switch (group->type)
|
||||
{
|
||||
case ControllerEmu::GroupType::Shake:
|
||||
indicator = new ShakeMappingIndicator(static_cast<ControllerEmu::Shake*>(group));
|
||||
break;
|
||||
case ControllerEmu::GroupType::MixedTriggers:
|
||||
indicator = new MixedTriggersIndicator(*static_cast<ControllerEmu::MixedTriggers*>(group));
|
||||
break;
|
||||
|
||||
case ControllerEmu::GroupType::IMUAccelerometer:
|
||||
indicator =
|
||||
new AccelerometerMappingIndicator(static_cast<ControllerEmu::IMUAccelerometer*>(group));
|
||||
break;
|
||||
case ControllerEmu::GroupType::Tilt:
|
||||
indicator = new TiltIndicator(*static_cast<ControllerEmu::Tilt*>(group));
|
||||
break;
|
||||
|
||||
case ControllerEmu::GroupType::IMUGyroscope:
|
||||
indicator = new GyroMappingIndicator(static_cast<ControllerEmu::IMUGyroscope*>(group));
|
||||
break;
|
||||
case ControllerEmu::GroupType::Cursor:
|
||||
indicator = new CursorIndicator(*static_cast<ControllerEmu::Cursor*>(group));
|
||||
break;
|
||||
|
||||
default:
|
||||
indicator = new MappingIndicator(group);
|
||||
break;
|
||||
}
|
||||
case ControllerEmu::GroupType::Force:
|
||||
indicator = new SwingIndicator(*static_cast<ControllerEmu::Force*>(group));
|
||||
break;
|
||||
|
||||
form_layout->addRow(indicator);
|
||||
case ControllerEmu::GroupType::IMUAccelerometer:
|
||||
indicator =
|
||||
new AccelerometerMappingIndicator(*static_cast<ControllerEmu::IMUAccelerometer*>(group));
|
||||
break;
|
||||
|
||||
case ControllerEmu::GroupType::IMUGyroscope:
|
||||
indicator = new GyroMappingIndicator(*static_cast<ControllerEmu::IMUGyroscope*>(group));
|
||||
break;
|
||||
|
||||
case ControllerEmu::GroupType::Stick:
|
||||
indicator = new AnalogStickIndicator(*static_cast<ControllerEmu::ReshapableInput*>(group));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (indicator)
|
||||
{
|
||||
const auto indicator_layout = new QBoxLayout(QBoxLayout::Direction::Down);
|
||||
indicator_layout->addWidget(indicator);
|
||||
indicator_layout->setAlignment(Qt::AlignCenter);
|
||||
form_layout->addRow(indicator_layout);
|
||||
|
||||
connect(this, &MappingWidget::Update, indicator, QOverload<>::of(&MappingIndicator::update));
|
||||
|
||||
const bool need_calibration = group->type == ControllerEmu::GroupType::Cursor ||
|
||||
group->type == ControllerEmu::GroupType::Stick ||
|
||||
group->type == ControllerEmu::GroupType::Tilt ||
|
||||
group->type == ControllerEmu::GroupType::Force;
|
||||
|
||||
if (need_calibration)
|
||||
{
|
||||
const auto calibrate =
|
||||
new CalibrationWidget(*static_cast<ControllerEmu::ReshapableInput*>(group), *indicator);
|
||||
new CalibrationWidget(*static_cast<ControllerEmu::ReshapableInput*>(group),
|
||||
*static_cast<ReshapableInputIndicator*>(indicator));
|
||||
|
||||
form_layout->addRow(calibrate);
|
||||
}
|
||||
@@ -105,7 +120,7 @@ QGroupBox* MappingWidget::CreateGroupBox(const QString& name, ControllerEmu::Con
|
||||
|
||||
for (auto& control : group->controls)
|
||||
{
|
||||
auto* button = new MappingButton(this, control->control_ref.get(), !need_indicator);
|
||||
auto* button = new MappingButton(this, control->control_ref.get(), !indicator);
|
||||
|
||||
button->setMinimumWidth(100);
|
||||
button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
|
||||
@@ -71,7 +71,7 @@ MappingWindow::MappingWindow(QWidget* parent, Type type, int port_num)
|
||||
|
||||
timer->start(1000 / INDICATOR_UPDATE_FREQ);
|
||||
|
||||
GetController()->GetStateLock();
|
||||
const auto lock = GetController()->GetStateLock();
|
||||
emit ConfigChanged();
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ void MappingWindow::OnLoadProfilePressed()
|
||||
m_controller->LoadConfig(ini.GetOrCreateSection("Profile"));
|
||||
m_controller->UpdateReferences(g_controller_interface);
|
||||
|
||||
GetController()->GetStateLock();
|
||||
const auto lock = GetController()->GetStateLock();
|
||||
emit ConfigChanged();
|
||||
}
|
||||
|
||||
@@ -438,7 +438,7 @@ void MappingWindow::OnDefaultFieldsPressed()
|
||||
m_controller->LoadDefaults(g_controller_interface);
|
||||
m_controller->UpdateReferences(g_controller_interface);
|
||||
|
||||
GetController()->GetStateLock();
|
||||
const auto lock = GetController()->GetStateLock();
|
||||
emit ConfigChanged();
|
||||
emit Save();
|
||||
}
|
||||
@@ -455,7 +455,7 @@ void MappingWindow::OnClearFieldsPressed()
|
||||
|
||||
m_controller->UpdateReferences(g_controller_interface);
|
||||
|
||||
GetController()->GetStateLock();
|
||||
const auto lock = GetController()->GetStateLock();
|
||||
emit ConfigChanged();
|
||||
emit Save();
|
||||
}
|
||||
|
||||
@@ -74,4 +74,9 @@ ControlState MixedTriggers::GetThreshold() const
|
||||
return m_threshold_setting.GetValue() / 100;
|
||||
}
|
||||
|
||||
size_t MixedTriggers::GetTriggerCount() const
|
||||
{
|
||||
return controls.size() / 2;
|
||||
}
|
||||
|
||||
} // namespace ControllerEmu
|
||||
|
||||
@@ -22,6 +22,8 @@ public:
|
||||
ControlState GetDeadzone() const;
|
||||
ControlState GetThreshold() const;
|
||||
|
||||
size_t GetTriggerCount() const;
|
||||
|
||||
private:
|
||||
SettingValue<double> m_threshold_setting;
|
||||
SettingValue<double> m_deadzone_setting;
|
||||
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
// references and GetState(), by extension. This prevents a race condition
|
||||
// which happens while handling a hotplug event because a control reference's State()
|
||||
// could be called before we have finished updating the reference.
|
||||
static std::unique_lock<std::recursive_mutex> GetStateLock();
|
||||
[[nodiscard]] static std::unique_lock<std::recursive_mutex> GetStateLock();
|
||||
|
||||
std::vector<std::unique_ptr<ControlGroup>> groups;
|
||||
|
||||
|
||||
@@ -309,7 +309,6 @@ DeviceContainer::DetectInput(u32 wait_ms, const std::vector<std::string>& device
|
||||
|
||||
for (auto& device_state : device_states)
|
||||
{
|
||||
device_state.device->UpdateInput();
|
||||
for (auto& input_state : device_state.input_states)
|
||||
{
|
||||
// We want an input that was initially 0.0 and currently 1.0.
|
||||
|
||||
Reference in New Issue
Block a user