Skip to content

Fix Gamepads getting recognized twice #205

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,4 @@ LogLoadingWarning.txt
LogConsole.txt
Console.dump.log
Console.input.log
imgui.ini
38 changes: 20 additions & 18 deletions Source/Managers/UInputMan.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#include "UInputMan.h"
#include "Constants.h"
#include "SDL3/SDL_events.h"
#include "SDL3/SDL_keyboard.h"
#include "SDL3/SDL_mouse.h"
#include "SceneMan.h"
#include "ActivityMan.h"
#include "MetaMan.h"
Expand All @@ -14,6 +11,7 @@
#include "Icon.h"
#include "GameActivity.h"
#include "System.h"

#include <SDL3/SDL.h>
#include <string>
#include <unordered_map>
Expand Down Expand Up @@ -82,7 +80,7 @@ int UInputMan::Initialize() {

int controllerIndex = 0;
int joystickCount = 0;
SDL_JoystickID* joysticks = SDL_GetJoysticks(&joystickCount);
SDL_JoystickID* joysticks = SDL_GetGamepads(&joystickCount);

for (size_t index = 0; index < std::min(joystickCount, static_cast<int>(Players::MaxPlayerCount)); ++index) {
if (SDL_IsGamepad(joysticks[index])) {
Expand Down Expand Up @@ -997,11 +995,12 @@ int UInputMan::Update() {
}
}
break;
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
case SDL_EVENT_GAMEPAD_BUTTON_UP:
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
case SDL_EVENT_JOYSTICK_BUTTON_UP:
if (std::vector<Gamepad>::iterator device = std::find(s_PrevJoystickStates.begin(), s_PrevJoystickStates.end(), (inputEvent.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN || inputEvent.type == SDL_EVENT_GAMEPAD_BUTTON_UP) ? inputEvent.gbutton.which : inputEvent.jbutton.which); device != s_PrevJoystickStates.end()) {
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
case SDL_EVENT_GAMEPAD_BUTTON_UP: {
bool joystickEvent = (inputEvent.type == SDL_EVENT_JOYSTICK_BUTTON_DOWN || inputEvent.type == SDL_EVENT_JOYSTICK_BUTTON_UP);
if (std::vector<Gamepad>::iterator device = std::find(s_PrevJoystickStates.begin(), s_PrevJoystickStates.end(), joystickEvent ? inputEvent.jbutton.which : inputEvent.gbutton.which); device != s_PrevJoystickStates.end()) {
int button = -1;
int down = false;
if (SDL_IsGamepad(device->m_DeviceIndex)) {
Expand All @@ -1020,10 +1019,14 @@ int UInputMan::Update() {
device->m_Buttons[button] = down;
}
break;
}
case SDL_EVENT_JOYSTICK_ADDED:
case SDL_EVENT_GAMEPAD_ADDED: {
HandleGamepadHotPlug(inputEvent.jdevice.which);
break;
}
case SDL_EVENT_JOYSTICK_REMOVED:
case SDL_EVENT_GAMEPAD_REMOVED:
if (std::vector<Gamepad>::iterator prevDevice = std::find(s_PrevJoystickStates.begin(), s_PrevJoystickStates.end(), inputEvent.jdevice.which); prevDevice != s_PrevJoystickStates.end()) {
g_ConsoleMan.PrintString("INFO: Gamepad " + std::to_string(prevDevice->m_DeviceIndex + 1) + " disconnected!");
SDL_CloseGamepad(SDL_GetGamepadFromID(prevDevice->m_JoystickID));
Expand Down Expand Up @@ -1281,17 +1284,19 @@ void UInputMan::UpdateJoystickDigitalAxis() {
}
}

void UInputMan::HandleGamepadHotPlug(int deviceIndex) {
void UInputMan::HandleGamepadHotPlug(SDL_JoystickID deviceIndex) {
SDL_Joystick* controller = nullptr;
int controllerIndex = 0;

for (controllerIndex = 0; controllerIndex < s_PrevJoystickStates.size(); ++controllerIndex) {
if (s_PrevJoystickStates[controllerIndex].m_DeviceIndex == deviceIndex || s_PrevJoystickStates[controllerIndex].m_DeviceIndex == -1) {
if (s_PrevJoystickStates[controllerIndex].m_JoystickID == deviceIndex) {
return;
}
if (s_PrevJoystickStates[controllerIndex].m_JoystickID == -1) {
if (SDL_IsGamepad(deviceIndex)) {
SDL_Gamepad* gameController = SDL_OpenGamepad(deviceIndex);
if (!gameController) {
std::string connectString = s_PrevJoystickStates[controllerIndex].m_DeviceIndex == deviceIndex ? "reconnect" : "connect";
g_ConsoleMan.PrintString("ERROR: Failed to " + connectString + " Gamepad " + std::to_string(controllerIndex + 1));
g_ConsoleMan.PrintString("ERROR: Failed to connect Gamepad!");
break;
}
controller = SDL_GetGamepadJoystick(gameController);
Expand All @@ -1300,12 +1305,10 @@ void UInputMan::HandleGamepadHotPlug(int deviceIndex) {
controller = SDL_OpenJoystick(deviceIndex);
}
if (!controller) {
std::string connectString = s_PrevJoystickStates[controllerIndex].m_DeviceIndex == deviceIndex ? "reconnect" : "connect";
g_ConsoleMan.PrintString("ERROR: Failed to " + connectString + " Gamepad " + std::to_string(controllerIndex + 1));
g_ConsoleMan.PrintString("ERROR: Failed to connect Gamepad!");
break;
}
std::string connectString = s_PrevJoystickStates[controllerIndex].m_DeviceIndex == deviceIndex ? " reconnected" : " connected";
g_ConsoleMan.PrintString("INFO: Gamepad " + std::to_string(controllerIndex + 1) + connectString);
g_ConsoleMan.PrintString("INFO: Gamepad " + std::to_string(controllerIndex + 1) + "connected.");
break;
}
}
Expand All @@ -1315,7 +1318,6 @@ void UInputMan::HandleGamepadHotPlug(int deviceIndex) {
}

if (controller) {
SDL_JoystickID id = SDL_GetJoystickID(controller);
int numAxis = 0;
int numButtons = 0;
if (SDL_IsGamepad(deviceIndex)) {
Expand All @@ -1325,8 +1327,8 @@ void UInputMan::HandleGamepadHotPlug(int deviceIndex) {
numAxis = SDL_GetNumJoystickAxes(controller);
numButtons = SDL_GetNumJoystickButtons(controller);
}
s_PrevJoystickStates[controllerIndex] = Gamepad(deviceIndex, id, numAxis, numButtons);
s_ChangedJoystickStates[controllerIndex] = Gamepad(deviceIndex, id, numAxis, numButtons);
s_PrevJoystickStates[controllerIndex] = Gamepad(controllerIndex, deviceIndex, numAxis, numButtons);
s_ChangedJoystickStates[controllerIndex] = Gamepad(controllerIndex, deviceIndex, numAxis, numButtons);
m_NumJoysticks++;
}
}
3 changes: 2 additions & 1 deletion Source/Managers/UInputMan.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "Constants.h"
#include "SDL3/SDL_joystick.h"
#include "SDL3/SDL_keycode.h"
#include "SDL3/SDL_scancode.h"
#include "Singleton.h"
Expand Down Expand Up @@ -606,7 +607,7 @@ namespace RTE {

/// Connect a joystick or gamepad device and add it to the joystick list if a slot is available (up to max player count).
/// @param deviceIndex The device index (generated by the connected event or a value up to SDL_NumJoysticks()).
void HandleGamepadHotPlug(int deviceIndex);
void HandleGamepadHotPlug(SDL_JoystickID deviceIndex);
#pragma endregion

/// Clears all the member variables of this UInputMan, effectively resetting the members of this abstraction level only.
Expand Down
4 changes: 0 additions & 4 deletions imgui.ini

This file was deleted.