input_common/CMakeLists: Make some warnings errors
Makes the input_common code warnings consistent with the rest of the codebase.
This commit is contained in:
		
							parent
							
								
									ca416a0fb8
								
							
						
					
					
						commit
						046c0c91a3
					
				| @ -20,8 +20,8 @@ struct Rectangle { | |||||||
| 
 | 
 | ||||||
|     constexpr Rectangle() = default; |     constexpr Rectangle() = default; | ||||||
| 
 | 
 | ||||||
|     constexpr Rectangle(T left, T top, T right, T bottom) |     constexpr Rectangle(T left_, T top_, T right_, T bottom_) | ||||||
|         : left(left), top(top), right(right), bottom(bottom) {} |         : left(left_), top(top_), right(right_), bottom(bottom_) {} | ||||||
| 
 | 
 | ||||||
|     [[nodiscard]] T GetWidth() const { |     [[nodiscard]] T GetWidth() const { | ||||||
|         if constexpr (std::is_floating_point_v<T>) { |         if constexpr (std::is_floating_point_v<T>) { | ||||||
|  | |||||||
| @ -87,7 +87,13 @@ public: | |||||||
| 
 | 
 | ||||||
|     template <typename V> |     template <typename V> | ||||||
|     [[nodiscard]] constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const { |     [[nodiscard]] constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const { | ||||||
|         return {x * f, y * f}; |         using TV = decltype(T{} * V{}); | ||||||
|  |         using C = std::common_type_t<T, V>; | ||||||
|  | 
 | ||||||
|  |         return { | ||||||
|  |             static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)), | ||||||
|  |             static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)), | ||||||
|  |         }; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     template <typename V> |     template <typename V> | ||||||
| @ -98,7 +104,13 @@ public: | |||||||
| 
 | 
 | ||||||
|     template <typename V> |     template <typename V> | ||||||
|     [[nodiscard]] constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const { |     [[nodiscard]] constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const { | ||||||
|         return {x / f, y / f}; |         using TV = decltype(T{} / V{}); | ||||||
|  |         using C = std::common_type_t<T, V>; | ||||||
|  | 
 | ||||||
|  |         return { | ||||||
|  |             static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)), | ||||||
|  |             static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)), | ||||||
|  |         }; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     template <typename V> |     template <typename V> | ||||||
| @ -168,7 +180,10 @@ public: | |||||||
| 
 | 
 | ||||||
| template <typename T, typename V> | template <typename T, typename V> | ||||||
| [[nodiscard]] constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) { | [[nodiscard]] constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) { | ||||||
|     return Vec2<T>(f * vec.x, f * vec.y); |     using C = std::common_type_t<T, V>; | ||||||
|  | 
 | ||||||
|  |     return Vec2<T>(static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.x)), | ||||||
|  |                    static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.y))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| using Vec2f = Vec2<float>; | using Vec2f = Vec2<float>; | ||||||
| @ -237,7 +252,14 @@ public: | |||||||
| 
 | 
 | ||||||
|     template <typename V> |     template <typename V> | ||||||
|     [[nodiscard]] constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const { |     [[nodiscard]] constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const { | ||||||
|         return {x * f, y * f, z * f}; |         using TV = decltype(T{} * V{}); | ||||||
|  |         using C = std::common_type_t<T, V>; | ||||||
|  | 
 | ||||||
|  |         return { | ||||||
|  |             static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)), | ||||||
|  |             static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)), | ||||||
|  |             static_cast<TV>(static_cast<C>(z) * static_cast<C>(f)), | ||||||
|  |         }; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     template <typename V> |     template <typename V> | ||||||
| @ -247,7 +269,14 @@ public: | |||||||
|     } |     } | ||||||
|     template <typename V> |     template <typename V> | ||||||
|     [[nodiscard]] constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const { |     [[nodiscard]] constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const { | ||||||
|         return {x / f, y / f, z / f}; |         using TV = decltype(T{} / V{}); | ||||||
|  |         using C = std::common_type_t<T, V>; | ||||||
|  | 
 | ||||||
|  |         return { | ||||||
|  |             static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)), | ||||||
|  |             static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)), | ||||||
|  |             static_cast<TV>(static_cast<C>(z) / static_cast<C>(f)), | ||||||
|  |         }; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     template <typename V> |     template <typename V> | ||||||
| @ -367,7 +396,11 @@ public: | |||||||
| 
 | 
 | ||||||
| template <typename T, typename V> | template <typename T, typename V> | ||||||
| [[nodiscard]] constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) { | [[nodiscard]] constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) { | ||||||
|     return Vec3<T>(f * vec.x, f * vec.y, f * vec.z); |     using C = std::common_type_t<T, V>; | ||||||
|  | 
 | ||||||
|  |     return Vec3<T>(static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.x)), | ||||||
|  |                    static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.y)), | ||||||
|  |                    static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.z))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <> | template <> | ||||||
| @ -446,7 +479,15 @@ public: | |||||||
| 
 | 
 | ||||||
|     template <typename V> |     template <typename V> | ||||||
|     [[nodiscard]] constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const { |     [[nodiscard]] constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const { | ||||||
|         return {x * f, y * f, z * f, w * f}; |         using TV = decltype(T{} * V{}); | ||||||
|  |         using C = std::common_type_t<T, V>; | ||||||
|  | 
 | ||||||
|  |         return { | ||||||
|  |             static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)), | ||||||
|  |             static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)), | ||||||
|  |             static_cast<TV>(static_cast<C>(z) * static_cast<C>(f)), | ||||||
|  |             static_cast<TV>(static_cast<C>(w) * static_cast<C>(f)), | ||||||
|  |         }; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     template <typename V> |     template <typename V> | ||||||
| @ -457,7 +498,15 @@ public: | |||||||
| 
 | 
 | ||||||
|     template <typename V> |     template <typename V> | ||||||
|     [[nodiscard]] constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const { |     [[nodiscard]] constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const { | ||||||
|         return {x / f, y / f, z / f, w / f}; |         using TV = decltype(T{} / V{}); | ||||||
|  |         using C = std::common_type_t<T, V>; | ||||||
|  | 
 | ||||||
|  |         return { | ||||||
|  |             static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)), | ||||||
|  |             static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)), | ||||||
|  |             static_cast<TV>(static_cast<C>(z) / static_cast<C>(f)), | ||||||
|  |             static_cast<TV>(static_cast<C>(w) / static_cast<C>(f)), | ||||||
|  |         }; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     template <typename V> |     template <typename V> | ||||||
| @ -582,7 +631,15 @@ public: | |||||||
| 
 | 
 | ||||||
| template <typename T, typename V> | template <typename T, typename V> | ||||||
| [[nodiscard]] constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) { | [[nodiscard]] constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) { | ||||||
|     return {f * vec.x, f * vec.y, f * vec.z, f * vec.w}; |     using TV = decltype(V{} * T{}); | ||||||
|  |     using C = std::common_type_t<T, V>; | ||||||
|  | 
 | ||||||
|  |     return { | ||||||
|  |         static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.x)), | ||||||
|  |         static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.y)), | ||||||
|  |         static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.z)), | ||||||
|  |         static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.w)), | ||||||
|  |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| using Vec4f = Vec4<float>; | using Vec4f = Vec4<float>; | ||||||
|  | |||||||
| @ -29,6 +29,35 @@ add_library(input_common STATIC | |||||||
|     udp/udp.h |     udp/udp.h | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | if (MSVC) | ||||||
|  |     target_compile_options(input_common PRIVATE | ||||||
|  |         # 'expression' : signed/unsigned mismatch | ||||||
|  |         /we4018 | ||||||
|  |         # 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point) | ||||||
|  |         /we4244 | ||||||
|  |         # 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch | ||||||
|  |         /we4245 | ||||||
|  |         # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data | ||||||
|  |         /we4254 | ||||||
|  |         # 'var' : conversion from 'size_t' to 'type', possible loss of data | ||||||
|  |         /we4267 | ||||||
|  |         # 'context' : truncation from 'type1' to 'type2' | ||||||
|  |         /we4305 | ||||||
|  |     ) | ||||||
|  | else() | ||||||
|  |     target_compile_options(input_common PRIVATE | ||||||
|  |         -Werror=conversion | ||||||
|  |         -Werror=ignored-qualifiers | ||||||
|  |         -Werror=implicit-fallthrough | ||||||
|  |         -Werror=reorder | ||||||
|  |         -Werror=shadow | ||||||
|  |         -Werror=sign-compare | ||||||
|  |         -Werror=unused-but-set-parameter | ||||||
|  |         -Werror=unused-but-set-variable | ||||||
|  |         -Werror=unused-variable | ||||||
|  |     ) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
| if(SDL2_FOUND) | if(SDL2_FOUND) | ||||||
|     target_sources(input_common PRIVATE |     target_sources(input_common PRIVATE | ||||||
|         sdl/sdl_impl.cpp |         sdl/sdl_impl.cpp | ||||||
|  | |||||||
| @ -20,18 +20,22 @@ public: | |||||||
|         constexpr float SQRT_HALF = 0.707106781f; |         constexpr float SQRT_HALF = 0.707106781f; | ||||||
|         int x = 0, y = 0; |         int x = 0, y = 0; | ||||||
| 
 | 
 | ||||||
|         if (right->GetStatus()) |         if (right->GetStatus()) { | ||||||
|             ++x; |             ++x; | ||||||
|         if (left->GetStatus()) |         } | ||||||
|  |         if (left->GetStatus()) { | ||||||
|             --x; |             --x; | ||||||
|         if (up->GetStatus()) |         } | ||||||
|  |         if (up->GetStatus()) { | ||||||
|             ++y; |             ++y; | ||||||
|         if (down->GetStatus()) |         } | ||||||
|  |         if (down->GetStatus()) { | ||||||
|             --y; |             --y; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         float coef = modifier->GetStatus() ? modifier_scale : 1.0f; |         const float coef = modifier->GetStatus() ? modifier_scale : 1.0f; | ||||||
|         return std::make_tuple(x * coef * (y == 0 ? 1.0f : SQRT_HALF), |         return std::make_tuple(static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF), | ||||||
|                                y * coef * (x == 0 ? 1.0f : SQRT_HALF)); |                                static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { |     bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ | |||||||
| 
 | 
 | ||||||
| namespace GCAdapter { | namespace GCAdapter { | ||||||
| 
 | 
 | ||||||
| /// Used to loop through and assign button in poller
 | // Used to loop through and assign button in poller
 | ||||||
| constexpr std::array<PadButton, 12> PadButtonArray{ | constexpr std::array<PadButton, 12> PadButtonArray{ | ||||||
|     PadButton::PAD_BUTTON_LEFT, PadButton::PAD_BUTTON_RIGHT, PadButton::PAD_BUTTON_DOWN, |     PadButton::PAD_BUTTON_LEFT, PadButton::PAD_BUTTON_RIGHT, PadButton::PAD_BUTTON_DOWN, | ||||||
|     PadButton::PAD_BUTTON_UP,   PadButton::PAD_TRIGGER_Z,    PadButton::PAD_TRIGGER_R, |     PadButton::PAD_BUTTON_UP,   PadButton::PAD_TRIGGER_Z,    PadButton::PAD_TRIGGER_R, | ||||||
| @ -29,6 +29,18 @@ constexpr std::array<PadButton, 12> PadButtonArray{ | |||||||
|     PadButton::PAD_BUTTON_X,    PadButton::PAD_BUTTON_Y,     PadButton::PAD_BUTTON_START, |     PadButton::PAD_BUTTON_X,    PadButton::PAD_BUTTON_Y,     PadButton::PAD_BUTTON_START, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static void PadToState(const GCPadStatus& pad, GCState& out_state) { | ||||||
|  |     for (const auto& button : PadButtonArray) { | ||||||
|  |         const auto button_key = static_cast<u16>(button); | ||||||
|  |         const auto button_value = (pad.button & button_key) != 0; | ||||||
|  |         out_state.buttons.insert_or_assign(static_cast<s32>(button_key), button_value); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     for (std::size_t i = 0; i < pad.axis_values.size(); ++i) { | ||||||
|  |         out_state.axes.insert_or_assign(static_cast<u32>(i), pad.axis_values[i]); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| Adapter::Adapter() { | Adapter::Adapter() { | ||||||
|     if (usb_adapter_handle != nullptr) { |     if (usb_adapter_handle != nullptr) { | ||||||
|         return; |         return; | ||||||
| @ -78,17 +90,17 @@ GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& ad | |||||||
| 
 | 
 | ||||||
|         for (std::size_t i = 0; i < b1_buttons.size(); ++i) { |         for (std::size_t i = 0; i < b1_buttons.size(); ++i) { | ||||||
|             if ((b1 & (1U << i)) != 0) { |             if ((b1 & (1U << i)) != 0) { | ||||||
|                 pad.button |= static_cast<u16>(b1_buttons[i]); |                 pad.button = static_cast<u16>(pad.button | static_cast<u16>(b1_buttons[i])); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         for (std::size_t j = 0; j < b2_buttons.size(); ++j) { |         for (std::size_t j = 0; j < b2_buttons.size(); ++j) { | ||||||
|             if ((b2 & (1U << j)) != 0) { |             if ((b2 & (1U << j)) != 0) { | ||||||
|                 pad.button |= static_cast<u16>(b2_buttons[j]); |                 pad.button = static_cast<u16>(pad.button | static_cast<u16>(b2_buttons[j])); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         for (PadAxes axis : axes) { |         for (PadAxes axis : axes) { | ||||||
|             const std::size_t index = static_cast<std::size_t>(axis); |             const auto index = static_cast<std::size_t>(axis); | ||||||
|             pad.axis_values[index] = adapter_payload[offset + 3 + index]; |             pad.axis_values[index] = adapter_payload[offset + 3 + index]; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -100,17 +112,6 @@ GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& ad | |||||||
|     return pad; |     return pad; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Adapter::PadToState(const GCPadStatus& pad, GCState& state) { |  | ||||||
|     for (const auto& button : PadButtonArray) { |  | ||||||
|         const u16 button_value = static_cast<u16>(button); |  | ||||||
|         state.buttons.insert_or_assign(button_value, pad.button & button_value); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     for (size_t i = 0; i < pad.axis_values.size(); ++i) { |  | ||||||
|         state.axes.insert_or_assign(static_cast<u8>(i), pad.axis_values[i]); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Adapter::Read() { | void Adapter::Read() { | ||||||
|     LOG_DEBUG(Input, "GC Adapter Read() thread started"); |     LOG_DEBUG(Input, "GC Adapter Read() thread started"); | ||||||
| 
 | 
 | ||||||
| @ -250,7 +251,7 @@ void Adapter::GetGCEndpoint(libusb_device* device) { | |||||||
|             const libusb_interface_descriptor* interface = &interfaceContainer->altsetting[i]; |             const libusb_interface_descriptor* interface = &interfaceContainer->altsetting[i]; | ||||||
|             for (u8 e = 0; e < interface->bNumEndpoints; e++) { |             for (u8 e = 0; e < interface->bNumEndpoints; e++) { | ||||||
|                 const libusb_endpoint_descriptor* endpoint = &interface->endpoint[e]; |                 const libusb_endpoint_descriptor* endpoint = &interface->endpoint[e]; | ||||||
|                 if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) { |                 if ((endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) != 0) { | ||||||
|                     input_endpoint = endpoint->bEndpointAddress; |                     input_endpoint = endpoint->bEndpointAddress; | ||||||
|                 } else { |                 } else { | ||||||
|                     output_endpoint = endpoint->bEndpointAddress; |                     output_endpoint = endpoint->bEndpointAddress; | ||||||
| @ -419,7 +420,7 @@ const std::array<GCState, 4>& Adapter::GetPadState() const { | |||||||
|     return state; |     return state; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int Adapter::GetOriginValue(int port, int axis) const { | int Adapter::GetOriginValue(u32 port, u32 axis) const { | ||||||
|     return origin_status[port].axis_values[axis]; |     return origin_status[port].axis_values[axis]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -60,7 +60,7 @@ struct GCPadStatus { | |||||||
| 
 | 
 | ||||||
| struct GCState { | struct GCState { | ||||||
|     std::unordered_map<int, bool> buttons; |     std::unordered_map<int, bool> buttons; | ||||||
|     std::unordered_map<int, u16> axes; |     std::unordered_map<u32, u16> axes; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum class ControllerTypes { None, Wired, Wireless }; | enum class ControllerTypes { None, Wired, Wireless }; | ||||||
| @ -89,13 +89,11 @@ public: | |||||||
|     std::array<GCState, 4>& GetPadState(); |     std::array<GCState, 4>& GetPadState(); | ||||||
|     const std::array<GCState, 4>& GetPadState() const; |     const std::array<GCState, 4>& GetPadState() const; | ||||||
| 
 | 
 | ||||||
|     int GetOriginValue(int port, int axis) const; |     int GetOriginValue(u32 port, u32 axis) const; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     GCPadStatus GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload); |     GCPadStatus GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload); | ||||||
| 
 | 
 | ||||||
|     void PadToState(const GCPadStatus& pad, GCState& state); |  | ||||||
| 
 |  | ||||||
|     void Read(); |     void Read(); | ||||||
| 
 | 
 | ||||||
|     /// Resets status of device connected to port
 |     /// Resets status of device connected to port
 | ||||||
|  | |||||||
| @ -15,7 +15,7 @@ namespace InputCommon { | |||||||
| 
 | 
 | ||||||
| class GCButton final : public Input::ButtonDevice { | class GCButton final : public Input::ButtonDevice { | ||||||
| public: | public: | ||||||
|     explicit GCButton(int port_, int button_, const GCAdapter::Adapter* adapter) |     explicit GCButton(u32 port_, int button_, const GCAdapter::Adapter* adapter) | ||||||
|         : port(port_), button(button_), gcadapter(adapter) {} |         : port(port_), button(button_), gcadapter(adapter) {} | ||||||
| 
 | 
 | ||||||
|     ~GCButton() override; |     ~GCButton() override; | ||||||
| @ -28,14 +28,14 @@ public: | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     const int port; |     const u32 port; | ||||||
|     const int button; |     const int button; | ||||||
|     const GCAdapter::Adapter* gcadapter; |     const GCAdapter::Adapter* gcadapter; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class GCAxisButton final : public Input::ButtonDevice { | class GCAxisButton final : public Input::ButtonDevice { | ||||||
| public: | public: | ||||||
|     explicit GCAxisButton(int port_, int axis_, float threshold_, bool trigger_if_greater_, |     explicit GCAxisButton(u32 port_, u32 axis_, float threshold_, bool trigger_if_greater_, | ||||||
|                           const GCAdapter::Adapter* adapter) |                           const GCAdapter::Adapter* adapter) | ||||||
|         : port(port_), axis(axis_), threshold(threshold_), trigger_if_greater(trigger_if_greater_), |         : port(port_), axis(axis_), threshold(threshold_), trigger_if_greater(trigger_if_greater_), | ||||||
|           gcadapter(adapter), |           gcadapter(adapter), | ||||||
| @ -56,8 +56,8 @@ public: | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     const int port; |     const u32 port; | ||||||
|     const int axis; |     const u32 axis; | ||||||
|     float threshold; |     float threshold; | ||||||
|     bool trigger_if_greater; |     bool trigger_if_greater; | ||||||
|     const GCAdapter::Adapter* gcadapter; |     const GCAdapter::Adapter* gcadapter; | ||||||
| @ -70,8 +70,8 @@ GCButtonFactory::GCButtonFactory(std::shared_ptr<GCAdapter::Adapter> adapter_) | |||||||
| GCButton::~GCButton() = default; | GCButton::~GCButton() = default; | ||||||
| 
 | 
 | ||||||
| std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::ParamPackage& params) { | std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::ParamPackage& params) { | ||||||
|     const int button_id = params.Get("button", 0); |     const auto button_id = params.Get("button", 0); | ||||||
|     const int port = params.Get("port", 0); |     const auto port = static_cast<u32>(params.Get("port", 0)); | ||||||
| 
 | 
 | ||||||
|     constexpr int PAD_STICK_ID = static_cast<u16>(GCAdapter::PadButton::PAD_STICK); |     constexpr int PAD_STICK_ID = static_cast<u16>(GCAdapter::PadButton::PAD_STICK); | ||||||
| 
 | 
 | ||||||
| @ -149,25 +149,27 @@ void GCButtonFactory::EndConfiguration() { | |||||||
| 
 | 
 | ||||||
| class GCAnalog final : public Input::AnalogDevice { | class GCAnalog final : public Input::AnalogDevice { | ||||||
| public: | public: | ||||||
|     GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_, |     explicit GCAnalog(u32 port_, u32 axis_x_, u32 axis_y_, float deadzone_, | ||||||
|              const GCAdapter::Adapter* adapter, float range_) |                       const GCAdapter::Adapter* adapter, float range_) | ||||||
|         : port(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), gcadapter(adapter), |         : port(port_), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), gcadapter(adapter), | ||||||
|           origin_value_x(static_cast<float>(adapter->GetOriginValue(port_, axis_x_))), |           origin_value_x(static_cast<float>(adapter->GetOriginValue(port_, axis_x_))), | ||||||
|           origin_value_y(static_cast<float>(adapter->GetOriginValue(port_, axis_y_))), |           origin_value_y(static_cast<float>(adapter->GetOriginValue(port_, axis_y_))), | ||||||
|           range(range_) {} |           range(range_) {} | ||||||
| 
 | 
 | ||||||
|     float GetAxis(int axis) const { |     float GetAxis(u32 axis) const { | ||||||
|         if (gcadapter->DeviceConnected(port)) { |         if (gcadapter->DeviceConnected(port)) { | ||||||
|             std::lock_guard lock{mutex}; |             std::lock_guard lock{mutex}; | ||||||
|             const auto origin_value = axis % 2 == 0 ? origin_value_x : origin_value_y; |             const auto origin_value = axis % 2 == 0 ? origin_value_x : origin_value_y; | ||||||
|             return (gcadapter->GetPadState()[port].axes.at(axis) - origin_value) / (100.0f * range); |             const auto axis_value = | ||||||
|  |                 static_cast<float>(gcadapter->GetPadState()[port].axes.at(axis)); | ||||||
|  |             return (axis_value - origin_value) / (100.0f * range); | ||||||
|         } |         } | ||||||
|         return 0.0f; |         return 0.0f; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::pair<float, float> GetAnalog(int axis_x, int axis_y) const { |     std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const { | ||||||
|         float x = GetAxis(axis_x); |         float x = GetAxis(analog_axis_x); | ||||||
|         float y = GetAxis(axis_y); |         float y = GetAxis(analog_axis_y); | ||||||
| 
 | 
 | ||||||
|         // Make sure the coordinates are in the unit circle,
 |         // Make sure the coordinates are in the unit circle,
 | ||||||
|         // otherwise normalize it.
 |         // otherwise normalize it.
 | ||||||
| @ -208,9 +210,9 @@ public: | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     const int port; |     const u32 port; | ||||||
|     const int axis_x; |     const u32 axis_x; | ||||||
|     const int axis_y; |     const u32 axis_y; | ||||||
|     const float deadzone; |     const float deadzone; | ||||||
|     const GCAdapter::Adapter* gcadapter; |     const GCAdapter::Adapter* gcadapter; | ||||||
|     const float origin_value_x; |     const float origin_value_x; | ||||||
| @ -231,11 +233,11 @@ GCAnalogFactory::GCAnalogFactory(std::shared_ptr<GCAdapter::Adapter> adapter_) | |||||||
|  *     - "axis_y": the index of the axis to be bind as y-axis |  *     - "axis_y": the index of the axis to be bind as y-axis | ||||||
|  */ |  */ | ||||||
| std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::ParamPackage& params) { | std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::ParamPackage& params) { | ||||||
|     const int port = params.Get("port", 0); |     const auto port = static_cast<u32>(params.Get("port", 0)); | ||||||
|     const int axis_x = params.Get("axis_x", 0); |     const auto axis_x = static_cast<u32>(params.Get("axis_x", 0)); | ||||||
|     const int axis_y = params.Get("axis_y", 1); |     const auto axis_y = static_cast<u32>(params.Get("axis_y", 1)); | ||||||
|     const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f); |     const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f); | ||||||
|     const float range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f); |     const auto range = std::clamp(params.Get("range", 1.0f), 0.50f, 1.50f); | ||||||
| 
 | 
 | ||||||
|     return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get(), range); |     return std::make_unique<GCAnalog>(port, axis_x, axis_y, deadzone, adapter.get(), range); | ||||||
| } | } | ||||||
| @ -256,7 +258,7 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() { | |||||||
|     for (std::size_t port = 0; port < queue.size(); ++port) { |     for (std::size_t port = 0; port < queue.size(); ++port) { | ||||||
|         while (queue[port].Pop(pad)) { |         while (queue[port].Pop(pad)) { | ||||||
|             if (pad.axis == GCAdapter::PadAxes::Undefined || |             if (pad.axis == GCAdapter::PadAxes::Undefined || | ||||||
|                 std::abs((pad.axis_value - 128.0f) / 128.0f) < 0.1) { |                 std::abs((static_cast<float>(pad.axis_value) - 128.0f) / 128.0f) < 0.1f) { | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|             // An analog device needs two axes, so we need to store the axis for later and wait for
 |             // An analog device needs two axes, so we need to store the axis for later and wait for
 | ||||||
|  | |||||||
| @ -49,8 +49,9 @@ public: | |||||||
|     void ChangeKeyStatus(int key_code, bool pressed) { |     void ChangeKeyStatus(int key_code, bool pressed) { | ||||||
|         std::lock_guard guard{mutex}; |         std::lock_guard guard{mutex}; | ||||||
|         for (const KeyButtonPair& pair : list) { |         for (const KeyButtonPair& pair : list) { | ||||||
|             if (pair.key_code == key_code) |             if (pair.key_code == key_code) { | ||||||
|                 pair.key_button->status.store(pressed); |                 pair.key_button->status.store(pressed); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -73,7 +74,7 @@ KeyButton::~KeyButton() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::unique_ptr<Input::ButtonDevice> Keyboard::Create(const Common::ParamPackage& params) { | std::unique_ptr<Input::ButtonDevice> Keyboard::Create(const Common::ParamPackage& params) { | ||||||
|     int key_code = params.Get("code", 0); |     const int key_code = params.Get("code", 0); | ||||||
|     std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list); |     std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list); | ||||||
|     key_button_list->AddKeyButton(key_code, button.get()); |     key_button_list->AddKeyButton(key_code, button.get()); | ||||||
|     return button; |     return button; | ||||||
|  | |||||||
| @ -196,6 +196,10 @@ ButtonMapping InputSubsystem::GetButtonMappingForDevice(const Common::ParamPacka | |||||||
|     return impl->GetButtonMappingForDevice(device); |     return impl->GetButtonMappingForDevice(device); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | MotionMapping InputSubsystem::GetMotionMappingForDevice(const Common::ParamPackage& device) const { | ||||||
|  |     return impl->GetMotionMappingForDevice(device); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| GCAnalogFactory* InputSubsystem::GetGCAnalogs() { | GCAnalogFactory* InputSubsystem::GetGCAnalogs() { | ||||||
|     return impl->gcanalog.get(); |     return impl->gcanalog.get(); | ||||||
| } | } | ||||||
|  | |||||||
| @ -18,11 +18,11 @@ namespace InputCommon { | |||||||
| // Implementation class of the motion emulation device
 | // Implementation class of the motion emulation device
 | ||||||
| class MotionEmuDevice { | class MotionEmuDevice { | ||||||
| public: | public: | ||||||
|     MotionEmuDevice(int update_millisecond, float sensitivity) |     explicit MotionEmuDevice(int update_millisecond_, float sensitivity_) | ||||||
|         : update_millisecond(update_millisecond), |         : update_millisecond(update_millisecond_), | ||||||
|           update_duration(std::chrono::duration_cast<std::chrono::steady_clock::duration>( |           update_duration(std::chrono::duration_cast<std::chrono::steady_clock::duration>( | ||||||
|               std::chrono::milliseconds(update_millisecond))), |               std::chrono::milliseconds(update_millisecond))), | ||||||
|           sensitivity(sensitivity), motion_emu_thread(&MotionEmuDevice::MotionEmuThread, this) {} |           sensitivity(sensitivity_), motion_emu_thread(&MotionEmuDevice::MotionEmuThread, this) {} | ||||||
| 
 | 
 | ||||||
|     ~MotionEmuDevice() { |     ~MotionEmuDevice() { | ||||||
|         if (motion_emu_thread.joinable()) { |         if (motion_emu_thread.joinable()) { | ||||||
| @ -37,16 +37,18 @@ public: | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void Tilt(int x, int y) { |     void Tilt(int x, int y) { | ||||||
|         auto mouse_move = Common::MakeVec(x, y) - mouse_origin; |         if (!is_tilting) { | ||||||
|         if (is_tilting) { |             return; | ||||||
|             std::lock_guard guard{tilt_mutex}; |         } | ||||||
|             if (mouse_move.x == 0 && mouse_move.y == 0) { | 
 | ||||||
|                 tilt_angle = 0; |         std::lock_guard guard{tilt_mutex}; | ||||||
|             } else { |         const auto mouse_move = Common::MakeVec(x, y) - mouse_origin; | ||||||
|                 tilt_direction = mouse_move.Cast<float>(); |         if (mouse_move.x == 0 && mouse_move.y == 0) { | ||||||
|                 tilt_angle = |             tilt_angle = 0; | ||||||
|                     std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f, Common::PI * 0.5f); |         } else { | ||||||
|             } |             tilt_direction = mouse_move.Cast<float>(); | ||||||
|  |             tilt_angle = | ||||||
|  |                 std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f, Common::PI * 0.5f); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -86,11 +88,10 @@ private: | |||||||
|     void MotionEmuThread() { |     void MotionEmuThread() { | ||||||
|         auto update_time = std::chrono::steady_clock::now(); |         auto update_time = std::chrono::steady_clock::now(); | ||||||
|         Common::Quaternion<float> q = Common::MakeQuaternion(Common::Vec3<float>(), 0); |         Common::Quaternion<float> q = Common::MakeQuaternion(Common::Vec3<float>(), 0); | ||||||
|         Common::Quaternion<float> old_q; |  | ||||||
| 
 | 
 | ||||||
|         while (!shutdown_event.WaitUntil(update_time)) { |         while (!shutdown_event.WaitUntil(update_time)) { | ||||||
|             update_time += update_duration; |             update_time += update_duration; | ||||||
|             old_q = q; |             const Common::Quaternion<float> old_q = q; | ||||||
| 
 | 
 | ||||||
|             { |             { | ||||||
|                 std::lock_guard guard{tilt_mutex}; |                 std::lock_guard guard{tilt_mutex}; | ||||||
| @ -100,14 +101,14 @@ private: | |||||||
|                     Common::MakeVec(-tilt_direction.y, 0.0f, tilt_direction.x), tilt_angle); |                     Common::MakeVec(-tilt_direction.y, 0.0f, tilt_direction.x), tilt_angle); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             auto inv_q = q.Inverse(); |             const auto inv_q = q.Inverse(); | ||||||
| 
 | 
 | ||||||
|             // Set the gravity vector in world space
 |             // Set the gravity vector in world space
 | ||||||
|             auto gravity = Common::MakeVec(0.0f, -1.0f, 0.0f); |             auto gravity = Common::MakeVec(0.0f, -1.0f, 0.0f); | ||||||
| 
 | 
 | ||||||
|             // Find the angular rate vector in world space
 |             // Find the angular rate vector in world space
 | ||||||
|             auto angular_rate = ((q - old_q) * inv_q).xyz * 2; |             auto angular_rate = ((q - old_q) * inv_q).xyz * 2; | ||||||
|             angular_rate *= 1000 / update_millisecond / Common::PI * 180; |             angular_rate *= static_cast<float>(1000 / update_millisecond) / Common::PI * 180.0f; | ||||||
| 
 | 
 | ||||||
|             // Transform the two vectors from world space to 3DS space
 |             // Transform the two vectors from world space to 3DS space
 | ||||||
|             gravity = QuaternionRotate(inv_q, gravity); |             gravity = QuaternionRotate(inv_q, gravity); | ||||||
| @ -136,7 +137,7 @@ private: | |||||||
| // can forward all the inputs to the implementation only when it is valid.
 | // can forward all the inputs to the implementation only when it is valid.
 | ||||||
| class MotionEmuDeviceWrapper : public Input::MotionDevice { | class MotionEmuDeviceWrapper : public Input::MotionDevice { | ||||||
| public: | public: | ||||||
|     MotionEmuDeviceWrapper(int update_millisecond, float sensitivity) { |     explicit MotionEmuDeviceWrapper(int update_millisecond, float sensitivity) { | ||||||
|         device = std::make_shared<MotionEmuDevice>(update_millisecond, sensitivity); |         device = std::make_shared<MotionEmuDevice>(update_millisecond, sensitivity); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -148,8 +149,8 @@ public: | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| std::unique_ptr<Input::MotionDevice> MotionEmu::Create(const Common::ParamPackage& params) { | std::unique_ptr<Input::MotionDevice> MotionEmu::Create(const Common::ParamPackage& params) { | ||||||
|     int update_period = params.Get("update_period", 100); |     const int update_period = params.Get("update_period", 100); | ||||||
|     float sensitivity = params.Get("sensitivity", 0.01f); |     const float sensitivity = params.Get("sensitivity", 0.01f); | ||||||
|     auto device_wrapper = std::make_unique<MotionEmuDeviceWrapper>(update_period, sensitivity); |     auto device_wrapper = std::make_unique<MotionEmuDeviceWrapper>(update_period, sensitivity); | ||||||
|     // Previously created device is disconnected here. Having two motion devices for 3DS is not
 |     // Previously created device is disconnected here. Having two motion devices for 3DS is not
 | ||||||
|     // expected.
 |     // expected.
 | ||||||
|  | |||||||
| @ -11,7 +11,7 @@ class MotionKey final : public Input::MotionDevice { | |||||||
| public: | public: | ||||||
|     using Button = std::unique_ptr<Input::ButtonDevice>; |     using Button = std::unique_ptr<Input::ButtonDevice>; | ||||||
| 
 | 
 | ||||||
|     MotionKey(Button key_) : key(std::move(key_)) {} |     explicit MotionKey(Button key_) : key(std::move(key_)) {} | ||||||
| 
 | 
 | ||||||
|     Input::MotionStatus GetStatus() const override { |     Input::MotionStatus GetStatus() const override { | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -8,8 +8,7 @@ | |||||||
| 
 | 
 | ||||||
| namespace InputCommon { | namespace InputCommon { | ||||||
| 
 | 
 | ||||||
| MotionInput::MotionInput(f32 new_kp, f32 new_ki, f32 new_kd) | MotionInput::MotionInput(f32 new_kp, f32 new_ki, f32 new_kd) : kp(new_kp), ki(new_ki), kd(new_kd) {} | ||||||
|     : kp(new_kp), ki(new_ki), kd(new_kd), quat{{0, 0, -1}, 0} {} |  | ||||||
| 
 | 
 | ||||||
| void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) { | void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) { | ||||||
|     accel = acceleration; |     accel = acceleration; | ||||||
| @ -59,7 +58,7 @@ bool MotionInput::IsCalibrated(f32 sensitivity) const { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MotionInput::UpdateRotation(u64 elapsed_time) { | void MotionInput::UpdateRotation(u64 elapsed_time) { | ||||||
|     const f32 sample_period = elapsed_time / 1000000.0f; |     const auto sample_period = static_cast<f32>(elapsed_time) / 1000000.0f; | ||||||
|     if (sample_period > 0.1f) { |     if (sample_period > 0.1f) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @ -75,7 +74,7 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) { | |||||||
|     f32 q2 = quat.xyz[0]; |     f32 q2 = quat.xyz[0]; | ||||||
|     f32 q3 = quat.xyz[1]; |     f32 q3 = quat.xyz[1]; | ||||||
|     f32 q4 = quat.xyz[2]; |     f32 q4 = quat.xyz[2]; | ||||||
|     const f32 sample_period = elapsed_time / 1000000.0f; |     const auto sample_period = static_cast<f32>(elapsed_time) / 1000000.0f; | ||||||
| 
 | 
 | ||||||
|     // Ignore invalid elapsed time
 |     // Ignore invalid elapsed time
 | ||||||
|     if (sample_period > 0.1f) { |     if (sample_period > 0.1f) { | ||||||
| @ -203,21 +202,21 @@ Input::MotionStatus MotionInput::GetRandomMotion(int accel_magnitude, int gyro_m | |||||||
|     std::random_device device; |     std::random_device device; | ||||||
|     std::mt19937 gen(device()); |     std::mt19937 gen(device()); | ||||||
|     std::uniform_int_distribution<s16> distribution(-1000, 1000); |     std::uniform_int_distribution<s16> distribution(-1000, 1000); | ||||||
|     const Common::Vec3f gyroscope = { |     const Common::Vec3f gyroscope{ | ||||||
|         distribution(gen) * 0.001f, |         static_cast<f32>(distribution(gen)) * 0.001f, | ||||||
|         distribution(gen) * 0.001f, |         static_cast<f32>(distribution(gen)) * 0.001f, | ||||||
|         distribution(gen) * 0.001f, |         static_cast<f32>(distribution(gen)) * 0.001f, | ||||||
|     }; |     }; | ||||||
|     const Common::Vec3f accelerometer = { |     const Common::Vec3f accelerometer{ | ||||||
|         distribution(gen) * 0.001f, |         static_cast<f32>(distribution(gen)) * 0.001f, | ||||||
|         distribution(gen) * 0.001f, |         static_cast<f32>(distribution(gen)) * 0.001f, | ||||||
|         distribution(gen) * 0.001f, |         static_cast<f32>(distribution(gen)) * 0.001f, | ||||||
|     }; |     }; | ||||||
|     const Common::Vec3f rotation = {}; |     constexpr Common::Vec3f rotation; | ||||||
|     const std::array<Common::Vec3f, 3> orientation = { |     constexpr std::array orientation{ | ||||||
|         Common::Vec3f{1.0f, 0, 0}, |         Common::Vec3f{1.0f, 0.0f, 0.0f}, | ||||||
|         Common::Vec3f{0, 1.0f, 0}, |         Common::Vec3f{0.0f, 1.0f, 0.0f}, | ||||||
|         Common::Vec3f{0, 0, 1.0f}, |         Common::Vec3f{0.0f, 0.0f, 1.0f}, | ||||||
|     }; |     }; | ||||||
|     return {accelerometer * accel_magnitude, gyroscope * gyro_magnitude, rotation, orientation}; |     return {accelerometer * accel_magnitude, gyroscope * gyro_magnitude, rotation, orientation}; | ||||||
| } | } | ||||||
| @ -247,9 +246,6 @@ void MotionInput::SetOrientationFromAccelerometer() { | |||||||
|     const f32 sample_period = 0.015f; |     const f32 sample_period = 0.015f; | ||||||
| 
 | 
 | ||||||
|     const auto normal_accel = accel.Normalized(); |     const auto normal_accel = accel.Normalized(); | ||||||
|     const f32 ax = -normal_accel.x; |  | ||||||
|     const f32 ay = normal_accel.y; |  | ||||||
|     const f32 az = -normal_accel.z; |  | ||||||
| 
 | 
 | ||||||
|     while (!IsCalibrated(0.01f) && ++iterations < 100) { |     while (!IsCalibrated(0.01f) && ++iterations < 100) { | ||||||
|         // Short name local variable for readability
 |         // Short name local variable for readability
 | ||||||
| @ -258,7 +254,7 @@ void MotionInput::SetOrientationFromAccelerometer() { | |||||||
|         f32 q3 = quat.xyz[1]; |         f32 q3 = quat.xyz[1]; | ||||||
|         f32 q4 = quat.xyz[2]; |         f32 q4 = quat.xyz[2]; | ||||||
| 
 | 
 | ||||||
|         Common::Vec3f rad_gyro = {}; |         Common::Vec3f rad_gyro; | ||||||
|         const f32 ax = -normal_accel.x; |         const f32 ax = -normal_accel.x; | ||||||
|         const f32 ay = normal_accel.y; |         const f32 ay = normal_accel.y; | ||||||
|         const f32 az = -normal_accel.z; |         const f32 az = -normal_accel.z; | ||||||
|  | |||||||
| @ -22,7 +22,7 @@ public: | |||||||
|     MotionInput& operator=(MotionInput&&) = default; |     MotionInput& operator=(MotionInput&&) = default; | ||||||
| 
 | 
 | ||||||
|     void SetAcceleration(const Common::Vec3f& acceleration); |     void SetAcceleration(const Common::Vec3f& acceleration); | ||||||
|     void SetGyroscope(const Common::Vec3f& acceleration); |     void SetGyroscope(const Common::Vec3f& gyroscope); | ||||||
|     void SetQuaternion(const Common::Quaternion<f32>& quaternion); |     void SetQuaternion(const Common::Quaternion<f32>& quaternion); | ||||||
|     void SetGyroDrift(const Common::Vec3f& drift); |     void SetGyroDrift(const Common::Vec3f& drift); | ||||||
|     void SetGyroThreshold(f32 threshold); |     void SetGyroThreshold(f32 threshold); | ||||||
| @ -49,16 +49,16 @@ private: | |||||||
|     void SetOrientationFromAccelerometer(); |     void SetOrientationFromAccelerometer(); | ||||||
| 
 | 
 | ||||||
|     // PID constants
 |     // PID constants
 | ||||||
|     const f32 kp; |     f32 kp; | ||||||
|     const f32 ki; |     f32 ki; | ||||||
|     const f32 kd; |     f32 kd; | ||||||
| 
 | 
 | ||||||
|     // PID errors
 |     // PID errors
 | ||||||
|     Common::Vec3f real_error; |     Common::Vec3f real_error; | ||||||
|     Common::Vec3f integral_error; |     Common::Vec3f integral_error; | ||||||
|     Common::Vec3f derivative_error; |     Common::Vec3f derivative_error; | ||||||
| 
 | 
 | ||||||
|     Common::Quaternion<f32> quat; |     Common::Quaternion<f32> quat{{0.0f, 0.0f, -1.0f}, 0.0f}; | ||||||
|     Common::Vec3f rotations; |     Common::Vec3f rotations; | ||||||
|     Common::Vec3f accel; |     Common::Vec3f accel; | ||||||
|     Common::Vec3f gyro; |     Common::Vec3f gyro; | ||||||
|  | |||||||
| @ -56,9 +56,9 @@ static int SDLEventWatcher(void* user_data, SDL_Event* event) { | |||||||
| class SDLJoystick { | class SDLJoystick { | ||||||
| public: | public: | ||||||
|     SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, |     SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, | ||||||
|                 SDL_GameController* gamecontroller) |                 SDL_GameController* game_controller) | ||||||
|         : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, |         : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, | ||||||
|           sdl_controller{gamecontroller, &SDL_GameControllerClose} {} |           sdl_controller{game_controller, &SDL_GameControllerClose} {} | ||||||
| 
 | 
 | ||||||
|     void SetButton(int button, bool value) { |     void SetButton(int button, bool value) { | ||||||
|         std::lock_guard lock{mutex}; |         std::lock_guard lock{mutex}; | ||||||
| @ -77,10 +77,10 @@ public: | |||||||
| 
 | 
 | ||||||
|     float GetAxis(int axis, float range) const { |     float GetAxis(int axis, float range) const { | ||||||
|         std::lock_guard lock{mutex}; |         std::lock_guard lock{mutex}; | ||||||
|         return state.axes.at(axis) / (32767.0f * range); |         return static_cast<float>(state.axes.at(axis)) / (32767.0f * range); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     bool RumblePlay(f32 amp_low, f32 amp_high, int time) { |     bool RumblePlay(f32 amp_low, f32 amp_high, u32 time) { | ||||||
|         const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF); |         const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF); | ||||||
|         const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF); |         const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF); | ||||||
|         // Lower drastically the number of state changes
 |         // Lower drastically the number of state changes
 | ||||||
| @ -124,7 +124,7 @@ public: | |||||||
|         return std::make_tuple(x, y); |         return std::make_tuple(x, y); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const InputCommon::MotionInput& GetMotion() const { |     const MotionInput& GetMotion() const { | ||||||
|         return motion; |         return motion; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -172,15 +172,15 @@ private: | |||||||
|     } state; |     } state; | ||||||
|     std::string guid; |     std::string guid; | ||||||
|     int port; |     int port; | ||||||
|     u16 last_state_rumble_high; |     u16 last_state_rumble_high = 0; | ||||||
|     u16 last_state_rumble_low; |     u16 last_state_rumble_low = 0; | ||||||
|     std::chrono::time_point<std::chrono::system_clock> last_vibration; |     std::chrono::time_point<std::chrono::system_clock> last_vibration; | ||||||
|     std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; |     std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; | ||||||
|     std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; |     std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; | ||||||
|     mutable std::mutex mutex; |     mutable std::mutex mutex; | ||||||
| 
 | 
 | ||||||
|     // motion is initalized without PID values as motion input is not aviable for SDL2
 |     // Motion is initialized without PID values as motion input is not aviable for SDL2
 | ||||||
|     InputCommon::MotionInput motion{0.0f, 0.0f, 0.0f}; |     MotionInput motion{0.0f, 0.0f, 0.0f}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) { | std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) { | ||||||
| @ -192,7 +192,7 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& g | |||||||
|                                                           nullptr, nullptr); |                                                           nullptr, nullptr); | ||||||
|             it->second.emplace_back(std::move(joystick)); |             it->second.emplace_back(std::move(joystick)); | ||||||
|         } |         } | ||||||
|         return it->second[port]; |         return it->second[static_cast<std::size_t>(port)]; | ||||||
|     } |     } | ||||||
|     auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, nullptr); |     auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, nullptr); | ||||||
|     return joystick_map[guid].emplace_back(std::move(joystick)); |     return joystick_map[guid].emplace_back(std::move(joystick)); | ||||||
| @ -212,7 +212,7 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_ | |||||||
|                              return sdl_joystick == joystick->GetSDLJoystick(); |                              return sdl_joystick == joystick->GetSDLJoystick(); | ||||||
|                          }); |                          }); | ||||||
|         if (vec_it != map_it->second.end()) { |         if (vec_it != map_it->second.end()) { | ||||||
|             // This is the common case: There is already an existing SDL_Joystick maped to a
 |             // This is the common case: There is already an existing SDL_Joystick mapped to a
 | ||||||
|             // SDLJoystick. return the SDLJoystick
 |             // SDLJoystick. return the SDLJoystick
 | ||||||
|             return *vec_it; |             return *vec_it; | ||||||
|         } |         } | ||||||
| @ -220,7 +220,7 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_ | |||||||
|         // Search for a SDLJoystick without a mapped SDL_Joystick...
 |         // Search for a SDLJoystick without a mapped SDL_Joystick...
 | ||||||
|         const auto nullptr_it = std::find_if(map_it->second.begin(), map_it->second.end(), |         const auto nullptr_it = std::find_if(map_it->second.begin(), map_it->second.end(), | ||||||
|                                              [](const std::shared_ptr<SDLJoystick>& joystick) { |                                              [](const std::shared_ptr<SDLJoystick>& joystick) { | ||||||
|                                                  return !joystick->GetSDLJoystick(); |                                                  return joystick->GetSDLJoystick() == nullptr; | ||||||
|                                              }); |                                              }); | ||||||
|         if (nullptr_it != map_it->second.end()) { |         if (nullptr_it != map_it->second.end()) { | ||||||
|             // ... and map it
 |             // ... and map it
 | ||||||
| @ -273,22 +273,21 @@ void SDLState::InitJoystick(int joystick_index) { | |||||||
| void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) { | void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) { | ||||||
|     const std::string guid = GetGUID(sdl_joystick); |     const std::string guid = GetGUID(sdl_joystick); | ||||||
| 
 | 
 | ||||||
|     std::shared_ptr<SDLJoystick> joystick; |     std::shared_ptr<SDLJoystick> found_joystick; | ||||||
|     { |     { | ||||||
|         std::lock_guard lock{joystick_map_mutex}; |         std::lock_guard lock{joystick_map_mutex}; | ||||||
|         // This call to guid is safe since the joystick is guaranteed to be in the map
 |         // This call to guid is safe since the joystick is guaranteed to be in the map
 | ||||||
|         const auto& joystick_guid_list = joystick_map[guid]; |         const auto& joystick_guid_list = joystick_map[guid]; | ||||||
|         const auto joystick_it = |         const auto joystick_it = std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(), | ||||||
|             std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(), |                                               [&sdl_joystick](const auto& joystick) { | ||||||
|                          [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) { |                                                   return joystick->GetSDLJoystick() == sdl_joystick; | ||||||
|                              return joystick->GetSDLJoystick() == sdl_joystick; |                                               }); | ||||||
|                          }); |         found_joystick = *joystick_it; | ||||||
|         joystick = *joystick_it; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Destruct SDL_Joystick outside the lock guard because SDL can internally call the
 |     // Destruct SDL_Joystick outside the lock guard because SDL can internally call the
 | ||||||
|     // event callback which locks the mutex again.
 |     // event callback which locks the mutex again.
 | ||||||
|     joystick->SetSDLJoystick(nullptr, nullptr); |     found_joystick->SetSDLJoystick(nullptr, nullptr); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SDLState::HandleGameControllerEvent(const SDL_Event& event) { | void SDLState::HandleGameControllerEvent(const SDL_Event& event) { | ||||||
| @ -392,8 +391,8 @@ private: | |||||||
| 
 | 
 | ||||||
| class SDLAnalog final : public Input::AnalogDevice { | class SDLAnalog final : public Input::AnalogDevice { | ||||||
| public: | public: | ||||||
|     SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_, float deadzone_, |     explicit SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_, | ||||||
|               float range_) |                        float deadzone_, float range_) | ||||||
|         : joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), |         : joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), | ||||||
|           range(range_) {} |           range(range_) {} | ||||||
| 
 | 
 | ||||||
| @ -672,13 +671,13 @@ SDLState::SDLState() { | |||||||
|     RegisterFactory<ButtonDevice>("sdl", button_factory); |     RegisterFactory<ButtonDevice>("sdl", button_factory); | ||||||
|     RegisterFactory<MotionDevice>("sdl", motion_factory); |     RegisterFactory<MotionDevice>("sdl", motion_factory); | ||||||
| 
 | 
 | ||||||
|     // If the frontend is going to manage the event loop, then we dont start one here
 |     // If the frontend is going to manage the event loop, then we don't start one here
 | ||||||
|     start_thread = !SDL_WasInit(SDL_INIT_JOYSTICK); |     start_thread = SDL_WasInit(SDL_INIT_JOYSTICK) == 0; | ||||||
|     if (start_thread && SDL_Init(SDL_INIT_JOYSTICK) < 0) { |     if (start_thread && SDL_Init(SDL_INIT_JOYSTICK) < 0) { | ||||||
|         LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError()); |         LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError()); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     has_gamecontroller = SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); |     has_gamecontroller = SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) != 0; | ||||||
|     if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) { |     if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) { | ||||||
|         LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError()); |         LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError()); | ||||||
|     } |     } | ||||||
| @ -723,8 +722,8 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() { | |||||||
|     std::vector<Common::ParamPackage> devices; |     std::vector<Common::ParamPackage> devices; | ||||||
|     for (const auto& [key, value] : joystick_map) { |     for (const auto& [key, value] : joystick_map) { | ||||||
|         for (const auto& joystick : value) { |         for (const auto& joystick : value) { | ||||||
|             auto joy = joystick->GetSDLJoystick(); |             auto* joy = joystick->GetSDLJoystick(); | ||||||
|             if (auto controller = joystick->GetSDLGameController()) { |             if (auto* controller = joystick->GetSDLGameController()) { | ||||||
|                 std::string name = |                 std::string name = | ||||||
|                     fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort()); |                     fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort()); | ||||||
|                 devices.emplace_back(Common::ParamPackage{ |                 devices.emplace_back(Common::ParamPackage{ | ||||||
| @ -748,7 +747,7 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| namespace { | namespace { | ||||||
| Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, u8 axis, | Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, | ||||||
|                                                       float value = 0.1f) { |                                                       float value = 0.1f) { | ||||||
|     Common::ParamPackage params({{"engine", "sdl"}}); |     Common::ParamPackage params({{"engine", "sdl"}}); | ||||||
|     params.Set("port", port); |     params.Set("port", port); | ||||||
| @ -764,7 +763,7 @@ Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid | |||||||
|     return params; |     return params; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, u8 button) { | Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, s32 button) { | ||||||
|     Common::ParamPackage params({{"engine", "sdl"}}); |     Common::ParamPackage params({{"engine", "sdl"}}); | ||||||
|     params.Set("port", port); |     params.Set("port", port); | ||||||
|     params.Set("guid", std::move(guid)); |     params.Set("guid", std::move(guid)); | ||||||
| @ -772,7 +771,7 @@ Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid | |||||||
|     return params; |     return params; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, u8 hat, u8 value) { | Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, s32 hat, s32 value) { | ||||||
|     Common::ParamPackage params({{"engine", "sdl"}}); |     Common::ParamPackage params({{"engine", "sdl"}}); | ||||||
| 
 | 
 | ||||||
|     params.Set("port", port); |     params.Set("port", port); | ||||||
| @ -802,17 +801,19 @@ Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Eve | |||||||
|     case SDL_JOYAXISMOTION: { |     case SDL_JOYAXISMOTION: { | ||||||
|         const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); |         const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); | ||||||
|         return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), |         return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), | ||||||
|                                                 event.jaxis.axis, event.jaxis.value); |                                                 static_cast<s32>(event.jaxis.axis), | ||||||
|  |                                                 event.jaxis.value); | ||||||
|     } |     } | ||||||
|     case SDL_JOYBUTTONUP: { |     case SDL_JOYBUTTONUP: { | ||||||
|         const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); |         const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); | ||||||
|         return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), |         return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), | ||||||
|                                                 event.jbutton.button); |                                                 static_cast<s32>(event.jbutton.button)); | ||||||
|     } |     } | ||||||
|     case SDL_JOYHATMOTION: { |     case SDL_JOYHATMOTION: { | ||||||
|         const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); |         const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); | ||||||
|         return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), |         return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), | ||||||
|                                              event.jhat.hat, event.jhat.value); |                                              static_cast<s32>(event.jhat.hat), | ||||||
|  |                                              static_cast<s32>(event.jhat.value)); | ||||||
|     } |     } | ||||||
|     } |     } | ||||||
|     return {}; |     return {}; | ||||||
| @ -823,17 +824,19 @@ Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Eve | |||||||
|     case SDL_JOYAXISMOTION: { |     case SDL_JOYAXISMOTION: { | ||||||
|         const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); |         const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); | ||||||
|         return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), |         return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), | ||||||
|                                                 event.jaxis.axis, event.jaxis.value); |                                                 static_cast<s32>(event.jaxis.axis), | ||||||
|  |                                                 event.jaxis.value); | ||||||
|     } |     } | ||||||
|     case SDL_JOYBUTTONUP: { |     case SDL_JOYBUTTONUP: { | ||||||
|         const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); |         const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); | ||||||
|         return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), |         return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), | ||||||
|                                                 event.jbutton.button); |                                                 static_cast<s32>(event.jbutton.button)); | ||||||
|     } |     } | ||||||
|     case SDL_JOYHATMOTION: { |     case SDL_JOYHATMOTION: { | ||||||
|         const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); |         const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); | ||||||
|         return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), |         return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), | ||||||
|                                              event.jhat.hat, event.jhat.value); |                                              static_cast<s32>(event.jhat.hat), | ||||||
|  |                                              static_cast<s32>(event.jhat.value)); | ||||||
|     } |     } | ||||||
|     } |     } | ||||||
|     return {}; |     return {}; | ||||||
| @ -1062,7 +1065,7 @@ public: | |||||||
|             if (event.type == SDL_JOYAXISMOTION) { |             if (event.type == SDL_JOYAXISMOTION) { | ||||||
|                 const auto axis = event.jaxis.axis; |                 const auto axis = event.jaxis.axis; | ||||||
|                 const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); |                 const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); | ||||||
|                 const auto controller = joystick->GetSDLGameController(); |                 auto* const controller = joystick->GetSDLGameController(); | ||||||
|                 if (controller) { |                 if (controller) { | ||||||
|                     const auto axis_left_x = |                     const auto axis_left_x = | ||||||
|                         SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) |                         SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) | ||||||
|  | |||||||
| @ -11,9 +11,11 @@ namespace InputCommon { | |||||||
| class TouchFromButtonDevice final : public Input::TouchDevice { | class TouchFromButtonDevice final : public Input::TouchDevice { | ||||||
| public: | public: | ||||||
|     TouchFromButtonDevice() { |     TouchFromButtonDevice() { | ||||||
|         for (const auto& config_entry : |         const auto button_index = | ||||||
|              Settings::values.touch_from_button_maps[Settings::values.touch_from_button_map_index] |             static_cast<std::size_t>(Settings::values.touch_from_button_map_index); | ||||||
|                  .buttons) { |         const auto& buttons = Settings::values.touch_from_button_maps[button_index].buttons; | ||||||
|  | 
 | ||||||
|  |         for (const auto& config_entry : buttons) { | ||||||
|             const Common::ParamPackage package{config_entry}; |             const Common::ParamPackage package{config_entry}; | ||||||
|             map.emplace_back( |             map.emplace_back( | ||||||
|                 Input::CreateDevice<Input::ButtonDevice>(config_entry), |                 Input::CreateDevice<Input::ButtonDevice>(config_entry), | ||||||
|  | |||||||
| @ -26,11 +26,11 @@ class Socket { | |||||||
| public: | public: | ||||||
|     using clock = std::chrono::system_clock; |     using clock = std::chrono::system_clock; | ||||||
| 
 | 
 | ||||||
|     explicit Socket(const std::string& host, u16 port, u8 pad_index, u32 client_id, |     explicit Socket(const std::string& host, u16 port, std::size_t pad_index_, u32 client_id_, | ||||||
|                     SocketCallback callback) |                     SocketCallback callback_) | ||||||
|         : callback(std::move(callback)), timer(io_service), |         : callback(std::move(callback_)), timer(io_service), | ||||||
|           socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(client_id), |           socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(client_id_), | ||||||
|           pad_index(pad_index) { |           pad_index(pad_index_) { | ||||||
|         boost::system::error_code ec{}; |         boost::system::error_code ec{}; | ||||||
|         auto ipv4 = boost::asio::ip::make_address_v4(host, ec); |         auto ipv4 = boost::asio::ip::make_address_v4(host, ec); | ||||||
|         if (ec.value() != boost::system::errc::success) { |         if (ec.value() != boost::system::errc::success) { | ||||||
| @ -93,13 +93,17 @@ private: | |||||||
|     void HandleSend(const boost::system::error_code& error) { |     void HandleSend(const boost::system::error_code& error) { | ||||||
|         boost::system::error_code _ignored{}; |         boost::system::error_code _ignored{}; | ||||||
|         // Send a request for getting port info for the pad
 |         // Send a request for getting port info for the pad
 | ||||||
|         Request::PortInfo port_info{1, {pad_index, 0, 0, 0}}; |         const Request::PortInfo port_info{1, {static_cast<u8>(pad_index), 0, 0, 0}}; | ||||||
|         const auto port_message = Request::Create(port_info, client_id); |         const auto port_message = Request::Create(port_info, client_id); | ||||||
|         std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE); |         std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE); | ||||||
|         socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored); |         socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored); | ||||||
| 
 | 
 | ||||||
|         // Send a request for getting pad data for the pad
 |         // Send a request for getting pad data for the pad
 | ||||||
|         Request::PadData pad_data{Request::PadData::Flags::Id, pad_index, EMPTY_MAC_ADDRESS}; |         const Request::PadData pad_data{ | ||||||
|  |             Request::PadData::Flags::Id, | ||||||
|  |             static_cast<u8>(pad_index), | ||||||
|  |             EMPTY_MAC_ADDRESS, | ||||||
|  |         }; | ||||||
|         const auto pad_message = Request::Create(pad_data, client_id); |         const auto pad_message = Request::Create(pad_data, client_id); | ||||||
|         std::memcpy(send_buffer2.data(), &pad_message, PAD_DATA_SIZE); |         std::memcpy(send_buffer2.data(), &pad_message, PAD_DATA_SIZE); | ||||||
|         socket.send_to(boost::asio::buffer(send_buffer2), send_endpoint, {}, _ignored); |         socket.send_to(boost::asio::buffer(send_buffer2), send_endpoint, {}, _ignored); | ||||||
| @ -112,7 +116,7 @@ private: | |||||||
|     udp::socket socket; |     udp::socket socket; | ||||||
| 
 | 
 | ||||||
|     u32 client_id{}; |     u32 client_id{}; | ||||||
|     u8 pad_index{}; |     std::size_t pad_index{}; | ||||||
| 
 | 
 | ||||||
|     static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>); |     static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>); | ||||||
|     static constexpr std::size_t PAD_DATA_SIZE = sizeof(Message<Request::PadData>); |     static constexpr std::size_t PAD_DATA_SIZE = sizeof(Message<Request::PadData>); | ||||||
| @ -133,7 +137,7 @@ static void SocketLoop(Socket* socket) { | |||||||
| Client::Client() { | Client::Client() { | ||||||
|     LOG_INFO(Input, "Udp Initialization started"); |     LOG_INFO(Input, "Udp Initialization started"); | ||||||
|     for (std::size_t client = 0; client < clients.size(); client++) { |     for (std::size_t client = 0; client < clients.size(); client++) { | ||||||
|         u8 pad = client % 4; |         const auto pad = client % 4; | ||||||
|         StartCommunication(client, Settings::values.udp_input_address, |         StartCommunication(client, Settings::values.udp_input_address, | ||||||
|                            Settings::values.udp_input_port, pad, 24872); |                            Settings::values.udp_input_port, pad, 24872); | ||||||
|         // Set motion parameters
 |         // Set motion parameters
 | ||||||
| @ -166,9 +170,9 @@ std::vector<Common::ParamPackage> Client::GetInputDevices() const { | |||||||
| bool Client::DeviceConnected(std::size_t pad) const { | bool Client::DeviceConnected(std::size_t pad) const { | ||||||
|     // Use last timestamp to detect if the socket has stopped sending data
 |     // Use last timestamp to detect if the socket has stopped sending data
 | ||||||
|     const auto now = std::chrono::system_clock::now(); |     const auto now = std::chrono::system_clock::now(); | ||||||
|     u64 time_difference = |     const auto time_difference = static_cast<u64>( | ||||||
|         std::chrono::duration_cast<std::chrono::milliseconds>(now - clients[pad].last_motion_update) |         std::chrono::duration_cast<std::chrono::milliseconds>(now - clients[pad].last_motion_update) | ||||||
|             .count(); |             .count()); | ||||||
|     return time_difference < 1000 && clients[pad].active == 1; |     return time_difference < 1000 && clients[pad].active == 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -177,9 +181,9 @@ void Client::ReloadUDPClient() { | |||||||
|         ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port, client); |         ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port, client); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| void Client::ReloadSocket(const std::string& host, u16 port, u8 pad_index, u32 client_id) { | void Client::ReloadSocket(const std::string& host, u16 port, std::size_t pad_index, u32 client_id) { | ||||||
|     // client number must be determined from host / port and pad index
 |     // client number must be determined from host / port and pad index
 | ||||||
|     std::size_t client = pad_index; |     const std::size_t client = pad_index; | ||||||
|     clients[client].socket->Stop(); |     clients[client].socket->Stop(); | ||||||
|     clients[client].thread.join(); |     clients[client].thread.join(); | ||||||
|     StartCommunication(client, host, port, pad_index, client_id); |     StartCommunication(client, host, port, pad_index, client_id); | ||||||
| @ -194,8 +198,8 @@ void Client::OnPortInfo(Response::PortInfo data) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Client::OnPadData(Response::PadData data) { | void Client::OnPadData(Response::PadData data) { | ||||||
|     // client number must be determined from host / port and pad index
 |     // Client number must be determined from host / port and pad index
 | ||||||
|     std::size_t client = data.info.id; |     const std::size_t client = data.info.id; | ||||||
|     LOG_TRACE(Input, "PadData packet received"); |     LOG_TRACE(Input, "PadData packet received"); | ||||||
|     if (data.packet_counter == clients[client].packet_sequence) { |     if (data.packet_counter == clients[client].packet_sequence) { | ||||||
|         LOG_WARNING( |         LOG_WARNING( | ||||||
| @ -207,11 +211,12 @@ void Client::OnPadData(Response::PadData data) { | |||||||
|     clients[client].active = data.info.is_pad_active; |     clients[client].active = data.info.is_pad_active; | ||||||
|     clients[client].packet_sequence = data.packet_counter; |     clients[client].packet_sequence = data.packet_counter; | ||||||
|     const auto now = std::chrono::system_clock::now(); |     const auto now = std::chrono::system_clock::now(); | ||||||
|     u64 time_difference = std::chrono::duration_cast<std::chrono::microseconds>( |     const auto time_difference = | ||||||
|                               now - clients[client].last_motion_update) |         static_cast<u64>(std::chrono::duration_cast<std::chrono::microseconds>( | ||||||
|                               .count(); |                              now - clients[client].last_motion_update) | ||||||
|  |                              .count()); | ||||||
|     clients[client].last_motion_update = now; |     clients[client].last_motion_update = now; | ||||||
|     Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw}; |     const Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw}; | ||||||
|     clients[client].motion.SetAcceleration({data.accel.x, -data.accel.z, data.accel.y}); |     clients[client].motion.SetAcceleration({data.accel.x, -data.accel.z, data.accel.y}); | ||||||
|     // Gyroscope values are not it the correct scale from better joy.
 |     // Gyroscope values are not it the correct scale from better joy.
 | ||||||
|     // Dividing by 312 allows us to make one full turn = 1 turn
 |     // Dividing by 312 allows us to make one full turn = 1 turn
 | ||||||
| @ -237,9 +242,11 @@ void Client::OnPadData(Response::PadData data) { | |||||||
|             const u16 min_y = clients[client].status.touch_calibration->min_y; |             const u16 min_y = clients[client].status.touch_calibration->min_y; | ||||||
|             const u16 max_y = clients[client].status.touch_calibration->max_y; |             const u16 max_y = clients[client].status.touch_calibration->max_y; | ||||||
| 
 | 
 | ||||||
|             x = (std::clamp(static_cast<u16>(data.touch_1.x), min_x, max_x) - min_x) / |             x = static_cast<float>(std::clamp(static_cast<u16>(data.touch_1.x), min_x, max_x) - | ||||||
|  |                                    min_x) / | ||||||
|                 static_cast<float>(max_x - min_x); |                 static_cast<float>(max_x - min_x); | ||||||
|             y = (std::clamp(static_cast<u16>(data.touch_1.y), min_y, max_y) - min_y) / |             y = static_cast<float>(std::clamp(static_cast<u16>(data.touch_1.y), min_y, max_y) - | ||||||
|  |                                    min_y) / | ||||||
|                 static_cast<float>(max_y - min_y); |                 static_cast<float>(max_y - min_y); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -253,8 +260,8 @@ void Client::OnPadData(Response::PadData data) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Client::StartCommunication(std::size_t client, const std::string& host, u16 port, u8 pad_index, | void Client::StartCommunication(std::size_t client, const std::string& host, u16 port, | ||||||
|                                 u32 client_id) { |                                 std::size_t pad_index, u32 client_id) { | ||||||
|     SocketCallback callback{[this](Response::Version version) { OnVersion(version); }, |     SocketCallback callback{[this](Response::Version version) { OnVersion(version); }, | ||||||
|                             [this](Response::PortInfo info) { OnPortInfo(info); }, |                             [this](Response::PortInfo info) { OnPortInfo(info); }, | ||||||
|                             [this](Response::PadData data) { OnPadData(data); }}; |                             [this](Response::PadData data) { OnPadData(data); }}; | ||||||
| @ -264,9 +271,9 @@ void Client::StartCommunication(std::size_t client, const std::string& host, u16 | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Client::Reset() { | void Client::Reset() { | ||||||
|     for (std::size_t client = 0; client < clients.size(); client++) { |     for (auto& client : clients) { | ||||||
|         clients[client].socket->Stop(); |         client.socket->Stop(); | ||||||
|         clients[client].thread.join(); |         client.thread.join(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -325,7 +332,7 @@ const std::array<Common::SPSCQueue<UDPPadStatus>, 4>& Client::GetPadQueue() cons | |||||||
|     return pad_queue; |     return pad_queue; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id, | void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, u32 client_id, | ||||||
|                        std::function<void()> success_callback, |                        std::function<void()> success_callback, | ||||||
|                        std::function<void()> failure_callback) { |                        std::function<void()> failure_callback) { | ||||||
|     std::thread([=] { |     std::thread([=] { | ||||||
| @ -346,7 +353,7 @@ void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 clie | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CalibrationConfigurationJob::CalibrationConfigurationJob( | CalibrationConfigurationJob::CalibrationConfigurationJob( | ||||||
|     const std::string& host, u16 port, u8 pad_index, u32 client_id, |     const std::string& host, u16 port, std::size_t pad_index, u32 client_id, | ||||||
|     std::function<void(Status)> status_callback, |     std::function<void(Status)> status_callback, | ||||||
|     std::function<void(u16, u16, u16, u16)> data_callback) { |     std::function<void(u16, u16, u16, u16)> data_callback) { | ||||||
| 
 | 
 | ||||||
| @ -366,7 +373,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob( | |||||||
|                                         current_status = Status::Ready; |                                         current_status = Status::Ready; | ||||||
|                                         status_callback(current_status); |                                         status_callback(current_status); | ||||||
|                                     } |                                     } | ||||||
|                                     if (!data.touch_1.is_active) { |                                     if (data.touch_1.is_active == 0) { | ||||||
|                                         return; |                                         return; | ||||||
|                                     } |                                     } | ||||||
|                                     LOG_DEBUG(Input, "Current touch: {} {}", data.touch_1.x, |                                     LOG_DEBUG(Input, "Current touch: {} {}", data.touch_1.x, | ||||||
|  | |||||||
| @ -84,8 +84,8 @@ public: | |||||||
| 
 | 
 | ||||||
|     bool DeviceConnected(std::size_t pad) const; |     bool DeviceConnected(std::size_t pad) const; | ||||||
|     void ReloadUDPClient(); |     void ReloadUDPClient(); | ||||||
|     void ReloadSocket(const std::string& host = "127.0.0.1", u16 port = 26760, u8 pad_index = 0, |     void ReloadSocket(const std::string& host = "127.0.0.1", u16 port = 26760, | ||||||
|                       u32 client_id = 24872); |                       std::size_t pad_index = 0, u32 client_id = 24872); | ||||||
| 
 | 
 | ||||||
|     std::array<Common::SPSCQueue<UDPPadStatus>, 4>& GetPadQueue(); |     std::array<Common::SPSCQueue<UDPPadStatus>, 4>& GetPadQueue(); | ||||||
|     const std::array<Common::SPSCQueue<UDPPadStatus>, 4>& GetPadQueue() const; |     const std::array<Common::SPSCQueue<UDPPadStatus>, 4>& GetPadQueue() const; | ||||||
| @ -99,7 +99,7 @@ private: | |||||||
|         DeviceStatus status; |         DeviceStatus status; | ||||||
|         std::thread thread; |         std::thread thread; | ||||||
|         u64 packet_sequence = 0; |         u64 packet_sequence = 0; | ||||||
|         u8 active; |         u8 active = 0; | ||||||
| 
 | 
 | ||||||
|         // Realtime values
 |         // Realtime values
 | ||||||
|         // motion is initalized with PID values for drift correction on joycons
 |         // motion is initalized with PID values for drift correction on joycons
 | ||||||
| @ -113,8 +113,8 @@ 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(std::size_t client, const std::string& host, u16 port, u8 pad_index, |     void StartCommunication(std::size_t client, const std::string& host, u16 port, | ||||||
|                             u32 client_id); |                             std::size_t pad_index, u32 client_id); | ||||||
|     void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, |     void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, | ||||||
|                             const Common::Vec3<float>& gyro, bool touch); |                             const Common::Vec3<float>& gyro, bool touch); | ||||||
| 
 | 
 | ||||||
| @ -139,7 +139,7 @@ public: | |||||||
|      * @param status_callback Callback for job status updates |      * @param status_callback Callback for job status updates | ||||||
|      * @param data_callback Called when calibration data is ready |      * @param data_callback Called when calibration data is ready | ||||||
|      */ |      */ | ||||||
|     explicit CalibrationConfigurationJob(const std::string& host, u16 port, u8 pad_index, |     explicit CalibrationConfigurationJob(const std::string& host, u16 port, std::size_t pad_index, | ||||||
|                                          u32 client_id, std::function<void(Status)> status_callback, |                                          u32 client_id, std::function<void(Status)> status_callback, | ||||||
|                                          std::function<void(u16, u16, u16, u16)> data_callback); |                                          std::function<void(u16, u16, u16, u16)> data_callback); | ||||||
|     ~CalibrationConfigurationJob(); |     ~CalibrationConfigurationJob(); | ||||||
| @ -149,7 +149,7 @@ private: | |||||||
|     Common::Event complete_event; |     Common::Event complete_event; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id, | void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, u32 client_id, | ||||||
|                        std::function<void()> success_callback, |                        std::function<void()> success_callback, | ||||||
|                        std::function<void()> failure_callback); |                        std::function<void()> failure_callback); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,8 +2,6 @@ | |||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include <atomic> |  | ||||||
| #include <list> |  | ||||||
| #include <mutex> | #include <mutex> | ||||||
| #include <utility> | #include <utility> | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| @ -15,8 +13,8 @@ namespace InputCommon { | |||||||
| 
 | 
 | ||||||
| class UDPMotion final : public Input::MotionDevice { | class UDPMotion final : public Input::MotionDevice { | ||||||
| public: | public: | ||||||
|     UDPMotion(std::string ip_, int port_, int pad_, CemuhookUDP::Client* client_) |     explicit UDPMotion(std::string ip_, int port_, u32 pad_, CemuhookUDP::Client* client_) | ||||||
|         : ip(ip_), port(port_), pad(pad_), client(client_) {} |         : ip(std::move(ip_)), port(port_), pad(pad_), client(client_) {} | ||||||
| 
 | 
 | ||||||
|     Input::MotionStatus GetStatus() const override { |     Input::MotionStatus GetStatus() const override { | ||||||
|         return client->GetPadState(pad).motion_status; |         return client->GetPadState(pad).motion_status; | ||||||
| @ -25,7 +23,7 @@ public: | |||||||
| private: | private: | ||||||
|     const std::string ip; |     const std::string ip; | ||||||
|     const int port; |     const int port; | ||||||
|     const int pad; |     const u32 pad; | ||||||
|     CemuhookUDP::Client* client; |     CemuhookUDP::Client* client; | ||||||
|     mutable std::mutex mutex; |     mutable std::mutex mutex; | ||||||
| }; | }; | ||||||
| @ -40,11 +38,11 @@ UDPMotionFactory::UDPMotionFactory(std::shared_ptr<CemuhookUDP::Client> client_) | |||||||
|  *     - "port": the nth jcpad on the adapter |  *     - "port": the nth jcpad on the adapter | ||||||
|  */ |  */ | ||||||
| std::unique_ptr<Input::MotionDevice> UDPMotionFactory::Create(const Common::ParamPackage& params) { | std::unique_ptr<Input::MotionDevice> UDPMotionFactory::Create(const Common::ParamPackage& params) { | ||||||
|     const std::string ip = params.Get("ip", "127.0.0.1"); |     auto ip = params.Get("ip", "127.0.0.1"); | ||||||
|     const int port = params.Get("port", 26760); |     const auto port = params.Get("port", 26760); | ||||||
|     const int pad = params.Get("pad_index", 0); |     const auto pad = static_cast<u32>(params.Get("pad_index", 0)); | ||||||
| 
 | 
 | ||||||
|     return std::make_unique<UDPMotion>(ip, port, pad, client.get()); |     return std::make_unique<UDPMotion>(std::move(ip), port, pad, client.get()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void UDPMotionFactory::BeginConfiguration() { | void UDPMotionFactory::BeginConfiguration() { | ||||||
| @ -79,7 +77,7 @@ Common::ParamPackage UDPMotionFactory::GetNextInput() { | |||||||
| 
 | 
 | ||||||
| class UDPTouch final : public Input::TouchDevice { | class UDPTouch final : public Input::TouchDevice { | ||||||
| public: | public: | ||||||
|     UDPTouch(std::string ip_, int port_, int pad_, CemuhookUDP::Client* client_) |     explicit UDPTouch(std::string ip_, int port_, u32 pad_, CemuhookUDP::Client* client_) | ||||||
|         : ip(std::move(ip_)), port(port_), pad(pad_), client(client_) {} |         : ip(std::move(ip_)), port(port_), pad(pad_), client(client_) {} | ||||||
| 
 | 
 | ||||||
|     std::tuple<float, float, bool> GetStatus() const override { |     std::tuple<float, float, bool> GetStatus() const override { | ||||||
| @ -89,7 +87,7 @@ public: | |||||||
| private: | private: | ||||||
|     const std::string ip; |     const std::string ip; | ||||||
|     const int port; |     const int port; | ||||||
|     const int pad; |     const u32 pad; | ||||||
|     CemuhookUDP::Client* client; |     CemuhookUDP::Client* client; | ||||||
|     mutable std::mutex mutex; |     mutable std::mutex mutex; | ||||||
| }; | }; | ||||||
| @ -104,11 +102,11 @@ UDPTouchFactory::UDPTouchFactory(std::shared_ptr<CemuhookUDP::Client> client_) | |||||||
|  *     - "port": the nth jcpad on the adapter |  *     - "port": the nth jcpad on the adapter | ||||||
|  */ |  */ | ||||||
| std::unique_ptr<Input::TouchDevice> UDPTouchFactory::Create(const Common::ParamPackage& params) { | std::unique_ptr<Input::TouchDevice> UDPTouchFactory::Create(const Common::ParamPackage& params) { | ||||||
|     const std::string ip = params.Get("ip", "127.0.0.1"); |     auto ip = params.Get("ip", "127.0.0.1"); | ||||||
|     const int port = params.Get("port", 26760); |     const auto port = params.Get("port", 26760); | ||||||
|     const int pad = params.Get("pad_index", 0); |     const auto pad = static_cast<u32>(params.Get("pad_index", 0)); | ||||||
| 
 | 
 | ||||||
|     return std::make_unique<UDPTouch>(ip, port, pad, client.get()); |     return std::make_unique<UDPTouch>(std::move(ip), port, pad, client.get()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void UDPTouchFactory::BeginConfiguration() { | void UDPTouchFactory::BeginConfiguration() { | ||||||
|  | |||||||
| @ -193,7 +193,7 @@ void ConfigureMotionTouch::OnCemuhookUDPTest() { | |||||||
|     udp_test_in_progress = true; |     udp_test_in_progress = true; | ||||||
|     InputCommon::CemuhookUDP::TestCommunication( |     InputCommon::CemuhookUDP::TestCommunication( | ||||||
|         ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()), |         ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()), | ||||||
|         static_cast<u8>(ui->udp_pad_index->currentIndex()), 24872, |         static_cast<u32>(ui->udp_pad_index->currentIndex()), 24872, | ||||||
|         [this] { |         [this] { | ||||||
|             LOG_INFO(Frontend, "UDP input test success"); |             LOG_INFO(Frontend, "UDP input test success"); | ||||||
|             QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true)); |             QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true)); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Lioncash
						Lioncash