|
|
|
|
@ -78,6 +78,7 @@ struct InputBinding
|
|
|
|
|
u8 num_keys = 0;
|
|
|
|
|
u8 full_mask = 0;
|
|
|
|
|
u8 current_mask = 0;
|
|
|
|
|
bool activate_when_captured = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct PadVibrationBinding
|
|
|
|
|
@ -146,7 +147,8 @@ static std::vector<std::string_view> SplitChord(std::string_view binding);
|
|
|
|
|
static bool SplitBinding(std::string_view binding, std::string_view* source, std::string_view* sub_binding);
|
|
|
|
|
static void PrettifyInputBindingPart(std::string_view binding, bool allow_icon, BindingIconMappingFunction mapper,
|
|
|
|
|
SmallString& ret, bool& changed);
|
|
|
|
|
static void AddBindings(const std::vector<std::string>& bindings, const InputEventHandler& handler);
|
|
|
|
|
static void AddBindings(const std::vector<std::string>& bindings, bool activate_when_captured,
|
|
|
|
|
const InputEventHandler& handler);
|
|
|
|
|
static void UpdatePointerCount();
|
|
|
|
|
|
|
|
|
|
static bool IsAxisHandler(const InputEventHandler& handler);
|
|
|
|
|
@ -637,13 +639,14 @@ void InputManager::PrettifyInputBindingPart(const std::string_view binding, bool
|
|
|
|
|
ret.append(binding);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InputManager::AddBindings(const std::vector<std::string>& bindings, const InputEventHandler& handler)
|
|
|
|
|
void InputManager::AddBindings(const std::vector<std::string>& bindings, bool activate_when_captured,
|
|
|
|
|
const InputEventHandler& handler)
|
|
|
|
|
{
|
|
|
|
|
for (const std::string& binding : bindings)
|
|
|
|
|
AddBinding(binding, handler);
|
|
|
|
|
AddBinding(binding, activate_when_captured, handler);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InputManager::AddBinding(std::string_view binding, const InputEventHandler& handler)
|
|
|
|
|
void InputManager::AddBinding(std::string_view binding, bool activate_when_captured, const InputEventHandler& handler)
|
|
|
|
|
{
|
|
|
|
|
std::shared_ptr<InputBinding> ibinding;
|
|
|
|
|
const std::vector<std::string_view> chord_bindings(SplitChord(binding));
|
|
|
|
|
@ -662,6 +665,7 @@ void InputManager::AddBinding(std::string_view binding, const InputEventHandler&
|
|
|
|
|
{
|
|
|
|
|
ibinding = std::make_shared<InputBinding>();
|
|
|
|
|
ibinding->handler = handler;
|
|
|
|
|
ibinding->activate_when_captured = activate_when_captured;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ibinding->num_keys == MAX_KEYS_PER_BINDING)
|
|
|
|
|
@ -955,7 +959,7 @@ void InputManager::AddHotkeyBindings(const SettingsInterface& si)
|
|
|
|
|
if (bindings.empty())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
AddBindings(bindings, InputButtonEventHandler{hotkey.handler});
|
|
|
|
|
AddBindings(bindings, hotkey.activate_when_captured, InputButtonEventHandler{hotkey.handler});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -978,15 +982,16 @@ void InputManager::AddPadBindings(const SettingsInterface& si, const std::string
|
|
|
|
|
si.GetFloatValue(section.c_str(), TinyString::from_format("{}Scale", bi.name), 1.0f);
|
|
|
|
|
const float deadzone =
|
|
|
|
|
si.GetFloatValue(section.c_str(), TinyString::from_format("{}Deadzone", bi.name), 0.0f);
|
|
|
|
|
AddBindings(bindings, InputAxisEventHandler{[pad_index, bind_index = bi.bind_index, sensitivity,
|
|
|
|
|
deadzone](float value) {
|
|
|
|
|
if (!System::IsValid())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Controller* c = System::GetController(pad_index);
|
|
|
|
|
if (c)
|
|
|
|
|
c->SetBindState(bind_index, ApplySingleBindingScale(sensitivity, deadzone, value));
|
|
|
|
|
}});
|
|
|
|
|
AddBindings(
|
|
|
|
|
bindings, false,
|
|
|
|
|
InputAxisEventHandler{[pad_index, bind_index = bi.bind_index, sensitivity, deadzone](float value) {
|
|
|
|
|
if (!System::IsValid())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Controller* c = System::GetController(pad_index);
|
|
|
|
|
if (c)
|
|
|
|
|
c->SetBindState(bind_index, ApplySingleBindingScale(sensitivity, deadzone, value));
|
|
|
|
|
}});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
@ -1243,9 +1248,11 @@ bool InputManager::ProcessEvent(InputBindingKey key, float value, bool skip_butt
|
|
|
|
|
}
|
|
|
|
|
else if (binding->num_keys >= min_num_keys)
|
|
|
|
|
{
|
|
|
|
|
const bool skip_button_handler = skip_button_handlers && !binding->activate_when_captured;
|
|
|
|
|
|
|
|
|
|
// update state based on whether the whole chord was activated
|
|
|
|
|
const u8 new_mask =
|
|
|
|
|
((new_state && !skip_button_handlers) ? (binding->current_mask | bit) : (binding->current_mask & ~bit));
|
|
|
|
|
((new_state && !skip_button_handler) ? (binding->current_mask | bit) : (binding->current_mask & ~bit));
|
|
|
|
|
const bool prev_full_state = (binding->current_mask == binding->full_mask);
|
|
|
|
|
const bool new_full_state = (new_mask == binding->full_mask);
|
|
|
|
|
binding->current_mask = new_mask;
|
|
|
|
|
@ -1289,7 +1296,7 @@ bool InputManager::ProcessEvent(InputBindingKey key, float value, bool skip_butt
|
|
|
|
|
|
|
|
|
|
if (prev_full_state != new_full_state && binding->num_keys >= min_num_keys)
|
|
|
|
|
{
|
|
|
|
|
const s32 pressed = skip_button_handlers ? -1 : static_cast<s32>(value_to_pass > 0.0f);
|
|
|
|
|
const s32 pressed = skip_button_handler ? -1 : static_cast<s32>(value_to_pass > 0.0f);
|
|
|
|
|
std::get<InputButtonEventHandler>(binding->handler)(pressed);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -1432,7 +1439,7 @@ bool InputManager::PreprocessEvent(InputBindingKey key, float value, GenericInpu
|
|
|
|
|
if (ImGuiManager::ProcessPointerButtonEvent(key, value))
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (generic_key != GenericInputBinding::Unknown)
|
|
|
|
|
else if (key.source_type > InputSourceType::Pointer)
|
|
|
|
|
{
|
|
|
|
|
if (ImGuiManager::ProcessGenericInputEvent(generic_key, value) && value != 0.0f)
|
|
|
|
|
return true;
|
|
|
|
|
@ -2143,17 +2150,17 @@ void InputManager::LoadMacroButtonConfig(const SettingsInterface& si, const std:
|
|
|
|
|
if (deadzone != 0.0f)
|
|
|
|
|
WARNING_LOG("Chord binding {} not supported with trigger deadzone {}.", trigger_binding, deadzone);
|
|
|
|
|
|
|
|
|
|
AddBinding(trigger_binding,
|
|
|
|
|
InputButtonEventHandler{[pad = macro.pad_index, index = macro.macro_index](bool state) {
|
|
|
|
|
AddBinding(trigger_binding, false,
|
|
|
|
|
InputButtonEventHandler{[pad = macro.pad_index, index = macro.macro_index](s32 state) {
|
|
|
|
|
if (!System::IsValid())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
SetMacroButtonState(pad, index, state);
|
|
|
|
|
SetMacroButtonState(pad, index, (state > 0));
|
|
|
|
|
}});
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
AddBindings(trigger_bindings,
|
|
|
|
|
AddBindings(trigger_bindings, false,
|
|
|
|
|
InputAxisEventHandler{[pad = macro.pad_index, index = macro.macro_index, deadzone](float value) {
|
|
|
|
|
if (!System::IsValid())
|
|
|
|
|
return;
|
|
|
|
|
|