diff --git a/src/citra/config.cpp b/src/citra/config.cpp index 3cd7bec88..563c3b953 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -71,6 +71,7 @@ static const std::array, 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] = diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp index dcbe18122..72c4b9917 100644 --- a/src/citra_qt/configuration/config.cpp +++ b/src/citra_qt/configuration/config.cpp @@ -50,45 +50,69 @@ const std::array, 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( + ReadSetting("udp_input_port", InputCommon::CemuhookUDP::DEFAULT_PORT).toInt()); + profile.udp_pad_index = static_cast(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( - ReadSetting("udp_input_port", InputCommon::CemuhookUDP::DEFAULT_PORT).toInt()); - Settings::values.udp_pad_index = static_cast(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"); diff --git a/src/citra_qt/configuration/configure_dialog.cpp b/src/citra_qt/configuration/configure_dialog.cpp index 3f13401f1..1d55f8934 100644 --- a/src/citra_qt/configuration/configure_dialog.cpp +++ b/src/citra_qt/configuration/configure_dialog.cpp @@ -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(); diff --git a/src/citra_qt/configuration/configure_input.cpp b/src/citra_qt/configuration/configure_input.cpp index b0cc53395..fdb0ef8d6 100644 --- a/src/citra_qt/configuration/configure_input.cpp +++ b/src/citra_qt/configuration/configure_input.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -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(&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()); +} diff --git a/src/citra_qt/configuration/configure_input.h b/src/citra_qt/configuration/configure_input.h index aa3cce7a5..7c4b02f7a 100644 --- a/src/citra_qt/configuration/configure_input.h +++ b/src/citra_qt/configuration/configure_input.h @@ -39,6 +39,9 @@ public: /// Load configuration settings. void loadConfiguration(); + // Save the current input profile index + void applyProfile(); + private: std::unique_ptr ui; @@ -91,4 +94,9 @@ private: /// Handle key press events. void keyPressEvent(QKeyEvent* event) override; + + /// input profiles + void newProfile(); + void deleteProfile(); + void renameProfile(); }; diff --git a/src/citra_qt/configuration/configure_input.ui b/src/citra_qt/configuration/configure_input.ui index 8421adf09..498e08b1d 100644 --- a/src/citra_qt/configuration/configure_input.ui +++ b/src/citra_qt/configuration/configure_input.ui @@ -6,8 +6,8 @@ 0 0 - 370 - 534 + 376 + 535 @@ -555,103 +555,155 @@ - + - - - - 0 - 0 - - - - - 0 - 0 - - - - - 0 - 0 - - - - Qt::LeftToRight - - - Motion / Touch... - - + + + + + Profile + + + + + + + + + + New + + + + + + + Delete + + + + + + + Rename + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 0 - 0 - - - - Qt::LeftToRight - - - Clear All - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 0 - 0 - - - - Qt::LeftToRight - - - Restore Defaults - - + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::LeftToRight + + + Motion / Touch... + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::LeftToRight + + + Clear All + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::LeftToRight + + + Restore Defaults + + + + diff --git a/src/citra_qt/configuration/configure_motion_touch.cpp b/src/citra_qt/configuration/configure_motion_touch.cpp index b1d04f0d2..494c5bd21 100644 --- a/src/citra_qt/configuration/configure_motion_touch.cpp +++ b/src/citra_qt/configuration/configure_motion_touch.cpp @@ -270,6 +270,7 @@ void ConfigureMotionTouch::applyConfiguration() { Settings::values.udp_input_address = ui->udp_server->text().toStdString(); Settings::values.udp_input_port = static_cast(ui->udp_port->text().toInt()); Settings::values.udp_pad_index = static_cast(ui->udp_pad_index->currentIndex()); + Settings::SaveProfile(Settings::values.profile); InputCommon::ReloadInputDevices(); accept(); diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 69d8636dc..f7206c93d 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -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); } } diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 8bdf5689b..ec7af5b5a 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #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(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 diff --git a/src/core/settings.h b/src/core/settings.h index 929db156c..e179b610d 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "common/common_types.h" #include "core/hle/service/cam/cam.h" @@ -92,11 +93,8 @@ static const std::array mapping = {{ }}; } // namespace NativeAnalog -struct Values { - // CheckNew3DS - bool is_new_3ds; - - // Controls +struct InputProfile { + std::string name; std::array buttons; std::array 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 buttons; + std::array 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 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