mirror of https://git.suyu.dev/suyu/suyu
Merge pull request #4866 from Morph1984/mjolnir-p3-prod
Project Mjölnir: Part 3 - Controller Profiles and Vibration Rework
This commit is contained in:
commit
abda366362
|
@ -1,3 +1,7 @@
|
|||
QAbstractSpinBox {
|
||||
min-height: 19px;
|
||||
}
|
||||
|
||||
QPushButton#TogglableStatusBarButton {
|
||||
color: #959595;
|
||||
border: 1px solid transparent;
|
||||
|
@ -35,10 +39,10 @@ QPushButton#RendererStatusBarButton:!checked {
|
|||
}
|
||||
|
||||
QPushButton#buttonRefreshDevices {
|
||||
min-width: 20px;
|
||||
min-height: 20px;
|
||||
max-width: 20px;
|
||||
max-height: 20px;
|
||||
min-width: 21px;
|
||||
min-height: 21px;
|
||||
max-width: 21px;
|
||||
max-height: 21px;
|
||||
}
|
||||
|
||||
QWidget#bottomPerGameInput,
|
||||
|
@ -71,7 +75,7 @@ QWidget#middleControllerApplet {
|
|||
|
||||
QWidget#topPerGameInput QComboBox,
|
||||
QWidget#middleControllerApplet QComboBox {
|
||||
width: 123px;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
QWidget#connectedControllers {
|
||||
|
|
|
@ -99,12 +99,19 @@ QGroupBox::indicator:unchecked:disabled {
|
|||
}
|
||||
|
||||
QRadioButton {
|
||||
spacing: 5px;
|
||||
outline: none;
|
||||
color: #eff0f1;
|
||||
spacing: 3px;
|
||||
padding: 0px;
|
||||
border: none;
|
||||
outline: none;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
QGroupBox QRadioButton {
|
||||
padding-left: 0px;
|
||||
padding-right: 7px;
|
||||
}
|
||||
|
||||
QRadioButton:disabled {
|
||||
color: #76797C;
|
||||
}
|
||||
|
@ -522,13 +529,12 @@ QToolButton#qt_toolbar_ext_button {
|
|||
|
||||
QPushButton {
|
||||
color: #eff0f1;
|
||||
border-width: 1px;
|
||||
border-color: #54575B;
|
||||
border-style: solid;
|
||||
padding: 6px 4px;
|
||||
border: 1px solid #54575B;
|
||||
border-radius: 2px;
|
||||
padding: 5px 0px 5px 0px;
|
||||
outline: none;
|
||||
min-width: 100px;
|
||||
min-height: 13px;
|
||||
background-color: #232629;
|
||||
}
|
||||
|
||||
|
@ -553,8 +559,9 @@ QComboBox {
|
|||
selection-background-color: #3daee9;
|
||||
border: 1px solid #54575B;
|
||||
border-radius: 2px;
|
||||
padding: 4px 6px;
|
||||
min-width: 75px;
|
||||
padding: 0px 4px 0px 4px;
|
||||
min-width: 60px;
|
||||
min-height: 23px;
|
||||
background-color: #232629;
|
||||
}
|
||||
|
||||
|
@ -608,26 +615,26 @@ QComboBox::down-arrow:focus {
|
|||
}
|
||||
|
||||
QAbstractSpinBox {
|
||||
padding: 4px 6px;
|
||||
border: 1px solid #54575B;
|
||||
background-color: #232629;
|
||||
color: #eff0f1;
|
||||
border-radius: 2px;
|
||||
min-width: 75px;
|
||||
min-width: 52px;
|
||||
min-height: 23px;
|
||||
}
|
||||
|
||||
QAbstractSpinBox:up-button {
|
||||
background-color: transparent;
|
||||
subcontrol-origin: border;
|
||||
subcontrol-position: center right;
|
||||
left: -6px;
|
||||
left: -2px;
|
||||
}
|
||||
|
||||
QAbstractSpinBox:down-button {
|
||||
background-color: transparent;
|
||||
subcontrol-origin: border;
|
||||
subcontrol-position: center left;
|
||||
right: -6px;
|
||||
right: -2px;
|
||||
}
|
||||
|
||||
QAbstractSpinBox::up-arrow,
|
||||
|
@ -1277,41 +1284,33 @@ QPushButton#RendererStatusBarButton:!checked {
|
|||
}
|
||||
|
||||
QPushButton#buttonRefreshDevices {
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
max-width: 24px;
|
||||
max-height: 24px;
|
||||
min-width: 23px;
|
||||
min-height: 23px;
|
||||
max-width: 23px;
|
||||
max-height: 23px;
|
||||
padding: 0px 0px;
|
||||
}
|
||||
|
||||
QSpinBox#spinboxLStickRange,
|
||||
QSpinBox#spinboxRStickRange {
|
||||
padding: 4px 0px 5px 0px;
|
||||
min-width: 63px;
|
||||
}
|
||||
|
||||
QSpinBox#vibrationSpin {
|
||||
padding: 4px 0px 5px 0px;
|
||||
min-width: 63px;
|
||||
}
|
||||
|
||||
QSpinBox#spinboxLStickRange:up-button,
|
||||
QSpinBox#spinboxRStickRange:up-button,
|
||||
QSpinBox#vibrationSpin:up-button {
|
||||
left: -2px;
|
||||
}
|
||||
|
||||
QSpinBox#spinboxLStickRange:down-button,
|
||||
QSpinBox#spinboxRStickRange:down-button,
|
||||
QSpinBox#vibrationSpin:down-button {
|
||||
right: -1px;
|
||||
QSpinBox#spinboxRStickRange,
|
||||
QSpinBox#vibrationSpinPlayer1,
|
||||
QSpinBox#vibrationSpinPlayer2,
|
||||
QSpinBox#vibrationSpinPlayer3,
|
||||
QSpinBox#vibrationSpinPlayer4,
|
||||
QSpinBox#vibrationSpinPlayer5,
|
||||
QSpinBox#vibrationSpinPlayer6,
|
||||
QSpinBox#vibrationSpinPlayer7,
|
||||
QSpinBox#vibrationSpinPlayer8 {
|
||||
min-width: 68px;
|
||||
}
|
||||
|
||||
QDialog#ConfigureVibration QGroupBox::indicator,
|
||||
QGroupBox#motionGroup::indicator,
|
||||
QGroupBox#vibrationGroup::indicator {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
QDialog#ConfigureVibration QGroupBox::title,
|
||||
QGroupBox#motionGroup::title,
|
||||
QGroupBox#vibrationGroup::title {
|
||||
spacing: 2px;
|
||||
|
@ -1340,16 +1339,7 @@ QWidget#middleControllerApplet {
|
|||
|
||||
QWidget#topPerGameInput QComboBox,
|
||||
QWidget#middleControllerApplet QComboBox {
|
||||
width: 119px;
|
||||
}
|
||||
|
||||
QRadioButton#radioDocked {
|
||||
margin-left: -3px;
|
||||
}
|
||||
|
||||
|
||||
QRadioButton#radioUndocked {
|
||||
margin-right: 5px;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
QWidget#connectedControllers {
|
||||
|
|
|
@ -172,8 +172,8 @@ QCheckBox {
|
|||
color: #F0F0F0;
|
||||
spacing: 4px;
|
||||
outline: none;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
QCheckBox:focus {
|
||||
|
@ -239,7 +239,7 @@ QGroupBox {
|
|||
border: 1px solid #32414B;
|
||||
border-radius: 4px;
|
||||
margin-top: 12px;
|
||||
padding: 4px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
QGroupBox::title {
|
||||
|
@ -247,7 +247,7 @@ QGroupBox::title {
|
|||
subcontrol-position: top left;
|
||||
padding-left: 3px;
|
||||
padding-right: 5px;
|
||||
padding-top: 4px;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
QGroupBox::indicator {
|
||||
|
@ -298,6 +298,11 @@ QRadioButton {
|
|||
outline: none;
|
||||
}
|
||||
|
||||
QGroupBox QRadioButton {
|
||||
padding-left: 0px;
|
||||
padding-right: 7px;
|
||||
}
|
||||
|
||||
QRadioButton:focus {
|
||||
border: none;
|
||||
}
|
||||
|
@ -321,7 +326,6 @@ QRadioButton QWidget {
|
|||
QRadioButton::indicator {
|
||||
border: none;
|
||||
outline: none;
|
||||
margin-left: 4px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
@ -785,14 +789,8 @@ QAbstractSpinBox {
|
|||
background-color: #19232D;
|
||||
border: 1px solid #32414B;
|
||||
color: #F0F0F0;
|
||||
/* This fixes 103, 111 */
|
||||
padding-top: 2px;
|
||||
/* This fixes 103, 111 */
|
||||
padding-bottom: 2px;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
border-radius: 4px;
|
||||
/* min-width: 5px; removed to fix 109 */
|
||||
min-height: 19px;
|
||||
}
|
||||
|
||||
QAbstractSpinBox:up-button {
|
||||
|
@ -997,10 +995,11 @@ QPushButton {
|
|||
border: 1px solid #32414B;
|
||||
color: #F0F0F0;
|
||||
border-radius: 4px;
|
||||
padding: 3px;
|
||||
padding: 3px 0px 3px 0px;
|
||||
outline: none;
|
||||
/* Issue #194 - Special case of QPushButton inside dialogs, for better UI */
|
||||
min-width: 80px;
|
||||
min-height: 13px;
|
||||
}
|
||||
|
||||
QPushButton:disabled {
|
||||
|
@ -1008,14 +1007,14 @@ QPushButton:disabled {
|
|||
border: 1px solid #32414B;
|
||||
color: #787878;
|
||||
border-radius: 4px;
|
||||
padding: 3px;
|
||||
padding: 3px 0px 3px 0px;
|
||||
}
|
||||
|
||||
QPushButton:checked {
|
||||
background-color: #32414B;
|
||||
border: 1px solid #32414B;
|
||||
border-radius: 4px;
|
||||
padding: 3px;
|
||||
padding: 3px 0px 3px 0px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
|
@ -1024,7 +1023,7 @@ QPushButton:checked:disabled {
|
|||
border: 1px solid #32414B;
|
||||
color: #787878;
|
||||
border-radius: 4px;
|
||||
padding: 3px;
|
||||
padding: 3px 0px 3px 0px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
|
@ -1197,15 +1196,9 @@ QComboBox {
|
|||
border: 1px solid #32414B;
|
||||
border-radius: 4px;
|
||||
selection-background-color: #1464A0;
|
||||
padding-left: 4px;
|
||||
padding-right: 36px;
|
||||
/* 4 + 16*2 See scrollbar size */
|
||||
/* Fixes #103, #111 */
|
||||
min-height: 1.5em;
|
||||
/* padding-top: 2px; removed to fix #132 */
|
||||
/* padding-bottom: 2px; removed to fix #132 */
|
||||
/* min-width: 75px; removed to fix #109 */
|
||||
/* Needed to remove indicator - fix #132 */
|
||||
padding: 0px 4px 0px 4px;
|
||||
min-width: 60px;
|
||||
min-height: 19px;
|
||||
}
|
||||
|
||||
QComboBox QAbstractItemView {
|
||||
|
@ -2198,29 +2191,40 @@ QPushButton#RendererStatusBarButton:!checked {
|
|||
}
|
||||
|
||||
QPushButton#buttonRefreshDevices {
|
||||
min-width: 20px;
|
||||
min-height: 20px;
|
||||
max-width: 20px;
|
||||
max-height: 20px;
|
||||
min-width: 19px;
|
||||
min-height: 19px;
|
||||
max-width: 19px;
|
||||
max-height: 19px;
|
||||
padding: 0px 0px;
|
||||
}
|
||||
|
||||
QSpinBox#spinboxLStickRange,
|
||||
QSpinBox#spinboxRStickRange {
|
||||
min-width: 38px;
|
||||
QSpinBox#spinboxRStickRange,
|
||||
QSpinBox#vibrationSpinPlayer1,
|
||||
QSpinBox#vibrationSpinPlayer2,
|
||||
QSpinBox#vibrationSpinPlayer3,
|
||||
QSpinBox#vibrationSpinPlayer4,
|
||||
QSpinBox#vibrationSpinPlayer5,
|
||||
QSpinBox#vibrationSpinPlayer6,
|
||||
QSpinBox#vibrationSpinPlayer7,
|
||||
QSpinBox#vibrationSpinPlayer8 {
|
||||
min-width: 68px;
|
||||
}
|
||||
|
||||
QDialog#ConfigureVibration QGroupBox::indicator,
|
||||
QGroupBox#motionGroup::indicator,
|
||||
QGroupBox#vibrationGroup::indicator {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
QDialog#ConfigureVibration QGroupBox,
|
||||
QWidget#bottomPerGameInput QGroupBox#motionGroup,
|
||||
QWidget#bottomPerGameInput QGroupBox#vibrationGroup,
|
||||
QWidget#bottomPerGameInput QGroupBox#inputConfigGroup {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
QDialog#ConfigureVibration QGroupBox::title,
|
||||
QGroupBox#motionGroup::title,
|
||||
QGroupBox#vibrationGroup::title {
|
||||
spacing: 2px;
|
||||
|
@ -2260,26 +2264,7 @@ QWidget#middleControllerApplet {
|
|||
|
||||
QWidget#topPerGameInput QComboBox,
|
||||
QWidget#middleControllerApplet QComboBox {
|
||||
padding-right: 2px;
|
||||
width: 127px;
|
||||
}
|
||||
|
||||
QGroupBox#handheldGroup {
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
QRadioButton#radioDocked {
|
||||
margin-left: -1px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
QRadioButton#radioDocked::indicator {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
|
||||
QRadioButton#radioUndocked {
|
||||
margin-right: 2px;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
QWidget#connectedControllers {
|
||||
|
@ -2352,7 +2337,7 @@ QCheckBox#checkboxPlayer5Connected,
|
|||
QCheckBox#checkboxPlayer6Connected,
|
||||
QCheckBox#checkboxPlayer7Connected,
|
||||
QCheckBox#checkboxPlayer8Connected {
|
||||
spacing: 0px;
|
||||
spacing: 0px;
|
||||
}
|
||||
|
||||
QWidget#connectedControllers QLabel {
|
||||
|
@ -2427,7 +2412,7 @@ QCheckBox#checkboxPlayer7Connected::indicator,
|
|||
QCheckBox#checkboxPlayer8Connected::indicator {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin-left: 2px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
QWidget#Player1LEDs QCheckBox::indicator:checked,
|
||||
|
|
|
@ -27,19 +27,19 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
|
|||
->GetAppletResource()
|
||||
->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad);
|
||||
|
||||
auto& players = Settings::values.players;
|
||||
auto& players = Settings::values.players.GetValue();
|
||||
|
||||
const std::size_t min_supported_players =
|
||||
parameters.enable_single_mode ? 1 : parameters.min_players;
|
||||
|
||||
// Disconnect Handheld first.
|
||||
npad.DisconnectNPadAtIndex(8);
|
||||
npad.DisconnectNpadAtIndex(8);
|
||||
|
||||
// Deduce the best configuration based on the input parameters.
|
||||
for (std::size_t index = 0; index < players.size() - 2; ++index) {
|
||||
// First, disconnect all controllers regardless of the value of keep_controllers_connected.
|
||||
// This makes it easy to connect the desired controllers.
|
||||
npad.DisconnectNPadAtIndex(index);
|
||||
npad.DisconnectNpadAtIndex(index);
|
||||
|
||||
// Only connect the minimum number of required players.
|
||||
if (index >= min_supported_players) {
|
||||
|
@ -66,7 +66,7 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
|
|||
npad.MapSettingsTypeToNPad(Settings::ControllerType::RightJoycon), index);
|
||||
}
|
||||
} else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld &&
|
||||
!Settings::values.use_docked_mode) {
|
||||
!Settings::values.use_docked_mode.GetValue()) {
|
||||
// We should *never* reach here under any normal circumstances.
|
||||
npad.AddNewControllerAt(npad.MapSettingsTypeToNPad(Settings::ControllerType::Handheld),
|
||||
index);
|
||||
|
|
|
@ -47,7 +47,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) {
|
|||
FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) {
|
||||
u32 width, height;
|
||||
|
||||
if (Settings::values.use_docked_mode) {
|
||||
if (Settings::values.use_docked_mode.GetValue()) {
|
||||
width = ScreenDocked::Width * res_scale;
|
||||
height = ScreenDocked::Height * res_scale;
|
||||
} else {
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const {
|
||||
return {};
|
||||
}
|
||||
virtual bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const {
|
||||
virtual bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
@ -121,6 +121,13 @@ using ButtonDevice = InputDevice<bool>;
|
|||
*/
|
||||
using AnalogDevice = InputDevice<std::tuple<float, float>>;
|
||||
|
||||
/**
|
||||
* A vibration device is an input device that returns an unsigned byte as status.
|
||||
* It represents whether the vibration device supports vibration or not.
|
||||
* If the status returns 1, it supports vibration. Otherwise, it does not support vibration.
|
||||
*/
|
||||
using VibrationDevice = InputDevice<u8>;
|
||||
|
||||
/**
|
||||
* A motion status is an object that returns a tuple of accelerometer state vector,
|
||||
* gyroscope state vector, rotation state vector and orientation state matrix.
|
||||
|
|
|
@ -751,7 +751,7 @@ void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext&
|
|||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
if (Settings::values.use_docked_mode) {
|
||||
if (Settings::values.use_docked_mode.GetValue()) {
|
||||
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) *
|
||||
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
|
||||
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) *
|
||||
|
@ -824,7 +824,7 @@ void IStorage::Open(Kernel::HLERequestContext& ctx) {
|
|||
}
|
||||
|
||||
void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
|
||||
const bool use_docked_mode{Settings::values.use_docked_mode};
|
||||
const bool use_docked_mode{Settings::values.use_docked_mode.GetValue()};
|
||||
LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Service::AM::Applets {
|
|||
static Core::Frontend::ControllerParameters ConvertToFrontendParameters(
|
||||
ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text,
|
||||
std::vector<IdentificationColor> identification_colors, std::vector<ExplainText> text) {
|
||||
HID::Controller_NPad::NPadType npad_style_set;
|
||||
HID::Controller_NPad::NpadStyleSet npad_style_set;
|
||||
npad_style_set.raw = private_arg.style_set;
|
||||
|
||||
return {
|
||||
|
@ -222,7 +222,7 @@ void Controller::Execute() {
|
|||
void Controller::ConfigurationComplete() {
|
||||
ControllerSupportResultInfo result_info{};
|
||||
|
||||
const auto& players = Settings::values.players;
|
||||
const auto& players = Settings::values.players.GetValue();
|
||||
|
||||
// If enable_single_mode is enabled, player_count is 1 regardless of any other parameters.
|
||||
// Otherwise, only count connected players from P1-P8.
|
||||
|
|
|
@ -69,7 +69,8 @@ void Controller::SetFromCpuBoostMode(CpuBoostMode mode) {
|
|||
}
|
||||
|
||||
PerformanceMode Controller::GetCurrentPerformanceMode() const {
|
||||
return Settings::values.use_docked_mode ? PerformanceMode::Docked : PerformanceMode::Handheld;
|
||||
return Settings::values.use_docked_mode.GetValue() ? PerformanceMode::Docked
|
||||
: PerformanceMode::Handheld;
|
||||
}
|
||||
|
||||
PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(PerformanceMode mode) {
|
||||
|
|
|
@ -117,7 +117,10 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) {
|
|||
}
|
||||
|
||||
Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {}
|
||||
Controller_NPad::~Controller_NPad() = default;
|
||||
|
||||
Controller_NPad::~Controller_NPad() {
|
||||
OnRelease();
|
||||
}
|
||||
|
||||
void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
|
||||
const auto controller_type = connected_controllers[controller_idx].type;
|
||||
|
@ -139,7 +142,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
|
|||
controller.properties.is_vertical.Assign(1);
|
||||
controller.properties.use_plus.Assign(1);
|
||||
controller.properties.use_minus.Assign(1);
|
||||
controller.pad_assignment = NPadAssignments::Single;
|
||||
controller.pad_assignment = NpadAssignments::Single;
|
||||
break;
|
||||
case NPadControllerType::Handheld:
|
||||
controller.joy_styles.handheld.Assign(1);
|
||||
|
@ -147,7 +150,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
|
|||
controller.properties.is_vertical.Assign(1);
|
||||
controller.properties.use_plus.Assign(1);
|
||||
controller.properties.use_minus.Assign(1);
|
||||
controller.pad_assignment = NPadAssignments::Dual;
|
||||
controller.pad_assignment = NpadAssignments::Dual;
|
||||
break;
|
||||
case NPadControllerType::JoyDual:
|
||||
controller.joy_styles.joycon_dual.Assign(1);
|
||||
|
@ -156,26 +159,26 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
|
|||
controller.properties.is_vertical.Assign(1);
|
||||
controller.properties.use_plus.Assign(1);
|
||||
controller.properties.use_minus.Assign(1);
|
||||
controller.pad_assignment = NPadAssignments::Dual;
|
||||
controller.pad_assignment = NpadAssignments::Dual;
|
||||
break;
|
||||
case NPadControllerType::JoyLeft:
|
||||
controller.joy_styles.joycon_left.Assign(1);
|
||||
controller.device_type.joycon_left.Assign(1);
|
||||
controller.properties.is_horizontal.Assign(1);
|
||||
controller.properties.use_minus.Assign(1);
|
||||
controller.pad_assignment = NPadAssignments::Single;
|
||||
controller.pad_assignment = NpadAssignments::Single;
|
||||
break;
|
||||
case NPadControllerType::JoyRight:
|
||||
controller.joy_styles.joycon_right.Assign(1);
|
||||
controller.device_type.joycon_right.Assign(1);
|
||||
controller.properties.is_horizontal.Assign(1);
|
||||
controller.properties.use_plus.Assign(1);
|
||||
controller.pad_assignment = NPadAssignments::Single;
|
||||
controller.pad_assignment = NpadAssignments::Single;
|
||||
break;
|
||||
case NPadControllerType::Pokeball:
|
||||
controller.joy_styles.pokeball.Assign(1);
|
||||
controller.device_type.pokeball.Assign(1);
|
||||
controller.pad_assignment = NPadAssignments::Single;
|
||||
controller.pad_assignment = NpadAssignments::Single;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -184,11 +187,14 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
|
|||
controller.single_color.button_color = 0;
|
||||
|
||||
controller.dual_color_error = ColorReadError::ReadOk;
|
||||
controller.left_color.body_color = Settings::values.players[controller_idx].body_color_left;
|
||||
controller.left_color.button_color = Settings::values.players[controller_idx].button_color_left;
|
||||
controller.right_color.body_color = Settings::values.players[controller_idx].body_color_right;
|
||||
controller.left_color.body_color =
|
||||
Settings::values.players.GetValue()[controller_idx].body_color_left;
|
||||
controller.left_color.button_color =
|
||||
Settings::values.players.GetValue()[controller_idx].button_color_left;
|
||||
controller.right_color.body_color =
|
||||
Settings::values.players.GetValue()[controller_idx].body_color_right;
|
||||
controller.right_color.button_color =
|
||||
Settings::values.players[controller_idx].button_color_right;
|
||||
Settings::values.players.GetValue()[controller_idx].button_color_right;
|
||||
|
||||
controller.battery_level[0] = BATTERY_FULL;
|
||||
controller.battery_level[1] = BATTERY_FULL;
|
||||
|
@ -199,7 +205,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
|
|||
|
||||
void Controller_NPad::OnInit() {
|
||||
auto& kernel = system.Kernel();
|
||||
for (std::size_t i = 0; i < styleset_changed_events.size(); i++) {
|
||||
for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) {
|
||||
styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair(
|
||||
kernel, fmt::format("npad:NpadStyleSetChanged_{}", i));
|
||||
}
|
||||
|
@ -208,6 +214,8 @@ void Controller_NPad::OnInit() {
|
|||
return;
|
||||
}
|
||||
|
||||
OnLoadInputDevices();
|
||||
|
||||
if (style.raw == 0) {
|
||||
// We want to support all controllers
|
||||
style.handheld.Assign(1);
|
||||
|
@ -218,12 +226,27 @@ void Controller_NPad::OnInit() {
|
|||
style.pokeball.Assign(1);
|
||||
}
|
||||
|
||||
std::transform(Settings::values.players.begin(), Settings::values.players.end(),
|
||||
connected_controllers.begin(), [](const Settings::PlayerInput& player) {
|
||||
std::transform(Settings::values.players.GetValue().begin(),
|
||||
Settings::values.players.GetValue().end(), connected_controllers.begin(),
|
||||
[](const Settings::PlayerInput& player) {
|
||||
return ControllerHolder{MapSettingsTypeToNPad(player.controller_type),
|
||||
player.connected};
|
||||
});
|
||||
|
||||
// Connect the Player 1 or Handheld controller if none are connected.
|
||||
if (std::none_of(connected_controllers.begin(), connected_controllers.end(),
|
||||
[](const ControllerHolder& controller) { return controller.is_connected; })) {
|
||||
const auto controller =
|
||||
MapSettingsTypeToNPad(Settings::values.players.GetValue()[0].controller_type);
|
||||
if (controller == NPadControllerType::Handheld) {
|
||||
Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true;
|
||||
connected_controllers[HANDHELD_INDEX] = {controller, true};
|
||||
} else {
|
||||
Settings::values.players.GetValue()[0].connected = true;
|
||||
connected_controllers[0] = {controller, true};
|
||||
}
|
||||
}
|
||||
|
||||
// Account for handheld
|
||||
if (connected_controllers[HANDHELD_INDEX].is_connected) {
|
||||
connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld;
|
||||
|
@ -242,7 +265,7 @@ void Controller_NPad::OnInit() {
|
|||
}
|
||||
|
||||
void Controller_NPad::OnLoadInputDevices() {
|
||||
const auto& players = Settings::values.players;
|
||||
const auto& players = Settings::values.players.GetValue();
|
||||
for (std::size_t i = 0; i < players.size(); ++i) {
|
||||
std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
|
||||
players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END,
|
||||
|
@ -250,13 +273,26 @@ void Controller_NPad::OnLoadInputDevices() {
|
|||
std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
|
||||
players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END,
|
||||
sticks[i].begin(), Input::CreateDevice<Input::AnalogDevice>);
|
||||
std::transform(players[i].vibrations.begin() +
|
||||
Settings::NativeVibration::VIBRATION_HID_BEGIN,
|
||||
players[i].vibrations.begin() + Settings::NativeVibration::VIBRATION_HID_END,
|
||||
vibrations[i].begin(), Input::CreateDevice<Input::VibrationDevice>);
|
||||
std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN,
|
||||
players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END,
|
||||
motions[i].begin(), Input::CreateDevice<Input::MotionDevice>);
|
||||
for (std::size_t device_idx = 0; device_idx < vibrations[i].size(); ++device_idx) {
|
||||
InitializeVibrationDeviceAtIndex(i, device_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Controller_NPad::OnRelease() {}
|
||||
void Controller_NPad::OnRelease() {
|
||||
for (std::size_t npad_idx = 0; npad_idx < vibrations.size(); ++npad_idx) {
|
||||
for (std::size_t device_idx = 0; device_idx < vibrations[npad_idx].size(); ++device_idx) {
|
||||
VibrateControllerAtIndex(npad_idx, device_idx, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
|
||||
const auto controller_idx = NPadIdToIndex(npad_id);
|
||||
|
@ -339,7 +375,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
|||
if (!IsControllerActivated()) {
|
||||
return;
|
||||
}
|
||||
for (std::size_t i = 0; i < shared_memory_entries.size(); i++) {
|
||||
for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) {
|
||||
auto& npad = shared_memory_entries[i];
|
||||
const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states,
|
||||
&npad.handheld_states,
|
||||
|
@ -481,7 +517,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
|
|||
if (!IsControllerActivated()) {
|
||||
return;
|
||||
}
|
||||
for (std::size_t i = 0; i < shared_memory_entries.size(); i++) {
|
||||
for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) {
|
||||
auto& npad = shared_memory_entries[i];
|
||||
|
||||
const auto& controller_type = connected_controllers[i].type;
|
||||
|
@ -515,7 +551,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
|
|||
// Try to read sixaxis sensor states
|
||||
std::array<MotionDevice, 2> motion_devices;
|
||||
|
||||
if (sixaxis_sensors_enabled && Settings::values.motion_enabled) {
|
||||
if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) {
|
||||
sixaxis_at_rest = true;
|
||||
for (std::size_t e = 0; e < motion_devices.size(); ++e) {
|
||||
const auto& device = motions[i][e];
|
||||
|
@ -601,15 +637,15 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
|
|||
shared_memory_entries.size() * sizeof(NPadEntry));
|
||||
}
|
||||
|
||||
void Controller_NPad::SetSupportedStyleSet(NPadType style_set) {
|
||||
void Controller_NPad::SetSupportedStyleSet(NpadStyleSet style_set) {
|
||||
style.raw = style_set.raw;
|
||||
}
|
||||
|
||||
Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const {
|
||||
Controller_NPad::NpadStyleSet Controller_NPad::GetSupportedStyleSet() const {
|
||||
return style;
|
||||
}
|
||||
|
||||
void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) {
|
||||
void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) {
|
||||
ASSERT(length > 0 && (length % sizeof(u32)) == 0);
|
||||
supported_npad_id_types.clear();
|
||||
supported_npad_id_types.resize(length / sizeof(u32));
|
||||
|
@ -621,7 +657,7 @@ void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length)
|
|||
std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size());
|
||||
}
|
||||
|
||||
std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const {
|
||||
std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const {
|
||||
return supported_npad_id_types.size();
|
||||
}
|
||||
|
||||
|
@ -641,7 +677,7 @@ Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActi
|
|||
return handheld_activation_mode;
|
||||
}
|
||||
|
||||
void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) {
|
||||
void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) {
|
||||
const std::size_t npad_index = NPadIdToIndex(npad_id);
|
||||
ASSERT(npad_index < shared_memory_entries.size());
|
||||
if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) {
|
||||
|
@ -649,35 +685,140 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode)
|
|||
}
|
||||
}
|
||||
|
||||
void Controller_NPad::VibrateController(const std::vector<u32>& controllers,
|
||||
const std::vector<Vibration>& vibrations) {
|
||||
LOG_TRACE(Service_HID, "called");
|
||||
bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index,
|
||||
const VibrationValue& vibration_value) {
|
||||
if (!connected_controllers[npad_index].is_connected || !vibrations[npad_index][device_index]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Settings::values.vibration_enabled || !can_controllers_vibrate) {
|
||||
const auto& player = Settings::values.players.GetValue()[npad_index];
|
||||
|
||||
if (!player.vibration_enabled) {
|
||||
if (latest_vibration_values[npad_index][device_index].amp_low != 0.0f ||
|
||||
latest_vibration_values[npad_index][device_index].amp_high != 0.0f) {
|
||||
// Send an empty vibration to stop any vibrations.
|
||||
vibrations[npad_index][device_index]->SetRumblePlay(0.0f, 160.0f, 0.0f, 320.0f);
|
||||
// Then reset the vibration value to its default value.
|
||||
latest_vibration_values[npad_index][device_index] = {};
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Settings::values.enable_accurate_vibrations.GetValue()) {
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::milliseconds;
|
||||
using std::chrono::steady_clock;
|
||||
|
||||
const auto now = steady_clock::now();
|
||||
|
||||
// Filter out non-zero vibrations that are within 10ms of each other.
|
||||
if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) &&
|
||||
duration_cast<milliseconds>(now - last_vibration_timepoints[npad_index][device_index]) <
|
||||
milliseconds(10)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
last_vibration_timepoints[npad_index][device_index] = now;
|
||||
}
|
||||
|
||||
auto& vibration = vibrations[npad_index][device_index];
|
||||
const auto player_vibration_strength = static_cast<f32>(player.vibration_strength);
|
||||
const auto amp_low =
|
||||
std::min(vibration_value.amp_low * player_vibration_strength / 100.0f, 1.0f);
|
||||
const auto amp_high =
|
||||
std::min(vibration_value.amp_high * player_vibration_strength / 100.0f, 1.0f);
|
||||
return vibration->SetRumblePlay(amp_low, vibration_value.freq_low, amp_high,
|
||||
vibration_value.freq_high);
|
||||
}
|
||||
|
||||
void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle,
|
||||
const VibrationValue& vibration_value) {
|
||||
if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
|
||||
return;
|
||||
}
|
||||
bool success = true;
|
||||
for (std::size_t i = 0; i < controllers.size(); ++i) {
|
||||
if (!connected_controllers[i].is_connected) {
|
||||
continue;
|
||||
}
|
||||
using namespace Settings::NativeButton;
|
||||
const auto& button_state = buttons[i];
|
||||
if (button_state[A - BUTTON_HID_BEGIN]) {
|
||||
if (button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay(
|
||||
vibrations[0].amp_high, vibrations[0].amp_low, vibrations[0].freq_high,
|
||||
vibrations[0].freq_low)) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
|
||||
const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
|
||||
|
||||
if (!vibration_devices_mounted[npad_index][device_index] ||
|
||||
!connected_controllers[npad_index].is_connected) {
|
||||
return;
|
||||
}
|
||||
if (success) {
|
||||
last_processed_vibration = vibrations.back();
|
||||
|
||||
if (vibration_device_handle.device_index == DeviceIndex::None) {
|
||||
UNREACHABLE_MSG("DeviceIndex should never be None!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Some games try to send mismatched parameters in the device handle, block these.
|
||||
if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft &&
|
||||
(vibration_device_handle.npad_type == NpadType::JoyconRight ||
|
||||
vibration_device_handle.device_index == DeviceIndex::Right)) ||
|
||||
(connected_controllers[npad_index].type == NPadControllerType::JoyRight &&
|
||||
(vibration_device_handle.npad_type == NpadType::JoyconLeft ||
|
||||
vibration_device_handle.device_index == DeviceIndex::Left))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter out vibrations with equivalent values to reduce unnecessary state changes.
|
||||
if (vibration_value.amp_low == latest_vibration_values[npad_index][device_index].amp_low &&
|
||||
vibration_value.amp_high == latest_vibration_values[npad_index][device_index].amp_high) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) {
|
||||
latest_vibration_values[npad_index][device_index] = vibration_value;
|
||||
}
|
||||
}
|
||||
|
||||
Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
|
||||
return last_processed_vibration;
|
||||
void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles,
|
||||
const std::vector<VibrationValue>& vibration_values) {
|
||||
if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT_OR_EXECUTE_MSG(
|
||||
vibration_device_handles.size() == vibration_values.size(), { return; },
|
||||
"The amount of device handles does not match with the amount of vibration values,"
|
||||
"this is undefined behavior!");
|
||||
|
||||
for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) {
|
||||
VibrateController(vibration_device_handles[i], vibration_values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Controller_NPad::VibrationValue Controller_NPad::GetLastVibration(
|
||||
const DeviceHandle& vibration_device_handle) const {
|
||||
const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
|
||||
const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
|
||||
return latest_vibration_values[npad_index][device_index];
|
||||
}
|
||||
|
||||
void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) {
|
||||
const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
|
||||
const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
|
||||
InitializeVibrationDeviceAtIndex(npad_index, device_index);
|
||||
}
|
||||
|
||||
void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index,
|
||||
std::size_t device_index) {
|
||||
if (vibrations[npad_index][device_index]) {
|
||||
vibration_devices_mounted[npad_index][device_index] =
|
||||
vibrations[npad_index][device_index]->GetStatus() == 1;
|
||||
} else {
|
||||
vibration_devices_mounted[npad_index][device_index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
|
||||
permit_vibration_session_enabled = permit_vibration_session;
|
||||
}
|
||||
|
||||
bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const {
|
||||
const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
|
||||
const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
|
||||
return vibration_devices_mounted[npad_index][device_index];
|
||||
}
|
||||
|
||||
std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const {
|
||||
|
@ -696,31 +837,38 @@ void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::siz
|
|||
void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index,
|
||||
bool connected) {
|
||||
if (!connected) {
|
||||
DisconnectNPadAtIndex(npad_index);
|
||||
DisconnectNpadAtIndex(npad_index);
|
||||
return;
|
||||
}
|
||||
|
||||
if (controller == NPadControllerType::Handheld) {
|
||||
Settings::values.players[HANDHELD_INDEX].controller_type =
|
||||
Settings::values.players.GetValue()[HANDHELD_INDEX].controller_type =
|
||||
MapNPadToSettingsType(controller);
|
||||
Settings::values.players[HANDHELD_INDEX].connected = true;
|
||||
Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true;
|
||||
connected_controllers[HANDHELD_INDEX] = {controller, true};
|
||||
InitNewlyAddedController(HANDHELD_INDEX);
|
||||
return;
|
||||
}
|
||||
|
||||
Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller);
|
||||
Settings::values.players[npad_index].connected = true;
|
||||
Settings::values.players.GetValue()[npad_index].controller_type =
|
||||
MapNPadToSettingsType(controller);
|
||||
Settings::values.players.GetValue()[npad_index].connected = true;
|
||||
connected_controllers[npad_index] = {controller, true};
|
||||
InitNewlyAddedController(npad_index);
|
||||
}
|
||||
|
||||
void Controller_NPad::DisconnectNPad(u32 npad_id) {
|
||||
DisconnectNPadAtIndex(NPadIdToIndex(npad_id));
|
||||
void Controller_NPad::DisconnectNpad(u32 npad_id) {
|
||||
DisconnectNpadAtIndex(NPadIdToIndex(npad_id));
|
||||
}
|
||||
|
||||
void Controller_NPad::DisconnectNPadAtIndex(std::size_t npad_index) {
|
||||
Settings::values.players[npad_index].connected = false;
|
||||
void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
|
||||
for (std::size_t device_idx = 0; device_idx < vibrations[npad_index].size(); ++device_idx) {
|
||||
// Send an empty vibration to stop any vibrations.
|
||||
VibrateControllerAtIndex(npad_index, device_idx, {});
|
||||
vibration_devices_mounted[npad_index][device_idx] = false;
|
||||
}
|
||||
|
||||
Settings::values.players.GetValue()[npad_index].connected = false;
|
||||
connected_controllers[npad_index].is_connected = false;
|
||||
|
||||
auto& controller = shared_memory_entries[npad_index];
|
||||
|
@ -758,7 +906,7 @@ void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) {
|
|||
(connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft &&
|
||||
connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) {
|
||||
// Disconnect the joycon at the second id and connect the dual joycon at the first index.
|
||||
DisconnectNPad(npad_id_2);
|
||||
DisconnectNpad(npad_id_2);
|
||||
AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1);
|
||||
}
|
||||
}
|
||||
|
@ -830,14 +978,6 @@ void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_prot
|
|||
unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled;
|
||||
}
|
||||
|
||||
void Controller_NPad::SetVibrationEnabled(bool can_vibrate) {
|
||||
can_controllers_vibrate = can_vibrate;
|
||||
}
|
||||
|
||||
bool Controller_NPad::IsVibrationEnabled() const {
|
||||
return can_controllers_vibrate;
|
||||
}
|
||||
|
||||
void Controller_NPad::ClearAllConnectedControllers() {
|
||||
for (auto& controller : connected_controllers) {
|
||||
if (controller.is_connected && controller.type != NPadControllerType::None) {
|
||||
|
@ -882,7 +1022,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
|
|||
return false;
|
||||
}
|
||||
// Handheld should not be supported in docked mode
|
||||
if (Settings::values.use_docked_mode) {
|
||||
if (Settings::values.use_docked_mode.GetValue()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,28 +39,30 @@ public:
|
|||
// Called when input devices should be loaded
|
||||
void OnLoadInputDevices() override;
|
||||
|
||||
struct NPadType {
|
||||
union {
|
||||
u32_le raw{};
|
||||
|
||||
BitField<0, 1, u32> pro_controller;
|
||||
BitField<1, 1, u32> handheld;
|
||||
BitField<2, 1, u32> joycon_dual;
|
||||
BitField<3, 1, u32> joycon_left;
|
||||
BitField<4, 1, u32> joycon_right;
|
||||
|
||||
BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible
|
||||
};
|
||||
enum class NPadControllerType {
|
||||
None,
|
||||
ProController,
|
||||
Handheld,
|
||||
JoyDual,
|
||||
JoyLeft,
|
||||
JoyRight,
|
||||
Pokeball,
|
||||
};
|
||||
static_assert(sizeof(NPadType) == 4, "NPadType is an invalid size");
|
||||
|
||||
struct Vibration {
|
||||
f32 amp_low;
|
||||
f32 freq_low;
|
||||
f32 amp_high;
|
||||
f32 freq_high;
|
||||
enum class NpadType : u8 {
|
||||
ProController = 3,
|
||||
Handheld = 4,
|
||||
JoyconDual = 5,
|
||||
JoyconLeft = 6,
|
||||
JoyconRight = 7,
|
||||
Pokeball = 9,
|
||||
};
|
||||
|
||||
enum class DeviceIndex : u8 {
|
||||
Left = 0,
|
||||
Right = 1,
|
||||
None = 2,
|
||||
};
|
||||
static_assert(sizeof(Vibration) == 0x10, "Vibration is an invalid size");
|
||||
|
||||
enum class GyroscopeZeroDriftMode : u32 {
|
||||
Loose = 0,
|
||||
|
@ -73,7 +75,7 @@ public:
|
|||
Horizontal = 1,
|
||||
};
|
||||
|
||||
enum class NPadAssignments : u32_le {
|
||||
enum class NpadAssignments : u32 {
|
||||
Dual = 0,
|
||||
Single = 1,
|
||||
};
|
||||
|
@ -84,15 +86,36 @@ public:
|
|||
None = 2,
|
||||
};
|
||||
|
||||
enum class NPadControllerType {
|
||||
None,
|
||||
ProController,
|
||||
Handheld,
|
||||
JoyDual,
|
||||
JoyLeft,
|
||||
JoyRight,
|
||||
Pokeball,
|
||||
struct DeviceHandle {
|
||||
NpadType npad_type{};
|
||||
u8 npad_id{};
|
||||
DeviceIndex device_index{};
|
||||
INSERT_PADDING_BYTES(1);
|
||||
};
|
||||
static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size");
|
||||
|
||||
struct NpadStyleSet {
|
||||
union {
|
||||
u32_le raw{};
|
||||
|
||||
BitField<0, 1, u32> pro_controller;
|
||||
BitField<1, 1, u32> handheld;
|
||||
BitField<2, 1, u32> joycon_dual;
|
||||
BitField<3, 1, u32> joycon_left;
|
||||
BitField<4, 1, u32> joycon_right;
|
||||
|
||||
BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size");
|
||||
|
||||
struct VibrationValue {
|
||||
f32 amp_low{0.0f};
|
||||
f32 freq_low{160.0f};
|
||||
f32 amp_high{0.0f};
|
||||
f32 freq_high{320.0f};
|
||||
};
|
||||
static_assert(sizeof(VibrationValue) == 0x10, "Vibration is an invalid size");
|
||||
|
||||
struct LedPattern {
|
||||
explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
|
||||
|
@ -110,12 +133,12 @@ public:
|
|||
};
|
||||
};
|
||||
|
||||
void SetSupportedStyleSet(NPadType style_set);
|
||||
NPadType GetSupportedStyleSet() const;
|
||||
void SetSupportedStyleSet(NpadStyleSet style_set);
|
||||
NpadStyleSet GetSupportedStyleSet() const;
|
||||
|
||||
void SetSupportedNPadIdTypes(u8* data, std::size_t length);
|
||||
void SetSupportedNpadIdTypes(u8* data, std::size_t length);
|
||||
void GetSupportedNpadIdTypes(u32* data, std::size_t max_length);
|
||||
std::size_t GetSupportedNPadIdTypesSize() const;
|
||||
std::size_t GetSupportedNpadIdTypesSize() const;
|
||||
|
||||
void SetHoldType(NpadHoldType joy_hold_type);
|
||||
NpadHoldType GetHoldType() const;
|
||||
|
@ -123,12 +146,26 @@ public:
|
|||
void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode);
|
||||
NpadHandheldActivationMode GetNpadHandheldActivationMode() const;
|
||||
|
||||
void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode);
|
||||
void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode);
|
||||
|
||||
void VibrateController(const std::vector<u32>& controllers,
|
||||
const std::vector<Vibration>& vibrations);
|
||||
bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index,
|
||||
const VibrationValue& vibration_value);
|
||||
|
||||
Vibration GetLastVibration() const;
|
||||
void VibrateController(const DeviceHandle& vibration_device_handle,
|
||||
const VibrationValue& vibration_value);
|
||||
|
||||
void VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles,
|
||||
const std::vector<VibrationValue>& vibration_values);
|
||||
|
||||
VibrationValue GetLastVibration(const DeviceHandle& vibration_device_handle) const;
|
||||
|
||||
void InitializeVibrationDevice(const DeviceHandle& vibration_device_handle);
|
||||
|
||||
void InitializeVibrationDeviceAtIndex(std::size_t npad_index, std::size_t device_index);
|
||||
|
||||
void SetPermitVibrationSession(bool permit_vibration_session);
|
||||
|
||||
bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const;
|
||||
|
||||
std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const;
|
||||
void SignalStyleSetChangedEvent(u32 npad_id) const;
|
||||
|
@ -138,8 +175,8 @@ public:
|
|||
// Adds a new controller at an index with connection status.
|
||||
void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected);
|
||||
|
||||
void DisconnectNPad(u32 npad_id);
|
||||
void DisconnectNPadAtIndex(std::size_t index);
|
||||
void DisconnectNpad(u32 npad_id);
|
||||
void DisconnectNpadAtIndex(std::size_t index);
|
||||
|
||||
void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode);
|
||||
GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const;
|
||||
|
@ -148,8 +185,6 @@ public:
|
|||
LedPattern GetLedPattern(u32 npad_id);
|
||||
bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const;
|
||||
void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id);
|
||||
void SetVibrationEnabled(bool can_vibrate);
|
||||
bool IsVibrationEnabled() const;
|
||||
void ClearAllConnectedControllers();
|
||||
void DisconnectAllConnectedControllers();
|
||||
void ConnectAllDisconnectedControllers();
|
||||
|
@ -324,8 +359,8 @@ private:
|
|||
};
|
||||
|
||||
struct NPadEntry {
|
||||
NPadType joy_styles;
|
||||
NPadAssignments pad_assignment;
|
||||
NpadStyleSet joy_styles;
|
||||
NpadAssignments pad_assignment;
|
||||
|
||||
ColorReadError single_color_error;
|
||||
ControllerColor single_color;
|
||||
|
@ -368,7 +403,7 @@ private:
|
|||
|
||||
u32 press_state{};
|
||||
|
||||
NPadType style{};
|
||||
NpadStyleSet style{};
|
||||
std::array<NPadEntry, 10> shared_memory_entries{};
|
||||
using ButtonArray = std::array<
|
||||
std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>,
|
||||
|
@ -376,22 +411,28 @@ private:
|
|||
using StickArray = std::array<
|
||||
std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>,
|
||||
10>;
|
||||
using VibrationArray = std::array<std::array<std::unique_ptr<Input::VibrationDevice>,
|
||||
Settings::NativeVibration::NUM_VIBRATIONS_HID>,
|
||||
10>;
|
||||
using MotionArray = std::array<
|
||||
std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTION_HID>,
|
||||
std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTIONS_HID>,
|
||||
10>;
|
||||
ButtonArray buttons;
|
||||
StickArray sticks;
|
||||
VibrationArray vibrations;
|
||||
MotionArray motions;
|
||||
std::vector<u32> supported_npad_id_types{};
|
||||
NpadHoldType hold_type{NpadHoldType::Vertical};
|
||||
NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual};
|
||||
// Each controller should have their own styleset changed event
|
||||
std::array<Kernel::EventPair, 10> styleset_changed_events;
|
||||
Vibration last_processed_vibration{};
|
||||
std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints;
|
||||
std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{};
|
||||
bool permit_vibration_session_enabled{false};
|
||||
std::array<std::array<bool, 2>, 10> vibration_devices_mounted{};
|
||||
std::array<ControllerHolder, 10> connected_controllers{};
|
||||
std::array<bool, 10> unintended_home_button_input_protection{};
|
||||
GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
|
||||
bool can_controllers_vibrate{true};
|
||||
bool sixaxis_sensors_enabled{true};
|
||||
bool sixaxis_at_rest{true};
|
||||
std::array<ControllerPad, 10> npad_pad_states{};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -86,17 +86,15 @@ public:
|
|||
|
||||
private:
|
||||
void CreateAppletResource(Kernel::HLERequestContext& ctx);
|
||||
void ActivateXpad(Kernel::HLERequestContext& ctx);
|
||||
void GetXpadIDs(Kernel::HLERequestContext& ctx);
|
||||
void ActivateSixAxisSensor(Kernel::HLERequestContext& ctx);
|
||||
void DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx);
|
||||
void ActivateDebugPad(Kernel::HLERequestContext& ctx);
|
||||
void ActivateTouchScreen(Kernel::HLERequestContext& ctx);
|
||||
void ActivateMouse(Kernel::HLERequestContext& ctx);
|
||||
void ActivateKeyboard(Kernel::HLERequestContext& ctx);
|
||||
void SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx);
|
||||
void ActivateGesture(Kernel::HLERequestContext& ctx);
|
||||
void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx);
|
||||
void ActivateXpad(Kernel::HLERequestContext& ctx);
|
||||
void GetXpadIDs(Kernel::HLERequestContext& ctx);
|
||||
void ActivateSixAxisSensor(Kernel::HLERequestContext& ctx);
|
||||
void DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx);
|
||||
void StartSixAxisSensor(Kernel::HLERequestContext& ctx);
|
||||
void StopSixAxisSensor(Kernel::HLERequestContext& ctx);
|
||||
void EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx);
|
||||
|
@ -104,6 +102,7 @@ private:
|
|||
void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
|
||||
void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
|
||||
void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx);
|
||||
void ActivateGesture(Kernel::HLERequestContext& ctx);
|
||||
void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx);
|
||||
void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx);
|
||||
void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx);
|
||||
|
@ -112,6 +111,7 @@ private:
|
|||
void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx);
|
||||
void DisconnectNpad(Kernel::HLERequestContext& ctx);
|
||||
void GetPlayerLedPattern(Kernel::HLERequestContext& ctx);
|
||||
void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx);
|
||||
void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx);
|
||||
void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx);
|
||||
void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx);
|
||||
|
@ -125,15 +125,16 @@ private:
|
|||
void SwapNpadAssignment(Kernel::HLERequestContext& ctx);
|
||||
void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx);
|
||||
void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx);
|
||||
void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx);
|
||||
void EndPermitVibrationSession(Kernel::HLERequestContext& ctx);
|
||||
void SendVibrationValue(Kernel::HLERequestContext& ctx);
|
||||
void SendVibrationValues(Kernel::HLERequestContext& ctx);
|
||||
void GetActualVibrationValue(Kernel::HLERequestContext& ctx);
|
||||
void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx);
|
||||
void SendVibrationValue(Kernel::HLERequestContext& ctx);
|
||||
void GetActualVibrationValue(Kernel::HLERequestContext& ctx);
|
||||
void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx);
|
||||
void PermitVibration(Kernel::HLERequestContext& ctx);
|
||||
void IsVibrationPermitted(Kernel::HLERequestContext& ctx);
|
||||
void SendVibrationValues(Kernel::HLERequestContext& ctx);
|
||||
void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx);
|
||||
void EndPermitVibrationSession(Kernel::HLERequestContext& ctx);
|
||||
void IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx);
|
||||
void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx);
|
||||
void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx);
|
||||
void StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx);
|
||||
|
@ -146,6 +147,22 @@ private:
|
|||
void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx);
|
||||
void SetPalmaBoostMode(Kernel::HLERequestContext& ctx);
|
||||
|
||||
enum class VibrationDeviceType : u32 {
|
||||
LinearResonantActuator = 1,
|
||||
};
|
||||
|
||||
enum class VibrationDevicePosition : u32 {
|
||||
None = 0,
|
||||
Left = 1,
|
||||
Right = 2,
|
||||
};
|
||||
|
||||
struct VibrationDeviceInfo {
|
||||
VibrationDeviceType type{};
|
||||
VibrationDevicePosition position{};
|
||||
};
|
||||
static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incorrect size.");
|
||||
|
||||
std::shared_ptr<IAppletResource> applet_resource;
|
||||
Core::System& system;
|
||||
};
|
||||
|
|
|
@ -771,7 +771,7 @@ private:
|
|||
IPC::ResponseBuilder rb{ctx, 6};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
if (Settings::values.use_docked_mode) {
|
||||
if (Settings::values.use_docked_mode.GetValue()) {
|
||||
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) *
|
||||
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
|
||||
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) *
|
||||
|
|
|
@ -49,7 +49,7 @@ void LogSettings() {
|
|||
};
|
||||
|
||||
LOG_INFO(Config, "yuzu Configuration:");
|
||||
log_setting("Controls_UseDockedMode", values.use_docked_mode);
|
||||
log_setting("Controls_UseDockedMode", values.use_docked_mode.GetValue());
|
||||
log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0));
|
||||
log_setting("System_CurrentUser", values.current_user);
|
||||
log_setting("System_LanguageIndex", values.language_index.GetValue());
|
||||
|
@ -145,6 +145,12 @@ void RestoreGlobalState() {
|
|||
values.rng_seed.SetGlobal(true);
|
||||
values.custom_rtc.SetGlobal(true);
|
||||
values.sound_index.SetGlobal(true);
|
||||
|
||||
// Controls
|
||||
values.players.SetGlobal(true);
|
||||
values.use_docked_mode.SetGlobal(true);
|
||||
values.vibration_enabled.SetGlobal(true);
|
||||
values.motion_enabled.SetGlobal(true);
|
||||
}
|
||||
|
||||
void Sanitize() {
|
||||
|
|
|
@ -65,6 +65,38 @@ private:
|
|||
Type local{};
|
||||
};
|
||||
|
||||
/**
|
||||
* The InputSetting class allows for getting a reference to either the global or local members.
|
||||
* This is required as we cannot easily modify the values of user-defined types within containers
|
||||
* using the SetValue() member function found in the Setting class. The primary purpose of this
|
||||
* class is to store an array of 10 PlayerInput structs for both the global and local (per-game)
|
||||
* setting and allows for easily accessing and modifying both settings.
|
||||
*/
|
||||
template <typename Type>
|
||||
class InputSetting final {
|
||||
public:
|
||||
InputSetting() = default;
|
||||
explicit InputSetting(Type val) : global{val} {}
|
||||
~InputSetting() = default;
|
||||
void SetGlobal(bool to_global) {
|
||||
use_global = to_global;
|
||||
}
|
||||
bool UsingGlobal() const {
|
||||
return use_global;
|
||||
}
|
||||
Type& GetValue(bool need_global = false) {
|
||||
if (use_global || need_global) {
|
||||
return global;
|
||||
}
|
||||
return local;
|
||||
}
|
||||
|
||||
private:
|
||||
bool use_global = true;
|
||||
Type global{};
|
||||
Type local{};
|
||||
};
|
||||
|
||||
struct TouchFromButtonMap {
|
||||
std::string name;
|
||||
std::vector<std::string> buttons;
|
||||
|
@ -133,9 +165,18 @@ struct Values {
|
|||
Setting<s32> sound_index;
|
||||
|
||||
// Controls
|
||||
std::array<PlayerInput, 10> players;
|
||||
InputSetting<std::array<PlayerInput, 10>> players;
|
||||
|
||||
bool use_docked_mode;
|
||||
Setting<bool> use_docked_mode;
|
||||
|
||||
Setting<bool> vibration_enabled;
|
||||
Setting<bool> enable_accurate_vibrations;
|
||||
|
||||
Setting<bool> motion_enabled;
|
||||
std::string motion_device;
|
||||
std::string udp_input_address;
|
||||
u16 udp_input_port;
|
||||
u8 udp_pad_index;
|
||||
|
||||
bool mouse_enabled;
|
||||
std::string mouse_device;
|
||||
|
@ -149,20 +190,15 @@ struct Values {
|
|||
ButtonsRaw debug_pad_buttons;
|
||||
AnalogsRaw debug_pad_analogs;
|
||||
|
||||
bool vibration_enabled;
|
||||
|
||||
bool motion_enabled;
|
||||
std::string motion_device;
|
||||
std::string touch_device;
|
||||
TouchscreenInput touchscreen;
|
||||
std::atomic_bool is_device_reload_pending{true};
|
||||
|
||||
bool use_touch_from_button;
|
||||
std::string touch_device;
|
||||
int touch_from_button_map_index;
|
||||
std::string udp_input_address;
|
||||
u16 udp_input_port;
|
||||
u8 udp_pad_index;
|
||||
std::vector<TouchFromButtonMap> touch_from_button_maps;
|
||||
|
||||
std::atomic_bool is_device_reload_pending{true};
|
||||
|
||||
// Data Storage
|
||||
bool use_virtual_sd;
|
||||
bool gamecard_inserted;
|
||||
|
|
|
@ -213,7 +213,7 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) {
|
|||
Settings::values.use_assembly_shaders.GetValue());
|
||||
AddField(field_type, "Renderer_UseAsynchronousShaders",
|
||||
Settings::values.use_asynchronous_shaders.GetValue());
|
||||
AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode);
|
||||
AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode.GetValue());
|
||||
}
|
||||
|
||||
bool TelemetrySession::SubmitTestcase() {
|
||||
|
|
|
@ -230,10 +230,8 @@ void Adapter::SendVibrations() {
|
|||
vibration_changed = false;
|
||||
}
|
||||
|
||||
bool Adapter::RumblePlay(std::size_t port, f32 amplitude) {
|
||||
amplitude = std::clamp(amplitude, 0.0f, 1.0f);
|
||||
const auto raw_amp = static_cast<u8>(amplitude * 0x8);
|
||||
pads[port].rumble_amplitude = raw_amp;
|
||||
bool Adapter::RumblePlay(std::size_t port, u8 amplitude) {
|
||||
pads[port].rumble_amplitude = amplitude;
|
||||
|
||||
return rumble_enabled;
|
||||
}
|
||||
|
|
|
@ -77,8 +77,8 @@ public:
|
|||
Adapter();
|
||||
~Adapter();
|
||||
|
||||
/// Request a vibration for a controlelr
|
||||
bool RumblePlay(std::size_t port, f32 amplitude);
|
||||
/// Request a vibration for a controller
|
||||
bool RumblePlay(std::size_t port, u8 amplitude);
|
||||
|
||||
/// Used for polling
|
||||
void BeginConfiguration();
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace InputCommon {
|
|||
|
||||
class GCButton final : public Input::ButtonDevice {
|
||||
public:
|
||||
explicit GCButton(u32 port_, s32 button_, GCAdapter::Adapter* adapter)
|
||||
explicit GCButton(u32 port_, s32 button_, const GCAdapter::Adapter* adapter)
|
||||
: port(port_), button(button_), gcadapter(adapter) {}
|
||||
|
||||
~GCButton() override;
|
||||
|
@ -27,18 +27,10 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override {
|
||||
const float amplitude = amp_high + amp_low > 2.0f ? 1.0f : (amp_high + amp_low) * 0.5f;
|
||||
const auto new_amp =
|
||||
static_cast<f32>(pow(amplitude, 0.5f) * (3.0f - 2.0f * pow(amplitude, 0.15f)));
|
||||
|
||||
return gcadapter->RumblePlay(port, new_amp);
|
||||
}
|
||||
|
||||
private:
|
||||
const u32 port;
|
||||
const s32 button;
|
||||
GCAdapter::Adapter* gcadapter;
|
||||
const GCAdapter::Adapter* gcadapter;
|
||||
};
|
||||
|
||||
class GCAxisButton final : public Input::ButtonDevice {
|
||||
|
@ -299,4 +291,42 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() {
|
|||
return params;
|
||||
}
|
||||
|
||||
class GCVibration final : public Input::VibrationDevice {
|
||||
public:
|
||||
explicit GCVibration(u32 port_, GCAdapter::Adapter* adapter)
|
||||
: port(port_), gcadapter(adapter) {}
|
||||
|
||||
u8 GetStatus() const override {
|
||||
return gcadapter->RumblePlay(port, 0);
|
||||
}
|
||||
|
||||
bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override {
|
||||
const auto mean_amplitude = (amp_low + amp_high) * 0.5f;
|
||||
const auto processed_amplitude = static_cast<u8>(
|
||||
pow(mean_amplitude, 0.5f) * (3.0f - 2.0f * pow(mean_amplitude, 0.15f)) * 0x8);
|
||||
|
||||
return gcadapter->RumblePlay(port, processed_amplitude);
|
||||
}
|
||||
|
||||
private:
|
||||
const u32 port;
|
||||
GCAdapter::Adapter* gcadapter;
|
||||
};
|
||||
|
||||
/// An vibration device factory that creates vibration devices from GC Adapter
|
||||
GCVibrationFactory::GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
|
||||
: adapter(std::move(adapter_)) {}
|
||||
|
||||
/**
|
||||
* Creates a vibration device from a joystick
|
||||
* @param params contains parameters for creating the device:
|
||||
* - "port": the nth gcpad on the adapter
|
||||
*/
|
||||
std::unique_ptr<Input::VibrationDevice> GCVibrationFactory::Create(
|
||||
const Common::ParamPackage& params) {
|
||||
const auto port = static_cast<u32>(params.Get("port", 0));
|
||||
|
||||
return std::make_unique<GCVibration>(port, adapter.get());
|
||||
}
|
||||
|
||||
} // namespace InputCommon
|
||||
|
|
|
@ -64,4 +64,15 @@ private:
|
|||
bool polling = false;
|
||||
};
|
||||
|
||||
/// A vibration device factory creates vibration devices from GC Adapter
|
||||
class GCVibrationFactory final : public Input::Factory<Input::VibrationDevice> {
|
||||
public:
|
||||
explicit GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_);
|
||||
|
||||
std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<GCAdapter::Adapter> adapter;
|
||||
};
|
||||
|
||||
} // namespace InputCommon
|
||||
|
|
|
@ -28,6 +28,8 @@ struct InputSubsystem::Impl {
|
|||
Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons);
|
||||
gcanalog = std::make_shared<GCAnalogFactory>(gcadapter);
|
||||
Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog);
|
||||
gcvibration = std::make_shared<GCVibrationFactory>(gcadapter);
|
||||
Input::RegisterFactory<Input::VibrationDevice>("gcpad", gcvibration);
|
||||
|
||||
keyboard = std::make_shared<Keyboard>();
|
||||
Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
|
||||
|
@ -64,9 +66,11 @@ struct InputSubsystem::Impl {
|
|||
#endif
|
||||
Input::UnregisterFactory<Input::ButtonDevice>("gcpad");
|
||||
Input::UnregisterFactory<Input::AnalogDevice>("gcpad");
|
||||
Input::UnregisterFactory<Input::VibrationDevice>("gcpad");
|
||||
|
||||
gcbuttons.reset();
|
||||
gcanalog.reset();
|
||||
gcvibration.reset();
|
||||
|
||||
Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp");
|
||||
Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp");
|
||||
|
@ -78,7 +82,7 @@ struct InputSubsystem::Impl {
|
|||
[[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const {
|
||||
std::vector<Common::ParamPackage> devices = {
|
||||
Common::ParamPackage{{"display", "Any"}, {"class", "any"}},
|
||||
Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}},
|
||||
Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "keyboard"}},
|
||||
};
|
||||
#ifdef HAVE_SDL2
|
||||
auto sdl_devices = sdl->GetInputDevices();
|
||||
|
@ -96,10 +100,6 @@ struct InputSubsystem::Impl {
|
|||
if (!params.Has("class") || params.Get("class", "") == "any") {
|
||||
return {};
|
||||
}
|
||||
if (params.Get("class", "") == "key") {
|
||||
// TODO consider returning the SDL key codes for the default keybindings
|
||||
return {};
|
||||
}
|
||||
if (params.Get("class", "") == "gcpad") {
|
||||
return gcadapter->GetAnalogMappingForDevice(params);
|
||||
}
|
||||
|
@ -116,10 +116,6 @@ struct InputSubsystem::Impl {
|
|||
if (!params.Has("class") || params.Get("class", "") == "any") {
|
||||
return {};
|
||||
}
|
||||
if (params.Get("class", "") == "key") {
|
||||
// TODO consider returning the SDL key codes for the default keybindings
|
||||
return {};
|
||||
}
|
||||
if (params.Get("class", "") == "gcpad") {
|
||||
return gcadapter->GetButtonMappingForDevice(params);
|
||||
}
|
||||
|
@ -150,6 +146,7 @@ struct InputSubsystem::Impl {
|
|||
#endif
|
||||
std::shared_ptr<GCButtonFactory> gcbuttons;
|
||||
std::shared_ptr<GCAnalogFactory> gcanalog;
|
||||
std::shared_ptr<GCVibrationFactory> gcvibration;
|
||||
std::shared_ptr<UDPMotionFactory> udpmotion;
|
||||
std::shared_ptr<UDPTouchFactory> udptouch;
|
||||
std::shared_ptr<CemuhookUDP::Client> udp;
|
||||
|
|
|
@ -80,30 +80,13 @@ public:
|
|||
return static_cast<float>(state.axes.at(axis)) / (32767.0f * range);
|
||||
}
|
||||
|
||||
bool RumblePlay(f32 amp_low, f32 amp_high, u32 time) {
|
||||
const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF);
|
||||
const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF);
|
||||
// Lower drastically the number of state changes
|
||||
if (raw_amp_low >> 11 == last_state_rumble_low >> 11 &&
|
||||
raw_amp_high >> 11 == last_state_rumble_high >> 11) {
|
||||
if (raw_amp_low + raw_amp_high != 0 ||
|
||||
last_state_rumble_low + last_state_rumble_high == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Don't change state if last vibration was < 20ms
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_vibration) <
|
||||
std::chrono::milliseconds(20)) {
|
||||
return raw_amp_low + raw_amp_high == 0;
|
||||
bool RumblePlay(u16 amp_low, u16 amp_high) {
|
||||
if (sdl_controller) {
|
||||
return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0;
|
||||
} else if (sdl_joystick) {
|
||||
return SDL_JoystickRumble(sdl_joystick.get(), amp_low, amp_high, 0) == 0;
|
||||
}
|
||||
|
||||
last_vibration = now;
|
||||
last_state_rumble_low = raw_amp_low;
|
||||
last_state_rumble_high = raw_amp_high;
|
||||
if (sdl_joystick) {
|
||||
SDL_JoystickRumble(sdl_joystick.get(), raw_amp_low, raw_amp_high, time);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -172,9 +155,6 @@ private:
|
|||
} state;
|
||||
std::string guid;
|
||||
int port;
|
||||
u16 last_state_rumble_high = 0;
|
||||
u16 last_state_rumble_low = 0;
|
||||
std::chrono::time_point<std::chrono::system_clock> last_vibration;
|
||||
std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
|
||||
std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
|
||||
mutable std::mutex mutex;
|
||||
|
@ -327,12 +307,6 @@ public:
|
|||
return joystick->GetButton(button);
|
||||
}
|
||||
|
||||
bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override {
|
||||
const f32 new_amp_low = pow(amp_low, 0.5f) * (3.0f - 2.0f * pow(amp_low, 0.15f));
|
||||
const f32 new_amp_high = pow(amp_high, 0.5f) * (3.0f - 2.0f * pow(amp_high, 0.15f));
|
||||
return joystick->RumblePlay(new_amp_low, new_amp_high, 250);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<SDLJoystick> joystick;
|
||||
int button;
|
||||
|
@ -416,6 +390,32 @@ private:
|
|||
const float range;
|
||||
};
|
||||
|
||||
class SDLVibration final : public Input::VibrationDevice {
|
||||
public:
|
||||
explicit SDLVibration(std::shared_ptr<SDLJoystick> joystick_)
|
||||
: joystick(std::move(joystick_)) {}
|
||||
|
||||
u8 GetStatus() const override {
|
||||
joystick->RumblePlay(1, 1);
|
||||
return joystick->RumblePlay(0, 0);
|
||||
}
|
||||
|
||||
bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override {
|
||||
const auto process_amplitude = [](f32 amplitude) {
|
||||
return static_cast<u16>(std::pow(amplitude, 0.5f) *
|
||||
(3.0f - 2.0f * std::pow(amplitude, 0.15f)) * 0xFFFF);
|
||||
};
|
||||
|
||||
const auto processed_amp_low = process_amplitude(amp_low);
|
||||
const auto processed_amp_high = process_amplitude(amp_high);
|
||||
|
||||
return joystick->RumblePlay(processed_amp_low, processed_amp_high);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<SDLJoystick> joystick;
|
||||
};
|
||||
|
||||
class SDLDirectionMotion final : public Input::MotionDevice {
|
||||
public:
|
||||
explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_)
|
||||
|
@ -558,7 +558,7 @@ class SDLAnalogFactory final : public Input::Factory<Input::AnalogDevice> {
|
|||
public:
|
||||
explicit SDLAnalogFactory(SDLState& state_) : state(state_) {}
|
||||
/**
|
||||
* Creates analog device from joystick axes
|
||||
* Creates an analog device from joystick axes
|
||||
* @param params contains parameters for creating the device:
|
||||
* - "guid": the guid of the joystick to bind
|
||||
* - "port": the nth joystick of the same type
|
||||
|
@ -584,6 +584,26 @@ private:
|
|||
SDLState& state;
|
||||
};
|
||||
|
||||
/// An vibration device factory that creates vibration devices from SDL joystick
|
||||
class SDLVibrationFactory final : public Input::Factory<Input::VibrationDevice> {
|
||||
public:
|
||||
explicit SDLVibrationFactory(SDLState& state_) : state(state_) {}
|
||||
/**
|
||||
* Creates a vibration device from a joystick
|
||||
* @param params contains parameters for creating the device:
|
||||
* - "guid": the guid of the joystick to bind
|
||||
* - "port": the nth joystick of the same type
|
||||
*/
|
||||
std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override {
|
||||
const std::string guid = params.Get("guid", "0");
|
||||
const int port = params.Get("port", 0);
|
||||
return std::make_unique<SDLVibration>(state.GetSDLJoystickByGUID(guid, port));
|
||||
}
|
||||
|
||||
private:
|
||||
SDLState& state;
|
||||
};
|
||||
|
||||
/// A motion device factory that creates motion devices from SDL joystick
|
||||
class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> {
|
||||
public:
|
||||
|
@ -650,11 +670,13 @@ private:
|
|||
|
||||
SDLState::SDLState() {
|
||||
using namespace Input;
|
||||
analog_factory = std::make_shared<SDLAnalogFactory>(*this);
|
||||
button_factory = std::make_shared<SDLButtonFactory>(*this);
|
||||
analog_factory = std::make_shared<SDLAnalogFactory>(*this);
|
||||
vibration_factory = std::make_shared<SDLVibrationFactory>(*this);
|
||||
motion_factory = std::make_shared<SDLMotionFactory>(*this);
|
||||
RegisterFactory<AnalogDevice>("sdl", analog_factory);
|
||||
RegisterFactory<ButtonDevice>("sdl", button_factory);
|
||||
RegisterFactory<AnalogDevice>("sdl", analog_factory);
|
||||
RegisterFactory<VibrationDevice>("sdl", vibration_factory);
|
||||
RegisterFactory<MotionDevice>("sdl", motion_factory);
|
||||
|
||||
// If the frontend is going to manage the event loop, then we don't start one here
|
||||
|
@ -676,7 +698,7 @@ SDLState::SDLState() {
|
|||
using namespace std::chrono_literals;
|
||||
while (initialized) {
|
||||
SDL_PumpEvents();
|
||||
std::this_thread::sleep_for(5ms);
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -691,6 +713,7 @@ SDLState::~SDLState() {
|
|||
using namespace Input;
|
||||
UnregisterFactory<ButtonDevice>("sdl");
|
||||
UnregisterFactory<AnalogDevice>("sdl");
|
||||
UnregisterFactory<VibrationDevice>("sdl");
|
||||
UnregisterFactory<MotionDevice>("sdl");
|
||||
|
||||
CloseJoysticks();
|
||||
|
@ -1045,7 +1068,6 @@ public:
|
|||
|
||||
void Start(const std::string& device_id) override {
|
||||
SDLPoller::Start(device_id);
|
||||
// Load the game controller
|
||||
// Reset stored axes
|
||||
analog_x_axis = -1;
|
||||
analog_y_axis = -1;
|
||||
|
@ -1058,40 +1080,21 @@ public:
|
|||
if (event.type == SDL_JOYAXISMOTION && std::abs(event.jaxis.value / 32767.0) < 0.5) {
|
||||
continue;
|
||||
}
|
||||
// Simplify controller config by testing if game controller support is enabled.
|
||||
if (event.type == SDL_JOYAXISMOTION) {
|
||||
const auto axis = event.jaxis.axis;
|
||||
if (const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
|
||||
auto* const controller = joystick->GetSDLGameController()) {
|
||||
const auto axis_left_x =
|
||||
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX)
|
||||
.value.axis;
|
||||
const auto axis_left_y =
|
||||
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY)
|
||||
.value.axis;
|
||||
const auto axis_right_x =
|
||||
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX)
|
||||
.value.axis;
|
||||
const auto axis_right_y =
|
||||
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY)
|
||||
.value.axis;
|
||||
|
||||
if (axis == axis_left_x || axis == axis_left_y) {
|
||||
analog_x_axis = axis_left_x;
|
||||
analog_y_axis = axis_left_y;
|
||||
break;
|
||||
} else if (axis == axis_right_x || axis == axis_right_y) {
|
||||
analog_x_axis = axis_right_x;
|
||||
analog_y_axis = axis_right_y;
|
||||
break;
|
||||
}
|
||||
// In order to return a complete analog param, we need inputs for both axes.
|
||||
// First we take the x-axis (horizontal) input, then the y-axis (vertical) input.
|
||||
if (analog_x_axis == -1) {
|
||||
analog_x_axis = axis;
|
||||
} else if (analog_y_axis == -1 && analog_x_axis != axis) {
|
||||
analog_y_axis = axis;
|
||||
}
|
||||
} else {
|
||||
// If the press wasn't accepted as a joy axis, check for a button press
|
||||
auto button_press = button_poller.FromEvent(event);
|
||||
if (button_press) {
|
||||
return *button_press;
|
||||
}
|
||||
}
|
||||
|
||||
// If the press wasn't accepted as a joy axis, check for a button press
|
||||
auto button_press = button_poller.FromEvent(event);
|
||||
if (button_press) {
|
||||
return *button_press;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1104,6 +1107,7 @@ public:
|
|||
return params;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace InputCommon::SDL {
|
|||
class SDLAnalogFactory;
|
||||
class SDLButtonFactory;
|
||||
class SDLMotionFactory;
|
||||
class SDLVibrationFactory;
|
||||
class SDLJoystick;
|
||||
|
||||
class SDLState : public State {
|
||||
|
@ -72,6 +73,7 @@ private:
|
|||
|
||||
std::shared_ptr<SDLButtonFactory> button_factory;
|
||||
std::shared_ptr<SDLAnalogFactory> analog_factory;
|
||||
std::shared_ptr<SDLVibrationFactory> vibration_factory;
|
||||
std::shared_ptr<SDLMotionFactory> motion_factory;
|
||||
|
||||
bool start_thread = false;
|
||||
|
|
|
@ -14,13 +14,6 @@ const std::array<const char*, NumButtons> mapping = {{
|
|||
}};
|
||||
}
|
||||
|
||||
namespace NativeMotion {
|
||||
const std::array<const char*, NumMotions> mapping = {{
|
||||
"motionleft",
|
||||
"motionright",
|
||||
}};
|
||||
}
|
||||
|
||||
namespace NativeAnalog {
|
||||
const std::array<const char*, NumAnalogs> mapping = {{
|
||||
"lstick",
|
||||
|
@ -28,6 +21,20 @@ const std::array<const char*, NumAnalogs> mapping = {{
|
|||
}};
|
||||
}
|
||||
|
||||
namespace NativeVibration {
|
||||
const std::array<const char*, NumVibrations> mapping = {{
|
||||
"left_vibration_device",
|
||||
"right_vibration_device",
|
||||
}};
|
||||
}
|
||||
|
||||
namespace NativeMotion {
|
||||
const std::array<const char*, NumMotions> mapping = {{
|
||||
"motionleft",
|
||||
"motionright",
|
||||
}};
|
||||
}
|
||||
|
||||
namespace NativeMouseButton {
|
||||
const std::array<const char*, NumMouseButtons> mapping = {{
|
||||
"left",
|
||||
|
|
|
@ -66,17 +66,32 @@ constexpr int NUM_STICKS_HID = NumAnalogs;
|
|||
extern const std::array<const char*, NumAnalogs> mapping;
|
||||
} // namespace NativeAnalog
|
||||
|
||||
namespace NativeVibration {
|
||||
enum Values : int {
|
||||
LeftVibrationDevice,
|
||||
RightVibrationDevice,
|
||||
|
||||
NumVibrations,
|
||||
};
|
||||
|
||||
constexpr int VIBRATION_HID_BEGIN = LeftVibrationDevice;
|
||||
constexpr int VIBRATION_HID_END = NumVibrations;
|
||||
constexpr int NUM_VIBRATIONS_HID = NumVibrations;
|
||||
|
||||
extern const std::array<const char*, NumVibrations> mapping;
|
||||
}; // namespace NativeVibration
|
||||
|
||||
namespace NativeMotion {
|
||||
enum Values : int {
|
||||
MOTIONLEFT,
|
||||
MOTIONRIGHT,
|
||||
MotionLeft,
|
||||
MotionRight,
|
||||
|
||||
NumMotions,
|
||||
};
|
||||
|
||||
constexpr int MOTION_HID_BEGIN = MOTIONLEFT;
|
||||
constexpr int MOTION_HID_BEGIN = MotionLeft;
|
||||
constexpr int MOTION_HID_END = NumMotions;
|
||||
constexpr int NUM_MOTION_HID = NumMotions;
|
||||
constexpr int NUM_MOTIONS_HID = NumMotions;
|
||||
|
||||
extern const std::array<const char*, NumMotions> mapping;
|
||||
} // namespace NativeMotion
|
||||
|
@ -305,9 +320,11 @@ constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods;
|
|||
|
||||
} // namespace NativeKeyboard
|
||||
|
||||
using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
|
||||
using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
|
||||
using MotionRaw = std::array<std::string, NativeMotion::NumMotions>;
|
||||
using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
|
||||
using MotionsRaw = std::array<std::string, NativeMotion::NumMotions>;
|
||||
using VibrationsRaw = std::array<std::string, NativeVibration::NumVibrations>;
|
||||
|
||||
using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>;
|
||||
using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>;
|
||||
using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>;
|
||||
|
@ -330,7 +347,11 @@ struct PlayerInput {
|
|||
ControllerType controller_type;
|
||||
ButtonsRaw buttons;
|
||||
AnalogsRaw analogs;
|
||||
MotionRaw motions;
|
||||
VibrationsRaw vibrations;
|
||||
MotionsRaw motions;
|
||||
|
||||
bool vibration_enabled;
|
||||
int vibration_strength;
|
||||
|
||||
u32 body_color_left;
|
||||
u32 body_color_right;
|
||||
|
|
|
@ -344,7 +344,7 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index,
|
|||
};
|
||||
Socket socket{host, port, pad_index, client_id, std::move(callback)};
|
||||
std::thread worker_thread{SocketLoop, &socket};
|
||||
const bool result = success_event.WaitFor(std::chrono::seconds(8));
|
||||
const bool result = success_event.WaitFor(std::chrono::seconds(5));
|
||||
socket.Stop();
|
||||
worker_thread.join();
|
||||
if (result) {
|
||||
|
|
|
@ -68,12 +68,12 @@ add_executable(yuzu
|
|||
configuration/configure_input_advanced.cpp
|
||||
configuration/configure_input_advanced.h
|
||||
configuration/configure_input_advanced.ui
|
||||
configuration/configure_input_dialog.cpp
|
||||
configuration/configure_input_dialog.h
|
||||
configuration/configure_input_dialog.ui
|
||||
configuration/configure_input_player.cpp
|
||||
configuration/configure_input_player.h
|
||||
configuration/configure_input_player.ui
|
||||
configuration/configure_input_profile_dialog.cpp
|
||||
configuration/configure_input_profile_dialog.h
|
||||
configuration/configure_input_profile_dialog.ui
|
||||
configuration/configure_motion_touch.cpp
|
||||
configuration/configure_motion_touch.h
|
||||
configuration/configure_motion_touch.ui
|
||||
|
@ -105,9 +105,14 @@ add_executable(yuzu
|
|||
configuration/configure_ui.cpp
|
||||
configuration/configure_ui.h
|
||||
configuration/configure_ui.ui
|
||||
configuration/configure_vibration.cpp
|
||||
configuration/configure_vibration.h
|
||||
configuration/configure_vibration.ui
|
||||
configuration/configure_web.cpp
|
||||
configuration/configure_web.h
|
||||
configuration/configure_web.ui
|
||||
configuration/input_profiles.cpp
|
||||
configuration/input_profiles.h
|
||||
debugger/console.cpp
|
||||
debugger/console.h
|
||||
debugger/profiler.cpp
|
||||
|
|
|
@ -160,32 +160,12 @@ p, li { white-space: pre-wrap; }
|
|||
<signal>accepted()</signal>
|
||||
<receiver>AboutDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AboutDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/string_util.h"
|
||||
|
@ -13,11 +14,16 @@
|
|||
#include "core/hle/service/sm/sm.h"
|
||||
#include "ui_controller.h"
|
||||
#include "yuzu/applets/controller.h"
|
||||
#include "yuzu/configuration/configure_input_dialog.h"
|
||||
#include "yuzu/configuration/configure_input.h"
|
||||
#include "yuzu/configuration/configure_input_profile_dialog.h"
|
||||
#include "yuzu/configuration/configure_vibration.h"
|
||||
#include "yuzu/configuration/input_profiles.h"
|
||||
#include "yuzu/main.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr std::size_t HANDHELD_INDEX = 8;
|
||||
|
||||
constexpr std::array<std::array<bool, 4>, 8> led_patterns{{
|
||||
{true, false, false, false},
|
||||
{true, true, false, false},
|
||||
|
@ -106,7 +112,8 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
|
|||
QWidget* parent, Core::Frontend::ControllerParameters parameters_,
|
||||
InputCommon::InputSubsystem* input_subsystem_)
|
||||
: QDialog(parent), ui(std::make_unique<Ui::QtControllerSelectorDialog>()),
|
||||
parameters(std::move(parameters_)), input_subsystem(input_subsystem_) {
|
||||
parameters(std::move(parameters_)), input_subsystem{input_subsystem_},
|
||||
input_profiles(std::make_unique<InputProfiles>()) {
|
||||
ui->setupUi(this);
|
||||
|
||||
player_widgets = {
|
||||
|
@ -223,12 +230,22 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
|
|||
}
|
||||
}
|
||||
|
||||
connect(ui->vibrationButton, &QPushButton::clicked, this,
|
||||
&QtControllerSelectorDialog::CallConfigureVibrationDialog);
|
||||
|
||||
connect(ui->inputConfigButton, &QPushButton::clicked, this,
|
||||
&QtControllerSelectorDialog::CallConfigureInputDialog);
|
||||
&QtControllerSelectorDialog::CallConfigureInputProfileDialog);
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
|
||||
&QtControllerSelectorDialog::ApplyConfiguration);
|
||||
|
||||
// Enhancement: Check if the parameters have already been met before disconnecting controllers.
|
||||
// If all the parameters are met AND only allows a single player,
|
||||
// stop the constructor here as we do not need to continue.
|
||||
if (CheckIfParametersMet() && parameters.enable_single_mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If keep_controllers_connected is false, forcefully disconnect all controllers
|
||||
if (!parameters.keep_controllers_connected) {
|
||||
for (auto player : player_groupboxes) {
|
||||
|
@ -236,58 +253,66 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
|
|||
}
|
||||
}
|
||||
|
||||
CheckIfParametersMet();
|
||||
|
||||
resize(0, 0);
|
||||
}
|
||||
|
||||
QtControllerSelectorDialog::~QtControllerSelectorDialog() = default;
|
||||
|
||||
void QtControllerSelectorDialog::ApplyConfiguration() {
|
||||
// Update the controller state once more, just to be sure they are properly applied.
|
||||
for (std::size_t index = 0; index < NUM_PLAYERS; ++index) {
|
||||
UpdateControllerState(index);
|
||||
int QtControllerSelectorDialog::exec() {
|
||||
if (parameters_met && parameters.enable_single_mode) {
|
||||
return QDialog::Accepted;
|
||||
}
|
||||
return QDialog::exec();
|
||||
}
|
||||
|
||||
const bool pre_docked_mode = Settings::values.use_docked_mode;
|
||||
Settings::values.use_docked_mode = ui->radioDocked->isChecked();
|
||||
OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode);
|
||||
void QtControllerSelectorDialog::ApplyConfiguration() {
|
||||
const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
|
||||
Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked());
|
||||
OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue());
|
||||
|
||||
Settings::values.vibration_enabled = ui->vibrationGroup->isChecked();
|
||||
Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
|
||||
Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked());
|
||||
}
|
||||
|
||||
void QtControllerSelectorDialog::LoadConfiguration() {
|
||||
for (std::size_t index = 0; index < NUM_PLAYERS; ++index) {
|
||||
const auto connected = Settings::values.players[index].connected ||
|
||||
(index == 0 && Settings::values.players[8].connected);
|
||||
const auto connected =
|
||||
Settings::values.players.GetValue()[index].connected ||
|
||||
(index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected);
|
||||
player_groupboxes[index]->setChecked(connected);
|
||||
connected_controller_checkboxes[index]->setChecked(connected);
|
||||
emulated_controllers[index]->setCurrentIndex(
|
||||
GetIndexFromControllerType(Settings::values.players[index].controller_type));
|
||||
GetIndexFromControllerType(Settings::values.players.GetValue()[index].controller_type));
|
||||
}
|
||||
|
||||
UpdateDockedState(Settings::values.players[8].connected);
|
||||
UpdateDockedState(Settings::values.players.GetValue()[HANDHELD_INDEX].connected);
|
||||
|
||||
ui->vibrationGroup->setChecked(Settings::values.vibration_enabled);
|
||||
ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue());
|
||||
ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue());
|
||||
}
|
||||
|
||||
void QtControllerSelectorDialog::CallConfigureInputDialog() {
|
||||
const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players;
|
||||
void QtControllerSelectorDialog::CallConfigureVibrationDialog() {
|
||||
ConfigureVibration dialog(this);
|
||||
|
||||
ConfigureInputDialog dialog(this, max_supported_players, input_subsystem);
|
||||
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
|
||||
Qt::WindowSystemMenuHint);
|
||||
dialog.setWindowModality(Qt::WindowModal);
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
dialog.ApplyConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
void QtControllerSelectorDialog::CallConfigureInputProfileDialog() {
|
||||
ConfigureInputProfileDialog dialog(this, input_subsystem, input_profiles.get());
|
||||
|
||||
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
|
||||
Qt::WindowSystemMenuHint);
|
||||
dialog.setWindowModality(Qt::WindowModal);
|
||||
dialog.exec();
|
||||
|
||||
dialog.ApplyConfiguration();
|
||||
|
||||
LoadConfiguration();
|
||||
CheckIfParametersMet();
|
||||
}
|
||||
|
||||
void QtControllerSelectorDialog::CheckIfParametersMet() {
|
||||
bool QtControllerSelectorDialog::CheckIfParametersMet() {
|
||||
// Here, we check and validate the current configuration against all applicable parameters.
|
||||
const auto num_connected_players = static_cast<int>(
|
||||
std::count_if(player_groupboxes.begin(), player_groupboxes.end(),
|
||||
|
@ -301,7 +326,7 @@ void QtControllerSelectorDialog::CheckIfParametersMet() {
|
|||
num_connected_players > max_supported_players) {
|
||||
parameters_met = false;
|
||||
ui->buttonBox->setEnabled(parameters_met);
|
||||
return;
|
||||
return parameters_met;
|
||||
}
|
||||
|
||||
// Next, check against all connected controllers.
|
||||
|
@ -326,18 +351,13 @@ void QtControllerSelectorDialog::CheckIfParametersMet() {
|
|||
return true;
|
||||
}();
|
||||
|
||||
if (!all_controllers_compatible) {
|
||||
parameters_met = false;
|
||||
ui->buttonBox->setEnabled(parameters_met);
|
||||
return;
|
||||
}
|
||||
|
||||
parameters_met = true;
|
||||
parameters_met = all_controllers_compatible;
|
||||
ui->buttonBox->setEnabled(parameters_met);
|
||||
return parameters_met;
|
||||
}
|
||||
|
||||
void QtControllerSelectorDialog::SetSupportedControllers() {
|
||||
const QString theme = [this] {
|
||||
const QString theme = [] {
|
||||
if (QIcon::themeName().contains(QStringLiteral("dark"))) {
|
||||
return QStringLiteral("_dark");
|
||||
} else if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
|
||||
|
@ -426,7 +446,7 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index)
|
|||
}
|
||||
}();
|
||||
|
||||
const QString theme = [this] {
|
||||
const QString theme = [] {
|
||||
if (QIcon::themeName().contains(QStringLiteral("dark"))) {
|
||||
return QStringLiteral("_dark");
|
||||
} else if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
|
||||
|
@ -441,32 +461,48 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index)
|
|||
}
|
||||
|
||||
void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) {
|
||||
auto& player = Settings::values.players[player_index];
|
||||
auto& player = Settings::values.players.GetValue()[player_index];
|
||||
|
||||
player.controller_type =
|
||||
const auto controller_type =
|
||||
GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex());
|
||||
player.connected = player_groupboxes[player_index]->isChecked();
|
||||
const auto player_connected = player_groupboxes[player_index]->isChecked() &&
|
||||
controller_type != Settings::ControllerType::Handheld;
|
||||
|
||||
// Player 2-8
|
||||
if (player_index != 0) {
|
||||
UpdateController(player.controller_type, player_index, player.connected);
|
||||
if (player.controller_type == controller_type && player.connected == player_connected) {
|
||||
// Set vibration devices in the event that the input device has changed.
|
||||
ConfigureVibration::SetVibrationDevices(player_index);
|
||||
return;
|
||||
}
|
||||
|
||||
// Player 1 and Handheld
|
||||
auto& handheld = Settings::values.players[8];
|
||||
// If Handheld is selected, copy all the settings from Player 1 to Handheld.
|
||||
if (player.controller_type == Settings::ControllerType::Handheld) {
|
||||
handheld = player;
|
||||
handheld.connected = player_groupboxes[player_index]->isChecked();
|
||||
player.connected = false; // Disconnect Player 1
|
||||
} else {
|
||||
player.connected = player_groupboxes[player_index]->isChecked();
|
||||
handheld.connected = false; // Disconnect Handheld
|
||||
// Disconnect the controller first.
|
||||
UpdateController(controller_type, player_index, false);
|
||||
|
||||
player.controller_type = controller_type;
|
||||
player.connected = player_connected;
|
||||
|
||||
ConfigureVibration::SetVibrationDevices(player_index);
|
||||
|
||||
// Handheld
|
||||
if (player_index == 0) {
|
||||
auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
|
||||
if (controller_type == Settings::ControllerType::Handheld) {
|
||||
handheld = player;
|
||||
}
|
||||
handheld.connected = player_groupboxes[player_index]->isChecked() &&
|
||||
controller_type == Settings::ControllerType::Handheld;
|
||||
UpdateController(Settings::ControllerType::Handheld, 8, handheld.connected);
|
||||
}
|
||||
|
||||
UpdateController(player.controller_type, player_index, player.connected);
|
||||
UpdateController(Settings::ControllerType::Handheld, 8, handheld.connected);
|
||||
if (!player.connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This emulates a delay between disconnecting and reconnecting controllers as some games
|
||||
// do not respond to a change in controller type if it was instantaneous.
|
||||
using namespace std::chrono_literals;
|
||||
std::this_thread::sleep_for(20ms);
|
||||
|
||||
UpdateController(controller_type, player_index, player_connected);
|
||||
}
|
||||
|
||||
void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) {
|
||||
|
@ -520,8 +556,8 @@ void QtControllerSelectorDialog::UpdateDockedState(bool is_handheld) {
|
|||
ui->radioDocked->setEnabled(!is_handheld);
|
||||
ui->radioUndocked->setEnabled(!is_handheld);
|
||||
|
||||
ui->radioDocked->setChecked(Settings::values.use_docked_mode);
|
||||
ui->radioUndocked->setChecked(!Settings::values.use_docked_mode);
|
||||
ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue());
|
||||
ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue());
|
||||
|
||||
// Also force into undocked mode if the controller type is handheld.
|
||||
if (is_handheld) {
|
||||
|
@ -564,8 +600,8 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() {
|
|||
|
||||
for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) {
|
||||
// Disconnect any unsupported players here and disable or hide them if applicable.
|
||||
Settings::values.players[index].connected = false;
|
||||
UpdateController(Settings::values.players[index].controller_type, index, false);
|
||||
Settings::values.players.GetValue()[index].connected = false;
|
||||
UpdateController(Settings::values.players.GetValue()[index].controller_type, index, false);
|
||||
// Hide the player widgets when max_supported_controllers is less than or equal to 4.
|
||||
if (max_supported_players <= 4) {
|
||||
player_widgets[index]->hide();
|
||||
|
|
|
@ -16,6 +16,8 @@ class QDialogButtonBox;
|
|||
class QGroupBox;
|
||||
class QLabel;
|
||||
|
||||
class InputProfiles;
|
||||
|
||||
namespace InputCommon {
|
||||
class InputSubsystem;
|
||||
}
|
||||
|
@ -33,6 +35,8 @@ public:
|
|||
InputCommon::InputSubsystem* input_subsystem_);
|
||||
~QtControllerSelectorDialog() override;
|
||||
|
||||
int exec() override;
|
||||
|
||||
private:
|
||||
// Applies the current configuration.
|
||||
void ApplyConfiguration();
|
||||
|
@ -40,12 +44,15 @@ private:
|
|||
// Loads the current input configuration into the frontend applet.
|
||||
void LoadConfiguration();
|
||||
|
||||
// Initializes the "Configure Input" Dialog.
|
||||
void CallConfigureInputDialog();
|
||||
// Initializes the "Configure Vibration" Dialog.
|
||||
void CallConfigureVibrationDialog();
|
||||
|
||||
// Checks the current configuration against the given parameters and
|
||||
// sets the value of parameters_met.
|
||||
void CheckIfParametersMet();
|
||||
// Initializes the "Create Input Profile" Dialog.
|
||||
void CallConfigureInputProfileDialog();
|
||||
|
||||
// Checks the current configuration against the given parameters.
|
||||
// This sets and returns the value of parameters_met.
|
||||
bool CheckIfParametersMet();
|
||||
|
||||
// Sets the controller icons for "Supported Controller Types".
|
||||
void SetSupportedControllers();
|
||||
|
@ -78,6 +85,8 @@ private:
|
|||
|
||||
InputCommon::InputSubsystem* input_subsystem;
|
||||
|
||||
std::unique_ptr<InputProfiles> input_profiles;
|
||||
|
||||
// This is true if and only if all parameters are met. Otherwise, this is false.
|
||||
// This determines whether the "OK" button can be clicked to exit the applet.
|
||||
bool parameters_met{false};
|
||||
|
|
|
@ -1217,9 +1217,6 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboPlayer3Emulated">
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Pro Controller</string>
|
||||
|
@ -2279,7 +2276,7 @@
|
|||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
|
@ -2332,30 +2329,24 @@
|
|||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="vibrationSpin">
|
||||
<widget class="QPushButton" name="vibrationButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>65</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>65</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -2387,18 +2378,18 @@
|
|||
<widget class="QPushButton" name="motionButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
|
@ -2411,7 +2402,7 @@
|
|||
<item>
|
||||
<widget class="QGroupBox" name="inputConfigGroup">
|
||||
<property name="title">
|
||||
<string>Input Config</string>
|
||||
<string>Profiles</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<property name="leftMargin">
|
||||
|
@ -2430,15 +2421,15 @@
|
|||
<widget class="QPushButton" name="inputConfigButton">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>65</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open</string>
|
||||
<string>Create</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -2657,16 +2648,6 @@
|
|||
<signal>accepted()</signal>
|
||||
<receiver>QtControllerSelectorDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
|
@ -382,7 +382,12 @@ void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
|
|||
}
|
||||
|
||||
void GRenderWindow::mousePressEvent(QMouseEvent* event) {
|
||||
// touch input is handled in TouchBeginEvent
|
||||
if (!Settings::values.touchscreen.enabled) {
|
||||
input_subsystem->GetKeyboard()->PressKey(event->button());
|
||||
return;
|
||||
}
|
||||
|
||||
// Touch input is handled in TouchBeginEvent
|
||||
if (event->source() == Qt::MouseEventSynthesizedBySystem) {
|
||||
return;
|
||||
}
|
||||
|
@ -398,7 +403,7 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) {
|
|||
}
|
||||
|
||||
void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
|
||||
// touch input is handled in TouchUpdateEvent
|
||||
// Touch input is handled in TouchUpdateEvent
|
||||
if (event->source() == Qt::MouseEventSynthesizedBySystem) {
|
||||
return;
|
||||
}
|
||||
|
@ -411,7 +416,12 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
|
|||
}
|
||||
|
||||
void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
|
||||
// touch input is handled in TouchEndEvent
|
||||
if (!Settings::values.touchscreen.enabled) {
|
||||
input_subsystem->GetKeyboard()->ReleaseKey(event->button());
|
||||
return;
|
||||
}
|
||||
|
||||
// Touch input is handled in TouchEndEvent
|
||||
if (event->source() == Qt::MouseEventSynthesizedBySystem) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <array>
|
||||
#include <QKeySequence>
|
||||
#include <QSettings>
|
||||
#include "common/common_paths.h"
|
||||
#include "common/file_util.h"
|
||||
#include "core/hle/service/acc/profile_manager.h"
|
||||
#include "core/hle/service/hid/controllers/npad.h"
|
||||
|
@ -14,14 +15,10 @@
|
|||
|
||||
namespace FS = Common::FS;
|
||||
|
||||
Config::Config(const std::string& config_file, bool is_global) {
|
||||
// TODO: Don't hardcode the path; let the frontend decide where to put the config files.
|
||||
qt_config_loc = FS::GetUserPath(FS::UserPath::ConfigDir) + config_file;
|
||||
FS::CreateFullPath(qt_config_loc);
|
||||
qt_config =
|
||||
std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat);
|
||||
global = is_global;
|
||||
Reload();
|
||||
Config::Config(const std::string& config_name, ConfigType config_type) : type(config_type) {
|
||||
global = config_type == ConfigType::GlobalConfig;
|
||||
|
||||
Initialize(config_name);
|
||||
}
|
||||
|
||||
Config::~Config() {
|
||||
|
@ -242,84 +239,152 @@ const std::array<UISettings::Shortcut, 16> Config::default_hotkeys{{
|
|||
}};
|
||||
// clang-format on
|
||||
|
||||
void Config::ReadPlayerValues() {
|
||||
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) {
|
||||
auto& player = Settings::values.players[p];
|
||||
void Config::Initialize(const std::string& config_name) {
|
||||
switch (type) {
|
||||
case ConfigType::GlobalConfig:
|
||||
qt_config_loc = fmt::format("{}" DIR_SEP "{}.ini", FS::GetUserPath(FS::UserPath::ConfigDir),
|
||||
config_name);
|
||||
FS::CreateFullPath(qt_config_loc);
|
||||
qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc),
|
||||
QSettings::IniFormat);
|
||||
Reload();
|
||||
break;
|
||||
case ConfigType::PerGameConfig:
|
||||
qt_config_loc = fmt::format("{}custom" DIR_SEP "{}.ini",
|
||||
FS::GetUserPath(FS::UserPath::ConfigDir), config_name);
|
||||
FS::CreateFullPath(qt_config_loc);
|
||||
qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc),
|
||||
QSettings::IniFormat);
|
||||
Reload();
|
||||
break;
|
||||
case ConfigType::InputProfile:
|
||||
qt_config_loc = fmt::format("{}input" DIR_SEP "{}.ini",
|
||||
FS::GetUserPath(FS::UserPath::ConfigDir), config_name);
|
||||
FS::CreateFullPath(qt_config_loc);
|
||||
qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc),
|
||||
QSettings::IniFormat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
player.connected =
|
||||
ReadSetting(QStringLiteral("player_%1_connected").arg(p), false).toBool();
|
||||
void Config::ReadPlayerValue(std::size_t player_index) {
|
||||
const QString player_prefix = [this, player_index] {
|
||||
if (type == ConfigType::InputProfile) {
|
||||
return QString{};
|
||||
} else {
|
||||
return QStringLiteral("player_%1_").arg(player_index);
|
||||
}
|
||||
}();
|
||||
|
||||
player.controller_type = static_cast<Settings::ControllerType>(
|
||||
auto& player = Settings::values.players.GetValue()[player_index];
|
||||
|
||||
if (player_prefix.isEmpty()) {
|
||||
const auto controller = static_cast<Settings::ControllerType>(
|
||||
qt_config
|
||||
->value(QStringLiteral("player_%1_type").arg(p),
|
||||
->value(QStringLiteral("%1type").arg(player_prefix),
|
||||
static_cast<u8>(Settings::ControllerType::ProController))
|
||||
.toUInt());
|
||||
|
||||
if (controller == Settings::ControllerType::LeftJoycon ||
|
||||
controller == Settings::ControllerType::RightJoycon) {
|
||||
player.controller_type = controller;
|
||||
}
|
||||
} else {
|
||||
player.connected =
|
||||
ReadSetting(QStringLiteral("%1connected").arg(player_prefix), player_index == 0)
|
||||
.toBool();
|
||||
|
||||
player.controller_type = static_cast<Settings::ControllerType>(
|
||||
qt_config
|
||||
->value(QStringLiteral("%1type").arg(player_prefix),
|
||||
static_cast<u8>(Settings::ControllerType::ProController))
|
||||
.toUInt());
|
||||
|
||||
player.vibration_enabled =
|
||||
qt_config->value(QStringLiteral("%1vibration_enabled").arg(player_prefix), true)
|
||||
.toBool();
|
||||
|
||||
player.vibration_strength =
|
||||
qt_config->value(QStringLiteral("%1vibration_strength").arg(player_prefix), 100)
|
||||
.toInt();
|
||||
|
||||
player.body_color_left = qt_config
|
||||
->value(QStringLiteral("player_%1_body_color_left").arg(p),
|
||||
->value(QStringLiteral("%1body_color_left").arg(player_prefix),
|
||||
Settings::JOYCON_BODY_NEON_BLUE)
|
||||
.toUInt();
|
||||
player.body_color_right = qt_config
|
||||
->value(QStringLiteral("player_%1_body_color_right").arg(p),
|
||||
Settings::JOYCON_BODY_NEON_RED)
|
||||
.toUInt();
|
||||
player.button_color_left = qt_config
|
||||
->value(QStringLiteral("player_%1_button_color_left").arg(p),
|
||||
Settings::JOYCON_BUTTONS_NEON_BLUE)
|
||||
.toUInt();
|
||||
player.body_color_right =
|
||||
qt_config
|
||||
->value(QStringLiteral("%1body_color_right").arg(player_prefix),
|
||||
Settings::JOYCON_BODY_NEON_RED)
|
||||
.toUInt();
|
||||
player.button_color_left =
|
||||
qt_config
|
||||
->value(QStringLiteral("%1button_color_left").arg(player_prefix),
|
||||
Settings::JOYCON_BUTTONS_NEON_BLUE)
|
||||
.toUInt();
|
||||
player.button_color_right =
|
||||
qt_config
|
||||
->value(QStringLiteral("player_%1_button_color_right").arg(p),
|
||||
->value(QStringLiteral("%1button_color_right").arg(player_prefix),
|
||||
Settings::JOYCON_BUTTONS_NEON_RED)
|
||||
.toUInt();
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
const std::string default_param =
|
||||
InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
auto& player_buttons = player.buttons[i];
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
auto& player_buttons = player.buttons[i];
|
||||
|
||||
player_buttons = qt_config
|
||||
->value(QStringLiteral("player_%1_").arg(p) +
|
||||
QString::fromUtf8(Settings::NativeButton::mapping[i]),
|
||||
QString::fromStdString(default_param))
|
||||
.toString()
|
||||
.toStdString();
|
||||
if (player_buttons.empty()) {
|
||||
player_buttons = default_param;
|
||||
}
|
||||
player_buttons = qt_config
|
||||
->value(QStringLiteral("%1").arg(player_prefix) +
|
||||
QString::fromUtf8(Settings::NativeButton::mapping[i]),
|
||||
QString::fromStdString(default_param))
|
||||
.toString()
|
||||
.toStdString();
|
||||
if (player_buttons.empty()) {
|
||||
player_buttons = default_param;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
|
||||
const std::string default_param =
|
||||
InputCommon::GenerateKeyboardParam(default_motions[i]);
|
||||
auto& player_motions = player.motions[i];
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
||||
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
||||
auto& player_analogs = player.analogs[i];
|
||||
|
||||
player_motions = qt_config
|
||||
->value(QStringLiteral("player_%1_").arg(p) +
|
||||
QString::fromUtf8(Settings::NativeMotion::mapping[i]),
|
||||
QString::fromStdString(default_param))
|
||||
.toString()
|
||||
.toStdString();
|
||||
if (player_motions.empty()) {
|
||||
player_motions = default_param;
|
||||
}
|
||||
player_analogs = qt_config
|
||||
->value(QStringLiteral("%1").arg(player_prefix) +
|
||||
QString::fromUtf8(Settings::NativeAnalog::mapping[i]),
|
||||
QString::fromStdString(default_param))
|
||||
.toString()
|
||||
.toStdString();
|
||||
if (player_analogs.empty()) {
|
||||
player_analogs = default_param;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
||||
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
||||
auto& player_analogs = player.analogs[i];
|
||||
for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) {
|
||||
auto& player_vibrations = player.vibrations[i];
|
||||
|
||||
player_analogs = qt_config
|
||||
->value(QStringLiteral("player_%1_").arg(p) +
|
||||
QString::fromUtf8(Settings::NativeAnalog::mapping[i]),
|
||||
QString::fromStdString(default_param))
|
||||
.toString()
|
||||
.toStdString();
|
||||
if (player_analogs.empty()) {
|
||||
player_analogs = default_param;
|
||||
}
|
||||
player_vibrations =
|
||||
qt_config
|
||||
->value(QStringLiteral("%1").arg(player_prefix) +
|
||||
QString::fromUtf8(Settings::NativeVibration::mapping[i]),
|
||||
QString{})
|
||||
.toString()
|
||||
.toStdString();
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
|
||||
auto& player_motions = player.motions[i];
|
||||
|
||||
player_motions = qt_config
|
||||
->value(QStringLiteral("%1").arg(player_prefix) +
|
||||
QString::fromUtf8(Settings::NativeMotion::mapping[i]),
|
||||
QString::fromStdString(default_param))
|
||||
.toString()
|
||||
.toStdString();
|
||||
if (player_motions.empty()) {
|
||||
player_motions = default_param;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -436,18 +501,21 @@ void Config::ReadAudioValues() {
|
|||
void Config::ReadControlValues() {
|
||||
qt_config->beginGroup(QStringLiteral("Controls"));
|
||||
|
||||
ReadPlayerValues();
|
||||
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
|
||||
ReadPlayerValue(p);
|
||||
}
|
||||
ReadDebugValues();
|
||||
ReadKeyboardValues();
|
||||
ReadMouseValues();
|
||||
ReadTouchscreenValues();
|
||||
ReadMotionTouchValues();
|
||||
|
||||
Settings::values.vibration_enabled =
|
||||
ReadSetting(QStringLiteral("vibration_enabled"), true).toBool();
|
||||
Settings::values.motion_enabled = ReadSetting(QStringLiteral("motion_enabled"), true).toBool();
|
||||
Settings::values.use_docked_mode =
|
||||
ReadSetting(QStringLiteral("use_docked_mode"), false).toBool();
|
||||
ReadSettingGlobal(Settings::values.use_docked_mode, QStringLiteral("use_docked_mode"), false);
|
||||
ReadSettingGlobal(Settings::values.vibration_enabled, QStringLiteral("vibration_enabled"),
|
||||
true);
|
||||
ReadSettingGlobal(Settings::values.enable_accurate_vibrations,
|
||||
QStringLiteral("enable_accurate_vibrations"), false);
|
||||
ReadSettingGlobal(Settings::values.motion_enabled, QStringLiteral("motion_enabled"), true);
|
||||
|
||||
qt_config->endGroup();
|
||||
}
|
||||
|
@ -920,49 +988,64 @@ void Config::ReadValues() {
|
|||
ReadSystemValues();
|
||||
}
|
||||
|
||||
void Config::SavePlayerValues() {
|
||||
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) {
|
||||
const auto& player = Settings::values.players[p];
|
||||
void Config::SavePlayerValue(std::size_t player_index) {
|
||||
const QString player_prefix = [this, player_index] {
|
||||
if (type == ConfigType::InputProfile) {
|
||||
return QString{};
|
||||
} else {
|
||||
return QStringLiteral("player_%1_").arg(player_index);
|
||||
}
|
||||
}();
|
||||
|
||||
WriteSetting(QStringLiteral("player_%1_connected").arg(p), player.connected, false);
|
||||
WriteSetting(QStringLiteral("player_%1_type").arg(p),
|
||||
static_cast<u8>(player.controller_type),
|
||||
static_cast<u8>(Settings::ControllerType::ProController));
|
||||
const auto& player = Settings::values.players.GetValue()[player_index];
|
||||
|
||||
WriteSetting(QStringLiteral("player_%1_body_color_left").arg(p), player.body_color_left,
|
||||
WriteSetting(QStringLiteral("%1type").arg(player_prefix),
|
||||
static_cast<u8>(player.controller_type),
|
||||
static_cast<u8>(Settings::ControllerType::ProController));
|
||||
|
||||
if (!player_prefix.isEmpty()) {
|
||||
WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected, false);
|
||||
WriteSetting(QStringLiteral("%1vibration_enabled").arg(player_prefix),
|
||||
player.vibration_enabled, true);
|
||||
WriteSetting(QStringLiteral("%1vibration_strength").arg(player_prefix),
|
||||
player.vibration_strength, 100);
|
||||
WriteSetting(QStringLiteral("%1body_color_left").arg(player_prefix), player.body_color_left,
|
||||
Settings::JOYCON_BODY_NEON_BLUE);
|
||||
WriteSetting(QStringLiteral("player_%1_body_color_right").arg(p), player.body_color_right,
|
||||
Settings::JOYCON_BODY_NEON_RED);
|
||||
WriteSetting(QStringLiteral("player_%1_button_color_left").arg(p), player.button_color_left,
|
||||
Settings::JOYCON_BUTTONS_NEON_BLUE);
|
||||
WriteSetting(QStringLiteral("player_%1_button_color_right").arg(p),
|
||||
WriteSetting(QStringLiteral("%1body_color_right").arg(player_prefix),
|
||||
player.body_color_right, Settings::JOYCON_BODY_NEON_RED);
|
||||
WriteSetting(QStringLiteral("%1button_color_left").arg(player_prefix),
|
||||
player.button_color_left, Settings::JOYCON_BUTTONS_NEON_BLUE);
|
||||
WriteSetting(QStringLiteral("%1button_color_right").arg(player_prefix),
|
||||
player.button_color_right, Settings::JOYCON_BUTTONS_NEON_RED);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
const std::string default_param =
|
||||
InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
WriteSetting(QStringLiteral("player_%1_").arg(p) +
|
||||
QString::fromStdString(Settings::NativeButton::mapping[i]),
|
||||
QString::fromStdString(player.buttons[i]),
|
||||
QString::fromStdString(default_param));
|
||||
}
|
||||
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
|
||||
const std::string default_param =
|
||||
InputCommon::GenerateKeyboardParam(default_motions[i]);
|
||||
WriteSetting(QStringLiteral("player_%1_").arg(p) +
|
||||
QString::fromStdString(Settings::NativeMotion::mapping[i]),
|
||||
QString::fromStdString(player.motions[i]),
|
||||
QString::fromStdString(default_param));
|
||||
}
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
||||
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
||||
WriteSetting(QStringLiteral("player_%1_").arg(p) +
|
||||
QString::fromStdString(Settings::NativeAnalog::mapping[i]),
|
||||
QString::fromStdString(player.analogs[i]),
|
||||
QString::fromStdString(default_param));
|
||||
}
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
WriteSetting(QStringLiteral("%1").arg(player_prefix) +
|
||||
QString::fromStdString(Settings::NativeButton::mapping[i]),
|
||||
QString::fromStdString(player.buttons[i]),
|
||||
QString::fromStdString(default_param));
|
||||
}
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
|
||||
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
|
||||
default_analogs[i][3], default_stick_mod[i], 0.5f);
|
||||
WriteSetting(QStringLiteral("%1").arg(player_prefix) +
|
||||
QString::fromStdString(Settings::NativeAnalog::mapping[i]),
|
||||
QString::fromStdString(player.analogs[i]),
|
||||
QString::fromStdString(default_param));
|
||||
}
|
||||
for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) {
|
||||
WriteSetting(QStringLiteral("%1").arg(player_prefix) +
|
||||
QString::fromStdString(Settings::NativeVibration::mapping[i]),
|
||||
QString::fromStdString(player.vibrations[i]), QString{});
|
||||
}
|
||||
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
|
||||
const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
|
||||
WriteSetting(QStringLiteral("%1").arg(player_prefix) +
|
||||
QString::fromStdString(Settings::NativeMotion::mapping[i]),
|
||||
QString::fromStdString(player.motions[i]),
|
||||
QString::fromStdString(default_param));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1087,14 +1170,20 @@ void Config::SaveAudioValues() {
|
|||
void Config::SaveControlValues() {
|
||||
qt_config->beginGroup(QStringLiteral("Controls"));
|
||||
|
||||
SavePlayerValues();
|
||||
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
|
||||
SavePlayerValue(p);
|
||||
}
|
||||
SaveDebugValues();
|
||||
SaveMouseValues();
|
||||
SaveTouchscreenValues();
|
||||
SaveMotionTouchValues();
|
||||
|
||||
WriteSetting(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled, true);
|
||||
WriteSetting(QStringLiteral("motion_enabled"), Settings::values.motion_enabled, true);
|
||||
WriteSettingGlobal(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false);
|
||||
WriteSettingGlobal(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled,
|
||||
true);
|
||||
WriteSettingGlobal(QStringLiteral("enable_accurate_vibrations"),
|
||||
Settings::values.enable_accurate_vibrations, false);
|
||||
WriteSettingGlobal(QStringLiteral("motion_enabled"), Settings::values.motion_enabled, true);
|
||||
WriteSetting(QStringLiteral("motion_device"),
|
||||
QString::fromStdString(Settings::values.motion_device),
|
||||
QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01"));
|
||||
|
@ -1102,7 +1191,6 @@ void Config::SaveControlValues() {
|
|||
QString::fromStdString(Settings::values.touch_device),
|
||||
QStringLiteral("engine:emu_window"));
|
||||
WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false);
|
||||
WriteSetting(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false);
|
||||
|
||||
qt_config->endGroup();
|
||||
}
|
||||
|
@ -1515,3 +1603,19 @@ void Config::Save() {
|
|||
Settings::Sanitize();
|
||||
SaveValues();
|
||||
}
|
||||
|
||||
void Config::ReadControlPlayerValue(std::size_t player_index) {
|
||||
qt_config->beginGroup(QStringLiteral("Controls"));
|
||||
ReadPlayerValue(player_index);
|
||||
qt_config->endGroup();
|
||||
}
|
||||
|
||||
void Config::SaveControlPlayerValue(std::size_t player_index) {
|
||||
qt_config->beginGroup(QStringLiteral("Controls"));
|
||||
SavePlayerValue(player_index);
|
||||
qt_config->endGroup();
|
||||
}
|
||||
|
||||
const std::string& Config::GetConfigFilePath() const {
|
||||
return qt_config_loc;
|
||||
}
|
||||
|
|
|
@ -16,12 +16,24 @@ class QSettings;
|
|||
|
||||
class Config {
|
||||
public:
|
||||
explicit Config(const std::string& config_loc = "qt-config.ini", bool is_global = true);
|
||||
enum class ConfigType {
|
||||
GlobalConfig,
|
||||
PerGameConfig,
|
||||
InputProfile,
|
||||
};
|
||||
|
||||
explicit Config(const std::string& config_name = "qt-config",
|
||||
ConfigType config_type = ConfigType::GlobalConfig);
|
||||
~Config();
|
||||
|
||||
void Reload();
|
||||
void Save();
|
||||
|
||||
void ReadControlPlayerValue(std::size_t player_index);
|
||||
void SaveControlPlayerValue(std::size_t player_index);
|
||||
|
||||
const std::string& GetConfigFilePath() const;
|
||||
|
||||
static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;
|
||||
static const std::array<int, Settings::NativeMotion::NumMotions> default_motions;
|
||||
static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs;
|
||||
|
@ -33,8 +45,10 @@ public:
|
|||
static const std::array<UISettings::Shortcut, 16> default_hotkeys;
|
||||
|
||||
private:
|
||||
void Initialize(const std::string& config_name);
|
||||
|
||||
void ReadValues();
|
||||
void ReadPlayerValues();
|
||||
void ReadPlayerValue(std::size_t player_index);
|
||||
void ReadDebugValues();
|
||||
void ReadKeyboardValues();
|
||||
void ReadMouseValues();
|
||||
|
@ -62,7 +76,7 @@ private:
|
|||
void ReadWebServiceValues();
|
||||
|
||||
void SaveValues();
|
||||
void SavePlayerValues();
|
||||
void SavePlayerValue(std::size_t player_index);
|
||||
void SaveDebugValues();
|
||||
void SaveMouseValues();
|
||||
void SaveTouchscreenValues();
|
||||
|
@ -111,9 +125,9 @@ private:
|
|||
void WriteSettingGlobal(const QString& name, const QVariant& value, bool use_global,
|
||||
const QVariant& default_value);
|
||||
|
||||
ConfigType type;
|
||||
std::unique_ptr<QSettings> qt_config;
|
||||
std::string qt_config_loc;
|
||||
|
||||
bool global;
|
||||
};
|
||||
|
||||
|
|
|
@ -275,32 +275,12 @@
|
|||
<signal>accepted()</signal>
|
||||
<receiver>ConfigureDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>220</x>
|
||||
<y>380</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>220</x>
|
||||
<y>200</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ConfigureDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>220</x>
|
||||
<y>380</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>220</x>
|
||||
<y>200</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
|
@ -4,11 +4,14 @@
|
|||
|
||||
#include "ui_configure_debug_controller.h"
|
||||
#include "yuzu/configuration/configure_debug_controller.h"
|
||||
#include "yuzu/configuration/configure_input_player.h"
|
||||
|
||||
ConfigureDebugController::ConfigureDebugController(QWidget* parent,
|
||||
InputCommon::InputSubsystem* input_subsystem)
|
||||
InputCommon::InputSubsystem* input_subsystem,
|
||||
InputProfiles* profiles)
|
||||
: QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()),
|
||||
debug_controller(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, true)) {
|
||||
debug_controller(
|
||||
new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles, true)) {
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->controllerLayout->addWidget(debug_controller);
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
|
||||
#include <memory>
|
||||
#include <QDialog>
|
||||
#include "yuzu/configuration/configure_input_player.h"
|
||||
|
||||
class QPushButton;
|
||||
|
||||
class ConfigureInputPlayer;
|
||||
|
||||
class InputProfiles;
|
||||
|
||||
namespace InputCommon {
|
||||
class InputSubsystem;
|
||||
}
|
||||
|
@ -22,8 +25,8 @@ class ConfigureDebugController : public QDialog {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureDebugController(QWidget* parent,
|
||||
InputCommon::InputSubsystem* input_subsystem);
|
||||
explicit ConfigureDebugController(QWidget* parent, InputCommon::InputSubsystem* input_subsystem,
|
||||
InputProfiles* profiles);
|
||||
~ConfigureDebugController() override;
|
||||
|
||||
void ApplyConfiguration();
|
||||
|
|
|
@ -66,32 +66,12 @@
|
|||
<signal>accepted()</signal>
|
||||
<receiver>ConfigureDebugController</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>140</x>
|
||||
<y>318</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>140</x>
|
||||
<y>169</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ConfigureDebugController</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>140</x>
|
||||
<y>318</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>140</x>
|
||||
<y>169</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "yuzu/configuration/configure_motion_touch.h"
|
||||
#include "yuzu/configuration/configure_mouse_advanced.h"
|
||||
#include "yuzu/configuration/configure_touchscreen_advanced.h"
|
||||
#include "yuzu/configuration/configure_vibration.h"
|
||||
#include "yuzu/configuration/input_profiles.h"
|
||||
|
||||
namespace {
|
||||
template <typename Dialog, typename... Args>
|
||||
|
@ -64,7 +66,8 @@ void OnDockedModeChanged(bool last_state, bool new_state) {
|
|||
}
|
||||
|
||||
ConfigureInput::ConfigureInput(QWidget* parent)
|
||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) {
|
||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()),
|
||||
profiles(std::make_unique<InputProfiles>()) {
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
|
@ -73,14 +76,22 @@ ConfigureInput::~ConfigureInput() = default;
|
|||
void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
|
||||
std::size_t max_players) {
|
||||
player_controllers = {
|
||||
new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem),
|
||||
new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem),
|
||||
new ConfigureInputPlayer(this, 2, ui->consoleInputSettings, input_subsystem),
|
||||
new ConfigureInputPlayer(this, 3, ui->consoleInputSettings, input_subsystem),
|
||||
new ConfigureInputPlayer(this, 4, ui->consoleInputSettings, input_subsystem),
|
||||
new ConfigureInputPlayer(this, 5, ui->consoleInputSettings, input_subsystem),
|
||||
new ConfigureInputPlayer(this, 6, ui->consoleInputSettings, input_subsystem),
|
||||
new ConfigureInputPlayer(this, 7, ui->consoleInputSettings, input_subsystem),
|
||||
new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem,
|
||||
profiles.get()),
|
||||
new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem,
|
||||
profiles.get()),
|
||||
new ConfigureInputPlayer(this, 2, ui->consoleInputSettings, input_subsystem,
|
||||
profiles.get()),
|
||||
new ConfigureInputPlayer(this, 3, ui->consoleInputSettings, input_subsystem,
|
||||
profiles.get()),
|
||||
new ConfigureInputPlayer(this, 4, ui->consoleInputSettings, input_subsystem,
|
||||
profiles.get()),
|
||||
new ConfigureInputPlayer(this, 5, ui->consoleInputSettings, input_subsystem,
|
||||
profiles.get()),
|
||||
new ConfigureInputPlayer(this, 6, ui->consoleInputSettings, input_subsystem,
|
||||
profiles.get()),
|
||||
new ConfigureInputPlayer(this, 7, ui->consoleInputSettings, input_subsystem,
|
||||
profiles.get()),
|
||||
};
|
||||
|
||||
player_tabs = {
|
||||
|
@ -113,8 +124,10 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
|
|||
}
|
||||
}
|
||||
});
|
||||
connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputDevices,
|
||||
[this] { UpdateAllInputDevices(); });
|
||||
connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputDevices, this,
|
||||
&ConfigureInput::UpdateAllInputDevices);
|
||||
connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputProfiles, this,
|
||||
&ConfigureInput::UpdateAllInputProfiles, Qt::QueuedConnection);
|
||||
connect(player_connected[i], &QCheckBox::stateChanged, [this, i](int state) {
|
||||
player_controllers[i]->ConnectPlayer(state == Qt::Checked);
|
||||
});
|
||||
|
@ -134,7 +147,7 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
|
|||
ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced));
|
||||
ui->tabAdvanced->layout()->addWidget(advanced);
|
||||
connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, [this, input_subsystem] {
|
||||
CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem);
|
||||
CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem, profiles.get());
|
||||
});
|
||||
connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] {
|
||||
CallConfigureDialog<ConfigureMouseAdvanced>(*this, input_subsystem);
|
||||
|
@ -146,6 +159,9 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
|
|||
CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem);
|
||||
});
|
||||
|
||||
connect(ui->vibrationButton, &QPushButton::clicked,
|
||||
[this] { CallConfigureDialog<ConfigureVibration>(*this); });
|
||||
|
||||
connect(ui->motionButton, &QPushButton::clicked, [this, input_subsystem] {
|
||||
CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem);
|
||||
});
|
||||
|
@ -171,12 +187,12 @@ void ConfigureInput::ApplyConfiguration() {
|
|||
|
||||
advanced->ApplyConfiguration();
|
||||
|
||||
const bool pre_docked_mode = Settings::values.use_docked_mode;
|
||||
Settings::values.use_docked_mode = ui->radioDocked->isChecked();
|
||||
OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode);
|
||||
const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
|
||||
Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked());
|
||||
OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue());
|
||||
|
||||
Settings::values.vibration_enabled = ui->vibrationGroup->isChecked();
|
||||
Settings::values.motion_enabled = ui->motionGroup->isChecked();
|
||||
Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
|
||||
Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked());
|
||||
}
|
||||
|
||||
void ConfigureInput::changeEvent(QEvent* event) {
|
||||
|
@ -193,16 +209,16 @@ void ConfigureInput::RetranslateUI() {
|
|||
|
||||
void ConfigureInput::LoadConfiguration() {
|
||||
LoadPlayerControllerIndices();
|
||||
UpdateDockedState(Settings::values.players[8].connected);
|
||||
UpdateDockedState(Settings::values.players.GetValue()[8].connected);
|
||||
|
||||
ui->vibrationGroup->setChecked(Settings::values.vibration_enabled);
|
||||
ui->motionGroup->setChecked(Settings::values.motion_enabled);
|
||||
ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue());
|
||||
ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue());
|
||||
}
|
||||
|
||||
void ConfigureInput::LoadPlayerControllerIndices() {
|
||||
for (std::size_t i = 0; i < player_connected.size(); ++i) {
|
||||
const auto connected = Settings::values.players[i].connected ||
|
||||
(i == 0 && Settings::values.players[8].connected);
|
||||
const auto connected = Settings::values.players.GetValue()[i].connected ||
|
||||
(i == 0 && Settings::values.players.GetValue()[8].connected);
|
||||
player_connected[i]->setChecked(connected);
|
||||
}
|
||||
}
|
||||
|
@ -231,8 +247,8 @@ void ConfigureInput::UpdateDockedState(bool is_handheld) {
|
|||
ui->radioDocked->setEnabled(!is_handheld);
|
||||
ui->radioUndocked->setEnabled(!is_handheld);
|
||||
|
||||
ui->radioDocked->setChecked(Settings::values.use_docked_mode);
|
||||
ui->radioUndocked->setChecked(!Settings::values.use_docked_mode);
|
||||
ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue());
|
||||
ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue());
|
||||
|
||||
// Also force into undocked mode if the controller type is handheld.
|
||||
if (is_handheld) {
|
||||
|
@ -242,6 +258,16 @@ void ConfigureInput::UpdateDockedState(bool is_handheld) {
|
|||
|
||||
void ConfigureInput::UpdateAllInputDevices() {
|
||||
for (const auto& player : player_controllers) {
|
||||
player->UpdateInputDevices();
|
||||
player->UpdateInputDeviceCombobox();
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureInput::UpdateAllInputProfiles(std::size_t player_index) {
|
||||
for (std::size_t i = 0; i < player_controllers.size(); ++i) {
|
||||
if (i == player_index) {
|
||||
continue;
|
||||
}
|
||||
|
||||
player_controllers[i]->UpdateInputProfiles();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,17 +8,18 @@
|
|||
#include <memory>
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <QList>
|
||||
#include <QWidget>
|
||||
|
||||
#include "yuzu/configuration/configure_input_advanced.h"
|
||||
#include "yuzu/configuration/configure_input_player.h"
|
||||
|
||||
#include "ui_configure_input.h"
|
||||
|
||||
class QCheckBox;
|
||||
class QString;
|
||||
class QTimer;
|
||||
|
||||
class ConfigureInputAdvanced;
|
||||
class ConfigureInputPlayer;
|
||||
|
||||
class InputProfiles;
|
||||
|
||||
namespace InputCommon {
|
||||
class InputSubsystem;
|
||||
}
|
||||
|
@ -51,6 +52,7 @@ private:
|
|||
|
||||
void UpdateDockedState(bool is_handheld);
|
||||
void UpdateAllInputDevices();
|
||||
void UpdateAllInputProfiles(std::size_t player_index);
|
||||
|
||||
/// Load configuration settings.
|
||||
void LoadConfiguration();
|
||||
|
@ -61,6 +63,8 @@ private:
|
|||
|
||||
std::unique_ptr<Ui::ConfigureInput> ui;
|
||||
|
||||
std::unique_ptr<InputProfiles> profiles;
|
||||
|
||||
std::array<ConfigureInputPlayer*, 8> player_controllers;
|
||||
std::array<QWidget*, 8> player_tabs;
|
||||
std::array<QCheckBox*, 8> player_connected;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>700</width>
|
||||
<width>680</width>
|
||||
<height>540</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -142,7 +142,7 @@
|
|||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
|
@ -195,30 +195,24 @@
|
|||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="vibrationSpin">
|
||||
<widget class="QPushButton" name="vibrationButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>65</width>
|
||||
<height>21</height>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>65</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -250,18 +244,18 @@
|
|||
<widget class="QPushButton" name="motionButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
|
@ -272,7 +266,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignVCenter">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<widget class="QWidget" name="connectedControllers" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
|
@ -468,13 +462,13 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
|
@ -494,7 +488,7 @@
|
|||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Defaults</string>
|
||||
|
@ -511,13 +505,13 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
|
@ -537,7 +531,7 @@
|
|||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
|
|
|
@ -68,8 +68,7 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent)
|
|||
for (std::size_t button_idx = 0; button_idx < color_buttons.size(); ++button_idx) {
|
||||
connect(color_buttons[button_idx], &QPushButton::clicked, this,
|
||||
[this, player_idx, button_idx] {
|
||||
OnControllerButtonClick(static_cast<int>(player_idx),
|
||||
static_cast<int>(button_idx));
|
||||
OnControllerButtonClick(player_idx, button_idx);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -94,20 +93,21 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent)
|
|||
|
||||
ConfigureInputAdvanced::~ConfigureInputAdvanced() = default;
|
||||
|
||||
void ConfigureInputAdvanced::OnControllerButtonClick(int player_idx, int button_idx) {
|
||||
void ConfigureInputAdvanced::OnControllerButtonClick(std::size_t player_idx,
|
||||
std::size_t button_idx) {
|
||||
const QColor new_bg_color = QColorDialog::getColor(controllers_colors[player_idx][button_idx]);
|
||||
if (!new_bg_color.isValid()) {
|
||||
return;
|
||||
}
|
||||
controllers_colors[player_idx][button_idx] = new_bg_color;
|
||||
controllers_color_buttons[player_idx][button_idx]->setStyleSheet(
|
||||
QStringLiteral("background-color: %1; min-width: 55px;")
|
||||
QStringLiteral("background-color: %1; min-width: 60px;")
|
||||
.arg(controllers_colors[player_idx][button_idx].name()));
|
||||
}
|
||||
|
||||
void ConfigureInputAdvanced::ApplyConfiguration() {
|
||||
for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) {
|
||||
auto& player = Settings::values.players[player_idx];
|
||||
auto& player = Settings::values.players.GetValue()[player_idx];
|
||||
std::array<u32, 4> colors{};
|
||||
std::transform(controllers_colors[player_idx].begin(), controllers_colors[player_idx].end(),
|
||||
colors.begin(), [](QColor color) { return color.rgb(); });
|
||||
|
@ -126,7 +126,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() {
|
|||
|
||||
void ConfigureInputAdvanced::LoadConfiguration() {
|
||||
for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) {
|
||||
auto& player = Settings::values.players[player_idx];
|
||||
auto& player = Settings::values.players.GetValue()[player_idx];
|
||||
std::array<u32, 4> colors = {
|
||||
player.body_color_left,
|
||||
player.button_color_left,
|
||||
|
@ -139,7 +139,7 @@ void ConfigureInputAdvanced::LoadConfiguration() {
|
|||
|
||||
for (std::size_t button_idx = 0; button_idx < colors.size(); ++button_idx) {
|
||||
controllers_color_buttons[player_idx][button_idx]->setStyleSheet(
|
||||
QStringLiteral("background-color: %1; min-width: 55px;")
|
||||
QStringLiteral("background-color: %1; min-width: 60px;")
|
||||
.arg(controllers_colors[player_idx][button_idx].name()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ private:
|
|||
void RetranslateUI();
|
||||
void UpdateUIEnabled();
|
||||
|
||||
void OnControllerButtonClick(int player_idx, int button_idx);
|
||||
void OnControllerButtonClick(std::size_t player_idx, std::size_t button_idx);
|
||||
|
||||
void LoadConfiguration();
|
||||
|
||||
|
|
|
@ -192,18 +192,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -247,18 +247,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -323,18 +323,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -378,18 +378,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -478,18 +478,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -533,18 +533,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -609,18 +609,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -664,18 +664,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -782,18 +782,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -837,18 +837,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -913,18 +913,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -968,18 +968,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -1068,18 +1068,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -1123,18 +1123,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -1199,18 +1199,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -1254,18 +1254,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -1393,18 +1393,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -1448,18 +1448,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -1524,18 +1524,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -1579,18 +1579,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -1679,18 +1679,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -1734,18 +1734,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -1810,18 +1810,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -1865,18 +1865,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -1983,18 +1983,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -2038,18 +2038,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -2114,18 +2114,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -2169,18 +2169,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -2269,18 +2269,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -2324,18 +2324,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -2400,18 +2400,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
@ -2455,18 +2455,18 @@
|
|||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <QGridLayout>
|
||||
#include <QInputDialog>
|
||||
|
@ -22,8 +23,9 @@
|
|||
#include "ui_configure_input_player.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configure_input_player.h"
|
||||
|
||||
constexpr std::size_t HANDHELD_INDEX = 8;
|
||||
#include "yuzu/configuration/configure_vibration.h"
|
||||
#include "yuzu/configuration/input_profiles.h"
|
||||
#include "yuzu/util/limitable_input_dialog.h"
|
||||
|
||||
const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM>
|
||||
ConfigureInputPlayer::analog_sub_buttons{{
|
||||
|
@ -35,6 +37,8 @@ const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM>
|
|||
|
||||
namespace {
|
||||
|
||||
constexpr std::size_t HANDHELD_INDEX = 8;
|
||||
|
||||
void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index,
|
||||
bool connected) {
|
||||
Core::System& system{Core::System::GetInstance()};
|
||||
|
@ -240,10 +244,11 @@ QString AnalogToText(const Common::ParamPackage& param, const std::string& dir)
|
|||
ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index,
|
||||
QWidget* bottom_row,
|
||||
InputCommon::InputSubsystem* input_subsystem_,
|
||||
bool debug)
|
||||
InputProfiles* profiles_, bool debug)
|
||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index),
|
||||
debug(debug), input_subsystem{input_subsystem_}, timeout_timer(std::make_unique<QTimer>()),
|
||||
poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row) {
|
||||
debug(debug), input_subsystem{input_subsystem_}, profiles(profiles_),
|
||||
timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()),
|
||||
bottom_row(bottom_row) {
|
||||
ui->setupUi(this);
|
||||
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
|
@ -366,6 +371,18 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||
}
|
||||
|
||||
connect(analog_button, &QPushButton::clicked, [=, this] {
|
||||
if (!map_analog_stick_accepted) {
|
||||
map_analog_stick_accepted =
|
||||
QMessageBox::information(
|
||||
this, tr("Map Analog Stick"),
|
||||
tr("After pressing OK, first move your joystick horizontally, and then "
|
||||
"vertically.\nTo invert the axes, first move your joystick "
|
||||
"vertically, and then horizontally."),
|
||||
QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok;
|
||||
if (!map_analog_stick_accepted) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
HandleClick(
|
||||
analog_map_buttons[analog_id][sub_button_id],
|
||||
[=, this](const Common::ParamPackage& params) {
|
||||
|
@ -455,11 +472,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||
});
|
||||
}
|
||||
|
||||
if (debug || player_index == 9) {
|
||||
ui->groupConnectedController->setCheckable(false);
|
||||
}
|
||||
|
||||
// The Debug Controller can only choose the Pro Controller.
|
||||
if (debug) {
|
||||
ui->buttonScreenshot->setEnabled(false);
|
||||
ui->buttonHome->setEnabled(false);
|
||||
ui->groupConnectedController->setCheckable(false);
|
||||
QStringList debug_controller_types = {
|
||||
tr("Pro Controller"),
|
||||
};
|
||||
|
@ -477,11 +497,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||
UpdateMotionButtons();
|
||||
});
|
||||
|
||||
connect(ui->comboDevices, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this,
|
||||
&ConfigureInputPlayer::UpdateMappingWithDefaults);
|
||||
|
||||
ui->comboDevices->setCurrentIndex(-1);
|
||||
|
||||
ui->buttonRefreshDevices->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh")));
|
||||
UpdateInputDevices();
|
||||
connect(ui->buttonRefreshDevices, &QPushButton::clicked,
|
||||
[this] { emit RefreshInputDevices(); });
|
||||
|
||||
|
@ -492,14 +513,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||
Common::ParamPackage params;
|
||||
if (input_subsystem->GetGCButtons()->IsPolling()) {
|
||||
params = input_subsystem->GetGCButtons()->GetNextInput();
|
||||
if (params.Has("engine")) {
|
||||
if (params.Has("engine") && IsInputAcceptable(params)) {
|
||||
SetPollingResult(params, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (input_subsystem->GetGCAnalogs()->IsPolling()) {
|
||||
params = input_subsystem->GetGCAnalogs()->GetNextInput();
|
||||
if (params.Has("engine")) {
|
||||
if (params.Has("engine") && IsInputAcceptable(params)) {
|
||||
SetPollingResult(params, false);
|
||||
return;
|
||||
}
|
||||
|
@ -513,13 +534,24 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||
}
|
||||
for (auto& poller : device_pollers) {
|
||||
params = poller->GetNextInput();
|
||||
if (params.Has("engine")) {
|
||||
if (params.Has("engine") && IsInputAcceptable(params)) {
|
||||
SetPollingResult(params, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
UpdateInputProfiles();
|
||||
|
||||
connect(ui->buttonProfilesNew, &QPushButton::clicked, this,
|
||||
&ConfigureInputPlayer::CreateProfile);
|
||||
connect(ui->buttonProfilesDelete, &QPushButton::clicked, this,
|
||||
&ConfigureInputPlayer::DeleteProfile);
|
||||
connect(ui->comboProfiles, qOverload<int>(&QComboBox::activated), this,
|
||||
&ConfigureInputPlayer::LoadProfile);
|
||||
connect(ui->buttonProfilesSave, &QPushButton::clicked, this,
|
||||
&ConfigureInputPlayer::SaveProfile);
|
||||
|
||||
LoadConfiguration();
|
||||
|
||||
// TODO(wwylele): enable this when we actually emulate it
|
||||
|
@ -529,7 +561,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||
ConfigureInputPlayer::~ConfigureInputPlayer() = default;
|
||||
|
||||
void ConfigureInputPlayer::ApplyConfiguration() {
|
||||
auto& player = Settings::values.players[player_index];
|
||||
auto& player = Settings::values.players.GetValue()[player_index];
|
||||
auto& buttons = debug ? Settings::values.debug_pad_buttons : player.buttons;
|
||||
auto& analogs = debug ? Settings::values.debug_pad_analogs : player.analogs;
|
||||
|
||||
|
@ -543,33 +575,58 @@ void ConfigureInputPlayer::ApplyConfiguration() {
|
|||
}
|
||||
|
||||
auto& motions = player.motions;
|
||||
|
||||
std::transform(motions_param.begin(), motions_param.end(), motions.begin(),
|
||||
[](const Common::ParamPackage& param) { return param.Serialize(); });
|
||||
|
||||
player.controller_type =
|
||||
static_cast<Settings::ControllerType>(ui->comboControllerType->currentIndex());
|
||||
player.connected = ui->groupConnectedController->isChecked();
|
||||
const auto controller_type =
|
||||
GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
|
||||
const auto player_connected = ui->groupConnectedController->isChecked() &&
|
||||
controller_type != Settings::ControllerType::Handheld;
|
||||
|
||||
// Player 2-8
|
||||
if (player_index != 0) {
|
||||
UpdateController(player.controller_type, player_index, player.connected);
|
||||
if (player.controller_type == controller_type && player.connected == player_connected) {
|
||||
// Set vibration devices in the event that the input device has changed.
|
||||
ConfigureVibration::SetVibrationDevices(player_index);
|
||||
return;
|
||||
}
|
||||
|
||||
// Player 1 and Handheld
|
||||
auto& handheld = Settings::values.players[HANDHELD_INDEX];
|
||||
// If Handheld is selected, copy all the settings from Player 1 to Handheld.
|
||||
if (player.controller_type == Settings::ControllerType::Handheld) {
|
||||
handheld = player;
|
||||
handheld.connected = ui->groupConnectedController->isChecked();
|
||||
player.connected = false; // Disconnect Player 1
|
||||
} else {
|
||||
player.connected = ui->groupConnectedController->isChecked();
|
||||
handheld.connected = false; // Disconnect Handheld
|
||||
// Disconnect the controller first.
|
||||
UpdateController(controller_type, player_index, false);
|
||||
|
||||
player.controller_type = controller_type;
|
||||
player.connected = player_connected;
|
||||
|
||||
ConfigureVibration::SetVibrationDevices(player_index);
|
||||
|
||||
// Handheld
|
||||
if (player_index == 0) {
|
||||
auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
|
||||
if (controller_type == Settings::ControllerType::Handheld) {
|
||||
handheld = player;
|
||||
}
|
||||
handheld.connected = ui->groupConnectedController->isChecked() &&
|
||||
controller_type == Settings::ControllerType::Handheld;
|
||||
UpdateController(Settings::ControllerType::Handheld, HANDHELD_INDEX, handheld.connected);
|
||||
}
|
||||
|
||||
UpdateController(player.controller_type, player_index, player.connected);
|
||||
UpdateController(Settings::ControllerType::Handheld, HANDHELD_INDEX, handheld.connected);
|
||||
if (!player.connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This emulates a delay between disconnecting and reconnecting controllers as some games
|
||||
// do not respond to a change in controller type if it was instantaneous.
|
||||
using namespace std::chrono_literals;
|
||||
std::this_thread::sleep_for(20ms);
|
||||
|
||||
UpdateController(controller_type, player_index, player_connected);
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::showEvent(QShowEvent* event) {
|
||||
if (bottom_row == nullptr) {
|
||||
return;
|
||||
}
|
||||
QWidget::showEvent(event);
|
||||
ui->main->addWidget(bottom_row);
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::changeEvent(QEvent* event) {
|
||||
|
@ -586,7 +643,7 @@ void ConfigureInputPlayer::RetranslateUI() {
|
|||
}
|
||||
|
||||
void ConfigureInputPlayer::LoadConfiguration() {
|
||||
auto& player = Settings::values.players[player_index];
|
||||
auto& player = Settings::values.players.GetValue()[player_index];
|
||||
if (debug) {
|
||||
std::transform(Settings::values.debug_pad_buttons.begin(),
|
||||
Settings::values.debug_pad_buttons.end(), buttons_param.begin(),
|
||||
|
@ -604,6 +661,7 @@ void ConfigureInputPlayer::LoadConfiguration() {
|
|||
}
|
||||
|
||||
UpdateUI();
|
||||
UpdateInputDeviceCombobox();
|
||||
|
||||
if (debug) {
|
||||
return;
|
||||
|
@ -612,44 +670,75 @@ void ConfigureInputPlayer::LoadConfiguration() {
|
|||
ui->comboControllerType->setCurrentIndex(static_cast<int>(player.controller_type));
|
||||
ui->groupConnectedController->setChecked(
|
||||
player.connected ||
|
||||
(player_index == 0 && Settings::values.players[HANDHELD_INDEX].connected));
|
||||
(player_index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected));
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::UpdateInputDevices() {
|
||||
input_devices = input_subsystem->GetInputDevices();
|
||||
ui->comboDevices->clear();
|
||||
for (auto device : input_devices) {
|
||||
ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {});
|
||||
void ConfigureInputPlayer::ConnectPlayer(bool connected) {
|
||||
ui->groupConnectedController->setChecked(connected);
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
|
||||
// Skip input device persistence if "Input Devices" is set to "Any".
|
||||
if (ui->comboDevices->currentIndex() == 0) {
|
||||
UpdateInputDevices();
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the first button that isn't empty.
|
||||
const auto button_param =
|
||||
std::find_if(buttons_param.begin(), buttons_param.end(),
|
||||
[](const Common::ParamPackage param) { return param.Has("engine"); });
|
||||
const bool buttons_empty = button_param == buttons_param.end();
|
||||
|
||||
const auto current_engine = button_param->Get("engine", "");
|
||||
const auto current_guid = button_param->Get("guid", "");
|
||||
const auto current_port = button_param->Get("port", "");
|
||||
|
||||
const bool is_keyboard_mouse = current_engine == "keyboard" || current_engine == "mouse";
|
||||
|
||||
UpdateInputDevices();
|
||||
|
||||
if (buttons_empty) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool all_one_device =
|
||||
std::all_of(buttons_param.begin(), buttons_param.end(),
|
||||
[current_engine, current_guid, current_port,
|
||||
is_keyboard_mouse](const Common::ParamPackage param) {
|
||||
if (is_keyboard_mouse) {
|
||||
return !param.Has("engine") || param.Get("engine", "") == "keyboard" ||
|
||||
param.Get("engine", "") == "mouse";
|
||||
}
|
||||
return !param.Has("engine") || (param.Get("engine", "") == current_engine &&
|
||||
param.Get("guid", "") == current_guid &&
|
||||
param.Get("port", "") == current_port);
|
||||
});
|
||||
|
||||
if (all_one_device) {
|
||||
if (is_keyboard_mouse) {
|
||||
ui->comboDevices->setCurrentIndex(1);
|
||||
return;
|
||||
}
|
||||
const auto devices_it = std::find_if(
|
||||
input_devices.begin(), input_devices.end(),
|
||||
[current_engine, current_guid, current_port](const Common::ParamPackage param) {
|
||||
return param.Get("class", "") == current_engine &&
|
||||
param.Get("guid", "") == current_guid &&
|
||||
param.Get("port", "") == current_port;
|
||||
});
|
||||
const int device_index =
|
||||
devices_it != input_devices.end()
|
||||
? static_cast<int>(std::distance(input_devices.begin(), devices_it))
|
||||
: 0;
|
||||
ui->comboDevices->setCurrentIndex(device_index);
|
||||
} else {
|
||||
ui->comboDevices->setCurrentIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::RestoreDefaults() {
|
||||
// Reset Buttons
|
||||
for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
|
||||
buttons_param[button_id] = Common::ParamPackage{
|
||||
InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])};
|
||||
}
|
||||
|
||||
// Reset Analogs and Modifier Buttons
|
||||
for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
|
||||
for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
|
||||
Common::ParamPackage params{InputCommon::GenerateKeyboardParam(
|
||||
Config::default_analogs[analog_id][sub_button_id])};
|
||||
SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]);
|
||||
}
|
||||
|
||||
analogs_param[analog_id].Set(
|
||||
"modifier", InputCommon::GenerateKeyboardParam(Config::default_stick_mod[analog_id]));
|
||||
}
|
||||
|
||||
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
|
||||
motions_param[motion_id] = Common::ParamPackage{
|
||||
InputCommon::GenerateKeyboardParam(Config::default_motions[motion_id])};
|
||||
}
|
||||
|
||||
UpdateUI();
|
||||
UpdateInputDevices();
|
||||
ui->comboControllerType->setCurrentIndex(0);
|
||||
UpdateMappingWithDefaults();
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::ClearAll() {
|
||||
|
@ -752,117 +841,12 @@ void ConfigureInputPlayer::UpdateUI() {
|
|||
}
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::UpdateMappingWithDefaults() {
|
||||
if (ui->comboDevices->currentIndex() < 2) {
|
||||
return;
|
||||
void ConfigureInputPlayer::UpdateInputDevices() {
|
||||
input_devices = input_subsystem->GetInputDevices();
|
||||
ui->comboDevices->clear();
|
||||
for (auto device : input_devices) {
|
||||
ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {});
|
||||
}
|
||||
const auto& device = input_devices[ui->comboDevices->currentIndex()];
|
||||
auto button_mapping = input_subsystem->GetButtonMappingForDevice(device);
|
||||
auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device);
|
||||
for (std::size_t i = 0; i < buttons_param.size(); ++i) {
|
||||
buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)];
|
||||
}
|
||||
for (std::size_t i = 0; i < analogs_param.size(); ++i) {
|
||||
analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)];
|
||||
}
|
||||
|
||||
UpdateUI();
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::HandleClick(
|
||||
QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter,
|
||||
InputCommon::Polling::DeviceType type) {
|
||||
if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) {
|
||||
button->setText(tr("Shake!"));
|
||||
} else {
|
||||
button->setText(tr("[waiting]"));
|
||||
}
|
||||
button->setFocus();
|
||||
|
||||
// The first two input devices are always Any and Keyboard/Mouse. If the user filtered to a
|
||||
// controller, then they don't want keyboard/mouse input
|
||||
want_keyboard_mouse = ui->comboDevices->currentIndex() < 2;
|
||||
|
||||
input_setter = new_input_setter;
|
||||
|
||||
device_pollers = input_subsystem->GetPollers(type);
|
||||
|
||||
for (auto& poller : device_pollers) {
|
||||
poller->Start();
|
||||
}
|
||||
|
||||
QWidget::grabMouse();
|
||||
QWidget::grabKeyboard();
|
||||
|
||||
if (type == InputCommon::Polling::DeviceType::Button) {
|
||||
input_subsystem->GetGCButtons()->BeginConfiguration();
|
||||
} else {
|
||||
input_subsystem->GetGCAnalogs()->BeginConfiguration();
|
||||
}
|
||||
|
||||
if (type == InputCommon::Polling::DeviceType::Motion) {
|
||||
input_subsystem->GetUDPMotions()->BeginConfiguration();
|
||||
}
|
||||
|
||||
timeout_timer->start(2500); // Cancel after 2.5 seconds
|
||||
poll_timer->start(50); // Check for new inputs every 50ms
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) {
|
||||
timeout_timer->stop();
|
||||
poll_timer->stop();
|
||||
for (auto& poller : device_pollers) {
|
||||
poller->Stop();
|
||||
}
|
||||
|
||||
QWidget::releaseMouse();
|
||||
QWidget::releaseKeyboard();
|
||||
|
||||
input_subsystem->GetGCButtons()->EndConfiguration();
|
||||
input_subsystem->GetGCAnalogs()->EndConfiguration();
|
||||
|
||||
input_subsystem->GetUDPMotions()->EndConfiguration();
|
||||
|
||||
if (!abort) {
|
||||
(*input_setter)(params);
|
||||
}
|
||||
|
||||
UpdateUI();
|
||||
input_setter = std::nullopt;
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) {
|
||||
if (!input_setter || !event) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (want_keyboard_mouse) {
|
||||
SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->button())},
|
||||
false);
|
||||
} else {
|
||||
// We don't want any mouse buttons, so don't stop polling
|
||||
return;
|
||||
}
|
||||
|
||||
SetPollingResult({}, true);
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
|
||||
if (!input_setter || !event) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->key() != Qt::Key_Escape) {
|
||||
if (want_keyboard_mouse) {
|
||||
SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())},
|
||||
false);
|
||||
} else {
|
||||
// Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetPollingResult({}, true);
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::UpdateControllerIcon() {
|
||||
|
@ -885,7 +869,7 @@ void ConfigureInputPlayer::UpdateControllerIcon() {
|
|||
}
|
||||
}();
|
||||
|
||||
const QString theme = [this] {
|
||||
const QString theme = [] {
|
||||
if (QIcon::themeName().contains(QStringLiteral("dark"))) {
|
||||
return QStringLiteral("_dark");
|
||||
} else if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
|
||||
|
@ -986,14 +970,260 @@ void ConfigureInputPlayer::UpdateMotionButtons() {
|
|||
}
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::showEvent(QShowEvent* event) {
|
||||
if (bottom_row == nullptr) {
|
||||
void ConfigureInputPlayer::UpdateMappingWithDefaults() {
|
||||
if (ui->comboDevices->currentIndex() == 0) {
|
||||
return;
|
||||
}
|
||||
QWidget::showEvent(event);
|
||||
ui->main->addWidget(bottom_row);
|
||||
|
||||
if (ui->comboDevices->currentIndex() == 1) {
|
||||
// Reset keyboard bindings
|
||||
for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) {
|
||||
buttons_param[button_id] = Common::ParamPackage{
|
||||
InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])};
|
||||
}
|
||||
for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) {
|
||||
for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
|
||||
Common::ParamPackage params{InputCommon::GenerateKeyboardParam(
|
||||
Config::default_analogs[analog_id][sub_button_id])};
|
||||
SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]);
|
||||
}
|
||||
|
||||
analogs_param[analog_id].Set("modifier", InputCommon::GenerateKeyboardParam(
|
||||
Config::default_stick_mod[analog_id]));
|
||||
}
|
||||
|
||||
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
|
||||
motions_param[motion_id] = Common::ParamPackage{
|
||||
InputCommon::GenerateKeyboardParam(Config::default_motions[motion_id])};
|
||||
}
|
||||
|
||||
UpdateUI();
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset controller bindings
|
||||
const auto& device = input_devices[ui->comboDevices->currentIndex()];
|
||||
auto button_mapping = input_subsystem->GetButtonMappingForDevice(device);
|
||||
auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device);
|
||||
for (std::size_t i = 0; i < buttons_param.size(); ++i) {
|
||||
buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)];
|
||||
}
|
||||
for (std::size_t i = 0; i < analogs_param.size(); ++i) {
|
||||
analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)];
|
||||
}
|
||||
|
||||
UpdateUI();
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::ConnectPlayer(bool connected) {
|
||||
ui->groupConnectedController->setChecked(connected);
|
||||
void ConfigureInputPlayer::HandleClick(
|
||||
QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter,
|
||||
InputCommon::Polling::DeviceType type) {
|
||||
if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) {
|
||||
button->setText(tr("Shake!"));
|
||||
} else {
|
||||
button->setText(tr("[waiting]"));
|
||||
}
|
||||
button->setFocus();
|
||||
|
||||
// The first two input devices are always Any and Keyboard/Mouse. If the user filtered to a
|
||||
// controller, then they don't want keyboard/mouse input
|
||||
want_keyboard_mouse = ui->comboDevices->currentIndex() < 2;
|
||||
|
||||
input_setter = new_input_setter;
|
||||
|
||||
device_pollers = input_subsystem->GetPollers(type);
|
||||
|
||||
for (auto& poller : device_pollers) {
|
||||
poller->Start();
|
||||
}
|
||||
|
||||
QWidget::grabMouse();
|
||||
QWidget::grabKeyboard();
|
||||
|
||||
if (type == InputCommon::Polling::DeviceType::Button) {
|
||||
input_subsystem->GetGCButtons()->BeginConfiguration();
|
||||
} else {
|
||||
input_subsystem->GetGCAnalogs()->BeginConfiguration();
|
||||
}
|
||||
|
||||
if (type == InputCommon::Polling::DeviceType::Motion) {
|
||||
input_subsystem->GetUDPMotions()->BeginConfiguration();
|
||||
}
|
||||
|
||||
timeout_timer->start(2500); // Cancel after 2.5 seconds
|
||||
poll_timer->start(50); // Check for new inputs every 50ms
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) {
|
||||
timeout_timer->stop();
|
||||
poll_timer->stop();
|
||||
for (auto& poller : device_pollers) {
|
||||
poller->Stop();
|
||||
}
|
||||
|
||||
QWidget::releaseMouse();
|
||||
QWidget::releaseKeyboard();
|
||||
|
||||
input_subsystem->GetGCButtons()->EndConfiguration();
|
||||
input_subsystem->GetGCAnalogs()->EndConfiguration();
|
||||
|
||||
input_subsystem->GetUDPMotions()->EndConfiguration();
|
||||
|
||||
if (!abort) {
|
||||
(*input_setter)(params);
|
||||
}
|
||||
|
||||
UpdateUI();
|
||||
UpdateInputDeviceCombobox();
|
||||
|
||||
input_setter = std::nullopt;
|
||||
}
|
||||
|
||||
bool ConfigureInputPlayer::IsInputAcceptable(const Common::ParamPackage& params) const {
|
||||
if (ui->comboDevices->currentIndex() == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Keyboard/Mouse
|
||||
if (ui->comboDevices->currentIndex() == 1) {
|
||||
return params.Get("engine", "") == "keyboard" || params.Get("engine", "") == "mouse";
|
||||
}
|
||||
|
||||
const auto current_input_device = input_devices[ui->comboDevices->currentIndex()];
|
||||
return params.Get("engine", "") == current_input_device.Get("class", "") &&
|
||||
params.Get("guid", "") == current_input_device.Get("guid", "") &&
|
||||
params.Get("port", "") == current_input_device.Get("port", "");
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) {
|
||||
if (!input_setter || !event) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (want_keyboard_mouse) {
|
||||
SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->button())},
|
||||
false);
|
||||
} else {
|
||||
// We don't want any mouse buttons, so don't stop polling
|
||||
return;
|
||||
}
|
||||
|
||||
SetPollingResult({}, true);
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
|
||||
if (!input_setter || !event) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->key() != Qt::Key_Escape) {
|
||||
if (want_keyboard_mouse) {
|
||||
SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())},
|
||||
false);
|
||||
} else {
|
||||
// Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetPollingResult({}, true);
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::CreateProfile() {
|
||||
const auto profile_name =
|
||||
LimitableInputDialog::GetText(this, tr("New Profile"), tr("Enter a profile name:"), 1, 20);
|
||||
|
||||
if (profile_name.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!profiles->IsProfileNameValid(profile_name.toStdString())) {
|
||||
QMessageBox::critical(this, tr("Create Input Profile"),
|
||||
tr("The given profile name is not valid!"));
|
||||
return;
|
||||
}
|
||||
|
||||
ApplyConfiguration();
|
||||
|
||||
if (!profiles->CreateProfile(profile_name.toStdString(), player_index)) {
|
||||
QMessageBox::critical(this, tr("Create Input Profile"),
|
||||
tr("Failed to create the input profile \"%1\"").arg(profile_name));
|
||||
UpdateInputProfiles();
|
||||
emit RefreshInputProfiles(player_index);
|
||||
return;
|
||||
}
|
||||
|
||||
emit RefreshInputProfiles(player_index);
|
||||
|
||||
ui->comboProfiles->addItem(profile_name);
|
||||
ui->comboProfiles->setCurrentIndex(ui->comboProfiles->count() - 1);
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::DeleteProfile() {
|
||||
const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex());
|
||||
|
||||
if (profile_name.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!profiles->DeleteProfile(profile_name.toStdString())) {
|
||||
QMessageBox::critical(this, tr("Delete Input Profile"),
|
||||
tr("Failed to delete the input profile \"%1\"").arg(profile_name));
|
||||
UpdateInputProfiles();
|
||||
emit RefreshInputProfiles(player_index);
|
||||
return;
|
||||
}
|
||||
|
||||
emit RefreshInputProfiles(player_index);
|
||||
|
||||
ui->comboProfiles->removeItem(ui->comboProfiles->currentIndex());
|
||||
ui->comboProfiles->setCurrentIndex(-1);
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::LoadProfile() {
|
||||
const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex());
|
||||
|
||||
if (profile_name.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ApplyConfiguration();
|
||||
|
||||
if (!profiles->LoadProfile(profile_name.toStdString(), player_index)) {
|
||||
QMessageBox::critical(this, tr("Load Input Profile"),
|
||||
tr("Failed to load the input profile \"%1\"").arg(profile_name));
|
||||
UpdateInputProfiles();
|
||||
emit RefreshInputProfiles(player_index);
|
||||
return;
|
||||
}
|
||||
|
||||
LoadConfiguration();
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::SaveProfile() {
|
||||
const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex());
|
||||
|
||||
if (profile_name.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ApplyConfiguration();
|
||||
|
||||
if (!profiles->SaveProfile(profile_name.toStdString(), player_index)) {
|
||||
QMessageBox::critical(this, tr("Save Input Profile"),
|
||||
tr("Failed to save the input profile \"%1\"").arg(profile_name));
|
||||
UpdateInputProfiles();
|
||||
emit RefreshInputProfiles(player_index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::UpdateInputProfiles() {
|
||||
ui->comboProfiles->clear();
|
||||
|
||||
for (const auto& profile_name : profiles->GetInputProfileNames()) {
|
||||
ui->comboProfiles->addItem(QString::fromStdString(profile_name));
|
||||
}
|
||||
|
||||
ui->comboProfiles->setCurrentIndex(-1);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ class QString;
|
|||
class QTimer;
|
||||
class QWidget;
|
||||
|
||||
class InputProfiles;
|
||||
|
||||
namespace InputCommon {
|
||||
class InputSubsystem;
|
||||
}
|
||||
|
@ -45,14 +47,20 @@ class ConfigureInputPlayer : public QWidget {
|
|||
public:
|
||||
explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row,
|
||||
InputCommon::InputSubsystem* input_subsystem_,
|
||||
bool debug = false);
|
||||
InputProfiles* profiles_, bool debug = false);
|
||||
~ConfigureInputPlayer() override;
|
||||
|
||||
/// Save all button configurations to settings file.
|
||||
void ApplyConfiguration();
|
||||
|
||||
/// Set the connection state checkbox (used to sync state).
|
||||
void ConnectPlayer(bool connected);
|
||||
|
||||
/// Update the input devices combobox.
|
||||
void UpdateInputDevices();
|
||||
void UpdateInputDeviceCombobox();
|
||||
|
||||
/// Updates the list of controller profiles.
|
||||
void UpdateInputProfiles();
|
||||
|
||||
/// Restore all buttons to their default values.
|
||||
void RestoreDefaults();
|
||||
|
@ -60,9 +68,6 @@ public:
|
|||
/// Clear all input configuration.
|
||||
void ClearAll();
|
||||
|
||||
/// Set the connection state checkbox (used to sync state).
|
||||
void ConnectPlayer(bool connected);
|
||||
|
||||
signals:
|
||||
/// Emitted when this controller is connected by the user.
|
||||
void Connected(bool connected);
|
||||
|
@ -70,6 +75,12 @@ signals:
|
|||
void HandheldStateChanged(bool is_handheld);
|
||||
/// Emitted when the input devices combobox is being refreshed.
|
||||
void RefreshInputDevices();
|
||||
/**
|
||||
* Emitted when the input profiles combobox is being refreshed.
|
||||
* The player_index represents the current player's index, and the profile combobox
|
||||
* will not be updated for this index as they are already updated by other mechanisms.
|
||||
*/
|
||||
void RefreshInputProfiles(std::size_t player_index);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent* event) override;
|
||||
|
@ -89,6 +100,9 @@ private:
|
|||
/// Finish polling and configure input using the input_setter.
|
||||
void SetPollingResult(const Common::ParamPackage& params, bool abort);
|
||||
|
||||
/// Checks whether a given input can be accepted.
|
||||
bool IsInputAcceptable(const Common::ParamPackage& params) const;
|
||||
|
||||
/// Handle mouse button press events.
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
|
||||
|
@ -98,8 +112,8 @@ private:
|
|||
/// Update UI to reflect current configuration.
|
||||
void UpdateUI();
|
||||
|
||||
/// Update the controller selection combobox
|
||||
void UpdateControllerCombobox();
|
||||
/// Update the available input devices.
|
||||
void UpdateInputDevices();
|
||||
|
||||
/// Update the current controller icon.
|
||||
void UpdateControllerIcon();
|
||||
|
@ -113,6 +127,18 @@ private:
|
|||
/// Gets the default controller mapping for this device and auto configures the input to match.
|
||||
void UpdateMappingWithDefaults();
|
||||
|
||||
/// Creates a controller profile.
|
||||
void CreateProfile();
|
||||
|
||||
/// Deletes the selected controller profile.
|
||||
void DeleteProfile();
|
||||
|
||||
/// Loads the selected controller profile.
|
||||
void LoadProfile();
|
||||
|
||||
/// Saves the current controller configuration into a selected controller profile.
|
||||
void SaveProfile();
|
||||
|
||||
std::unique_ptr<Ui::ConfigureInputPlayer> ui;
|
||||
|
||||
std::size_t player_index;
|
||||
|
@ -120,6 +146,8 @@ private:
|
|||
|
||||
InputCommon::InputSubsystem* input_subsystem;
|
||||
|
||||
InputProfiles* profiles;
|
||||
|
||||
std::unique_ptr<QTimer> timeout_timer;
|
||||
std::unique_ptr<QTimer> poll_timer;
|
||||
|
||||
|
@ -159,12 +187,15 @@ private:
|
|||
|
||||
std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers;
|
||||
|
||||
/// A flag to indicate that the "Map Analog Stick" pop-up has been shown and accepted once.
|
||||
bool map_analog_stick_accepted{};
|
||||
|
||||
/// A flag to indicate if keyboard keys are okay when configuring an input. If this is false,
|
||||
/// keyboard events are ignored.
|
||||
bool want_keyboard_mouse = false;
|
||||
bool want_keyboard_mouse{};
|
||||
|
||||
/// List of physical devices users can map with. If a SDL backed device is selected, then you
|
||||
/// can usue this device to get a default mapping.
|
||||
/// can use this device to get a default mapping.
|
||||
std::vector<Common::ParamPackage> input_devices;
|
||||
|
||||
/// Bottom row is where console wide settings are held, and its "owned" by the parent
|
||||
|
|
|
@ -83,6 +83,12 @@
|
|||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboControllerType">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>21</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Pro Controller</string>
|
||||
|
@ -136,6 +142,12 @@
|
|||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboDevices">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>21</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Any</string>
|
||||
|
@ -152,14 +164,14 @@
|
|||
<widget class="QPushButton" name="buttonRefreshDevices">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>22</height>
|
||||
<width>21</width>
|
||||
<height>21</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>22</height>
|
||||
<width>21</width>
|
||||
<height>21</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
|
@ -198,18 +210,25 @@
|
|||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboProfiles"/>
|
||||
<widget class="QComboBox" name="comboProfiles">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>21</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonProfilesSave">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
|
@ -220,12 +239,12 @@
|
|||
<widget class="QPushButton" name="buttonProfilesNew">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>New</string>
|
||||
|
@ -236,12 +255,12 @@
|
|||
<widget class="QPushButton" name="buttonProfilesDelete">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
|
@ -393,18 +412,18 @@
|
|||
<widget class="QPushButton" name="buttonLStickUp">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Up</string>
|
||||
|
@ -463,18 +482,18 @@
|
|||
<widget class="QPushButton" name="buttonLStickLeft">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Left</string>
|
||||
|
@ -512,18 +531,18 @@
|
|||
<widget class="QPushButton" name="buttonLStickRight">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Right</string>
|
||||
|
@ -594,18 +613,18 @@
|
|||
<widget class="QPushButton" name="buttonLStickDown">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Down</string>
|
||||
|
@ -664,18 +683,18 @@
|
|||
<widget class="QPushButton" name="buttonLStick">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pressed</string>
|
||||
|
@ -713,18 +732,18 @@
|
|||
<widget class="QPushButton" name="buttonLStickMod">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Modifier</string>
|
||||
|
@ -759,13 +778,13 @@
|
|||
<widget class="QSpinBox" name="spinboxLStickRange">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>21</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
|
@ -966,18 +985,18 @@
|
|||
<widget class="QPushButton" name="buttonDpadUp">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Up</string>
|
||||
|
@ -1036,18 +1055,18 @@
|
|||
<widget class="QPushButton" name="buttonDpadLeft">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Left</string>
|
||||
|
@ -1085,18 +1104,18 @@
|
|||
<widget class="QPushButton" name="buttonDpadRight">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Right</string>
|
||||
|
@ -1167,18 +1186,18 @@
|
|||
<widget class="QPushButton" name="buttonDpadDown">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Down</string>
|
||||
|
@ -1292,18 +1311,18 @@
|
|||
<widget class="QPushButton" name="buttonL">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>L</string>
|
||||
|
@ -1341,18 +1360,18 @@
|
|||
<widget class="QPushButton" name="buttonZL">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ZL</string>
|
||||
|
@ -1445,18 +1464,18 @@
|
|||
<widget class="QPushButton" name="buttonMinus">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Minus</string>
|
||||
|
@ -1494,18 +1513,18 @@
|
|||
<widget class="QPushButton" name="buttonScreenshot">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Capture</string>
|
||||
|
@ -1564,18 +1583,18 @@
|
|||
<widget class="QPushButton" name="buttonPlus">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Plus</string>
|
||||
|
@ -1613,18 +1632,18 @@
|
|||
<widget class="QPushButton" name="buttonHome">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Home</string>
|
||||
|
@ -1717,18 +1736,18 @@
|
|||
<widget class="QPushButton" name="buttonR">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>R</string>
|
||||
|
@ -1766,18 +1785,18 @@
|
|||
<widget class="QPushButton" name="buttonZR">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ZR</string>
|
||||
|
@ -1870,18 +1889,18 @@
|
|||
<widget class="QPushButton" name="buttonSL">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>SL</string>
|
||||
|
@ -1919,18 +1938,18 @@
|
|||
<widget class="QPushButton" name="buttonSR">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>SR</string>
|
||||
|
@ -2027,18 +2046,18 @@
|
|||
<widget class="QPushButton" name="buttonMotionLeft">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Left</string>
|
||||
|
@ -2076,18 +2095,18 @@
|
|||
<widget class="QPushButton" name="buttonMotionRight">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Right</string>
|
||||
|
@ -2225,18 +2244,18 @@
|
|||
<widget class="QPushButton" name="buttonX">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
|
@ -2295,18 +2314,18 @@
|
|||
<widget class="QPushButton" name="buttonY">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Y</string>
|
||||
|
@ -2344,18 +2363,18 @@
|
|||
<widget class="QPushButton" name="buttonA">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>A</string>
|
||||
|
@ -2426,18 +2445,18 @@
|
|||
<widget class="QPushButton" name="buttonB">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>B</string>
|
||||
|
@ -2580,18 +2599,18 @@
|
|||
<widget class="QPushButton" name="buttonRStickUp">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Up</string>
|
||||
|
@ -2650,18 +2669,18 @@
|
|||
<widget class="QPushButton" name="buttonRStickLeft">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Left</string>
|
||||
|
@ -2699,18 +2718,18 @@
|
|||
<widget class="QPushButton" name="buttonRStickRight">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Right</string>
|
||||
|
@ -2781,18 +2800,18 @@
|
|||
<widget class="QPushButton" name="buttonRStickDown">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Down</string>
|
||||
|
@ -2851,18 +2870,18 @@
|
|||
<widget class="QPushButton" name="buttonRStick">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pressed</string>
|
||||
|
@ -2900,18 +2919,18 @@
|
|||
<widget class="QPushButton" name="buttonRStickMod">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">min-width: 55px;</string>
|
||||
<string notr="true">min-width: 68px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Modifier</string>
|
||||
|
@ -2946,13 +2965,13 @@
|
|||
<widget class="QSpinBox" name="spinboxRStickRange">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>21</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ConfigureInputDialog</class>
|
||||
<widget class="QDialog" name="ConfigureInputDialog">
|
||||
<class>ConfigureInputProfileDialog</class>
|
||||
<widget class="QDialog" name="ConfigureInputProfileDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@ -11,7 +11,7 @@
|
|||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Configure Input</string>
|
||||
<string>Create Input Profile</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
|
@ -30,10 +30,24 @@
|
|||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="inputLayout"/>
|
||||
<layout class="QHBoxLayout" name="controllerLayout"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="clear_all_button">
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="restore_defaults_button">
|
||||
<property name="text">
|
||||
<string>Defaults</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
|
@ -50,7 +64,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ConfigureInputDialog</receiver>
|
||||
<receiver>ConfigureInputProfileDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
</connection>
|
||||
</connections>
|
|
@ -312,16 +312,6 @@
|
|||
<signal>accepted()</signal>
|
||||
<receiver>ConfigureMotionTouch</receiver>
|
||||
<slot>ApplyConfiguration()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>220</x>
|
||||
<y>380</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>220</x>
|
||||
<y>200</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton {
|
||||
min-width: 55px;
|
||||
min-width: 60px;
|
||||
}</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
|
@ -42,13 +42,13 @@
|
|||
<widget class="QPushButton" name="forward_button">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
|
@ -82,7 +82,7 @@
|
|||
<widget class="QPushButton" name="back_button">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
|
@ -110,7 +110,7 @@
|
|||
<widget class="QPushButton" name="left_button">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
|
@ -138,13 +138,13 @@
|
|||
<widget class="QPushButton" name="middle_button">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
|
@ -204,13 +204,13 @@
|
|||
<widget class="QPushButton" name="right_button">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
|
@ -256,13 +256,13 @@
|
|||
<widget class="QPushButton" name="buttonClearAll">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
|
@ -275,13 +275,13 @@
|
|||
<widget class="QPushButton" name="buttonRestoreDefaults">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>57</width>
|
||||
<width>68</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<width>68</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
|
@ -324,32 +324,12 @@
|
|||
<signal>accepted()</signal>
|
||||
<receiver>ConfigureMouseAdvanced</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>124</x>
|
||||
<y>266</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>124</x>
|
||||
<y>143</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ConfigureMouseAdvanced</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>124</x>
|
||||
<y>266</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>124</x>
|
||||
<y>143</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
|
||||
ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id)
|
||||
: QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()), title_id(title_id) {
|
||||
game_config = std::make_unique<Config>(fmt::format("{:016X}.ini", title_id), false);
|
||||
game_config = std::make_unique<Config>(fmt::format("{:016X}", title_id),
|
||||
Config::ConfigType::PerGameConfig);
|
||||
|
||||
Settings::SetConfiguringGlobal(false);
|
||||
|
||||
|
|
|
@ -319,32 +319,12 @@
|
|||
<signal>accepted()</signal>
|
||||
<receiver>ConfigurePerGame</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ConfigurePerGame</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
|
@ -216,16 +216,6 @@ Drag points to change position, or double-click table cells to edit values.</str
|
|||
<signal>rejected()</signal>
|
||||
<receiver>ConfigureTouchFromButton</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>249</x>
|
||||
<y>428</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>249</x>
|
||||
<y>224</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
|
@ -168,32 +168,12 @@
|
|||
<signal>accepted()</signal>
|
||||
<receiver>ConfigureTouchscreenAdvanced</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>140</x>
|
||||
<y>318</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>140</x>
|
||||
<y>169</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ConfigureTouchscreenAdvanced</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>140</x>
|
||||
<y>318</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>140</x>
|
||||
<y>169</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -18,6 +18,7 @@
|
|||
#include "applets/web_browser.h"
|
||||
#include "configuration/configure_input.h"
|
||||
#include "configuration/configure_per_game.h"
|
||||
#include "configuration/configure_vibration.h"
|
||||
#include "core/file_sys/vfs.h"
|
||||
#include "core/file_sys/vfs_real.h"
|
||||
#include "core/frontend/applets/controller.h"
|
||||
|
@ -50,12 +51,14 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
|
|||
#include <QDesktopServices>
|
||||
#include <QDesktopWidget>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QProgressBar>
|
||||
#include <QProgressDialog>
|
||||
#include <QPushButton>
|
||||
#include <QShortcut>
|
||||
#include <QStatusBar>
|
||||
#include <QSysInfo>
|
||||
|
@ -277,6 +280,8 @@ GMainWindow::GMainWindow()
|
|||
if (args.length() >= 2) {
|
||||
BootGame(args[1]);
|
||||
}
|
||||
|
||||
MigrateConfigFiles();
|
||||
}
|
||||
|
||||
GMainWindow::~GMainWindow() {
|
||||
|
@ -288,6 +293,7 @@ GMainWindow::~GMainWindow() {
|
|||
void GMainWindow::ControllerSelectorReconfigureControllers(
|
||||
const Core::Frontend::ControllerParameters& parameters) {
|
||||
QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get());
|
||||
|
||||
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint |
|
||||
Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
|
||||
dialog.setWindowModality(Qt::WindowModal);
|
||||
|
@ -547,13 +553,14 @@ void GMainWindow::InitializeWidgets() {
|
|||
dock_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton"));
|
||||
dock_status_button->setFocusPolicy(Qt::NoFocus);
|
||||
connect(dock_status_button, &QPushButton::clicked, [&] {
|
||||
Settings::values.use_docked_mode = !Settings::values.use_docked_mode;
|
||||
dock_status_button->setChecked(Settings::values.use_docked_mode);
|
||||
OnDockedModeChanged(!Settings::values.use_docked_mode, Settings::values.use_docked_mode);
|
||||
Settings::values.use_docked_mode.SetValue(!Settings::values.use_docked_mode.GetValue());
|
||||
dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue());
|
||||
OnDockedModeChanged(!Settings::values.use_docked_mode.GetValue(),
|
||||
Settings::values.use_docked_mode.GetValue());
|
||||
});
|
||||
dock_status_button->setText(tr("DOCK"));
|
||||
dock_status_button->setCheckable(true);
|
||||
dock_status_button->setChecked(Settings::values.use_docked_mode);
|
||||
dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue());
|
||||
statusBar()->insertPermanentWidget(0, dock_status_button);
|
||||
|
||||
// Setup ASync button
|
||||
|
@ -792,10 +799,11 @@ void GMainWindow::InitializeHotkeys() {
|
|||
});
|
||||
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Change Docked Mode"), this),
|
||||
&QShortcut::activated, this, [&] {
|
||||
Settings::values.use_docked_mode = !Settings::values.use_docked_mode;
|
||||
OnDockedModeChanged(!Settings::values.use_docked_mode,
|
||||
Settings::values.use_docked_mode);
|
||||
dock_status_button->setChecked(Settings::values.use_docked_mode);
|
||||
Settings::values.use_docked_mode.SetValue(
|
||||
!Settings::values.use_docked_mode.GetValue());
|
||||
OnDockedModeChanged(!Settings::values.use_docked_mode.GetValue(),
|
||||
Settings::values.use_docked_mode.GetValue());
|
||||
dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue());
|
||||
});
|
||||
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Mute Audio"), this),
|
||||
&QShortcut::activated, this,
|
||||
|
@ -1087,9 +1095,11 @@ void GMainWindow::BootGame(const QString& filename) {
|
|||
const auto loader = Loader::GetLoader(v_file);
|
||||
if (!(loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success)) {
|
||||
// Load per game settings
|
||||
Config per_game_config(fmt::format("{:016X}.ini", title_id), false);
|
||||
Config per_game_config(fmt::format("{:016X}", title_id), Config::ConfigType::PerGameConfig);
|
||||
}
|
||||
|
||||
ConfigureVibration::SetAllVibrationDevices();
|
||||
|
||||
Settings::LogSettings();
|
||||
|
||||
if (UISettings::values.select_user_on_boot) {
|
||||
|
@ -1577,7 +1587,8 @@ void GMainWindow::RemoveCustomConfiguration(u64 program_id) {
|
|||
const QString config_dir =
|
||||
QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir));
|
||||
const QString custom_config_file_path =
|
||||
config_dir + QString::fromStdString(fmt::format("{:016X}.ini", program_id));
|
||||
config_dir + QStringLiteral("custom") + QDir::separator() +
|
||||
QString::fromStdString(fmt::format("{:016X}.ini", program_id));
|
||||
|
||||
if (!QFile::exists(custom_config_file_path)) {
|
||||
QMessageBox::warning(this, tr("Error Removing Custom Configuration"),
|
||||
|
@ -2393,6 +2404,29 @@ void GMainWindow::OnCaptureScreenshot() {
|
|||
OnStartGame();
|
||||
}
|
||||
|
||||
// TODO: Written 2020-10-01: Remove per-game config migration code when it is irrelevant
|
||||
void GMainWindow::MigrateConfigFiles() {
|
||||
const std::string& config_dir_str = Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir);
|
||||
const QDir config_dir = QDir(QString::fromStdString(config_dir_str));
|
||||
const QStringList config_dir_list = config_dir.entryList(QStringList(QStringLiteral("*.ini")));
|
||||
|
||||
Common::FS::CreateFullPath(fmt::format("{}custom" DIR_SEP, config_dir_str));
|
||||
for (QStringList::const_iterator it = config_dir_list.constBegin();
|
||||
it != config_dir_list.constEnd(); ++it) {
|
||||
const auto filename = it->toStdString();
|
||||
if (filename.find_first_not_of("0123456789abcdefACBDEF", 0) < 16) {
|
||||
continue;
|
||||
}
|
||||
const auto origin = fmt::format("{}{}", config_dir_str, filename);
|
||||
const auto destination = fmt::format("{}custom" DIR_SEP "{}", config_dir_str, filename);
|
||||
LOG_INFO(Frontend, "Migrating config file from {} to {}", origin, destination);
|
||||
if (!Common::FS::Rename(origin, destination)) {
|
||||
// Delete the old config file if one already exists in the new location.
|
||||
Common::FS::Delete(origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::UpdateWindowTitle(const std::string& title_name,
|
||||
const std::string& title_version) {
|
||||
const auto full_name = std::string(Common::g_build_fullname);
|
||||
|
@ -2450,7 +2484,7 @@ void GMainWindow::UpdateStatusBar() {
|
|||
}
|
||||
|
||||
void GMainWindow::UpdateStatusButtons() {
|
||||
dock_status_button->setChecked(Settings::values.use_docked_mode);
|
||||
dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue());
|
||||
multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue());
|
||||
Settings::values.use_asynchronous_gpu_emulation.SetValue(
|
||||
Settings::values.use_asynchronous_gpu_emulation.GetValue() ||
|
||||
|
|
|
@ -251,6 +251,7 @@ private:
|
|||
std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id);
|
||||
InstallResult InstallNSPXCI(const QString& filename);
|
||||
InstallResult InstallNCA(const QString& filename);
|
||||
void MigrateConfigFiles();
|
||||
void UpdateWindowTitle(const std::string& title_name = {},
|
||||
const std::string& title_version = {});
|
||||
void UpdateStatusBar();
|
||||
|
|
|
@ -228,24 +228,24 @@ static const std::array<int, 8> keyboard_mods{
|
|||
|
||||
void Config::ReadValues() {
|
||||
// Controls
|
||||
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) {
|
||||
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
|
||||
const auto group = fmt::format("ControlsP{}", p);
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||
Settings::values.players[p].buttons[i] =
|
||||
Settings::values.players.GetValue()[p].buttons[i] =
|
||||
sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param);
|
||||
if (Settings::values.players[p].buttons[i].empty())
|
||||
Settings::values.players[p].buttons[i] = default_param;
|
||||
if (Settings::values.players.GetValue()[p].buttons[i].empty())
|
||||
Settings::values.players.GetValue()[p].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.players[p].analogs[i] =
|
||||
Settings::values.players.GetValue()[p].analogs[i] =
|
||||
sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param);
|
||||
if (Settings::values.players[p].analogs[i].empty())
|
||||
Settings::values.players[p].analogs[i] = default_param;
|
||||
if (Settings::values.players.GetValue()[p].analogs[i].empty())
|
||||
Settings::values.players.GetValue()[p].analogs[i] = default_param;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,10 +288,12 @@ void Config::ReadValues() {
|
|||
Settings::values.debug_pad_analogs[i] = default_param;
|
||||
}
|
||||
|
||||
Settings::values.vibration_enabled =
|
||||
sdl2_config->GetBoolean("ControlsGeneral", "vibration_enabled", true);
|
||||
Settings::values.motion_enabled =
|
||||
sdl2_config->GetBoolean("ControlsGeneral", "motion_enabled", true);
|
||||
Settings::values.vibration_enabled.SetValue(
|
||||
sdl2_config->GetBoolean("ControlsGeneral", "vibration_enabled", true));
|
||||
Settings::values.enable_accurate_vibrations.SetValue(
|
||||
sdl2_config->GetBoolean("ControlsGeneral", "enable_accurate_vibrations", false));
|
||||
Settings::values.motion_enabled.SetValue(
|
||||
sdl2_config->GetBoolean("ControlsGeneral", "motion_enabled", true));
|
||||
Settings::values.touchscreen.enabled =
|
||||
sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true);
|
||||
Settings::values.touchscreen.device =
|
||||
|
@ -343,7 +345,8 @@ void Config::ReadValues() {
|
|||
Settings::values.gamecard_path = sdl2_config->Get("Data Storage", "gamecard_path", "");
|
||||
|
||||
// System
|
||||
Settings::values.use_docked_mode = sdl2_config->GetBoolean("System", "use_docked_mode", false);
|
||||
Settings::values.use_docked_mode.SetValue(
|
||||
sdl2_config->GetBoolean("System", "use_docked_mode", false));
|
||||
const auto size = sdl2_config->GetInteger("System", "users_size", 0);
|
||||
|
||||
Settings::values.current_user = std::clamp<int>(
|
||||
|
|
|
@ -65,6 +65,14 @@ button_screenshot=
|
|||
lstick=
|
||||
rstick=
|
||||
|
||||
# Whether to enable or disable vibration
|
||||
# 0: Disabled, 1 (default): Enabled
|
||||
vibration_enabled=
|
||||
|
||||
# Whether to enable or disable accurate vibrations
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
enable_accurate_vibrations=
|
||||
|
||||
# for motion input, the following devices are available:
|
||||
# - "motion_emu" (default) for emulating motion input from mouse input. Required parameters:
|
||||
# - "update_period": update period in milliseconds (default to 100)
|
||||
|
|
|
@ -47,13 +47,13 @@ bool Config::LoadINI(const std::string& default_contents, bool retry) {
|
|||
|
||||
void Config::ReadValues() {
|
||||
// Controls
|
||||
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) {
|
||||
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
|
||||
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||
Settings::values.players[p].buttons[i] = "";
|
||||
Settings::values.players.GetValue()[p].buttons[i] = "";
|
||||
}
|
||||
|
||||
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
|
||||
Settings::values.players[p].analogs[i] = "";
|
||||
Settings::values.players.GetValue()[p].analogs[i] = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,8 +75,9 @@ void Config::ReadValues() {
|
|||
Settings::values.debug_pad_analogs[i] = "";
|
||||
}
|
||||
|
||||
Settings::values.vibration_enabled = true;
|
||||
Settings::values.motion_enabled = true;
|
||||
Settings::values.vibration_enabled.SetValue(true);
|
||||
Settings::values.enable_accurate_vibrations.SetValue(false);
|
||||
Settings::values.motion_enabled.SetValue(true);
|
||||
Settings::values.touchscreen.enabled = "";
|
||||
Settings::values.touchscreen.device = "";
|
||||
Settings::values.touchscreen.finger = 0;
|
||||
|
@ -84,8 +85,8 @@ void Config::ReadValues() {
|
|||
Settings::values.touchscreen.diameter_x = 15;
|
||||
Settings::values.touchscreen.diameter_y = 15;
|
||||
|
||||
Settings::values.use_docked_mode =
|
||||
sdl2_config->GetBoolean("Controls", "use_docked_mode", false);
|
||||
Settings::values.use_docked_mode.SetValue(
|
||||
sdl2_config->GetBoolean("Controls", "use_docked_mode", false));
|
||||
|
||||
// Data Storage
|
||||
Settings::values.use_virtual_sd =
|
||||
|
|
Loading…
Reference in New Issue