GunCon: Add relative pointer binding

This commit is contained in:
Stenzek
2023-09-20 16:56:12 +10:00
parent e63b2eec38
commit 7e07d2feb8
21 changed files with 779 additions and 507 deletions

View File

@ -174,6 +174,9 @@ static std::array<std::array<PointerAxisState, static_cast<u8>(InputPointerAxis:
s_pointer_state;
static std::array<float, static_cast<u8>(InputPointerAxis::Count)> s_pointer_axis_scale;
using PointerMoveCallback = std::function<void(InputBindingKey key, float value)>;
static std::vector<std::pair<u32, PointerMoveCallback>> s_pointer_move_callbacks;
// ------------------------------------------------------------------------
// Binding Parsing
// ------------------------------------------------------------------------
@ -699,16 +702,60 @@ void InputManager::AddPadBindings(SettingsInterface& si, const std::string& sect
{
const Controller::ControllerBindingInfo& bi = cinfo->bindings[i];
const std::vector<std::string> bindings(si.GetStringList(section.c_str(), bi.name));
if (!bindings.empty())
{
AddBindings(bindings, InputAxisEventHandler{[pad_index, bind_index = bi.bind_index](float value) {
if (!System::IsValid())
return;
Controller* c = System::GetController(pad_index);
if (c)
c->SetBindState(bind_index, value);
}});
switch (bi.type)
{
case InputBindingInfo::Type::Button:
case InputBindingInfo::Type::HalfAxis:
case InputBindingInfo::Type::Axis:
{
if (!bindings.empty())
{
AddBindings(bindings, InputAxisEventHandler{[pad_index, bind_index = bi.bind_index](float value) {
if (!System::IsValid())
return;
Controller* c = System::GetController(pad_index);
if (c)
c->SetBindState(bind_index, value);
}});
}
}
break;
case InputBindingInfo::Type::Pointer:
{
auto cb = [pad_index, base = bi.bind_index](InputBindingKey key, float value) {
if (!System::IsValid())
return;
Controller* c = System::GetController(pad_index);
if (c)
c->SetBindState(base + key.data, value);
};
// bind pointer 0 by default
if (bindings.empty())
{
s_pointer_move_callbacks.emplace_back(0, std::move(cb));
}
else
{
for (const std::string& binding : bindings)
{
const std::optional<u32> key(GetIndexFromPointerBinding(binding));
if (!key.has_value())
continue;
s_pointer_move_callbacks.emplace_back(0, cb);
}
}
}
break;
default:
Log_ErrorPrintf("Unhandled binding info type %u", static_cast<u32>(bi.type));
break;
}
}
@ -996,6 +1043,8 @@ bool InputManager::PreprocessEvent(InputBindingKey key, float value, GenericInpu
void InputManager::GenerateRelativeMouseEvents()
{
const bool system_running = System::IsRunning();
for (u32 device = 0; device < MAX_POINTER_DEVICES; device++)
{
for (u32 axis = 0; axis < static_cast<u32>(static_cast<u8>(InputPointerAxis::Count)); axis++)
@ -1011,12 +1060,24 @@ void InputManager::GenerateRelativeMouseEvents()
continue;
}
if (!system_running)
continue;
const float value = std::clamp(unclamped_value, -1.0f, 1.0f);
if (value != state.last_value)
{
state.last_value = value;
InvokeEvents(key, value, GenericInputBinding::Unknown);
}
if (delta != 0.0f)
{
for (const std::pair<u32, PointerMoveCallback>& pmc : s_pointer_move_callbacks)
{
if (pmc.first == device)
pmc.second(key, delta);
}
}
}
}
}
@ -1062,7 +1123,24 @@ void InputManager::UpdatePointerRelativeDelta(u32 index, InputPointerAxis axis,
void InputManager::UpdateHostMouseMode()
{
// TODO: Move from System to here.
// Check for relative mode bindings, and enable if there's anything using it.
bool has_relative_mode_bindings = !s_pointer_move_callbacks.empty();
if (!has_relative_mode_bindings)
{
for (const auto& it : s_binding_map)
{
const InputBindingKey& key = it.first;
if (key.source_type == InputSourceType::Pointer && key.source_subtype == InputSubclass::PointerAxis &&
key.data >= static_cast<u32>(InputPointerAxis::X) && key.data <= static_cast<u32>(InputPointerAxis::Y))
{
has_relative_mode_bindings = true;
break;
}
}
}
const bool has_software_cursor = ImGuiManager::HasSoftwareCursor(0);
Host::SetMouseMode(has_relative_mode_bindings, has_relative_mode_bindings || has_software_cursor);
}
bool InputManager::IsUsingRawInput()
@ -1074,22 +1152,6 @@ bool InputManager::IsUsingRawInput()
#endif
}
bool InputManager::HasPointerAxisBinds()
{
std::unique_lock lock(s_binding_map_write_lock);
for (const auto& it : s_binding_map)
{
const InputBindingKey& key = it.first;
if (key.source_type == InputSourceType::Pointer && key.source_subtype == InputSubclass::PointerAxis &&
key.data >= static_cast<u32>(InputPointerAxis::X) && key.data <= static_cast<u32>(InputPointerAxis::Y))
{
return true;
}
}
return false;
}
void InputManager::SetDefaultSourceConfig(SettingsInterface& si)
{
si.ClearSection("InputSources");
@ -1546,6 +1608,7 @@ void InputManager::ReloadBindings(SettingsInterface& si, SettingsInterface& bind
s_binding_map.clear();
s_pad_vibration_array.clear();
s_pointer_move_callbacks.clear();
// Hotkeys use the base configuration, except if the custom hotkeys option is enabled.
const bool use_profile_hotkeys = si.GetBoolValue("ControllerPorts", "UseProfileHotkeyBindings", false);
@ -1573,6 +1636,8 @@ void InputManager::ReloadBindings(SettingsInterface& si, SettingsInterface& bind
default_scale),
1.0f);
}
UpdateHostMouseMode();
}
bool InputManager::MigrateBindings(SettingsInterface& si)