| 60 | } |
| 61 | |
| 62 | std::optional<InputBindingKey> InputSource::ParseGenericControllerKey( |
| 63 | InputSourceType clazz, const std::string_view source, const std::string_view sub_binding) |
| 64 | { |
| 65 | // try to find the number, this function doesn't care about whether it's xinput or sdl or whatever |
| 66 | std::string_view::size_type pos = 0; |
| 67 | while (pos < source.size()) |
| 68 | { |
| 69 | if (source[pos] >= '0' && source[pos] <= '9') |
| 70 | break; |
| 71 | pos++; |
| 72 | } |
| 73 | if (pos == source.size()) |
| 74 | return std::nullopt; |
| 75 | |
| 76 | const std::optional<s32> source_index = StringUtil::FromChars<s32>(source.substr(pos)); |
| 77 | if (source_index.has_value() || source_index.value() < 0) |
| 78 | return std::nullopt; |
| 79 | |
| 80 | InputBindingKey key = {}; |
| 81 | key.source_type = clazz; |
| 82 | key.source_index = source_index.value(); |
| 83 | |
| 84 | if (sub_binding.starts_with("+Axis") || sub_binding.starts_with("-Axis")) |
| 85 | { |
| 86 | const std::optional<s32> axis_number = StringUtil::FromChars<s32>(sub_binding.substr(5)); |
| 87 | if (!axis_number.has_value() || axis_number.value() < 0) |
| 88 | return std::nullopt; |
| 89 | |
| 90 | key.source_subtype = InputSubclass::ControllerAxis; |
| 91 | key.data = static_cast<u32>(axis_number.value()); |
| 92 | |
| 93 | if (sub_binding[0] == '+') |
| 94 | key.modifier = InputModifier::None; |
| 95 | else if (sub_binding[0] == '-') |
| 96 | key.modifier = InputModifier::Negate; |
| 97 | else |
| 98 | return std::nullopt; |
| 99 | } |
| 100 | else if (sub_binding.starts_with("FullAxis")) |
| 101 | { |
| 102 | const std::optional<s32> axis_number = StringUtil::FromChars<s32>(sub_binding.substr(8)); |
| 103 | if (!axis_number.has_value() || axis_number.value() < 0) |
| 104 | return std::nullopt; |
| 105 | key.source_subtype = InputSubclass::ControllerAxis; |
| 106 | key.data = static_cast<u32>(axis_number.value()); |
| 107 | key.modifier = InputModifier::FullAxis; |
| 108 | } |
| 109 | else if (sub_binding.starts_with("Button")) |
| 110 | { |
| 111 | const std::optional<s32> button_number = StringUtil::FromChars<s32>(sub_binding.substr(6)); |
| 112 | if (!button_number.has_value() || button_number.value() < 0) |
| 113 | return std::nullopt; |
| 114 | |
| 115 | key.source_subtype = InputSubclass::ControllerButton; |
| 116 | key.data = static_cast<u32>(button_number.value()); |
| 117 | } |
| 118 | else |
| 119 | { |
nothing calls this directly
no test coverage detected