Merge pull request #4538 from valentinvanelslande/profiles
Add multiple input profile support
This commit is contained in:
commit
95a57a2fe3
14 changed files with 518 additions and 280 deletions
|
@ -71,33 +71,35 @@ static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs>
|
|||
|
||||
void Config::ReadValues() {
|
||||
// Controls
|
||||
// TODO: add multiple input profile support
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
Settings::values.buttons[i] =
|
||||
Settings::values.current_input_profile.buttons[i] =
|
||||
sdl2_config->GetString("Controls", Settings::NativeButton::mapping[i], default_param);
|
||||
if (Settings::values.buttons[i].empty())
|
||||
Settings::values.buttons[i] = default_param;
|
||||
if (Settings::values.current_input_profile.buttons[i].empty())
|
||||
Settings::values.current_input_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);
|
||||
Settings::values.analogs[i] =
|
||||
Settings::values.current_input_profile.analogs[i] =
|
||||
sdl2_config->GetString("Controls", Settings::NativeAnalog::mapping[i], default_param);
|
||||
if (Settings::values.analogs[i].empty())
|
||||
Settings::values.analogs[i] = default_param;
|
||||
if (Settings::values.current_input_profile.analogs[i].empty())
|
||||
Settings::values.current_input_profile.analogs[i] = default_param;
|
||||
}
|
||||
|
||||
Settings::values.motion_device = sdl2_config->GetString(
|
||||
Settings::values.current_input_profile.motion_device = sdl2_config->GetString(
|
||||
"Controls", "motion_device",
|
||||
"engine:motion_emu,update_period:100,sensitivity:0.01,tilt_clamp:90.0");
|
||||
Settings::values.touch_device =
|
||||
Settings::values.current_input_profile.touch_device =
|
||||
sdl2_config->GetString("Controls", "touch_device", "engine:emu_window");
|
||||
Settings::values.udp_input_address = sdl2_config->GetString(
|
||||
Settings::values.current_input_profile.udp_input_address = sdl2_config->GetString(
|
||||
"Controls", "udp_input_address", InputCommon::CemuhookUDP::DEFAULT_ADDR);
|
||||
Settings::values.udp_input_port = static_cast<u16>(sdl2_config->GetInteger(
|
||||
"Controls", "udp_input_port", InputCommon::CemuhookUDP::DEFAULT_PORT));
|
||||
Settings::values.current_input_profile.udp_input_port =
|
||||
static_cast<u16>(sdl2_config->GetInteger("Controls", "udp_input_port",
|
||||
InputCommon::CemuhookUDP::DEFAULT_PORT));
|
||||
|
||||
// Core
|
||||
Settings::values.use_cpu_jit = sdl2_config->GetBoolean("Core", "use_cpu_jit", true);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <QSettings>
|
||||
#include "citra_qt/configuration/config.h"
|
||||
|
@ -51,43 +52,69 @@ const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config:
|
|||
|
||||
void Config::ReadValues() {
|
||||
qt_config->beginGroup("Controls");
|
||||
|
||||
Settings::values.current_input_profile_index = ReadSetting("profile", 0).toInt();
|
||||
|
||||
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]);
|
||||
Settings::values.buttons[i] =
|
||||
ReadSetting(Settings::NativeButton::mapping[i], QString::fromStdString(default_param))
|
||||
profile.buttons[i] = ReadSetting(Settings::NativeButton::mapping[i],
|
||||
QString::fromStdString(default_param))
|
||||
.toString()
|
||||
.toStdString();
|
||||
if (Settings::values.buttons[i].empty())
|
||||
Settings::values.buttons[i] = default_param;
|
||||
if (profile.buttons[i].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);
|
||||
Settings::values.analogs[i] =
|
||||
ReadSetting(Settings::NativeAnalog::mapping[i], QString::fromStdString(default_param))
|
||||
profile.analogs[i] = ReadSetting(Settings::NativeAnalog::mapping[i],
|
||||
QString::fromStdString(default_param))
|
||||
.toString()
|
||||
.toStdString();
|
||||
if (Settings::values.analogs[i].empty())
|
||||
Settings::values.analogs[i] = default_param;
|
||||
if (profile.analogs[i].empty())
|
||||
profile.analogs[i] = default_param;
|
||||
}
|
||||
|
||||
Settings::values.motion_device =
|
||||
profile.motion_device =
|
||||
ReadSetting("motion_device",
|
||||
"engine:motion_emu,update_period:100,sensitivity:0.01,tilt_clamp:90.0")
|
||||
.toString()
|
||||
.toStdString();
|
||||
Settings::values.touch_device =
|
||||
profile.touch_device =
|
||||
ReadSetting("touch_device", "engine:emu_window").toString().toStdString();
|
||||
|
||||
Settings::values.udp_input_address =
|
||||
profile.udp_input_address =
|
||||
ReadSetting("udp_input_address", InputCommon::CemuhookUDP::DEFAULT_ADDR)
|
||||
.toString()
|
||||
.toStdString();
|
||||
Settings::values.udp_input_port = static_cast<u16>(
|
||||
profile.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());
|
||||
profile.udp_pad_index = static_cast<u8>(ReadSetting("udp_pad_index", 0).toUInt());
|
||||
Settings::values.input_profiles.emplace_back(std::move(profile));
|
||||
};
|
||||
|
||||
int num_input_profiles = qt_config->beginReadArray("profiles");
|
||||
|
||||
for (int i = 0; i < num_input_profiles; ++i) {
|
||||
qt_config->setArrayIndex(i);
|
||||
append_profile();
|
||||
}
|
||||
|
||||
qt_config->endArray();
|
||||
|
||||
// create a input profile if no input profiles exist, with the default or old settings
|
||||
if (num_input_profiles == 0) {
|
||||
append_profile();
|
||||
num_input_profiles = 1;
|
||||
}
|
||||
|
||||
// ensure that the current input profile index is valid.
|
||||
Settings::values.current_input_profile_index =
|
||||
std::clamp(Settings::values.current_input_profile_index, 0, num_input_profiles - 1);
|
||||
|
||||
Settings::LoadProfile(Settings::values.current_input_profile_index);
|
||||
|
||||
qt_config->endGroup();
|
||||
|
||||
|
@ -271,8 +298,8 @@ void Config::ReadValues() {
|
|||
UISettings::values.game_dirs.append(game_dir);
|
||||
}
|
||||
qt_config->endArray();
|
||||
// create NAND and SD card directories if empty, these are not removable through the UI, also
|
||||
// carries over old game list settings if present
|
||||
// create NAND and SD card directories if empty, these are not removable through the UI,
|
||||
// also carries over old game list settings if present
|
||||
if (UISettings::values.game_dirs.isEmpty()) {
|
||||
UISettings::GameDir game_dir;
|
||||
game_dir.path = "INSTALLED";
|
||||
|
@ -356,10 +383,15 @@ void Config::ReadValues() {
|
|||
|
||||
void Config::SaveValues() {
|
||||
qt_config->beginGroup("Controls");
|
||||
WriteSetting("profile", Settings::values.current_input_profile_index, 0);
|
||||
qt_config->beginWriteArray("profiles");
|
||||
for (std::size_t p = 0; p < Settings::values.input_profiles.size(); ++p) {
|
||||
qt_config->setArrayIndex(static_cast<int>(p));
|
||||
const auto& profile = Settings::values.input_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(Settings::values.buttons[i]),
|
||||
QString::fromStdString(profile.buttons[i]),
|
||||
QString::fromStdString(default_param));
|
||||
}
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
|
@ -367,18 +399,20 @@ void Config::SaveValues() {
|
|||
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(profile.analogs[i]),
|
||||
QString::fromStdString(default_param));
|
||||
}
|
||||
WriteSetting("motion_device", QString::fromStdString(Settings::values.motion_device),
|
||||
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(Settings::values.touch_device),
|
||||
WriteSetting("touch_device", QString::fromStdString(profile.touch_device),
|
||||
"engine:emu_window");
|
||||
WriteSetting("udp_input_address", QString::fromStdString(Settings::values.udp_input_address),
|
||||
WriteSetting("udp_input_address", QString::fromStdString(profile.udp_input_address),
|
||||
InputCommon::CemuhookUDP::DEFAULT_ADDR);
|
||||
WriteSetting("udp_input_port", Settings::values.udp_input_port,
|
||||
WriteSetting("udp_input_port", profile.udp_input_port,
|
||||
InputCommon::CemuhookUDP::DEFAULT_PORT);
|
||||
WriteSetting("udp_pad_index", Settings::values.udp_pad_index, 0);
|
||||
WriteSetting("udp_pad_index", profile.udp_pad_index, 0);
|
||||
}
|
||||
qt_config->endArray();
|
||||
qt_config->endGroup();
|
||||
|
||||
qt_config->beginGroup("Core");
|
||||
|
|
|
@ -42,6 +42,7 @@ void ConfigureDialog::applyConfiguration() {
|
|||
ui->generalTab->applyConfiguration();
|
||||
ui->systemTab->applyConfiguration();
|
||||
ui->inputTab->applyConfiguration();
|
||||
ui->inputTab->ApplyProfile();
|
||||
ui->graphicsTab->applyConfiguration();
|
||||
ui->audioTab->applyConfiguration();
|
||||
ui->cameraTab->applyConfiguration();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <QInputDialog>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QTimer>
|
||||
|
@ -95,10 +96,15 @@ static QString AnalogToText(const Common::ParamPackage& param, const std::string
|
|||
ConfigureInput::ConfigureInput(QWidget* parent)
|
||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()),
|
||||
timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) {
|
||||
|
||||
ui->setupUi(this);
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
|
||||
for (const auto& profile : Settings::values.input_profiles) {
|
||||
ui->profile->addItem(QString::fromStdString(profile.name));
|
||||
}
|
||||
|
||||
ui->profile->setCurrentIndex(Settings::values.current_input_profile_index);
|
||||
|
||||
button_map = {
|
||||
ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY,
|
||||
ui->buttonDpadUp, ui->buttonDpadDown, ui->buttonDpadLeft, ui->buttonDpadRight,
|
||||
|
@ -131,9 +137,14 @@ ConfigureInput::ConfigureInput(QWidget* parent)
|
|||
continue;
|
||||
button_map[button_id]->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(button_map[button_id], &QPushButton::released, [=]() {
|
||||
handleClick(
|
||||
button_map[button_id],
|
||||
[=](const Common::ParamPackage& params) { buttons_param[button_id] = params; },
|
||||
handleClick(button_map[button_id],
|
||||
[=](const Common::ParamPackage& params) {
|
||||
buttons_param[button_id] = params;
|
||||
// If the user closes the dialog, the changes are reverted in
|
||||
// `GMainWindow::OnConfigure()`
|
||||
applyConfiguration();
|
||||
Settings::SaveProfile(ui->profile->currentIndex());
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Button);
|
||||
});
|
||||
connect(button_map[button_id], &QPushButton::customContextMenuRequested,
|
||||
|
@ -142,11 +153,15 @@ ConfigureInput::ConfigureInput(QWidget* parent)
|
|||
context_menu.addAction(tr("Clear"), [&] {
|
||||
buttons_param[button_id].Clear();
|
||||
button_map[button_id]->setText(tr("[not set]"));
|
||||
applyConfiguration();
|
||||
Settings::SaveProfile(ui->profile->currentIndex());
|
||||
});
|
||||
context_menu.addAction(tr("Restore Default"), [&] {
|
||||
buttons_param[button_id] = Common::ParamPackage{
|
||||
InputCommon::GenerateKeyboardParam(Config::default_buttons[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));
|
||||
});
|
||||
|
@ -163,6 +178,8 @@ ConfigureInput::ConfigureInput(QWidget* parent)
|
|||
[=](const Common::ParamPackage& params) {
|
||||
SetAnalogButton(params, analogs_param[analog_id],
|
||||
analog_sub_buttons[sub_button_id]);
|
||||
applyConfiguration();
|
||||
Settings::SaveProfile(ui->profile->currentIndex());
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Button);
|
||||
});
|
||||
|
@ -172,6 +189,8 @@ ConfigureInput::ConfigureInput(QWidget* parent)
|
|||
context_menu.addAction(tr("Clear"), [&] {
|
||||
analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]);
|
||||
analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]"));
|
||||
applyConfiguration();
|
||||
Settings::SaveProfile(ui->profile->currentIndex());
|
||||
});
|
||||
context_menu.addAction(tr("Restore Default"), [&] {
|
||||
Common::ParamPackage params{InputCommon::GenerateKeyboardParam(
|
||||
|
@ -180,6 +199,8 @@ ConfigureInput::ConfigureInput(QWidget* parent)
|
|||
analog_sub_buttons[sub_button_id]);
|
||||
analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText(
|
||||
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(
|
||||
menu_location));
|
||||
|
@ -189,9 +210,12 @@ ConfigureInput::ConfigureInput(QWidget* parent)
|
|||
QMessageBox::information(this, tr("Information"),
|
||||
tr("After pressing OK, first move your joystick horizontally, "
|
||||
"and then vertically."));
|
||||
handleClick(
|
||||
analog_map_stick[analog_id],
|
||||
[=](const Common::ParamPackage& params) { analogs_param[analog_id] = params; },
|
||||
handleClick(analog_map_stick[analog_id],
|
||||
[=](const Common::ParamPackage& params) {
|
||||
analogs_param[analog_id] = params;
|
||||
applyConfiguration();
|
||||
Settings::SaveProfile(ui->profile->currentIndex());
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Analog);
|
||||
});
|
||||
}
|
||||
|
@ -200,8 +224,22 @@ ConfigureInput::ConfigureInput(QWidget* parent)
|
|||
QDialog* motion_touch_dialog = new ConfigureMotionTouch(this);
|
||||
return motion_touch_dialog->exec();
|
||||
});
|
||||
|
||||
ui->buttonDelete->setEnabled(ui->profile->count() > 1);
|
||||
|
||||
connect(ui->buttonClearAll, &QPushButton::released, [this] { ClearAll(); });
|
||||
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.current_input_profile_index);
|
||||
Settings::LoadProfile(i);
|
||||
loadConfiguration();
|
||||
});
|
||||
|
||||
timeout_timer->setSingleShot(true);
|
||||
connect(timeout_timer.get(), &QTimer::timeout, [this]() { setPollingResult({}, true); });
|
||||
|
@ -226,18 +264,24 @@ ConfigureInput::ConfigureInput(QWidget* parent)
|
|||
ConfigureInput::~ConfigureInput() = default;
|
||||
|
||||
void ConfigureInput::applyConfiguration() {
|
||||
std::transform(buttons_param.begin(), buttons_param.end(), Settings::values.buttons.begin(),
|
||||
std::transform(buttons_param.begin(), buttons_param.end(),
|
||||
Settings::values.current_input_profile.buttons.begin(),
|
||||
[](const Common::ParamPackage& param) { return param.Serialize(); });
|
||||
std::transform(analogs_param.begin(), analogs_param.end(), Settings::values.analogs.begin(),
|
||||
std::transform(analogs_param.begin(), analogs_param.end(),
|
||||
Settings::values.current_input_profile.analogs.begin(),
|
||||
[](const Common::ParamPackage& param) { return param.Serialize(); });
|
||||
}
|
||||
|
||||
void ConfigureInput::ApplyProfile() {
|
||||
Settings::values.current_input_profile_index = ui->profile->currentIndex();
|
||||
}
|
||||
|
||||
void ConfigureInput::loadConfiguration() {
|
||||
std::transform(Settings::values.buttons.begin(), Settings::values.buttons.end(),
|
||||
buttons_param.begin(),
|
||||
std::transform(Settings::values.current_input_profile.buttons.begin(),
|
||||
Settings::values.current_input_profile.buttons.end(), buttons_param.begin(),
|
||||
[](const std::string& str) { return Common::ParamPackage(str); });
|
||||
std::transform(Settings::values.analogs.begin(), Settings::values.analogs.end(),
|
||||
analogs_param.begin(),
|
||||
std::transform(Settings::values.current_input_profile.analogs.begin(),
|
||||
Settings::values.current_input_profile.analogs.end(), analogs_param.begin(),
|
||||
[](const std::string& str) { return Common::ParamPackage(str); });
|
||||
updateButtonLabels();
|
||||
}
|
||||
|
@ -349,3 +393,41 @@ void ConfigureInput::keyPressEvent(QKeyEvent* event) {
|
|||
void ConfigureInput::retranslateUi() {
|
||||
ui->retranslateUi(this);
|
||||
}
|
||||
|
||||
void ConfigureInput::NewProfile() {
|
||||
const 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.current_input_profile_index);
|
||||
loadConfiguration();
|
||||
ui->buttonDelete->setEnabled(ui->profile->count() > 1);
|
||||
}
|
||||
|
||||
void ConfigureInput::DeleteProfile() {
|
||||
const auto answer = QMessageBox::question(
|
||||
this, tr("Delete Profile"), tr("Delete profile %1?").arg(ui->profile->currentText()));
|
||||
if (answer != QMessageBox::Yes) {
|
||||
return;
|
||||
}
|
||||
const int index = ui->profile->currentIndex();
|
||||
ui->profile->removeItem(index);
|
||||
ui->profile->setCurrentIndex(0);
|
||||
Settings::DeleteProfile(index);
|
||||
loadConfiguration();
|
||||
ui->buttonDelete->setEnabled(ui->profile->count() > 1);
|
||||
}
|
||||
|
||||
void ConfigureInput::RenameProfile() {
|
||||
const 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());
|
||||
}
|
||||
|
|
|
@ -39,6 +39,9 @@ public:
|
|||
/// Load configuration settings.
|
||||
void loadConfiguration();
|
||||
|
||||
// Save the current input profile index
|
||||
void ApplyProfile();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::ConfigureInput> ui;
|
||||
|
||||
|
@ -91,4 +94,9 @@ private:
|
|||
|
||||
/// Handle key press events.
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
|
||||
/// input profiles
|
||||
void NewProfile();
|
||||
void DeleteProfile();
|
||||
void RenameProfile();
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>370</width>
|
||||
<width>374</width>
|
||||
<height>595</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -14,6 +14,54 @@
|
|||
<string>ConfigureInput</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Profile</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="profile"/>
|
||||
</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>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonNew">
|
||||
<property name="text">
|
||||
<string>New</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonDelete">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonRename">
|
||||
<property name="text">
|
||||
<string>Rename</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_7">
|
||||
<item row="0" column="0">
|
||||
|
@ -28,35 +76,17 @@
|
|||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item row="1" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>A:</string>
|
||||
<string>Y:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonA">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>B:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonB">
|
||||
<widget class="QPushButton" name="buttonY">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
|
@ -82,17 +112,35 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item row="0" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Y:</string>
|
||||
<string>B:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonY">
|
||||
<widget class="QPushButton" name="buttonB">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>A:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonA">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
|
@ -289,50 +337,7 @@
|
|||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="buttonCircleAnalog">
|
||||
<property name="text">
|
||||
<string>Set Analog Stick</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_17">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>Left:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonCircleLeft">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_18">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_23">
|
||||
<property name="text">
|
||||
<string>Right:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonCircleRight">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="1" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_19">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_24">
|
||||
|
@ -350,7 +355,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="1" column="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_20">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_22">
|
||||
|
@ -368,6 +373,49 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_18">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_23">
|
||||
<property name="text">
|
||||
<string>Right:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonCircleRight">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="QPushButton" name="buttonCircleAnalog">
|
||||
<property name="text">
|
||||
<string>Set Analog Stick</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_17">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>Left:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonCircleLeft">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -590,6 +638,8 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
|
@ -692,6 +742,8 @@
|
|||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
|
@ -102,8 +102,8 @@ ConfigureMotionTouch::ConfigureMotionTouch(QWidget* parent)
|
|||
ConfigureMotionTouch::~ConfigureMotionTouch() = default;
|
||||
|
||||
void ConfigureMotionTouch::setConfiguration() {
|
||||
Common::ParamPackage motion_param(Settings::values.motion_device);
|
||||
Common::ParamPackage touch_param(Settings::values.touch_device);
|
||||
Common::ParamPackage motion_param(Settings::values.current_input_profile.motion_device);
|
||||
Common::ParamPackage touch_param(Settings::values.current_input_profile.touch_device);
|
||||
std::string motion_engine = motion_param.Get("engine", "motion_emu");
|
||||
std::string touch_engine = touch_param.Get("engine", "emu_window");
|
||||
|
||||
|
@ -118,9 +118,10 @@ void ConfigureMotionTouch::setConfiguration() {
|
|||
max_x = touch_param.Get("max_x", 1800);
|
||||
max_y = touch_param.Get("max_y", 850);
|
||||
|
||||
ui->udp_server->setText(QString::fromStdString(Settings::values.udp_input_address));
|
||||
ui->udp_port->setText(QString::number(Settings::values.udp_input_port));
|
||||
ui->udp_pad_index->setCurrentIndex(Settings::values.udp_pad_index);
|
||||
ui->udp_server->setText(
|
||||
QString::fromStdString(Settings::values.current_input_profile.udp_input_address));
|
||||
ui->udp_port->setText(QString::number(Settings::values.current_input_profile.udp_input_port));
|
||||
ui->udp_pad_index->setCurrentIndex(Settings::values.current_input_profile.udp_pad_index);
|
||||
}
|
||||
|
||||
void ConfigureMotionTouch::updateUiDisplay() {
|
||||
|
@ -265,11 +266,14 @@ void ConfigureMotionTouch::applyConfiguration() {
|
|||
touch_param.Set("max_y", max_y);
|
||||
}
|
||||
|
||||
Settings::values.motion_device = motion_param.Serialize();
|
||||
Settings::values.touch_device = touch_param.Serialize();
|
||||
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_pad_index = static_cast<u8>(ui->udp_pad_index->currentIndex());
|
||||
Settings::values.current_input_profile.motion_device = motion_param.Serialize();
|
||||
Settings::values.current_input_profile.touch_device = touch_param.Serialize();
|
||||
Settings::values.current_input_profile.udp_input_address = ui->udp_server->text().toStdString();
|
||||
Settings::values.current_input_profile.udp_input_port =
|
||||
static_cast<u16>(ui->udp_port->text().toInt());
|
||||
Settings::values.current_input_profile.udp_pad_index =
|
||||
static_cast<u8>(ui->udp_pad_index->currentIndex());
|
||||
Settings::SaveProfile(Settings::values.current_input_profile_index);
|
||||
InputCommon::ReloadInputDevices();
|
||||
|
||||
accept();
|
||||
|
|
|
@ -1326,6 +1326,8 @@ void GMainWindow::OnConfigure() {
|
|||
connect(&configureDialog, &ConfigureDialog::languageChanged, this,
|
||||
&GMainWindow::OnLanguageChanged);
|
||||
auto old_theme = UISettings::values.theme;
|
||||
const int old_input_profile_index = Settings::values.current_input_profile_index;
|
||||
const auto old_input_profiles = Settings::values.input_profiles;
|
||||
const bool old_discord_presence = UISettings::values.enable_discord_presence;
|
||||
auto result = configureDialog.exec();
|
||||
if (result == QDialog::Accepted) {
|
||||
|
@ -1338,6 +1340,9 @@ void GMainWindow::OnConfigure() {
|
|||
SyncMenuUISettings();
|
||||
game_list->RefreshGameDirectory();
|
||||
config->Save();
|
||||
} else {
|
||||
Settings::values.input_profiles = old_input_profiles;
|
||||
Settings::LoadProfile(old_input_profile_index);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,13 +59,17 @@ DirectionState GetStickDirectionState(s16 circle_pad_x, s16 circle_pad_y) {
|
|||
}
|
||||
|
||||
void Module::LoadInputDevices() {
|
||||
std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
|
||||
Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END,
|
||||
std::transform(Settings::values.current_input_profile.buttons.begin() +
|
||||
Settings::NativeButton::BUTTON_HID_BEGIN,
|
||||
Settings::values.current_input_profile.buttons.begin() +
|
||||
Settings::NativeButton::BUTTON_HID_END,
|
||||
buttons.begin(), Input::CreateDevice<Input::ButtonDevice>);
|
||||
circle_pad = Input::CreateDevice<Input::AnalogDevice>(
|
||||
Settings::values.analogs[Settings::NativeAnalog::CirclePad]);
|
||||
motion_device = Input::CreateDevice<Input::MotionDevice>(Settings::values.motion_device);
|
||||
touch_device = Input::CreateDevice<Input::TouchDevice>(Settings::values.touch_device);
|
||||
Settings::values.current_input_profile.analogs[Settings::NativeAnalog::CirclePad]);
|
||||
motion_device = Input::CreateDevice<Input::MotionDevice>(
|
||||
Settings::values.current_input_profile.motion_device);
|
||||
touch_device = Input::CreateDevice<Input::TouchDevice>(
|
||||
Settings::values.current_input_profile.touch_device);
|
||||
}
|
||||
|
||||
void Module::UpdatePadCallback(u64 userdata, s64 cycles_late) {
|
||||
|
|
|
@ -263,11 +263,11 @@ void ExtraHID::RequestInputDevicesReload() {
|
|||
|
||||
void ExtraHID::LoadInputDevices() {
|
||||
zl = Input::CreateDevice<Input::ButtonDevice>(
|
||||
Settings::values.buttons[Settings::NativeButton::ZL]);
|
||||
Settings::values.current_input_profile.buttons[Settings::NativeButton::ZL]);
|
||||
zr = Input::CreateDevice<Input::ButtonDevice>(
|
||||
Settings::values.buttons[Settings::NativeButton::ZR]);
|
||||
Settings::values.current_input_profile.buttons[Settings::NativeButton::ZR]);
|
||||
c_stick = Input::CreateDevice<Input::AnalogDevice>(
|
||||
Settings::values.analogs[Settings::NativeAnalog::CStick]);
|
||||
Settings::values.current_input_profile.analogs[Settings::NativeAnalog::CStick]);
|
||||
}
|
||||
|
||||
} // namespace Service::IR
|
||||
|
|
|
@ -35,11 +35,11 @@ static_assert(sizeof(SharedMem) == 0x98, "SharedMem has wrong size!");
|
|||
|
||||
void IR_RST::LoadInputDevices() {
|
||||
zl_button = Input::CreateDevice<Input::ButtonDevice>(
|
||||
Settings::values.buttons[Settings::NativeButton::ZL]);
|
||||
Settings::values.current_input_profile.buttons[Settings::NativeButton::ZL]);
|
||||
zr_button = Input::CreateDevice<Input::ButtonDevice>(
|
||||
Settings::values.buttons[Settings::NativeButton::ZR]);
|
||||
Settings::values.current_input_profile.buttons[Settings::NativeButton::ZR]);
|
||||
c_stick = Input::CreateDevice<Input::AnalogDevice>(
|
||||
Settings::values.analogs[Settings::NativeAnalog::CStick]);
|
||||
Settings::values.current_input_profile.analogs[Settings::NativeAnalog::CStick]);
|
||||
}
|
||||
|
||||
void IR_RST::UnloadInputDevices() {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <utility>
|
||||
#include "audio_core/dsp_interface.h"
|
||||
#include "core/core.h"
|
||||
#include "core/gdbstub/gdbstub.h"
|
||||
|
@ -101,4 +102,32 @@ void LogSettings() {
|
|||
LogSetting("Debugging_GdbstubPort", Settings::values.gdbstub_port);
|
||||
}
|
||||
|
||||
void LoadProfile(int index) {
|
||||
Settings::values.current_input_profile = Settings::values.input_profiles[index];
|
||||
Settings::values.current_input_profile_index = index;
|
||||
}
|
||||
|
||||
void SaveProfile(int index) {
|
||||
Settings::values.input_profiles[index] = Settings::values.current_input_profile;
|
||||
}
|
||||
|
||||
void CreateProfile(std::string name) {
|
||||
Settings::InputProfile profile = values.current_input_profile;
|
||||
profile.name = std::move(name);
|
||||
Settings::values.input_profiles.push_back(std::move(profile));
|
||||
Settings::values.current_input_profile_index =
|
||||
static_cast<int>(Settings::values.input_profiles.size()) - 1;
|
||||
Settings::LoadProfile(Settings::values.current_input_profile_index);
|
||||
}
|
||||
|
||||
void DeleteProfile(int index) {
|
||||
Settings::values.input_profiles.erase(Settings::values.input_profiles.begin() + index);
|
||||
Settings::LoadProfile(0);
|
||||
}
|
||||
|
||||
void RenameCurrentProfile(std::string new_name) {
|
||||
Settings::values.input_profiles[Settings::values.current_input_profile_index].name =
|
||||
std::move(new_name);
|
||||
}
|
||||
|
||||
} // namespace Settings
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <array>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/service/cam/cam.h"
|
||||
|
||||
|
@ -96,11 +97,8 @@ static const std::array<const char*, NumAnalogs> mapping = {{
|
|||
}};
|
||||
} // namespace NativeAnalog
|
||||
|
||||
struct Values {
|
||||
// CheckNew3DS
|
||||
bool is_new_3ds;
|
||||
|
||||
// Controls
|
||||
struct InputProfile {
|
||||
std::string name;
|
||||
std::array<std::string, NativeButton::NumButtons> buttons;
|
||||
std::array<std::string, NativeAnalog::NumAnalogs> analogs;
|
||||
std::string motion_device;
|
||||
|
@ -108,6 +106,16 @@ struct Values {
|
|||
std::string udp_input_address;
|
||||
u16 udp_input_port;
|
||||
u8 udp_pad_index;
|
||||
};
|
||||
|
||||
struct Values {
|
||||
// CheckNew3DS
|
||||
bool is_new_3ds;
|
||||
|
||||
// Controls
|
||||
InputProfile current_input_profile; ///< The current input profile
|
||||
int current_input_profile_index; ///< The current input profile index
|
||||
std::vector<InputProfile> input_profiles; ///< The list of input profiles
|
||||
|
||||
// Core
|
||||
bool use_cpu_jit;
|
||||
|
@ -182,4 +190,11 @@ static constexpr int REGION_VALUE_AUTO_SELECT = -1;
|
|||
|
||||
void Apply();
|
||||
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
|
||||
|
|
|
@ -71,8 +71,9 @@ private:
|
|||
State::State() {
|
||||
auto status = std::make_shared<DeviceStatus>();
|
||||
client =
|
||||
std::make_unique<Client>(status, Settings::values.udp_input_address,
|
||||
Settings::values.udp_input_port, Settings::values.udp_pad_index);
|
||||
std::make_unique<Client>(status, Settings::values.current_input_profile.udp_input_address,
|
||||
Settings::values.current_input_profile.udp_input_port,
|
||||
Settings::values.current_input_profile.udp_pad_index);
|
||||
|
||||
Input::RegisterFactory<Input::TouchDevice>("cemuhookudp",
|
||||
std::make_shared<UDPTouchFactory>(status));
|
||||
|
@ -86,8 +87,9 @@ State::~State() {
|
|||
}
|
||||
|
||||
void State::ReloadUDPClient() {
|
||||
client->ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port,
|
||||
Settings::values.udp_pad_index);
|
||||
client->ReloadSocket(Settings::values.current_input_profile.udp_input_address,
|
||||
Settings::values.current_input_profile.udp_input_port,
|
||||
Settings::values.current_input_profile.udp_pad_index);
|
||||
}
|
||||
|
||||
std::unique_ptr<State> Init() {
|
||||
|
|
Loading…
Reference in a new issue