Merge pull request #4790 from lioncash/input-common
input_common/CMakeLists: Make some warnings errors
This commit is contained in:
		@@ -20,8 +20,8 @@ struct Rectangle {
 | 
			
		||||
 | 
			
		||||
    constexpr Rectangle() = default;
 | 
			
		||||
 | 
			
		||||
    constexpr Rectangle(T left, T top, T right, T bottom)
 | 
			
		||||
        : left(left), top(top), right(right), bottom(bottom) {}
 | 
			
		||||
    constexpr Rectangle(T left_, T top_, T right_, T bottom_)
 | 
			
		||||
        : left(left_), top(top_), right(right_), bottom(bottom_) {}
 | 
			
		||||
 | 
			
		||||
    [[nodiscard]] T GetWidth() const {
 | 
			
		||||
        if constexpr (std::is_floating_point_v<T>) {
 | 
			
		||||
 
 | 
			
		||||
@@ -87,7 +87,13 @@ public:
 | 
			
		||||
 | 
			
		||||
    template <typename V>
 | 
			
		||||
    [[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>
 | 
			
		||||
@@ -98,7 +104,13 @@ public:
 | 
			
		||||
 | 
			
		||||
    template <typename V>
 | 
			
		||||
    [[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>
 | 
			
		||||
@@ -168,7 +180,10 @@ public:
 | 
			
		||||
 | 
			
		||||
template <typename T, typename V>
 | 
			
		||||
[[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>;
 | 
			
		||||
@@ -237,7 +252,14 @@ public:
 | 
			
		||||
 | 
			
		||||
    template <typename V>
 | 
			
		||||
    [[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>
 | 
			
		||||
@@ -247,7 +269,14 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
    template <typename V>
 | 
			
		||||
    [[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>
 | 
			
		||||
@@ -367,7 +396,11 @@ public:
 | 
			
		||||
 | 
			
		||||
template <typename T, typename V>
 | 
			
		||||
[[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 <>
 | 
			
		||||
@@ -446,7 +479,15 @@ public:
 | 
			
		||||
 | 
			
		||||
    template <typename V>
 | 
			
		||||
    [[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>
 | 
			
		||||
@@ -457,7 +498,15 @@ public:
 | 
			
		||||
 | 
			
		||||
    template <typename V>
 | 
			
		||||
    [[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>
 | 
			
		||||
@@ -582,7 +631,15 @@ public:
 | 
			
		||||
 | 
			
		||||
template <typename T, typename V>
 | 
			
		||||
[[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>;
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,35 @@ add_library(input_common STATIC
 | 
			
		||||
    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)
 | 
			
		||||
    target_sources(input_common PRIVATE
 | 
			
		||||
        sdl/sdl_impl.cpp
 | 
			
		||||
 
 | 
			
		||||
@@ -20,18 +20,22 @@ public:
 | 
			
		||||
        constexpr float SQRT_HALF = 0.707106781f;
 | 
			
		||||
        int x = 0, y = 0;
 | 
			
		||||
 | 
			
		||||
        if (right->GetStatus())
 | 
			
		||||
        if (right->GetStatus()) {
 | 
			
		||||
            ++x;
 | 
			
		||||
        if (left->GetStatus())
 | 
			
		||||
        }
 | 
			
		||||
        if (left->GetStatus()) {
 | 
			
		||||
            --x;
 | 
			
		||||
        if (up->GetStatus())
 | 
			
		||||
        }
 | 
			
		||||
        if (up->GetStatus()) {
 | 
			
		||||
            ++y;
 | 
			
		||||
        if (down->GetStatus())
 | 
			
		||||
        }
 | 
			
		||||
        if (down->GetStatus()) {
 | 
			
		||||
            --y;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
 | 
			
		||||
        return std::make_tuple(x * coef * (y == 0 ? 1.0f : SQRT_HALF),
 | 
			
		||||
                               y * coef * (x == 0 ? 1.0f : SQRT_HALF));
 | 
			
		||||
        const float coef = modifier->GetStatus() ? modifier_scale : 1.0f;
 | 
			
		||||
        return std::make_tuple(static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF),
 | 
			
		||||
                               static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@
 | 
			
		||||
 | 
			
		||||
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{
 | 
			
		||||
    PadButton::PAD_BUTTON_LEFT, PadButton::PAD_BUTTON_RIGHT, PadButton::PAD_BUTTON_DOWN,
 | 
			
		||||
    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,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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() {
 | 
			
		||||
    if (usb_adapter_handle != nullptr) {
 | 
			
		||||
        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) {
 | 
			
		||||
            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) {
 | 
			
		||||
            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) {
 | 
			
		||||
            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];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -100,17 +112,6 @@ GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& ad
 | 
			
		||||
    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() {
 | 
			
		||||
    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];
 | 
			
		||||
            for (u8 e = 0; e < interface->bNumEndpoints; 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;
 | 
			
		||||
                } else {
 | 
			
		||||
                    output_endpoint = endpoint->bEndpointAddress;
 | 
			
		||||
@@ -419,7 +420,7 @@ const std::array<GCState, 4>& Adapter::GetPadState() const {
 | 
			
		||||
    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];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -60,7 +60,7 @@ struct GCPadStatus {
 | 
			
		||||
 | 
			
		||||
struct GCState {
 | 
			
		||||
    std::unordered_map<int, bool> buttons;
 | 
			
		||||
    std::unordered_map<int, u16> axes;
 | 
			
		||||
    std::unordered_map<u32, u16> axes;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class ControllerTypes { None, Wired, Wireless };
 | 
			
		||||
@@ -89,13 +89,11 @@ public:
 | 
			
		||||
    std::array<GCState, 4>& GetPadState();
 | 
			
		||||
    const std::array<GCState, 4>& GetPadState() const;
 | 
			
		||||
 | 
			
		||||
    int GetOriginValue(int port, int axis) const;
 | 
			
		||||
    int GetOriginValue(u32 port, u32 axis) const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    GCPadStatus GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload);
 | 
			
		||||
 | 
			
		||||
    void PadToState(const GCPadStatus& pad, GCState& state);
 | 
			
		||||
 | 
			
		||||
    void Read();
 | 
			
		||||
 | 
			
		||||
    /// Resets status of device connected to port
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ namespace InputCommon {
 | 
			
		||||
 | 
			
		||||
class GCButton final : public Input::ButtonDevice {
 | 
			
		||||
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) {}
 | 
			
		||||
 | 
			
		||||
    ~GCButton() override;
 | 
			
		||||
@@ -28,14 +28,14 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    const int port;
 | 
			
		||||
    const u32 port;
 | 
			
		||||
    const int button;
 | 
			
		||||
    const GCAdapter::Adapter* gcadapter;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class GCAxisButton final : public Input::ButtonDevice {
 | 
			
		||||
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)
 | 
			
		||||
        : port(port_), axis(axis_), threshold(threshold_), trigger_if_greater(trigger_if_greater_),
 | 
			
		||||
          gcadapter(adapter),
 | 
			
		||||
@@ -56,8 +56,8 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    const int port;
 | 
			
		||||
    const int axis;
 | 
			
		||||
    const u32 port;
 | 
			
		||||
    const u32 axis;
 | 
			
		||||
    float threshold;
 | 
			
		||||
    bool trigger_if_greater;
 | 
			
		||||
    const GCAdapter::Adapter* gcadapter;
 | 
			
		||||
@@ -70,8 +70,8 @@ GCButtonFactory::GCButtonFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
 | 
			
		||||
GCButton::~GCButton() = default;
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::ParamPackage& params) {
 | 
			
		||||
    const int button_id = params.Get("button", 0);
 | 
			
		||||
    const int port = params.Get("port", 0);
 | 
			
		||||
    const auto button_id = params.Get("button", 0);
 | 
			
		||||
    const auto port = static_cast<u32>(params.Get("port", 0));
 | 
			
		||||
 | 
			
		||||
    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 {
 | 
			
		||||
public:
 | 
			
		||||
    GCAnalog(int port_, int axis_x_, int axis_y_, float deadzone_,
 | 
			
		||||
             const GCAdapter::Adapter* adapter, float range_)
 | 
			
		||||
    explicit GCAnalog(u32 port_, u32 axis_x_, u32 axis_y_, float deadzone_,
 | 
			
		||||
                      const GCAdapter::Adapter* adapter, float range_)
 | 
			
		||||
        : 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_y(static_cast<float>(adapter->GetOriginValue(port_, axis_y_))),
 | 
			
		||||
          range(range_) {}
 | 
			
		||||
 | 
			
		||||
    float GetAxis(int axis) const {
 | 
			
		||||
    float GetAxis(u32 axis) const {
 | 
			
		||||
        if (gcadapter->DeviceConnected(port)) {
 | 
			
		||||
            std::lock_guard lock{mutex};
 | 
			
		||||
            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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::pair<float, float> GetAnalog(int axis_x, int axis_y) const {
 | 
			
		||||
        float x = GetAxis(axis_x);
 | 
			
		||||
        float y = GetAxis(axis_y);
 | 
			
		||||
    std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const {
 | 
			
		||||
        float x = GetAxis(analog_axis_x);
 | 
			
		||||
        float y = GetAxis(analog_axis_y);
 | 
			
		||||
 | 
			
		||||
        // Make sure the coordinates are in the unit circle,
 | 
			
		||||
        // otherwise normalize it.
 | 
			
		||||
@@ -208,9 +210,9 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    const int port;
 | 
			
		||||
    const int axis_x;
 | 
			
		||||
    const int axis_y;
 | 
			
		||||
    const u32 port;
 | 
			
		||||
    const u32 axis_x;
 | 
			
		||||
    const u32 axis_y;
 | 
			
		||||
    const float deadzone;
 | 
			
		||||
    const GCAdapter::Adapter* gcadapter;
 | 
			
		||||
    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
 | 
			
		||||
 */
 | 
			
		||||
std::unique_ptr<Input::AnalogDevice> GCAnalogFactory::Create(const Common::ParamPackage& params) {
 | 
			
		||||
    const int port = params.Get("port", 0);
 | 
			
		||||
    const int axis_x = params.Get("axis_x", 0);
 | 
			
		||||
    const int axis_y = params.Get("axis_y", 1);
 | 
			
		||||
    const float 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 port = static_cast<u32>(params.Get("port", 0));
 | 
			
		||||
    const auto axis_x = static_cast<u32>(params.Get("axis_x", 0));
 | 
			
		||||
    const auto axis_y = static_cast<u32>(params.Get("axis_y", 1));
 | 
			
		||||
    const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);
 | 
			
		||||
    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);
 | 
			
		||||
}
 | 
			
		||||
@@ -256,7 +258,7 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() {
 | 
			
		||||
    for (std::size_t port = 0; port < queue.size(); ++port) {
 | 
			
		||||
        while (queue[port].Pop(pad)) {
 | 
			
		||||
            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;
 | 
			
		||||
            }
 | 
			
		||||
            // 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) {
 | 
			
		||||
        std::lock_guard guard{mutex};
 | 
			
		||||
        for (const KeyButtonPair& pair : list) {
 | 
			
		||||
            if (pair.key_code == key_code)
 | 
			
		||||
            if (pair.key_code == key_code) {
 | 
			
		||||
                pair.key_button->status.store(pressed);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -73,7 +74,7 @@ KeyButton::~KeyButton() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
    key_button_list->AddKeyButton(key_code, button.get());
 | 
			
		||||
    return button;
 | 
			
		||||
 
 | 
			
		||||
@@ -196,6 +196,10 @@ ButtonMapping InputSubsystem::GetButtonMappingForDevice(const Common::ParamPacka
 | 
			
		||||
    return impl->GetButtonMappingForDevice(device);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MotionMapping InputSubsystem::GetMotionMappingForDevice(const Common::ParamPackage& device) const {
 | 
			
		||||
    return impl->GetMotionMappingForDevice(device);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GCAnalogFactory* InputSubsystem::GetGCAnalogs() {
 | 
			
		||||
    return impl->gcanalog.get();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,11 +18,11 @@ namespace InputCommon {
 | 
			
		||||
// Implementation class of the motion emulation device
 | 
			
		||||
class MotionEmuDevice {
 | 
			
		||||
public:
 | 
			
		||||
    MotionEmuDevice(int update_millisecond, float sensitivity)
 | 
			
		||||
        : update_millisecond(update_millisecond),
 | 
			
		||||
    explicit MotionEmuDevice(int update_millisecond_, float sensitivity_)
 | 
			
		||||
        : update_millisecond(update_millisecond_),
 | 
			
		||||
          update_duration(std::chrono::duration_cast<std::chrono::steady_clock::duration>(
 | 
			
		||||
              std::chrono::milliseconds(update_millisecond))),
 | 
			
		||||
          sensitivity(sensitivity), motion_emu_thread(&MotionEmuDevice::MotionEmuThread, this) {}
 | 
			
		||||
          sensitivity(sensitivity_), motion_emu_thread(&MotionEmuDevice::MotionEmuThread, this) {}
 | 
			
		||||
 | 
			
		||||
    ~MotionEmuDevice() {
 | 
			
		||||
        if (motion_emu_thread.joinable()) {
 | 
			
		||||
@@ -37,16 +37,18 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Tilt(int x, int y) {
 | 
			
		||||
        auto mouse_move = Common::MakeVec(x, y) - mouse_origin;
 | 
			
		||||
        if (is_tilting) {
 | 
			
		||||
            std::lock_guard guard{tilt_mutex};
 | 
			
		||||
            if (mouse_move.x == 0 && mouse_move.y == 0) {
 | 
			
		||||
                tilt_angle = 0;
 | 
			
		||||
            } else {
 | 
			
		||||
                tilt_direction = mouse_move.Cast<float>();
 | 
			
		||||
                tilt_angle =
 | 
			
		||||
                    std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f, Common::PI * 0.5f);
 | 
			
		||||
            }
 | 
			
		||||
        if (!is_tilting) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::lock_guard guard{tilt_mutex};
 | 
			
		||||
        const auto mouse_move = Common::MakeVec(x, y) - mouse_origin;
 | 
			
		||||
        if (mouse_move.x == 0 && mouse_move.y == 0) {
 | 
			
		||||
            tilt_angle = 0;
 | 
			
		||||
        } 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() {
 | 
			
		||||
        auto update_time = std::chrono::steady_clock::now();
 | 
			
		||||
        Common::Quaternion<float> q = Common::MakeQuaternion(Common::Vec3<float>(), 0);
 | 
			
		||||
        Common::Quaternion<float> old_q;
 | 
			
		||||
 | 
			
		||||
        while (!shutdown_event.WaitUntil(update_time)) {
 | 
			
		||||
            update_time += update_duration;
 | 
			
		||||
            old_q = q;
 | 
			
		||||
            const Common::Quaternion<float> old_q = q;
 | 
			
		||||
 | 
			
		||||
            {
 | 
			
		||||
                std::lock_guard guard{tilt_mutex};
 | 
			
		||||
@@ -100,14 +101,14 @@ private:
 | 
			
		||||
                    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
 | 
			
		||||
            auto gravity = Common::MakeVec(0.0f, -1.0f, 0.0f);
 | 
			
		||||
 | 
			
		||||
            // Find the angular rate vector in world space
 | 
			
		||||
            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
 | 
			
		||||
            gravity = QuaternionRotate(inv_q, gravity);
 | 
			
		||||
@@ -136,7 +137,7 @@ private:
 | 
			
		||||
// can forward all the inputs to the implementation only when it is valid.
 | 
			
		||||
class MotionEmuDeviceWrapper : public Input::MotionDevice {
 | 
			
		||||
public:
 | 
			
		||||
    MotionEmuDeviceWrapper(int update_millisecond, float sensitivity) {
 | 
			
		||||
    explicit MotionEmuDeviceWrapper(int update_millisecond, float 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) {
 | 
			
		||||
    int update_period = params.Get("update_period", 100);
 | 
			
		||||
    float sensitivity = params.Get("sensitivity", 0.01f);
 | 
			
		||||
    const int update_period = params.Get("update_period", 100);
 | 
			
		||||
    const float sensitivity = params.Get("sensitivity", 0.01f);
 | 
			
		||||
    auto device_wrapper = std::make_unique<MotionEmuDeviceWrapper>(update_period, sensitivity);
 | 
			
		||||
    // Previously created device is disconnected here. Having two motion devices for 3DS is not
 | 
			
		||||
    // expected.
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ class MotionKey final : public Input::MotionDevice {
 | 
			
		||||
public:
 | 
			
		||||
    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 {
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,7 @@
 | 
			
		||||
 | 
			
		||||
namespace InputCommon {
 | 
			
		||||
 | 
			
		||||
MotionInput::MotionInput(f32 new_kp, f32 new_ki, f32 new_kd)
 | 
			
		||||
    : kp(new_kp), ki(new_ki), kd(new_kd), quat{{0, 0, -1}, 0} {}
 | 
			
		||||
MotionInput::MotionInput(f32 new_kp, f32 new_ki, f32 new_kd) : kp(new_kp), ki(new_ki), kd(new_kd) {}
 | 
			
		||||
 | 
			
		||||
void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) {
 | 
			
		||||
    accel = acceleration;
 | 
			
		||||
@@ -59,7 +58,7 @@ bool MotionInput::IsCalibrated(f32 sensitivity) const {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
@@ -75,7 +74,7 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) {
 | 
			
		||||
    f32 q2 = quat.xyz[0];
 | 
			
		||||
    f32 q3 = quat.xyz[1];
 | 
			
		||||
    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
 | 
			
		||||
    if (sample_period > 0.1f) {
 | 
			
		||||
@@ -203,21 +202,21 @@ Input::MotionStatus MotionInput::GetRandomMotion(int accel_magnitude, int gyro_m
 | 
			
		||||
    std::random_device device;
 | 
			
		||||
    std::mt19937 gen(device());
 | 
			
		||||
    std::uniform_int_distribution<s16> distribution(-1000, 1000);
 | 
			
		||||
    const Common::Vec3f gyroscope = {
 | 
			
		||||
        distribution(gen) * 0.001f,
 | 
			
		||||
        distribution(gen) * 0.001f,
 | 
			
		||||
        distribution(gen) * 0.001f,
 | 
			
		||||
    const Common::Vec3f gyroscope{
 | 
			
		||||
        static_cast<f32>(distribution(gen)) * 0.001f,
 | 
			
		||||
        static_cast<f32>(distribution(gen)) * 0.001f,
 | 
			
		||||
        static_cast<f32>(distribution(gen)) * 0.001f,
 | 
			
		||||
    };
 | 
			
		||||
    const Common::Vec3f accelerometer = {
 | 
			
		||||
        distribution(gen) * 0.001f,
 | 
			
		||||
        distribution(gen) * 0.001f,
 | 
			
		||||
        distribution(gen) * 0.001f,
 | 
			
		||||
    const Common::Vec3f accelerometer{
 | 
			
		||||
        static_cast<f32>(distribution(gen)) * 0.001f,
 | 
			
		||||
        static_cast<f32>(distribution(gen)) * 0.001f,
 | 
			
		||||
        static_cast<f32>(distribution(gen)) * 0.001f,
 | 
			
		||||
    };
 | 
			
		||||
    const Common::Vec3f rotation = {};
 | 
			
		||||
    const std::array<Common::Vec3f, 3> orientation = {
 | 
			
		||||
        Common::Vec3f{1.0f, 0, 0},
 | 
			
		||||
        Common::Vec3f{0, 1.0f, 0},
 | 
			
		||||
        Common::Vec3f{0, 0, 1.0f},
 | 
			
		||||
    constexpr Common::Vec3f rotation;
 | 
			
		||||
    constexpr std::array orientation{
 | 
			
		||||
        Common::Vec3f{1.0f, 0.0f, 0.0f},
 | 
			
		||||
        Common::Vec3f{0.0f, 1.0f, 0.0f},
 | 
			
		||||
        Common::Vec3f{0.0f, 0.0f, 1.0f},
 | 
			
		||||
    };
 | 
			
		||||
    return {accelerometer * accel_magnitude, gyroscope * gyro_magnitude, rotation, orientation};
 | 
			
		||||
}
 | 
			
		||||
@@ -247,9 +246,6 @@ void MotionInput::SetOrientationFromAccelerometer() {
 | 
			
		||||
    const f32 sample_period = 0.015f;
 | 
			
		||||
 | 
			
		||||
    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) {
 | 
			
		||||
        // Short name local variable for readability
 | 
			
		||||
@@ -258,7 +254,7 @@ void MotionInput::SetOrientationFromAccelerometer() {
 | 
			
		||||
        f32 q3 = quat.xyz[1];
 | 
			
		||||
        f32 q4 = quat.xyz[2];
 | 
			
		||||
 | 
			
		||||
        Common::Vec3f rad_gyro = {};
 | 
			
		||||
        Common::Vec3f rad_gyro;
 | 
			
		||||
        const f32 ax = -normal_accel.x;
 | 
			
		||||
        const f32 ay = normal_accel.y;
 | 
			
		||||
        const f32 az = -normal_accel.z;
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ public:
 | 
			
		||||
    MotionInput& operator=(MotionInput&&) = default;
 | 
			
		||||
 | 
			
		||||
    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 SetGyroDrift(const Common::Vec3f& drift);
 | 
			
		||||
    void SetGyroThreshold(f32 threshold);
 | 
			
		||||
@@ -49,16 +49,16 @@ private:
 | 
			
		||||
    void SetOrientationFromAccelerometer();
 | 
			
		||||
 | 
			
		||||
    // PID constants
 | 
			
		||||
    const f32 kp;
 | 
			
		||||
    const f32 ki;
 | 
			
		||||
    const f32 kd;
 | 
			
		||||
    f32 kp;
 | 
			
		||||
    f32 ki;
 | 
			
		||||
    f32 kd;
 | 
			
		||||
 | 
			
		||||
    // PID errors
 | 
			
		||||
    Common::Vec3f real_error;
 | 
			
		||||
    Common::Vec3f integral_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 accel;
 | 
			
		||||
    Common::Vec3f gyro;
 | 
			
		||||
 
 | 
			
		||||
@@ -56,9 +56,9 @@ static int SDLEventWatcher(void* user_data, SDL_Event* event) {
 | 
			
		||||
class SDLJoystick {
 | 
			
		||||
public:
 | 
			
		||||
    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},
 | 
			
		||||
          sdl_controller{gamecontroller, &SDL_GameControllerClose} {}
 | 
			
		||||
          sdl_controller{game_controller, &SDL_GameControllerClose} {}
 | 
			
		||||
 | 
			
		||||
    void SetButton(int button, bool value) {
 | 
			
		||||
        std::lock_guard lock{mutex};
 | 
			
		||||
@@ -77,10 +77,10 @@ public:
 | 
			
		||||
 | 
			
		||||
    float GetAxis(int axis, float range) const {
 | 
			
		||||
        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_high = static_cast<u16>(amp_high * 0xFFFF);
 | 
			
		||||
        // Lower drastically the number of state changes
 | 
			
		||||
@@ -124,7 +124,7 @@ public:
 | 
			
		||||
        return std::make_tuple(x, y);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const InputCommon::MotionInput& GetMotion() const {
 | 
			
		||||
    const MotionInput& GetMotion() const {
 | 
			
		||||
        return motion;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -172,15 +172,15 @@ private:
 | 
			
		||||
    } state;
 | 
			
		||||
    std::string guid;
 | 
			
		||||
    int port;
 | 
			
		||||
    u16 last_state_rumble_high;
 | 
			
		||||
    u16 last_state_rumble_low;
 | 
			
		||||
    u16 last_state_rumble_high = 0;
 | 
			
		||||
    u16 last_state_rumble_low = 0;
 | 
			
		||||
    std::chrono::time_point<std::chrono::system_clock> last_vibration;
 | 
			
		||||
    std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
 | 
			
		||||
    std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
 | 
			
		||||
    mutable std::mutex mutex;
 | 
			
		||||
 | 
			
		||||
    // motion is initalized without PID values as motion input is not aviable for SDL2
 | 
			
		||||
    InputCommon::MotionInput motion{0.0f, 0.0f, 0.0f};
 | 
			
		||||
    // Motion is initialized without PID values as motion input is not aviable for SDL2
 | 
			
		||||
    MotionInput motion{0.0f, 0.0f, 0.0f};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
            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);
 | 
			
		||||
    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();
 | 
			
		||||
                         });
 | 
			
		||||
        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
 | 
			
		||||
            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...
 | 
			
		||||
        const auto nullptr_it = std::find_if(map_it->second.begin(), map_it->second.end(),
 | 
			
		||||
                                             [](const std::shared_ptr<SDLJoystick>& joystick) {
 | 
			
		||||
                                                 return !joystick->GetSDLJoystick();
 | 
			
		||||
                                                 return joystick->GetSDLJoystick() == nullptr;
 | 
			
		||||
                                             });
 | 
			
		||||
        if (nullptr_it != map_it->second.end()) {
 | 
			
		||||
            // ... and map it
 | 
			
		||||
@@ -273,22 +273,21 @@ void SDLState::InitJoystick(int joystick_index) {
 | 
			
		||||
void SDLState::CloseJoystick(SDL_Joystick* 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};
 | 
			
		||||
        // 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_it =
 | 
			
		||||
            std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),
 | 
			
		||||
                         [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) {
 | 
			
		||||
                             return joystick->GetSDLJoystick() == sdl_joystick;
 | 
			
		||||
                         });
 | 
			
		||||
        joystick = *joystick_it;
 | 
			
		||||
        const auto joystick_it = std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),
 | 
			
		||||
                                              [&sdl_joystick](const auto& joystick) {
 | 
			
		||||
                                                  return joystick->GetSDLJoystick() == sdl_joystick;
 | 
			
		||||
                                              });
 | 
			
		||||
        found_joystick = *joystick_it;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Destruct SDL_Joystick outside the lock guard because SDL can internally call the
 | 
			
		||||
    // event callback which locks the mutex again.
 | 
			
		||||
    joystick->SetSDLJoystick(nullptr, nullptr);
 | 
			
		||||
    found_joystick->SetSDLJoystick(nullptr, nullptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDLState::HandleGameControllerEvent(const SDL_Event& event) {
 | 
			
		||||
@@ -392,8 +391,8 @@ private:
 | 
			
		||||
 | 
			
		||||
class SDLAnalog final : public Input::AnalogDevice {
 | 
			
		||||
public:
 | 
			
		||||
    SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_, float deadzone_,
 | 
			
		||||
              float range_)
 | 
			
		||||
    explicit SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_,
 | 
			
		||||
                       float deadzone_, float range_)
 | 
			
		||||
        : joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_),
 | 
			
		||||
          range(range_) {}
 | 
			
		||||
 | 
			
		||||
@@ -672,13 +671,13 @@ SDLState::SDLState() {
 | 
			
		||||
    RegisterFactory<ButtonDevice>("sdl", button_factory);
 | 
			
		||||
    RegisterFactory<MotionDevice>("sdl", motion_factory);
 | 
			
		||||
 | 
			
		||||
    // If the frontend is going to manage the event loop, then we dont start one here
 | 
			
		||||
    start_thread = !SDL_WasInit(SDL_INIT_JOYSTICK);
 | 
			
		||||
    // If the frontend is going to manage the event loop, then we don't start one here
 | 
			
		||||
    start_thread = SDL_WasInit(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());
 | 
			
		||||
        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) {
 | 
			
		||||
        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;
 | 
			
		||||
    for (const auto& [key, value] : joystick_map) {
 | 
			
		||||
        for (const auto& joystick : value) {
 | 
			
		||||
            auto joy = joystick->GetSDLJoystick();
 | 
			
		||||
            if (auto controller = joystick->GetSDLGameController()) {
 | 
			
		||||
            auto* joy = joystick->GetSDLJoystick();
 | 
			
		||||
            if (auto* controller = joystick->GetSDLGameController()) {
 | 
			
		||||
                std::string name =
 | 
			
		||||
                    fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort());
 | 
			
		||||
                devices.emplace_back(Common::ParamPackage{
 | 
			
		||||
@@ -748,7 +747,7 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
    Common::ParamPackage params({{"engine", "sdl"}});
 | 
			
		||||
    params.Set("port", port);
 | 
			
		||||
@@ -764,7 +763,7 @@ Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid
 | 
			
		||||
    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"}});
 | 
			
		||||
    params.Set("port", port);
 | 
			
		||||
    params.Set("guid", std::move(guid));
 | 
			
		||||
@@ -772,7 +771,7 @@ Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid
 | 
			
		||||
    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"}});
 | 
			
		||||
 | 
			
		||||
    params.Set("port", port);
 | 
			
		||||
@@ -802,17 +801,19 @@ Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Eve
 | 
			
		||||
    case SDL_JOYAXISMOTION: {
 | 
			
		||||
        const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
 | 
			
		||||
        return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
 | 
			
		||||
                                                event.jaxis.axis, event.jaxis.value);
 | 
			
		||||
                                                static_cast<s32>(event.jaxis.axis),
 | 
			
		||||
                                                event.jaxis.value);
 | 
			
		||||
    }
 | 
			
		||||
    case SDL_JOYBUTTONUP: {
 | 
			
		||||
        const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which);
 | 
			
		||||
        return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
 | 
			
		||||
                                                event.jbutton.button);
 | 
			
		||||
                                                static_cast<s32>(event.jbutton.button));
 | 
			
		||||
    }
 | 
			
		||||
    case SDL_JOYHATMOTION: {
 | 
			
		||||
        const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which);
 | 
			
		||||
        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 {};
 | 
			
		||||
@@ -823,17 +824,19 @@ Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Eve
 | 
			
		||||
    case SDL_JOYAXISMOTION: {
 | 
			
		||||
        const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
 | 
			
		||||
        return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
 | 
			
		||||
                                                event.jaxis.axis, event.jaxis.value);
 | 
			
		||||
                                                static_cast<s32>(event.jaxis.axis),
 | 
			
		||||
                                                event.jaxis.value);
 | 
			
		||||
    }
 | 
			
		||||
    case SDL_JOYBUTTONUP: {
 | 
			
		||||
        const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which);
 | 
			
		||||
        return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
 | 
			
		||||
                                                event.jbutton.button);
 | 
			
		||||
                                                static_cast<s32>(event.jbutton.button));
 | 
			
		||||
    }
 | 
			
		||||
    case SDL_JOYHATMOTION: {
 | 
			
		||||
        const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which);
 | 
			
		||||
        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 {};
 | 
			
		||||
@@ -1062,7 +1065,7 @@ public:
 | 
			
		||||
            if (event.type == SDL_JOYAXISMOTION) {
 | 
			
		||||
                const auto axis = event.jaxis.axis;
 | 
			
		||||
                const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
 | 
			
		||||
                const auto controller = joystick->GetSDLGameController();
 | 
			
		||||
                auto* const controller = joystick->GetSDLGameController();
 | 
			
		||||
                if (controller) {
 | 
			
		||||
                    const auto axis_left_x =
 | 
			
		||||
                        SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX)
 | 
			
		||||
 
 | 
			
		||||
@@ -11,9 +11,11 @@ namespace InputCommon {
 | 
			
		||||
class TouchFromButtonDevice final : public Input::TouchDevice {
 | 
			
		||||
public:
 | 
			
		||||
    TouchFromButtonDevice() {
 | 
			
		||||
        for (const auto& config_entry :
 | 
			
		||||
             Settings::values.touch_from_button_maps[Settings::values.touch_from_button_map_index]
 | 
			
		||||
                 .buttons) {
 | 
			
		||||
        const auto button_index =
 | 
			
		||||
            static_cast<std::size_t>(Settings::values.touch_from_button_map_index);
 | 
			
		||||
        const auto& buttons = Settings::values.touch_from_button_maps[button_index].buttons;
 | 
			
		||||
 | 
			
		||||
        for (const auto& config_entry : buttons) {
 | 
			
		||||
            const Common::ParamPackage package{config_entry};
 | 
			
		||||
            map.emplace_back(
 | 
			
		||||
                Input::CreateDevice<Input::ButtonDevice>(config_entry),
 | 
			
		||||
 
 | 
			
		||||
@@ -26,11 +26,11 @@ class Socket {
 | 
			
		||||
public:
 | 
			
		||||
    using clock = std::chrono::system_clock;
 | 
			
		||||
 | 
			
		||||
    explicit Socket(const std::string& host, u16 port, u8 pad_index, u32 client_id,
 | 
			
		||||
                    SocketCallback callback)
 | 
			
		||||
        : callback(std::move(callback)), timer(io_service),
 | 
			
		||||
          socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(client_id),
 | 
			
		||||
          pad_index(pad_index) {
 | 
			
		||||
    explicit Socket(const std::string& host, u16 port, std::size_t pad_index_, u32 client_id_,
 | 
			
		||||
                    SocketCallback callback_)
 | 
			
		||||
        : callback(std::move(callback_)), timer(io_service),
 | 
			
		||||
          socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(client_id_),
 | 
			
		||||
          pad_index(pad_index_) {
 | 
			
		||||
        boost::system::error_code ec{};
 | 
			
		||||
        auto ipv4 = boost::asio::ip::make_address_v4(host, ec);
 | 
			
		||||
        if (ec.value() != boost::system::errc::success) {
 | 
			
		||||
@@ -93,13 +93,17 @@ private:
 | 
			
		||||
    void HandleSend(const boost::system::error_code& error) {
 | 
			
		||||
        boost::system::error_code _ignored{};
 | 
			
		||||
        // 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);
 | 
			
		||||
        std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE);
 | 
			
		||||
        socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored);
 | 
			
		||||
 | 
			
		||||
        // 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);
 | 
			
		||||
        std::memcpy(send_buffer2.data(), &pad_message, PAD_DATA_SIZE);
 | 
			
		||||
        socket.send_to(boost::asio::buffer(send_buffer2), send_endpoint, {}, _ignored);
 | 
			
		||||
@@ -112,7 +116,7 @@ private:
 | 
			
		||||
    udp::socket socket;
 | 
			
		||||
 | 
			
		||||
    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 PAD_DATA_SIZE = sizeof(Message<Request::PadData>);
 | 
			
		||||
@@ -133,7 +137,7 @@ static void SocketLoop(Socket* socket) {
 | 
			
		||||
Client::Client() {
 | 
			
		||||
    LOG_INFO(Input, "Udp Initialization started");
 | 
			
		||||
    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,
 | 
			
		||||
                           Settings::values.udp_input_port, pad, 24872);
 | 
			
		||||
        // Set motion parameters
 | 
			
		||||
@@ -166,9 +170,9 @@ std::vector<Common::ParamPackage> Client::GetInputDevices() const {
 | 
			
		||||
bool Client::DeviceConnected(std::size_t pad) const {
 | 
			
		||||
    // Use last timestamp to detect if the socket has stopped sending data
 | 
			
		||||
    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)
 | 
			
		||||
            .count();
 | 
			
		||||
            .count());
 | 
			
		||||
    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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
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
 | 
			
		||||
    std::size_t client = pad_index;
 | 
			
		||||
    const std::size_t client = pad_index;
 | 
			
		||||
    clients[client].socket->Stop();
 | 
			
		||||
    clients[client].thread.join();
 | 
			
		||||
    StartCommunication(client, host, port, pad_index, client_id);
 | 
			
		||||
@@ -194,8 +198,8 @@ void Client::OnPortInfo(Response::PortInfo data) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Client::OnPadData(Response::PadData data) {
 | 
			
		||||
    // client number must be determined from host / port and pad index
 | 
			
		||||
    std::size_t client = data.info.id;
 | 
			
		||||
    // Client number must be determined from host / port and pad index
 | 
			
		||||
    const std::size_t client = data.info.id;
 | 
			
		||||
    LOG_TRACE(Input, "PadData packet received");
 | 
			
		||||
    if (data.packet_counter == clients[client].packet_sequence) {
 | 
			
		||||
        LOG_WARNING(
 | 
			
		||||
@@ -207,11 +211,12 @@ void Client::OnPadData(Response::PadData data) {
 | 
			
		||||
    clients[client].active = data.info.is_pad_active;
 | 
			
		||||
    clients[client].packet_sequence = data.packet_counter;
 | 
			
		||||
    const auto now = std::chrono::system_clock::now();
 | 
			
		||||
    u64 time_difference = std::chrono::duration_cast<std::chrono::microseconds>(
 | 
			
		||||
                              now - clients[client].last_motion_update)
 | 
			
		||||
                              .count();
 | 
			
		||||
    const auto time_difference =
 | 
			
		||||
        static_cast<u64>(std::chrono::duration_cast<std::chrono::microseconds>(
 | 
			
		||||
                             now - clients[client].last_motion_update)
 | 
			
		||||
                             .count());
 | 
			
		||||
    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});
 | 
			
		||||
    // Gyroscope values are not it the correct scale from better joy.
 | 
			
		||||
    // 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 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);
 | 
			
		||||
            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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -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,
 | 
			
		||||
                                u32 client_id) {
 | 
			
		||||
void Client::StartCommunication(std::size_t client, const std::string& host, u16 port,
 | 
			
		||||
                                std::size_t pad_index, u32 client_id) {
 | 
			
		||||
    SocketCallback callback{[this](Response::Version version) { OnVersion(version); },
 | 
			
		||||
                            [this](Response::PortInfo info) { OnPortInfo(info); },
 | 
			
		||||
                            [this](Response::PadData data) { OnPadData(data); }};
 | 
			
		||||
@@ -264,9 +271,9 @@ void Client::StartCommunication(std::size_t client, const std::string& host, u16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Client::Reset() {
 | 
			
		||||
    for (std::size_t client = 0; client < clients.size(); client++) {
 | 
			
		||||
        clients[client].socket->Stop();
 | 
			
		||||
        clients[client].thread.join();
 | 
			
		||||
    for (auto& client : clients) {
 | 
			
		||||
        client.socket->Stop();
 | 
			
		||||
        client.thread.join();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -325,7 +332,7 @@ const std::array<Common::SPSCQueue<UDPPadStatus>, 4>& Client::GetPadQueue() cons
 | 
			
		||||
    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()> failure_callback) {
 | 
			
		||||
    std::thread([=] {
 | 
			
		||||
@@ -346,7 +353,7 @@ void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 clie
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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(u16, u16, u16, u16)> data_callback) {
 | 
			
		||||
 | 
			
		||||
@@ -366,7 +373,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
 | 
			
		||||
                                        current_status = Status::Ready;
 | 
			
		||||
                                        status_callback(current_status);
 | 
			
		||||
                                    }
 | 
			
		||||
                                    if (!data.touch_1.is_active) {
 | 
			
		||||
                                    if (data.touch_1.is_active == 0) {
 | 
			
		||||
                                        return;
 | 
			
		||||
                                    }
 | 
			
		||||
                                    LOG_DEBUG(Input, "Current touch: {} {}", data.touch_1.x,
 | 
			
		||||
 
 | 
			
		||||
@@ -84,8 +84,8 @@ public:
 | 
			
		||||
 | 
			
		||||
    bool DeviceConnected(std::size_t pad) const;
 | 
			
		||||
    void ReloadUDPClient();
 | 
			
		||||
    void ReloadSocket(const std::string& host = "127.0.0.1", u16 port = 26760, u8 pad_index = 0,
 | 
			
		||||
                      u32 client_id = 24872);
 | 
			
		||||
    void ReloadSocket(const std::string& host = "127.0.0.1", u16 port = 26760,
 | 
			
		||||
                      std::size_t pad_index = 0, u32 client_id = 24872);
 | 
			
		||||
 | 
			
		||||
    std::array<Common::SPSCQueue<UDPPadStatus>, 4>& GetPadQueue();
 | 
			
		||||
    const std::array<Common::SPSCQueue<UDPPadStatus>, 4>& GetPadQueue() const;
 | 
			
		||||
@@ -99,7 +99,7 @@ private:
 | 
			
		||||
        DeviceStatus status;
 | 
			
		||||
        std::thread thread;
 | 
			
		||||
        u64 packet_sequence = 0;
 | 
			
		||||
        u8 active;
 | 
			
		||||
        u8 active = 0;
 | 
			
		||||
 | 
			
		||||
        // Realtime values
 | 
			
		||||
        // motion is initalized with PID values for drift correction on joycons
 | 
			
		||||
@@ -113,8 +113,8 @@ private:
 | 
			
		||||
    void OnVersion(Response::Version);
 | 
			
		||||
    void OnPortInfo(Response::PortInfo);
 | 
			
		||||
    void OnPadData(Response::PadData);
 | 
			
		||||
    void StartCommunication(std::size_t client, const std::string& host, u16 port, u8 pad_index,
 | 
			
		||||
                            u32 client_id);
 | 
			
		||||
    void StartCommunication(std::size_t client, const std::string& host, u16 port,
 | 
			
		||||
                            std::size_t pad_index, u32 client_id);
 | 
			
		||||
    void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc,
 | 
			
		||||
                            const Common::Vec3<float>& gyro, bool touch);
 | 
			
		||||
 | 
			
		||||
@@ -139,7 +139,7 @@ public:
 | 
			
		||||
     * @param status_callback Callback for job status updates
 | 
			
		||||
     * @param data_callback Called when calibration data is ready
 | 
			
		||||
     */
 | 
			
		||||
    explicit CalibrationConfigurationJob(const std::string& host, u16 port, u8 pad_index,
 | 
			
		||||
    explicit CalibrationConfigurationJob(const std::string& host, u16 port, std::size_t pad_index,
 | 
			
		||||
                                         u32 client_id, std::function<void(Status)> status_callback,
 | 
			
		||||
                                         std::function<void(u16, u16, u16, u16)> data_callback);
 | 
			
		||||
    ~CalibrationConfigurationJob();
 | 
			
		||||
@@ -149,7 +149,7 @@ private:
 | 
			
		||||
    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()> failure_callback);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,8 +2,6 @@
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include "common/assert.h"
 | 
			
		||||
@@ -15,8 +13,8 @@ namespace InputCommon {
 | 
			
		||||
 | 
			
		||||
class UDPMotion final : public Input::MotionDevice {
 | 
			
		||||
public:
 | 
			
		||||
    UDPMotion(std::string ip_, int port_, int pad_, CemuhookUDP::Client* client_)
 | 
			
		||||
        : ip(ip_), port(port_), pad(pad_), client(client_) {}
 | 
			
		||||
    explicit UDPMotion(std::string ip_, int port_, u32 pad_, CemuhookUDP::Client* client_)
 | 
			
		||||
        : ip(std::move(ip_)), port(port_), pad(pad_), client(client_) {}
 | 
			
		||||
 | 
			
		||||
    Input::MotionStatus GetStatus() const override {
 | 
			
		||||
        return client->GetPadState(pad).motion_status;
 | 
			
		||||
@@ -25,7 +23,7 @@ public:
 | 
			
		||||
private:
 | 
			
		||||
    const std::string ip;
 | 
			
		||||
    const int port;
 | 
			
		||||
    const int pad;
 | 
			
		||||
    const u32 pad;
 | 
			
		||||
    CemuhookUDP::Client* client;
 | 
			
		||||
    mutable std::mutex mutex;
 | 
			
		||||
};
 | 
			
		||||
@@ -40,11 +38,11 @@ UDPMotionFactory::UDPMotionFactory(std::shared_ptr<CemuhookUDP::Client> client_)
 | 
			
		||||
 *     - "port": the nth jcpad on the adapter
 | 
			
		||||
 */
 | 
			
		||||
std::unique_ptr<Input::MotionDevice> UDPMotionFactory::Create(const Common::ParamPackage& params) {
 | 
			
		||||
    const std::string ip = params.Get("ip", "127.0.0.1");
 | 
			
		||||
    const int port = params.Get("port", 26760);
 | 
			
		||||
    const int pad = params.Get("pad_index", 0);
 | 
			
		||||
    auto ip = params.Get("ip", "127.0.0.1");
 | 
			
		||||
    const auto port = params.Get("port", 26760);
 | 
			
		||||
    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() {
 | 
			
		||||
@@ -79,7 +77,7 @@ Common::ParamPackage UDPMotionFactory::GetNextInput() {
 | 
			
		||||
 | 
			
		||||
class UDPTouch final : public Input::TouchDevice {
 | 
			
		||||
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_) {}
 | 
			
		||||
 | 
			
		||||
    std::tuple<float, float, bool> GetStatus() const override {
 | 
			
		||||
@@ -89,7 +87,7 @@ public:
 | 
			
		||||
private:
 | 
			
		||||
    const std::string ip;
 | 
			
		||||
    const int port;
 | 
			
		||||
    const int pad;
 | 
			
		||||
    const u32 pad;
 | 
			
		||||
    CemuhookUDP::Client* client;
 | 
			
		||||
    mutable std::mutex mutex;
 | 
			
		||||
};
 | 
			
		||||
@@ -104,11 +102,11 @@ UDPTouchFactory::UDPTouchFactory(std::shared_ptr<CemuhookUDP::Client> client_)
 | 
			
		||||
 *     - "port": the nth jcpad on the adapter
 | 
			
		||||
 */
 | 
			
		||||
std::unique_ptr<Input::TouchDevice> UDPTouchFactory::Create(const Common::ParamPackage& params) {
 | 
			
		||||
    const std::string ip = params.Get("ip", "127.0.0.1");
 | 
			
		||||
    const int port = params.Get("port", 26760);
 | 
			
		||||
    const int pad = params.Get("pad_index", 0);
 | 
			
		||||
    auto ip = params.Get("ip", "127.0.0.1");
 | 
			
		||||
    const auto port = params.Get("port", 26760);
 | 
			
		||||
    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() {
 | 
			
		||||
 
 | 
			
		||||
@@ -193,7 +193,7 @@ void ConfigureMotionTouch::OnCemuhookUDPTest() {
 | 
			
		||||
    udp_test_in_progress = true;
 | 
			
		||||
    InputCommon::CemuhookUDP::TestCommunication(
 | 
			
		||||
        ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()),
 | 
			
		||||
        static_cast<u8>(ui->udp_pad_index->currentIndex()), 24872,
 | 
			
		||||
        static_cast<u32>(ui->udp_pad_index->currentIndex()), 24872,
 | 
			
		||||
        [this] {
 | 
			
		||||
            LOG_INFO(Frontend, "UDP input test success");
 | 
			
		||||
            QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true));
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user