2929#include < memory>
3030#include < mutex>
3131#include < sstream>
32+ #include < tuple>
3233#include < unordered_map>
3334#include < variant>
3435#include < vector>
@@ -73,6 +74,16 @@ struct PadVibrationBinding
7374 Timer::Value last_update_time; // /< Last time this motor was updated.
7475 InputSource* source; // /< Input source for this motor.
7576 float last_intensity; // /< Last intensity we sent to the motor.
77+
78+ ALWAYS_INLINE static u64 PackPadAndBindIndex (u32 pad_index, u32 bind_index)
79+ {
80+ return (static_cast <u64 >(pad_index) << 32 ) | static_cast <u64 >(bind_index);
81+ }
82+
83+ ALWAYS_INLINE static std::tuple<u32 , u32 > UnpackPadAndBindIndex (u64 packed)
84+ {
85+ return {static_cast <u32 >(packed >> 32 ), static_cast <u32 >(packed)};
86+ }
7687};
7788
7889struct PadLEDBinding
@@ -132,6 +143,7 @@ static float ApplySingleBindingScale(float sensitivity, float deadzone, float va
132143static void AddHotkeyBindings (const SettingsInterface& si);
133144static void AddPadBindings (const SettingsInterface& si, const std::string& section, u32 pad,
134145 const Controller::ControllerInfo& cinfo);
146+ static void SynchronizePadEffectBindings (InputBindingKey key);
135147static void UpdateContinuedVibration ();
136148static void GenerateRelativeMouseEvents ();
137149
@@ -149,11 +161,6 @@ static void UpdateInputSourceState(const SettingsInterface& si, std::unique_lock
149161
150162static const KeyCodeData* FindKeyCodeData (u32 usb_code);
151163
152- ALWAYS_INLINE static u64 PackPadAndBindIndex (u32 pad_index, u32 bind_index)
153- {
154- return (static_cast <u64 >(pad_index) << 32 ) | static_cast <u64 >(bind_index);
155- }
156-
157164// ------------------------------------------------------------------------
158165// Tracking host mouse movement and turning into relative events
159166// 4 axes: pointer left/right, wheel vertical/horizontal. Last/Next/Normalized.
@@ -617,7 +624,7 @@ void InputManager::AddVibrationBinding(u32 pad_index, u32 bind_index, const Inpu
617624 InputSource* source)
618625{
619626 s_state.pad_vibration_array .push_back (
620- PadVibrationBinding{.pad_and_bind_index = PackPadAndBindIndex (pad_index, bind_index),
627+ PadVibrationBinding{.pad_and_bind_index = PadVibrationBinding:: PackPadAndBindIndex (pad_index, bind_index),
621628 .binding = binding,
622629 .last_update_time = 0 ,
623630 .source = source,
@@ -1016,7 +1023,7 @@ void InputManager::AddPadBindings(const SettingsInterface& si, const std::string
10161023 PadVibrationBinding vib_binding;
10171024 if (ParseBindingAndGetSource (binding, &vib_binding.binding , &vib_binding.source ))
10181025 {
1019- vib_binding.pad_and_bind_index = PackPadAndBindIndex (pad_index, bi.bind_index );
1026+ vib_binding.pad_and_bind_index = PadVibrationBinding:: PackPadAndBindIndex (pad_index, bi.bind_index );
10201027 vib_binding.last_update_time = 0 ;
10211028
10221029 // If we're reloading bindings due to e.g. device connection, sync the vibration state.
@@ -1070,6 +1077,37 @@ void InputManager::AddPadBindings(const SettingsInterface& si, const std::string
10701077 }
10711078}
10721079
1080+ void InputManager::SynchronizePadEffectBindings (InputBindingKey key)
1081+ {
1082+ for (PadVibrationBinding& vib_binding : s_state.pad_vibration_array )
1083+ {
1084+ // only matching devices
1085+ if (vib_binding.binding .source_type != key.source_type && vib_binding.binding .source_index != key.source_index )
1086+ continue ;
1087+
1088+ // need to find the max intensity for this binding, might be more than one if combined motors
1089+ float max_intensity = 0 .0f ;
1090+ for (PadVibrationBinding& other_vib_binding : s_state.pad_vibration_array )
1091+ {
1092+ if (vib_binding.binding == other_vib_binding.binding )
1093+ max_intensity = std::max (max_intensity, other_vib_binding.last_intensity );
1094+ }
1095+
1096+ if (max_intensity > 0 .0f )
1097+ vib_binding.source ->UpdateMotorState (vib_binding.binding , max_intensity);
1098+ }
1099+
1100+ for (PadLEDBinding& led_binding : s_state.pad_led_array )
1101+ {
1102+ // only matching devices
1103+ if (led_binding.binding .source_type != key.source_type && led_binding.binding .source_index != key.source_index )
1104+ continue ;
1105+
1106+ // Need to pass it through unconditionally, otherwise if the LED was on it'll stay on.
1107+ led_binding.source ->UpdateLEDState (led_binding.binding , led_binding.last_intensity );
1108+ }
1109+ }
1110+
10731111// ------------------------------------------------------------------------
10741112// Event Handling
10751113// ------------------------------------------------------------------------
@@ -1791,6 +1829,7 @@ void InputManager::OnInputDeviceConnected(InputBindingKey key, std::string_view
17911829 std::string_view device_name)
17921830{
17931831 INFO_LOG (" Device '{}' connected: '{}'" , identifier, device_name);
1832+ SynchronizePadEffectBindings (key);
17941833 Host::OnInputDeviceConnected (key, identifier, device_name);
17951834}
17961835
@@ -1819,7 +1858,7 @@ std::unique_ptr<ForceFeedbackDevice> InputManager::CreateForceFeedbackDevice(con
18191858
18201859void InputManager::SetPadVibrationIntensity (u32 pad_index, u32 bind_index, float intensity)
18211860{
1822- const u64 pad_and_bind_index = PackPadAndBindIndex (pad_index, bind_index);
1861+ const u64 pad_and_bind_index = PadVibrationBinding:: PackPadAndBindIndex (pad_index, bind_index);
18231862 for (PadVibrationBinding& vib : s_state.pad_vibration_array )
18241863 {
18251864 if (vib.pad_and_bind_index == pad_and_bind_index && vib.last_intensity != intensity)
0 commit comments