feat(input): Implement SDL3 input and window management - #2639
feat(input): Implement SDL3 input and window management#2639githubawn wants to merge 36 commits into
Conversation
a785545 to
7cc0861
Compare
|
| Filename | Overview |
|---|---|
| Core/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Input.cpp | Implements SDL3 mouse, keyboard, gamepad, coordinate scaling, focus synchronization, and buffered event translation; the previously reported input issues are addressed. |
| Core/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Cursor.cpp | Implements SDL3 animated cursor loading, but configured direction counts can index beyond the fixed resource array. |
| Core/GameEngineDevice/Source/SDL3Device/Common/SDL3GameEngine.cpp | Integrates SDL event polling and text input while preserving unconditional base-engine subsystem initialization. |
| Core/Main/SDL3Main.cpp | Adds SDL initialization, window creation, splash rendering, and clean startup-failure exits. |
| Core/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp | Adds controller-aware camera scrolling behavior and zoom-dependent scroll scaling. |
| vcpkg.json | Adds pinned SDL3 and SDL3_image dependencies. |
| vcpkg-lock.json | Resolves SDL3 and SDL3_image at versions matching the manifest overrides. |
Sequence Diagram
sequenceDiagram
participant OS
participant SDLMain as SDL3Main
participant Engine as SDL3GameEngine
participant Input as SDL3InputManager
participant Devices as Mouse/Keyboard
participant Stream as MessageStream
OS->>SDLMain: Start application
SDLMain->>SDLMain: Initialize SDL and create window
SDLMain->>Engine: Create and initialize engine
Engine->>Input: Create input manager
loop Each update
Engine->>Input: Poll SDL events
Input->>Devices: Buffer mouse and keyboard events
Devices->>Stream: Emit raw game messages
end
Prompt To Fix All With AI
### Issue 1
Core/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Cursor.cpp:69
**Cursor direction count exceeds bounds**
When a cursor defines more than `MAX_2D_CURSOR_DIRECTIONS` directions, this loop indexes beyond the fixed second dimension of `m_cursorResources`, causing memory corruption or a crash during cursor initialization.
```suggestion
for (Int direction = 0; direction < mouse->m_cursorInfo[cursor].numDirections && direction < MAX_2D_CURSOR_DIRECTIONS; direction++)
```
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (34): Last reviewed commit: "fix(sdl3): backport SDL3 input, focus, a..." | 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
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.
|
|
||
| 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.
|
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? |
|
I've started cleaning up the style and structural issues in the latest commits. Regarding SDL3Main: The main benefit of the current approach is that we keep the game's native Win32 WinMain entry point and startup sequence intact. To get rid of the #ifdef blocks in WinMain while minimizing duplication, I can move the window initialization out into SDL3Window. Regarding splitting out subclasses: I don't think splitting the input handling into isolated SDL3Keyboard and SDL3Mouse subclasses is the right way. It runs contrary to how SDL3 tries to be a unified way; it relies on a single event pump where all keyboard, mouse, and gamepad signals flow together. |
But this is how you currently have set this up. What is the plan here? |
5da34d4 to
78f7e15
Compare
|
There's a lot of SDL stuff in my stack that you could use here, and I'd extract this into a separate SDL3Gamepad translator vs adopt its central input manager. See if Gippity can take a stab at taking the best of both |
- Fix symbol collisions for g_strFile, g_csfFile, gAppPrefix, and TheWin32Mouse in WinMain - Call AppMain::initBeforeWindow() in WinMain prior to accessing splash screen and TheGlobalData - Use timeGetTime() for key down timestamping in SDL3Input to match Keyboard::checkKeyRepeat() - Release active synthetic inputs and reset state on gamepad close in SDL3InputManager - Read live CapsLock toggle state from SDL via SDL_GetModState() in getCapsState() Co-authored-by: Bobby Battista <bobtista@gmail.com>
ca6aa95 to
38bc8f6
Compare
- Add radial deadzone removal, smoothstep response curve, and velocity acceleration for analog sticks - Retire precision mode in favor of continuous stick acceleration (LT is currently unmapped) - Add getControllerScrollScale() to scale camera panning when zoomed close to ground - Suppress mouse edge scrolling automatically while gamepad input is active - Expose getMinHeightAboveGround and getMaxHeightAboveGround on View Co-authored-by: stm <14291421+stephanmeesters@users.noreply.github.com>
- Replace SDL_GetWindowSizeInPixels with SDL_GetWindowSize in scaleMouseCoordinates - Fixes HiDPI/Retina coordinate space mismatch where mouse & gamepad motion events delivered in logical points were scaled by physical pixel dimensions Co-authored-by: Bobby Battista <bobtista@gmail.com>
- Fix camera panning and scroll state handling for gamepads - Fix double-click detection for gamepad button pulses to trigger Guard mode orders
|
It's improved a lot. I left more comments - also, there are thousands of lines changed in MainMenuUtils.cpp, CHATAPI.cpp, and both OptionsMenu.cpp that are just line ending stuff, could remove that and let a formatting pass deal with it later. My stack has working implementations of several of the inline items (close → MSG_META_DEMO_INSTANT_QUIT routing, focus → setIsActive + keyboard reset, Return → GWM_IME_CHAR commit, cursor position sync, deferred resize) if you want to lift from them. |
0acb86c to
3bd8573
Compare
Co-authored-by: Bobby Battista <bobtista@gmail.com>
|
|
||
| for (Int cursor = Mouse::FIRST_CURSOR; cursor < Mouse::NUM_MOUSE_CURSORS; cursor++) | ||
| { | ||
| for (Int direction = 0; direction < mouse->m_cursorInfo[cursor].numDirections; direction++) |
There was a problem hiding this comment.
Cursor direction count exceeds bounds
When a cursor defines more than MAX_2D_CURSOR_DIRECTIONS directions, this loop indexes beyond the fixed second dimension of m_cursorResources, causing memory corruption or a crash during cursor initialization.
| for (Int direction = 0; direction < mouse->m_cursorInfo[cursor].numDirections; direction++) | |
| for (Int direction = 0; direction < mouse->m_cursorInfo[cursor].numDirections && direction < MAX_2D_CURSOR_DIRECTIONS; direction++) |
Knowledge Base Used: GameClient Rendering, GUI, and Input
Prompt To Fix With AI
This is a comment left during a code review.
Path: Core/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Cursor.cpp
Line: 69
Comment:
**Cursor direction count exceeds bounds**
When a cursor defines more than `MAX_2D_CURSOR_DIRECTIONS` directions, this loop indexes beyond the fixed second dimension of `m_cursorResources`, causing memory corruption or a crash during cursor initialization.
```suggestion
for (Int direction = 0; direction < mouse->m_cursorInfo[cursor].numDirections && direction < MAX_2D_CURSOR_DIRECTIONS; direction++)
```
**Knowledge Base Used:** [GameClient Rendering, GUI, and Input](https://app.greptile.com/thesuperhackers/-/custom-context/knowledge-base/thesuperhackers/generalsgamecode/-/docs/gameclient-rendering.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
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:
properly attribute all forks that have inspired this.