mirror of
https://git.suyu.dev/suyu/suyu
synced 2024-11-01 04:47:53 +00:00
input: Disconnect a controller prior to connecting a new one
Some games do not respond to a change in controller type if 1) The controller is not disconnected prior to being reconnected and/or 2) The controller is reconnected instantly after being disconnected. Since it is not possible to change controllers instantly on hardware and requiring a disconnect prior to connecting a new one, we should emulate this as well with a small delay, fixing the aforementioned issue.
This commit is contained in:
parent
978ca65f59
commit
91c06dae1a
2 changed files with 74 additions and 51 deletions
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
constexpr std::size_t HANDHELD_INDEX = 8;
|
||||||
|
|
||||||
constexpr std::array<std::array<bool, 4>, 8> led_patterns{{
|
constexpr std::array<std::array<bool, 4>, 8> led_patterns{{
|
||||||
{true, false, false, false},
|
{true, false, false, false},
|
||||||
{true, true, false, false},
|
{true, true, false, false},
|
||||||
|
@ -260,11 +262,6 @@ int QtControllerSelectorDialog::exec() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtControllerSelectorDialog::ApplyConfiguration() {
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
|
const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
|
||||||
Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked());
|
Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked());
|
||||||
OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue());
|
OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue());
|
||||||
|
@ -275,15 +272,16 @@ void QtControllerSelectorDialog::ApplyConfiguration() {
|
||||||
|
|
||||||
void QtControllerSelectorDialog::LoadConfiguration() {
|
void QtControllerSelectorDialog::LoadConfiguration() {
|
||||||
for (std::size_t index = 0; index < NUM_PLAYERS; ++index) {
|
for (std::size_t index = 0; index < NUM_PLAYERS; ++index) {
|
||||||
const auto connected = Settings::values.players.GetValue()[index].connected ||
|
const auto connected =
|
||||||
(index == 0 && Settings::values.players.GetValue()[8].connected);
|
Settings::values.players.GetValue()[index].connected ||
|
||||||
|
(index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected);
|
||||||
player_groupboxes[index]->setChecked(connected);
|
player_groupboxes[index]->setChecked(connected);
|
||||||
connected_controller_checkboxes[index]->setChecked(connected);
|
connected_controller_checkboxes[index]->setChecked(connected);
|
||||||
emulated_controllers[index]->setCurrentIndex(
|
emulated_controllers[index]->setCurrentIndex(
|
||||||
GetIndexFromControllerType(Settings::values.players.GetValue()[index].controller_type));
|
GetIndexFromControllerType(Settings::values.players.GetValue()[index].controller_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateDockedState(Settings::values.players.GetValue()[8].connected);
|
UpdateDockedState(Settings::values.players.GetValue()[HANDHELD_INDEX].connected);
|
||||||
|
|
||||||
ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue());
|
ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue());
|
||||||
ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue());
|
ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue());
|
||||||
|
@ -468,32 +466,46 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index)
|
||||||
void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) {
|
void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) {
|
||||||
auto& player = Settings::values.players.GetValue()[player_index];
|
auto& player = Settings::values.players.GetValue()[player_index];
|
||||||
|
|
||||||
player.controller_type =
|
const auto controller_type =
|
||||||
GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex());
|
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.controller_type == controller_type && player.connected == player_connected) {
|
||||||
if (player_index != 0) {
|
// Set vibration devices in the event that the input device has changed.
|
||||||
UpdateController(player.controller_type, player_index, player.connected);
|
ConfigureVibration::SetVibrationDevices(player_index);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disconnect the controller first.
|
||||||
|
UpdateController(controller_type, player_index, false);
|
||||||
|
|
||||||
|
player.controller_type = controller_type;
|
||||||
|
player.connected = player_connected;
|
||||||
|
|
||||||
ConfigureVibration::SetVibrationDevices(player_index);
|
ConfigureVibration::SetVibrationDevices(player_index);
|
||||||
|
|
||||||
// Player 1 and Handheld
|
// Handheld
|
||||||
auto& handheld = Settings::values.players.GetValue()[8];
|
if (player_index == 0) {
|
||||||
// If Handheld is selected, copy all the settings from Player 1 to Handheld.
|
auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
|
||||||
if (player.controller_type == Settings::ControllerType::Handheld) {
|
if (controller_type == Settings::ControllerType::Handheld) {
|
||||||
handheld = player;
|
handheld = player;
|
||||||
handheld.connected = player_groupboxes[player_index]->isChecked();
|
}
|
||||||
player.connected = false; // Disconnect Player 1
|
handheld.connected = player_groupboxes[player_index]->isChecked() &&
|
||||||
} else {
|
controller_type == Settings::ControllerType::Handheld;
|
||||||
player.connected = player_groupboxes[player_index]->isChecked();
|
UpdateController(Settings::ControllerType::Handheld, 8, handheld.connected);
|
||||||
handheld.connected = false; // Disconnect Handheld
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateController(player.controller_type, player_index, player.connected);
|
if (!player.connected) {
|
||||||
UpdateController(Settings::ControllerType::Handheld, 8, handheld.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) {
|
void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) {
|
||||||
|
|
|
@ -26,8 +26,6 @@
|
||||||
#include "yuzu/configuration/input_profiles.h"
|
#include "yuzu/configuration/input_profiles.h"
|
||||||
#include "yuzu/util/limitable_input_dialog.h"
|
#include "yuzu/util/limitable_input_dialog.h"
|
||||||
|
|
||||||
constexpr std::size_t HANDHELD_INDEX = 8;
|
|
||||||
|
|
||||||
const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM>
|
const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM>
|
||||||
ConfigureInputPlayer::analog_sub_buttons{{
|
ConfigureInputPlayer::analog_sub_buttons{{
|
||||||
"up",
|
"up",
|
||||||
|
@ -38,12 +36,10 @@ const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
constexpr std::size_t HANDHELD_INDEX = 8;
|
||||||
|
|
||||||
void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index,
|
void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index,
|
||||||
bool connected) {
|
bool connected) {
|
||||||
auto& player = Settings::values.players.GetValue()[npad_index];
|
|
||||||
player.controller_type = controller_type;
|
|
||||||
player.connected = connected;
|
|
||||||
|
|
||||||
Core::System& system{Core::System::GetInstance()};
|
Core::System& system{Core::System::GetInstance()};
|
||||||
if (!system.IsPoweredOn()) {
|
if (!system.IsPoweredOn()) {
|
||||||
return;
|
return;
|
||||||
|
@ -563,35 +559,50 @@ void ConfigureInputPlayer::ApplyConfiguration() {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& motions = player.motions;
|
auto& motions = player.motions;
|
||||||
|
|
||||||
std::transform(motions_param.begin(), motions_param.end(), motions.begin(),
|
std::transform(motions_param.begin(), motions_param.end(), motions.begin(),
|
||||||
[](const Common::ParamPackage& param) { return param.Serialize(); });
|
[](const Common::ParamPackage& param) { return param.Serialize(); });
|
||||||
|
|
||||||
player.controller_type =
|
const auto controller_type =
|
||||||
static_cast<Settings::ControllerType>(ui->comboControllerType->currentIndex());
|
GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
|
||||||
player.connected = ui->groupConnectedController->isChecked();
|
const auto player_connected = ui->groupConnectedController->isChecked() &&
|
||||||
|
controller_type != Settings::ControllerType::Handheld;
|
||||||
|
|
||||||
ConfigureVibration::SetVibrationDevices(player_index);
|
if (player.controller_type == controller_type && player.connected == player_connected) {
|
||||||
|
// Set vibration devices in the event that the input device has changed.
|
||||||
// Player 2-8
|
ConfigureVibration::SetVibrationDevices(player_index);
|
||||||
if (player_index != 0) {
|
|
||||||
UpdateController(player.controller_type, player_index, player.connected);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Player 1 and Handheld
|
// Disconnect the controller first.
|
||||||
auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
|
UpdateController(controller_type, player_index, false);
|
||||||
// If Handheld is selected, copy all the settings from Player 1 to Handheld.
|
|
||||||
if (player.controller_type == Settings::ControllerType::Handheld) {
|
player.controller_type = controller_type;
|
||||||
handheld = player;
|
player.connected = player_connected;
|
||||||
handheld.connected = ui->groupConnectedController->isChecked();
|
|
||||||
player.connected = false; // Disconnect Player 1
|
ConfigureVibration::SetVibrationDevices(player_index);
|
||||||
} else {
|
|
||||||
player.connected = ui->groupConnectedController->isChecked();
|
// Handheld
|
||||||
handheld.connected = false; // Disconnect 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);
|
if (!player.connected) {
|
||||||
UpdateController(Settings::ControllerType::Handheld, HANDHELD_INDEX, handheld.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) {
|
void ConfigureInputPlayer::showEvent(QShowEvent* event) {
|
||||||
|
|
Loading…
Reference in a new issue