input_common/CMakeLists: Make some warnings errors

Makes the input_common code warnings consistent with the rest of the
codebase.
merge-requests/60/head
Lioncash 2020-10-14 02:51:14 +07:00
parent ca416a0fb8
commit 046c0c91a3
19 changed files with 306 additions and 203 deletions

@ -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,10 +49,11 @@ 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);
} }
} }
}
void ChangeAllKeyStatus(bool pressed) { void ChangeAllKeyStatus(bool pressed) {
std::lock_guard guard{mutex}; std::lock_guard guard{mutex};
@ -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,9 +37,12 @@ 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}; 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) { if (mouse_move.x == 0 && mouse_move.y == 0) {
tilt_angle = 0; tilt_angle = 0;
} else { } else {
@ -48,7 +51,6 @@ public:
std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f, Common::PI * 0.5f); std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f, Common::PI * 0.5f);
} }
} }
}
void EndTilt() { void EndTilt() {
std::lock_guard guard{tilt_mutex}; std::lock_guard guard{tilt_mutex};
@ -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;
}); });
joystick = *joystick_it; found_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 =
static_cast<u64>(std::chrono::duration_cast<std::chrono::microseconds>(
now - clients[client].last_motion_update) now - clients[client].last_motion_update)
.count(); .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));