Repository navigation
Conversation
a785545 to
7cc0861
Compare
|
| Filename | Overview |
|---|---|
| Core/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Input.cpp | New 1268-line file implementing SDL3Mouse, SDL3Keyboard, and SDL3InputManager with full gamepad support. The constructor correctly initialises all event-buffer slots to SDL_EVENT_FIRST and m_isQuitting to false; synthetic mouse/button events now carry the correct windowID; SDL_WarpMouseInWindow uses m_window, not nullptr. The three lambdas for NORTH/L3/R3 gamepad buttons contain inline if-bodies that violate the repo's debugger-line rule (P2). |
| Core/GameEngineDevice/Source/SDL3Device/Common/SDL3GameEngine.cpp | New SDL3GameEngine implementation. GameEngine::init() is called unconditionally, so headless mode is handled correctly. The minimised-window throttle loop and text-input state management look sound. |
| Core/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Cursor.cpp | New cursor manager that delegates frame storage to SDL3's own SDL_CreateAnimatedCursor, removing the need for a fixed-size m_frameCursors array. Direction iteration in initResources is capped at MAX_2D_CURSOR_DIRECTIONS, and getCursor() clamps out-of-range direction to 0. |
| Core/Main/SDL3Main.cpp | New SDL3 entry point. SDL_Init failure returns early with proper shutdown; window creation failure also cleans up; headless path correctly skips SDL initialisation while still calling AppMain::run(). ApplicationHWnd is retrieved from SDL window properties for DirectX compatibility. |
| Core/Main/AppMain.cpp | New shared startup/shutdown helper that consolidates memory manager init, working-directory setup, version object lifecycle, and single-instance mutex between Win32 and SDL3 backends. Reduces duplication across both WinMain.cpp files cleanly. |
| Core/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp | Refactored setScrolling/stopScrolling to null-guard all subsystem pointers and move stats tracking into the state-transition guards; the input-enabled early-return is retained. Added controller scroll-speed scaling based on current zoom height and setControllerInputActive() to suppress edge-scroll during gamepad use. |
| Generals/Code/Main/WinMain.cpp | Refactored to delegate all pre/post-window init and shutdown to AppMain helpers; focus-change handling now routes through AppMain::setAppActive(). Boilerplate removed from WinMain body. |
| GeneralsMD/Code/Main/WinMain.cpp | Same AppMain delegation refactor as Generals/WinMain.cpp; SDL3-specific splash-surface variable added under RTS_SDL3_ENABLE guard but unused in this file (splash is rendered by SDL3Main instead). |
| vcpkg.json | Adds sdl3 and sdl3-image dependencies with version overrides (3.4.10 / 3.4.4). The vcpkg-lock.json is included in the changeset, but reviewers should regenerate and confirm the lock matches these overrides before merging. |
Sequence Diagram
sequenceDiagram
participant OS as OS / SDL3
participant Main as SDL3Main / WinMain
participant Engine as SDL3GameEngine
participant Manager as SDL3InputManager
participant Mouse as SDL3Mouse
participant KB as SDL3Keyboard
participant Game as GameEngine / GameLogic
Main->>Engine: init() — creates SDL3InputManager, stores m_SDLWindow
Engine->>Manager: new SDL3InputManager(window)
loop Each Frame
Engine->>Engine: update()
Engine->>Manager: update() via pollSDL3Events()
OS-->>Manager: SDL_PollEvent loop
Manager->>Manager: addMouseSDLEvent / addKeyboardSDLEvent
Manager->>Manager: processGamepadInput() → virtualPulseMouse / virtualPulseKey
Engine->>Game: GameEngine::update()
Game->>Mouse: getMouseEvent() → getNextMouseEvent()
Mouse->>Mouse: translateEvent() → scaleMouseCoordinates()
Game->>KB: getKey() → getNextKeyboardEvent()
end
Manager-->>Engine: "isQuitting() → m_quitting = true"
Engine-->>Main: getQuitting() → exit loop
Reviews (38): Last reviewed commit: "rebased" | Re-trigger Greptile
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.
|
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? |
- 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
Co-authored-by: Bobby Battista <bobtista@gmail.com>
SDL3 loads .ani cursors via TheFileSystem rather than Win32's LoadCursorFromFile, enabling cursor loading from .BIG archives and virtual filesystems. Add a non-positive size check before allocating memory buffers to handle empty or invalid files safely.
- Use event.wheel.mouse_x/y directly instead of calling SDL_GetMouseState, ensuring accurate cursor position at the exact moment of the wheel event. - Replace Win32 timeGetTime() with SDL keyEvent.timestamp in SDL3Keyboard::getKey for portable millisecond key-down timing. - Replace Win32 VK_RETURN macro with character code 13 in IME Return key dispatch.
…ameEngine::getTicksMsec()
combo box text dropping fixed
Fix the crash when launching a second instance. Timestamp injected gamepad events so key repeat works. Ignore gamepad input while the window is unfocused. Let the window actually resize to the chosen resolution.
7ef9d02 to
4993bc8
Compare
WalkthroughThe change adds SDL3 build support, shared application lifecycle code, SDL3 engine and input implementations, cursor management, controller input, and related timing and window behavior updates. Existing Win32 builds retain their original backend selection. ChangesSDL3 backend integration
Priority: ➖ Normal Estimated code review effort: 5 (Critical) | ~90 minutes Change: Feature Merge Risk: 🟡 Moderate · up to Controller disconnect or focus loss can leave a virtual mouse button pressed when input traffic fills the queue. Ensure release delivery before merging. 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Advanced
Run ID: b10c0e59-5b76-4a9a-9960-26ac59b3d55a
📒 Files selected for processing (39)
.github/workflows/ci.yml.github/workflows/reusable-build-toolchain.ymlCMakeLists.txtCMakePresets.jsonCore/GameEngine/Include/GameClient/Display.hCore/GameEngine/Include/GameClient/LookAtXlat.hCore/GameEngine/Include/GameClient/Mouse.hCore/GameEngine/Include/GameClient/View.hCore/GameEngine/Source/GameClient/Input/Keyboard.cppCore/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cppCore/GameEngineDevice/CMakeLists.txtCore/GameEngineDevice/Include/SDL3Device/Common/SDL3GameEngine.hCore/GameEngineDevice/Include/SDL3Device/GameClient/SDL3Cursor.hCore/GameEngineDevice/Include/SDL3Device/GameClient/SDL3Input.hCore/GameEngineDevice/Source/SDL3Device/Common/SDL3GameEngine.cppCore/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Cursor.cppCore/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Input.cppCore/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cppCore/Main/AppMain.cppCore/Main/AppMain.hCore/Main/SDL3Main.cppCore/Main/SDL3Main.hGenerals/Code/GameEngine/Include/Common/GameEngine.hGenerals/Code/GameEngine/Source/Common/GameEngine.cppGenerals/Code/GameEngine/Source/GameClient/GameClient.cppGenerals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DGameClient.hGenerals/Code/Main/CMakeLists.txtGenerals/Code/Main/WinMain.cppGeneralsMD/Code/GameEngine/Include/Common/GameEngine.hGeneralsMD/Code/GameEngine/Source/Common/GameEngine.cppGeneralsMD/Code/GameEngine/Source/GameClient/GameClient.cppGeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DGameClient.hGeneralsMD/Code/Main/CMakeLists.txtGeneralsMD/Code/Main/WinMain.cppcmake/config-build.cmakecmake/sdl3.cmaketriplets/x86-windows.cmakevcpkg-configuration.jsonvcpkg.json
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
…oints SDL3Main.cpp had no SetUnhandledExceptionFilter/try-catch, losing crash dumps on that path; move WinMain.cpp's handler into AppMain so both entry points install it once instead of duplicating it, and wrap AppMain::run() in a catch-all so both paths get equivalent coverage.
…heck The shared fallback branch called FetchContent_MakeAvailable(SDL3) whenever SDL3_image's version check failed, even if SDL3 was already found via find_package - defining its targets twice and stopping the configure. Give each library its own guarded fallback branch.
Restore ALT-key release (resetKeys instead of the no-op reset), audio mute/unmute, and stuck gamepad-driven virtual keys on window focus change, and stop double-counting gamepad cursor motion deltas.
loadANI now returns nullptr instead of a cursor with a null SDL_Cursor when creation fails; clamp viewport-scaled mouse coordinates to the last valid pixel instead of one past it; skip loading the splash BMP in headless mode; drop the dead addSDLEvent wrappers and unused SDL3CursorManager::init(); use snprintf for the splash path buffer.
setScrolling/stopScrolling were retrofitted with null checks for TheMouse/TheDisplay et al. but canScrollAtScreenEdge still dereferenced TheMouse and TheDisplay unconditionally.
1570138 to
138be1c
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Advanced
Run ID: 903dd94a-ed5f-4511-8606-db3f1e01b64a
📒 Files selected for processing (12)
Core/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cppCore/GameEngineDevice/Include/SDL3Device/GameClient/SDL3Cursor.hCore/GameEngineDevice/Include/SDL3Device/GameClient/SDL3Input.hCore/GameEngineDevice/Source/SDL3Device/Common/SDL3GameEngine.cppCore/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Cursor.cppCore/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Input.cppCore/Main/AppMain.cppCore/Main/AppMain.hCore/Main/SDL3Main.cppGenerals/Code/Main/WinMain.cppGeneralsMD/Code/Main/WinMain.cppcmake/sdl3.cmake
💤 Files with no reviewable changes (1)
- Core/GameEngineDevice/Include/SDL3Device/GameClient/SDL3Cursor.h
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
| if (m_state.buttonState[SDL_GAMEPAD_BUTTON_DPAD_LEFT]) virtualPulseKey(SDL_SCANCODE_1, false); | ||
| if (m_state.buttonState[SDL_GAMEPAD_BUTTON_DPAD_RIGHT]) virtualPulseKey(SDL_SCANCODE_3, false); | ||
|
|
||
| m_state = GamepadState(); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
sed -n '800,1030p' Core/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Input.cpp
sed -n '100,190p' Core/GameEngineDevice/Include/SDL3Device/GameClient/SDL3Input.h
rg -n 'releaseGamepadVirtualInputs|addMouseEvent|addKeyboardEvent|virtual.*(Mouse|Key)|clear.*(Mouse|Keyboard)|reset.*(Mouse|Keyboard)|getMouseEvent|getKeyboardEvent' Core/GameEngineDevice Core/GameEngineRepository: TheSuperHackers/GeneralsGameCode
Length of output: 19375
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- event ingestion and queue consumers ---'
sed -n '1,430p' Core/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Input.cpp
printf '%s\n' '--- gamepad injection and state transitions ---'
sed -n '1020,1250p' Core/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Input.cpp
printf '%s\n' '--- SDL input declarations and reset-related symbols ---'
sed -n '1,190p' Core/GameEngineDevice/Include/SDL3Device/GameClient/SDL3Input.h
rg -n -C 4 'reset\\(|SDL_EVENT_MOUSE_MOTION|SDL_EVENT_MOUSE_BUTTON|SDL_EVENT_KEY|addMouseSDLEvent|addKeyboardSDLEvent|m_mouseNext|getNextMouseEvent|m_keyNext|getNextKeyboardEvent' Core/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Input.cpp Core/GameEngineDevice/Include/SDL3Device/GameClient/SDL3Input.h Core/GameEngine/Source/GameClient/Input Core/GameEngine/Include/GameClientRepository: TheSuperHackers/GeneralsGameCode
Length of output: 22766
🏁 Script executed:
sed -n '1,430p' Core/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Input.cpp
sed -n '1020,1250p' Core/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Input.cpp
rg -n -C 4 'reset\(|SDL_EVENT_MOUSE_MOTION|SDL_EVENT_MOUSE_BUTTON|SDL_EVENT_KEY|addMouseSDLEvent|addKeyboardSDLEvent|m_mouseNext|getNextMouseEvent|m_keyNext|getNextKeyboardEvent' Core/GameEngineDevice/Source/SDL3Device/GameClient/SDL3Input.cpp Core/GameEngineDevice/Include/SDL3Device/GameClient/SDL3Input.h Core/GameEngine/Source/GameClient/Input Core/GameEngine/Include/GameClientRepository: TheSuperHackers/GeneralsGameCode
Length of output: 50388
Guarantee synthesized releases before clearing m_state.
SDL3InputManager::update() queues SDL_EVENT_MOUSE_MOTION through addMouseSDLEvent(), so motion can fill the mouse ring. A full ring drops the event. releaseGamepadVirtualInputs() uses the same path for SOUTH and EAST button-up events, then clears m_state without retrying. Focus loss and gamepad disconnect can therefore leave a virtual mouse button pressed.
SDL3Mouse::reset() and Keyboard::reset() do not clear this queued or pressed state. Guarantee release insertion before clearing m_state by reserving capacity for releases or evicting non-critical motion events.
SDL3 Input Backend
This PR updates the windowing and input pipeline to use SDL3 by default on modern toolchains (non-VC6 builds) 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.
This SDL3 input/windowing backend builds on prior work from the community: