Browse Source
Merge pull request #4866 from Morph1984/mjolnir-p3-prod
Merge pull request #4866 from Morph1984/mjolnir-p3-prod
Project Mjölnir: Part 3 - Controller Profiles and Vibration Reworkremotes/1778439668340191200/nce_cpp
committed by
GitHub
69 changed files with 3352 additions and 1539 deletions
-
14dist/qt_themes/default/style.qss
-
86dist/qt_themes/qdarkstyle/style.qss
-
95dist/qt_themes/qdarkstyle_midnight_blue/style.qss
-
8src/core/frontend/applets/controller.cpp
-
2src/core/frontend/framebuffer_layout.cpp
-
9src/core/frontend/input.h
-
4src/core/hle/service/am/am.cpp
-
4src/core/hle/service/am/applets/controller.cpp
-
3src/core/hle/service/apm/controller.cpp
-
270src/core/hle/service/hid/controllers/npad.cpp
-
131src/core/hle/service/hid/controllers/npad.h
-
703src/core/hle/service/hid/hid.cpp
-
37src/core/hle/service/hid/hid.h
-
2src/core/hle/service/vi/vi.cpp
-
8src/core/settings.cpp
-
58src/core/settings.h
-
2src/core/telemetry_session.cpp
-
6src/input_common/gcadapter/gc_adapter.cpp
-
4src/input_common/gcadapter/gc_adapter.h
-
50src/input_common/gcadapter/gc_poller.cpp
-
11src/input_common/gcadapter/gc_poller.h
-
15src/input_common/main.cpp
-
138src/input_common/sdl/sdl_impl.cpp
-
2src/input_common/sdl/sdl_impl.h
-
21src/input_common/settings.cpp
-
35src/input_common/settings.h
-
2src/input_common/udp/client.cpp
-
11src/yuzu/CMakeLists.txt
-
20src/yuzu/aboutdialog.ui
-
154src/yuzu/applets/controller.cpp
-
19src/yuzu/applets/controller.h
-
49src/yuzu/applets/controller.ui
-
16src/yuzu/bootmanager.cpp
-
332src/yuzu/configuration/config.cpp
-
22src/yuzu/configuration/config.h
-
20src/yuzu/configuration/configure.ui
-
7src/yuzu/configuration/configure_debug_controller.cpp
-
9src/yuzu/configuration/configure_debug_controller.h
-
20src/yuzu/configuration/configure_debug_controller.ui
-
76src/yuzu/configuration/configure_input.cpp
-
14src/yuzu/configuration/configure_input.h
-
46src/yuzu/configuration/configure_input.ui
-
14src/yuzu/configuration/configure_input_advanced.cpp
-
2src/yuzu/configuration/configure_input_advanced.h
-
192src/yuzu/configuration/configure_input_advanced.ui
-
37src/yuzu/configuration/configure_input_dialog.cpp
-
38src/yuzu/configuration/configure_input_dialog.h
-
566src/yuzu/configuration/configure_input_player.cpp
-
49src/yuzu/configuration/configure_input_player.h
-
241src/yuzu/configuration/configure_input_player.ui
-
37src/yuzu/configuration/configure_input_profile_dialog.cpp
-
40src/yuzu/configuration/configure_input_profile_dialog.h
-
24src/yuzu/configuration/configure_input_profile_dialog.ui
-
10src/yuzu/configuration/configure_motion_touch.ui
-
46src/yuzu/configuration/configure_mouse_advanced.ui
-
3src/yuzu/configuration/configure_per_game.cpp
-
20src/yuzu/configuration/configure_per_game.ui
-
10src/yuzu/configuration/configure_touch_from_button.ui
-
22src/yuzu/configuration/configure_touchscreen_advanced.ui
-
146src/yuzu/configuration/configure_vibration.cpp
-
43src/yuzu/configuration/configure_vibration.h
-
546src/yuzu/configuration/configure_vibration.ui
-
131src/yuzu/configuration/input_profiles.cpp
-
32src/yuzu/configuration/input_profiles.h
-
56src/yuzu/main.cpp
-
1src/yuzu/main.h
-
27src/yuzu_cmd/config.cpp
-
8src/yuzu_cmd/default_ini.h
-
15src/yuzu_tester/config.cpp
703
src/core/hle/service/hid/hid.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,37 +0,0 @@ |
|||
// Copyright 2020 yuzu Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include "ui_configure_input_dialog.h"
|
|||
#include "yuzu/configuration/configure_input_dialog.h"
|
|||
|
|||
ConfigureInputDialog::ConfigureInputDialog(QWidget* parent, std::size_t max_players, |
|||
InputCommon::InputSubsystem* input_subsystem) |
|||
: QDialog(parent), ui(std::make_unique<Ui::ConfigureInputDialog>()), |
|||
input_widget(new ConfigureInput(this)) { |
|||
ui->setupUi(this); |
|||
|
|||
input_widget->Initialize(input_subsystem, max_players); |
|||
|
|||
ui->inputLayout->addWidget(input_widget); |
|||
|
|||
RetranslateUI(); |
|||
} |
|||
|
|||
ConfigureInputDialog::~ConfigureInputDialog() = default; |
|||
|
|||
void ConfigureInputDialog::ApplyConfiguration() { |
|||
input_widget->ApplyConfiguration(); |
|||
} |
|||
|
|||
void ConfigureInputDialog::changeEvent(QEvent* event) { |
|||
if (event->type() == QEvent::LanguageChange) { |
|||
RetranslateUI(); |
|||
} |
|||
|
|||
QDialog::changeEvent(event); |
|||
} |
|||
|
|||
void ConfigureInputDialog::RetranslateUI() { |
|||
ui->retranslateUi(this); |
|||
} |
|||
@ -1,38 +0,0 @@ |
|||
// Copyright 2020 yuzu Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include <memory> |
|||
#include <QDialog> |
|||
#include "yuzu/configuration/configure_input.h" |
|||
|
|||
class QPushButton; |
|||
|
|||
namespace InputCommon { |
|||
class InputSubsystem; |
|||
} |
|||
|
|||
namespace Ui { |
|||
class ConfigureInputDialog; |
|||
} |
|||
|
|||
class ConfigureInputDialog : public QDialog { |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
explicit ConfigureInputDialog(QWidget* parent, std::size_t max_players, |
|||
InputCommon::InputSubsystem* input_subsystem); |
|||
~ConfigureInputDialog() override; |
|||
|
|||
void ApplyConfiguration(); |
|||
|
|||
private: |
|||
void changeEvent(QEvent* event) override; |
|||
void RetranslateUI(); |
|||
|
|||
std::unique_ptr<Ui::ConfigureInputDialog> ui; |
|||
|
|||
ConfigureInput* input_widget; |
|||
}; |
|||
@ -0,0 +1,37 @@ |
|||
// Copyright 2020 yuzu Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include "ui_configure_input_profile_dialog.h"
|
|||
#include "yuzu/configuration/configure_input_player.h"
|
|||
#include "yuzu/configuration/configure_input_profile_dialog.h"
|
|||
|
|||
ConfigureInputProfileDialog::ConfigureInputProfileDialog( |
|||
QWidget* parent, InputCommon::InputSubsystem* input_subsystem, InputProfiles* profiles) |
|||
: QDialog(parent), ui(std::make_unique<Ui::ConfigureInputProfileDialog>()), |
|||
profile_widget(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles, false)) { |
|||
ui->setupUi(this); |
|||
|
|||
ui->controllerLayout->addWidget(profile_widget); |
|||
|
|||
connect(ui->clear_all_button, &QPushButton::clicked, this, |
|||
[this] { profile_widget->ClearAll(); }); |
|||
connect(ui->restore_defaults_button, &QPushButton::clicked, this, |
|||
[this] { profile_widget->RestoreDefaults(); }); |
|||
|
|||
RetranslateUI(); |
|||
} |
|||
|
|||
ConfigureInputProfileDialog::~ConfigureInputProfileDialog() = default; |
|||
|
|||
void ConfigureInputProfileDialog::changeEvent(QEvent* event) { |
|||
if (event->type() == QEvent::LanguageChange) { |
|||
RetranslateUI(); |
|||
} |
|||
|
|||
QDialog::changeEvent(event); |
|||
} |
|||
|
|||
void ConfigureInputProfileDialog::RetranslateUI() { |
|||
ui->retranslateUi(this); |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
// Copyright 2020 yuzu Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include <memory> |
|||
#include <QDialog> |
|||
|
|||
class QPushButton; |
|||
|
|||
class ConfigureInputPlayer; |
|||
|
|||
class InputProfiles; |
|||
|
|||
namespace InputCommon { |
|||
class InputSubsystem; |
|||
} |
|||
|
|||
namespace Ui { |
|||
class ConfigureInputProfileDialog; |
|||
} |
|||
|
|||
class ConfigureInputProfileDialog : public QDialog { |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
explicit ConfigureInputProfileDialog(QWidget* parent, |
|||
InputCommon::InputSubsystem* input_subsystem, |
|||
InputProfiles* profiles); |
|||
~ConfigureInputProfileDialog() override; |
|||
|
|||
private: |
|||
void changeEvent(QEvent* event) override; |
|||
void RetranslateUI(); |
|||
|
|||
std::unique_ptr<Ui::ConfigureInputProfileDialog> ui; |
|||
|
|||
ConfigureInputPlayer* profile_widget; |
|||
}; |
|||
@ -0,0 +1,146 @@ |
|||
// Copyright 2020 yuzu Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include <algorithm>
|
|||
#include <unordered_map>
|
|||
|
|||
#include <fmt/format.h>
|
|||
|
|||
#include "common/param_package.h"
|
|||
#include "core/settings.h"
|
|||
#include "ui_configure_vibration.h"
|
|||
#include "yuzu/configuration/configure_vibration.h"
|
|||
|
|||
ConfigureVibration::ConfigureVibration(QWidget* parent) |
|||
: QDialog(parent), ui(std::make_unique<Ui::ConfigureVibration>()) { |
|||
ui->setupUi(this); |
|||
|
|||
vibration_groupboxes = { |
|||
ui->vibrationGroupPlayer1, ui->vibrationGroupPlayer2, ui->vibrationGroupPlayer3, |
|||
ui->vibrationGroupPlayer4, ui->vibrationGroupPlayer5, ui->vibrationGroupPlayer6, |
|||
ui->vibrationGroupPlayer7, ui->vibrationGroupPlayer8, |
|||
}; |
|||
|
|||
vibration_spinboxes = { |
|||
ui->vibrationSpinPlayer1, ui->vibrationSpinPlayer2, ui->vibrationSpinPlayer3, |
|||
ui->vibrationSpinPlayer4, ui->vibrationSpinPlayer5, ui->vibrationSpinPlayer6, |
|||
ui->vibrationSpinPlayer7, ui->vibrationSpinPlayer8, |
|||
}; |
|||
|
|||
const auto& players = Settings::values.players.GetValue(); |
|||
|
|||
for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { |
|||
vibration_groupboxes[i]->setChecked(players[i].vibration_enabled); |
|||
vibration_spinboxes[i]->setValue(players[i].vibration_strength); |
|||
} |
|||
|
|||
ui->checkBoxAccurateVibration->setChecked( |
|||
Settings::values.enable_accurate_vibrations.GetValue()); |
|||
|
|||
if (!Settings::IsConfiguringGlobal()) { |
|||
ui->checkBoxAccurateVibration->setDisabled(true); |
|||
} |
|||
|
|||
RetranslateUI(); |
|||
} |
|||
|
|||
ConfigureVibration::~ConfigureVibration() = default; |
|||
|
|||
void ConfigureVibration::ApplyConfiguration() { |
|||
auto& players = Settings::values.players.GetValue(); |
|||
|
|||
for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { |
|||
players[i].vibration_enabled = vibration_groupboxes[i]->isChecked(); |
|||
players[i].vibration_strength = vibration_spinboxes[i]->value(); |
|||
} |
|||
|
|||
Settings::values.enable_accurate_vibrations.SetValue( |
|||
ui->checkBoxAccurateVibration->isChecked()); |
|||
} |
|||
|
|||
void ConfigureVibration::SetVibrationDevices(std::size_t player_index) { |
|||
using namespace Settings::NativeButton; |
|||
static constexpr std::array<std::array<Settings::NativeButton::Values, 6>, 2> buttons{{ |
|||
{DLeft, DUp, DRight, DDown, L, ZL}, // Left Buttons
|
|||
{A, B, X, Y, R, ZR}, // Right Buttons
|
|||
}}; |
|||
|
|||
auto& player = Settings::values.players.GetValue()[player_index]; |
|||
|
|||
for (std::size_t device_idx = 0; device_idx < buttons.size(); ++device_idx) { |
|||
std::unordered_map<std::string, int> params_count; |
|||
|
|||
for (const auto button_index : buttons[device_idx]) { |
|||
const auto& player_button = player.buttons[button_index]; |
|||
|
|||
if (params_count.find(player_button) != params_count.end()) { |
|||
++params_count[player_button]; |
|||
continue; |
|||
} |
|||
|
|||
params_count.insert_or_assign(player_button, 1); |
|||
} |
|||
|
|||
const auto it = std::max_element( |
|||
params_count.begin(), params_count.end(), |
|||
[](const auto& lhs, const auto& rhs) { return lhs.second < rhs.second; }); |
|||
|
|||
auto& vibration_param_str = player.vibrations[device_idx]; |
|||
vibration_param_str.clear(); |
|||
|
|||
if (it->first.empty()) { |
|||
continue; |
|||
} |
|||
|
|||
const auto param = Common::ParamPackage(it->first); |
|||
|
|||
const auto engine = param.Get("engine", ""); |
|||
const auto guid = param.Get("guid", ""); |
|||
const auto port = param.Get("port", ""); |
|||
|
|||
if (engine.empty() || engine == "keyboard" || engine == "mouse") { |
|||
continue; |
|||
} |
|||
|
|||
vibration_param_str += fmt::format("engine:{}", engine); |
|||
|
|||
if (!port.empty()) { |
|||
vibration_param_str += fmt::format(",port:{}", port); |
|||
} |
|||
if (!guid.empty()) { |
|||
vibration_param_str += fmt::format(",guid:{}", guid); |
|||
} |
|||
} |
|||
|
|||
if (player.vibrations[0] != player.vibrations[1]) { |
|||
return; |
|||
} |
|||
|
|||
if (!player.vibrations[0].empty() && |
|||
player.controller_type != Settings::ControllerType::RightJoycon) { |
|||
player.vibrations[1].clear(); |
|||
} else if (!player.vibrations[1].empty() && |
|||
player.controller_type == Settings::ControllerType::RightJoycon) { |
|||
player.vibrations[0].clear(); |
|||
} |
|||
} |
|||
|
|||
void ConfigureVibration::SetAllVibrationDevices() { |
|||
// Set vibration devices for all player indices including handheld
|
|||
for (std::size_t player_idx = 0; player_idx < NUM_PLAYERS + 1; ++player_idx) { |
|||
SetVibrationDevices(player_idx); |
|||
} |
|||
} |
|||
|
|||
void ConfigureVibration::changeEvent(QEvent* event) { |
|||
if (event->type() == QEvent::LanguageChange) { |
|||
RetranslateUI(); |
|||
} |
|||
|
|||
QDialog::changeEvent(event); |
|||
} |
|||
|
|||
void ConfigureVibration::RetranslateUI() { |
|||
ui->retranslateUi(this); |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
// Copyright 2020 yuzu Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include <array> |
|||
#include <memory> |
|||
#include <QDialog> |
|||
|
|||
class QGroupBox; |
|||
class QSpinBox; |
|||
|
|||
namespace Ui { |
|||
class ConfigureVibration; |
|||
} |
|||
|
|||
class ConfigureVibration : public QDialog { |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
explicit ConfigureVibration(QWidget* parent); |
|||
~ConfigureVibration() override; |
|||
|
|||
void ApplyConfiguration(); |
|||
|
|||
static void SetVibrationDevices(std::size_t player_index); |
|||
static void SetAllVibrationDevices(); |
|||
|
|||
private: |
|||
void changeEvent(QEvent* event) override; |
|||
void RetranslateUI(); |
|||
|
|||
std::unique_ptr<Ui::ConfigureVibration> ui; |
|||
|
|||
static constexpr std::size_t NUM_PLAYERS = 8; |
|||
|
|||
// Groupboxes encapsulating the vibration strength spinbox. |
|||
std::array<QGroupBox*, NUM_PLAYERS> vibration_groupboxes; |
|||
|
|||
// Spinboxes representing the vibration strength percentage. |
|||
std::array<QSpinBox*, NUM_PLAYERS> vibration_spinboxes; |
|||
}; |
|||
@ -0,0 +1,546 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<ui version="4.0"> |
|||
<class>ConfigureVibration</class> |
|||
<widget class="QDialog" name="ConfigureVibration"> |
|||
<property name="geometry"> |
|||
<rect> |
|||
<x>0</x> |
|||
<y>0</y> |
|||
<width>364</width> |
|||
<height>242</height> |
|||
</rect> |
|||
</property> |
|||
<property name="windowTitle"> |
|||
<string>Configure Vibration</string> |
|||
</property> |
|||
<property name="styleSheet"> |
|||
<string notr="true"/> |
|||
</property> |
|||
<layout class="QVBoxLayout"> |
|||
<item> |
|||
<widget class="QGroupBox" name="vibrationStrengthGroup"> |
|||
<property name="title"> |
|||
<string>Vibration</string> |
|||
</property> |
|||
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="0,0"> |
|||
<property name="leftMargin"> |
|||
<number>9</number> |
|||
</property> |
|||
<property name="topMargin"> |
|||
<number>9</number> |
|||
</property> |
|||
<property name="rightMargin"> |
|||
<number>9</number> |
|||
</property> |
|||
<property name="bottomMargin"> |
|||
<number>9</number> |
|||
</property> |
|||
<item> |
|||
<widget class="QWidget" name="player14Widget" native="true"> |
|||
<layout class="QHBoxLayout" name="horizontalLayout_4"> |
|||
<property name="leftMargin"> |
|||
<number>0</number> |
|||
</property> |
|||
<property name="topMargin"> |
|||
<number>0</number> |
|||
</property> |
|||
<property name="rightMargin"> |
|||
<number>0</number> |
|||
</property> |
|||
<property name="bottomMargin"> |
|||
<number>0</number> |
|||
</property> |
|||
<item> |
|||
<widget class="QGroupBox" name="vibrationGroupPlayer1"> |
|||
<property name="title"> |
|||
<string>Player 1</string> |
|||
</property> |
|||
<property name="checkable"> |
|||
<bool>true</bool> |
|||
</property> |
|||
<layout class="QHBoxLayout" name="horizontalLayout_8"> |
|||
<property name="leftMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="topMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="rightMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="bottomMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<item> |
|||
<widget class="QSpinBox" name="vibrationSpinPlayer1"> |
|||
<property name="minimumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>21</height> |
|||
</size> |
|||
</property> |
|||
<property name="maximumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>16777215</height> |
|||
</size> |
|||
</property> |
|||
<property name="suffix"> |
|||
<string>%</string> |
|||
</property> |
|||
<property name="minimum"> |
|||
<number>1</number> |
|||
</property> |
|||
<property name="maximum"> |
|||
<number>150</number> |
|||
</property> |
|||
<property name="value"> |
|||
<number>100</number> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<widget class="QGroupBox" name="vibrationGroupPlayer2"> |
|||
<property name="title"> |
|||
<string>Player 2</string> |
|||
</property> |
|||
<property name="checkable"> |
|||
<bool>true</bool> |
|||
</property> |
|||
<layout class="QHBoxLayout" name="horizontalLayout_9"> |
|||
<property name="leftMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="topMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="rightMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="bottomMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<item> |
|||
<widget class="QSpinBox" name="vibrationSpinPlayer2"> |
|||
<property name="minimumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>21</height> |
|||
</size> |
|||
</property> |
|||
<property name="maximumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>16777215</height> |
|||
</size> |
|||
</property> |
|||
<property name="suffix"> |
|||
<string>%</string> |
|||
</property> |
|||
<property name="minimum"> |
|||
<number>1</number> |
|||
</property> |
|||
<property name="maximum"> |
|||
<number>150</number> |
|||
</property> |
|||
<property name="value"> |
|||
<number>100</number> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<widget class="QGroupBox" name="vibrationGroupPlayer3"> |
|||
<property name="title"> |
|||
<string>Player 3</string> |
|||
</property> |
|||
<property name="checkable"> |
|||
<bool>true</bool> |
|||
</property> |
|||
<layout class="QHBoxLayout" name="horizontalLayout_10"> |
|||
<property name="leftMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="topMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="rightMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="bottomMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<item> |
|||
<widget class="QSpinBox" name="vibrationSpinPlayer3"> |
|||
<property name="minimumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>21</height> |
|||
</size> |
|||
</property> |
|||
<property name="maximumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>16777215</height> |
|||
</size> |
|||
</property> |
|||
<property name="suffix"> |
|||
<string>%</string> |
|||
</property> |
|||
<property name="minimum"> |
|||
<number>1</number> |
|||
</property> |
|||
<property name="maximum"> |
|||
<number>150</number> |
|||
</property> |
|||
<property name="value"> |
|||
<number>100</number> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<widget class="QGroupBox" name="vibrationGroupPlayer4"> |
|||
<property name="title"> |
|||
<string>Player 4</string> |
|||
</property> |
|||
<property name="checkable"> |
|||
<bool>true</bool> |
|||
</property> |
|||
<layout class="QHBoxLayout" name="horizontalLayout_11"> |
|||
<property name="leftMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="topMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="rightMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="bottomMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<item> |
|||
<widget class="QSpinBox" name="vibrationSpinPlayer4"> |
|||
<property name="minimumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>21</height> |
|||
</size> |
|||
</property> |
|||
<property name="maximumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>16777215</height> |
|||
</size> |
|||
</property> |
|||
<property name="suffix"> |
|||
<string>%</string> |
|||
</property> |
|||
<property name="minimum"> |
|||
<number>1</number> |
|||
</property> |
|||
<property name="maximum"> |
|||
<number>150</number> |
|||
</property> |
|||
<property name="value"> |
|||
<number>100</number> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<widget class="QWidget" name="player58Widget" native="true"> |
|||
<layout class="QHBoxLayout" name="horizontalLayout_6"> |
|||
<property name="leftMargin"> |
|||
<number>0</number> |
|||
</property> |
|||
<property name="topMargin"> |
|||
<number>0</number> |
|||
</property> |
|||
<property name="rightMargin"> |
|||
<number>0</number> |
|||
</property> |
|||
<property name="bottomMargin"> |
|||
<number>0</number> |
|||
</property> |
|||
<item> |
|||
<widget class="QGroupBox" name="vibrationGroupPlayer7"> |
|||
<property name="title"> |
|||
<string>Player 5</string> |
|||
</property> |
|||
<property name="checkable"> |
|||
<bool>true</bool> |
|||
</property> |
|||
<layout class="QHBoxLayout" name="horizontalLayout_14"> |
|||
<property name="leftMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="topMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="rightMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="bottomMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<item> |
|||
<widget class="QSpinBox" name="vibrationSpinPlayer7"> |
|||
<property name="minimumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>21</height> |
|||
</size> |
|||
</property> |
|||
<property name="maximumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>16777215</height> |
|||
</size> |
|||
</property> |
|||
<property name="suffix"> |
|||
<string>%</string> |
|||
</property> |
|||
<property name="minimum"> |
|||
<number>1</number> |
|||
</property> |
|||
<property name="maximum"> |
|||
<number>150</number> |
|||
</property> |
|||
<property name="value"> |
|||
<number>100</number> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<widget class="QGroupBox" name="vibrationGroupPlayer8"> |
|||
<property name="title"> |
|||
<string>Player 6</string> |
|||
</property> |
|||
<property name="checkable"> |
|||
<bool>true</bool> |
|||
</property> |
|||
<layout class="QHBoxLayout" name="horizontalLayout_15"> |
|||
<property name="leftMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="topMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="rightMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="bottomMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<item> |
|||
<widget class="QSpinBox" name="vibrationSpinPlayer8"> |
|||
<property name="minimumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>21</height> |
|||
</size> |
|||
</property> |
|||
<property name="maximumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>16777215</height> |
|||
</size> |
|||
</property> |
|||
<property name="suffix"> |
|||
<string>%</string> |
|||
</property> |
|||
<property name="minimum"> |
|||
<number>1</number> |
|||
</property> |
|||
<property name="maximum"> |
|||
<number>150</number> |
|||
</property> |
|||
<property name="value"> |
|||
<number>100</number> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<widget class="QGroupBox" name="vibrationGroupPlayer5"> |
|||
<property name="title"> |
|||
<string>Player 7</string> |
|||
</property> |
|||
<property name="checkable"> |
|||
<bool>true</bool> |
|||
</property> |
|||
<layout class="QHBoxLayout" name="horizontalLayout_12"> |
|||
<property name="leftMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="topMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="rightMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="bottomMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<item> |
|||
<widget class="QSpinBox" name="vibrationSpinPlayer5"> |
|||
<property name="minimumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>21</height> |
|||
</size> |
|||
</property> |
|||
<property name="maximumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>16777215</height> |
|||
</size> |
|||
</property> |
|||
<property name="suffix"> |
|||
<string>%</string> |
|||
</property> |
|||
<property name="minimum"> |
|||
<number>1</number> |
|||
</property> |
|||
<property name="maximum"> |
|||
<number>150</number> |
|||
</property> |
|||
<property name="value"> |
|||
<number>100</number> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<widget class="QGroupBox" name="vibrationGroupPlayer6"> |
|||
<property name="title"> |
|||
<string>Player 8</string> |
|||
</property> |
|||
<property name="checkable"> |
|||
<bool>true</bool> |
|||
</property> |
|||
<layout class="QHBoxLayout" name="horizontalLayout_13"> |
|||
<property name="leftMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="topMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="rightMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<property name="bottomMargin"> |
|||
<number>3</number> |
|||
</property> |
|||
<item> |
|||
<widget class="QSpinBox" name="vibrationSpinPlayer6"> |
|||
<property name="minimumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>21</height> |
|||
</size> |
|||
</property> |
|||
<property name="maximumSize"> |
|||
<size> |
|||
<width>68</width> |
|||
<height>16777215</height> |
|||
</size> |
|||
</property> |
|||
<property name="suffix"> |
|||
<string>%</string> |
|||
</property> |
|||
<property name="minimum"> |
|||
<number>1</number> |
|||
</property> |
|||
<property name="maximum"> |
|||
<number>150</number> |
|||
</property> |
|||
<property name="value"> |
|||
<number>100</number> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<widget class="QGroupBox" name="vibrationSettingsGroup"> |
|||
<property name="title"> |
|||
<string>Settings</string> |
|||
</property> |
|||
<layout class="QVBoxLayout" name="verticalLayout"> |
|||
<item> |
|||
<widget class="QCheckBox" name="checkBoxAccurateVibration"> |
|||
<property name="text"> |
|||
<string>Enable Accurate Vibration</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<spacer name="spacerVibration"> |
|||
<property name="orientation"> |
|||
<enum>Qt::Vertical</enum> |
|||
</property> |
|||
<property name="sizeHint" stdset="0"> |
|||
<size> |
|||
<width>167</width> |
|||
<height>55</height> |
|||
</size> |
|||
</property> |
|||
</spacer> |
|||
</item> |
|||
<item> |
|||
<widget class="QDialogButtonBox" name="buttonBoxVibration"> |
|||
<property name="standardButtons"> |
|||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
<resources/> |
|||
<connections> |
|||
<connection> |
|||
<sender>buttonBoxVibration</sender> |
|||
<signal>accepted()</signal> |
|||
<receiver>ConfigureVibration</receiver> |
|||
<slot>accept()</slot> |
|||
</connection> |
|||
<connection> |
|||
<sender>buttonBoxVibration</sender> |
|||
<signal>rejected()</signal> |
|||
<receiver>ConfigureVibration</receiver> |
|||
<slot>reject()</slot> |
|||
</connection> |
|||
</connections> |
|||
</ui> |
|||
@ -0,0 +1,131 @@ |
|||
// Copyright 2020 yuzu Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include <fmt/format.h>
|
|||
|
|||
#include "common/common_paths.h"
|
|||
#include "common/file_util.h"
|
|||
#include "yuzu/configuration/config.h"
|
|||
#include "yuzu/configuration/input_profiles.h"
|
|||
|
|||
namespace FS = Common::FS; |
|||
|
|||
namespace { |
|||
|
|||
bool ProfileExistsInFilesystem(std::string_view profile_name) { |
|||
return FS::Exists(fmt::format("{}input" DIR_SEP "{}.ini", |
|||
FS::GetUserPath(FS::UserPath::ConfigDir), profile_name)); |
|||
} |
|||
|
|||
bool IsINI(std::string_view filename) { |
|||
const std::size_t index = filename.rfind('.'); |
|||
|
|||
if (index == std::string::npos) { |
|||
return false; |
|||
} |
|||
|
|||
return filename.substr(index) == ".ini"; |
|||
} |
|||
|
|||
std::string GetNameWithoutExtension(const std::string& filename) { |
|||
const std::size_t index = filename.rfind('.'); |
|||
|
|||
if (index == std::string::npos) { |
|||
return filename; |
|||
} |
|||
|
|||
return filename.substr(0, index); |
|||
} |
|||
|
|||
} // namespace
|
|||
|
|||
InputProfiles::InputProfiles() { |
|||
const std::string input_profile_loc = |
|||
fmt::format("{}input", FS::GetUserPath(FS::UserPath::ConfigDir)); |
|||
|
|||
FS::ForeachDirectoryEntry( |
|||
nullptr, input_profile_loc, |
|||
[this](u64* entries_out, const std::string& directory, const std::string& filename) { |
|||
if (IsINI(filename) && IsProfileNameValid(GetNameWithoutExtension(filename))) { |
|||
map_profiles.insert_or_assign( |
|||
GetNameWithoutExtension(filename), |
|||
std::make_unique<Config>(GetNameWithoutExtension(filename), |
|||
Config::ConfigType::InputProfile)); |
|||
} |
|||
return true; |
|||
}); |
|||
} |
|||
|
|||
InputProfiles::~InputProfiles() = default; |
|||
|
|||
std::vector<std::string> InputProfiles::GetInputProfileNames() { |
|||
std::vector<std::string> profile_names; |
|||
profile_names.reserve(map_profiles.size()); |
|||
|
|||
for (const auto& [profile_name, config] : map_profiles) { |
|||
if (!ProfileExistsInFilesystem(profile_name)) { |
|||
DeleteProfile(profile_name); |
|||
continue; |
|||
} |
|||
|
|||
profile_names.push_back(profile_name); |
|||
} |
|||
|
|||
return profile_names; |
|||
} |
|||
|
|||
bool InputProfiles::IsProfileNameValid(std::string_view profile_name) { |
|||
return profile_name.find_first_of("<>:;\"/\\|,.!?*") == std::string::npos; |
|||
} |
|||
|
|||
bool InputProfiles::CreateProfile(const std::string& profile_name, std::size_t player_index) { |
|||
if (ProfileExistsInMap(profile_name)) { |
|||
return false; |
|||
} |
|||
|
|||
map_profiles.insert_or_assign( |
|||
profile_name, std::make_unique<Config>(profile_name, Config::ConfigType::InputProfile)); |
|||
|
|||
return SaveProfile(profile_name, player_index); |
|||
} |
|||
|
|||
bool InputProfiles::DeleteProfile(const std::string& profile_name) { |
|||
if (!ProfileExistsInMap(profile_name)) { |
|||
return false; |
|||
} |
|||
|
|||
if (!ProfileExistsInFilesystem(profile_name) || |
|||
FS::Delete(map_profiles[profile_name]->GetConfigFilePath())) { |
|||
map_profiles.erase(profile_name); |
|||
} |
|||
|
|||
return !ProfileExistsInMap(profile_name) && !ProfileExistsInFilesystem(profile_name); |
|||
} |
|||
|
|||
bool InputProfiles::LoadProfile(const std::string& profile_name, std::size_t player_index) { |
|||
if (!ProfileExistsInMap(profile_name)) { |
|||
return false; |
|||
} |
|||
|
|||
if (!ProfileExistsInFilesystem(profile_name)) { |
|||
map_profiles.erase(profile_name); |
|||
return false; |
|||
} |
|||
|
|||
map_profiles[profile_name]->ReadControlPlayerValue(player_index); |
|||
return true; |
|||
} |
|||
|
|||
bool InputProfiles::SaveProfile(const std::string& profile_name, std::size_t player_index) { |
|||
if (!ProfileExistsInMap(profile_name)) { |
|||
return false; |
|||
} |
|||
|
|||
map_profiles[profile_name]->SaveControlPlayerValue(player_index); |
|||
return true; |
|||
} |
|||
|
|||
bool InputProfiles::ProfileExistsInMap(const std::string& profile_name) const { |
|||
return map_profiles.find(profile_name) != map_profiles.end(); |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
// Copyright 2020 yuzu Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include <string> |
|||
#include <string_view> |
|||
#include <unordered_map> |
|||
|
|||
class Config; |
|||
|
|||
class InputProfiles { |
|||
|
|||
public: |
|||
explicit InputProfiles(); |
|||
virtual ~InputProfiles(); |
|||
|
|||
std::vector<std::string> GetInputProfileNames(); |
|||
|
|||
static bool IsProfileNameValid(std::string_view profile_name); |
|||
|
|||
bool CreateProfile(const std::string& profile_name, std::size_t player_index); |
|||
bool DeleteProfile(const std::string& profile_name); |
|||
bool LoadProfile(const std::string& profile_name, std::size_t player_index); |
|||
bool SaveProfile(const std::string& profile_name, std::size_t player_index); |
|||
|
|||
private: |
|||
bool ProfileExistsInMap(const std::string& profile_name) const; |
|||
|
|||
std::unordered_map<std::string, std::unique_ptr<Config>> map_profiles; |
|||
}; |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue