mirror of
https://github.com/yuzu-emu/yuzu-android.git
synced 2025-06-13 21:37:58 -05:00
Merge pull request #4594 from german77/MotionHID
hid/configuration: Implement motion controls to HID
This commit is contained in:
@ -18,6 +18,7 @@
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
#include "input_common/gcadapter/gc_poller.h"
|
||||
#include "input_common/main.h"
|
||||
#include "input_common/udp/udp.h"
|
||||
#include "ui_configure_input_player.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configure_input_player.h"
|
||||
@ -149,6 +150,14 @@ QString ButtonToText(const Common::ParamPackage& param) {
|
||||
return GetKeyName(param.Get("code", 0));
|
||||
}
|
||||
|
||||
if (param.Get("engine", "") == "cemuhookudp") {
|
||||
if (param.Has("pad_index")) {
|
||||
const QString motion_str = QString::fromStdString(param.Get("pad_index", ""));
|
||||
return QObject::tr("Motion %1").arg(motion_str);
|
||||
}
|
||||
return GetKeyName(param.Get("code", 0));
|
||||
}
|
||||
|
||||
if (param.Get("engine", "") == "sdl") {
|
||||
if (param.Has("hat")) {
|
||||
const QString hat_str = QString::fromStdString(param.Get("hat", ""));
|
||||
@ -262,6 +271,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
},
|
||||
}};
|
||||
|
||||
motion_map = {
|
||||
ui->buttonMotionLeft,
|
||||
ui->buttonMotionRight,
|
||||
};
|
||||
|
||||
analog_map_deadzone_label = {ui->labelLStickDeadzone, ui->labelRStickDeadzone};
|
||||
analog_map_deadzone_slider = {ui->sliderLStickDeadzone, ui->sliderRStickDeadzone};
|
||||
analog_map_modifier_groupbox = {ui->buttonLStickModGroup, ui->buttonRStickModGroup};
|
||||
@ -304,6 +318,32 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
Config::default_buttons[button_id]);
|
||||
}
|
||||
|
||||
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
|
||||
auto* const button = motion_map[motion_id];
|
||||
if (button == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
button->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(button, &QPushButton::clicked, [=, this] {
|
||||
HandleClick(
|
||||
motion_map[motion_id],
|
||||
[=, this](Common::ParamPackage params) {
|
||||
motions_param[motion_id] = std::move(params);
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Motion);
|
||||
});
|
||||
connect(button, &QPushButton::customContextMenuRequested,
|
||||
[=, this](const QPoint& menu_location) {
|
||||
QMenu context_menu;
|
||||
context_menu.addAction(tr("Clear"), [&] {
|
||||
motions_param[motion_id].Clear();
|
||||
motion_map[motion_id]->setText(tr("[not set]"));
|
||||
});
|
||||
context_menu.exec(motion_map[motion_id]->mapToGlobal(menu_location));
|
||||
});
|
||||
}
|
||||
|
||||
// Handle clicks for the modifier buttons as well.
|
||||
ConfigureButtonClick(ui->buttonLStickMod, &lstick_mod, Config::default_stick_mod[0]);
|
||||
ConfigureButtonClick(ui->buttonRStickMod, &rstick_mod, Config::default_stick_mod[1]);
|
||||
@ -385,9 +425,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
|
||||
UpdateControllerIcon();
|
||||
UpdateControllerAvailableButtons();
|
||||
UpdateMotionButtons();
|
||||
connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this](int) {
|
||||
UpdateControllerIcon();
|
||||
UpdateControllerAvailableButtons();
|
||||
UpdateMotionButtons();
|
||||
});
|
||||
|
||||
connect(ui->comboDevices, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
@ -417,6 +459,13 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (input_subsystem->GetUDPMotions()->IsPolling()) {
|
||||
params = input_subsystem->GetUDPMotions()->GetNextInput();
|
||||
if (params.Has("engine")) {
|
||||
SetPollingResult(params, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (auto& poller : device_pollers) {
|
||||
params = poller->GetNextInput();
|
||||
if (params.Has("engine")) {
|
||||
@ -448,6 +497,10 @@ void ConfigureInputPlayer::ApplyConfiguration() {
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
@ -501,6 +554,8 @@ void ConfigureInputPlayer::LoadConfiguration() {
|
||||
[](const std::string& str) { return Common::ParamPackage(str); });
|
||||
std::transform(player.analogs.begin(), player.analogs.end(), analogs_param.begin(),
|
||||
[](const std::string& str) { return Common::ParamPackage(str); });
|
||||
std::transform(player.motions.begin(), player.motions.end(), motions_param.begin(),
|
||||
[](const std::string& str) { return Common::ParamPackage(str); });
|
||||
}
|
||||
|
||||
UpdateUI();
|
||||
@ -544,6 +599,12 @@ void ConfigureInputPlayer::RestoreDefaults() {
|
||||
SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_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);
|
||||
@ -573,6 +634,15 @@ void ConfigureInputPlayer::ClearAll() {
|
||||
}
|
||||
}
|
||||
|
||||
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
|
||||
const auto* const button = motion_map[motion_id];
|
||||
if (button == nullptr || !button->isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
motions_param[motion_id].Clear();
|
||||
}
|
||||
|
||||
UpdateUI();
|
||||
UpdateInputDevices();
|
||||
}
|
||||
@ -582,6 +652,10 @@ void ConfigureInputPlayer::UpdateUI() {
|
||||
button_map[button]->setText(ButtonToText(buttons_param[button]));
|
||||
}
|
||||
|
||||
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
|
||||
motion_map[motion_id]->setText(ButtonToText(motions_param[motion_id]));
|
||||
}
|
||||
|
||||
ui->buttonLStickMod->setText(ButtonToText(lstick_mod));
|
||||
ui->buttonRStickMod->setText(ButtonToText(rstick_mod));
|
||||
|
||||
@ -659,7 +733,11 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
|
||||
void ConfigureInputPlayer::HandleClick(
|
||||
QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter,
|
||||
InputCommon::Polling::DeviceType type) {
|
||||
button->setText(tr("[waiting]"));
|
||||
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
|
||||
@ -683,6 +761,10 @@ void ConfigureInputPlayer::HandleClick(
|
||||
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
|
||||
}
|
||||
@ -700,6 +782,8 @@ void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params,
|
||||
input_subsystem->GetGCButtons()->EndConfiguration();
|
||||
input_subsystem->GetGCAnalogs()->EndConfiguration();
|
||||
|
||||
input_subsystem->GetUDPMotions()->EndConfiguration();
|
||||
|
||||
if (!abort) {
|
||||
(*input_setter)(params);
|
||||
}
|
||||
@ -832,6 +916,37 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::UpdateMotionButtons() {
|
||||
if (debug) {
|
||||
// Motion isn't used with the debug controller, hide both groupboxes.
|
||||
ui->buttonMotionLeftGroup->hide();
|
||||
ui->buttonMotionRightGroup->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
// Show/hide the "Motion 1/2" groupboxes depending on the currently selected controller.
|
||||
switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) {
|
||||
case Settings::ControllerType::ProController:
|
||||
case Settings::ControllerType::LeftJoycon:
|
||||
case Settings::ControllerType::Handheld:
|
||||
// Show "Motion 1" and hide "Motion 2".
|
||||
ui->buttonMotionLeftGroup->show();
|
||||
ui->buttonMotionRightGroup->hide();
|
||||
break;
|
||||
case Settings::ControllerType::RightJoycon:
|
||||
// Show "Motion 2" and hide "Motion 1".
|
||||
ui->buttonMotionLeftGroup->hide();
|
||||
ui->buttonMotionRightGroup->show();
|
||||
break;
|
||||
case Settings::ControllerType::DualJoyconDetached:
|
||||
default:
|
||||
// Show both "Motion 1/2".
|
||||
ui->buttonMotionLeftGroup->show();
|
||||
ui->buttonMotionRightGroup->show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::showEvent(QShowEvent* event) {
|
||||
if (bottom_row == nullptr) {
|
||||
return;
|
||||
|
Reference in New Issue
Block a user