GUI + calibration + multiple sources
Added proper QT GUI and proper multiple controller support. Calibration using offsets and sensitivity as a scale factor has also been added.
This commit is contained in:
@@ -236,8 +236,12 @@ 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].motion_devices.begin(), players[i].motion_devices.end(),
|
||||
motion_sensors[i].begin(), [](const Settings::MotionRaw& raw) {
|
||||
return raw.enabled ? Input::CreateDevice<Input::MotionDevice>(raw.device)
|
||||
: nullptr;
|
||||
});
|
||||
}
|
||||
motion_sensors[0] = Input::CreateDevice<Input::MotionDevice>(Settings::values.motion_device);
|
||||
}
|
||||
|
||||
void Controller_NPad::OnRelease() {}
|
||||
@@ -369,19 +373,16 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
auto& pad_state = npad_pad_states[npad_index];
|
||||
|
||||
// Try to get motion sensor state if it exists
|
||||
Common::Vec3f accel, gyro;
|
||||
if (sixaxis_sensor_enabled && motion_sensors[i]) {
|
||||
std::tie(accel, gyro) = motion_sensors[i]->GetStatus();
|
||||
#if 1
|
||||
std::ostringstream builder{};
|
||||
builder << "Got gyro x=";
|
||||
builder << gyro.x;
|
||||
builder << " y=";
|
||||
builder << gyro.y;
|
||||
builder << " z=";
|
||||
builder << gyro.z;
|
||||
LOG_INFO(Service_HID, builder.str().c_str());
|
||||
#endif
|
||||
Common::Vec3f accel1, gyro1, accel2, gyro2;
|
||||
if (sixaxis_sensor_enabled) {
|
||||
const auto& sensor1 = motion_sensors[i][0];
|
||||
const auto& sensor2 = motion_sensors[i][1];
|
||||
if (sensor1) {
|
||||
std::tie(accel1, gyro1) = sensor1->GetStatus();
|
||||
}
|
||||
if (sensor2) {
|
||||
std::tie(accel2, gyro2) = sensor2->GetStatus();
|
||||
}
|
||||
}
|
||||
|
||||
auto& main_controller =
|
||||
@@ -413,9 +414,9 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
handheld_entry.pad.l_stick = pad_state.l_stick;
|
||||
handheld_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
if (sixaxis_sensor_enabled && motion_sensors[i]) {
|
||||
npad.handheld.sixaxis[npad.handheld.common.last_entry_index].accelerometer = accel;
|
||||
npad.handheld.sixaxis[npad.handheld.common.last_entry_index].gyroscope = gyro;
|
||||
if (sixaxis_sensor_enabled && motion_sensors[i][0]) {
|
||||
npad.handheld.sixaxis[npad.handheld.common.last_entry_index].accelerometer = accel1;
|
||||
npad.handheld.sixaxis[npad.handheld.common.last_entry_index].gyroscope = gyro1;
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::JoyDual:
|
||||
@@ -433,15 +434,21 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
dual_entry.pad.l_stick = pad_state.l_stick;
|
||||
dual_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
if (sixaxis_sensor_enabled && motion_sensors[i]) {
|
||||
// TODO(anirudhb): Separate inputs for dual joy-cons.
|
||||
npad.left_dual.sixaxis[npad.left_dual.common.last_entry_index].accelerometer =
|
||||
accel;
|
||||
npad.left_dual.sixaxis[npad.left_dual.common.last_entry_index].gyroscope = gyro;
|
||||
|
||||
npad.right_dual.sixaxis[npad.right_dual.common.last_entry_index].accelerometer =
|
||||
accel;
|
||||
npad.right_dual.sixaxis[npad.right_dual.common.last_entry_index].gyroscope = gyro;
|
||||
if (sixaxis_sensor_enabled) {
|
||||
if (motion_sensors[i][0] && motion_sensors[i][1]) {
|
||||
npad.left_dual.sixaxis[npad.left_dual.common.last_entry_index].accelerometer =
|
||||
accel1;
|
||||
npad.left_dual.sixaxis[npad.left_dual.common.last_entry_index].gyroscope = gyro1;
|
||||
npad.right_dual.sixaxis[npad.right_dual.common.last_entry_index].accelerometer =
|
||||
accel2;
|
||||
npad.right_dual.sixaxis[npad.right_dual.common.last_entry_index].gyroscope =
|
||||
gyro2;
|
||||
} else {
|
||||
npad.right_dual.sixaxis[npad.right_dual.common.last_entry_index].accelerometer =
|
||||
accel1;
|
||||
npad.right_dual.sixaxis[npad.right_dual.common.last_entry_index].gyroscope =
|
||||
gyro1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::JoyLeft:
|
||||
@@ -452,9 +459,9 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
left_entry.pad.l_stick = pad_state.l_stick;
|
||||
left_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
if (sixaxis_sensor_enabled && motion_sensors[i]) {
|
||||
npad.left.sixaxis[npad.left.common.last_entry_index].accelerometer = accel;
|
||||
npad.left.sixaxis[npad.left.common.last_entry_index].gyroscope = gyro;
|
||||
if (sixaxis_sensor_enabled && motion_sensors[i][0]) {
|
||||
npad.left.sixaxis[npad.left.common.last_entry_index].accelerometer = accel1;
|
||||
npad.left.sixaxis[npad.left.common.last_entry_index].gyroscope = gyro1;
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::JoyRight:
|
||||
@@ -465,9 +472,9 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
right_entry.pad.l_stick = pad_state.l_stick;
|
||||
right_entry.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
if (sixaxis_sensor_enabled && motion_sensors[i]) {
|
||||
npad.right.sixaxis[npad.right.common.last_entry_index].accelerometer = accel;
|
||||
npad.right.sixaxis[npad.right.common.last_entry_index].gyroscope = gyro;
|
||||
if (sixaxis_sensor_enabled && motion_sensors[i][0]) {
|
||||
npad.right.sixaxis[npad.right.common.last_entry_index].accelerometer = accel1;
|
||||
npad.right.sixaxis[npad.right.common.last_entry_index].gyroscope = gyro1;
|
||||
}
|
||||
break;
|
||||
case NPadControllerType::Pokeball:
|
||||
@@ -489,9 +496,9 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
main_controller.pad.l_stick = pad_state.l_stick;
|
||||
main_controller.pad.r_stick = pad_state.r_stick;
|
||||
|
||||
if (sixaxis_sensor_enabled && motion_sensors[i]) {
|
||||
npad.full.sixaxis[npad.full.common.last_entry_index].accelerometer = accel;
|
||||
npad.full.sixaxis[npad.full.common.last_entry_index].gyroscope = gyro;
|
||||
if (sixaxis_sensor_enabled && motion_sensors[i][0]) {
|
||||
npad.full.sixaxis[npad.full.common.last_entry_index].accelerometer = accel1;
|
||||
npad.full.sixaxis[npad.full.common.last_entry_index].gyroscope = gyro1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -340,7 +340,7 @@ private:
|
||||
std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>,
|
||||
10>
|
||||
sticks;
|
||||
std::array<std::unique_ptr<Input::MotionDevice>, 10> motion_sensors;
|
||||
std::array<std::array<std::unique_ptr<Input::MotionDevice>, 2>, 10> motion_sensors;
|
||||
bool sixaxis_sensor_enabled{true};
|
||||
std::vector<u32> supported_npad_id_types{};
|
||||
NpadHoldType hold_type{NpadHoldType::Vertical};
|
||||
|
||||
@@ -324,12 +324,19 @@ enum class ControllerType {
|
||||
LeftJoycon,
|
||||
};
|
||||
|
||||
struct MotionRaw {
|
||||
bool enabled;
|
||||
std::string device;
|
||||
};
|
||||
|
||||
struct PlayerInput {
|
||||
bool connected;
|
||||
ControllerType type;
|
||||
ButtonsRaw buttons;
|
||||
AnalogsRaw analogs;
|
||||
|
||||
std::array<MotionRaw, 2> motion_devices;
|
||||
|
||||
u32 body_color_right;
|
||||
u32 button_color_right;
|
||||
u32 body_color_left;
|
||||
|
||||
@@ -52,6 +52,17 @@ MotionEmu* GetMotionEmu() {
|
||||
return motion_emu.get();
|
||||
}
|
||||
|
||||
std::string GenerateMotionParam(const std::string& address, int port, int pad_index, float cx,
|
||||
float cy, float cz, float sensitivity) {
|
||||
Common::ParamPackage param{
|
||||
{"engine", "cemuhookudp"}, {"address", address},
|
||||
{"port", std::to_string(port)}, {"pad_index", std::to_string(pad_index)},
|
||||
{"cx", std::to_string(cx)}, {"cy", std::to_string(cy)},
|
||||
{"cz", std::to_string(cz)}, {"sensitivity", std::to_string(sensitivity)},
|
||||
};
|
||||
return param.Serialize();
|
||||
}
|
||||
|
||||
std::string GenerateKeyboardParam(int key_code) {
|
||||
Common::ParamPackage param{
|
||||
{"engine", "keyboard"},
|
||||
|
||||
@@ -30,6 +30,10 @@ class MotionEmu;
|
||||
/// Gets the motion emulation factory.
|
||||
MotionEmu* GetMotionEmu();
|
||||
|
||||
/// Generates a serialized param package for creating a cemuhookudp motion device
|
||||
std::string GenerateMotionParam(const std::string& address, int port, int pad_index, float cx,
|
||||
float cy, float cz, float sensitivity);
|
||||
|
||||
/// Generates a serialized param package for creating a keyboard button device
|
||||
std::string GenerateKeyboardParam(int key_code);
|
||||
|
||||
|
||||
@@ -28,14 +28,24 @@ private:
|
||||
|
||||
class UDPMotionDevice final : public Input::MotionDevice {
|
||||
public:
|
||||
explicit UDPMotionDevice(std::shared_ptr<DeviceStatus> status_) : status(std::move(status_)) {}
|
||||
explicit UDPMotionDevice(const std::string& host, int port, int pad_index, Common::Vec3f offset,
|
||||
float sensitivity)
|
||||
: offset(offset), sensitivity(sensitivity) {
|
||||
status = std::make_shared<DeviceStatus>();
|
||||
client = std::make_unique<Client>(status, host, port, pad_index);
|
||||
}
|
||||
std::tuple<Common::Vec3<float>, Common::Vec3<float>> GetStatus() const override {
|
||||
std::lock_guard guard(status->update_mutex);
|
||||
return status->motion_status;
|
||||
std::tuple<Common::Vec3<float>, Common::Vec3<float>> motion = status->motion_status;
|
||||
std::get<0>(motion) = (std::get<0>(motion) + offset) * sensitivity;
|
||||
return motion;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<DeviceStatus> status;
|
||||
std::unique_ptr<Client> client;
|
||||
Common::Vec3f offset;
|
||||
float sensitivity;
|
||||
};
|
||||
|
||||
class UDPTouchFactory final : public Input::Factory<Input::TouchDevice> {
|
||||
@@ -73,14 +83,13 @@ public:
|
||||
std::string host = params.Get("host", "127.0.0.1");
|
||||
int port = params.Get("port", 26760);
|
||||
int pad_index = params.Get("pad_index", 0);
|
||||
status = std::make_shared<DeviceStatus>();
|
||||
client = std::make_shared<Client>(status, host, port, pad_index);
|
||||
return std::make_unique<UDPMotionDevice>(status);
|
||||
float cx = params.Get("cx", 0);
|
||||
float cy = params.Get("cy", 0);
|
||||
float cz = params.Get("cz", 0);
|
||||
Common::Vec3f offset(cx, cy, cz);
|
||||
float sensitivity = params.Get("sensitivity", 1);
|
||||
return std::make_unique<UDPMotionDevice>(host, port, pad_index, offset, sensitivity);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<DeviceStatus> status;
|
||||
std::shared_ptr<Client> client;
|
||||
};
|
||||
|
||||
State::State() {
|
||||
|
||||
@@ -293,6 +293,26 @@ void Config::ReadPlayerValues() {
|
||||
player_analogs = default_param;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
const std::string default_param =
|
||||
InputCommon::GenerateMotionParam("127.0.0.1", 26760, 0, 0, 0, 0, 1);
|
||||
auto& player_motion = player.motion_devices[i];
|
||||
|
||||
player_motion.device =
|
||||
qt_config
|
||||
->value(QStringLiteral("player_%1_motion_device%2").arg(p).arg(i),
|
||||
QString::fromStdString(default_param))
|
||||
.toString()
|
||||
.toStdString();
|
||||
player_motion.enabled =
|
||||
qt_config
|
||||
->value(QStringLiteral("player_%1_motion_device%2/enabled").arg(p).arg(i), false)
|
||||
.toBool();
|
||||
if (player_motion.device.empty()) {
|
||||
player_motion.device = default_param;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::stable_partition(
|
||||
@@ -845,6 +865,16 @@ void Config::SavePlayerValues() {
|
||||
QString::fromStdString(player.analogs[i]),
|
||||
QString::fromStdString(default_param));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
const std::string default_param =
|
||||
InputCommon::GenerateMotionParam("127.0.0.1", 26760, 0, 0, 0, 0, 1);
|
||||
WriteSetting(QStringLiteral("player_%1_motion_device%2").arg(p).arg(i),
|
||||
QString::fromStdString(player.motion_devices[i].device),
|
||||
QString::fromStdString(default_param));
|
||||
WriteSetting(QStringLiteral("player_%1_motion_device%2/enabled").arg(p).arg(i),
|
||||
player.motion_devices[i].enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,13 @@
|
||||
#include <QKeyEvent>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QProgressBar>
|
||||
#include <QProgressDialog>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
#include "common/assert.h"
|
||||
#include "common/param_package.h"
|
||||
#include "core/frontend/input.h"
|
||||
#include "input_common/main.h"
|
||||
#include "ui_configure_input_player.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
@@ -176,8 +180,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
if (debug)
|
||||
layout = Settings::ControllerType::DualJoycon;
|
||||
|
||||
ui->firstMotionDeviceInner->hide();
|
||||
ui->secondMotionDeviceInner->hide();
|
||||
|
||||
switch (layout) {
|
||||
case Settings::ControllerType::ProController:
|
||||
ui->secondMotionDevice_2->hide(); // frame
|
||||
case Settings::ControllerType::DualJoycon:
|
||||
layout_hidden = {
|
||||
ui->buttonSL,
|
||||
@@ -187,6 +195,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
};
|
||||
break;
|
||||
case Settings::ControllerType::LeftJoycon:
|
||||
ui->secondMotionDevice_2->hide(); // frame
|
||||
layout_hidden = {
|
||||
ui->right_body_button,
|
||||
ui->right_buttons_button,
|
||||
@@ -205,6 +214,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
};
|
||||
break;
|
||||
case Settings::ControllerType::RightJoycon:
|
||||
ui->secondMotionDevice_2->hide(); // frame
|
||||
layout_hidden = {
|
||||
ui->left_body_button, ui->left_buttons_button,
|
||||
ui->left_body_label, ui->left_buttons_label,
|
||||
@@ -217,6 +227,10 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
break;
|
||||
}
|
||||
|
||||
if (layout == Settings::ControllerType::DualJoycon) {
|
||||
ui->firstMotionEnabled->setText(tr("Left"));
|
||||
}
|
||||
|
||||
if (debug || layout == Settings::ControllerType::ProController) {
|
||||
ui->controller_color->hide();
|
||||
} else {
|
||||
@@ -234,6 +248,59 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
for (auto* widget : layout_hidden)
|
||||
widget->setVisible(false);
|
||||
|
||||
motion_groups[0] = {
|
||||
ui->motionAddress1, ui->motionPort1,
|
||||
ui->motionPadIndex1, ui->gyroXoff1,
|
||||
ui->gyroYoff1, ui->gyroZoff1,
|
||||
ui->gyroSensitivity1, ui->calibrate1,
|
||||
ui->firstMotionEnabled, ui->firstMotionDeviceInner,
|
||||
};
|
||||
motion_groups[1] = {
|
||||
ui->motionAddress2, ui->motionPort2,
|
||||
ui->motionPadIndex2, ui->gyroXoff2,
|
||||
ui->gyroYoff2, ui->gyroZoff2,
|
||||
ui->gyroSensitivity2, ui->calibrate2,
|
||||
ui->secondMotionEnabled, ui->secondMotionDeviceInner,
|
||||
};
|
||||
|
||||
for (const auto& group : motion_groups) {
|
||||
connect(group.calibrateButton, &QPushButton::clicked, [=] {
|
||||
if (QMessageBox::information(this, tr("Gyro calibration"),
|
||||
tr("Put your controller flat, then press OK to continue."),
|
||||
QMessageBox::Ok, QMessageBox::Cancel) == QMessageBox::Ok) {
|
||||
QProgressDialog* progress = new QProgressDialog(this);
|
||||
QProgressBar* bar = new QProgressBar(progress);
|
||||
bar->setRange(0, 0);
|
||||
bar->setValue(0);
|
||||
progress->setWindowTitle(tr("Gyro calibration"));
|
||||
progress->setLabelText(tr("Please wait..."));
|
||||
progress->setBar(bar);
|
||||
progress->setCancelButton(nullptr);
|
||||
progress->show();
|
||||
// Get 100 samples and set boxes
|
||||
std::string address = group.address->text().toStdString();
|
||||
// offsets are applied before scaling
|
||||
std::string param = InputCommon::GenerateMotionParam(
|
||||
address, group.port->value(), group.padIndex->value(), 0, 0, 0, 1);
|
||||
std::unique_ptr<Input::MotionDevice> device =
|
||||
Input::CreateDevice<Input::MotionDevice>(param);
|
||||
Common::Vec3f acc;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
Common::Vec3f gyro, accel;
|
||||
std::tie(gyro, accel) = device->GetStatus();
|
||||
acc += gyro;
|
||||
QApplication::processEvents();
|
||||
QThread::msleep(16);
|
||||
}
|
||||
acc /= 100;
|
||||
progress->close();
|
||||
group.cx->setValue(acc.x);
|
||||
group.cy->setValue(acc.y);
|
||||
group.cz->setValue(acc.z);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
analog_map_stick = {ui->buttonLStickAnalog, ui->buttonRStickAnalog};
|
||||
analog_map_deadzone_and_modifier_slider = {ui->sliderLStickDeadzoneAndModifier,
|
||||
ui->sliderRStickDeadzoneAndModifier};
|
||||
@@ -248,24 +315,25 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
|
||||
button->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(button, &QPushButton::clicked, [=] {
|
||||
HandleClick(button_map[button_id],
|
||||
[=](Common::ParamPackage params) {
|
||||
// Workaround for ZL & ZR for analog triggers like on XBOX controllors.
|
||||
// Analog triggers (from controllers like the XBOX controller) would not
|
||||
// work due to a different range of their signals (from 0 to 255 on
|
||||
// analog triggers instead of -32768 to 32768 on analog joysticks). The
|
||||
// SDL driver misinterprets analog triggers as analog joysticks.
|
||||
// TODO: reinterpret the signal range for analog triggers to map the
|
||||
// values correctly. This is required for the correct emulation of the
|
||||
// analog triggers of the GameCube controller.
|
||||
if (button_id == Settings::NativeButton::ZL ||
|
||||
button_id == Settings::NativeButton::ZR) {
|
||||
params.Set("direction", "+");
|
||||
params.Set("threshold", "0.5");
|
||||
}
|
||||
buttons_param[button_id] = std::move(params);
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Button);
|
||||
HandleClick(
|
||||
button_map[button_id],
|
||||
[=](Common::ParamPackage params) {
|
||||
// Workaround for ZL & ZR for analog triggers like on XBOX controllors.
|
||||
// Analog triggers (from controllers like the XBOX controller) would not
|
||||
// work due to a different range of their signals (from 0 to 255 on
|
||||
// analog triggers instead of -32768 to 32768 on analog joysticks). The
|
||||
// SDL driver misinterprets analog triggers as analog joysticks.
|
||||
// TODO: reinterpret the signal range for analog triggers to map the
|
||||
// values correctly. This is required for the correct emulation of the
|
||||
// analog triggers of the GameCube controller.
|
||||
if (button_id == Settings::NativeButton::ZL ||
|
||||
button_id == Settings::NativeButton::ZR) {
|
||||
params.Set("direction", "+");
|
||||
params.Set("threshold", "0.5");
|
||||
}
|
||||
buttons_param[button_id] = std::move(params);
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Button);
|
||||
});
|
||||
connect(button, &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) {
|
||||
QMenu context_menu;
|
||||
@@ -291,12 +359,13 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
|
||||
analog_button->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(analog_button, &QPushButton::clicked, [=]() {
|
||||
HandleClick(analog_map_buttons[analog_id][sub_button_id],
|
||||
[=](const Common::ParamPackage& params) {
|
||||
SetAnalogButton(params, analogs_param[analog_id],
|
||||
analog_sub_buttons[sub_button_id]);
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Button);
|
||||
HandleClick(
|
||||
analog_map_buttons[analog_id][sub_button_id],
|
||||
[=](const Common::ParamPackage& params) {
|
||||
SetAnalogButton(params, analogs_param[analog_id],
|
||||
analog_sub_buttons[sub_button_id]);
|
||||
},
|
||||
InputCommon::Polling::DeviceType::Button);
|
||||
});
|
||||
connect(analog_button, &QPushButton::customContextMenuRequested,
|
||||
[=](const QPoint& menu_location) {
|
||||
@@ -387,11 +456,16 @@ void ConfigureInputPlayer::ApplyConfiguration() {
|
||||
debug ? Settings::values.debug_pad_buttons : Settings::values.players[player_index].buttons;
|
||||
auto& analogs =
|
||||
debug ? Settings::values.debug_pad_analogs : Settings::values.players[player_index].analogs;
|
||||
auto& motion = Settings::values.players[player_index].motion_devices;
|
||||
|
||||
std::transform(buttons_param.begin(), buttons_param.end(), buttons.begin(),
|
||||
[](const Common::ParamPackage& param) { return param.Serialize(); });
|
||||
std::transform(analogs_param.begin(), analogs_param.end(), analogs.begin(),
|
||||
[](const Common::ParamPackage& param) { return param.Serialize(); });
|
||||
std::transform(motion_param.begin(), motion_param.end(), motion.begin(),
|
||||
[](const MotionParam& param) {
|
||||
return Settings::MotionRaw{param.enabled, param.param.Serialize()};
|
||||
});
|
||||
|
||||
if (debug)
|
||||
return;
|
||||
@@ -443,6 +517,11 @@ void ConfigureInputPlayer::LoadConfiguration() {
|
||||
std::transform(Settings::values.players[player_index].analogs.begin(),
|
||||
Settings::values.players[player_index].analogs.end(), analogs_param.begin(),
|
||||
[](const std::string& str) { return Common::ParamPackage(str); });
|
||||
std::transform(Settings::values.players[player_index].motion_devices.begin(),
|
||||
Settings::values.players[player_index].motion_devices.end(),
|
||||
motion_param.begin(), [](const Settings::MotionRaw& raw) {
|
||||
return MotionParam{raw.enabled, Common::ParamPackage(raw.device)};
|
||||
});
|
||||
}
|
||||
|
||||
UpdateButtonLabels();
|
||||
@@ -480,6 +559,17 @@ void ConfigureInputPlayer::RestoreDefaults() {
|
||||
SetAnalogButton(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& group : motion_groups) {
|
||||
group.address->setText(tr("127.0.0.1"));
|
||||
group.port->setValue(26760);
|
||||
group.padIndex->setValue(0);
|
||||
group.cx->setValue(0);
|
||||
group.cy->setValue(0);
|
||||
group.cz->setValue(0);
|
||||
group.enabled->setChecked(false);
|
||||
group.inner->hide();
|
||||
}
|
||||
UpdateButtonLabels();
|
||||
}
|
||||
|
||||
@@ -553,6 +643,20 @@ void ConfigureInputPlayer::UpdateButtonLabels() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int motion_id = 0; motion_id < 2; motion_id++) {
|
||||
auto& param = motion_param[motion_id];
|
||||
auto& group = motion_groups[motion_id];
|
||||
|
||||
group.address->setText(QString::fromStdString(param.param.Get("address", "127.0.0.1")));
|
||||
group.port->setValue(param.param.Get("port", 26760));
|
||||
group.padIndex->setValue(param.param.Get("pad_index", 0));
|
||||
group.cx->setValue(param.param.Get("cx", 0));
|
||||
group.cy->setValue(param.param.Get("cy", 0));
|
||||
group.cz->setValue(param.param.Get("cz", 0));
|
||||
group.enabled->setChecked(param.enabled);
|
||||
group.inner->setVisible(param.enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::HandleClick(
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
#include "ui_configure_input.h"
|
||||
|
||||
class QKeyEvent;
|
||||
class QLineEdit;
|
||||
class QSpinBox;
|
||||
class QDoubleSpinBox;
|
||||
class QPushButton;
|
||||
class QString;
|
||||
class QTimer;
|
||||
@@ -78,8 +81,14 @@ private:
|
||||
/// This will be the the setting function when an input is awaiting configuration.
|
||||
std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
|
||||
|
||||
struct MotionParam {
|
||||
bool enabled;
|
||||
Common::ParamPackage param;
|
||||
};
|
||||
|
||||
std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param;
|
||||
std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param;
|
||||
std::array<MotionParam, 2> motion_param;
|
||||
|
||||
static constexpr int ANALOG_SUB_BUTTONS_NUM = 5;
|
||||
|
||||
@@ -102,6 +111,21 @@ private:
|
||||
std::array<QLabel*, Settings::NativeAnalog::NumAnalogs>
|
||||
analog_map_deadzone_and_modifier_slider_label;
|
||||
|
||||
/// Motion inputs are represented with 6 fields, used to configure calibration and connection
|
||||
struct MotionGroup {
|
||||
QLineEdit* address;
|
||||
QSpinBox* port;
|
||||
QSpinBox* padIndex;
|
||||
QDoubleSpinBox* cx;
|
||||
QDoubleSpinBox* cy;
|
||||
QDoubleSpinBox* cz;
|
||||
QDoubleSpinBox* sensitivity;
|
||||
QPushButton* calibrateButton;
|
||||
QCheckBox* enabled;
|
||||
QFrame* inner;
|
||||
};
|
||||
std::array<MotionGroup, 2> motion_groups;
|
||||
|
||||
static const std::array<std::string, ANALOG_SUB_BUTTONS_NUM> analog_sub_buttons;
|
||||
|
||||
std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user