Input: improve evdev and mmjoy stick input

This commit is contained in:
Unknown 2017-12-01 10:16:48 +01:00 committed by Ani
parent 7165001b68
commit 2ec4f66427
3 changed files with 26 additions and 55 deletions

View File

@ -408,6 +408,14 @@ protected:
return 255.0f * val; return 255.0f * val;
}; };
// Get new scaled value between -255 and 255 based on its minimum and maximum
float ScaleStickInput2(s32 raw_value, int minimum, int maximum)
{
// value based on max range converted to [0, 1]
float val = float(Clamp(raw_value, minimum, maximum) - minimum) / float(abs(maximum) + abs(minimum));
return (510.0f * val) - 255.0f;
};
// normalizes a directed input, meaning it will correspond to a single "button" and not an axis with two directions // normalizes a directed input, meaning it will correspond to a single "button" and not an axis with two directions
// the input values must lie in 0+ // the input values must lie in 0+
u16 NormalizeDirectedInput(u16 raw_value, float threshold, float maximum) u16 NormalizeDirectedInput(u16 raw_value, float threshold, float maximum)
@ -505,12 +513,6 @@ protected:
return static_cast<u16>((value + 1.0)*(255.0 / 2.0)); return static_cast<u16>((value + 1.0)*(255.0 / 2.0));
}; };
// input has to be [-1,1]. result will be [0,255]
float ConvertAxisF(float value)
{
return (value + 1.0f) * (255.0f / 2.0f);
};
// The DS3, (and i think xbox controllers) give a 'square-ish' type response, so that the corners will give (almost)max x/y instead of the ~30x30 from a perfect circle // The DS3, (and i think xbox controllers) give a 'square-ish' type response, so that the corners will give (almost)max x/y instead of the ~30x30 from a perfect circle
// using a simple scale/sensitivity increase would *work* although it eats a chunk of our usable range in exchange // using a simple scale/sensitivity increase would *work* although it eats a chunk of our usable range in exchange
// this might be the best for now, in practice it seems to push the corners to max of 20x20, with a squircle_factor of 8000 // this might be the best for now, in practice it seems to push the corners to max of 20x20, with a squircle_factor of 8000

View File

@ -187,27 +187,20 @@ std::unordered_map<u64, std::pair<u16, bool>> evdev_joystick_handler::GetButtonV
if (libevdev_fetch_event_value(dev, EV_ABS, code, &val) == 0) if (libevdev_fetch_event_value(dev, EV_ABS, code, &val) == 0)
continue; continue;
float fvalue = ScaleStickInput(val, libevdev_get_abs_minimum(dev, code), libevdev_get_abs_maximum(dev, code));
// Triggers should be ABS_Z and ABS_RZ and do not need handling of negative values // Triggers should be ABS_Z and ABS_RZ and do not need handling of negative values
if (code == ABS_Z || code == ABS_RZ) if (code == ABS_Z || code == ABS_RZ)
{ {
float fvalue = ScaleStickInput(val, libevdev_get_abs_minimum(dev, code), libevdev_get_abs_maximum(dev, code));
button_values.emplace(code, std::make_pair<u16, bool>(static_cast<u16>(fvalue), false)); button_values.emplace(code, std::make_pair<u16, bool>(static_cast<u16>(fvalue), false));
continue; continue;
} }
bool is_negative = fvalue <= 127.5; float fvalue = ScaleStickInput2(val, libevdev_get_abs_minimum(dev, code), libevdev_get_abs_maximum(dev, code));
if (is_negative) if (fvalue < 0)
{ button_values.emplace(code, std::make_pair<u16, bool>(static_cast<u16>(std::abs(fvalue)), true));
u16 value = Clamp0To255((127.5f - fvalue) * 2.0f);
button_values.emplace(code, std::make_pair<u16, bool>(static_cast<u16>(value), true));
}
else else
{ button_values.emplace(code, std::make_pair<u16, bool>(static_cast<u16>(fvalue), false));
u16 value = Clamp0To255((fvalue - 127.5f) * 2.0f);
button_values.emplace(code, std::make_pair<u16, bool>(static_cast<u16>(value), false));
}
} }
return button_values; return button_values;
@ -418,21 +411,16 @@ int evdev_joystick_handler::GetButtonInfo(const input_event& evt, libevdev* dev,
} }
case EV_ABS: case EV_ABS:
{ {
float fvalue = ScaleStickInput(val, libevdev_get_abs_minimum(dev, code), libevdev_get_abs_maximum(dev, code));
// Triggers should be ABS_Z and ABS_RZ and do not need handling of negative values // Triggers should be ABS_Z and ABS_RZ and do not need handling of negative values
if (code == ABS_Z || code == ABS_RZ) if (code == ABS_Z || code == ABS_RZ)
{ {
value = static_cast<u16>(fvalue); value = static_cast<u16>(ScaleStickInput(val, libevdev_get_abs_minimum(dev, code), libevdev_get_abs_maximum(dev, code)));
return code; return code;
} }
is_negative = fvalue <= 127.5; float fvalue = ScaleStickInput2(val, libevdev_get_abs_minimum(dev, code), libevdev_get_abs_maximum(dev, code));
is_negative = fvalue < 0;
if (is_negative) value = static_cast<u16>(std::abs(fvalue));
value = Clamp0To255((127.5f - fvalue) * 2.0f);
else
value = Clamp0To255((fvalue - 127.5f) * 2.0f);
return code; return code;
} }

View File

@ -2,18 +2,6 @@
#ifdef _WIN32 #ifdef _WIN32
#include "mm_joystick_handler.h" #include "mm_joystick_handler.h"
namespace
{
const DWORD THREAD_SLEEP = 10;
const DWORD THREAD_SLEEP_INACTIVE = 100;
const DWORD THREAD_TIMEOUT = 1000;
inline u16 ConvertAxis(DWORD value)
{
return static_cast<u16>((value) >> 8);
}
}
mm_joystick_handler::mm_joystick_handler() : is_init(false) mm_joystick_handler::mm_joystick_handler() : is_init(false)
{ {
// Define border values // Define border values
@ -475,23 +463,21 @@ std::unordered_map<u64, u16> mm_joystick_handler::GetButtonValues(const JOYINFOE
{ {
auto emplacePOVs = [&](float val, u64 pov_neg, u64 pov_pos) auto emplacePOVs = [&](float val, u64 pov_neg, u64 pov_pos)
{ {
if (val <= 127.5) if (val < 0)
{ {
val = Clamp0To255((127.5f - val) * 2.0f); button_values.emplace(pov_neg, static_cast<u16>(std::abs(val)));
button_values.emplace(pov_neg, val);
button_values.emplace(pov_pos, 0); button_values.emplace(pov_pos, 0);
} }
else else
{ {
val = Clamp0To255((val - 127.5f) * 2.0f);
button_values.emplace(pov_neg, 0); button_values.emplace(pov_neg, 0);
button_values.emplace(pov_pos, val); button_values.emplace(pov_pos, static_cast<u16>(val));
} }
}; };
float rad = static_cast<float>(js_info.dwPOV / 100 * acos(-1) / 180); float rad = static_cast<float>(js_info.dwPOV / 100 * acos(-1) / 180);
emplacePOVs(ConvertAxisF(std::cosf(rad)), JOY_POVBACKWARD, JOY_POVFORWARD); emplacePOVs(std::cosf(rad) * 255.0f, JOY_POVBACKWARD, JOY_POVFORWARD);
emplacePOVs(ConvertAxisF(std::sinf(rad)), JOY_POVLEFT, JOY_POVRIGHT); emplacePOVs(std::sinf(rad) * 255.0f, JOY_POVLEFT, JOY_POVRIGHT);
} }
} }
else if (js_caps.wCaps & JOYCAPS_POV4DIR) else if (js_caps.wCaps & JOYCAPS_POV4DIR)
@ -514,20 +500,15 @@ std::unordered_map<u64, u16> mm_joystick_handler::GetButtonValues(const JOYINFOE
auto add_axis_value = [&](DWORD axis, UINT min, UINT max, u64 pos, u64 neg) auto add_axis_value = [&](DWORD axis, UINT min, UINT max, u64 pos, u64 neg)
{ {
u16 value = 0; float val = ScaleStickInput2(axis, min, max);
float fvalue = ScaleStickInput(axis, min, max); if (val < 0)
bool is_negative = fvalue <= 127.5;
if (is_negative)
{ {
value = Clamp0To255((127.5f - fvalue) * 2.0f);
button_values.emplace(pos, 0); button_values.emplace(pos, 0);
button_values.emplace(neg, value); button_values.emplace(neg, static_cast<u16>(std::abs(val)));
} }
else else
{ {
value = Clamp0To255((fvalue - 127.5f) * 2.0f); button_values.emplace(pos, static_cast<u16>(val));
button_values.emplace(pos, value);
button_values.emplace(neg, 0); button_values.emplace(neg, 0);
} }
}; };