From 1076c1448ca1cc97110484f1bf3fb697f8ea70ee Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Fri, 16 Aug 2019 13:35:47 -0700 Subject: [PATCH] Redo balance board TAS input --- .../Core/DolphinQt/TAS/BalanceBoardWidget.cpp | 95 +++++++++++--- .../Core/DolphinQt/TAS/BalanceBoardWidget.h | 23 ++-- Source/Core/DolphinQt/TAS/TASInputWindow.cpp | 38 +++++- Source/Core/DolphinQt/TAS/TASInputWindow.h | 6 +- .../Core/DolphinQt/TAS/WiiTASInputWindow.cpp | 119 +++++++++++------- Source/Core/DolphinQt/TAS/WiiTASInputWindow.h | 8 +- 6 files changed, 211 insertions(+), 78 deletions(-) diff --git a/Source/Core/DolphinQt/TAS/BalanceBoardWidget.cpp b/Source/Core/DolphinQt/TAS/BalanceBoardWidget.cpp index 30a2d952a153..a59f3f154fc2 100644 --- a/Source/Core/DolphinQt/TAS/BalanceBoardWidget.cpp +++ b/Source/Core/DolphinQt/TAS/BalanceBoardWidget.cpp @@ -15,21 +15,67 @@ BalanceBoardWidget::BalanceBoardWidget(QWidget* parent) : QWidget(parent) { setMouseTracking(false); - setToolTip(tr("Left click to set the IR value.\n" - "Right click to re-center it.")); + setToolTip(tr("Left click to set the balance value.\n" + "Right click to return to perfect balance.")); } -void BalanceBoardWidget::SetX(u16 x) +void BalanceBoardWidget::SetTR(double top_right) { - m_x = std::min(balance_range, x); + m_top_right = top_right; + emit ChangedTotal(TotalWeight()); + update(); +} +void BalanceBoardWidget::SetBR(double bottom_right) +{ + m_bottom_right = bottom_right; + emit ChangedTotal(TotalWeight()); update(); } -void BalanceBoardWidget::SetY(u16 y) +void BalanceBoardWidget::SetTL(double top_left) { - m_y = std::min(balance_range, y); + m_top_left = top_left; + emit ChangedTotal(TotalWeight()); + update(); +} +void BalanceBoardWidget::SetBL(double bottom_left) +{ + m_bottom_left = bottom_left; + emit ChangedTotal(TotalWeight()); + update(); +} + +void BalanceBoardWidget::SetTotal(double total) +{ + const double current_total = TotalWeight(); + if (current_total != 0) + { + const double ratio = total / current_total; + m_top_right *= ratio; + m_bottom_right *= ratio; + m_top_left *= ratio; + m_bottom_left *= ratio; + } + else + { + m_top_right = total / 4; + m_bottom_right = total / 4; + m_top_left = total / 4; + m_bottom_left = total / 4; + } + emit ChangedTR(m_top_right); + emit ChangedBR(m_bottom_right); + emit ChangedTL(m_top_left); + emit ChangedBL(m_bottom_left); + + const double new_total = TotalWeight(); + if (new_total != total) + { + // This probably shouldn't happen, and I probably should round out numbers a bit closer + emit ChangedTotal(new_total); + } update(); } @@ -46,9 +92,17 @@ void BalanceBoardWidget::paintEvent(QPaintEvent* event) painter.drawLine(0, height() / 2, width(), height() / 2); painter.drawLine(width() / 2, 0, width() / 2, height()); - // convert from value space to widget space - const int x = (m_x * width()) / balance_range; - const int y = height() - (m_y * height()) / balance_range; + // Compute center of balance + const double total = TotalWeight(); + const double right = m_top_right + m_bottom_right; + const double left = m_top_left + m_bottom_left; + const double top = m_top_right + m_top_left; + const double bottom = m_bottom_right + m_bottom_left; + const double com_x = (total != 0) ? (right - left) / total : 0; + const double com_y = (total != 0) ? (top - bottom) / total : 0; + + const int x = (int)((com_x + 1) * width() / 2); + const int y = (int)((1 - com_y) * height() / 2); painter.drawLine(width() / 2, height() / 2, x, y); @@ -72,22 +126,29 @@ void BalanceBoardWidget::mouseMoveEvent(QMouseEvent* event) void BalanceBoardWidget::handleMouseEvent(QMouseEvent* event) { + const double total = TotalWeight(); if (event->button() == Qt::RightButton) { - m_x = std::round(balance_range / 2.); - m_y = std::round(balance_range / 2.); + m_top_right = total / 4; + m_bottom_right = total / 4; + m_top_left = total / 4; + m_bottom_left = total / 4; } else { // convert from widget space to value space - const int new_x = (event->x() * balance_range) / width(); - const int new_y = balance_range - (event->y() * balance_range) / height(); + const double com_x = std::clamp((event->x() * 2.) / width() - 1, -1., 1.); + const double com_y = std::clamp(1 - (event->y() * 2.) / height(), -1., 1.); - m_x = std::max(0, std::min(static_cast(balance_range), new_x)); - m_y = std::max(0, std::min(static_cast(balance_range), new_y)); + m_top_right = total * (1 + com_x + com_y) / 4; + m_bottom_right = total * (1 + com_x - com_y) / 4; + m_top_left = total * (1 - com_x + com_y) / 4; + m_bottom_left = total * (1 - com_x - com_y) / 4; } - emit ChangedX(m_x); - emit ChangedY(m_y); + emit ChangedTR(m_top_right); + emit ChangedBR(m_bottom_right); + emit ChangedTL(m_top_left); + emit ChangedBL(m_bottom_left); update(); } diff --git a/Source/Core/DolphinQt/TAS/BalanceBoardWidget.h b/Source/Core/DolphinQt/TAS/BalanceBoardWidget.h index e6605c5595c7..4ff958d331cf 100644 --- a/Source/Core/DolphinQt/TAS/BalanceBoardWidget.h +++ b/Source/Core/DolphinQt/TAS/BalanceBoardWidget.h @@ -14,15 +14,19 @@ class BalanceBoardWidget : public QWidget public: explicit BalanceBoardWidget(QWidget* parent); - static constexpr u16 balance_range = 1000; - signals: - void ChangedX(u16 x); - void ChangedY(u16 y); + void ChangedTR(double top_right); + void ChangedBR(double bottom_right); + void ChangedTL(double top_left); + void ChangedBL(double bottom_left); + void ChangedTotal(double total_weight); public slots: - void SetX(u16 x); - void SetY(u16 y); + void SetTR(double top_right); + void SetBR(double bottom_right); + void SetTL(double top_left); + void SetBL(double bottom_left); + void SetTotal(double total_weight); protected: void paintEvent(QPaintEvent* event) override; @@ -31,7 +35,10 @@ public slots: void handleMouseEvent(QMouseEvent* event); private: - u16 m_x = 0; - u16 m_y = 0; + double TotalWeight() { return m_top_right + m_bottom_right + m_top_left + m_bottom_left; } + double m_top_right = 0; + double m_bottom_right = 0; + double m_top_left = 0; + double m_bottom_left = 0; bool m_ignore_movement = false; }; diff --git a/Source/Core/DolphinQt/TAS/TASInputWindow.cpp b/Source/Core/DolphinQt/TAS/TASInputWindow.cpp index a4057a48d3e7..e7b78a5ff45e 100644 --- a/Source/Core/DolphinQt/TAS/TASInputWindow.cpp +++ b/Source/Core/DolphinQt/TAS/TASInputWindow.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -116,8 +117,8 @@ QGroupBox* TASInputWindow::CreateStickInputs(QString name, QSpinBox*& x_value, Q return box; } -QBoxLayout* TASInputWindow::CreateSliderValuePairLayout(QString name, QSpinBox*& value, int default_, u16 max, - Qt::Key shortcut_key, +QBoxLayout* TASInputWindow::CreateSliderValuePairLayout(QString name, QSpinBox*& value, + int default_, u16 max, Qt::Key shortcut_key, QWidget* shortcut_widget, bool invert) { const QKeySequence shortcut_key_sequence = QKeySequence(Qt::ALT + shortcut_key); @@ -171,6 +172,39 @@ QSpinBox* TASInputWindow::CreateSliderValuePair(QBoxLayout* layout, int default_ return value; } +// The shortcut_widget argument needs to specify the container widget that will be hidden/shown. +// This is done to avoid ambigous shortcuts +QDoubleSpinBox* TASInputWindow::CreateWeightSliderValuePair(QBoxLayout* layout, int min, int max, + QKeySequence shortcut_key_sequence, + QWidget* shortcut_widget) +{ + auto* value = new QDoubleSpinBox(); + value->setRange(min, max); + value->setDecimals(2); + value->setSuffix(QStringLiteral("kg")); + auto* slider = new QSlider(Qt::Orientation::Horizontal); + slider->setRange(min * 100, max * 100); + slider->setFocusPolicy(Qt::ClickFocus); + slider->setSingleStep(100); + slider->setPageStep(1000); + slider->setTickPosition(QSlider::TickPosition::TicksBelow); + + connect(slider, &QSlider::valueChanged, value, [value](int i) { value->setValue(i / 100.0); }); + connect(value, static_cast(&QDoubleSpinBox::valueChanged), + slider, [slider](double d) { slider->setValue((int)(d * 100)); }); + + auto* shortcut = new QShortcut(shortcut_key_sequence, shortcut_widget); + connect(shortcut, &QShortcut::activated, [value] { + value->setFocus(); + value->selectAll(); + }); + + layout->addWidget(slider); + layout->addWidget(value); + + return value; +} + template void TASInputWindow::GetButton(TASCheckBox* checkbox, UX& buttons, UX mask) { diff --git a/Source/Core/DolphinQt/TAS/TASInputWindow.h b/Source/Core/DolphinQt/TAS/TASInputWindow.h index d76da87d8195..3cc3ae1b7b26 100644 --- a/Source/Core/DolphinQt/TAS/TASInputWindow.h +++ b/Source/Core/DolphinQt/TAS/TASInputWindow.h @@ -11,7 +11,7 @@ struct GCPadStatus; class QBoxLayout; class QCheckBox; -class QDialog; +class QDoubleSpinBox; class QGroupBox; class QSpinBox; class QString; @@ -36,6 +36,10 @@ class TASInputWindow : public QDialog QSpinBox* CreateSliderValuePair(QBoxLayout* layout, int default_, u16 max, QKeySequence shortcut_key_sequence, Qt::Orientation orientation, QWidget* shortcut_widget, bool invert = false); + QDoubleSpinBox* CreateWeightSliderValuePair(QBoxLayout* layout, int min, int max, + QKeySequence shortcut_key_sequence, + QWidget* shortcut_widget); + template void GetButton(TASCheckBox* button, UX& pad, UX mask); void GetSpinBoxU8(QSpinBox* spin, u8& controller_value); diff --git a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp index 4f6ba2466e93..e0d50e79b695 100644 --- a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp +++ b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp @@ -92,50 +92,80 @@ WiiTASInputWindow::WiiTASInputWindow(QWidget* parent, int num) : TASInputWindow( CreateStickInputs(tr("Right Stick"), m_classic_right_stick_x_value, m_classic_right_stick_y_value, 31, 31, Qt::Key_Q, Qt::Key_W); - const QKeySequence balance_x_shortcut_key_sequence = QKeySequence(Qt::ALT + Qt::Key_X); - const QKeySequence balance_y_shortcut_key_sequence = QKeySequence(Qt::ALT + Qt::Key_Y); + const QKeySequence balance_tl_shortcut_key_sequence = QKeySequence(Qt::ALT + Qt::Key_L); + const QKeySequence balance_tr_shortcut_key_sequence = QKeySequence(Qt::ALT + Qt::Key_R); + const QKeySequence balance_bl_shortcut_key_sequence = + QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_L); + const QKeySequence balance_br_shortcut_key_sequence = + QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_R); const QKeySequence balance_weight_shortcut_key_sequence = QKeySequence(Qt::ALT + Qt::Key_W); m_balance_board_box = new QGroupBox( QStringLiteral("%1 (%2/%3/%4)") - .arg(tr("Balance"), balance_x_shortcut_key_sequence.toString(QKeySequence::NativeText), - balance_y_shortcut_key_sequence.toString(QKeySequence::NativeText), + .arg(tr("Balance"), balance_tl_shortcut_key_sequence.toString(QKeySequence::NativeText), + balance_tr_shortcut_key_sequence.toString(QKeySequence::NativeText), balance_weight_shortcut_key_sequence.toString(QKeySequence::NativeText))); - auto* bal_x_layout = new QHBoxLayout; - m_horizontal_balance_value = CreateSliderValuePair( - bal_x_layout, BalanceBoardWidget::balance_range / 2, BalanceBoardWidget::balance_range, - balance_x_shortcut_key_sequence, Qt::Horizontal, m_balance_board_box); + auto* bal_top_layout = new QHBoxLayout; + m_top_left_balance_value = CreateWeightSliderValuePair( + bal_top_layout, -34, 68, balance_tl_shortcut_key_sequence, m_balance_board_box); + m_top_right_balance_value = CreateWeightSliderValuePair( + bal_top_layout, -34, 68, balance_tr_shortcut_key_sequence, m_balance_board_box); - auto* bal_y_layout = new QVBoxLayout; - m_vertical_balance_value = CreateSliderValuePair( - bal_y_layout, BalanceBoardWidget::balance_range / 2, BalanceBoardWidget::balance_range, - balance_y_shortcut_key_sequence, Qt::Vertical, m_balance_board_box); - m_vertical_balance_value->setMaximumWidth(60); + auto* bal_bottom_layout = new QHBoxLayout; + m_bottom_left_balance_value = CreateWeightSliderValuePair( + bal_bottom_layout, -34, 68, balance_bl_shortcut_key_sequence, m_balance_board_box); + m_bottom_right_balance_value = CreateWeightSliderValuePair( + bal_bottom_layout, -34, 68, balance_br_shortcut_key_sequence, m_balance_board_box); auto* bal_weight_layout = new QHBoxLayout; - m_weight_total_value = - CreateSliderValuePair(bal_weight_layout, 63500, 150000, balance_weight_shortcut_key_sequence, - Qt::Horizontal, m_balance_board_box); + m_total_weight_value = CreateWeightSliderValuePair( + bal_weight_layout, 0, 136, balance_weight_shortcut_key_sequence, m_balance_board_box); auto* bal_visual = new BalanceBoardWidget(this); - connect(m_horizontal_balance_value, static_cast(&QSpinBox::valueChanged), - bal_visual, &BalanceBoardWidget::SetX); - connect(m_vertical_balance_value, static_cast(&QSpinBox::valueChanged), - bal_visual, &BalanceBoardWidget::SetY); - connect(bal_visual, &BalanceBoardWidget::ChangedX, m_horizontal_balance_value, - &QSpinBox::setValue); - connect(bal_visual, &BalanceBoardWidget::ChangedY, m_vertical_balance_value, &QSpinBox::setValue); + connect(m_top_right_balance_value, + static_cast(&QDoubleSpinBox::valueChanged), bal_visual, + &BalanceBoardWidget::SetTR); + connect(m_bottom_right_balance_value, + static_cast(&QDoubleSpinBox::valueChanged), bal_visual, + &BalanceBoardWidget::SetBR); + connect(m_top_left_balance_value, + static_cast(&QDoubleSpinBox::valueChanged), bal_visual, + &BalanceBoardWidget::SetTL); + connect(m_bottom_left_balance_value, + static_cast(&QDoubleSpinBox::valueChanged), bal_visual, + &BalanceBoardWidget::SetBL); + connect(bal_visual, &BalanceBoardWidget::ChangedTR, m_top_right_balance_value, + &QDoubleSpinBox::setValue); + connect(bal_visual, &BalanceBoardWidget::ChangedBR, m_bottom_right_balance_value, + &QDoubleSpinBox::setValue); + connect(bal_visual, &BalanceBoardWidget::ChangedTL, m_top_left_balance_value, + &QDoubleSpinBox::setValue); + connect(bal_visual, &BalanceBoardWidget::ChangedBL, m_bottom_left_balance_value, + &QDoubleSpinBox::setValue); + + constexpr double DEFAULT_WEIGHT = 63.5; + m_top_right_balance_value->setValue(DEFAULT_WEIGHT / 4); + m_bottom_right_balance_value->setValue(DEFAULT_WEIGHT / 4); + m_top_left_balance_value->setValue(DEFAULT_WEIGHT / 4); + m_bottom_left_balance_value->setValue(DEFAULT_WEIGHT / 4); + + connect(m_total_weight_value, + static_cast(&QDoubleSpinBox::valueChanged), bal_visual, + &BalanceBoardWidget::SetTotal); + connect(bal_visual, &BalanceBoardWidget::ChangedTotal, m_total_weight_value, + &QDoubleSpinBox::setValue); + m_total_weight_value->setValue(DEFAULT_WEIGHT); auto* bal_ar = new AspectRatioWidget(bal_visual, 20, 12); - + bal_ar->setMinimumHeight(120); auto* bal_visual_layout = new QHBoxLayout; bal_visual_layout->addWidget(bal_ar); - bal_visual_layout->addLayout(bal_y_layout); auto* bal_layout = new QVBoxLayout; - bal_layout->addLayout(bal_x_layout); + bal_layout->addLayout(bal_top_layout); bal_layout->addLayout(bal_visual_layout); + bal_layout->addLayout(bal_bottom_layout); bal_layout->addLayout(bal_weight_layout); m_balance_board_box->setLayout(bal_layout); @@ -576,29 +606,24 @@ void WiiTASInputWindow::GetValues(DataReportBuilder& rpt, WiimoteEmu::ExtensionN using WiimoteEmu::BalanceBoard; u8* const ext_data = rpt.GetExtDataPtr(); - // TODO: This code exists to read existing data, as well as to write TAS data; - // currently it is only reading... BalanceBoard::DataFormat bb_data = Common::BitCastPtr(ext_data); - int weight = m_weight_total_value->value(); - u16 horizontal = 500, vertical = 500; - GetSpinBoxU16(m_horizontal_balance_value, horizontal); - GetSpinBoxU16(m_vertical_balance_value, vertical); - const u16 top_right = - weight * (horizontal + vertical) / (4 * BalanceBoardWidget::balance_range); - const u16 bottom_right = weight * - (horizontal + (BalanceBoardWidget::balance_range - vertical)) / - (4 * BalanceBoardWidget::balance_range); - const u16 top_left = weight * ((BalanceBoardWidget::balance_range - horizontal) + vertical) / - (4 * BalanceBoardWidget::balance_range); - const u16 bottom_left = weight * - ((BalanceBoardWidget::balance_range - horizontal) + - (BalanceBoardWidget::balance_range - vertical)) / - (4 * BalanceBoardWidget::balance_range); - bb_data.top_right = Common::swap16(top_right); - bb_data.bottom_right = Common::swap16(bottom_right); - bb_data.top_left = Common::swap16(top_left); - bb_data.bottom_left = Common::swap16(bottom_left); + // TODO: Reading the existing values, but then just clobbering them instead of using them if + // controller input is enabled + double top_right = BalanceBoard::ConvertToKilograms(Common::swap16(bb_data.top_right)); + double bottom_right = BalanceBoard::ConvertToKilograms(Common::swap16(bb_data.bottom_right)); + double top_left = BalanceBoard::ConvertToKilograms(Common::swap16(bb_data.top_left)); + double bottom_left = BalanceBoard::ConvertToKilograms(Common::swap16(bb_data.bottom_left)); + + top_right = m_top_right_balance_value->value(); + bottom_right = m_bottom_right_balance_value->value(); + top_left = m_top_left_balance_value->value(); + bottom_left = m_bottom_left_balance_value->value(); + + bb_data.top_right = Common::swap16(BalanceBoard::ConvertToSensorWeight(top_right)); + bb_data.bottom_right = Common::swap16(BalanceBoard::ConvertToSensorWeight(bottom_right)); + bb_data.top_left = Common::swap16(BalanceBoard::ConvertToSensorWeight(top_left)); + bb_data.bottom_left = Common::swap16(BalanceBoard::ConvertToSensorWeight(bottom_left)); bb_data.temperature = BalanceBoard::TEMPERATURE; bb_data.battery = 0x83; diff --git a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h index a1254e8e2446..660a80d2d9e3 100644 --- a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h +++ b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h @@ -76,9 +76,11 @@ class WiiTASInputWindow : public TASInputWindow QSpinBox* m_classic_right_stick_y_value; QSpinBox* m_left_trigger_value; QSpinBox* m_right_trigger_value; - QSpinBox* m_weight_total_value; - QSpinBox* m_horizontal_balance_value; - QSpinBox* m_vertical_balance_value; + QDoubleSpinBox* m_total_weight_value; + QDoubleSpinBox* m_top_right_balance_value; + QDoubleSpinBox* m_bottom_right_balance_value; + QDoubleSpinBox* m_top_left_balance_value; + QDoubleSpinBox* m_bottom_left_balance_value; QGroupBox* m_remote_orientation_box; QGroupBox* m_nunchuk_orientation_box; QGroupBox* m_ir_box;