mirror of
https://github.com/yuzu-emu/yuzu-android.git
synced 2025-06-14 18:07:58 -05:00
configuration: Migrate controller settings to emulated controller
This commit is contained in:
@ -9,6 +9,8 @@
|
||||
#include "common/param_package.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hid/emulated_controller.h"
|
||||
#include "core/hid/hid_types.h"
|
||||
#include "core/hle/lock.h"
|
||||
#include "core/hle/service/hid/controllers/npad.h"
|
||||
#include "core/hle/service/hid/hid.h"
|
||||
@ -26,48 +28,31 @@ 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},
|
||||
{true, true, true, false},
|
||||
{true, true, true, true},
|
||||
{true, false, false, true},
|
||||
{true, false, true, false},
|
||||
{true, false, true, true},
|
||||
{false, true, true, false},
|
||||
}};
|
||||
|
||||
void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index,
|
||||
bool connected, Core::System& system) {
|
||||
if (!system.IsPoweredOn()) {
|
||||
return;
|
||||
void UpdateController(Core::HID::EmulatedController* controller, Core::HID::NpadType controller_type, bool connected) {
|
||||
if (controller->IsConnected()) {
|
||||
controller->Disconnect();
|
||||
}
|
||||
controller->SetNpadType(controller_type);
|
||||
if (connected) {
|
||||
controller->Connect();
|
||||
}
|
||||
|
||||
auto& npad =
|
||||
system.ServiceManager()
|
||||
.GetService<Service::HID::Hid>("hid")
|
||||
->GetAppletResource()
|
||||
->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad);
|
||||
|
||||
npad.UpdateControllerAt(Core::HID::EmulatedController::MapSettingsTypeToNPad(controller_type),
|
||||
npad_index, connected);
|
||||
}
|
||||
|
||||
// Returns true if the given controller type is compatible with the given parameters.
|
||||
bool IsControllerCompatible(Settings::ControllerType controller_type,
|
||||
bool IsControllerCompatible(Core::HID::NpadType controller_type,
|
||||
Core::Frontend::ControllerParameters parameters) {
|
||||
switch (controller_type) {
|
||||
case Settings::ControllerType::ProController:
|
||||
case Core::HID::NpadType::ProController:
|
||||
return parameters.allow_pro_controller;
|
||||
case Settings::ControllerType::DualJoyconDetached:
|
||||
case Core::HID::NpadType::JoyconDual:
|
||||
return parameters.allow_dual_joycons;
|
||||
case Settings::ControllerType::LeftJoycon:
|
||||
case Core::HID::NpadType::JoyconLeft:
|
||||
return parameters.allow_left_joycon;
|
||||
case Settings::ControllerType::RightJoycon:
|
||||
case Core::HID::NpadType::JoyconRight:
|
||||
return parameters.allow_right_joycon;
|
||||
case Settings::ControllerType::Handheld:
|
||||
case Core::HID::NpadType::Handheld:
|
||||
return parameters.enable_single_mode && parameters.allow_handheld;
|
||||
case Settings::ControllerType::GameCube:
|
||||
case Core::HID::NpadType::GameCube:
|
||||
return parameters.allow_gamecube_controller;
|
||||
default:
|
||||
return false;
|
||||
@ -198,7 +183,7 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
|
||||
connect(emulated_controllers[i], qOverload<int>(&QComboBox::currentIndexChanged),
|
||||
[this, i](int index) {
|
||||
UpdateDockedState(GetControllerTypeFromIndex(index, i) ==
|
||||
Settings::ControllerType::Handheld);
|
||||
Core::HID::NpadType::Handheld);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -251,17 +236,17 @@ void QtControllerSelectorDialog::ApplyConfiguration() {
|
||||
}
|
||||
|
||||
void QtControllerSelectorDialog::LoadConfiguration() {
|
||||
const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
|
||||
for (std::size_t index = 0; index < NUM_PLAYERS; ++index) {
|
||||
const auto connected =
|
||||
Settings::values.players.GetValue()[index].connected ||
|
||||
(index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected);
|
||||
const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index);
|
||||
const auto connected = controller->IsConnected() || (index == 0 && handheld->IsConnected());
|
||||
player_groupboxes[index]->setChecked(connected);
|
||||
connected_controller_checkboxes[index]->setChecked(connected);
|
||||
emulated_controllers[index]->setCurrentIndex(GetIndexFromControllerType(
|
||||
Settings::values.players.GetValue()[index].controller_type, index));
|
||||
emulated_controllers[index]->setCurrentIndex(
|
||||
GetIndexFromControllerType(controller->GetNpadType(), index));
|
||||
}
|
||||
|
||||
UpdateDockedState(Settings::values.players.GetValue()[HANDHELD_INDEX].connected);
|
||||
UpdateDockedState(handheld->IsConnected());
|
||||
|
||||
ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue());
|
||||
ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue());
|
||||
@ -417,33 +402,32 @@ void QtControllerSelectorDialog::SetEmulatedControllers(std::size_t player_index
|
||||
emulated_controllers[player_index]->clear();
|
||||
|
||||
pairs.emplace_back(emulated_controllers[player_index]->count(),
|
||||
Settings::ControllerType::ProController);
|
||||
Core::HID::NpadType::ProController);
|
||||
emulated_controllers[player_index]->addItem(tr("Pro Controller"));
|
||||
|
||||
pairs.emplace_back(emulated_controllers[player_index]->count(),
|
||||
Settings::ControllerType::DualJoyconDetached);
|
||||
Core::HID::NpadType::JoyconDual);
|
||||
emulated_controllers[player_index]->addItem(tr("Dual Joycons"));
|
||||
|
||||
pairs.emplace_back(emulated_controllers[player_index]->count(),
|
||||
Settings::ControllerType::LeftJoycon);
|
||||
Core::HID::NpadType::JoyconLeft);
|
||||
emulated_controllers[player_index]->addItem(tr("Left Joycon"));
|
||||
|
||||
pairs.emplace_back(emulated_controllers[player_index]->count(),
|
||||
Settings::ControllerType::RightJoycon);
|
||||
Core::HID::NpadType::JoyconRight);
|
||||
emulated_controllers[player_index]->addItem(tr("Right Joycon"));
|
||||
|
||||
if (player_index == 0) {
|
||||
pairs.emplace_back(emulated_controllers[player_index]->count(),
|
||||
Settings::ControllerType::Handheld);
|
||||
Core::HID::NpadType::Handheld);
|
||||
emulated_controllers[player_index]->addItem(tr("Handheld"));
|
||||
}
|
||||
|
||||
pairs.emplace_back(emulated_controllers[player_index]->count(),
|
||||
Settings::ControllerType::GameCube);
|
||||
pairs.emplace_back(emulated_controllers[player_index]->count(), Core::HID::NpadType::GameCube);
|
||||
emulated_controllers[player_index]->addItem(tr("GameCube Controller"));
|
||||
}
|
||||
|
||||
Settings::ControllerType QtControllerSelectorDialog::GetControllerTypeFromIndex(
|
||||
Core::HID::NpadType QtControllerSelectorDialog::GetControllerTypeFromIndex(
|
||||
int index, std::size_t player_index) const {
|
||||
const auto& pairs = index_controller_type_pairs[player_index];
|
||||
|
||||
@ -451,13 +435,13 @@ Settings::ControllerType QtControllerSelectorDialog::GetControllerTypeFromIndex(
|
||||
[index](const auto& pair) { return pair.first == index; });
|
||||
|
||||
if (it == pairs.end()) {
|
||||
return Settings::ControllerType::ProController;
|
||||
return Core::HID::NpadType::ProController;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
int QtControllerSelectorDialog::GetIndexFromControllerType(Settings::ControllerType type,
|
||||
int QtControllerSelectorDialog::GetIndexFromControllerType(Core::HID::NpadType type,
|
||||
std::size_t player_index) const {
|
||||
const auto& pairs = index_controller_type_pairs[player_index];
|
||||
|
||||
@ -481,16 +465,16 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index)
|
||||
const QString stylesheet = [this, player_index] {
|
||||
switch (GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(),
|
||||
player_index)) {
|
||||
case Settings::ControllerType::ProController:
|
||||
case Settings::ControllerType::GameCube:
|
||||
case Core::HID::NpadType::ProController:
|
||||
case Core::HID::NpadType::GameCube:
|
||||
return QStringLiteral("image: url(:/controller/applet_pro_controller%0); ");
|
||||
case Settings::ControllerType::DualJoyconDetached:
|
||||
case Core::HID::NpadType::JoyconDual:
|
||||
return QStringLiteral("image: url(:/controller/applet_dual_joycon%0); ");
|
||||
case Settings::ControllerType::LeftJoycon:
|
||||
case Core::HID::NpadType::JoyconLeft:
|
||||
return QStringLiteral("image: url(:/controller/applet_joycon_left%0); ");
|
||||
case Settings::ControllerType::RightJoycon:
|
||||
case Core::HID::NpadType::JoyconRight:
|
||||
return QStringLiteral("image: url(:/controller/applet_joycon_right%0); ");
|
||||
case Settings::ControllerType::Handheld:
|
||||
case Core::HID::NpadType::Handheld:
|
||||
return QStringLiteral("image: url(:/controller/applet_handheld%0); ");
|
||||
default:
|
||||
return QString{};
|
||||
@ -518,54 +502,42 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index)
|
||||
}
|
||||
|
||||
void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) {
|
||||
auto& player = Settings::values.players.GetValue()[player_index];
|
||||
auto* controller = system.HIDCore().GetEmulatedControllerByIndex(player_index);
|
||||
|
||||
const auto controller_type = GetControllerTypeFromIndex(
|
||||
emulated_controllers[player_index]->currentIndex(), player_index);
|
||||
const auto player_connected = player_groupboxes[player_index]->isChecked() &&
|
||||
controller_type != Settings::ControllerType::Handheld;
|
||||
controller_type != Core::HID::NpadType::Handheld;
|
||||
|
||||
if (player.controller_type == controller_type && player.connected == player_connected) {
|
||||
if (controller->GetNpadType() == controller_type &&
|
||||
controller->IsConnected() == player_connected) {
|
||||
// Set vibration devices in the event that the input device has changed.
|
||||
ConfigureVibration::SetVibrationDevices(player_index);
|
||||
return;
|
||||
}
|
||||
|
||||
// Disconnect the controller first.
|
||||
UpdateController(controller_type, player_index, false, system);
|
||||
|
||||
player.controller_type = controller_type;
|
||||
player.connected = player_connected;
|
||||
UpdateController(controller, controller_type, false);
|
||||
|
||||
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;
|
||||
if (controller_type == Core::HID::NpadType::Handheld) {
|
||||
auto* handheld =
|
||||
system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
|
||||
UpdateController(handheld, Core::HID::NpadType::Handheld,
|
||||
player_groupboxes[player_index]->isChecked());
|
||||
}
|
||||
handheld.connected = player_groupboxes[player_index]->isChecked() &&
|
||||
controller_type == Settings::ControllerType::Handheld;
|
||||
UpdateController(Settings::ControllerType::Handheld, 8, handheld.connected, system);
|
||||
}
|
||||
|
||||
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(60ms);
|
||||
|
||||
UpdateController(controller_type, player_index, player_connected, system);
|
||||
UpdateController(controller, controller_type, player_connected);
|
||||
}
|
||||
|
||||
void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) {
|
||||
if (!player_groupboxes[player_index]->isChecked() ||
|
||||
GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(),
|
||||
player_index) == Settings::ControllerType::Handheld) {
|
||||
player_index) == Core::HID::NpadType::Handheld) {
|
||||
led_patterns_boxes[player_index][0]->setChecked(false);
|
||||
led_patterns_boxes[player_index][1]->setChecked(false);
|
||||
led_patterns_boxes[player_index][2]->setChecked(false);
|
||||
@ -573,10 +545,12 @@ void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) {
|
||||
return;
|
||||
}
|
||||
|
||||
led_patterns_boxes[player_index][0]->setChecked(led_patterns[player_index][0]);
|
||||
led_patterns_boxes[player_index][1]->setChecked(led_patterns[player_index][1]);
|
||||
led_patterns_boxes[player_index][2]->setChecked(led_patterns[player_index][2]);
|
||||
led_patterns_boxes[player_index][3]->setChecked(led_patterns[player_index][3]);
|
||||
const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(player_index);
|
||||
const auto led_pattern = controller->GetLedPattern();
|
||||
led_patterns_boxes[player_index][0]->setChecked(led_pattern.position1);
|
||||
led_patterns_boxes[player_index][1]->setChecked(led_pattern.position2);
|
||||
led_patterns_boxes[player_index][2]->setChecked(led_pattern.position3);
|
||||
led_patterns_boxes[player_index][3]->setChecked(led_pattern.position4);
|
||||
}
|
||||
|
||||
void QtControllerSelectorDialog::UpdateBorderColor(std::size_t player_index) {
|
||||
@ -656,10 +630,9 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() {
|
||||
}
|
||||
|
||||
for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) {
|
||||
auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index);
|
||||
// Disconnect any unsupported players here and disable or hide them if applicable.
|
||||
Settings::values.players.GetValue()[index].connected = false;
|
||||
UpdateController(Settings::values.players.GetValue()[index].controller_type, index, false,
|
||||
system);
|
||||
UpdateController(controller, controller->GetNpadType(), 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();
|
||||
|
Reference in New Issue
Block a user