mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-06-28 01:49:33 -06:00
DolphinQt: Make Calibration autocomplete when data is "sensible" and stick is returned to neutral position.
This commit is contained in:
@ -980,12 +980,17 @@ void CalibrationWidget::DrawInProgressCalibration(QPainter& p, Common::DVec2 poi
|
|||||||
|
|
||||||
const auto elapsed_seconds = GetAnimationElapsedSeconds();
|
const auto elapsed_seconds = GetAnimationElapsedSeconds();
|
||||||
|
|
||||||
|
const auto stop_spinning_amount =
|
||||||
|
std::max(DT_s{m_stop_spinning_time - Clock::now()} / STOP_SPINNING_DURATION, 0.0);
|
||||||
|
|
||||||
|
const auto stick_pushed_amount =
|
||||||
|
QEasingCurve(QEasingCurve::OutCirc).valueForProgress(std::min(elapsed_seconds * 2, 1.0)) *
|
||||||
|
stop_spinning_amount;
|
||||||
|
|
||||||
// Clockwise spinning stick starting from center.
|
// Clockwise spinning stick starting from center.
|
||||||
p.save();
|
p.save();
|
||||||
p.rotate(elapsed_seconds * -360.0);
|
p.rotate(elapsed_seconds * -360.0);
|
||||||
DrawPushedStick(
|
DrawPushedStick(p, m_indicator, -stick_pushed_amount);
|
||||||
p, m_indicator,
|
|
||||||
-QEasingCurve(QEasingCurve::OutCirc).valueForProgress(std::min(elapsed_seconds * 2, 1.0)));
|
|
||||||
p.restore();
|
p.restore();
|
||||||
|
|
||||||
const auto center = m_calibrator->GetCenter();
|
const auto center = m_calibrator->GetCenter();
|
||||||
@ -1031,8 +1036,6 @@ void ReshapableInputIndicator::SetCalibrationWidget(CalibrationWidget* widget)
|
|||||||
m_calibration_widget = widget;
|
m_calibration_widget = widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
CalibrationWidget::~CalibrationWidget() = default;
|
|
||||||
|
|
||||||
CalibrationWidget::CalibrationWidget(MappingWidget& mapping_widget,
|
CalibrationWidget::CalibrationWidget(MappingWidget& mapping_widget,
|
||||||
ControllerEmu::ReshapableInput& input,
|
ControllerEmu::ReshapableInput& input,
|
||||||
ReshapableInputIndicator& indicator)
|
ReshapableInputIndicator& indicator)
|
||||||
@ -1132,13 +1135,7 @@ void CalibrationWidget::StartCalibration(std::optional<Common::DVec2> center)
|
|||||||
|
|
||||||
// i18n: A button to finalize a game controller calibration process.
|
// i18n: A button to finalize a game controller calibration process.
|
||||||
auto* const finish_action = new QAction(tr("Finish Calibration"), this);
|
auto* const finish_action = new QAction(tr("Finish Calibration"), this);
|
||||||
connect(finish_action, &QAction::triggered, this, [this]() {
|
connect(finish_action, &QAction::triggered, this, &CalibrationWidget::FinishCalibration);
|
||||||
const auto lock = m_mapping_widget.GetController()->GetStateLock();
|
|
||||||
m_calibrator->ApplyResults(&m_input);
|
|
||||||
ResetActions();
|
|
||||||
});
|
|
||||||
connect(this, &CalibrationWidget::CalibrationIsSensible, finish_action,
|
|
||||||
[this, finish_action]() { setDefaultAction(finish_action); });
|
|
||||||
|
|
||||||
DeleteAllActions();
|
DeleteAllActions();
|
||||||
|
|
||||||
@ -1147,6 +1144,13 @@ void CalibrationWidget::StartCalibration(std::optional<Common::DVec2> center)
|
|||||||
setDefaultAction(cancel_action);
|
setDefaultAction(cancel_action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CalibrationWidget::FinishCalibration()
|
||||||
|
{
|
||||||
|
const auto lock = m_mapping_widget.GetController()->GetStateLock();
|
||||||
|
m_calibrator->ApplyResults(&m_input);
|
||||||
|
ResetActions();
|
||||||
|
}
|
||||||
|
|
||||||
void CalibrationWidget::Update(Common::DVec2 point)
|
void CalibrationWidget::Update(Common::DVec2 point)
|
||||||
{
|
{
|
||||||
// FYI: The "StateLock" is always held when this is called.
|
// FYI: The "StateLock" is always held when this is called.
|
||||||
@ -1194,9 +1198,14 @@ void CalibrationWidget::Update(Common::DVec2 point)
|
|||||||
else if (IsCalibrating())
|
else if (IsCalibrating())
|
||||||
{
|
{
|
||||||
m_calibrator->Update(point);
|
m_calibrator->Update(point);
|
||||||
if (m_calibrator->IsCalibrationDataSensible())
|
|
||||||
|
if (!m_calibrator->IsCalibrationDataSensible())
|
||||||
{
|
{
|
||||||
emit CalibrationIsSensible();
|
m_stop_spinning_time = Clock::now() + STOP_SPINNING_DURATION;
|
||||||
|
}
|
||||||
|
else if (m_calibrator->IsComplete())
|
||||||
|
{
|
||||||
|
FinishCalibration();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (IsPointOutsideCalibration(point, m_input))
|
else if (IsPointOutsideCalibration(point, m_input))
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
#include "Core/HW/WiimoteEmu/Dynamics.h"
|
#include "Core/HW/WiimoteEmu/Dynamics.h"
|
||||||
@ -238,11 +239,9 @@ private:
|
|||||||
|
|
||||||
class CalibrationWidget : public QToolButton
|
class CalibrationWidget : public QToolButton
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
|
||||||
public:
|
public:
|
||||||
CalibrationWidget(MappingWidget& mapping_widget, ControllerEmu::ReshapableInput& input,
|
CalibrationWidget(MappingWidget& mapping_widget, ControllerEmu::ReshapableInput& input,
|
||||||
ReshapableInputIndicator& indicator);
|
ReshapableInputIndicator& indicator);
|
||||||
~CalibrationWidget() override;
|
|
||||||
|
|
||||||
void Update(Common::DVec2 point);
|
void Update(Common::DVec2 point);
|
||||||
|
|
||||||
@ -250,9 +249,6 @@ public:
|
|||||||
|
|
||||||
bool IsActive() const;
|
bool IsActive() const;
|
||||||
|
|
||||||
signals:
|
|
||||||
void CalibrationIsSensible();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DrawInProgressMapping(QPainter& p);
|
void DrawInProgressMapping(QPainter& p);
|
||||||
void DrawInProgressCalibration(QPainter& p, Common::DVec2 point);
|
void DrawInProgressCalibration(QPainter& p, Common::DVec2 point);
|
||||||
@ -263,6 +259,8 @@ private:
|
|||||||
void StartMappingAndCalibration();
|
void StartMappingAndCalibration();
|
||||||
void StartCalibration(std::optional<Common::DVec2> center = Common::DVec2{});
|
void StartCalibration(std::optional<Common::DVec2> center = Common::DVec2{});
|
||||||
|
|
||||||
|
void FinishCalibration();
|
||||||
|
|
||||||
void ResetActions();
|
void ResetActions();
|
||||||
void DeleteAllActions();
|
void DeleteAllActions();
|
||||||
|
|
||||||
@ -277,4 +275,8 @@ private:
|
|||||||
void RestartAnimation();
|
void RestartAnimation();
|
||||||
|
|
||||||
Clock::time_point m_animation_start_time{};
|
Clock::time_point m_animation_start_time{};
|
||||||
|
|
||||||
|
static constexpr auto STOP_SPINNING_DURATION = std::chrono::seconds{2};
|
||||||
|
|
||||||
|
Clock::time_point m_stop_spinning_time{};
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <cmath>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -277,6 +278,16 @@ bool CalibrationBuilder::IsCalibrationDataSensible() const
|
|||||||
return stats.StandardDeviation() < REASONABLE_DEVIATION;
|
return stats.StandardDeviation() < REASONABLE_DEVIATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CalibrationBuilder::IsComplete() const
|
||||||
|
{
|
||||||
|
if (!IsCalibrationDataSensible())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto half_calibration =
|
||||||
|
0.5 * GetCalibrationRadiusAtAngle(std::atan2(m_prev_point.y, m_prev_point.x) + MathUtil::TAU);
|
||||||
|
return m_prev_point.LengthSquared() < (half_calibration * half_calibration);
|
||||||
|
}
|
||||||
|
|
||||||
ControlState CalibrationBuilder::GetCalibrationRadiusAtAngle(double angle) const
|
ControlState CalibrationBuilder::GetCalibrationRadiusAtAngle(double angle) const
|
||||||
{
|
{
|
||||||
return ControllerEmu::ReshapableInput::GetCalibrationDataRadiusAtAngle(m_calibration_data, angle);
|
return ControllerEmu::ReshapableInput::GetCalibrationDataRadiusAtAngle(m_calibration_data, angle);
|
||||||
|
@ -85,6 +85,10 @@ public:
|
|||||||
// Used to update the UI to encourage the user to click the "Finish" button.
|
// Used to update the UI to encourage the user to click the "Finish" button.
|
||||||
bool IsCalibrationDataSensible() const;
|
bool IsCalibrationDataSensible() const;
|
||||||
|
|
||||||
|
// Returns true when the calibration data seems sensible,
|
||||||
|
// and the input then approaches the center position.
|
||||||
|
bool IsComplete() const;
|
||||||
|
|
||||||
// Grabs the calibration value at the provided angle.
|
// Grabs the calibration value at the provided angle.
|
||||||
// Used to render the calibration in the UI while it's in progress.
|
// Used to render the calibration in the UI while it's in progress.
|
||||||
ControlState GetCalibrationRadiusAtAngle(double angle) const;
|
ControlState GetCalibrationRadiusAtAngle(double angle) const;
|
||||||
|
Reference in New Issue
Block a user