diff options
Diffstat (limited to 'Source/Core/DolphinQt/TAS/TASInputWindow.cpp')
| -rw-r--r-- | Source/Core/DolphinQt/TAS/TASInputWindow.cpp | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/Source/Core/DolphinQt/TAS/TASInputWindow.cpp b/Source/Core/DolphinQt/TAS/TASInputWindow.cpp new file mode 100644 index 0000000000..e87f358889 --- /dev/null +++ b/Source/Core/DolphinQt/TAS/TASInputWindow.cpp @@ -0,0 +1,192 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include <cmath> + +#include <QCheckBox> +#include <QGroupBox> +#include <QHBoxLayout> +#include <QLabel> +#include <QShortcut> +#include <QSlider> +#include <QSpinBox> +#include <QVBoxLayout> + +#include "Common/CommonTypes.h" + +#include "DolphinQt/QtUtils/AspectRatioWidget.h" +#include "DolphinQt/QtUtils/QueueOnObject.h" +#include "DolphinQt/TAS/StickWidget.h" +#include "DolphinQt/TAS/TASInputWindow.h" + +#include "InputCommon/GCPadStatus.h" + +TASInputWindow::TASInputWindow(QWidget* parent) : QDialog(parent) +{ + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + m_use_controller = new QCheckBox(QStringLiteral("Enable Controller Inpu&t")); + m_use_controller->setToolTip(tr("Warning: Analog inputs may reset to controller values at " + "random. In some cases this can be fixed by adding a deadzone.")); +} + +QGroupBox* TASInputWindow::CreateStickInputs(QString name, QSpinBox*& x_value, QSpinBox*& y_value, + u16 max_x, u16 max_y, Qt::Key x_shortcut_key, + Qt::Key y_shortcut_key) +{ + const QKeySequence x_shortcut_key_sequence = QKeySequence(Qt::ALT + x_shortcut_key); + const QKeySequence y_shortcut_key_sequence = QKeySequence(Qt::ALT + y_shortcut_key); + + auto* box = + new QGroupBox(QStringLiteral("%1 (%2/%3)") + .arg(name, x_shortcut_key_sequence.toString(QKeySequence::NativeText), + y_shortcut_key_sequence.toString(QKeySequence::NativeText))); + + auto* x_layout = new QHBoxLayout; + x_value = CreateSliderValuePair(x_layout, max_x, x_shortcut_key_sequence, Qt::Horizontal, box); + + auto* y_layout = new QVBoxLayout; + y_value = CreateSliderValuePair(y_layout, max_y, y_shortcut_key_sequence, Qt::Vertical, box); + y_value->setMaximumWidth(60); + + auto* visual = new StickWidget(this, max_x, max_y); + connect(x_value, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), visual, + &StickWidget::SetX); + connect(y_value, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), visual, + &StickWidget::SetY); + connect(visual, &StickWidget::ChangedX, x_value, &QSpinBox::setValue); + connect(visual, &StickWidget::ChangedY, y_value, &QSpinBox::setValue); + + x_value->setValue(static_cast<int>(std::round(max_x / 2.))); + y_value->setValue(static_cast<int>(std::round(max_y / 2.))); + + auto* visual_ar = new AspectRatioWidget(visual, max_x, max_y); + + auto* visual_layout = new QHBoxLayout; + visual_layout->addWidget(visual_ar); + visual_layout->addLayout(y_layout); + + auto* layout = new QVBoxLayout; + layout->addLayout(x_layout); + layout->addLayout(visual_layout); + box->setLayout(layout); + + return box; +} + +QBoxLayout* TASInputWindow::CreateSliderValuePairLayout(QString name, QSpinBox*& value, u16 max, + Qt::Key shortcut_key, + QWidget* shortcut_widget, bool invert) +{ + const QKeySequence shortcut_key_sequence = QKeySequence(Qt::ALT + shortcut_key); + + auto* label = new QLabel(QStringLiteral("%1 (%2)").arg( + name, shortcut_key_sequence.toString(QKeySequence::NativeText))); + + QBoxLayout* layout = new QHBoxLayout; + layout->addWidget(label); + + value = CreateSliderValuePair(layout, max, shortcut_key_sequence, Qt::Horizontal, shortcut_widget, + invert); + + return layout; +} + +// The shortcut_widget argument needs to specify the container widget that will be hidden/shown. +// This is done to avoid ambigous shortcuts +QSpinBox* TASInputWindow::CreateSliderValuePair(QBoxLayout* layout, u16 max, + QKeySequence shortcut_key_sequence, + Qt::Orientation orientation, + QWidget* shortcut_widget, bool invert) +{ + auto* value = new QSpinBox(); + value->setRange(0, 99999); + connect(value, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), + [value, max](int i) { + if (i > max) + value->setValue(max); + }); + auto* slider = new QSlider(orientation); + slider->setRange(0, max); + slider->setFocusPolicy(Qt::ClickFocus); + slider->setInvertedAppearance(invert); + + connect(slider, &QSlider::valueChanged, value, &QSpinBox::setValue); + connect(value, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), slider, + &QSlider::setValue); + + auto* shortcut = new QShortcut(shortcut_key_sequence, shortcut_widget); + connect(shortcut, &QShortcut::activated, [value] { + value->setFocus(); + value->selectAll(); + }); + + layout->addWidget(slider); + layout->addWidget(value); + if (orientation == Qt::Vertical) + layout->setAlignment(slider, Qt::AlignRight); + + return value; +} + +template <typename UX> +void TASInputWindow::GetButton(QCheckBox* checkbox, UX& buttons, UX mask) +{ + const bool pressed = (buttons & mask) != 0; + if (m_use_controller->isChecked()) + { + if (pressed) + { + m_checkbox_set_by_controller[checkbox] = true; + QueueOnObject(checkbox, [checkbox] { checkbox->setChecked(true); }); + } + else if (m_checkbox_set_by_controller.count(checkbox) && m_checkbox_set_by_controller[checkbox]) + { + m_checkbox_set_by_controller[checkbox] = false; + QueueOnObject(checkbox, [checkbox] { checkbox->setChecked(false); }); + } + } + + if (checkbox->isChecked()) + buttons |= mask; + else + buttons &= ~mask; +} +template void TASInputWindow::GetButton<u8>(QCheckBox* button, u8& pad, u8 mask); +template void TASInputWindow::GetButton<u16>(QCheckBox* button, u16& pad, u16 mask); + +void TASInputWindow::GetSpinBoxU8(QSpinBox* spin, u8& controller_value) +{ + if (m_use_controller->isChecked()) + { + if (!m_spinbox_most_recent_values_u8.count(spin) || + m_spinbox_most_recent_values_u8[spin] != controller_value) + QueueOnObject(spin, [spin, controller_value] { spin->setValue(controller_value); }); + + m_spinbox_most_recent_values_u8[spin] = controller_value; + } + else + { + m_spinbox_most_recent_values_u8.clear(); + } + + controller_value = spin->value(); +} + +void TASInputWindow::GetSpinBoxU16(QSpinBox* spin, u16& controller_value) +{ + if (m_use_controller->isChecked()) + { + if (!m_spinbox_most_recent_values_u16.count(spin) || + m_spinbox_most_recent_values_u16[spin] != controller_value) + QueueOnObject(spin, [spin, controller_value] { spin->setValue(controller_value); }); + + m_spinbox_most_recent_values_u16[spin] = controller_value; + } + else + { + m_spinbox_most_recent_values_u16.clear(); + } + + controller_value = spin->value(); +} |
