mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-04 03:46:42 +01:00
Merge pull request #10682 from jordan-woyak/gate-size-setting
ControllerEmu: Allow changing the target gate radius of octagon sticks.
This commit is contained in:
commit
e8965c63e4
@ -4,6 +4,7 @@
|
|||||||
#include "DolphinQt/Config/Mapping/MappingWidget.h"
|
#include "DolphinQt/Config/Mapping/MappingWidget.h"
|
||||||
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
|
#include <QDialogButtonBox>
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
@ -121,8 +122,54 @@ QGroupBox* MappingWidget::CreateGroupBox(const QString& name, ControllerEmu::Con
|
|||||||
for (auto& control : group->controls)
|
for (auto& control : group->controls)
|
||||||
CreateControl(control.get(), form_layout, !indicator);
|
CreateControl(control.get(), form_layout, !indicator);
|
||||||
|
|
||||||
|
AddSettingWidgets(form_layout, group, ControllerEmu::SettingVisibility::Normal);
|
||||||
|
|
||||||
|
if (group->default_value != ControllerEmu::ControlGroup::DefaultValue::AlwaysEnabled)
|
||||||
|
{
|
||||||
|
QLabel* group_enable_label = new QLabel(tr("Enable"));
|
||||||
|
QCheckBox* group_enable_checkbox = new QCheckBox();
|
||||||
|
group_enable_checkbox->setChecked(group->enabled);
|
||||||
|
form_layout->insertRow(0, group_enable_label, group_enable_checkbox);
|
||||||
|
auto enable_group_by_checkbox = [group, form_layout, group_enable_label,
|
||||||
|
group_enable_checkbox] {
|
||||||
|
group->enabled = group_enable_checkbox->isChecked();
|
||||||
|
for (int i = 0; i < form_layout->count(); ++i)
|
||||||
|
{
|
||||||
|
QWidget* widget = form_layout->itemAt(i)->widget();
|
||||||
|
if (widget != nullptr && widget != group_enable_label && widget != group_enable_checkbox)
|
||||||
|
widget->setEnabled(group->enabled);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
enable_group_by_checkbox();
|
||||||
|
connect(group_enable_checkbox, &QCheckBox::toggled, this, enable_group_by_checkbox);
|
||||||
|
connect(this, &MappingWidget::ConfigChanged, this,
|
||||||
|
[group_enable_checkbox, group] { group_enable_checkbox->setChecked(group->enabled); });
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto advanced_setting_count = std::count_if(
|
||||||
|
group->numeric_settings.begin(), group->numeric_settings.end(), [](auto& setting) {
|
||||||
|
return setting->GetVisibility() == ControllerEmu::SettingVisibility::Advanced;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (advanced_setting_count != 0)
|
||||||
|
{
|
||||||
|
const auto advanced_button = new QPushButton(tr("Advanced"));
|
||||||
|
form_layout->addRow(advanced_button);
|
||||||
|
connect(advanced_button, &QPushButton::clicked,
|
||||||
|
[this, group] { ShowAdvancedControlGroupDialog(group); });
|
||||||
|
}
|
||||||
|
|
||||||
|
return group_box;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MappingWidget::AddSettingWidgets(QFormLayout* layout, ControllerEmu::ControlGroup* group,
|
||||||
|
ControllerEmu::SettingVisibility visibility)
|
||||||
|
{
|
||||||
for (auto& setting : group->numeric_settings)
|
for (auto& setting : group->numeric_settings)
|
||||||
{
|
{
|
||||||
|
if (setting->GetVisibility() != visibility)
|
||||||
|
continue;
|
||||||
|
|
||||||
QWidget* setting_widget = nullptr;
|
QWidget* setting_widget = nullptr;
|
||||||
|
|
||||||
switch (setting->GetType())
|
switch (setting->GetType())
|
||||||
@ -149,33 +196,59 @@ QGroupBox* MappingWidget::CreateGroupBox(const QString& name, ControllerEmu::Con
|
|||||||
hbox->addWidget(setting_widget);
|
hbox->addWidget(setting_widget);
|
||||||
hbox->addWidget(CreateSettingAdvancedMappingButton(*setting));
|
hbox->addWidget(CreateSettingAdvancedMappingButton(*setting));
|
||||||
|
|
||||||
form_layout->addRow(tr(setting->GetUIName()), hbox);
|
layout->addRow(tr(setting->GetUIName()), hbox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (group->default_value != ControllerEmu::ControlGroup::DefaultValue::AlwaysEnabled)
|
void MappingWidget::ShowAdvancedControlGroupDialog(ControllerEmu::ControlGroup* group)
|
||||||
{
|
{
|
||||||
QLabel* group_enable_label = new QLabel(tr("Enable"));
|
QDialog dialog{this};
|
||||||
QCheckBox* group_enable_checkbox = new QCheckBox();
|
dialog.setWindowTitle(tr(group->ui_name.c_str()));
|
||||||
group_enable_checkbox->setChecked(group->enabled);
|
|
||||||
form_layout->insertRow(0, group_enable_label, group_enable_checkbox);
|
|
||||||
auto enable_group_by_checkbox = [group, form_layout, group_enable_label,
|
|
||||||
group_enable_checkbox] {
|
|
||||||
group->enabled = group_enable_checkbox->isChecked();
|
|
||||||
for (int i = 0; i < form_layout->count(); ++i)
|
|
||||||
{
|
|
||||||
QWidget* widget = form_layout->itemAt(i)->widget();
|
|
||||||
if (widget != nullptr && widget != group_enable_label && widget != group_enable_checkbox)
|
|
||||||
widget->setEnabled(group->enabled);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
enable_group_by_checkbox();
|
|
||||||
connect(group_enable_checkbox, &QCheckBox::toggled, this, enable_group_by_checkbox);
|
|
||||||
connect(this, &MappingWidget::ConfigChanged, this,
|
|
||||||
[group_enable_checkbox, group] { group_enable_checkbox->setChecked(group->enabled); });
|
|
||||||
}
|
|
||||||
|
|
||||||
return group_box;
|
const auto group_box = new QGroupBox(tr("Advanced Settings"));
|
||||||
|
|
||||||
|
QFormLayout* form_layout = new QFormLayout();
|
||||||
|
|
||||||
|
AddSettingWidgets(form_layout, group, ControllerEmu::SettingVisibility::Advanced);
|
||||||
|
|
||||||
|
const auto reset_button = new QPushButton(tr("Reset All"));
|
||||||
|
form_layout->addRow(reset_button);
|
||||||
|
|
||||||
|
connect(reset_button, &QPushButton::clicked, [this, group] {
|
||||||
|
for (auto& setting : group->numeric_settings)
|
||||||
|
{
|
||||||
|
if (setting->GetVisibility() != ControllerEmu::SettingVisibility::Advanced)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
setting->SetToDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
emit ConfigChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
const auto main_layout = new QVBoxLayout();
|
||||||
|
const auto button_box = new QDialogButtonBox(QDialogButtonBox::Close);
|
||||||
|
|
||||||
|
group_box->setLayout(form_layout);
|
||||||
|
|
||||||
|
main_layout->addWidget(group_box);
|
||||||
|
main_layout->addWidget(button_box);
|
||||||
|
|
||||||
|
dialog.setLayout(main_layout);
|
||||||
|
|
||||||
|
// Focusing something else by default instead of the first spin box.
|
||||||
|
// Dynamically changing expression-backed settings pause when taking input.
|
||||||
|
// This just avoids that weird edge case behavior when the dialog is first open.
|
||||||
|
button_box->setFocus();
|
||||||
|
|
||||||
|
// Signal the newly created numeric setting widgets to display the current values.
|
||||||
|
emit ConfigChanged();
|
||||||
|
|
||||||
|
// Enable "Close" button functionality.
|
||||||
|
connect(button_box, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
|
||||||
|
|
||||||
|
dialog.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
QGroupBox* MappingWidget::CreateControlsBox(const QString& name, ControllerEmu::ControlGroup* group,
|
QGroupBox* MappingWidget::CreateControlsBox(const QString& name, ControllerEmu::ControlGroup* group,
|
||||||
|
@ -26,6 +26,7 @@ class Control;
|
|||||||
class ControlGroup;
|
class ControlGroup;
|
||||||
class EmulatedController;
|
class EmulatedController;
|
||||||
class NumericSettingBase;
|
class NumericSettingBase;
|
||||||
|
enum class SettingVisibility;
|
||||||
} // namespace ControllerEmu
|
} // namespace ControllerEmu
|
||||||
|
|
||||||
constexpr int INDICATOR_UPDATE_FREQ = 30;
|
constexpr int INDICATOR_UPDATE_FREQ = 30;
|
||||||
@ -57,6 +58,9 @@ protected:
|
|||||||
int columns);
|
int columns);
|
||||||
void CreateControl(const ControllerEmu::Control* control, QFormLayout* layout, bool indicator);
|
void CreateControl(const ControllerEmu::Control* control, QFormLayout* layout, bool indicator);
|
||||||
QPushButton* CreateSettingAdvancedMappingButton(ControllerEmu::NumericSettingBase& setting);
|
QPushButton* CreateSettingAdvancedMappingButton(ControllerEmu::NumericSettingBase& setting);
|
||||||
|
void AddSettingWidgets(QFormLayout* layout, ControllerEmu::ControlGroup* group,
|
||||||
|
ControllerEmu::SettingVisibility visibility);
|
||||||
|
void ShowAdvancedControlGroupDialog(ControllerEmu::ControlGroup* group);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MappingWindow* m_parent;
|
MappingWindow* m_parent;
|
||||||
|
@ -65,9 +65,19 @@ OctagonAnalogStick::OctagonAnalogStick(const char* name_, ControlState gate_radi
|
|||||||
|
|
||||||
OctagonAnalogStick::OctagonAnalogStick(const char* name_, const char* ui_name_,
|
OctagonAnalogStick::OctagonAnalogStick(const char* name_, const char* ui_name_,
|
||||||
ControlState gate_radius)
|
ControlState gate_radius)
|
||||||
: AnalogStick(name_, ui_name_, std::make_unique<ControllerEmu::OctagonStickGate>(gate_radius))
|
: AnalogStick(name_, ui_name_, std::make_unique<ControllerEmu::OctagonStickGate>(1.0))
|
||||||
{
|
{
|
||||||
AddVirtualNotchSetting(&m_virtual_notch_setting, 45);
|
AddVirtualNotchSetting(&m_virtual_notch_setting, 45);
|
||||||
|
|
||||||
|
AddSetting(
|
||||||
|
&m_gate_size_setting,
|
||||||
|
{_trans("Gate Size"),
|
||||||
|
// i18n: The percent symbol.
|
||||||
|
_trans("%"),
|
||||||
|
// i18n: Refers to plastic shell of game controller (stick gate) that limits stick movements.
|
||||||
|
_trans("Adjusts target radius of simulated stick gate."), nullptr,
|
||||||
|
SettingVisibility::Advanced},
|
||||||
|
gate_radius * 100, 0.01, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
ControlState OctagonAnalogStick::GetVirtualNotchSize() const
|
ControlState OctagonAnalogStick::GetVirtualNotchSize() const
|
||||||
@ -75,4 +85,9 @@ ControlState OctagonAnalogStick::GetVirtualNotchSize() const
|
|||||||
return m_virtual_notch_setting.GetValue() * MathUtil::TAU / 360;
|
return m_virtual_notch_setting.GetValue() * MathUtil::TAU / 360;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ControlState OctagonAnalogStick::GetGateRadiusAtAngle(double ang) const
|
||||||
|
{
|
||||||
|
return AnalogStick::GetGateRadiusAtAngle(ang) * m_gate_size_setting.GetValue() / 100;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ControllerEmu
|
} // namespace ControllerEmu
|
||||||
|
@ -36,9 +36,11 @@ public:
|
|||||||
OctagonAnalogStick(const char* name, const char* ui_name, ControlState gate_radius);
|
OctagonAnalogStick(const char* name, const char* ui_name, ControlState gate_radius);
|
||||||
|
|
||||||
ControlState GetVirtualNotchSize() const override;
|
ControlState GetVirtualNotchSize() const override;
|
||||||
|
ControlState GetGateRadiusAtAngle(double ang) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SettingValue<double> m_virtual_notch_setting;
|
SettingValue<double> m_virtual_notch_setting;
|
||||||
|
SettingValue<double> m_gate_size_setting;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ControllerEmu
|
} // namespace ControllerEmu
|
||||||
|
@ -32,7 +32,8 @@ void ControlGroup::AddVirtualNotchSetting(SettingValue<double>* value, double ma
|
|||||||
AddSetting(value,
|
AddSetting(value,
|
||||||
{_trans("Virtual Notches"),
|
{_trans("Virtual Notches"),
|
||||||
// i18n: The degrees symbol.
|
// i18n: The degrees symbol.
|
||||||
_trans("°"), _trans("Snap the thumbstick position to the nearest octagonal axis.")},
|
_trans("°"), _trans("Snap the thumbstick position to the nearest octagonal axis."),
|
||||||
|
nullptr, SettingVisibility::Advanced},
|
||||||
0, 0, max_virtual_notch_deg);
|
0, 0, max_virtual_notch_deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,11 @@ const char* NumericSettingBase::GetUIDescription() const
|
|||||||
return m_details.ui_description;
|
return m_details.ui_description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingVisibility NumericSettingBase::GetVisibility() const
|
||||||
|
{
|
||||||
|
return m_details.visibility;
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void NumericSetting<int>::SetExpressionFromValue()
|
void NumericSetting<int>::SetExpressionFromValue()
|
||||||
{
|
{
|
||||||
|
@ -20,13 +20,20 @@ enum class SettingType
|
|||||||
Bool,
|
Bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class SettingVisibility
|
||||||
|
{
|
||||||
|
Normal,
|
||||||
|
Advanced,
|
||||||
|
};
|
||||||
|
|
||||||
struct NumericSettingDetails
|
struct NumericSettingDetails
|
||||||
{
|
{
|
||||||
NumericSettingDetails(const char* const _ini_name, const char* const _ui_suffix = nullptr,
|
NumericSettingDetails(const char* const _ini_name, const char* const _ui_suffix = nullptr,
|
||||||
const char* const _ui_description = nullptr,
|
const char* const _ui_description = nullptr,
|
||||||
const char* const _ui_name = nullptr)
|
const char* const _ui_name = nullptr,
|
||||||
|
SettingVisibility _visibility = SettingVisibility::Normal)
|
||||||
: ini_name(_ini_name), ui_suffix(_ui_suffix), ui_description(_ui_description),
|
: ini_name(_ini_name), ui_suffix(_ui_suffix), ui_description(_ui_description),
|
||||||
ui_name(_ui_name ? _ui_name : _ini_name)
|
ui_name(_ui_name ? _ui_name : _ini_name), visibility(_visibility)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,6 +48,9 @@ struct NumericSettingDetails
|
|||||||
|
|
||||||
// The name used in the UI (if different from ini file).
|
// The name used in the UI (if different from ini file).
|
||||||
const char* const ui_name;
|
const char* const ui_name;
|
||||||
|
|
||||||
|
// Advanced settings should be harder to change in the UI. They might confuse users.
|
||||||
|
const SettingVisibility visibility;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NumericSettingBase
|
class NumericSettingBase
|
||||||
@ -66,9 +76,12 @@ public:
|
|||||||
|
|
||||||
virtual SettingType GetType() const = 0;
|
virtual SettingType GetType() const = 0;
|
||||||
|
|
||||||
|
virtual void SetToDefault() = 0;
|
||||||
|
|
||||||
const char* GetUIName() const;
|
const char* GetUIName() const;
|
||||||
const char* GetUISuffix() const;
|
const char* GetUISuffix() const;
|
||||||
const char* GetUIDescription() const;
|
const char* GetUIDescription() const;
|
||||||
|
SettingVisibility GetVisibility() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NumericSettingDetails m_details;
|
NumericSettingDetails m_details;
|
||||||
@ -92,9 +105,11 @@ public:
|
|||||||
: NumericSettingBase(details), m_value(*value), m_default_value(default_value),
|
: NumericSettingBase(details), m_value(*value), m_default_value(default_value),
|
||||||
m_min_value(min_value), m_max_value(max_value)
|
m_min_value(min_value), m_max_value(max_value)
|
||||||
{
|
{
|
||||||
m_value.SetValue(m_default_value);
|
SetToDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetToDefault() override { m_value.SetValue(m_default_value); }
|
||||||
|
|
||||||
void LoadFromIni(const IniFile::Section& section, const std::string& group_name) override
|
void LoadFromIni(const IniFile::Section& section, const std::string& group_name) override
|
||||||
{
|
{
|
||||||
std::string str_value;
|
std::string str_value;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user