Add multiple input profile support

Only supported in the Qt frontend.
This commit is contained in:
Valentin Vanelslande 2018-12-28 19:24:56 -05:00
parent 3989c17cb0
commit 7c95032e3a
10 changed files with 415 additions and 165 deletions

View File

@ -71,6 +71,7 @@ static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs>
void Config::ReadValues() { void Config::ReadValues() {
// Controls // Controls
// TODO: add multiple input profile support
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
Settings::values.buttons[i] = Settings::values.buttons[i] =

View File

@ -50,45 +50,69 @@ const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config:
void Config::ReadValues() { void Config::ReadValues() {
qt_config->beginGroup("Controls"); qt_config->beginGroup("Controls");
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); Settings::values.profile = ReadSetting("profile", 0).toInt();
Settings::values.buttons[i] =
ReadSetting(Settings::NativeButton::mapping[i], QString::fromStdString(default_param)) const auto append_profile = [this] {
Settings::InputProfile profile;
profile.name = ReadSetting("name", "default").toString().toStdString();
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
profile.buttons[i] = ReadSetting(Settings::NativeButton::mapping[i],
QString::fromStdString(default_param))
.toString()
.toStdString();
if (profile.buttons.empty())
profile.buttons[i] = default_param;
}
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
default_analogs[i][3], default_analogs[i][4], 0.5f);
profile.analogs[i] = ReadSetting(Settings::NativeAnalog::mapping[i],
QString::fromStdString(default_param))
.toString()
.toStdString();
if (profile.analogs[i].empty())
profile.analogs[i] = default_param;
}
profile.motion_device =
ReadSetting("motion_device",
"engine:motion_emu,update_period:100,sensitivity:0.01,tilt_clamp:90.0")
.toString() .toString()
.toStdString(); .toStdString();
if (Settings::values.buttons[i].empty()) profile.touch_device =
Settings::values.buttons[i] = default_param; ReadSetting("touch_device", "engine:emu_window").toString().toStdString();
} profile.udp_input_address =
ReadSetting("udp_input_address", InputCommon::CemuhookUDP::DEFAULT_ADDR)
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
default_analogs[i][3], default_analogs[i][4], 0.5f);
Settings::values.analogs[i] =
ReadSetting(Settings::NativeAnalog::mapping[i], QString::fromStdString(default_param))
.toString() .toString()
.toStdString(); .toStdString();
if (Settings::values.analogs[i].empty()) profile.udp_input_port = static_cast<u16>(
Settings::values.analogs[i] = default_param; ReadSetting("udp_input_port", InputCommon::CemuhookUDP::DEFAULT_PORT).toInt());
profile.udp_pad_index = static_cast<u8>(ReadSetting("udp_pad_index", 0).toUInt());
Settings::values.profiles.emplace_back(std::move(profile));
};
int size = qt_config->beginReadArray("profiles");
for (int i = 0; i < size; ++i) {
qt_config->setArrayIndex(i);
append_profile();
} }
Settings::values.motion_device = qt_config->endArray();
ReadSetting("motion_device",
"engine:motion_emu,update_period:100,sensitivity:0.01,tilt_clamp:90.0")
.toString()
.toStdString();
Settings::values.touch_device =
ReadSetting("touch_device", "engine:emu_window").toString().toStdString();
Settings::values.udp_input_address = if (Settings::values.profile <= size) {
ReadSetting("udp_input_address", InputCommon::CemuhookUDP::DEFAULT_ADDR) Settings::values.profile = 0;
.toString() }
.toStdString();
Settings::values.udp_input_port = static_cast<u16>(
ReadSetting("udp_input_port", InputCommon::CemuhookUDP::DEFAULT_PORT).toInt());
Settings::values.udp_pad_index = static_cast<u8>(ReadSetting("udp_pad_index", 0).toUInt());
qt_config->endGroup(); if (size == 0) {
append_profile();
}
Settings::LoadProfile(Settings::values.profile);
qt_config->endArray();
qt_config->beginGroup("Core"); qt_config->beginGroup("Core");
Settings::values.use_cpu_jit = ReadSetting("use_cpu_jit", true).toBool(); Settings::values.use_cpu_jit = ReadSetting("use_cpu_jit", true).toBool();
@ -257,7 +281,7 @@ void Config::ReadValues() {
UISettings::values.game_dir_deprecated = ReadSetting("gameListRootDir", ".").toString(); UISettings::values.game_dir_deprecated = ReadSetting("gameListRootDir", ".").toString();
UISettings::values.game_dir_deprecated_deepscan = UISettings::values.game_dir_deprecated_deepscan =
ReadSetting("gameListDeepScan", false).toBool(); ReadSetting("gameListDeepScan", false).toBool();
int size = qt_config->beginReadArray("gamedirs"); size = qt_config->beginReadArray("gamedirs");
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
qt_config->setArrayIndex(i); qt_config->setArrayIndex(i);
UISettings::GameDir game_dir; UISettings::GameDir game_dir;
@ -267,8 +291,8 @@ void Config::ReadValues() {
UISettings::values.game_dirs.append(game_dir); UISettings::values.game_dirs.append(game_dir);
} }
qt_config->endArray(); qt_config->endArray();
// create NAND and SD card directories if empty, these are not removable through the UI, also // create NAND and SD card directories if empty, these are not removable through the UI,
// carries over old game list settings if present // also carries over old game list settings if present
if (UISettings::values.game_dirs.isEmpty()) { if (UISettings::values.game_dirs.isEmpty()) {
UISettings::GameDir game_dir; UISettings::GameDir game_dir;
game_dir.path = "INSTALLED"; game_dir.path = "INSTALLED";
@ -352,29 +376,36 @@ void Config::ReadValues() {
void Config::SaveValues() { void Config::SaveValues() {
qt_config->beginGroup("Controls"); qt_config->beginGroup("Controls");
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { WriteSetting("profile", Settings::values.profile, 0);
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); qt_config->beginWriteArray("profiles");
WriteSetting(QString::fromStdString(Settings::NativeButton::mapping[i]), for (int p = 0; p < Settings::values.profiles.size(); ++p) {
QString::fromStdString(Settings::values.buttons[i]), qt_config->setArrayIndex(p);
QString::fromStdString(default_param)); const auto& profile = Settings::values.profiles[p];
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
WriteSetting(QString::fromStdString(Settings::NativeButton::mapping[i]),
QString::fromStdString(profile.buttons[i]),
QString::fromStdString(default_param));
}
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
default_analogs[i][3], default_analogs[i][4], 0.5f);
WriteSetting(QString::fromStdString(Settings::NativeAnalog::mapping[i]),
QString::fromStdString(profile.analogs[i]),
QString::fromStdString(default_param));
}
WriteSetting("motion_device", QString::fromStdString(profile.motion_device),
"engine:motion_emu,update_period:100,sensitivity:0.01,tilt_clamp:90.0");
WriteSetting("touch_device", QString::fromStdString(profile.touch_device),
"engine:emu_window");
WriteSetting("udp_input_address", QString::fromStdString(profile.udp_input_address),
InputCommon::CemuhookUDP::DEFAULT_ADDR);
WriteSetting("udp_input_port", profile.udp_input_port,
InputCommon::CemuhookUDP::DEFAULT_PORT);
WriteSetting("udp_pad_index", profile.udp_pad_index, 0);
} }
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { qt_config->endArray();
std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
default_analogs[i][3], default_analogs[i][4], 0.5f);
WriteSetting(QString::fromStdString(Settings::NativeAnalog::mapping[i]),
QString::fromStdString(Settings::values.analogs[i]),
QString::fromStdString(default_param));
}
WriteSetting("motion_device", QString::fromStdString(Settings::values.motion_device),
"engine:motion_emu,update_period:100,sensitivity:0.01,tilt_clamp:90.0");
WriteSetting("touch_device", QString::fromStdString(Settings::values.touch_device),
"engine:emu_window");
WriteSetting("udp_input_address", QString::fromStdString(Settings::values.udp_input_address),
InputCommon::CemuhookUDP::DEFAULT_ADDR);
WriteSetting("udp_input_port", Settings::values.udp_input_port,
InputCommon::CemuhookUDP::DEFAULT_PORT);
WriteSetting("udp_pad_index", Settings::values.udp_pad_index, 0);
qt_config->endGroup(); qt_config->endGroup();
qt_config->beginGroup("Core"); qt_config->beginGroup("Core");

View File

@ -42,6 +42,7 @@ void ConfigureDialog::applyConfiguration() {
ui->generalTab->applyConfiguration(); ui->generalTab->applyConfiguration();
ui->systemTab->applyConfiguration(); ui->systemTab->applyConfiguration();
ui->inputTab->applyConfiguration(); ui->inputTab->applyConfiguration();
ui->inputTab->applyProfile();
ui->graphicsTab->applyConfiguration(); ui->graphicsTab->applyConfiguration();
ui->audioTab->applyConfiguration(); ui->audioTab->applyConfiguration();
ui->cameraTab->applyConfiguration(); ui->cameraTab->applyConfiguration();

View File

@ -5,6 +5,7 @@
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <QInputDialog>
#include <QMenu> #include <QMenu>
#include <QMessageBox> #include <QMessageBox>
#include <QTimer> #include <QTimer>
@ -99,6 +100,12 @@ ConfigureInput::ConfigureInput(QWidget* parent)
ui->setupUi(this); ui->setupUi(this);
setFocusPolicy(Qt::ClickFocus); setFocusPolicy(Qt::ClickFocus);
for (int i = 0; i < Settings::values.profiles.size(); ++i) {
ui->profile->addItem(QString::fromStdString(Settings::values.profiles[i].name));
}
ui->profile->setCurrentIndex(Settings::values.profile);
button_map = { button_map = {
ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, ui->buttonDpadUp, ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, ui->buttonDpadUp,
ui->buttonDpadDown, ui->buttonDpadLeft, ui->buttonDpadRight, ui->buttonL, ui->buttonR, ui->buttonDpadDown, ui->buttonDpadLeft, ui->buttonDpadRight, ui->buttonL, ui->buttonR,
@ -131,7 +138,11 @@ ConfigureInput::ConfigureInput(QWidget* parent)
connect(button_map[button_id], &QPushButton::released, [=]() { connect(button_map[button_id], &QPushButton::released, [=]() {
handleClick( handleClick(
button_map[button_id], button_map[button_id],
[=](const Common::ParamPackage& params) { buttons_param[button_id] = params; }, [=](const Common::ParamPackage& params) {
buttons_param[button_id] = params;
applyConfiguration();
Settings::SaveProfile(ui->profile->currentIndex());
},
InputCommon::Polling::DeviceType::Button); InputCommon::Polling::DeviceType::Button);
}); });
connect(button_map[button_id], &QPushButton::customContextMenuRequested, connect(button_map[button_id], &QPushButton::customContextMenuRequested,
@ -140,11 +151,15 @@ ConfigureInput::ConfigureInput(QWidget* parent)
context_menu.addAction(tr("Clear"), [&] { context_menu.addAction(tr("Clear"), [&] {
buttons_param[button_id].Clear(); buttons_param[button_id].Clear();
button_map[button_id]->setText(tr("[not set]")); button_map[button_id]->setText(tr("[not set]"));
applyConfiguration();
Settings::SaveProfile(ui->profile->currentIndex());
}); });
context_menu.addAction(tr("Restore Default"), [&] { context_menu.addAction(tr("Restore Default"), [&] {
buttons_param[button_id] = Common::ParamPackage{ buttons_param[button_id] = Common::ParamPackage{
InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])};
button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); button_map[button_id]->setText(ButtonToText(buttons_param[button_id]));
applyConfiguration();
Settings::SaveProfile(ui->profile->currentIndex());
}); });
context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
}); });
@ -157,12 +172,15 @@ ConfigureInput::ConfigureInput(QWidget* parent)
analog_map_buttons[analog_id][sub_button_id]->setContextMenuPolicy( analog_map_buttons[analog_id][sub_button_id]->setContextMenuPolicy(
Qt::CustomContextMenu); Qt::CustomContextMenu);
connect(analog_map_buttons[analog_id][sub_button_id], &QPushButton::released, [=]() { connect(analog_map_buttons[analog_id][sub_button_id], &QPushButton::released, [=]() {
handleClick(analog_map_buttons[analog_id][sub_button_id], handleClick(
[=](const Common::ParamPackage& params) { analog_map_buttons[analog_id][sub_button_id],
SetAnalogButton(params, analogs_param[analog_id], [=](const Common::ParamPackage& params) {
analog_sub_buttons[sub_button_id]); SetAnalogButton(params, analogs_param[analog_id],
}, analog_sub_buttons[sub_button_id]);
InputCommon::Polling::DeviceType::Button); applyConfiguration();
Settings::SaveProfile(ui->profile->currentIndex());
},
InputCommon::Polling::DeviceType::Button);
}); });
connect(analog_map_buttons[analog_id][sub_button_id], connect(analog_map_buttons[analog_id][sub_button_id],
&QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) { &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) {
@ -170,6 +188,8 @@ ConfigureInput::ConfigureInput(QWidget* parent)
context_menu.addAction(tr("Clear"), [&] { context_menu.addAction(tr("Clear"), [&] {
analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]); analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]);
analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]")); analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]"));
applyConfiguration();
Settings::SaveProfile(ui->profile->currentIndex());
}); });
context_menu.addAction(tr("Restore Default"), [&] { context_menu.addAction(tr("Restore Default"), [&] {
Common::ParamPackage params{InputCommon::GenerateKeyboardParam( Common::ParamPackage params{InputCommon::GenerateKeyboardParam(
@ -178,6 +198,8 @@ ConfigureInput::ConfigureInput(QWidget* parent)
analog_sub_buttons[sub_button_id]); analog_sub_buttons[sub_button_id]);
analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText( analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText(
analogs_param[analog_id], analog_sub_buttons[sub_button_id])); analogs_param[analog_id], analog_sub_buttons[sub_button_id]));
applyConfiguration();
Settings::SaveProfile(ui->profile->currentIndex());
}); });
context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal( context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal(
menu_location)); menu_location));
@ -189,7 +211,11 @@ ConfigureInput::ConfigureInput(QWidget* parent)
"and then vertically.")); "and then vertically."));
handleClick( handleClick(
analog_map_stick[analog_id], analog_map_stick[analog_id],
[=](const Common::ParamPackage& params) { analogs_param[analog_id] = params; }, [=](const Common::ParamPackage& params) {
analogs_param[analog_id] = params;
applyConfiguration();
Settings::SaveProfile(ui->profile->currentIndex());
},
InputCommon::Polling::DeviceType::Analog); InputCommon::Polling::DeviceType::Analog);
}); });
} }
@ -200,6 +226,17 @@ ConfigureInput::ConfigureInput(QWidget* parent)
}); });
connect(ui->buttonClearAll, &QPushButton::released, [this] { ClearAll(); }); connect(ui->buttonClearAll, &QPushButton::released, [this] { ClearAll(); });
connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); }); connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); });
connect(ui->buttonNew, &QPushButton::released, [this] { newProfile(); });
connect(ui->buttonDelete, &QPushButton::released, [this] { deleteProfile(); });
connect(ui->buttonRename, &QPushButton::released, [this] { renameProfile(); });
connect(ui->profile, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
[this](int i) {
applyConfiguration();
Settings::SaveProfile(Settings::values.profile);
Settings::LoadProfile(i);
loadConfiguration();
});
timeout_timer->setSingleShot(true); timeout_timer->setSingleShot(true);
connect(timeout_timer.get(), &QTimer::timeout, [this]() { setPollingResult({}, true); }); connect(timeout_timer.get(), &QTimer::timeout, [this]() { setPollingResult({}, true); });
@ -230,6 +267,10 @@ void ConfigureInput::applyConfiguration() {
[](const Common::ParamPackage& param) { return param.Serialize(); }); [](const Common::ParamPackage& param) { return param.Serialize(); });
} }
void ConfigureInput::applyProfile() {
Settings::values.profile = ui->profile->currentIndex();
}
void ConfigureInput::loadConfiguration() { void ConfigureInput::loadConfiguration() {
std::transform(Settings::values.buttons.begin(), Settings::values.buttons.end(), std::transform(Settings::values.buttons.begin(), Settings::values.buttons.end(),
buttons_param.begin(), buttons_param.begin(),
@ -346,3 +387,43 @@ void ConfigureInput::keyPressEvent(QKeyEvent* event) {
void ConfigureInput::retranslateUi() { void ConfigureInput::retranslateUi() {
ui->retranslateUi(this); ui->retranslateUi(this);
} }
void ConfigureInput::newProfile() {
QString name =
QInputDialog::getText(this, tr("New Profile"), tr("Enter the name for the new profile."));
if (name.isEmpty()) {
return;
}
applyConfiguration();
Settings::SaveProfile(ui->profile->currentIndex());
Settings::CreateProfile(name.toStdString());
ui->profile->addItem(name);
ui->profile->setCurrentIndex(Settings::values.profile);
loadConfiguration();
}
void ConfigureInput::deleteProfile() {
if (ui->profile->count() == 1) {
QMessageBox::critical(this, tr("Citra"), tr("You need to have 1 profile at least"));
return;
}
QMessageBox::StandardButton answer = QMessageBox::question(
this, tr("Delete Profile"), tr("Delete profile %1?").arg(ui->profile->currentText()));
if (answer != QMessageBox::Yes) {
return;
}
int index = ui->profile->currentIndex();
ui->profile->removeItem(index);
ui->profile->setCurrentIndex(0);
Settings::DeleteProfile(index);
loadConfiguration();
}
void ConfigureInput::renameProfile() {
QString new_name = QInputDialog::getText(this, tr("Rename Profile"), tr("New name:"));
if (new_name.isEmpty()) {
return;
}
ui->profile->setItemText(ui->profile->currentIndex(), new_name);
Settings::RenameCurrentProfile(new_name.toStdString());
}

View File

@ -39,6 +39,9 @@ public:
/// Load configuration settings. /// Load configuration settings.
void loadConfiguration(); void loadConfiguration();
// Save the current input profile index
void applyProfile();
private: private:
std::unique_ptr<Ui::ConfigureInput> ui; std::unique_ptr<Ui::ConfigureInput> ui;
@ -91,4 +94,9 @@ private:
/// Handle key press events. /// Handle key press events.
void keyPressEvent(QKeyEvent* event) override; void keyPressEvent(QKeyEvent* event) override;
/// input profiles
void newProfile();
void deleteProfile();
void renameProfile();
}; };

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>370</width> <width>376</width>
<height>534</height> <height>535</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -555,103 +555,155 @@
</layout> </layout>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QVBoxLayout" name="verticalLayout_6">
<item> <item>
<widget class="QPushButton" name="buttonMotionTouch"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="sizePolicy"> <item>
<sizepolicy hsizetype="Minimum" vsizetype="Fixed"> <widget class="QLabel" name="label_5">
<horstretch>0</horstretch> <property name="text">
<verstretch>0</verstretch> <string>Profile</string>
</sizepolicy> </property>
</property> </widget>
<property name="sizeIncrement"> </item>
<size> <item>
<width>0</width> <widget class="QComboBox" name="profile"/>
<height>0</height> </item>
</size> <item>
</property> <widget class="QPushButton" name="buttonNew">
<property name="baseSize"> <property name="text">
<size> <string>New</string>
<width>0</width> </property>
<height>0</height> </widget>
</size> </item>
</property> <item>
<property name="layoutDirection"> <widget class="QPushButton" name="buttonDelete">
<enum>Qt::LeftToRight</enum> <property name="text">
</property> <string>Delete</string>
<property name="text"> </property>
<string>Motion / Touch...</string> </widget>
</property> </item>
</widget> <item>
<widget class="QPushButton" name="buttonRename">
<property name="text">
<string>Rename</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer"> <layout class="QHBoxLayout" name="horizontalLayout">
<property name="orientation"> <item>
<enum>Qt::Horizontal</enum> <widget class="QPushButton" name="buttonMotionTouch">
</property> <property name="sizePolicy">
<property name="sizeHint" stdset="0"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<size> <horstretch>0</horstretch>
<width>40</width> <verstretch>0</verstretch>
<height>20</height> </sizepolicy>
</size> </property>
</property> <property name="sizeIncrement">
</spacer> <size>
</item> <width>0</width>
<item> <height>0</height>
<widget class="QPushButton" name="buttonClearAll"> </size>
<property name="sizePolicy"> </property>
<sizepolicy hsizetype="Minimum" vsizetype="Fixed"> <property name="baseSize">
<horstretch>0</horstretch> <size>
<verstretch>0</verstretch> <width>0</width>
</sizepolicy> <height>0</height>
</property> </size>
<property name="sizeIncrement"> </property>
<size> <property name="layoutDirection">
<width>0</width> <enum>Qt::LeftToRight</enum>
<height>0</height> </property>
</size> <property name="text">
</property> <string>Motion / Touch...</string>
<property name="baseSize"> </property>
<size> </widget>
<width>0</width> </item>
<height>0</height> <item>
</size> <spacer name="horizontalSpacer">
</property> <property name="orientation">
<property name="layoutDirection"> <enum>Qt::Horizontal</enum>
<enum>Qt::LeftToRight</enum> </property>
</property> <property name="sizeHint" stdset="0">
<property name="text"> <size>
<string>Clear All</string> <width>40</width>
</property> <height>20</height>
</widget> </size>
</item> </property>
<item> </spacer>
<widget class="QPushButton" name="buttonRestoreDefaults"> </item>
<property name="sizePolicy"> <item>
<sizepolicy hsizetype="Minimum" vsizetype="Fixed"> <widget class="QPushButton" name="buttonClearAll">
<horstretch>0</horstretch> <property name="sizePolicy">
<verstretch>0</verstretch> <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
</sizepolicy> <horstretch>0</horstretch>
</property> <verstretch>0</verstretch>
<property name="sizeIncrement"> </sizepolicy>
<size> </property>
<width>0</width> <property name="sizeIncrement">
<height>0</height> <size>
</size> <width>0</width>
</property> <height>0</height>
<property name="baseSize"> </size>
<size> </property>
<width>0</width> <property name="baseSize">
<height>0</height> <size>
</size> <width>0</width>
</property> <height>0</height>
<property name="layoutDirection"> </size>
<enum>Qt::LeftToRight</enum> </property>
</property> <property name="layoutDirection">
<property name="text"> <enum>Qt::LeftToRight</enum>
<string>Restore Defaults</string> </property>
</property> <property name="text">
</widget> <string>Clear All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonRestoreDefaults">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeIncrement">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Restore Defaults</string>
</property>
</widget>
</item>
</layout>
</item> </item>
</layout> </layout>
</item> </item>

View File

@ -270,6 +270,7 @@ void ConfigureMotionTouch::applyConfiguration() {
Settings::values.udp_input_address = ui->udp_server->text().toStdString(); Settings::values.udp_input_address = ui->udp_server->text().toStdString();
Settings::values.udp_input_port = static_cast<u16>(ui->udp_port->text().toInt()); Settings::values.udp_input_port = static_cast<u16>(ui->udp_port->text().toInt());
Settings::values.udp_pad_index = static_cast<u8>(ui->udp_pad_index->currentIndex()); Settings::values.udp_pad_index = static_cast<u8>(ui->udp_pad_index->currentIndex());
Settings::SaveProfile(Settings::values.profile);
InputCommon::ReloadInputDevices(); InputCommon::ReloadInputDevices();
accept(); accept();

View File

@ -1326,6 +1326,8 @@ void GMainWindow::OnConfigure() {
connect(&configureDialog, &ConfigureDialog::languageChanged, this, connect(&configureDialog, &ConfigureDialog::languageChanged, this,
&GMainWindow::OnLanguageChanged); &GMainWindow::OnLanguageChanged);
auto old_theme = UISettings::values.theme; auto old_theme = UISettings::values.theme;
const int old_profile = Settings::values.profile;
auto old_profiles = Settings::values.profiles;
const bool old_discord_presence = UISettings::values.enable_discord_presence; const bool old_discord_presence = UISettings::values.enable_discord_presence;
auto result = configureDialog.exec(); auto result = configureDialog.exec();
if (result == QDialog::Accepted) { if (result == QDialog::Accepted) {
@ -1338,6 +1340,9 @@ void GMainWindow::OnConfigure() {
SyncMenuUISettings(); SyncMenuUISettings();
game_list->RefreshGameDirectory(); game_list->RefreshGameDirectory();
config->Save(); config->Save();
} else {
Settings::values.profiles = old_profiles;
Settings::LoadProfile(old_profile);
} }
} }

View File

@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <utility>
#include "audio_core/dsp_interface.h" #include "audio_core/dsp_interface.h"
#include "core/core.h" #include "core/core.h"
#include "core/gdbstub/gdbstub.h" #include "core/gdbstub/gdbstub.h"
@ -99,4 +100,51 @@ void LogSettings() {
LogSetting("Debugging_GdbstubPort", Settings::values.gdbstub_port); LogSetting("Debugging_GdbstubPort", Settings::values.gdbstub_port);
} }
void LoadProfile(int index) {
const auto& profile = values.profiles[index];
values.profile = index;
values.analogs = profile.analogs;
values.buttons = profile.buttons;
values.motion_device = profile.motion_device;
values.touch_device = profile.touch_device;
values.udp_input_address = profile.udp_input_address;
values.udp_input_port = profile.udp_input_port;
values.udp_pad_index = profile.udp_pad_index;
}
void SaveProfile(int index) {
auto& profile = values.profiles[index];
profile.analogs = values.analogs;
profile.buttons = values.buttons;
profile.motion_device = values.motion_device;
profile.touch_device = values.touch_device;
profile.udp_input_address = values.udp_input_address;
profile.udp_input_port = values.udp_input_port;
profile.udp_pad_index = values.udp_pad_index;
}
void CreateProfile(std::string name) {
InputProfile profile;
profile.name = std::move(name);
profile.analogs = values.analogs;
profile.buttons = values.buttons;
profile.motion_device = values.motion_device;
profile.touch_device = values.touch_device;
profile.udp_input_address = values.udp_input_address;
profile.udp_input_port = values.udp_input_port;
profile.udp_pad_index = values.udp_pad_index;
values.profiles.push_back(profile);
values.profile = static_cast<int>(values.profiles.size()) - 1;
LoadProfile(values.profile);
}
void DeleteProfile(int index) {
values.profiles.erase(values.profiles.begin() + index);
LoadProfile(0);
}
void RenameCurrentProfile(std::string new_name) {
values.profiles[values.profile].name = std::move(new_name);
}
} // namespace Settings } // namespace Settings

View File

@ -7,6 +7,7 @@
#include <array> #include <array>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/service/cam/cam.h" #include "core/hle/service/cam/cam.h"
@ -92,11 +93,8 @@ static const std::array<const char*, NumAnalogs> mapping = {{
}}; }};
} // namespace NativeAnalog } // namespace NativeAnalog
struct Values { struct InputProfile {
// CheckNew3DS std::string name;
bool is_new_3ds;
// Controls
std::array<std::string, NativeButton::NumButtons> buttons; std::array<std::string, NativeButton::NumButtons> buttons;
std::array<std::string, NativeAnalog::NumAnalogs> analogs; std::array<std::string, NativeAnalog::NumAnalogs> analogs;
std::string motion_device; std::string motion_device;
@ -104,6 +102,23 @@ struct Values {
std::string udp_input_address; std::string udp_input_address;
u16 udp_input_port; u16 udp_input_port;
u8 udp_pad_index; u8 udp_pad_index;
};
struct Values {
// CheckNew3DS
bool is_new_3ds;
// Current controls
std::array<std::string, NativeButton::NumButtons> buttons;
std::array<std::string, NativeAnalog::NumAnalogs> analogs;
std::string motion_device;
std::string touch_device;
std::string udp_input_address;
u16 udp_input_port;
u8 udp_pad_index;
int profile; ///< The current input profile index
std::vector<InputProfile> profiles; ///< The list of input profiles
// Core // Core
bool use_cpu_jit; bool use_cpu_jit;
@ -176,4 +191,11 @@ static constexpr int REGION_VALUE_AUTO_SELECT = -1;
void Apply(); void Apply();
void LogSettings(); void LogSettings();
// input profiles
void LoadProfile(int index);
void SaveProfile(int index);
void CreateProfile(std::string name);
void DeleteProfile(int index);
void RenameCurrentProfile(std::string new_name);
} // namespace Settings } // namespace Settings