feat(input): Implement SDL3 input and window management#2639
feat(input): Implement SDL3 input and window management#2639githubawn wants to merge 29 commits into
Conversation
a785545 to
7cc0861
Compare
|
| Filename | Overview |
|---|---|
| Core/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Input.cpp | New file: implements SDL3Mouse, SDL3Keyboard, and SDL3InputManager with ring-buffer event queuing and gamepad-to-keyboard/mouse mapping; inline if bodies inside lambdas violate the team's debuggability rule |
| Core/GameEngineDevice/Source/SDL3Device/Common/SDL3GameEngine.cpp | New file: SDL3GameEngine lifecycle (init/reset/update/poll), text input forwarding with correct UTF-8 decode, headless guard properly deferred past GameEngine::init() |
| Core/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Cursor.cpp | New file: ANI/animated cursor loading via SDL3_image; delegates animation lifetime to SDL3 (SDL_CreateAnimatedCursor), correct cleanup in AnimatedCursor destructor |
| GeneralsMD/Code/Main/WinMain.cpp | SDL3 path added: window creation, splash screen blit, SDL3GameEngine factory; two new lines pass NULL instead of nullptr to SDL3 C++ APIs |
| GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DGameClient.h | Conditional compile split: SDL3 path creates SDL3Mouse/SDL3Keyboard; Win32 path retains W3DMouse/DirectInputKeyboard; W3DSnow.h correctly moved outside the guard |
| Core/GameEngine/Include/GameClient/Display.h | Adds getViewportRect() virtual stub to Display base class, guarded by RTS_SDL3_ENABLE, returns FALSE for the no-letterbox default path |
| cmake/sdl3.cmake | New cmake module: vcpkg find_package with FetchContent fallback; SDL3 alias targets and static link helper added; SDL3_image lacks OVERRIDE_FIND_PACKAGE so mixed found/not-found states could redundantly trigger FetchContent for both libs |
| vcpkg.json | Adds sdl3 and sdl3-image dependencies with overrides pinned to 3.4.10 and 3.4.4; builtin-baseline correctly migrated to vcpkg-configuration.json default-registry |
| vcpkg-lock.json | Lock file regenerated: sdl3@3.4.10 and sdl3-image@3.4.4 now match vcpkg.json overrides; vcpkg-cmake-config entry added as expected new transitive dep |
| vcpkg-configuration.json | New file: default-registry carries the previous builtin-baseline, secondary registry pins SDL3/SDL3_image to a baseline with 3.4.x packages |
Sequence Diagram
sequenceDiagram
participant WM as WinMain
participant SGE as SDL3GameEngine
participant SIM as SDL3InputManager
participant SMouse as SDL3Mouse
participant SKbd as SDL3Keyboard
participant GP as Gamepad
WM->>SGE: CreateGameEngine() → new SDL3GameEngine
WM->>WM: SDL_Init + SDL_CreateWindow
SGE->>SIM: new SDL3InputManager(m_SDLWindow)
SIM->>SIM: openFirstGamepad()
loop Game loop
SGE->>SGE: update()
SGE->>SIM: update()
SIM->>SIM: SDL_PollEvent()
SIM->>SIM: addMouseSDLEvent / addKeyboardSDLEvent
SIM->>SIM: processGamepadInput()
GP-->>SIM: axis/button state
SIM->>SIM: virtualPulseKey / virtualPulseMouse
note over SIM: synthetic events injected into ring buffers
SMouse->>SIM: getNextMouseEvent()
SKbd->>SIM: getNextKeyboardEvent()
SMouse->>SMouse: translateEvent → scaleMouseCoordinates
SKbd->>SKbd: translateScanCodeToKeyVal
end
Reviews (30): Last reviewed commit: "Move SDL3GameEngine files to Common dire..." | Re-trigger Greptile
|
|
||
| namespace { | ||
|
|
||
| Bool DecodeNextUtf8Codepoint(const char* text, size_t length, size_t& offset, UnsignedInt& outCodepoint) |
There was a problem hiding this comment.
Do we need this, maybe better placed in UnicodeString? Or some other helper if it's generic stuff
There was a problem hiding this comment.
Good point.
I looked at #2045 and #2528 which are working on UTF-8 infrastructure.
If one of those lands first, forwardTextInputEvent could use the bulk Utf8_To_Utf16Le conversion and iterate the resulting wchar_t string directly, making this function unnecessary.
Happy to refactor once there's a clear winner between those two. For now it's self-contained here.
e365605 to
627ef23
Compare
Consolidated all work from the test/sdl3-backport branch into a single atomic commit: - Centralized input management via SDL3InputManager. - Hardened Ani/RIFF cursor loading with robust bounds checking. - Native Gamepad support with analogue stick-to-mouse emulation and custom RTS mappings. - Modernized focus and capture handling for better stability during Alt-Tab. - Standardized and secured string operations throughout the SDL3 path.
Consolidated all work from the test/sdl3-backport branch into a single atomic commit: - Centralized input management via SDL3InputManager. - Hardened Ani/RIFF cursor loading with robust bounds checking. - Native Gamepad support with analogue stick-to-mouse emulation and custom RTS mappings. - Modernized focus and capture handling for better stability during Alt-Tab. - Standardized and secured string operations throughout the SDL3 path. - Updated credit attribution (fbraz3).
eb9908a to
534e694
Compare
xezon
left a comment
There was a problem hiding this comment.
This needs polishing. Not yet reviewed extensively until the obvious style issues are fixed.
|
|
||
| #if SAGE_USE_SDL3 | ||
| #include <SDL3/SDL.h> | ||
| #include "SDL3GameEngine.h" |
There was a problem hiding this comment.
This SDL code is added to a file called WinMain (for Windows). Is this intentional?
There was a problem hiding this comment.
This was intentional. The SDL3 input backend is designed with a future splitscreen skirmish feature in mind, supporting multiple simultaneous mice/keyboards so that 2–8 players can share a single machine rather than needing separate computers, either controlling the same or unique armies.
SDL3 input doesn't function without an SDL window, so creating the window here was the minimum viable approach to make the input backend functional. The Win32/DirectInput path doesn't lend itself to the multi-device model SDL3 enables, which is why SDL3 is the foundation for this direction.
There was a problem hiding this comment.
Shouldn't we have a SDL3Main then? I have seen other forks do that.
Maybe make WinMain and SDL3Main share code if they do. But basically get rid of the ifdef approach.
|
|
||
| ParticleSystemManager* SDL3GameEngine::createParticleSystemManager(Bool dummy) | ||
| { | ||
| (void)dummy; |
|
|
||
| namespace { | ||
|
|
||
| Bool DecodeNextUtf8Codepoint(const char* text, size_t length, size_t& offset, UnsignedInt& outCodepoint) |
There was a problem hiding this comment.
This function looks out of place. Bobtista was also working on Utf8 decoding in another change. It would be good to have this as a utility somewhere accessible engine wide, and not specific to this file.
| m_gamepad(nullptr), | ||
| m_precisionMode(FALSE), | ||
| m_lastUpdateTime(0), | ||
| m_isQuitting(FALSE) |
| handleGamepadButton(SDL_GAMEPAD_BUTTON_DPAD_RIGHT, m_state.buttonState[SDL_GAMEPAD_BUTTON_DPAD_RIGHT], SDL_GetGamepadButton(m_gamepad, SDL_GAMEPAD_BUTTON_DPAD_RIGHT), [&](bool d){ virtualPulseKey(SDL_SCANCODE_3, d); }); | ||
| handleGamepadButton(SDL_GAMEPAD_BUTTON_DPAD_DOWN, m_state.buttonState[SDL_GAMEPAD_BUTTON_DPAD_DOWN], SDL_GetGamepadButton(m_gamepad, SDL_GAMEPAD_BUTTON_DPAD_DOWN), [&](bool d){ virtualPulseKey(SDL_SCANCODE_4, d); }); | ||
| handleGamepadButton(SDL_GAMEPAD_BUTTON_LEFT_STICK, m_state.buttonState[SDL_GAMEPAD_BUTTON_LEFT_STICK], SDL_GetGamepadButton(m_gamepad, SDL_GAMEPAD_BUTTON_LEFT_STICK), [&](bool d){ if (d) TheMessageStream->appendMessage(GameMessage::MSG_META_SELECT_NEXT_IDLE_WORKER); }); | ||
| handleGamepadButton(SDL_GAMEPAD_BUTTON_RIGHT_STICK, m_state.buttonState[SDL_GAMEPAD_BUTTON_RIGHT_STICK], SDL_GetGamepadButton(m_gamepad, SDL_GAMEPAD_BUTTON_RIGHT_STICK), [&](bool d){ if (d) TheMessageStream->appendMessage(GameMessage::MSG_META_VIEW_COMMAND_CENTER); }); |
|
Perhaps also check Fighter19's fork for SDL related implementations. As far as I am aware he has it all done. |
|
I have looked at all existing forks and attributed where possible. |
|
How about changing display-mode? eg getDisplayModeCount() / getDisplayModeDescription() using SDL_GetFullscreenDisplayModes + desktop mode + resolution filtering. EDIT: Also account for mouse position which can sometimes not match clicks to cursor position. |
|
Is it better to use SDL3InputManager (+ SDL3CursorManager) or to split out SDL3Keyboard + SDL3Mouse that subclass the engine's existing Keyboard/Mouse base classes? |
- Switched SDL3_image to the latest GitHub main branch commit to natively resolve the RIFF/ANI odd-chunk parsing bug. - Removed the legacy cbSize header patching workaround in SDL3CursorManager::loadANI. - Kept base SDL3 library pinned to stable release-3.4.10. - Cleaned up transient code-level header comments. Co-authored-by: fbraz3 <fbraz3@users.noreply.github.com> Co-authored-by: Fighter19 <Fighter19@users.noreply.github.com> Co-authored-by: feliwir <feliwir@users.noreply.github.com>
- Replaced (void) with empty parentheses () in SDL3Input and SDL3GameEngine declarations and definitions. Co-authored-by: fbraz3 <fbraz3@users.noreply.github.com> Co-authored-by: Fighter19 <Fighter19@users.noreply.github.com> Co-authored-by: feliwir <feliwir@users.noreply.github.com>
- Updated vcpkg.json overrides and regenerated vcpkg-lock.json (sdl3 to 3.4.10, sdl3-image to 3.4.4). - Normalized formatting on vcpkg.json using the official vcpkg format-manifest tool. - Changed translateScanCodeToKeyVal parameter type to SDL_Scancode to prevent high-range media keys from wrapping into valid letter keycodes. - Documented SDL3_image FetchContent Git pin reasoning in cmake/sdl3.cmake. Co-authored-by: fbraz3 <fbraz3@users.noreply.github.com> Co-authored-by: Fighter19 <Fighter19@users.noreply.github.com> Co-authored-by: feliwir <feliwir@users.noreply.github.com>
Replace legacy block comment banners with line comments. Group and sort header includes. Break long gamepad input lines in SDL3Input.cpp with newlines. Remove Sage mentions.
SDL3 Input Backend
This PR implements an SDL3-based input and windowing backend as a modern alternative to DirectInput and Win32 window creation. By utilizing SDL3, we bypass DirectInput emulation layers on modern systems, providing a lower-latency pipeline for Windows 11 and Wine/Linux users.
Input handling
Unified event manager that centralizes keyboard, mouse, and gamepad events into a thread-safe buffer
Gamepad Support (v0.1)
This is an initial baseline implementation focused on providing functional out-of-the-box playability. Feedback is encouraged regarding the ergonomics and logic of these default mappings.
Scope Note: This implementation provides a hardcoded default layout to establish core functionality. Advanced features, such as input remapping, radial menus, adjustable deadzones, are currently out of scope for this PR and may be addressed in future iterations.
The foundation of this backend was built using the SDL3 input work from the generalsX fork by fbraz3.
Todo: replicate to generals