Merge pull request #4059 from zhaowenlan1779/udp-input-ui
citra_qt: add motion/touch config
This commit is contained in:
commit
50270fd791
|
@ -39,6 +39,8 @@ add_executable(citra-qt
|
||||||
configuration/configure_graphics.h
|
configuration/configure_graphics.h
|
||||||
configuration/configure_input.cpp
|
configuration/configure_input.cpp
|
||||||
configuration/configure_input.h
|
configuration/configure_input.h
|
||||||
|
configuration/configure_motion_touch.cpp
|
||||||
|
configuration/configure_motion_touch.h
|
||||||
configuration/configure_system.cpp
|
configuration/configure_system.cpp
|
||||||
configuration/configure_system.h
|
configuration/configure_system.h
|
||||||
configuration/configure_web.cpp
|
configuration/configure_web.cpp
|
||||||
|
@ -115,6 +117,7 @@ set(UIS
|
||||||
configuration/configure_general.ui
|
configuration/configure_general.ui
|
||||||
configuration/configure_graphics.ui
|
configuration/configure_graphics.ui
|
||||||
configuration/configure_input.ui
|
configuration/configure_input.ui
|
||||||
|
configuration/configure_motion_touch.ui
|
||||||
configuration/configure_system.ui
|
configuration/configure_system.ui
|
||||||
configuration/configure_web.ui
|
configuration/configure_web.ui
|
||||||
debugger/registers.ui
|
debugger/registers.ui
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include "citra_qt/configuration/config.h"
|
#include "citra_qt/configuration/config.h"
|
||||||
#include "citra_qt/configuration/configure_input.h"
|
#include "citra_qt/configuration/configure_input.h"
|
||||||
|
#include "citra_qt/configuration/configure_motion_touch.h"
|
||||||
#include "common/param_package.h"
|
#include "common/param_package.h"
|
||||||
|
|
||||||
const std::array<std::string, ConfigureInput::ANALOG_SUB_BUTTONS_NUM>
|
const std::array<std::string, ConfigureInput::ANALOG_SUB_BUTTONS_NUM>
|
||||||
|
@ -159,6 +160,10 @@ ConfigureInput::ConfigureInput(QWidget* parent)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connect(ui->buttonMotionTouch, &QPushButton::released, [this] {
|
||||||
|
QDialog* motion_touch_dialog = new ConfigureMotionTouch(this);
|
||||||
|
return motion_touch_dialog->exec();
|
||||||
|
});
|
||||||
connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); });
|
connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); });
|
||||||
|
|
||||||
timeout_timer->setSingleShot(true);
|
timeout_timer->setSingleShot(true);
|
||||||
|
|
|
@ -556,6 +556,34 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonMotionTouch">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="sizeIncrement">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="baseSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="layoutDirection">
|
||||||
|
<enum>Qt::LeftToRight</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Motion / Touch...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer">
|
<spacer name="horizontalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|
|
@ -0,0 +1,276 @@
|
||||||
|
// Copyright 2018 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <QCloseEvent>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include "citra_qt/configuration/configure_motion_touch.h"
|
||||||
|
#include "core/settings.h"
|
||||||
|
#include "input_common/main.h"
|
||||||
|
#include "ui_configure_motion_touch.h"
|
||||||
|
|
||||||
|
CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent,
|
||||||
|
const std::string& host, u16 port,
|
||||||
|
u8 pad_index, u16 client_id)
|
||||||
|
: QDialog(parent) {
|
||||||
|
layout = new QVBoxLayout;
|
||||||
|
status_label = new QLabel(tr("Communicating with the server..."));
|
||||||
|
cancel_button = new QPushButton(tr("Cancel"));
|
||||||
|
connect(cancel_button, &QPushButton::clicked, this, [this] {
|
||||||
|
if (!completed)
|
||||||
|
job->Stop();
|
||||||
|
accept();
|
||||||
|
});
|
||||||
|
layout->addWidget(status_label);
|
||||||
|
layout->addWidget(cancel_button);
|
||||||
|
setLayout(layout);
|
||||||
|
|
||||||
|
using namespace InputCommon::CemuhookUDP;
|
||||||
|
job = std::move(std::make_unique<CalibrationConfigurationJob>(
|
||||||
|
host, port, pad_index, client_id,
|
||||||
|
[this](CalibrationConfigurationJob::Status status) {
|
||||||
|
QString text;
|
||||||
|
switch (status) {
|
||||||
|
case CalibrationConfigurationJob::Status::Ready:
|
||||||
|
text = tr("Touch the top left corner <br>of your touchpad.");
|
||||||
|
break;
|
||||||
|
case CalibrationConfigurationJob::Status::Stage1Completed:
|
||||||
|
text = tr("Now touch the bottom right corner <br>of your touchpad.");
|
||||||
|
break;
|
||||||
|
case CalibrationConfigurationJob::Status::Completed:
|
||||||
|
text = tr("Configuration completed!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QMetaObject::invokeMethod(this, "UpdateLabelText", Q_ARG(QString, text));
|
||||||
|
if (status == CalibrationConfigurationJob::Status::Completed) {
|
||||||
|
QMetaObject::invokeMethod(this, "UpdateButtonText", Q_ARG(QString, tr("OK")));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[this](u16 min_x_, u16 min_y_, u16 max_x_, u16 max_y_) {
|
||||||
|
completed = true;
|
||||||
|
min_x = min_x_;
|
||||||
|
min_y = min_y_;
|
||||||
|
max_x = max_x_;
|
||||||
|
max_y = max_y_;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
CalibrationConfigurationDialog::~CalibrationConfigurationDialog() = default;
|
||||||
|
|
||||||
|
void CalibrationConfigurationDialog::UpdateLabelText(QString text) {
|
||||||
|
status_label->setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CalibrationConfigurationDialog::UpdateButtonText(QString text) {
|
||||||
|
cancel_button->setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::array<std::pair<const char*, const char*>, 2> MotionProviders = {
|
||||||
|
{{"motion_emu", QT_TRANSLATE_NOOP("ConfigureMotionTouch", "Mouse (Right Click)")},
|
||||||
|
{"cemuhookudp", QT_TRANSLATE_NOOP("ConfigureMotionTouch", "CemuhookUDP")}}};
|
||||||
|
|
||||||
|
const std::array<std::pair<const char*, const char*>, 2> TouchProviders = {
|
||||||
|
{{"emu_window", QT_TRANSLATE_NOOP("ConfigureMotionTouch", "Emulator Window")},
|
||||||
|
{"cemuhookudp", QT_TRANSLATE_NOOP("ConfigureMotionTouch", "CemuhookUDP")}}};
|
||||||
|
|
||||||
|
ConfigureMotionTouch::ConfigureMotionTouch(QWidget* parent)
|
||||||
|
: QDialog(parent), ui(std::make_unique<Ui::ConfigureMotionTouch>()) {
|
||||||
|
ui->setupUi(this);
|
||||||
|
for (auto [provider, name] : MotionProviders) {
|
||||||
|
ui->motion_provider->addItem(tr(name), provider);
|
||||||
|
}
|
||||||
|
for (auto [provider, name] : TouchProviders) {
|
||||||
|
ui->touch_provider->addItem(tr(name), provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->udp_learn_more->setOpenExternalLinks(true);
|
||||||
|
ui->udp_learn_more->setText(
|
||||||
|
tr("<a "
|
||||||
|
"href='https://citra-emu.org/wiki/"
|
||||||
|
"using-a-controller-or-android-phone-for-motion-or-touch-input'><span "
|
||||||
|
"style=\"text-decoration: underline; color:#039be5;\">Learn More</span></a>"));
|
||||||
|
|
||||||
|
setConfiguration();
|
||||||
|
updateUiDisplay();
|
||||||
|
connectEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigureMotionTouch::~ConfigureMotionTouch() = default;
|
||||||
|
|
||||||
|
void ConfigureMotionTouch::setConfiguration() {
|
||||||
|
Common::ParamPackage motion_param(Settings::values.motion_device);
|
||||||
|
Common::ParamPackage touch_param(Settings::values.touch_device);
|
||||||
|
std::string motion_engine = motion_param.Get("engine", "motion_emu");
|
||||||
|
std::string touch_engine = touch_param.Get("engine", "emu_window");
|
||||||
|
|
||||||
|
ui->motion_provider->setCurrentIndex(
|
||||||
|
ui->motion_provider->findData(QString::fromStdString(motion_engine)));
|
||||||
|
ui->touch_provider->setCurrentIndex(
|
||||||
|
ui->touch_provider->findData(QString::fromStdString(touch_engine)));
|
||||||
|
ui->motion_sensitivity->setValue(motion_param.Get("sensitivity", 0.01f));
|
||||||
|
|
||||||
|
min_x = touch_param.Get("min_x", 100);
|
||||||
|
min_y = touch_param.Get("min_y", 50);
|
||||||
|
max_x = touch_param.Get("max_x", 1800);
|
||||||
|
max_y = touch_param.Get("max_y", 850);
|
||||||
|
|
||||||
|
ui->udp_server->setText(QString::fromStdString(Settings::values.udp_input_address));
|
||||||
|
ui->udp_port->setText(QString::number(Settings::values.udp_input_port));
|
||||||
|
ui->udp_pad_index->setCurrentIndex(Settings::values.udp_pad_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureMotionTouch::updateUiDisplay() {
|
||||||
|
std::string motion_engine = ui->motion_provider->currentData().toString().toStdString();
|
||||||
|
std::string touch_engine = ui->touch_provider->currentData().toString().toStdString();
|
||||||
|
|
||||||
|
if (motion_engine == "motion_emu") {
|
||||||
|
ui->motion_sensitivity_label->setVisible(true);
|
||||||
|
ui->motion_sensitivity->setVisible(true);
|
||||||
|
} else {
|
||||||
|
ui->motion_sensitivity_label->setVisible(false);
|
||||||
|
ui->motion_sensitivity->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (touch_engine == "cemuhookudp") {
|
||||||
|
ui->touch_calibration->setVisible(true);
|
||||||
|
ui->touch_calibration_config->setVisible(true);
|
||||||
|
ui->touch_calibration_label->setVisible(true);
|
||||||
|
ui->touch_calibration->setText(QString("(%1, %2) - (%3, %4)")
|
||||||
|
.arg(QString::number(min_x), QString::number(min_y),
|
||||||
|
QString::number(max_x), QString::number(max_y)));
|
||||||
|
} else {
|
||||||
|
ui->touch_calibration->setVisible(false);
|
||||||
|
ui->touch_calibration_config->setVisible(false);
|
||||||
|
ui->touch_calibration_label->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (motion_engine == "cemuhookudp" || touch_engine == "cemuhookudp") {
|
||||||
|
ui->udp_config_group_box->setVisible(true);
|
||||||
|
} else {
|
||||||
|
ui->udp_config_group_box->setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureMotionTouch::connectEvents() {
|
||||||
|
connect(ui->motion_provider,
|
||||||
|
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
|
||||||
|
[this](int index) { updateUiDisplay(); });
|
||||||
|
connect(ui->touch_provider,
|
||||||
|
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
|
||||||
|
[this](int index) { updateUiDisplay(); });
|
||||||
|
connect(ui->udp_test, &QPushButton::clicked, this, &ConfigureMotionTouch::OnCemuhookUDPTest);
|
||||||
|
connect(ui->touch_calibration_config, &QPushButton::clicked, this,
|
||||||
|
&ConfigureMotionTouch::OnConfigureTouchCalibration);
|
||||||
|
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, [this] {
|
||||||
|
if (CanCloseDialog())
|
||||||
|
reject();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureMotionTouch::OnCemuhookUDPTest() {
|
||||||
|
ui->udp_test->setEnabled(false);
|
||||||
|
ui->udp_test->setText(tr("Testing"));
|
||||||
|
udp_test_in_progress = true;
|
||||||
|
InputCommon::CemuhookUDP::TestCommunication(
|
||||||
|
ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()),
|
||||||
|
static_cast<u8>(ui->udp_pad_index->currentIndex()), 24872,
|
||||||
|
[this] {
|
||||||
|
LOG_INFO(Frontend, "UDP input test success");
|
||||||
|
QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true));
|
||||||
|
},
|
||||||
|
[this] {
|
||||||
|
LOG_ERROR(Frontend, "UDP input test failed");
|
||||||
|
QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureMotionTouch::OnConfigureTouchCalibration() {
|
||||||
|
ui->touch_calibration_config->setEnabled(false);
|
||||||
|
ui->touch_calibration_config->setText(tr("Configuring"));
|
||||||
|
CalibrationConfigurationDialog* dialog = new CalibrationConfigurationDialog(
|
||||||
|
this, ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toUInt()),
|
||||||
|
static_cast<u8>(ui->udp_pad_index->currentIndex()), 24872);
|
||||||
|
dialog->exec();
|
||||||
|
if (dialog->completed) {
|
||||||
|
min_x = dialog->min_x;
|
||||||
|
min_y = dialog->min_y;
|
||||||
|
max_x = dialog->max_x;
|
||||||
|
max_y = dialog->max_y;
|
||||||
|
LOG_INFO(Frontend,
|
||||||
|
"UDP touchpad calibration config success: min_x={}, min_y={}, max_x={}, max_y={}",
|
||||||
|
min_x, min_y, max_x, max_y);
|
||||||
|
updateUiDisplay();
|
||||||
|
} else {
|
||||||
|
LOG_ERROR(Frontend, "UDP touchpad calibration config failed");
|
||||||
|
}
|
||||||
|
ui->touch_calibration_config->setEnabled(true);
|
||||||
|
ui->touch_calibration_config->setText(tr("Configure"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureMotionTouch::closeEvent(QCloseEvent* event) {
|
||||||
|
if (CanCloseDialog())
|
||||||
|
event->accept();
|
||||||
|
else
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureMotionTouch::ShowUDPTestResult(bool result) {
|
||||||
|
udp_test_in_progress = false;
|
||||||
|
if (result) {
|
||||||
|
QMessageBox::information(this, tr("Test Successful"),
|
||||||
|
tr("Successfully received data from the server."));
|
||||||
|
} else {
|
||||||
|
QMessageBox::warning(this, tr("Test Failed"),
|
||||||
|
tr("Could not receive valid data from the server.<br>Please verify "
|
||||||
|
"that the server is set up correctly and "
|
||||||
|
"the address and port are correct."));
|
||||||
|
}
|
||||||
|
ui->udp_test->setEnabled(true);
|
||||||
|
ui->udp_test->setText(tr("Test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConfigureMotionTouch::CanCloseDialog() {
|
||||||
|
if (udp_test_in_progress) {
|
||||||
|
QMessageBox::warning(this, tr("Citra"),
|
||||||
|
tr("UDP Test or calibration configuration is in progress.<br>Please "
|
||||||
|
"wait for them to finish."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureMotionTouch::applyConfiguration() {
|
||||||
|
if (!CanCloseDialog())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string motion_engine = ui->motion_provider->currentData().toString().toStdString();
|
||||||
|
std::string touch_engine = ui->touch_provider->currentData().toString().toStdString();
|
||||||
|
|
||||||
|
Common::ParamPackage motion_param{}, touch_param{};
|
||||||
|
motion_param.Set("engine", motion_engine);
|
||||||
|
touch_param.Set("engine", touch_engine);
|
||||||
|
|
||||||
|
if (motion_engine == "motion_emu") {
|
||||||
|
motion_param.Set("sensitivity", static_cast<float>(ui->motion_sensitivity->value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (touch_engine == "cemuhookudp") {
|
||||||
|
touch_param.Set("min_x", min_x);
|
||||||
|
touch_param.Set("min_y", min_y);
|
||||||
|
touch_param.Set("max_x", max_x);
|
||||||
|
touch_param.Set("max_y", max_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::values.motion_device = motion_param.Serialize();
|
||||||
|
Settings::values.touch_device = touch_param.Serialize();
|
||||||
|
Settings::values.udp_input_address = ui->udp_server->text().toStdString();
|
||||||
|
Settings::values.udp_input_port = static_cast<u16>(ui->udp_port->text().toInt());
|
||||||
|
Settings::values.udp_pad_index = static_cast<u8>(ui->udp_pad_index->currentIndex());
|
||||||
|
InputCommon::ReloadInputDevices();
|
||||||
|
|
||||||
|
accept();
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
// Copyright 2018 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <QDialog>
|
||||||
|
#include "common/param_package.h"
|
||||||
|
#include "input_common/udp/udp.h"
|
||||||
|
|
||||||
|
class QVBoxLayout;
|
||||||
|
class QLabel;
|
||||||
|
class QPushButton;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ConfigureMotionTouch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A dialog for touchpad calibration configuration.
|
||||||
|
class CalibrationConfigurationDialog : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port,
|
||||||
|
u8 pad_index, u16 client_id);
|
||||||
|
~CalibrationConfigurationDialog();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q_INVOKABLE void UpdateLabelText(QString text);
|
||||||
|
Q_INVOKABLE void UpdateButtonText(QString text);
|
||||||
|
|
||||||
|
QVBoxLayout* layout;
|
||||||
|
QLabel* status_label;
|
||||||
|
QPushButton* cancel_button;
|
||||||
|
std::unique_ptr<InputCommon::CemuhookUDP::CalibrationConfigurationJob> job;
|
||||||
|
|
||||||
|
// Configuration results
|
||||||
|
bool completed{};
|
||||||
|
u16 min_x, min_y, max_x, max_y;
|
||||||
|
|
||||||
|
friend class ConfigureMotionTouch;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConfigureMotionTouch : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ConfigureMotionTouch(QWidget* parent = nullptr);
|
||||||
|
~ConfigureMotionTouch();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void applyConfiguration();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void OnCemuhookUDPTest();
|
||||||
|
void OnConfigureTouchCalibration();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void closeEvent(QCloseEvent* event) override;
|
||||||
|
Q_INVOKABLE void ShowUDPTestResult(bool result);
|
||||||
|
void setConfiguration();
|
||||||
|
void updateUiDisplay();
|
||||||
|
void connectEvents();
|
||||||
|
bool CanCloseDialog();
|
||||||
|
|
||||||
|
std::unique_ptr<Ui::ConfigureMotionTouch> ui;
|
||||||
|
|
||||||
|
// Coordinate system of the CemuhookUDP touch provider
|
||||||
|
int min_x, min_y, max_x, max_y;
|
||||||
|
|
||||||
|
bool udp_test_in_progress{};
|
||||||
|
};
|
|
@ -0,0 +1,294 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ConfigureMotionTouch</class>
|
||||||
|
<widget class="QDialog" name="ConfigureMotionTouch">
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Configure Motion / Touch</string>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>500</width>
|
||||||
|
<height>450</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="motion_group_box">
|
||||||
|
<property name="title">
|
||||||
|
<string>Motion</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="motion_provider_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Motion Provider:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="motion_provider"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="motion_sensitivity_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Sensitivity:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDoubleSpinBox" name="motion_sensitivity">
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>0.010000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>10.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.001000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>0.010000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="touch_group_box">
|
||||||
|
<property name="title">
|
||||||
|
<string>Touch</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="touch_provider_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Touch Provider:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="touch_provider"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="touch_calibration_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Calibration:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="touch_calibration">
|
||||||
|
<property name="text">
|
||||||
|
<string>(100, 50) - (1800, 850)</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="touch_calibration_config">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Configure</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="udp_config_group_box">
|
||||||
|
<property name="title">
|
||||||
|
<string>CemuhookUDP Config</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="udp_help">
|
||||||
|
<property name="text">
|
||||||
|
<string>You may use any Cemuhook compatible UDP input source to provide motion and touch input.</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="udp_server_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Server:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="udp_server">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="udp_port_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Port:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="udp_port">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="udp_pad_index_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Pad:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="udp_pad_index">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Pad 1</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Pad 2</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Pad 3</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Pad 4</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="udp_learn_more">
|
||||||
|
<property name="text">
|
||||||
|
<string>Learn More</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="udp_test">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Test</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer>
|
||||||
|
<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="buttonBox">
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<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>
|
|
@ -55,6 +55,15 @@ public:
|
||||||
is_set = false;
|
is_set = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Duration>
|
||||||
|
bool WaitFor(const std::chrono::duration<Duration>& time) {
|
||||||
|
std::unique_lock<std::mutex> lk(mutex);
|
||||||
|
if (!condvar.wait_for(lk, time, [this] { return is_set; }))
|
||||||
|
return false;
|
||||||
|
is_set = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template <class Clock, class Duration>
|
template <class Clock, class Duration>
|
||||||
bool WaitUntil(const std::chrono::time_point<Clock, Duration>& time) {
|
bool WaitUntil(const std::chrono::time_point<Clock, Duration>& time) {
|
||||||
std::unique_lock<std::mutex> lk(mutex);
|
std::unique_lock<std::mutex> lk(mutex);
|
||||||
|
|
|
@ -76,6 +76,11 @@ std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left,
|
||||||
return circle_pad_param.Serialize();
|
return circle_pad_param.Serialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ReloadInputDevices() {
|
||||||
|
if (udp)
|
||||||
|
udp->ReloadUDPClient();
|
||||||
|
}
|
||||||
|
|
||||||
namespace Polling {
|
namespace Polling {
|
||||||
|
|
||||||
std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type) {
|
std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type) {
|
||||||
|
|
|
@ -37,6 +37,9 @@ std::string GenerateKeyboardParam(int key_code);
|
||||||
std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
|
std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
|
||||||
int key_modifier, float modifier_scale);
|
int key_modifier, float modifier_scale);
|
||||||
|
|
||||||
|
/// Reloads the input devices
|
||||||
|
void ReloadInputDevices();
|
||||||
|
|
||||||
namespace Polling {
|
namespace Polling {
|
||||||
|
|
||||||
enum class DeviceType { Button, Analog };
|
enum class DeviceType { Button, Analog };
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/vector_math.h"
|
|
||||||
#include "input_common/udp/client.h"
|
#include "input_common/udp/client.h"
|
||||||
#include "input_common/udp/protocol.h"
|
#include "input_common/udp/protocol.h"
|
||||||
|
|
||||||
|
@ -128,12 +127,7 @@ static void SocketLoop(Socket* socket) {
|
||||||
Client::Client(std::shared_ptr<DeviceStatus> status, const std::string& host, u16 port,
|
Client::Client(std::shared_ptr<DeviceStatus> status, const std::string& host, u16 port,
|
||||||
u8 pad_index, u32 client_id)
|
u8 pad_index, u32 client_id)
|
||||||
: status(status) {
|
: status(status) {
|
||||||
SocketCallback callback{[this](Response::Version version) { OnVersion(version); },
|
StartCommunication(host, port, pad_index, client_id);
|
||||||
[this](Response::PortInfo info) { OnPortInfo(info); },
|
|
||||||
[this](Response::PadData data) { OnPadData(data); }};
|
|
||||||
LOG_INFO(Input, "Starting communication with UDP input server on {}:{}", host, port);
|
|
||||||
socket = std::make_unique<Socket>(host, port, pad_index, client_id, callback);
|
|
||||||
thread = std::thread{SocketLoop, this->socket.get()};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::~Client() {
|
Client::~Client() {
|
||||||
|
@ -141,6 +135,12 @@ Client::~Client() {
|
||||||
thread.join();
|
thread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::ReloadSocket(const std::string& host, u16 port, u8 pad_index, u32 client_id) {
|
||||||
|
socket->Stop();
|
||||||
|
thread.join();
|
||||||
|
StartCommunication(host, port, pad_index, client_id);
|
||||||
|
}
|
||||||
|
|
||||||
void Client::OnVersion(Response::Version data) {
|
void Client::OnVersion(Response::Version data) {
|
||||||
LOG_TRACE(Input, "Version packet received: {}", data.version);
|
LOG_TRACE(Input, "Version packet received: {}", data.version);
|
||||||
}
|
}
|
||||||
|
@ -192,4 +192,93 @@ void Client::OnPadData(Response::PadData data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::StartCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id) {
|
||||||
|
SocketCallback callback{[this](Response::Version version) { OnVersion(version); },
|
||||||
|
[this](Response::PortInfo info) { OnPortInfo(info); },
|
||||||
|
[this](Response::PadData data) { OnPadData(data); }};
|
||||||
|
LOG_INFO(Input, "Starting communication with UDP input server on {}:{}", host, port);
|
||||||
|
socket = std::make_unique<Socket>(host, port, pad_index, client_id, callback);
|
||||||
|
thread = std::thread{SocketLoop, this->socket.get()};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id,
|
||||||
|
std::function<void()> success_callback,
|
||||||
|
std::function<void()> failure_callback) {
|
||||||
|
std::thread([=] {
|
||||||
|
Common::Event success_event;
|
||||||
|
SocketCallback callback{[](Response::Version version) {}, [](Response::PortInfo info) {},
|
||||||
|
[&](Response::PadData data) { success_event.Set(); }};
|
||||||
|
Socket socket{host, port, pad_index, client_id, callback};
|
||||||
|
std::thread worker_thread{SocketLoop, &socket};
|
||||||
|
bool result = success_event.WaitFor(std::chrono::seconds(8));
|
||||||
|
socket.Stop();
|
||||||
|
worker_thread.join();
|
||||||
|
if (result)
|
||||||
|
success_callback();
|
||||||
|
else
|
||||||
|
failure_callback();
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
CalibrationConfigurationJob::CalibrationConfigurationJob(
|
||||||
|
const std::string& host, u16 port, u8 pad_index, u32 client_id,
|
||||||
|
std::function<void(Status)> status_callback,
|
||||||
|
std::function<void(u16, u16, u16, u16)> data_callback) {
|
||||||
|
|
||||||
|
std::thread([=] {
|
||||||
|
constexpr u16 CALIBRATION_THRESHOLD = 100;
|
||||||
|
|
||||||
|
u16 min_x{UINT16_MAX}, min_y{UINT16_MAX};
|
||||||
|
u16 max_x, max_y;
|
||||||
|
|
||||||
|
Status current_status{Status::Initialized};
|
||||||
|
SocketCallback callback{[](Response::Version version) {}, [](Response::PortInfo info) {},
|
||||||
|
[&](Response::PadData data) {
|
||||||
|
if (current_status == Status::Initialized) {
|
||||||
|
// Receiving data means the communication is ready now
|
||||||
|
current_status = Status::Ready;
|
||||||
|
status_callback(current_status);
|
||||||
|
}
|
||||||
|
if (!data.touch_1.is_active)
|
||||||
|
return;
|
||||||
|
LOG_DEBUG(Input, "Current touch: {} {}", data.touch_1.x,
|
||||||
|
data.touch_1.y);
|
||||||
|
min_x = std::min(min_x, static_cast<u16>(data.touch_1.x));
|
||||||
|
min_y = std::min(min_y, static_cast<u16>(data.touch_1.y));
|
||||||
|
if (current_status == Status::Ready) {
|
||||||
|
// First touch - min data (min_x/min_y)
|
||||||
|
current_status = Status::Stage1Completed;
|
||||||
|
status_callback(current_status);
|
||||||
|
}
|
||||||
|
if (data.touch_1.x - min_x > CALIBRATION_THRESHOLD &&
|
||||||
|
data.touch_1.y - min_y > CALIBRATION_THRESHOLD) {
|
||||||
|
// Set the current position as max value and finishes
|
||||||
|
// configuration
|
||||||
|
max_x = data.touch_1.x;
|
||||||
|
max_y = data.touch_1.y;
|
||||||
|
current_status = Status::Completed;
|
||||||
|
data_callback(min_x, min_y, max_x, max_y);
|
||||||
|
status_callback(current_status);
|
||||||
|
|
||||||
|
complete_event.Set();
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
Socket socket{host, port, pad_index, client_id, callback};
|
||||||
|
std::thread worker_thread{SocketLoop, &socket};
|
||||||
|
complete_event.Wait();
|
||||||
|
socket.Stop();
|
||||||
|
worker_thread.join();
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
CalibrationConfigurationJob::~CalibrationConfigurationJob() {
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CalibrationConfigurationJob::Stop() {
|
||||||
|
complete_event.Set();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace InputCommon::CemuhookUDP
|
} // namespace InputCommon::CemuhookUDP
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "common/thread.h"
|
||||||
#include "common/vector_math.h"
|
#include "common/vector_math.h"
|
||||||
|
|
||||||
namespace InputCommon::CemuhookUDP {
|
namespace InputCommon::CemuhookUDP {
|
||||||
|
@ -47,15 +48,48 @@ public:
|
||||||
explicit Client(std::shared_ptr<DeviceStatus> status, const std::string& host = DEFAULT_ADDR,
|
explicit Client(std::shared_ptr<DeviceStatus> status, const std::string& host = DEFAULT_ADDR,
|
||||||
u16 port = DEFAULT_PORT, u8 pad_index = 0, u32 client_id = 24872);
|
u16 port = DEFAULT_PORT, u8 pad_index = 0, u32 client_id = 24872);
|
||||||
~Client();
|
~Client();
|
||||||
|
void ReloadSocket(const std::string& host = "127.0.0.1", u16 port = 26760, u8 pad_index = 0,
|
||||||
|
u32 client_id = 24872);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnVersion(Response::Version);
|
void OnVersion(Response::Version);
|
||||||
void OnPortInfo(Response::PortInfo);
|
void OnPortInfo(Response::PortInfo);
|
||||||
void OnPadData(Response::PadData);
|
void OnPadData(Response::PadData);
|
||||||
|
void StartCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id);
|
||||||
|
|
||||||
std::unique_ptr<Socket> socket;
|
std::unique_ptr<Socket> socket;
|
||||||
std::shared_ptr<DeviceStatus> status;
|
std::shared_ptr<DeviceStatus> status;
|
||||||
std::thread thread;
|
std::thread thread;
|
||||||
u64 packet_sequence = 0;
|
u64 packet_sequence = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// An async job allowing configuration of the touchpad calibration.
|
||||||
|
class CalibrationConfigurationJob {
|
||||||
|
public:
|
||||||
|
enum class Status {
|
||||||
|
Initialized,
|
||||||
|
Ready,
|
||||||
|
Stage1Completed,
|
||||||
|
Completed,
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Constructs and starts the job with the specified parameter.
|
||||||
|
*
|
||||||
|
* @param status_callback Callback for job status updates
|
||||||
|
* @param data_callback Called when calibration data is ready
|
||||||
|
*/
|
||||||
|
explicit CalibrationConfigurationJob(const std::string& host, u16 port, u8 pad_index,
|
||||||
|
u32 client_id, std::function<void(Status)> status_callback,
|
||||||
|
std::function<void(u16, u16, u16, u16)> data_callback);
|
||||||
|
~CalibrationConfigurationJob();
|
||||||
|
void Stop();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Common::Event complete_event;
|
||||||
|
};
|
||||||
|
|
||||||
|
void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id,
|
||||||
|
std::function<void()> success_callback,
|
||||||
|
std::function<void()> failure_callback);
|
||||||
|
|
||||||
} // namespace InputCommon::CemuhookUDP
|
} // namespace InputCommon::CemuhookUDP
|
||||||
|
|
|
@ -85,6 +85,11 @@ State::~State() {
|
||||||
Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp");
|
Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void State::ReloadUDPClient() {
|
||||||
|
client->ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port,
|
||||||
|
Settings::values.udp_pad_index);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<State> Init() {
|
std::unique_ptr<State> Init() {
|
||||||
return std::make_unique<State>();
|
return std::make_unique<State>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ class State {
|
||||||
public:
|
public:
|
||||||
State();
|
State();
|
||||||
~State();
|
~State();
|
||||||
|
void ReloadUDPClient();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Client> client;
|
std::unique_ptr<Client> client;
|
||||||
|
|
Reference in New Issue