From 639402850ac65c694967ef6519becb65abe89b39 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Fri, 26 Nov 2021 15:45:37 -0600 Subject: input_common: Fully implement UDP controllers --- src/input_common/drivers/udp_client.cpp | 206 ++++++++++++++++++++++++++++++-- src/input_common/drivers/udp_client.h | 56 +++++++++ 2 files changed, 254 insertions(+), 8 deletions(-) (limited to 'src/input_common/drivers') diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp index 7cab707da..fdee0f2d5 100644 --- a/src/input_common/drivers/udp_client.cpp +++ b/src/input_common/drivers/udp_client.cpp @@ -103,7 +103,7 @@ private: // Send a request for getting pad data for the pad const Request::PadData pad_data{ - Request::PadData::Flags::AllPorts, + Request::RegisterFlags::AllPads, 0, 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) { const auto touch_pad = data.touch[id]; - const int touch_id = static_cast(client * 2 + id); + const auto touch_axis_x_id = + static_cast(id == 0 ? PadAxes::Touch1X : PadAxes::Touch2X); + const auto touch_axis_y_id = + static_cast(id == 0 ? PadAxes::Touch1Y : PadAxes::Touch2Y); + const auto touch_button_id = + static_cast(id == 0 ? PadButton::Touch1 : PadButton::touch2); // TODO: Use custom calibration per device 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(max_y - min_y); if (touch_pad.is_active) { - SetAxis(identifier, touch_id * 2, x); - SetAxis(identifier, touch_id * 2 + 1, y); - SetButton(identifier, touch_id, true); + SetAxis(identifier, touch_axis_x_id, x); + SetAxis(identifier, touch_axis_y_id, y); + SetButton(identifier, touch_button_id, true); continue; } - SetAxis(identifier, touch_id * 2, 0); - SetAxis(identifier, touch_id * 2 + 1, 0); - SetButton(identifier, touch_id, false); + SetAxis(identifier, touch_axis_x_id, 0); + SetAxis(identifier, touch_axis_y_id, 0); + SetButton(identifier, touch_button_id, false); + } + + SetAxis(identifier, static_cast(PadAxes::LeftStickX), + (data.left_stick_x - 127.0f) / 127.0f); + SetAxis(identifier, static_cast(PadAxes::LeftStickY), + (data.left_stick_y - 127.0f) / 127.0f); + SetAxis(identifier, static_cast(PadAxes::RightStickX), + (data.right_stick_x - 127.0f) / 127.0f); + SetAxis(identifier, static_cast(PadAxes::RightStickY), + (data.right_stick_y - 127.0f) / 127.0f); + + static constexpr std::array 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(buttons[i]); + SetButton(identifier, button, button_status); } } @@ -317,6 +343,170 @@ void UDPClient::Reset() { } } +std::vector UDPClient::GetInputDevices() const { + std::vector 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(pad_identifier.port)); + identifier.Set("pad", static_cast(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, 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(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(PadAxes::LeftStickX)); + left_analog_params.Set("axis_y", static_cast(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(PadAxes::RightStickX)); + right_analog_params.Set("axis_y", static_cast(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(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, const std::function& success_callback, const std::function& failure_callback) { diff --git a/src/input_common/drivers/udp_client.h b/src/input_common/drivers/udp_client.h index 1f02adba5..5d483f26b 100644 --- a/src/input_common/drivers/udp_client.h +++ b/src/input_common/drivers/udp_client.h @@ -56,7 +56,61 @@ public: void ReloadSockets(); + /// Used for automapping features + std::vector 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: + 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 { std::size_t pad_index{}; bool connected{}; @@ -90,6 +144,8 @@ private: const PadIdentifier GetPadIdentifier(std::size_t pad_index) 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 static constexpr std::size_t MAX_UDP_CLIENTS = 8; static constexpr std::size_t PADS_PER_CLIENT = 4; -- cgit v1.2.3