Add multiple input profile support
Only supported in the Qt frontend.
This commit is contained in:
		@@ -71,6 +71,7 @@ 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] =
 | 
			
		||||
 
 | 
			
		||||
@@ -50,45 +50,69 @@ const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config:
 | 
			
		||||
 | 
			
		||||
void Config::ReadValues() {
 | 
			
		||||
    qt_config->beginGroup("Controls");
 | 
			
		||||
    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))
 | 
			
		||||
 | 
			
		||||
    Settings::values.profile = 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]);
 | 
			
		||||
            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()
 | 
			
		||||
                .toStdString();
 | 
			
		||||
        if (Settings::values.buttons[i].empty())
 | 
			
		||||
            Settings::values.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.touch_device =
 | 
			
		||||
            ReadSetting("touch_device", "engine:emu_window").toString().toStdString();
 | 
			
		||||
        profile.udp_input_address =
 | 
			
		||||
            ReadSetting("udp_input_address", InputCommon::CemuhookUDP::DEFAULT_ADDR)
 | 
			
		||||
                .toString()
 | 
			
		||||
                .toStdString();
 | 
			
		||||
        if (Settings::values.analogs[i].empty())
 | 
			
		||||
            Settings::values.analogs[i] = default_param;
 | 
			
		||||
        profile.udp_input_port = static_cast<u16>(
 | 
			
		||||
            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 =
 | 
			
		||||
        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();
 | 
			
		||||
    qt_config->endArray();
 | 
			
		||||
 | 
			
		||||
    Settings::values.udp_input_address =
 | 
			
		||||
        ReadSetting("udp_input_address", InputCommon::CemuhookUDP::DEFAULT_ADDR)
 | 
			
		||||
            .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());
 | 
			
		||||
    if (Settings::values.profile <= size) {
 | 
			
		||||
        Settings::values.profile = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qt_config->endGroup();
 | 
			
		||||
    if (size == 0) {
 | 
			
		||||
        append_profile();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Settings::LoadProfile(Settings::values.profile);
 | 
			
		||||
 | 
			
		||||
    qt_config->endArray();
 | 
			
		||||
 | 
			
		||||
    qt_config->beginGroup("Core");
 | 
			
		||||
    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_deepscan =
 | 
			
		||||
        ReadSetting("gameListDeepScan", false).toBool();
 | 
			
		||||
    int size = qt_config->beginReadArray("gamedirs");
 | 
			
		||||
    size = qt_config->beginReadArray("gamedirs");
 | 
			
		||||
    for (int i = 0; i < size; ++i) {
 | 
			
		||||
        qt_config->setArrayIndex(i);
 | 
			
		||||
        UISettings::GameDir game_dir;
 | 
			
		||||
@@ -267,8 +291,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";
 | 
			
		||||
@@ -352,29 +376,36 @@ void Config::ReadValues() {
 | 
			
		||||
 | 
			
		||||
void Config::SaveValues() {
 | 
			
		||||
    qt_config->beginGroup("Controls");
 | 
			
		||||
    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(default_param));
 | 
			
		||||
    WriteSetting("profile", Settings::values.profile, 0);
 | 
			
		||||
    qt_config->beginWriteArray("profiles");
 | 
			
		||||
    for (int p = 0; p < Settings::values.profiles.size(); ++p) {
 | 
			
		||||
        qt_config->setArrayIndex(p);
 | 
			
		||||
        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) {
 | 
			
		||||
        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->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>
 | 
			
		||||
@@ -99,6 +100,12 @@ ConfigureInput::ConfigureInput(QWidget* parent)
 | 
			
		||||
    ui->setupUi(this);
 | 
			
		||||
    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 = {
 | 
			
		||||
        ui->buttonA,        ui->buttonB,        ui->buttonX,         ui->buttonY,  ui->buttonDpadUp,
 | 
			
		||||
        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, [=]() {
 | 
			
		||||
            handleClick(
 | 
			
		||||
                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);
 | 
			
		||||
        });
 | 
			
		||||
        connect(button_map[button_id], &QPushButton::customContextMenuRequested,
 | 
			
		||||
@@ -140,11 +151,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));
 | 
			
		||||
                });
 | 
			
		||||
@@ -157,12 +172,15 @@ ConfigureInput::ConfigureInput(QWidget* parent)
 | 
			
		||||
            analog_map_buttons[analog_id][sub_button_id]->setContextMenuPolicy(
 | 
			
		||||
                Qt::CustomContextMenu);
 | 
			
		||||
            connect(analog_map_buttons[analog_id][sub_button_id], &QPushButton::released, [=]() {
 | 
			
		||||
                handleClick(analog_map_buttons[analog_id][sub_button_id],
 | 
			
		||||
                            [=](const Common::ParamPackage& params) {
 | 
			
		||||
                                SetAnalogButton(params, analogs_param[analog_id],
 | 
			
		||||
                                                analog_sub_buttons[sub_button_id]);
 | 
			
		||||
                            },
 | 
			
		||||
                            InputCommon::Polling::DeviceType::Button);
 | 
			
		||||
                handleClick(
 | 
			
		||||
                    analog_map_buttons[analog_id][sub_button_id],
 | 
			
		||||
                    [=](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);
 | 
			
		||||
            });
 | 
			
		||||
            connect(analog_map_buttons[analog_id][sub_button_id],
 | 
			
		||||
                    &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) {
 | 
			
		||||
@@ -170,6 +188,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(
 | 
			
		||||
@@ -178,6 +198,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,7 +211,11 @@ ConfigureInput::ConfigureInput(QWidget* parent)
 | 
			
		||||
                                        "and then vertically."));
 | 
			
		||||
            handleClick(
 | 
			
		||||
                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);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
@@ -200,6 +226,17 @@ ConfigureInput::ConfigureInput(QWidget* parent)
 | 
			
		||||
    });
 | 
			
		||||
    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.profile);
 | 
			
		||||
                Settings::LoadProfile(i);
 | 
			
		||||
                loadConfiguration();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
    timeout_timer->setSingleShot(true);
 | 
			
		||||
    connect(timeout_timer.get(), &QTimer::timeout, [this]() { setPollingResult({}, true); });
 | 
			
		||||
@@ -230,6 +267,10 @@ void ConfigureInput::applyConfiguration() {
 | 
			
		||||
                   [](const Common::ParamPackage& param) { return param.Serialize(); });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ConfigureInput::applyProfile() {
 | 
			
		||||
    Settings::values.profile = ui->profile->currentIndex();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ConfigureInput::loadConfiguration() {
 | 
			
		||||
    std::transform(Settings::values.buttons.begin(), Settings::values.buttons.end(),
 | 
			
		||||
                   buttons_param.begin(),
 | 
			
		||||
@@ -346,3 +387,43 @@ void ConfigureInput::keyPressEvent(QKeyEvent* event) {
 | 
			
		||||
void ConfigureInput::retranslateUi() {
 | 
			
		||||
    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());
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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,8 +6,8 @@
 | 
			
		||||
   <rect>
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>370</width>
 | 
			
		||||
    <height>534</height>
 | 
			
		||||
    <width>376</width>
 | 
			
		||||
    <height>535</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowTitle">
 | 
			
		||||
@@ -555,103 +555,155 @@
 | 
			
		||||
    </layout>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <layout class="QHBoxLayout" name="horizontalLayout">
 | 
			
		||||
    <layout class="QVBoxLayout" name="verticalLayout_6">
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QPushButton" name="buttonMotionTouch">
 | 
			
		||||
       <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>Motion / Touch...</string>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
      <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>
 | 
			
		||||
        <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>
 | 
			
		||||
       <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>
 | 
			
		||||
      <spacer name="horizontalSpacer">
 | 
			
		||||
       <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="buttonClearAll">
 | 
			
		||||
       <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>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>
 | 
			
		||||
      <layout class="QHBoxLayout" name="horizontalLayout">
 | 
			
		||||
       <item>
 | 
			
		||||
        <widget class="QPushButton" name="buttonMotionTouch">
 | 
			
		||||
         <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>Motion / Touch...</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item>
 | 
			
		||||
        <spacer name="horizontalSpacer">
 | 
			
		||||
         <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="buttonClearAll">
 | 
			
		||||
         <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>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>
 | 
			
		||||
    </layout>
 | 
			
		||||
   </item>
 | 
			
		||||
 
 | 
			
		||||
@@ -270,6 +270,7 @@ void ConfigureMotionTouch::applyConfiguration() {
 | 
			
		||||
    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::SaveProfile(Settings::values.profile);
 | 
			
		||||
    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_profile = Settings::values.profile;
 | 
			
		||||
    auto old_profiles = Settings::values.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.profiles = old_profiles;
 | 
			
		||||
        Settings::LoadProfile(old_profile);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
@@ -99,4 +100,51 @@ void LogSettings() {
 | 
			
		||||
    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
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 | 
			
		||||
@@ -92,11 +93,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;
 | 
			
		||||
@@ -104,6 +102,23 @@ struct Values {
 | 
			
		||||
    std::string udp_input_address;
 | 
			
		||||
    u16 udp_input_port;
 | 
			
		||||
    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
 | 
			
		||||
    bool use_cpu_jit;
 | 
			
		||||
@@ -176,4 +191,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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user