Skip to content

Commit 8f22b0f

Browse files
committed
Big Picture Mode: Fix analog stick input bursting
Analog inputs are now read as single event once it passes the deadzone / threshold.
1 parent ff7fa6f commit 8f22b0f

File tree

1 file changed

+52
-16
lines changed

1 file changed

+52
-16
lines changed

pcsx2/ImGui/ImGuiManager.cpp

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,40 +1209,76 @@ void ImGuiManager::ProcessGenericAxisEvent(GenericInputBinding negative_key, Gen
12091209
static constexpr float DEADZONE = 0.25f;
12101210

12111211
// Ignore diagonal analog stick input — neither axis fires when both exceed the deadzone.
1212-
static float s_left_stick_x = 0.0f, s_left_stick_y = 0.0f;
1213-
static float s_right_stick_x = 0.0f, s_right_stick_y = 0.0f;
1212+
// Also track last sent binary state per direction to avoid bursting duplicate events when
1213+
// the controller sends many axis updates in quick succession.
1214+
struct AxisState
1215+
{
1216+
float x = 0.0f, y = 0.0f;
1217+
bool x_neg_active = false, x_pos_active = false;
1218+
bool y_neg_active = false, y_pos_active = false;
1219+
};
1220+
static AxisState s_left_stick, s_right_stick;
12141221

1215-
float suppressed_value = value;
1222+
AxisState* state = nullptr;
1223+
bool is_x_axis = false;
12161224
if (negative_key == GenericInputBinding::LeftStickLeft)
12171225
{
1218-
s_left_stick_x = value;
1219-
if (std::abs(s_left_stick_y) > DEADZONE)
1220-
suppressed_value = 0.0f;
1226+
state = &s_left_stick;
1227+
state->x = value;
1228+
is_x_axis = true;
12211229
}
12221230
else if (negative_key == GenericInputBinding::LeftStickUp)
12231231
{
1224-
s_left_stick_y = value;
1225-
if (std::abs(s_left_stick_x) > DEADZONE)
1226-
suppressed_value = 0.0f;
1232+
state = &s_left_stick;
1233+
state->y = value;
1234+
is_x_axis = false;
12271235
}
12281236
else if (negative_key == GenericInputBinding::RightStickLeft)
12291237
{
1230-
s_right_stick_x = value;
1231-
if (std::abs(s_right_stick_y) > DEADZONE)
1232-
suppressed_value = 0.0f;
1238+
state = &s_right_stick;
1239+
state->x = value;
1240+
is_x_axis = true;
12331241
}
12341242
else if (negative_key == GenericInputBinding::RightStickUp)
12351243
{
1236-
s_right_stick_y = value;
1237-
if (std::abs(s_right_stick_x) > DEADZONE)
1244+
state = &s_right_stick;
1245+
state->y = value;
1246+
is_x_axis = false;
1247+
}
1248+
1249+
float suppressed_value = value;
1250+
if (state)
1251+
{
1252+
const float other = is_x_axis ? state->y : state->x;
1253+
if (std::abs(other) > DEADZONE)
12381254
suppressed_value = 0.0f;
12391255
}
12401256

12411257
// Treat as binary like the D-pad: either fully pressed or released, with a deadzone.
1258+
// Only forward the event if the binary state actually changed to avoid input bursts.
1259+
bool* neg_active_ptr = state ? (is_x_axis ? &state->x_neg_active : &state->y_neg_active) : nullptr;
1260+
bool* pos_active_ptr = state ? (is_x_axis ? &state->x_pos_active : &state->y_pos_active) : nullptr;
1261+
12421262
if (negative_key != GenericInputBinding::Unknown)
1243-
ProcessGenericInputEvent(negative_key, layout, (suppressed_value < -DEADZONE) ? 1.0f : 0.0f);
1263+
{
1264+
const bool active = suppressed_value < -DEADZONE;
1265+
if (!neg_active_ptr || active != *neg_active_ptr)
1266+
{
1267+
if (neg_active_ptr)
1268+
*neg_active_ptr = active;
1269+
ProcessGenericInputEvent(negative_key, layout, active ? 1.0f : 0.0f);
1270+
}
1271+
}
12441272
if (positive_key != GenericInputBinding::Unknown)
1245-
ProcessGenericInputEvent(positive_key, layout, (suppressed_value > DEADZONE) ? 1.0f : 0.0f);
1273+
{
1274+
const bool active = suppressed_value > DEADZONE;
1275+
if (!pos_active_ptr || active != *pos_active_ptr)
1276+
{
1277+
if (pos_active_ptr)
1278+
*pos_active_ptr = active;
1279+
ProcessGenericInputEvent(positive_key, layout, active ? 1.0f : 0.0f);
1280+
}
1281+
}
12461282
}
12471283

12481284
void ImGuiManager::SwapGamepadNorthWest(bool value)

0 commit comments

Comments
 (0)