Skip to content

Commit 0b3496f

Browse files
NintorchEIREXEXavier Sellierakien-mga
committed
Add support for SDL3 joystick input driver
Made possible by EIREXE, xsellier and the SDL team. This commit includes statically linked SDL3 for Windows, Linux and macOS. The vendored copy of SDL3 was setup to only build the required subsystems for gamepad/joystick support, with some patches to be able to make it as minimal as possible and reduce the impact on binary size and code size. Co-authored-by: Álex Román Núñez <[email protected]> Co-authored-by: Xavier Sellier <[email protected]> Co-authored-by: Rémi Verschelde <[email protected]>
1 parent 987832b commit 0b3496f

File tree

330 files changed

+154930
-1561
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

330 files changed

+154930
-1561
lines changed

COPYRIGHT.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,16 @@ Comment: RVO2
541541
Copyright: 2016, University of North Carolina at Chapel Hill
542542
License: Apache-2.0
543543

544+
Files: thirdparty/sdl/*
545+
Comment: SDL
546+
Copyright: 1997-2025, Sam Lantinga
547+
License: Zlib
548+
549+
Files: thirdparty/sdl/hidapi/*
550+
Comment: hidapi
551+
Copyright: 2010, Alan Ott, Signal 11 Software
552+
License: BSD-3-Clause
553+
544554
Files: thirdparty/spirv-cross/*
545555
Comment: SPIRV-Cross
546556
Copyright: 2015-2021, Arm Limited

SConstruct

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -194,16 +194,14 @@ opts.Add(
194194
opts.Add(BoolVariable("minizip", "Enable ZIP archive support using minizip", True))
195195
opts.Add(BoolVariable("brotli", "Enable Brotli for decompression and WOFF2 fonts support", True))
196196
opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver on supported platforms", False))
197-
opts.Add(BoolVariable("vulkan", "Enable the vulkan rendering driver", True))
197+
opts.Add(BoolVariable("vulkan", "Enable the Vulkan rendering driver", True))
198198
opts.Add(BoolVariable("opengl3", "Enable the OpenGL/GLES3 rendering driver", True))
199199
opts.Add(BoolVariable("d3d12", "Enable the Direct3D 12 rendering driver on supported platforms", False))
200200
opts.Add(BoolVariable("metal", "Enable the Metal rendering driver on supported platforms (Apple arm64 only)", False))
201201
opts.Add(BoolVariable("use_volk", "Use the volk library to load the Vulkan loader dynamically", True))
202-
opts.Add(BoolVariable("disable_exceptions", "Force disabling exception handling code", True))
203-
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
204-
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
205202
opts.Add(BoolVariable("accesskit", "Use AccessKit C SDK", True))
206203
opts.Add(("accesskit_sdk_path", "Path to the AccessKit C SDK", ""))
204+
opts.Add(BoolVariable("sdl", "Enable the SDL3 input driver", True))
207205

208206
# Advanced options
209207
opts.Add(
@@ -233,6 +231,7 @@ opts.Add("object_prefix", "Custom prefix added to the base filename of all gener
233231
opts.Add(BoolVariable("vsproj", "Generate a Visual Studio solution", False))
234232
opts.Add("vsproj_name", "Name of the Visual Studio solution", "godot")
235233
opts.Add("import_env_vars", "A comma-separated list of environment variables to copy from the outer environment.", "")
234+
opts.Add(BoolVariable("disable_exceptions", "Force disabling exception handling code", True))
236235
opts.Add(BoolVariable("disable_3d", "Disable 3D nodes for a smaller executable", False))
237236
opts.Add(BoolVariable("disable_advanced_gui", "Disable advanced GUI nodes and behaviors", False))
238237
opts.Add(BoolVariable("disable_physics_2d", "Disable 2D physics nodes and server", False))
@@ -241,6 +240,8 @@ opts.Add(BoolVariable("disable_navigation_2d", "Disable 2D navigation features",
241240
opts.Add(BoolVariable("disable_navigation_3d", "Disable 3D navigation features", False))
242241
opts.Add(BoolVariable("disable_xr", "Disable XR nodes and server", False))
243242
opts.Add("build_profile", "Path to a file containing a feature build profile", "")
243+
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
244+
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
244245
opts.Add(BoolVariable("modules_enabled_by_default", "If no, disable all modules except ones explicitly enabled", True))
245246
opts.Add(BoolVariable("no_editor_splash", "Don't use the custom splash screen for the editor", True))
246247
opts.Add(
@@ -275,6 +276,7 @@ opts.Add(BoolVariable("builtin_msdfgen", "Use the built-in MSDFgen library", Tru
275276
opts.Add(BoolVariable("builtin_glslang", "Use the built-in glslang library", True))
276277
opts.Add(BoolVariable("builtin_graphite", "Use the built-in Graphite library", True))
277278
opts.Add(BoolVariable("builtin_harfbuzz", "Use the built-in HarfBuzz library", True))
279+
opts.Add(BoolVariable("builtin_sdl", "Use the built-in SDL library", True))
278280
opts.Add(BoolVariable("builtin_icu4c", "Use the built-in ICU library", True))
279281
opts.Add(BoolVariable("builtin_libjpeg_turbo", "Use the built-in libjpeg-turbo library", True))
280282
opts.Add(BoolVariable("builtin_libogg", "Use the built-in libogg library", True))

core/input/input.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -587,9 +587,13 @@ void Input::joy_connection_changed(int p_idx, bool p_connected, const String &p_
587587
js.uid = uidname;
588588
js.connected = true;
589589
int mapping = fallback_mapping;
590-
for (int i = 0; i < map_db.size(); i++) {
591-
if (js.uid == map_db[i].uid) {
592-
mapping = i;
590+
// Bypass the mapping system if the joypad's mapping is already handled by its driver
591+
// (for example, the SDL joypad driver).
592+
if (!p_joypad_info.get("mapping_handled", false)) {
593+
for (int i = 0; i < map_db.size(); i++) {
594+
if (js.uid == map_db[i].uid) {
595+
mapping = i;
596+
}
593597
}
594598
}
595599
_set_joypad_mapping(js, mapping);

drivers/SCsub

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ if env["metal"]:
6060
Exit(255)
6161
SConscript("metal/SCsub")
6262

63+
# Input drivers
64+
if env["sdl"] and env["platform"] in ["linuxbsd", "macos", "windows"]:
65+
# TODO: Evaluate support for Android, iOS, and Web.
66+
SConscript("sdl/SCsub")
67+
6368
# Core dependencies
6469
SConscript("png/SCsub")
6570

drivers/sdl/SCsub

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
#!/usr/bin/env python
2+
from misc.utility.scons_hints import *
3+
4+
Import("env")
5+
6+
env_sdl = env.Clone()
7+
8+
# Thirdparty source files
9+
10+
thirdparty_obj = []
11+
12+
if env["builtin_sdl"]:
13+
thirdparty_dir = "#thirdparty/sdl/"
14+
15+
# Use our own SDL_build_config_private.h.
16+
env_sdl.Prepend(CPPDEFINES=["SDL_PLATFORM_PRIVATE"])
17+
18+
# Common sources.
19+
20+
env_sdl.Prepend(
21+
CPPPATH=[
22+
thirdparty_dir,
23+
thirdparty_dir + "include",
24+
thirdparty_dir + "include/build_config",
25+
".", # SDL_build_config_private.h
26+
]
27+
)
28+
29+
thirdparty_sources = [
30+
"SDL.c",
31+
"SDL_assert.c",
32+
"SDL_error.c",
33+
"SDL_guid.c",
34+
"SDL_hashtable.c",
35+
"SDL_hints.c",
36+
"SDL_list.c",
37+
"SDL_log.c",
38+
"SDL_properties.c",
39+
"SDL_utils.c",
40+
"atomic/SDL_atomic.c",
41+
"atomic/SDL_spinlock.c",
42+
"events/SDL_events.c",
43+
"events/SDL_eventwatch.c",
44+
"haptic/SDL_haptic.c",
45+
"io/SDL_iostream.c",
46+
"joystick/SDL_gamepad.c",
47+
"joystick/SDL_joystick.c",
48+
"joystick/SDL_steam_virtual_gamepad.c",
49+
"joystick/controller_type.c",
50+
"libm/e_atan2.c",
51+
"libm/e_exp.c",
52+
"libm/e_fmod.c",
53+
"libm/e_log.c",
54+
"libm/e_log10.c",
55+
"libm/e_pow.c",
56+
"libm/e_rem_pio2.c",
57+
"libm/e_sqrt.c",
58+
"libm/k_cos.c",
59+
"libm/k_rem_pio2.c",
60+
"libm/k_sin.c",
61+
"libm/k_tan.c",
62+
"libm/s_atan.c",
63+
"libm/s_copysign.c",
64+
"libm/s_cos.c",
65+
"libm/s_fabs.c",
66+
"libm/s_floor.c",
67+
"libm/s_isinf.c",
68+
"libm/s_isinff.c",
69+
"libm/s_isnan.c",
70+
"libm/s_isnanf.c",
71+
"libm/s_modf.c",
72+
"libm/s_scalbn.c",
73+
"libm/s_sin.c",
74+
"libm/s_tan.c",
75+
"sensor/SDL_sensor.c",
76+
"sensor/dummy/SDL_dummysensor.c",
77+
"stdlib/SDL_crc16.c",
78+
"stdlib/SDL_crc32.c",
79+
"stdlib/SDL_getenv.c",
80+
"stdlib/SDL_iconv.c",
81+
"stdlib/SDL_malloc.c",
82+
"stdlib/SDL_memcpy.c",
83+
"stdlib/SDL_memmove.c",
84+
"stdlib/SDL_memset.c",
85+
"stdlib/SDL_mslibc.c",
86+
"stdlib/SDL_murmur3.c",
87+
"stdlib/SDL_qsort.c",
88+
"stdlib/SDL_random.c",
89+
"stdlib/SDL_stdlib.c",
90+
"stdlib/SDL_string.c",
91+
"stdlib/SDL_strtokr.c",
92+
"thread/SDL_thread.c",
93+
"thread/generic/SDL_syscond.c",
94+
"thread/generic/SDL_sysrwlock.c",
95+
"thread/generic/SDL_systhread.c",
96+
"timer/SDL_timer.c",
97+
]
98+
99+
# HIDAPI
100+
thirdparty_sources += [
101+
"hidapi/SDL_hidapi.c",
102+
"joystick/hidapi/SDL_hidapi_combined.c",
103+
"joystick/hidapi/SDL_hidapi_gamecube.c",
104+
"joystick/hidapi/SDL_hidapijoystick.c",
105+
"joystick/hidapi/SDL_hidapi_luna.c",
106+
"joystick/hidapi/SDL_hidapi_ps3.c",
107+
"joystick/hidapi/SDL_hidapi_ps4.c",
108+
"joystick/hidapi/SDL_hidapi_ps5.c",
109+
"joystick/hidapi/SDL_hidapi_rumble.c",
110+
"joystick/hidapi/SDL_hidapi_shield.c",
111+
"joystick/hidapi/SDL_hidapi_stadia.c",
112+
"joystick/hidapi/SDL_hidapi_steam.c",
113+
"joystick/hidapi/SDL_hidapi_steamdeck.c",
114+
"joystick/hidapi/SDL_hidapi_steam_hori.c",
115+
"joystick/hidapi/SDL_hidapi_switch.c",
116+
"joystick/hidapi/SDL_hidapi_wii.c",
117+
"joystick/hidapi/SDL_hidapi_xbox360.c",
118+
"joystick/hidapi/SDL_hidapi_xbox360w.c",
119+
"joystick/hidapi/SDL_hidapi_xboxone.c",
120+
]
121+
122+
# Platform specific sources.
123+
124+
if env["platform"] == "linuxbsd":
125+
# TODO: Check support for BSD systems.
126+
env_sdl.Append(CPPDEFINES=["SDL_PLATFORM_LINUX"])
127+
thirdparty_sources += [
128+
"core/linux/SDL_dbus.c",
129+
"core/linux/SDL_evdev.c",
130+
"core/linux/SDL_evdev_capabilities.c",
131+
"core/linux/SDL_evdev_kbd.c",
132+
"core/linux/SDL_fcitx.c",
133+
"core/linux/SDL_ibus.c",
134+
"core/linux/SDL_ime.c",
135+
"core/linux/SDL_system_theme.c",
136+
"core/linux/SDL_threadprio.c",
137+
"core/linux/SDL_udev.c",
138+
"core/unix/SDL_appid.c",
139+
"core/unix/SDL_poll.c",
140+
"haptic/linux/SDL_syshaptic.c",
141+
"joystick/linux/SDL_sysjoystick.c",
142+
"loadso/dlopen/SDL_sysloadso.c",
143+
"thread/pthread/SDL_syscond.c",
144+
"thread/pthread/SDL_sysmutex.c",
145+
"thread/pthread/SDL_sysrwlock.c",
146+
"thread/pthread/SDL_syssem.c",
147+
"thread/pthread/SDL_systhread.c",
148+
"thread/pthread/SDL_systls.c",
149+
"timer/unix/SDL_systimer.c",
150+
]
151+
152+
elif env["platform"] == "macos":
153+
env_sdl.Append(CPPDEFINES=["SDL_PLATFORM_MACOS"])
154+
thirdparty_sources += [
155+
"core/unix/SDL_appid.c",
156+
"core/unix/SDL_poll.c",
157+
"haptic/darwin/SDL_syshaptic.c",
158+
"joystick/darwin/SDL_iokitjoystick.c",
159+
"joystick/apple/SDL_mfijoystick.m",
160+
"thread/pthread/SDL_syscond.c",
161+
"thread/pthread/SDL_sysmutex.c",
162+
"thread/pthread/SDL_sysrwlock.c",
163+
"thread/pthread/SDL_syssem.c",
164+
"thread/pthread/SDL_systhread.c",
165+
"thread/pthread/SDL_systls.c",
166+
"timer/unix/SDL_systimer.c",
167+
]
168+
169+
elif env["platform"] == "windows":
170+
env_sdl.Append(CPPDEFINES=["SDL_PLATFORM_WINDOWS"])
171+
thirdparty_sources += [
172+
"core/windows/SDL_gameinput.c",
173+
"core/windows/SDL_hid.c",
174+
"core/windows/SDL_immdevice.c",
175+
"core/windows/SDL_windows.c",
176+
"core/windows/SDL_xinput.c",
177+
"core/windows/pch.c",
178+
"haptic/windows/SDL_dinputhaptic.c",
179+
"haptic/windows/SDL_windowshaptic.c",
180+
"joystick/windows/SDL_dinputjoystick.c",
181+
"joystick/windows/SDL_rawinputjoystick.c",
182+
"joystick/windows/SDL_windows_gaming_input.c",
183+
"joystick/windows/SDL_windowsjoystick.c",
184+
"joystick/windows/SDL_xinputjoystick.c",
185+
"thread/windows/SDL_syscond_cv.c",
186+
"thread/windows/SDL_sysmutex.c",
187+
"thread/windows/SDL_sysrwlock_srw.c",
188+
"thread/windows/SDL_syssem.c",
189+
"thread/windows/SDL_systhread.c",
190+
"thread/windows/SDL_systls.c",
191+
"timer/windows/SDL_systimer.c",
192+
]
193+
194+
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
195+
196+
env_thirdparty = env_sdl.Clone()
197+
env_thirdparty.disable_warnings()
198+
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
199+
env.drivers_sources += thirdparty_obj
200+
201+
# Godot source files
202+
203+
driver_obj = []
204+
205+
env_sdl.add_source_files(driver_obj, "*.cpp")
206+
env.drivers_sources += driver_obj
207+
208+
# Needed to force rebuilding the driver files when the thirdparty library is updated.
209+
env.Depends(driver_obj, thirdparty_obj)

0 commit comments

Comments
 (0)