mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-07-04 23:31:19 +01:00
input_common: Fully implement UDP controllers
This commit is contained in:
parent
23bf2e3bb6
commit
639402850a
12 changed files with 397 additions and 40 deletions
|
@ -195,6 +195,20 @@ enum class ButtonNames {
|
||||||
ButtonX,
|
ButtonX,
|
||||||
ButtonY,
|
ButtonY,
|
||||||
ButtonStart,
|
ButtonStart,
|
||||||
|
|
||||||
|
// DS4 button names
|
||||||
|
L1,
|
||||||
|
L2,
|
||||||
|
L3,
|
||||||
|
R1,
|
||||||
|
R2,
|
||||||
|
R3,
|
||||||
|
Circle,
|
||||||
|
Cross,
|
||||||
|
Square,
|
||||||
|
Triangle,
|
||||||
|
Share,
|
||||||
|
Options,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Callback data consisting of an input type and the equivalent data status
|
// Callback data consisting of an input type and the equivalent data status
|
||||||
|
|
|
@ -560,6 +560,7 @@ struct Values {
|
||||||
|
|
||||||
Setting<bool> motion_enabled{true, "motion_enabled"};
|
Setting<bool> motion_enabled{true, "motion_enabled"};
|
||||||
BasicSetting<std::string> udp_input_servers{"127.0.0.1:26760", "udp_input_servers"};
|
BasicSetting<std::string> udp_input_servers{"127.0.0.1:26760", "udp_input_servers"};
|
||||||
|
BasicSetting<bool> enable_udp_controller{false, "enable_udp_controller"};
|
||||||
|
|
||||||
BasicSetting<bool> pause_tas_on_load{true, "pause_tas_on_load"};
|
BasicSetting<bool> pause_tas_on_load{true, "pause_tas_on_load"};
|
||||||
BasicSetting<bool> tas_enable{false, "tas_enable"};
|
BasicSetting<bool> tas_enable{false, "tas_enable"};
|
||||||
|
|
|
@ -30,8 +30,10 @@ void EmulatedConsole::SetTouchParams() {
|
||||||
}
|
}
|
||||||
touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0"};
|
touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0"};
|
||||||
touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1"};
|
touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1"};
|
||||||
touch_params[index++] = Common::ParamPackage{"engine:cemuhookudp,axis_x:0,axis_y:1,button:0"};
|
touch_params[index++] =
|
||||||
touch_params[index++] = Common::ParamPackage{"engine:cemuhookudp,axis_x:2,axis_y:3,button:1"};
|
Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536"};
|
||||||
|
touch_params[index++] =
|
||||||
|
Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072"};
|
||||||
|
|
||||||
const auto button_index =
|
const auto button_index =
|
||||||
static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue());
|
static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue());
|
||||||
|
|
|
@ -103,7 +103,7 @@ private:
|
||||||
|
|
||||||
// Send a request for getting pad data for the pad
|
// Send a request for getting pad data for the pad
|
||||||
const Request::PadData pad_data{
|
const Request::PadData pad_data{
|
||||||
Request::PadData::Flags::AllPorts,
|
Request::RegisterFlags::AllPads,
|
||||||
0,
|
0,
|
||||||
EMPTY_MAC_ADDRESS,
|
EMPTY_MAC_ADDRESS,
|
||||||
};
|
};
|
||||||
|
@ -247,7 +247,12 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) {
|
||||||
|
|
||||||
for (std::size_t id = 0; id < data.touch.size(); ++id) {
|
for (std::size_t id = 0; id < data.touch.size(); ++id) {
|
||||||
const auto touch_pad = data.touch[id];
|
const auto touch_pad = data.touch[id];
|
||||||
const int touch_id = static_cast<int>(client * 2 + id);
|
const auto touch_axis_x_id =
|
||||||
|
static_cast<int>(id == 0 ? PadAxes::Touch1X : PadAxes::Touch2X);
|
||||||
|
const auto touch_axis_y_id =
|
||||||
|
static_cast<int>(id == 0 ? PadAxes::Touch1Y : PadAxes::Touch2Y);
|
||||||
|
const auto touch_button_id =
|
||||||
|
static_cast<int>(id == 0 ? PadButton::Touch1 : PadButton::touch2);
|
||||||
|
|
||||||
// TODO: Use custom calibration per device
|
// TODO: Use custom calibration per device
|
||||||
const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue());
|
const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue());
|
||||||
|
@ -264,14 +269,35 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) {
|
||||||
static_cast<f32>(max_y - min_y);
|
static_cast<f32>(max_y - min_y);
|
||||||
|
|
||||||
if (touch_pad.is_active) {
|
if (touch_pad.is_active) {
|
||||||
SetAxis(identifier, touch_id * 2, x);
|
SetAxis(identifier, touch_axis_x_id, x);
|
||||||
SetAxis(identifier, touch_id * 2 + 1, y);
|
SetAxis(identifier, touch_axis_y_id, y);
|
||||||
SetButton(identifier, touch_id, true);
|
SetButton(identifier, touch_button_id, true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SetAxis(identifier, touch_id * 2, 0);
|
SetAxis(identifier, touch_axis_x_id, 0);
|
||||||
SetAxis(identifier, touch_id * 2 + 1, 0);
|
SetAxis(identifier, touch_axis_y_id, 0);
|
||||||
SetButton(identifier, touch_id, false);
|
SetButton(identifier, touch_button_id, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetAxis(identifier, static_cast<int>(PadAxes::LeftStickX),
|
||||||
|
(data.left_stick_x - 127.0f) / 127.0f);
|
||||||
|
SetAxis(identifier, static_cast<int>(PadAxes::LeftStickY),
|
||||||
|
(data.left_stick_y - 127.0f) / 127.0f);
|
||||||
|
SetAxis(identifier, static_cast<int>(PadAxes::RightStickX),
|
||||||
|
(data.right_stick_x - 127.0f) / 127.0f);
|
||||||
|
SetAxis(identifier, static_cast<int>(PadAxes::RightStickY),
|
||||||
|
(data.right_stick_y - 127.0f) / 127.0f);
|
||||||
|
|
||||||
|
static constexpr std::array<PadButton, 16> buttons{
|
||||||
|
PadButton::Share, PadButton::L3, PadButton::R3, PadButton::Options,
|
||||||
|
PadButton::Up, PadButton::Right, PadButton::Down, PadButton::Left,
|
||||||
|
PadButton::L2, PadButton::R2, PadButton::L1, PadButton::R1,
|
||||||
|
PadButton::Triangle, PadButton::Circle, PadButton::Cross, PadButton::Square};
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < buttons.size(); ++i) {
|
||||||
|
const bool button_status = (data.digital_button & (1U << i)) != 0;
|
||||||
|
const int button = static_cast<int>(buttons[i]);
|
||||||
|
SetButton(identifier, button, button_status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,6 +343,170 @@ void UDPClient::Reset() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Common::ParamPackage> UDPClient::GetInputDevices() const {
|
||||||
|
std::vector<Common::ParamPackage> devices;
|
||||||
|
if (!Settings::values.enable_udp_controller) {
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
for (std::size_t client = 0; client < clients.size(); client++) {
|
||||||
|
if (clients[client].active != 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (std::size_t index = 0; index < PADS_PER_CLIENT; ++index) {
|
||||||
|
const std::size_t pad_index = client * PADS_PER_CLIENT + index;
|
||||||
|
if (!pads[pad_index].connected) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto pad_identifier = GetPadIdentifier(pad_index);
|
||||||
|
Common::ParamPackage identifier{};
|
||||||
|
identifier.Set("engine", GetEngineName());
|
||||||
|
identifier.Set("display", fmt::format("UDP Controller {}", pad_identifier.pad));
|
||||||
|
identifier.Set("guid", pad_identifier.guid.Format());
|
||||||
|
identifier.Set("port", static_cast<int>(pad_identifier.port));
|
||||||
|
identifier.Set("pad", static_cast<int>(pad_identifier.pad));
|
||||||
|
devices.emplace_back(identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonMapping UDPClient::GetButtonMappingForDevice(const Common::ParamPackage& params) {
|
||||||
|
// This list excludes any button that can't be really mapped
|
||||||
|
static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 18>
|
||||||
|
switch_to_dsu_button = {
|
||||||
|
std::pair{Settings::NativeButton::A, PadButton::Circle},
|
||||||
|
{Settings::NativeButton::B, PadButton::Cross},
|
||||||
|
{Settings::NativeButton::X, PadButton::Triangle},
|
||||||
|
{Settings::NativeButton::Y, PadButton::Square},
|
||||||
|
{Settings::NativeButton::Plus, PadButton::Options},
|
||||||
|
{Settings::NativeButton::Minus, PadButton::Share},
|
||||||
|
{Settings::NativeButton::DLeft, PadButton::Left},
|
||||||
|
{Settings::NativeButton::DUp, PadButton::Up},
|
||||||
|
{Settings::NativeButton::DRight, PadButton::Right},
|
||||||
|
{Settings::NativeButton::DDown, PadButton::Down},
|
||||||
|
{Settings::NativeButton::L, PadButton::L1},
|
||||||
|
{Settings::NativeButton::R, PadButton::R1},
|
||||||
|
{Settings::NativeButton::ZL, PadButton::L2},
|
||||||
|
{Settings::NativeButton::ZR, PadButton::R2},
|
||||||
|
{Settings::NativeButton::SL, PadButton::L2},
|
||||||
|
{Settings::NativeButton::SR, PadButton::R2},
|
||||||
|
{Settings::NativeButton::LStick, PadButton::L3},
|
||||||
|
{Settings::NativeButton::RStick, PadButton::R3},
|
||||||
|
};
|
||||||
|
if (!params.Has("guid") || !params.Has("port") || !params.Has("pad")) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonMapping mapping{};
|
||||||
|
for (const auto& [switch_button, dsu_button] : switch_to_dsu_button) {
|
||||||
|
Common::ParamPackage button_params{};
|
||||||
|
button_params.Set("engine", GetEngineName());
|
||||||
|
button_params.Set("guid", params.Get("guid", ""));
|
||||||
|
button_params.Set("port", params.Get("port", 0));
|
||||||
|
button_params.Set("pad", params.Get("pad", 0));
|
||||||
|
button_params.Set("button", static_cast<int>(dsu_button));
|
||||||
|
mapping.insert_or_assign(switch_button, std::move(button_params));
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalogMapping UDPClient::GetAnalogMappingForDevice(const Common::ParamPackage& params) {
|
||||||
|
if (!params.Has("guid") || !params.Has("port") || !params.Has("pad")) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalogMapping mapping = {};
|
||||||
|
Common::ParamPackage left_analog_params;
|
||||||
|
left_analog_params.Set("engine", GetEngineName());
|
||||||
|
left_analog_params.Set("guid", params.Get("guid", ""));
|
||||||
|
left_analog_params.Set("port", params.Get("port", 0));
|
||||||
|
left_analog_params.Set("pad", params.Get("pad", 0));
|
||||||
|
left_analog_params.Set("axis_x", static_cast<int>(PadAxes::LeftStickX));
|
||||||
|
left_analog_params.Set("axis_y", static_cast<int>(PadAxes::LeftStickY));
|
||||||
|
mapping.insert_or_assign(Settings::NativeAnalog::LStick, std::move(left_analog_params));
|
||||||
|
Common::ParamPackage right_analog_params;
|
||||||
|
right_analog_params.Set("engine", GetEngineName());
|
||||||
|
right_analog_params.Set("guid", params.Get("guid", ""));
|
||||||
|
right_analog_params.Set("port", params.Get("port", 0));
|
||||||
|
right_analog_params.Set("pad", params.Get("pad", 0));
|
||||||
|
right_analog_params.Set("axis_x", static_cast<int>(PadAxes::RightStickX));
|
||||||
|
right_analog_params.Set("axis_y", static_cast<int>(PadAxes::RightStickY));
|
||||||
|
mapping.insert_or_assign(Settings::NativeAnalog::RStick, std::move(right_analog_params));
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
MotionMapping UDPClient::GetMotionMappingForDevice(const Common::ParamPackage& params) {
|
||||||
|
if (!params.Has("guid") || !params.Has("port") || !params.Has("pad")) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
MotionMapping mapping = {};
|
||||||
|
Common::ParamPackage motion_params;
|
||||||
|
motion_params.Set("engine", GetEngineName());
|
||||||
|
motion_params.Set("guid", params.Get("guid", ""));
|
||||||
|
motion_params.Set("port", params.Get("port", 0));
|
||||||
|
motion_params.Set("pad", params.Get("pad", 0));
|
||||||
|
motion_params.Set("motion", 0);
|
||||||
|
mapping.insert_or_assign(Settings::NativeMotion::MotionLeft, std::move(motion_params));
|
||||||
|
mapping.insert_or_assign(Settings::NativeMotion::MotionRight, std::move(motion_params));
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::Input::ButtonNames UDPClient::GetUIButtonName(const Common::ParamPackage& params) const {
|
||||||
|
PadButton button = static_cast<PadButton>(params.Get("button", 0));
|
||||||
|
switch (button) {
|
||||||
|
case PadButton::Left:
|
||||||
|
return Common::Input::ButtonNames::ButtonLeft;
|
||||||
|
case PadButton::Right:
|
||||||
|
return Common::Input::ButtonNames::ButtonRight;
|
||||||
|
case PadButton::Down:
|
||||||
|
return Common::Input::ButtonNames::ButtonDown;
|
||||||
|
case PadButton::Up:
|
||||||
|
return Common::Input::ButtonNames::ButtonUp;
|
||||||
|
case PadButton::L1:
|
||||||
|
return Common::Input::ButtonNames::L1;
|
||||||
|
case PadButton::L2:
|
||||||
|
return Common::Input::ButtonNames::L2;
|
||||||
|
case PadButton::L3:
|
||||||
|
return Common::Input::ButtonNames::L3;
|
||||||
|
case PadButton::R1:
|
||||||
|
return Common::Input::ButtonNames::R1;
|
||||||
|
case PadButton::R2:
|
||||||
|
return Common::Input::ButtonNames::R2;
|
||||||
|
case PadButton::R3:
|
||||||
|
return Common::Input::ButtonNames::R3;
|
||||||
|
case PadButton::Circle:
|
||||||
|
return Common::Input::ButtonNames::Circle;
|
||||||
|
case PadButton::Cross:
|
||||||
|
return Common::Input::ButtonNames::Cross;
|
||||||
|
case PadButton::Square:
|
||||||
|
return Common::Input::ButtonNames::Square;
|
||||||
|
case PadButton::Triangle:
|
||||||
|
return Common::Input::ButtonNames::Triangle;
|
||||||
|
case PadButton::Share:
|
||||||
|
return Common::Input::ButtonNames::Share;
|
||||||
|
case PadButton::Options:
|
||||||
|
return Common::Input::ButtonNames::Options;
|
||||||
|
default:
|
||||||
|
return Common::Input::ButtonNames::Undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::Input::ButtonNames UDPClient::GetUIName(const Common::ParamPackage& params) const {
|
||||||
|
if (params.Has("button")) {
|
||||||
|
return GetUIButtonName(params);
|
||||||
|
}
|
||||||
|
if (params.Has("axis")) {
|
||||||
|
return Common::Input::ButtonNames::Value;
|
||||||
|
}
|
||||||
|
if (params.Has("motion")) {
|
||||||
|
return Common::Input::ButtonNames::Engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Common::Input::ButtonNames::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
void TestCommunication(const std::string& host, u16 port,
|
void TestCommunication(const std::string& host, u16 port,
|
||||||
const std::function<void()>& success_callback,
|
const std::function<void()>& success_callback,
|
||||||
const std::function<void()>& failure_callback) {
|
const std::function<void()>& failure_callback) {
|
||||||
|
|
|
@ -56,7 +56,61 @@ public:
|
||||||
|
|
||||||
void ReloadSockets();
|
void ReloadSockets();
|
||||||
|
|
||||||
|
/// Used for automapping features
|
||||||
|
std::vector<Common::ParamPackage> GetInputDevices() const override;
|
||||||
|
ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override;
|
||||||
|
AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override;
|
||||||
|
MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& params) override;
|
||||||
|
Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum class PadButton {
|
||||||
|
Undefined = 0x0000,
|
||||||
|
Share = 0x0001,
|
||||||
|
L3 = 0x0002,
|
||||||
|
R3 = 0x0004,
|
||||||
|
Options = 0x0008,
|
||||||
|
Up = 0x0010,
|
||||||
|
Right = 0x0020,
|
||||||
|
Down = 0x0040,
|
||||||
|
Left = 0x0080,
|
||||||
|
L2 = 0x0100,
|
||||||
|
R2 = 0x0200,
|
||||||
|
L1 = 0x0400,
|
||||||
|
R1 = 0x0800,
|
||||||
|
Triangle = 0x1000,
|
||||||
|
Circle = 0x2000,
|
||||||
|
Cross = 0x4000,
|
||||||
|
Square = 0x8000,
|
||||||
|
Touch1 = 0x10000,
|
||||||
|
touch2 = 0x20000,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class PadAxes : u8 {
|
||||||
|
LeftStickX,
|
||||||
|
LeftStickY,
|
||||||
|
RightStickX,
|
||||||
|
RightStickY,
|
||||||
|
AnalogLeft,
|
||||||
|
AnalogDown,
|
||||||
|
AnalogRight,
|
||||||
|
AnalogUp,
|
||||||
|
AnalogSquare,
|
||||||
|
AnalogCross,
|
||||||
|
AnalogCircle,
|
||||||
|
AnalogTriangle,
|
||||||
|
AnalogR1,
|
||||||
|
AnalogL1,
|
||||||
|
AnalogR2,
|
||||||
|
AnalogL3,
|
||||||
|
AnalogR3,
|
||||||
|
Touch1X,
|
||||||
|
Touch1Y,
|
||||||
|
Touch2X,
|
||||||
|
Touch2Y,
|
||||||
|
Undefined,
|
||||||
|
};
|
||||||
|
|
||||||
struct PadData {
|
struct PadData {
|
||||||
std::size_t pad_index{};
|
std::size_t pad_index{};
|
||||||
bool connected{};
|
bool connected{};
|
||||||
|
@ -90,6 +144,8 @@ private:
|
||||||
const PadIdentifier GetPadIdentifier(std::size_t pad_index) const;
|
const PadIdentifier GetPadIdentifier(std::size_t pad_index) const;
|
||||||
const Common::UUID GetHostUUID(const std::string host) const;
|
const Common::UUID GetHostUUID(const std::string host) const;
|
||||||
|
|
||||||
|
Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const;
|
||||||
|
|
||||||
// Allocate clients for 8 udp servers
|
// Allocate clients for 8 udp servers
|
||||||
static constexpr std::size_t MAX_UDP_CLIENTS = 8;
|
static constexpr std::size_t MAX_UDP_CLIENTS = 8;
|
||||||
static constexpr std::size_t PADS_PER_CLIENT = 4;
|
static constexpr std::size_t PADS_PER_CLIENT = 4;
|
||||||
|
|
|
@ -56,6 +56,12 @@ constexpr Type GetMessageType();
|
||||||
|
|
||||||
namespace Request {
|
namespace Request {
|
||||||
|
|
||||||
|
enum RegisterFlags : u8 {
|
||||||
|
AllPads,
|
||||||
|
PadID,
|
||||||
|
PadMACAdddress,
|
||||||
|
};
|
||||||
|
|
||||||
struct Version {};
|
struct Version {};
|
||||||
/**
|
/**
|
||||||
* Requests the server to send information about what controllers are plugged into the ports
|
* Requests the server to send information about what controllers are plugged into the ports
|
||||||
|
@ -77,13 +83,8 @@ static_assert(std::is_trivially_copyable_v<PortInfo>,
|
||||||
* timeout seems to be 5 seconds.
|
* timeout seems to be 5 seconds.
|
||||||
*/
|
*/
|
||||||
struct PadData {
|
struct PadData {
|
||||||
enum class Flags : u8 {
|
|
||||||
AllPorts,
|
|
||||||
Id,
|
|
||||||
Mac,
|
|
||||||
};
|
|
||||||
/// Determines which method will be used as a look up for the controller
|
/// Determines which method will be used as a look up for the controller
|
||||||
Flags flags{};
|
RegisterFlags flags{};
|
||||||
/// Index of the port of the controller to retrieve data about
|
/// Index of the port of the controller to retrieve data about
|
||||||
u8 port_id{};
|
u8 port_id{};
|
||||||
/// Mac address of the controller to retrieve data about
|
/// Mac address of the controller to retrieve data about
|
||||||
|
@ -113,6 +114,36 @@ Message<T> Create(const T data, const u32 client_id = 0) {
|
||||||
|
|
||||||
namespace Response {
|
namespace Response {
|
||||||
|
|
||||||
|
enum class ConnectionType : u8 {
|
||||||
|
None,
|
||||||
|
Usb,
|
||||||
|
Bluetooth,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class State : u8 {
|
||||||
|
Disconnected,
|
||||||
|
Reserved,
|
||||||
|
Connected,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Model : u8 {
|
||||||
|
None,
|
||||||
|
PartialGyro,
|
||||||
|
FullGyro,
|
||||||
|
Generic,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Battery : u8 {
|
||||||
|
None = 0x00,
|
||||||
|
Dying = 0x01,
|
||||||
|
Low = 0x02,
|
||||||
|
Medium = 0x03,
|
||||||
|
High = 0x04,
|
||||||
|
Full = 0x05,
|
||||||
|
Charging = 0xEE,
|
||||||
|
Charged = 0xEF,
|
||||||
|
};
|
||||||
|
|
||||||
struct Version {
|
struct Version {
|
||||||
u16_le version{};
|
u16_le version{};
|
||||||
};
|
};
|
||||||
|
@ -122,11 +153,11 @@ static_assert(std::is_trivially_copyable_v<Version>,
|
||||||
|
|
||||||
struct PortInfo {
|
struct PortInfo {
|
||||||
u8 id{};
|
u8 id{};
|
||||||
u8 state{};
|
State state{};
|
||||||
u8 model{};
|
Model model{};
|
||||||
u8 connection_type{};
|
ConnectionType connection_type{};
|
||||||
MacAddress mac;
|
MacAddress mac;
|
||||||
u8 battery{};
|
Battery battery{};
|
||||||
u8 is_pad_active{};
|
u8 is_pad_active{};
|
||||||
};
|
};
|
||||||
static_assert(sizeof(PortInfo) == 12, "UDP Response PortInfo struct has wrong size");
|
static_assert(sizeof(PortInfo) == 12, "UDP Response PortInfo struct has wrong size");
|
||||||
|
@ -177,18 +208,18 @@ struct PadData {
|
||||||
u8 right_stick_y{};
|
u8 right_stick_y{};
|
||||||
|
|
||||||
struct AnalogButton {
|
struct AnalogButton {
|
||||||
u8 button_8{};
|
u8 button_dpad_left_analog{};
|
||||||
u8 button_7{};
|
u8 button_dpad_down_analog{};
|
||||||
u8 button_6{};
|
u8 button_dpad_right_analog{};
|
||||||
u8 button_5{};
|
u8 button_dpad_up_analog{};
|
||||||
u8 button_12{};
|
u8 button_square_analog{};
|
||||||
u8 button_11{};
|
u8 button_cross_analog{};
|
||||||
u8 button_10{};
|
u8 button_circle_analog{};
|
||||||
u8 button_9{};
|
u8 button_triangle_analog{};
|
||||||
u8 button_16{};
|
u8 button_r1_analog{};
|
||||||
u8 button_15{};
|
u8 button_l1_analog{};
|
||||||
u8 button_14{};
|
u8 trigger_r2{};
|
||||||
u8 button_13{};
|
u8 trigger_l2{};
|
||||||
} analog_button;
|
} analog_button;
|
||||||
|
|
||||||
std::array<TouchPad, 2> touch;
|
std::array<TouchPad, 2> touch;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// Refer to the license.txt file included
|
// Refer to the license.txt file included
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "common/settings.h"
|
||||||
#include "input_common/input_engine.h"
|
#include "input_common/input_engine.h"
|
||||||
#include "input_common/input_mapping.h"
|
#include "input_common/input_mapping.h"
|
||||||
|
|
||||||
|
@ -182,6 +183,11 @@ bool MappingFactory::IsDriverValid(const MappingData& data) const {
|
||||||
if (data.engine == "keyboard" && data.pad.port != 0) {
|
if (data.engine == "keyboard" && data.pad.port != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// To prevent mapping with two devices we disable any UDP except motion
|
||||||
|
if (!Settings::values.enable_udp_controller && data.engine == "cemuhookudp" &&
|
||||||
|
data.type != EngineInputType::Motion) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// The following drivers don't need to be mapped
|
// The following drivers don't need to be mapped
|
||||||
if (data.engine == "tas") {
|
if (data.engine == "tas") {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -63,9 +63,12 @@ struct InputSubsystem::Impl {
|
||||||
|
|
||||||
udp_client = std::make_shared<CemuhookUDP::UDPClient>("cemuhookudp");
|
udp_client = std::make_shared<CemuhookUDP::UDPClient>("cemuhookudp");
|
||||||
udp_client->SetMappingCallback(mapping_callback);
|
udp_client->SetMappingCallback(mapping_callback);
|
||||||
udp_client_factory = std::make_shared<InputFactory>(udp_client);
|
udp_client_input_factory = std::make_shared<InputFactory>(udp_client);
|
||||||
|
udp_client_output_factory = std::make_shared<OutputFactory>(udp_client);
|
||||||
Common::Input::RegisterFactory<Common::Input::InputDevice>(udp_client->GetEngineName(),
|
Common::Input::RegisterFactory<Common::Input::InputDevice>(udp_client->GetEngineName(),
|
||||||
udp_client_factory);
|
udp_client_input_factory);
|
||||||
|
Common::Input::RegisterFactory<Common::Input::OutputDevice>(udp_client->GetEngineName(),
|
||||||
|
udp_client_output_factory);
|
||||||
|
|
||||||
tas_input = std::make_shared<TasInput::Tas>("tas");
|
tas_input = std::make_shared<TasInput::Tas>("tas");
|
||||||
tas_input->SetMappingCallback(mapping_callback);
|
tas_input->SetMappingCallback(mapping_callback);
|
||||||
|
@ -110,6 +113,7 @@ struct InputSubsystem::Impl {
|
||||||
gcadapter.reset();
|
gcadapter.reset();
|
||||||
|
|
||||||
Common::Input::UnregisterFactory<Common::Input::InputDevice>(udp_client->GetEngineName());
|
Common::Input::UnregisterFactory<Common::Input::InputDevice>(udp_client->GetEngineName());
|
||||||
|
Common::Input::UnregisterFactory<Common::Input::OutputDevice>(udp_client->GetEngineName());
|
||||||
udp_client.reset();
|
udp_client.reset();
|
||||||
|
|
||||||
Common::Input::UnregisterFactory<Common::Input::InputDevice>(tas_input->GetEngineName());
|
Common::Input::UnregisterFactory<Common::Input::InputDevice>(tas_input->GetEngineName());
|
||||||
|
@ -137,6 +141,8 @@ struct InputSubsystem::Impl {
|
||||||
devices.insert(devices.end(), mouse_devices.begin(), mouse_devices.end());
|
devices.insert(devices.end(), mouse_devices.begin(), mouse_devices.end());
|
||||||
auto gcadapter_devices = gcadapter->GetInputDevices();
|
auto gcadapter_devices = gcadapter->GetInputDevices();
|
||||||
devices.insert(devices.end(), gcadapter_devices.begin(), gcadapter_devices.end());
|
devices.insert(devices.end(), gcadapter_devices.begin(), gcadapter_devices.end());
|
||||||
|
auto udp_devices = udp_client->GetInputDevices();
|
||||||
|
devices.insert(devices.end(), udp_devices.begin(), udp_devices.end());
|
||||||
#ifdef HAVE_SDL2
|
#ifdef HAVE_SDL2
|
||||||
auto sdl_devices = sdl->GetInputDevices();
|
auto sdl_devices = sdl->GetInputDevices();
|
||||||
devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end());
|
devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end());
|
||||||
|
@ -157,6 +163,9 @@ struct InputSubsystem::Impl {
|
||||||
if (engine == gcadapter->GetEngineName()) {
|
if (engine == gcadapter->GetEngineName()) {
|
||||||
return gcadapter->GetAnalogMappingForDevice(params);
|
return gcadapter->GetAnalogMappingForDevice(params);
|
||||||
}
|
}
|
||||||
|
if (engine == udp_client->GetEngineName()) {
|
||||||
|
return udp_client->GetAnalogMappingForDevice(params);
|
||||||
|
}
|
||||||
if (engine == tas_input->GetEngineName()) {
|
if (engine == tas_input->GetEngineName()) {
|
||||||
return tas_input->GetAnalogMappingForDevice(params);
|
return tas_input->GetAnalogMappingForDevice(params);
|
||||||
}
|
}
|
||||||
|
@ -177,6 +186,9 @@ struct InputSubsystem::Impl {
|
||||||
if (engine == gcadapter->GetEngineName()) {
|
if (engine == gcadapter->GetEngineName()) {
|
||||||
return gcadapter->GetButtonMappingForDevice(params);
|
return gcadapter->GetButtonMappingForDevice(params);
|
||||||
}
|
}
|
||||||
|
if (engine == udp_client->GetEngineName()) {
|
||||||
|
return udp_client->GetButtonMappingForDevice(params);
|
||||||
|
}
|
||||||
if (engine == tas_input->GetEngineName()) {
|
if (engine == tas_input->GetEngineName()) {
|
||||||
return tas_input->GetButtonMappingForDevice(params);
|
return tas_input->GetButtonMappingForDevice(params);
|
||||||
}
|
}
|
||||||
|
@ -194,8 +206,8 @@ struct InputSubsystem::Impl {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const std::string engine = params.Get("engine", "");
|
const std::string engine = params.Get("engine", "");
|
||||||
if (engine == gcadapter->GetEngineName()) {
|
if (engine == udp_client->GetEngineName()) {
|
||||||
return gcadapter->GetMotionMappingForDevice(params);
|
return udp_client->GetMotionMappingForDevice(params);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_SDL2
|
#ifdef HAVE_SDL2
|
||||||
if (engine == sdl->GetEngineName()) {
|
if (engine == sdl->GetEngineName()) {
|
||||||
|
@ -238,6 +250,9 @@ struct InputSubsystem::Impl {
|
||||||
if (engine == gcadapter->GetEngineName()) {
|
if (engine == gcadapter->GetEngineName()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (engine == udp_client->GetEngineName()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (engine == tas_input->GetEngineName()) {
|
if (engine == tas_input->GetEngineName()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -286,12 +301,13 @@ struct InputSubsystem::Impl {
|
||||||
std::shared_ptr<InputFactory> mouse_factory;
|
std::shared_ptr<InputFactory> mouse_factory;
|
||||||
std::shared_ptr<InputFactory> gcadapter_input_factory;
|
std::shared_ptr<InputFactory> gcadapter_input_factory;
|
||||||
std::shared_ptr<InputFactory> touch_screen_factory;
|
std::shared_ptr<InputFactory> touch_screen_factory;
|
||||||
std::shared_ptr<InputFactory> udp_client_factory;
|
std::shared_ptr<InputFactory> udp_client_input_factory;
|
||||||
std::shared_ptr<InputFactory> tas_input_factory;
|
std::shared_ptr<InputFactory> tas_input_factory;
|
||||||
|
|
||||||
std::shared_ptr<OutputFactory> keyboard_output_factory;
|
std::shared_ptr<OutputFactory> keyboard_output_factory;
|
||||||
std::shared_ptr<OutputFactory> mouse_output_factory;
|
std::shared_ptr<OutputFactory> mouse_output_factory;
|
||||||
std::shared_ptr<OutputFactory> gcadapter_output_factory;
|
std::shared_ptr<OutputFactory> gcadapter_output_factory;
|
||||||
|
std::shared_ptr<OutputFactory> udp_client_output_factory;
|
||||||
std::shared_ptr<OutputFactory> tas_output_factory;
|
std::shared_ptr<OutputFactory> tas_output_factory;
|
||||||
|
|
||||||
#ifdef HAVE_SDL2
|
#ifdef HAVE_SDL2
|
||||||
|
|
|
@ -447,6 +447,7 @@ void Config::ReadMotionTouchValues() {
|
||||||
Settings::values.touch_from_button_map_index = std::clamp(
|
Settings::values.touch_from_button_map_index = std::clamp(
|
||||||
Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
|
Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1);
|
||||||
ReadBasicSetting(Settings::values.udp_input_servers);
|
ReadBasicSetting(Settings::values.udp_input_servers);
|
||||||
|
ReadBasicSetting(Settings::values.enable_udp_controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::ReadCoreValues() {
|
void Config::ReadCoreValues() {
|
||||||
|
@ -942,6 +943,7 @@ void Config::SaveMotionTouchValues() {
|
||||||
WriteBasicSetting(Settings::values.touch_device);
|
WriteBasicSetting(Settings::values.touch_device);
|
||||||
WriteBasicSetting(Settings::values.touch_from_button_map_index);
|
WriteBasicSetting(Settings::values.touch_from_button_map_index);
|
||||||
WriteBasicSetting(Settings::values.udp_input_servers);
|
WriteBasicSetting(Settings::values.udp_input_servers);
|
||||||
|
WriteBasicSetting(Settings::values.enable_udp_controller);
|
||||||
|
|
||||||
qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps"));
|
qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps"));
|
||||||
for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) {
|
for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) {
|
||||||
|
|
|
@ -130,6 +130,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() {
|
||||||
static_cast<float>(ui->mouse_panning_sensitivity->value());
|
static_cast<float>(ui->mouse_panning_sensitivity->value());
|
||||||
Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked();
|
Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked();
|
||||||
Settings::values.enable_raw_input = ui->enable_raw_input->isChecked();
|
Settings::values.enable_raw_input = ui->enable_raw_input->isChecked();
|
||||||
|
Settings::values.enable_udp_controller = ui->enable_udp_controller->isChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureInputAdvanced::LoadConfiguration() {
|
void ConfigureInputAdvanced::LoadConfiguration() {
|
||||||
|
@ -160,6 +161,7 @@ void ConfigureInputAdvanced::LoadConfiguration() {
|
||||||
ui->mouse_panning_sensitivity->setValue(Settings::values.mouse_panning_sensitivity.GetValue());
|
ui->mouse_panning_sensitivity->setValue(Settings::values.mouse_panning_sensitivity.GetValue());
|
||||||
ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled);
|
ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled);
|
||||||
ui->enable_raw_input->setChecked(Settings::values.enable_raw_input.GetValue());
|
ui->enable_raw_input->setChecked(Settings::values.enable_raw_input.GetValue());
|
||||||
|
ui->enable_udp_controller->setChecked(Settings::values.enable_udp_controller.GetValue());
|
||||||
|
|
||||||
UpdateUIEnabled();
|
UpdateUIEnabled();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2642,6 +2642,19 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="enable_udp_controller">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>23</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Enable UDP controllers (not needed for motion)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
<widget class="QCheckBox" name="mouse_panning">
|
<widget class="QCheckBox" name="mouse_panning">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
|
@ -2654,7 +2667,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="2">
|
<item row="4" column="2">
|
||||||
<widget class="QSpinBox" name="mouse_panning_sensitivity">
|
<widget class="QSpinBox" name="mouse_panning_sensitivity">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Mouse sensitivity</string>
|
<string>Mouse sensitivity</string>
|
||||||
|
@ -2676,14 +2689,14 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="5" column="0">
|
||||||
<widget class="QLabel" name="motion_touch">
|
<widget class="QLabel" name="motion_touch">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Motion / Touch</string>
|
<string>Motion / Touch</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="2">
|
<item row="5" column="2">
|
||||||
<widget class="QPushButton" name="buttonMotionTouch">
|
<widget class="QPushButton" name="buttonMotionTouch">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Configure</string>
|
<string>Configure</string>
|
||||||
|
|
|
@ -78,6 +78,30 @@ QString GetButtonName(Common::Input::ButtonNames button_name) {
|
||||||
return QObject::tr("Y");
|
return QObject::tr("Y");
|
||||||
case Common::Input::ButtonNames::ButtonStart:
|
case Common::Input::ButtonNames::ButtonStart:
|
||||||
return QObject::tr("Start");
|
return QObject::tr("Start");
|
||||||
|
case Common::Input::ButtonNames::L1:
|
||||||
|
return QObject::tr("L1");
|
||||||
|
case Common::Input::ButtonNames::L2:
|
||||||
|
return QObject::tr("L2");
|
||||||
|
case Common::Input::ButtonNames::L3:
|
||||||
|
return QObject::tr("L3");
|
||||||
|
case Common::Input::ButtonNames::R1:
|
||||||
|
return QObject::tr("R1");
|
||||||
|
case Common::Input::ButtonNames::R2:
|
||||||
|
return QObject::tr("R2");
|
||||||
|
case Common::Input::ButtonNames::R3:
|
||||||
|
return QObject::tr("R3");
|
||||||
|
case Common::Input::ButtonNames::Circle:
|
||||||
|
return QObject::tr("Circle");
|
||||||
|
case Common::Input::ButtonNames::Cross:
|
||||||
|
return QObject::tr("Cross");
|
||||||
|
case Common::Input::ButtonNames::Square:
|
||||||
|
return QObject::tr("Square");
|
||||||
|
case Common::Input::ButtonNames::Triangle:
|
||||||
|
return QObject::tr("Triangle");
|
||||||
|
case Common::Input::ButtonNames::Share:
|
||||||
|
return QObject::tr("Share");
|
||||||
|
case Common::Input::ButtonNames::Options:
|
||||||
|
return QObject::tr("Options");
|
||||||
default:
|
default:
|
||||||
return QObject::tr("[undefined]");
|
return QObject::tr("[undefined]");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue