mirror of https://github.com/PCSX2/pcsx2.git
Input: Add migrations for SDL Buttons/Axis rename
This commit is contained in:
parent
3bc658aaf6
commit
bd18d3ae48
|
@ -379,7 +379,7 @@ std::optional<InputBindingKey> DInputSource::ParseKeyString(const std::string_vi
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
TinyString DInputSource::ConvertKeyToString(InputBindingKey key)
|
||||
TinyString DInputSource::ConvertKeyToString(InputBindingKey key, bool migration)
|
||||
{
|
||||
TinyString ret;
|
||||
|
||||
|
@ -388,7 +388,7 @@ TinyString DInputSource::ConvertKeyToString(InputBindingKey key)
|
|||
if (key.source_subtype == InputSubclass::ControllerAxis)
|
||||
{
|
||||
const char* modifier = (key.modifier == InputModifier::FullAxis ? "Full" : (key.modifier == InputModifier::Negate ? "-" : "+"));
|
||||
ret.format("DInput-{}/{}Axis{}{}", u32(key.source_index), modifier, u32(key.data), (key.invert && !ShouldIgnoreInversion()) ? "~" : "");
|
||||
ret.format("DInput-{}/{}Axis{}{}", u32(key.source_index), modifier, u32(key.data), (key.invert && (migration || !ShouldIgnoreInversion())) ? "~" : "");
|
||||
}
|
||||
else if (key.source_subtype == InputSubclass::ControllerButton && key.data >= MAX_NUM_BUTTONS)
|
||||
{
|
||||
|
|
|
@ -47,7 +47,7 @@ public:
|
|||
void UpdateMotorState(InputBindingKey large_key, InputBindingKey small_key, float large_intensity, float small_intensity) override;
|
||||
|
||||
std::optional<InputBindingKey> ParseKeyString(const std::string_view device, const std::string_view binding) override;
|
||||
TinyString ConvertKeyToString(InputBindingKey key) override;
|
||||
TinyString ConvertKeyToString(InputBindingKey key, bool migration = false) override;
|
||||
TinyString ConvertKeyToIcon(InputBindingKey key) override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "SIO/Sio.h"
|
||||
#include "USB/USB.h"
|
||||
#include "VMManager.h"
|
||||
#include "LayeredSettingsInterface.h"
|
||||
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Console.h"
|
||||
|
@ -94,8 +95,10 @@ namespace InputManager
|
|||
|
||||
static bool SplitBinding(const std::string_view binding, std::string_view* source, std::string_view* sub_binding);
|
||||
static void PrettifyInputBindingPart(const std::string_view binding, SmallString& ret, bool& changed);
|
||||
static void AddBinding(const std::string_view binding, const InputEventHandler& handler);
|
||||
static void AddBindings(const std::vector<std::string>& bindings, const InputEventHandler& handler);
|
||||
static std::shared_ptr<InputBinding> AddBinding(const std::string_view binding, const InputEventHandler& handler);
|
||||
// Will also apply SDL2-SDL3 migrations and update the provided section & key
|
||||
static void AddBindings(const std::vector<std::string>& bindings, const InputEventHandler& handler,
|
||||
InputBindingInfo::Type binding_type, SettingsInterface& si, const char* section, const char* key);
|
||||
static bool ParseBindingAndGetSource(const std::string_view binding, InputBindingKey* key, InputSource** source);
|
||||
|
||||
static bool IsAxisHandler(const InputEventHandler& handler);
|
||||
|
@ -267,7 +270,7 @@ bool InputManager::ParseBindingAndGetSource(const std::string_view binding, Inpu
|
|||
return false;
|
||||
}
|
||||
|
||||
std::string InputManager::ConvertInputBindingKeyToString(InputBindingInfo::Type binding_type, InputBindingKey key)
|
||||
std::string InputManager::ConvertInputBindingKeyToString(InputBindingInfo::Type binding_type, InputBindingKey key, bool migration)
|
||||
{
|
||||
if (binding_type == InputBindingInfo::Type::Pointer || binding_type == InputBindingInfo::Type::Device)
|
||||
{
|
||||
|
@ -315,27 +318,27 @@ std::string InputManager::ConvertInputBindingKeyToString(InputBindingInfo::Type
|
|||
}
|
||||
else if (key.source_type < InputSourceType::Count && s_input_sources[static_cast<u32>(key.source_type)])
|
||||
{
|
||||
return std::string(s_input_sources[static_cast<u32>(key.source_type)]->ConvertKeyToString(key));
|
||||
return std::string(s_input_sources[static_cast<u32>(key.source_type)]->ConvertKeyToString(key, migration));
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string InputManager::ConvertInputBindingKeysToString(InputBindingInfo::Type binding_type, const InputBindingKey* keys, size_t num_keys)
|
||||
std::string InputManager::ConvertInputBindingKeysToString(InputBindingInfo::Type binding_type, const InputBindingKey* keys, size_t num_keys, bool migration)
|
||||
{
|
||||
// can't have a chord of devices/pointers
|
||||
if (binding_type == InputBindingInfo::Type::Pointer || binding_type == InputBindingInfo::Type::Device)
|
||||
{
|
||||
// so only take the first
|
||||
if (num_keys > 0)
|
||||
return ConvertInputBindingKeyToString(binding_type, keys[0]);
|
||||
return ConvertInputBindingKeyToString(binding_type, keys[0], migration);
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
for (size_t i = 0; i < num_keys; i++)
|
||||
{
|
||||
const std::string keystr(ConvertInputBindingKeyToString(binding_type, keys[i]));
|
||||
const std::string keystr(ConvertInputBindingKeyToString(binding_type, keys[i], migration));
|
||||
if (keystr.empty())
|
||||
return std::string();
|
||||
|
||||
|
@ -459,7 +462,7 @@ void InputManager::PrettifyInputBindingPart(const std::string_view binding, Smal
|
|||
}
|
||||
|
||||
|
||||
void InputManager::AddBinding(const std::string_view binding, const InputEventHandler& handler)
|
||||
std::shared_ptr<InputBinding> InputManager::AddBinding(const std::string_view binding, const InputEventHandler& handler)
|
||||
{
|
||||
std::shared_ptr<InputBinding> ibinding;
|
||||
const std::vector<std::string_view> chord_bindings(SplitChord(binding));
|
||||
|
@ -493,17 +496,65 @@ void InputManager::AddBinding(const std::string_view binding, const InputEventHa
|
|||
}
|
||||
|
||||
if (!ibinding)
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
// plop it in the input map for all the keys
|
||||
for (u32 i = 0; i < ibinding->num_keys; i++)
|
||||
s_binding_map.emplace(ibinding->keys[i].MaskDirection(), ibinding);
|
||||
|
||||
return ibinding;
|
||||
}
|
||||
|
||||
void InputManager::AddBindings(const std::vector<std::string>& bindings, const InputEventHandler& handler)
|
||||
void InputManager::AddBindings(const std::vector<std::string>& bindings, const InputEventHandler& handler,
|
||||
InputBindingInfo::Type binding_type, SettingsInterface& si, const char* section, const char* key)
|
||||
{
|
||||
std::vector<std::shared_ptr<InputBinding>> ibindings;
|
||||
|
||||
bool migrate = false;
|
||||
for (const std::string& binding : bindings)
|
||||
AddBinding(binding, handler);
|
||||
{
|
||||
std::shared_ptr<InputBinding> ibinding = AddBinding(binding, handler);
|
||||
ibindings.push_back(ibinding);
|
||||
|
||||
if (ibinding)
|
||||
{
|
||||
// Check for SDL2-3 migrations
|
||||
for (u32 i = 0; i < ibinding->num_keys; i++)
|
||||
{
|
||||
if (ibinding->keys[i].needs_migration)
|
||||
migrate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save migrations
|
||||
if (migrate)
|
||||
{
|
||||
std::vector<std::string> new_bindings;
|
||||
new_bindings.reserve(bindings.size());
|
||||
|
||||
for (int i = 0; i < bindings.size(); i++)
|
||||
{
|
||||
if (ibindings[i])
|
||||
new_bindings.push_back(ConvertInputBindingKeysToString(binding_type, ibindings[i]->keys, ibindings[i]->num_keys, true));
|
||||
else
|
||||
// Retain invalid bindings as is
|
||||
new_bindings.push_back(bindings[i]);
|
||||
}
|
||||
|
||||
// Need to find where our binding came from
|
||||
LayeredSettingsInterface& lsi = static_cast<LayeredSettingsInterface&>(si);
|
||||
for (int i = 0; i < LayeredSettingsInterface::NUM_LAYERS; i++)
|
||||
{
|
||||
SettingsInterface* layer = lsi.GetLayer(static_cast<LayeredSettingsInterface::Layer>(i));
|
||||
if (layer && layer->GetStringList(section, key) == bindings)
|
||||
{
|
||||
// Layer found, update settings
|
||||
layer->SetStringList(section, key, new_bindings);
|
||||
layer->Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -711,7 +762,7 @@ void InputManager::AddHotkeyBindings(SettingsInterface& si)
|
|||
if (bindings.empty())
|
||||
continue;
|
||||
|
||||
AddBindings(bindings, InputButtonEventHandler{hotkey->handler});
|
||||
AddBindings(bindings, InputButtonEventHandler{hotkey->handler}, InputBindingInfo::Type::Unknown, si, "Hotkeys", hotkey->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -753,7 +804,8 @@ void InputManager::AddPadBindings(SettingsInterface& si, u32 pad_index)
|
|||
AddBindings(
|
||||
bindings, InputAxisEventHandler{[pad_index, bind_index = bi.bind_index, sensitivity, deadzone](InputBindingKey key, float value) {
|
||||
Pad::SetControllerState(pad_index, bind_index, ApplySingleBindingScale(sensitivity, deadzone, value));
|
||||
}});
|
||||
}},
|
||||
bi.bind_type, si, section.c_str(), bi.name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -771,10 +823,12 @@ void InputManager::AddPadBindings(SettingsInterface& si, u32 pad_index)
|
|||
if (!bindings.empty())
|
||||
{
|
||||
const float deadzone = si.GetFloatValue(section.c_str(), fmt::format("Macro{}Deadzone", macro_button_index + 1).c_str(), 0.0f);
|
||||
AddBindings(bindings, InputAxisEventHandler{[pad_index, macro_button_index, deadzone](InputBindingKey key, float value) {
|
||||
const bool state = (value > deadzone);
|
||||
Pad::SetMacroButtonState(key, pad_index, macro_button_index, state);
|
||||
}});
|
||||
AddBindings(
|
||||
bindings, InputAxisEventHandler{[pad_index, macro_button_index, deadzone](InputBindingKey key, float value) {
|
||||
const bool state = (value > deadzone);
|
||||
Pad::SetMacroButtonState(key, pad_index, macro_button_index, state);
|
||||
}},
|
||||
InputBindingInfo::Type::Macro, si, section.c_str(), fmt::format("Macro{}", macro_button_index + 1).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -835,9 +889,11 @@ void InputManager::AddUSBBindings(SettingsInterface& si, u32 port)
|
|||
{
|
||||
const float sensitivity = si.GetFloatValue(section.c_str(), fmt::format("{}Scale", bi.name).c_str(), 1.0f);
|
||||
const float deadzone = si.GetFloatValue(section.c_str(), fmt::format("{}Deadzone", bi.name).c_str(), 0.0f);
|
||||
AddBindings(bindings, InputAxisEventHandler{[port, bind_index = bi.bind_index, sensitivity, deadzone](InputBindingKey key, float value) {
|
||||
USB::SetDeviceBindValue(port, bind_index, ApplySingleBindingScale(sensitivity, deadzone, value));
|
||||
}});
|
||||
AddBindings(
|
||||
bindings, InputAxisEventHandler{[port, bind_index = bi.bind_index, sensitivity, deadzone](InputBindingKey key, float value) {
|
||||
USB::SetDeviceBindValue(port, bind_index, ApplySingleBindingScale(sensitivity, deadzone, value));
|
||||
}},
|
||||
bi.bind_type, si, section.c_str(), bind_name.c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -63,7 +63,8 @@ union InputBindingKey
|
|||
InputSubclass source_subtype : 3; ///< if 1, binding is for an axis and not a button (used for controllers)
|
||||
InputModifier modifier : 2;
|
||||
u32 invert : 1; ///< if 1, value is inverted prior to being sent to the sink
|
||||
u32 unused : 14;
|
||||
u32 needs_migration : 1; //< Used for SDL2-3 Migration, binding should be saved to complete migration
|
||||
u32 unused : 13;
|
||||
u32 data;
|
||||
};
|
||||
|
||||
|
@ -80,6 +81,7 @@ union InputBindingKey
|
|||
r.bits = bits;
|
||||
r.modifier = InputModifier::None;
|
||||
r.invert = 0;
|
||||
r.needs_migration = false;
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
@ -203,10 +205,10 @@ namespace InputManager
|
|||
std::optional<InputBindingKey> ParseInputBindingKey(const std::string_view binding);
|
||||
|
||||
/// Converts a input key to a string.
|
||||
std::string ConvertInputBindingKeyToString(InputBindingInfo::Type binding_type, InputBindingKey key);
|
||||
std::string ConvertInputBindingKeyToString(InputBindingInfo::Type binding_type, InputBindingKey key, bool migration = false);
|
||||
|
||||
/// Converts a chord of binding keys to a string.
|
||||
std::string ConvertInputBindingKeysToString(InputBindingInfo::Type binding_type, const InputBindingKey* keys, size_t num_keys);
|
||||
std::string ConvertInputBindingKeysToString(InputBindingInfo::Type binding_type, const InputBindingKey* keys, size_t num_keys, bool migration = false);
|
||||
|
||||
/// Represents a binding with icon fonts, if available.
|
||||
bool PrettifyInputBinding(SmallStringBase& binding);
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
virtual void PollEvents() = 0;
|
||||
|
||||
virtual std::optional<InputBindingKey> ParseKeyString(const std::string_view device, const std::string_view binding) = 0;
|
||||
virtual TinyString ConvertKeyToString(InputBindingKey key) = 0;
|
||||
virtual TinyString ConvertKeyToString(InputBindingKey key, bool migration = false) = 0;
|
||||
virtual TinyString ConvertKeyToIcon(InputBindingKey key) = 0;
|
||||
|
||||
/// Enumerates available devices. Returns a pair of the prefix (e.g. SDL-0) and the device name.
|
||||
|
|
|
@ -505,6 +505,50 @@ std::optional<InputBindingKey> SDLInputSource::ParseKeyString(const std::string_
|
|||
key.source_type = InputSourceType::SDL;
|
||||
key.source_index = static_cast<u32>(player_id.value());
|
||||
|
||||
// SDL2-SDL3 migrations
|
||||
if (binding.starts_with("+Axis") || binding.starts_with("-Axis"))
|
||||
{
|
||||
const std::string_view axis_name(binding.substr(1));
|
||||
|
||||
std::string_view end;
|
||||
if (auto value = StringUtil::FromChars<u32>(axis_name.substr(4), 10, &end))
|
||||
{
|
||||
key.source_subtype = InputSubclass::ControllerAxis;
|
||||
key.data = *value - 6 + std::size(s_sdl_axis_names);
|
||||
key.modifier = (binding[0] == '-') ? InputModifier::Negate : InputModifier::None;
|
||||
key.invert = (end == "~");
|
||||
|
||||
key.needs_migration = true;
|
||||
return key;
|
||||
}
|
||||
}
|
||||
else if (binding.starts_with("FullAxis"))
|
||||
{
|
||||
std::string_view end;
|
||||
if (auto value = StringUtil::FromChars<u32>(binding.substr(8), 10, &end))
|
||||
{
|
||||
key.source_subtype = InputSubclass::ControllerAxis;
|
||||
key.data = *value - 6 + std::size(s_sdl_axis_names);
|
||||
key.modifier = InputModifier::FullAxis;
|
||||
key.invert = (end == "~");
|
||||
|
||||
key.needs_migration = true;
|
||||
return key;
|
||||
}
|
||||
}
|
||||
else if (binding.starts_with("Button"))
|
||||
{
|
||||
if (auto value = StringUtil::FromChars<u32>(binding.substr(6)))
|
||||
{
|
||||
key.source_subtype = InputSubclass::ControllerButton;
|
||||
key.data = *value - 21 + std::size(s_sdl_button_names);
|
||||
|
||||
key.needs_migration = true;
|
||||
return key;
|
||||
}
|
||||
}
|
||||
// End Migrations
|
||||
|
||||
if (binding.ends_with("Motor"))
|
||||
{
|
||||
key.source_subtype = InputSubclass::ControllerMotor;
|
||||
|
@ -613,7 +657,7 @@ std::optional<InputBindingKey> SDLInputSource::ParseKeyString(const std::string_
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
TinyString SDLInputSource::ConvertKeyToString(InputBindingKey key)
|
||||
TinyString SDLInputSource::ConvertKeyToString(InputBindingKey key, bool migration)
|
||||
{
|
||||
TinyString ret;
|
||||
|
||||
|
@ -625,7 +669,7 @@ TinyString SDLInputSource::ConvertKeyToString(InputBindingKey key)
|
|||
if (key.data < std::size(s_sdl_axis_names))
|
||||
ret.format("SDL-{}/{}{}", static_cast<u32>(key.source_index), modifier, s_sdl_axis_names[key.data]);
|
||||
else
|
||||
ret.format("SDL-{}/{}JoyAxis{}{}", static_cast<u32>(key.source_index), modifier, key.data - std::size(s_sdl_axis_names), (key.invert && !ShouldIgnoreInversion()) ? "~" : "");
|
||||
ret.format("SDL-{}/{}JoyAxis{}{}", static_cast<u32>(key.source_index), modifier, key.data - std::size(s_sdl_axis_names), (key.invert && (migration || !ShouldIgnoreInversion())) ? "~" : "");)
|
||||
}
|
||||
else if (key.source_subtype == InputSubclass::ControllerButton)
|
||||
{
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
void UpdateMotorState(InputBindingKey large_key, InputBindingKey small_key, float large_intensity, float small_intensity) override;
|
||||
|
||||
std::optional<InputBindingKey> ParseKeyString(const std::string_view device, const std::string_view binding) override;
|
||||
TinyString ConvertKeyToString(InputBindingKey key) override;
|
||||
TinyString ConvertKeyToString(InputBindingKey key, bool migration = false) override;
|
||||
TinyString ConvertKeyToIcon(InputBindingKey key) override;
|
||||
|
||||
bool ProcessSDLEvent(const SDL_Event* event);
|
||||
|
|
|
@ -317,7 +317,7 @@ std::optional<InputBindingKey> XInputSource::ParseKeyString(const std::string_vi
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
TinyString XInputSource::ConvertKeyToString(InputBindingKey key)
|
||||
TinyString XInputSource::ConvertKeyToString(InputBindingKey key, bool migration)
|
||||
{
|
||||
TinyString ret;
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ public:
|
|||
void UpdateMotorState(InputBindingKey large_key, InputBindingKey small_key, float large_intensity, float small_intensity) override;
|
||||
|
||||
std::optional<InputBindingKey> ParseKeyString(const std::string_view device, const std::string_view binding) override;
|
||||
TinyString ConvertKeyToString(InputBindingKey key) override;
|
||||
TinyString ConvertKeyToString(InputBindingKey key, bool migration = false) override;
|
||||
TinyString ConvertKeyToIcon(InputBindingKey key) override;
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue