diff --git a/Source/Core/DolphinQt/QtUtils/AspectRatioWidget.cpp b/Source/Core/DolphinQt/QtUtils/AspectRatioWidget.cpp index 793e24d0ec..e607149563 100644 --- a/Source/Core/DolphinQt/QtUtils/AspectRatioWidget.cpp +++ b/Source/Core/DolphinQt/QtUtils/AspectRatioWidget.cpp @@ -13,6 +13,7 @@ AspectRatioWidget::AspectRatioWidget(QWidget* widget, float width, float height, : QWidget(parent), m_ar_width(width), m_ar_height(height) { m_layout = new QBoxLayout(QBoxLayout::LeftToRight, this); + m_layout->setContentsMargins(0, 0, 0, 0); // add spacer, then your widget, then spacer m_layout->addItem(new QSpacerItem(0, 0)); diff --git a/Source/Core/DolphinQt/Styles/Dark/dark.qss b/Source/Core/DolphinQt/Styles/Dark/dark.qss index 3e01577ec2..dbb380c878 100644 --- a/Source/Core/DolphinQt/Styles/Dark/dark.qss +++ b/Source/Core/DolphinQt/Styles/Dark/dark.qss @@ -383,7 +383,7 @@ QScrollBar::right-arrow:horizontal { QSpinBox, QDateEdit, QDateTimeEdit, QTimeEdit, QDoubleSpinBox { border: 1px solid #7e7e7e; - padding-right: 15px; + padding-right: 4px; } QSpinBox:disabled, QDateEdit:disabled, QDateTimeEdit:disabled, QTimeEdit:disabled, QDoubleSpinBox:disabled { background-color: #505050; diff --git a/Source/Core/DolphinQt/TAS/GBATASInputWindow.cpp b/Source/Core/DolphinQt/TAS/GBATASInputWindow.cpp index afc73a9f78..1e1ad2e3d2 100644 --- a/Source/Core/DolphinQt/TAS/GBATASInputWindow.cpp +++ b/Source/Core/DolphinQt/TAS/GBATASInputWindow.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "Core/HW/GBAPad.h" @@ -69,7 +70,10 @@ GBATASInputWindow::GBATASInputWindow(QWidget* parent, int controller_id) layout->addWidget(buttons_box); layout->addWidget(m_settings_box); - setLayout(layout); + SetupScrollArea(layout); + const QSize hint = m_scroll_widget->sizeHint(); + const int scrollbar_buffer = style()->pixelMetric(QStyle::PM_ScrollBarExtent) + 10; + resize(hint.width() + scrollbar_buffer, hint.height() + scrollbar_buffer); } void GBATASInputWindow::hideEvent(QHideEvent* event) diff --git a/Source/Core/DolphinQt/TAS/GCTASInputWindow.cpp b/Source/Core/DolphinQt/TAS/GCTASInputWindow.cpp index b544cf0fd2..11ef8c7afb 100644 --- a/Source/Core/DolphinQt/TAS/GCTASInputWindow.cpp +++ b/Source/Core/DolphinQt/TAS/GCTASInputWindow.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "Core/HW/GCPad.h" @@ -19,6 +20,8 @@ #include "InputCommon/ControllerEmu/ControllerEmu.h" #include "InputCommon/InputConfig.h" +#include "DolphinQt/QtUtils/AspectRatioWidget.h" + GCTASInputWindow::GCTASInputWindow(QWidget* parent, int controller_id) : TASInputWindow(parent), m_controller_id(controller_id) { @@ -30,8 +33,8 @@ GCTASInputWindow::GCTASInputWindow(QWidget* parent, int controller_id) 255, Qt::Key_H, Qt::Key_J); auto* top_layout = new QHBoxLayout; - top_layout->addWidget(m_main_stick_box); - top_layout->addWidget(m_c_stick_box); + top_layout->addWidget(new AspectRatioWidget(m_main_stick_box, 1, 1.02f)); + top_layout->addWidget(new AspectRatioWidget(m_c_stick_box, 1, 1.02f)); m_triggers_box = new QGroupBox(tr("Triggers")); @@ -100,7 +103,10 @@ GCTASInputWindow::GCTASInputWindow(QWidget* parent, int controller_id) layout->addWidget(m_buttons_box); layout->addWidget(m_settings_box); - setLayout(layout); + SetupScrollArea(layout); + const QSize hint = m_scroll_widget->sizeHint(); + const int scrollbar_buffer = style()->pixelMetric(QStyle::PM_ScrollBarExtent) + 10; + resize(hint.width() + scrollbar_buffer, hint.height() + scrollbar_buffer); } void GCTASInputWindow::hideEvent(QHideEvent* event) diff --git a/Source/Core/DolphinQt/TAS/IRWidget.cpp b/Source/Core/DolphinQt/TAS/IRWidget.cpp index e9f4033672..f0dd5f766c 100644 --- a/Source/Core/DolphinQt/TAS/IRWidget.cpp +++ b/Source/Core/DolphinQt/TAS/IRWidget.cpp @@ -20,7 +20,7 @@ IRWidget::IRWidget(QWidget* parent) : QWidget(parent) "Right click to re-center it.")); // If the widget gets too small, it will get deformed. - setMinimumSize(QSize(64, 48)); + setMinimumSize(QSize(128, 96)); } void IRWidget::SetX(u16 x) diff --git a/Source/Core/DolphinQt/TAS/StickWidget.cpp b/Source/Core/DolphinQt/TAS/StickWidget.cpp index fd43496930..85e6671df0 100644 --- a/Source/Core/DolphinQt/TAS/StickWidget.cpp +++ b/Source/Core/DolphinQt/TAS/StickWidget.cpp @@ -21,7 +21,7 @@ StickWidget::StickWidget(QWidget* parent, u16 max_x, u16 max_y) "Right click to re-center it.")); // If the widget gets too small, it will get deformed. - setMinimumSize(QSize(64, 64)); + setMinimumSize(QSize(128, 128)); } void StickWidget::SetX(u16 x) diff --git a/Source/Core/DolphinQt/TAS/TASInputWindow.cpp b/Source/Core/DolphinQt/TAS/TASInputWindow.cpp index 8c2318f1e9..7b2cff94a0 100644 --- a/Source/Core/DolphinQt/TAS/TASInputWindow.cpp +++ b/Source/Core/DolphinQt/TAS/TASInputWindow.cpp @@ -9,13 +9,13 @@ #include #include #include +#include #include -#include #include +#include #include #include #include -#include #include "DolphinQt/Host.h" #include "DolphinQt/QtUtils/AspectRatioWidget.h" @@ -108,14 +108,12 @@ QGroupBox* TASInputWindow::CreateStickInputs(const QString& text, std::string_vi const int x_default = static_cast(std::round(max_x / 2.)); const int y_default = static_cast(std::round(max_y / 2.)); - auto* x_layout = new QHBoxLayout; - TASSpinBox* x_value = CreateSliderValuePair(x_layout, x_default, max_x, x_shortcut_key_sequence, + auto* box_layout = new QGridLayout; + TASSpinBox* x_value = CreateSliderValuePair(box_layout, x_default, max_x, x_shortcut_key_sequence, Qt::Horizontal, box); - auto* y_layout = new QVBoxLayout; - TASSpinBox* y_value = - CreateSliderValuePair(y_layout, y_default, max_y, y_shortcut_key_sequence, Qt::Vertical, box); - y_value->setMaximumWidth(60); + TASSpinBox* y_value = CreateSliderValuePair(box_layout, y_default, max_y, y_shortcut_key_sequence, + Qt::Vertical, box); auto* visual = new StickWidget(this, max_x, max_y); visual->SetX(x_default); @@ -128,14 +126,10 @@ QGroupBox* TASInputWindow::CreateStickInputs(const QString& text, std::string_vi 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); + // This is done to prevent the stick widget from stretching + box_layout->addItem(new QSpacerItem(0, 0), 2, 1); + box_layout->addWidget(visual_ar, 1, 1); + box->setLayout(box_layout); overrider->AddFunction(group_name, ControllerEmu::ReshapableInput::X_INPUT_OVERRIDE, [this, x_value, x_default, min_x, max_x](ControlState controller_state) { @@ -150,7 +144,7 @@ QGroupBox* TASInputWindow::CreateStickInputs(const QString& text, std::string_vi return box; } -QBoxLayout* TASInputWindow::CreateSliderValuePairLayout( +QGridLayout* TASInputWindow::CreateSliderValuePairLayout( const QString& text, std::string_view group_name, std::string_view control_name, InputOverrider* overrider, int zero, int default_, int min, int max, Qt::Key shortcut_key, QWidget* shortcut_widget, std::optional scale) @@ -160,8 +154,8 @@ QBoxLayout* TASInputWindow::CreateSliderValuePairLayout( auto* label = new QLabel(QStringLiteral("%1 (%2)").arg( text, shortcut_key_sequence.toString(QKeySequence::NativeText))); - QBoxLayout* layout = new QHBoxLayout; - layout->addWidget(label); + QGridLayout* layout = new QGridLayout; + layout->addWidget(label, 0, 0); CreateSliderValuePair(group_name, control_name, overrider, layout, zero, default_, min, max, shortcut_key_sequence, Qt::Horizontal, shortcut_widget, scale); @@ -171,7 +165,7 @@ QBoxLayout* TASInputWindow::CreateSliderValuePairLayout( TASSpinBox* TASInputWindow::CreateSliderValuePair( std::string_view group_name, std::string_view control_name, InputOverrider* overrider, - QBoxLayout* layout, int zero, int default_, int min, int max, + QGridLayout* layout, int zero, int default_, int min, int max, QKeySequence shortcut_key_sequence, Qt::Orientation orientation, QWidget* shortcut_widget, std::optional scale) { @@ -199,23 +193,22 @@ TASSpinBox* TASInputWindow::CreateSliderValuePair( // The shortcut_widget argument needs to specify the container widget that will be hidden/shown. // This is done to avoid ambiguous shortcuts -TASSpinBox* TASInputWindow::CreateSliderValuePair(QBoxLayout* layout, int default_, int max, +TASSpinBox* TASInputWindow::CreateSliderValuePair(QGridLayout* layout, int default_, int max, QKeySequence shortcut_key_sequence, Qt::Orientation orientation, QWidget* shortcut_widget) { auto* value = new TASSpinBox(); - value->setRange(0, 99999); + value->setRange(0, max); value->setValue(default_); - connect(value, &QSpinBox::valueChanged, [value, max](int i) { - if (i > max) - value->setValue(max); - }); + auto* slider = new TASSlider(default_, orientation); slider->setRange(0, max); slider->setValue(default_); slider->setFocusPolicy(Qt::ClickFocus); + value->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + connect(slider, &QSlider::valueChanged, value, &QSpinBox::setValue); connect(value, &QSpinBox::valueChanged, slider, &QSlider::setValue); @@ -225,14 +218,45 @@ TASSpinBox* TASInputWindow::CreateSliderValuePair(QBoxLayout* layout, int defaul value->selectAll(); }); - layout->addWidget(slider); - layout->addWidget(value); if (orientation == Qt::Vertical) - layout->setAlignment(slider, Qt::AlignRight); + { + layout->addWidget(slider, 1, 2); + layout->addWidget(value, 2, 2); + + layout->setAlignment(slider, Qt::AlignHCenter); + slider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); + } + else + { + layout->addWidget(slider, 0, 1); + layout->addWidget(value, 0, 2); + + slider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + } return value; } +void TASInputWindow::SetupScrollArea(QLayout* layout) +{ + m_scroll_widget = new QWidget; + m_scroll_widget->setLayout(layout); + + auto* scroll_area = new QScrollArea; + scroll_area->setWidget(m_scroll_widget); + scroll_area->setWidgetResizable(true); + scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + + auto* outer_layout = new QVBoxLayout; + outer_layout->setContentsMargins(0, 0, 0, 0); + outer_layout->addWidget(scroll_area); + setLayout(outer_layout); + + layout->activate(); + m_scroll_widget->layout()->activate(); +} + std::optional TASInputWindow::GetButton(TASCheckBox* checkbox, ControlState controller_state) { diff --git a/Source/Core/DolphinQt/TAS/TASInputWindow.h b/Source/Core/DolphinQt/TAS/TASInputWindow.h index 924e53ac87..0ae14a22fc 100644 --- a/Source/Core/DolphinQt/TAS/TASInputWindow.h +++ b/Source/Core/DolphinQt/TAS/TASInputWindow.h @@ -15,13 +15,15 @@ #include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" #include "InputCommon/ControllerInterface/CoreDevice.h" -class QBoxLayout; class QCheckBox; class QDialog; class QEvent; +class QGridLayout; class QGroupBox; +class QLayout; class QSpinBox; class QString; +class QWidget; class TASCheckBox; class TASSpinBox; @@ -54,23 +56,26 @@ protected: QGroupBox* CreateStickInputs(const QString& text, std::string_view group_name, InputOverrider* overrider, int min_x, int min_y, int max_x, int max_y, Qt::Key x_shortcut_key, Qt::Key y_shortcut_key); - QBoxLayout* CreateSliderValuePairLayout(const QString& text, std::string_view group_name, - std::string_view control_name, InputOverrider* overrider, - int zero, int default_, int min, int max, - Qt::Key shortcut_key, QWidget* shortcut_widget, - std::optional scale = {}); + QGridLayout* CreateSliderValuePairLayout(const QString& text, std::string_view group_name, + std::string_view control_name, InputOverrider* overrider, + int zero, int default_, int min, int max, + Qt::Key shortcut_key, QWidget* shortcut_widget, + std::optional scale = {}); TASSpinBox* CreateSliderValuePair(std::string_view group_name, std::string_view control_name, - InputOverrider* overrider, QBoxLayout* layout, int zero, + InputOverrider* overrider, QGridLayout* layout, int zero, int default_, int min, int max, QKeySequence shortcut_key_sequence, Qt::Orientation orientation, QWidget* shortcut_widget, std::optional scale = {}); - TASSpinBox* CreateSliderValuePair(QBoxLayout* layout, int default_, int max, + TASSpinBox* CreateSliderValuePair(QGridLayout* layout, int default_, int max, QKeySequence shortcut_key_sequence, Qt::Orientation orientation, QWidget* shortcut_widget); + void SetupScrollArea(QLayout* layout); + void changeEvent(QEvent* event) override; + QWidget* m_scroll_widget; QGroupBox* m_settings_box; QCheckBox* m_use_controller; QSpinBox* m_turbo_press_frames; diff --git a/Source/Core/DolphinQt/TAS/TASSpinBox.cpp b/Source/Core/DolphinQt/TAS/TASSpinBox.cpp index b1c4eeb660..33e3541d41 100644 --- a/Source/Core/DolphinQt/TAS/TASSpinBox.cpp +++ b/Source/Core/DolphinQt/TAS/TASSpinBox.cpp @@ -30,3 +30,31 @@ void TASSpinBox::ApplyControllerValueChange() { setValue(m_state.ApplyControllerValueChange()); } + +QValidator::State TASSpinBox::validate(QString& input, int& pos) const +{ + auto state = QSpinBox::validate(input, pos); + if (state == QValidator::Invalid) + { + bool ok; + input.toInt(&ok); + if (ok) + return QValidator::Intermediate; + } + return state; +} + +void TASSpinBox::fixup(QString& input) const +{ + bool ok; + int val = input.toInt(&ok); + if (ok) + { + if (val > maximum()) + input = QString::number(maximum()); + else if (val < minimum()) + input = QString::number(minimum()); + return; + } + QSpinBox::fixup(input); +} diff --git a/Source/Core/DolphinQt/TAS/TASSpinBox.h b/Source/Core/DolphinQt/TAS/TASSpinBox.h index 55908911d7..25e661c7ab 100644 --- a/Source/Core/DolphinQt/TAS/TASSpinBox.h +++ b/Source/Core/DolphinQt/TAS/TASSpinBox.h @@ -19,6 +19,8 @@ public: int GetValue() const; // Must be called from the CPU thread void OnControllerValueChanged(int new_value); + QValidator::State validate(QString& input, int& pos) const override; + void fixup(QString& input) const override; private slots: void OnUIValueChanged(int new_value); diff --git a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp index c00c6d0206..48a55dbef8 100644 --- a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp +++ b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "Common/CommonTypes.h" @@ -44,25 +45,24 @@ WiiTASInputWindow::WiiTASInputWindow(QWidget* parent, int num) : TASInputWindow( const QKeySequence ir_x_shortcut_key_sequence = QKeySequence(Qt::ALT | Qt::Key_X); const QKeySequence ir_y_shortcut_key_sequence = QKeySequence(Qt::ALT | Qt::Key_C); - m_ir_box = new QGroupBox(QStringLiteral("%1 (%2/%3)") - .arg(tr("IR"), - ir_x_shortcut_key_sequence.toString(QKeySequence::NativeText), - ir_y_shortcut_key_sequence.toString(QKeySequence::NativeText))); + auto* ir_box = new QGroupBox( + QStringLiteral("%1 (%2/%3)") + .arg(tr("IR"), ir_x_shortcut_key_sequence.toString(QKeySequence::NativeText), + ir_y_shortcut_key_sequence.toString(QKeySequence::NativeText))); const int ir_x_center = static_cast(std::round(IRWidget::IR_MAX_X / 2.)); const int ir_y_center = static_cast(std::round(IRWidget::IR_MAX_Y / 2.)); - auto* x_layout = new QHBoxLayout; + auto* box_layout = new QGridLayout; m_ir_x_value = CreateSliderValuePair( WiimoteEmu::Wiimote::IR_GROUP, ControllerEmu::ReshapableInput::X_INPUT_OVERRIDE, - &m_wiimote_overrider, x_layout, ir_x_center, ir_x_center, IRWidget::IR_MIN_X, - IRWidget::IR_MAX_X, ir_x_shortcut_key_sequence, Qt::Horizontal, m_ir_box); + &m_wiimote_overrider, box_layout, ir_x_center, ir_x_center, IRWidget::IR_MIN_X, + IRWidget::IR_MAX_X, ir_x_shortcut_key_sequence, Qt::Horizontal, ir_box); - auto* y_layout = new QVBoxLayout; m_ir_y_value = CreateSliderValuePair( WiimoteEmu::Wiimote::IR_GROUP, ControllerEmu::ReshapableInput::Y_INPUT_OVERRIDE, - &m_wiimote_overrider, y_layout, ir_y_center, ir_y_center, IRWidget::IR_MIN_Y, - IRWidget::IR_MAX_Y, ir_y_shortcut_key_sequence, Qt::Vertical, m_ir_box); + &m_wiimote_overrider, box_layout, ir_y_center, ir_y_center, IRWidget::IR_MIN_Y, + IRWidget::IR_MAX_Y, ir_y_shortcut_key_sequence, Qt::Vertical, ir_box); m_ir_y_value->setMaximumWidth(60); auto* visual = new IRWidget(this); @@ -76,31 +76,27 @@ WiiTASInputWindow::WiiTASInputWindow(QWidget* parent, int num) : TASInputWindow( auto* visual_ar = new AspectRatioWidget(visual, IRWidget::IR_MAX_X, IRWidget::IR_MAX_Y); - auto* visual_layout = new QHBoxLayout; - visual_layout->addWidget(visual_ar); - visual_layout->addLayout(y_layout); + // This is done to prevent the stick widget from stretching + box_layout->addItem(new QSpacerItem(0, 0), 2, 1); + box_layout->addWidget(visual_ar, 1, 1); + ir_box->setLayout(box_layout); - auto* ir_layout = new QVBoxLayout; - ir_layout->addLayout(x_layout); - ir_layout->addLayout(visual_layout); - m_ir_box->setLayout(ir_layout); + m_ir_box = new AspectRatioWidget(ir_box, 1, 1.02f); - m_nunchuk_stick_box = + m_nunchuk_stick_box = new AspectRatioWidget( CreateStickInputs(tr("Nunchuk Stick"), WiimoteEmu::Nunchuk::STICK_GROUP, &m_nunchuk_overrider, - 0, 0, 255, 255, Qt::Key_F, Qt::Key_G); + 0, 0, 255, 255, Qt::Key_F, Qt::Key_G), + 1, 1.02f); - m_classic_left_stick_box = + m_classic_left_stick_box = new AspectRatioWidget( CreateStickInputs(tr("Left Stick"), WiimoteEmu::Classic::LEFT_STICK_GROUP, - &m_classic_overrider, 0, 0, 63, 63, Qt::Key_F, Qt::Key_G); + &m_classic_overrider, 0, 0, 63, 63, Qt::Key_F, Qt::Key_G), + 1, 1.02f); - m_classic_right_stick_box = + m_classic_right_stick_box = new AspectRatioWidget( CreateStickInputs(tr("Right Stick"), WiimoteEmu::Classic::RIGHT_STICK_GROUP, - &m_classic_overrider, 0, 0, 31, 31, Qt::Key_Q, Qt::Key_W); - - // Need to enforce the same minimum width because otherwise the different lengths in the labels - // used on the QGroupBox will cause the StickWidgets to have different sizes. - m_ir_box->setMinimumWidth(20); - m_nunchuk_stick_box->setMinimumWidth(20); + &m_classic_overrider, 0, 0, 31, 31, Qt::Key_Q, Qt::Key_W), + 1, 1.02f); auto* top_layout = new QHBoxLayout; top_layout->addWidget(m_ir_box); @@ -344,7 +340,7 @@ WiiTASInputWindow::WiiTASInputWindow(QWidget* parent, int num) : TASInputWindow( layout->addWidget(m_classic_buttons_box); layout->addWidget(m_settings_box); - setLayout(layout); + SetupScrollArea(layout); } WiimoteEmu::Wiimote* WiiTASInputWindow::GetWiimote() @@ -478,8 +474,10 @@ void WiiTASInputWindow::UpdateControlVisibility() // Without these calls, switching between attachments can result in the Stick/IRWidgets being // surrounded by large amounts of empty space in one dimension. - adjustSize(); - resize(sizeHint()); + m_scroll_widget->layout()->activate(); + const QSize hint = m_scroll_widget->sizeHint(); + const int scrollbar_buffer = style()->pixelMetric(QStyle::PM_ScrollBarExtent) + 10; + resize(hint.width() + scrollbar_buffer, hint.height() + scrollbar_buffer); } void WiiTASInputWindow::hideEvent(QHideEvent* const event) diff --git a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h index a7a413e864..25e55eb1fa 100644 --- a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h +++ b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h @@ -3,6 +3,7 @@ #pragma once +#include "DolphinQt/QtUtils/AspectRatioWidget.h" #include "DolphinQt/TAS/TASInputWindow.h" #include "Core/HW/WiimoteEmu/ExtensionPort.h" @@ -89,12 +90,12 @@ private: QGroupBox* m_remote_accelerometer_box; QGroupBox* m_remote_gyroscope_box; QGroupBox* m_nunchuk_accelerometer_box; - QGroupBox* m_ir_box; - QGroupBox* m_nunchuk_stick_box; - QGroupBox* m_classic_left_stick_box; - QGroupBox* m_classic_right_stick_box; QGroupBox* m_remote_buttons_box; QGroupBox* m_nunchuk_buttons_box; QGroupBox* m_classic_buttons_box; QGroupBox* m_triggers_box; + AspectRatioWidget* m_ir_box; + AspectRatioWidget* m_nunchuk_stick_box; + AspectRatioWidget* m_classic_left_stick_box; + AspectRatioWidget* m_classic_right_stick_box; };