Skip to content

Commit a96b224

Browse files
The-Night-WatchArthur
and
Arthur
authored
Add gamepad support to PLATFORM_DESKTOP_SDL (#3776)
Co-authored-by: Arthur <[email protected]>
1 parent 868d515 commit a96b224

File tree

1 file changed

+150
-16
lines changed

1 file changed

+150
-16
lines changed

src/platforms/rcore_desktop_sdl.c

+150-16
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ typedef struct {
6464
SDL_Window *window;
6565
SDL_GLContext glContext;
6666

67-
SDL_Joystick *gamepad;
67+
SDL_Joystick *gamepad[MAX_GAMEPADS];
6868
SDL_Cursor *cursor;
6969
bool cursorRelative;
7070
} PlatformData;
@@ -978,8 +978,18 @@ void PollInputEvents(void)
978978
else CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
979979

980980
// Reset last gamepad button/axis registered state
981-
CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_UNKNOWN;
982-
for (int i = 0; i < MAX_GAMEPADS; i++) CORE.Input.Gamepad.axisCount[i] = 0;
981+
for (int i = 0; (i < SDL_NumJoysticks()) && (i < MAX_GAMEPADS); i++)
982+
{
983+
// Check if gamepad is available
984+
if (CORE.Input.Gamepad.ready[i])
985+
{
986+
// Register previous gamepad button states
987+
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++)
988+
{
989+
CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
990+
}
991+
}
992+
}
983993

984994
// Register previous touch states
985995
for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i];
@@ -1215,20 +1225,134 @@ void PollInputEvents(void)
12151225
} break;
12161226

12171227
// Check gamepad events
1218-
case SDL_JOYAXISMOTION:
1228+
case SDL_JOYDEVICEADDED:
12191229
{
1220-
// Motion on gamepad 0
1221-
if (event.jaxis.which == 0)
1222-
{
1223-
// X axis motion
1224-
if (event.jaxis.axis == 0)
1230+
int jid = event.jdevice.which;
1231+
if (!CORE.Input.Gamepad.ready[jid] && (jid < MAX_GAMEPADS)) {
1232+
platform.gamepad[jid] = SDL_JoystickOpen(jid);
1233+
1234+
if (platform.gamepad[jid])
12251235
{
1226-
//...
1236+
CORE.Input.Gamepad.ready[jid] = true;
1237+
CORE.Input.Gamepad.axisCount[jid] = SDL_JoystickNumAxes(platform.gamepad[jid]);
1238+
CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
1239+
CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
1240+
strncpy(CORE.Input.Gamepad.name[jid], SDL_JoystickName(platform.gamepad[jid]), 63);
1241+
CORE.Input.Gamepad.name[jid][63] = '\0';
12271242
}
1228-
// Y axis motion
1229-
else if (event.jaxis.axis == 1)
1243+
else
12301244
{
1231-
//...
1245+
TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
1246+
}
1247+
}
1248+
} break;
1249+
case SDL_JOYDEVICEREMOVED:
1250+
{
1251+
int jid = event.jdevice.which;
1252+
if (jid == SDL_JoystickInstanceID(platform.gamepad[jid])) {
1253+
SDL_JoystickClose(platform.gamepad[jid]);
1254+
platform.gamepad[jid] = SDL_JoystickOpen(0);
1255+
CORE.Input.Gamepad.ready[jid] = false;
1256+
memset(CORE.Input.Gamepad.name[jid], 0, 64);
1257+
}
1258+
} break;
1259+
case SDL_JOYBUTTONDOWN:
1260+
{
1261+
int button = -1;
1262+
1263+
switch (event.jbutton.button)
1264+
{
1265+
case SDL_CONTROLLER_BUTTON_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break;
1266+
case SDL_CONTROLLER_BUTTON_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; break;
1267+
case SDL_CONTROLLER_BUTTON_A: button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN; break;
1268+
case SDL_CONTROLLER_BUTTON_X: button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT; break;
1269+
1270+
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: button = GAMEPAD_BUTTON_LEFT_TRIGGER_1; break;
1271+
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_1; break;
1272+
1273+
case SDL_CONTROLLER_BUTTON_BACK: button = GAMEPAD_BUTTON_MIDDLE_LEFT; break;
1274+
case SDL_CONTROLLER_BUTTON_GUIDE: button = GAMEPAD_BUTTON_MIDDLE; break;
1275+
case SDL_CONTROLLER_BUTTON_START: button = GAMEPAD_BUTTON_MIDDLE_RIGHT; break;
1276+
1277+
case SDL_CONTROLLER_BUTTON_DPAD_UP: button = GAMEPAD_BUTTON_LEFT_FACE_UP; break;
1278+
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT; break;
1279+
case SDL_CONTROLLER_BUTTON_DPAD_DOWN: button = GAMEPAD_BUTTON_LEFT_FACE_DOWN; break;
1280+
case SDL_CONTROLLER_BUTTON_DPAD_LEFT: button = GAMEPAD_BUTTON_LEFT_FACE_LEFT; break;
1281+
1282+
case SDL_CONTROLLER_BUTTON_LEFTSTICK: button = GAMEPAD_BUTTON_LEFT_THUMB; break;
1283+
case SDL_CONTROLLER_BUTTON_RIGHTSTICK: button = GAMEPAD_BUTTON_RIGHT_THUMB; break;
1284+
default: break;
1285+
}
1286+
1287+
if (button >= 0)
1288+
{
1289+
CORE.Input.Gamepad.currentButtonState[event.jbutton.which][button] = 1;
1290+
CORE.Input.Gamepad.lastButtonPressed = button;
1291+
}
1292+
} break;
1293+
case SDL_JOYBUTTONUP:
1294+
{
1295+
int button = -1;
1296+
1297+
switch (event.jbutton.button)
1298+
{
1299+
case SDL_CONTROLLER_BUTTON_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break;
1300+
case SDL_CONTROLLER_BUTTON_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; break;
1301+
case SDL_CONTROLLER_BUTTON_A: button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN; break;
1302+
case SDL_CONTROLLER_BUTTON_X: button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT; break;
1303+
1304+
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: button = GAMEPAD_BUTTON_LEFT_TRIGGER_1; break;
1305+
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_1; break;
1306+
1307+
case SDL_CONTROLLER_BUTTON_BACK: button = GAMEPAD_BUTTON_MIDDLE_LEFT; break;
1308+
case SDL_CONTROLLER_BUTTON_GUIDE: button = GAMEPAD_BUTTON_MIDDLE; break;
1309+
case SDL_CONTROLLER_BUTTON_START: button = GAMEPAD_BUTTON_MIDDLE_RIGHT; break;
1310+
1311+
case SDL_CONTROLLER_BUTTON_DPAD_UP: button = GAMEPAD_BUTTON_LEFT_FACE_UP; break;
1312+
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT; break;
1313+
case SDL_CONTROLLER_BUTTON_DPAD_DOWN: button = GAMEPAD_BUTTON_LEFT_FACE_DOWN; break;
1314+
case SDL_CONTROLLER_BUTTON_DPAD_LEFT: button = GAMEPAD_BUTTON_LEFT_FACE_LEFT; break;
1315+
1316+
case SDL_CONTROLLER_BUTTON_LEFTSTICK: button = GAMEPAD_BUTTON_LEFT_THUMB; break;
1317+
case SDL_CONTROLLER_BUTTON_RIGHTSTICK: button = GAMEPAD_BUTTON_RIGHT_THUMB; break;
1318+
default: break;
1319+
}
1320+
1321+
if (button >= 0)
1322+
{
1323+
CORE.Input.Gamepad.currentButtonState[event.jbutton.which][button] = 0;
1324+
if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
1325+
}
1326+
} break;
1327+
case SDL_JOYAXISMOTION:
1328+
{
1329+
int axis = -1;
1330+
1331+
switch (event.jaxis.axis)
1332+
{
1333+
case SDL_CONTROLLER_AXIS_LEFTX: axis = GAMEPAD_AXIS_LEFT_X; break;
1334+
case SDL_CONTROLLER_AXIS_LEFTY: axis = GAMEPAD_AXIS_LEFT_Y; break;
1335+
case SDL_CONTROLLER_AXIS_RIGHTX: axis = GAMEPAD_AXIS_RIGHT_X; break;
1336+
case SDL_CONTROLLER_AXIS_RIGHTY: axis = GAMEPAD_AXIS_RIGHT_Y; break;
1337+
case SDL_CONTROLLER_AXIS_TRIGGERLEFT: axis = GAMEPAD_AXIS_LEFT_TRIGGER; break;
1338+
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: axis = GAMEPAD_AXIS_RIGHT_TRIGGER; break;
1339+
default: break;
1340+
}
1341+
1342+
if (axis >= 0)
1343+
{
1344+
// SDL axis value range is -32768 to 32767, we normalize it to RayLib's -1.0 to 1.0f range
1345+
float value = event.jaxis.value / (float) 32767;
1346+
CORE.Input.Gamepad.axisState[event.jaxis.which][axis] = value;
1347+
1348+
// Register button state for triggers in addition to their axes
1349+
if ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER))
1350+
{
1351+
int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER) ? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2;
1352+
int pressed = (value > 0.1f);
1353+
CORE.Input.Gamepad.currentButtonState[event.jaxis.which][button] = pressed;
1354+
if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;
1355+
else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
12321356
}
12331357
}
12341358
} break;
@@ -1405,10 +1529,20 @@ int InitPlatform(void)
14051529

14061530
// Initialize input events system
14071531
//----------------------------------------------------------------------------
1408-
if (SDL_NumJoysticks() >= 1)
1532+
// Initialize gamepads
1533+
for (int i = 0; (i < SDL_NumJoysticks()) && (i < MAX_GAMEPADS); i++)
14091534
{
1410-
platform.gamepad = SDL_JoystickOpen(0);
1411-
//if (platform.gamepadgamepad == NULL) TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
1535+
platform.gamepad[i] = SDL_JoystickOpen(i);
1536+
if (platform.gamepad[i])
1537+
{
1538+
CORE.Input.Gamepad.ready[i] = true;
1539+
CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(platform.gamepad[i]);
1540+
CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
1541+
CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
1542+
strncpy(CORE.Input.Gamepad.name[i], SDL_JoystickName(platform.gamepad[i]), 63);
1543+
CORE.Input.Gamepad.name[i][63] = '\0';
1544+
}
1545+
else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
14121546
}
14131547

14141548
// Disable mouse events being interpreted as touch events

0 commit comments

Comments
 (0)