Skip to content

Commit

Permalink
Redo balance board TAS input
Browse files Browse the repository at this point in the history
  • Loading branch information
Pokechu22 committed Oct 27, 2019
1 parent a723fa1 commit a02c184
Show file tree
Hide file tree
Showing 6 changed files with 211 additions and 80 deletions.
95 changes: 78 additions & 17 deletions Source/Core/DolphinQt/TAS/BalanceBoardWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand All @@ -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);

Expand All @@ -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<int>(balance_range), new_x));
m_y = std::max(0, std::min(static_cast<int>(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();
}
25 changes: 17 additions & 8 deletions Source/Core/DolphinQt/TAS/BalanceBoardWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -31,7 +35,12 @@ 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;
};
34 changes: 34 additions & 0 deletions Source/Core/DolphinQt/TAS/TASInputWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <cmath>

#include <QCheckBox>
#include <QDoubleSpinBox>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QLabel>
Expand Down Expand Up @@ -130,6 +131,39 @@ QSpinBox* TASInputWindow::CreateSliderValuePair(QBoxLayout* layout, u16 max,
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<void (QDoubleSpinBox::*)(double)>(&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 <typename UX>
void TASInputWindow::GetButton(TASCheckBox* checkbox, UX& buttons, UX mask)
{
Expand Down
6 changes: 5 additions & 1 deletion Source/Core/DolphinQt/TAS/TASInputWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
struct GCPadStatus;
class QBoxLayout;
class QCheckBox;
class QDialog;
class QDoubleSpinBox;
class QGroupBox;
class QSpinBox;
class QString;
Expand All @@ -32,6 +32,10 @@ class TASInputWindow : public QDialog
QSpinBox* CreateSliderValuePair(QBoxLayout* layout, 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 <typename UX>
void GetButton(TASCheckBox* button, UX& pad, UX mask);
void GetSpinBoxU8(QSpinBox* spin, u8& controller_value);
Expand Down
123 changes: 72 additions & 51 deletions Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,54 +91,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,
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,
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, 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<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
bal_visual, &BalanceBoardWidget::SetX);
connect(m_vertical_balance_value, static_cast<void (QSpinBox::*)(int)>(&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);

m_horizontal_balance_value->setValue(BalanceBoardWidget::balance_range / 2);
m_vertical_balance_value->setValue(BalanceBoardWidget::balance_range / 2);
m_weight_total_value->setValue(63500);
connect(m_top_right_balance_value,
static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), bal_visual,
&BalanceBoardWidget::SetTR);
connect(m_bottom_right_balance_value,
static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), bal_visual,
&BalanceBoardWidget::SetBR);
connect(m_top_left_balance_value,
static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), bal_visual,
&BalanceBoardWidget::SetTL);
connect(m_bottom_left_balance_value,
static_cast<void (QDoubleSpinBox::*)(double)>(&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<void (QDoubleSpinBox::*)(double)>(&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);

Expand Down Expand Up @@ -604,29 +630,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<BalanceBoard::DataFormat>(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;

Expand Down
Loading

0 comments on commit a02c184

Please sign in to comment.