InputManager: Support inverted full axis

i.e. pedals
This commit is contained in:
Connor McLaughlin
2023-01-15 14:00:51 +10:00
parent 01270bac35
commit 395e9a934b
39 changed files with 1022 additions and 366 deletions

View File

@ -281,48 +281,72 @@ bool InputManager::ParseBindingAndGetSource(const std::string_view& binding, Inp
return false;
}
std::string InputManager::ConvertInputBindingKeyToString(InputBindingKey key)
std::string InputManager::ConvertInputBindingKeyToString(InputBindingInfo::Type binding_type, InputBindingKey key)
{
if (key.source_type == InputSourceType::Keyboard)
if (binding_type == InputBindingInfo::Type::Pointer)
{
const std::optional<std::string> str(ConvertHostKeyboardCodeToString(key.data));
if (str.has_value() && !str->empty())
return fmt::format("Keyboard/{}", str->c_str());
}
else if (key.source_type == InputSourceType::Pointer)
{
if (key.source_subtype == InputSubclass::PointerButton)
// pointer and device bindings don't have a data part
if (key.source_type == InputSourceType::Pointer)
{
if (key.data < s_pointer_button_names.size())
return fmt::format("Pointer-{}/{}", u32{key.source_index}, s_pointer_button_names[key.data]);
else
return fmt::format("Pointer-{}/Button{}", u32{key.source_index}, key.data);
return GetPointerDeviceName(key.data);
}
else if (key.source_subtype == InputSubclass::PointerAxis)
else if (key.source_type < InputSourceType::Count && s_input_sources[static_cast<u32>(key.source_type)])
{
return fmt::format("Pointer-{}/{}{:c}", u32{key.source_index}, s_pointer_axis_names[key.data],
key.negative ? '-' : '+');
// This assumes that it always follows the Type/Binding form.
std::string keystr(s_input_sources[static_cast<u32>(key.source_type)]->ConvertKeyToString(key));
std::string::size_type pos = keystr.find('/');
if (pos != std::string::npos)
keystr.erase(pos);
return keystr;
}
}
else if (key.source_type == InputSourceType::Sensor)
else
{
if (key.source_subtype == InputSubclass::SensorAccelerometer && key.data < s_sensor_accelerometer_names.size())
return fmt::format("Sensor/{}", s_sensor_accelerometer_names[key.data]);
}
else if (key.source_type < InputSourceType::Count && s_input_sources[static_cast<u32>(key.source_type)])
{
return s_input_sources[static_cast<u32>(key.source_type)]->ConvertKeyToString(key);
if (key.source_type == InputSourceType::Keyboard)
{
const std::optional<std::string> str(ConvertHostKeyboardCodeToString(key.data));
if (str.has_value() && !str->empty())
return fmt::format("Keyboard/{}", str->c_str());
}
else if (key.source_type == InputSourceType::Pointer)
{
if (key.source_subtype == InputSubclass::PointerButton)
{
if (key.data < s_pointer_button_names.size())
return fmt::format("Pointer-{}/{}", u32{key.source_index}, s_pointer_button_names[key.data]);
else
return fmt::format("Pointer-{}/Button{}", u32{key.source_index}, key.data);
}
else if (key.source_subtype == InputSubclass::PointerAxis)
{
return fmt::format("Pointer-{}/{}{:c}", u32{key.source_index}, s_pointer_axis_names[key.data],
key.modifier == InputModifier::Negate ? '-' : '+');
}
}
else if (key.source_type < InputSourceType::Count && s_input_sources[static_cast<u32>(key.source_type)])
{
return s_input_sources[static_cast<u32>(key.source_type)]->ConvertKeyToString(key);
}
}
return {};
}
std::string InputManager::ConvertInputBindingKeysToString(const InputBindingKey* keys, size_t num_keys)
std::string InputManager::ConvertInputBindingKeysToString(InputBindingInfo::Type binding_type,
const InputBindingKey* keys, size_t num_keys)
{
// can't have a chord of devices/pointers
if (binding_type == InputBindingInfo::Type::Pointer)
{
// so only take the first
if (num_keys > 0)
return ConvertInputBindingKeyToString(binding_type, keys[0]);
}
std::stringstream ss;
for (size_t i = 0; i < num_keys; i++)
{
const std::string keystr(ConvertInputBindingKeyToString(keys[i]));
const std::string keystr(ConvertInputBindingKeyToString(binding_type, keys[i]));
if (keystr.empty())
return std::string();
@ -574,9 +598,9 @@ std::optional<InputBindingKey> InputManager::ParsePointerKey(const std::string_v
const std::string_view dir_part(sub_binding.substr(std::strlen(s_pointer_axis_names[i])));
if (dir_part == "+")
key.negative = false;
key.modifier = InputModifier::None;
else if (dir_part == "-")
key.negative = true;
key.modifier = InputModifier::Negate;
else
return std::nullopt;
@ -597,6 +621,23 @@ std::optional<InputBindingKey> InputManager::ParsePointerKey(const std::string_v
return std::nullopt;
}
std::optional<u32> InputManager::GetIndexFromPointerBinding(const std::string_view& source)
{
if (!StringUtil::StartsWith(source, "Pointer-"))
return std::nullopt;
const std::optional<s32> pointer_index = StringUtil::FromChars<s32>(source.substr(8));
if (!pointer_index.has_value() || pointer_index.value() < 0)
return std::nullopt;
return static_cast<u32>(pointer_index.value());
}
std::string InputManager::GetPointerDeviceName(u32 pointer_index)
{
return fmt::format("Pointer-{}", pointer_index);
}
std::optional<InputBindingKey> InputManager::ParseSensorKey(const std::string_view& source,
const std::string_view& sub_binding)
{
@ -616,9 +657,9 @@ std::optional<InputBindingKey> InputManager::ParseSensorKey(const std::string_vi
const std::string_view dir_part(sub_binding.substr(std::strlen(s_sensor_accelerometer_names[i])));
if (dir_part == "+")
key.negative = false;
key.modifier = InputModifier::None;
else if (dir_part == "-")
key.negative = true;
key.modifier = InputModifier::Negate;
else
return std::nullopt;
@ -777,7 +818,6 @@ bool InputManager::InvokeEvents(InputBindingKey key, float value, GenericInputBi
for (auto it = range.first; it != range.second; ++it)
{
InputBinding* binding = it->second.get();
// find the key which matches us
for (u32 i = 0; i < binding->num_keys; i++)
{
@ -785,11 +825,26 @@ bool InputManager::InvokeEvents(InputBindingKey key, float value, GenericInputBi
continue;
const u8 bit = static_cast<u8>(1) << i;
const bool negative = binding->keys[i].negative;
const bool negative = binding->keys[i].modifier == InputModifier::Negate;
const bool new_state = (negative ? (value < 0.0f) : (value > 0.0f));
float value_to_pass = 0.0f;
switch (binding->keys[i].modifier)
{
case InputModifier::None:
if (value > 0.0f)
value_to_pass = value;
break;
case InputModifier::Negate:
if (value < 0.0f)
value_to_pass = -value;
break;
case InputModifier::FullAxis:
value_to_pass = value * 0.5f + 0.5f;
break;
}
// invert if we're negative, since the handler expects 0..1
const float value_to_pass = (negative ? ((value < 0.0f) ? -value : 0.0f) : (value > 0.0f) ? value : 0.0f);
// handle inverting, needed for some wheels.
value_to_pass = binding->keys[i].invert ? (1.0f - value_to_pass) : value_to_pass;
// axes are fired regardless of a state change, unless they're zero
// (but going from not-zero to zero will still fire, because of the full state)
@ -1130,6 +1185,16 @@ std::vector<std::string> InputManager::GetInputProfileNames()
return ret;
}
void InputManager::OnInputDeviceConnected(const std::string_view& identifier, const std::string_view& device_name)
{
Host::OnInputDeviceConnected(identifier, device_name);
}
void InputManager::OnInputDeviceDisconnected(const std::string_view& identifier)
{
Host::OnInputDeviceDisconnected(identifier);
}
// ------------------------------------------------------------------------
// Vibration
// ------------------------------------------------------------------------