mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-06-28 01:49:33 -06:00
Merge pull request #13759 from jordan-woyak/calibrate-autocomplete
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 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.
|
||||
p.save();
|
||||
p.rotate(elapsed_seconds * -360.0);
|
||||
DrawPushedStick(
|
||||
p, m_indicator,
|
||||
-QEasingCurve(QEasingCurve::OutCirc).valueForProgress(std::min(elapsed_seconds * 2, 1.0)));
|
||||
DrawPushedStick(p, m_indicator, -stick_pushed_amount);
|
||||
p.restore();
|
||||
|
||||
const auto center = m_calibrator->GetCenter();
|
||||
@ -1031,8 +1036,6 @@ void ReshapableInputIndicator::SetCalibrationWidget(CalibrationWidget* widget)
|
||||
m_calibration_widget = widget;
|
||||
}
|
||||
|
||||
CalibrationWidget::~CalibrationWidget() = default;
|
||||
|
||||
CalibrationWidget::CalibrationWidget(MappingWidget& mapping_widget,
|
||||
ControllerEmu::ReshapableInput& input,
|
||||
ReshapableInputIndicator& indicator)
|
||||
@ -1132,13 +1135,7 @@ void CalibrationWidget::StartCalibration(std::optional<Common::DVec2> center)
|
||||
|
||||
// i18n: A button to finalize a game controller calibration process.
|
||||
auto* const finish_action = new QAction(tr("Finish Calibration"), this);
|
||||
connect(finish_action, &QAction::triggered, this, [this]() {
|
||||
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); });
|
||||
connect(finish_action, &QAction::triggered, this, &CalibrationWidget::FinishCalibration);
|
||||
|
||||
DeleteAllActions();
|
||||
|
||||
@ -1147,6 +1144,13 @@ void CalibrationWidget::StartCalibration(std::optional<Common::DVec2> center)
|
||||
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)
|
||||
{
|
||||
// FYI: The "StateLock" is always held when this is called.
|
||||
@ -1194,9 +1198,14 @@ void CalibrationWidget::Update(Common::DVec2 point)
|
||||
else if (IsCalibrating())
|
||||
{
|
||||
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))
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <QToolButton>
|
||||
#include <QWidget>
|
||||
|
||||
#include <chrono>
|
||||
#include <deque>
|
||||
|
||||
#include "Core/HW/WiimoteEmu/Dynamics.h"
|
||||
@ -238,11 +239,9 @@ private:
|
||||
|
||||
class CalibrationWidget : public QToolButton
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CalibrationWidget(MappingWidget& mapping_widget, ControllerEmu::ReshapableInput& input,
|
||||
ReshapableInputIndicator& indicator);
|
||||
~CalibrationWidget() override;
|
||||
|
||||
void Update(Common::DVec2 point);
|
||||
|
||||
@ -250,9 +249,6 @@ public:
|
||||
|
||||
bool IsActive() const;
|
||||
|
||||
signals:
|
||||
void CalibrationIsSensible();
|
||||
|
||||
private:
|
||||
void DrawInProgressMapping(QPainter& p);
|
||||
void DrawInProgressCalibration(QPainter& p, Common::DVec2 point);
|
||||
@ -263,6 +259,8 @@ private:
|
||||
void StartMappingAndCalibration();
|
||||
void StartCalibration(std::optional<Common::DVec2> center = Common::DVec2{});
|
||||
|
||||
void FinishCalibration();
|
||||
|
||||
void ResetActions();
|
||||
void DeleteAllActions();
|
||||
|
||||
@ -277,4 +275,8 @@ private:
|
||||
void RestartAnimation();
|
||||
|
||||
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 <chrono>
|
||||
#include <cmath>
|
||||
#include <ranges>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -277,6 +278,16 @@ bool CalibrationBuilder::IsCalibrationDataSensible() const
|
||||
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
|
||||
{
|
||||
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.
|
||||
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.
|
||||
// Used to render the calibration in the UI while it's in progress.
|
||||
ControlState GetCalibrationRadiusAtAngle(double angle) const;
|
||||
|
Reference in New Issue
Block a user