You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
drawGameTime() positioned the top-right clock by subtracting live-measured text width every frame, right-anchored to the screen edge. With the proportional Tahoma font, digit widths change as the time ticks (and the .NN frame counter changes every frame), so the whole timer shifted a pixel or two each frame.
Reserve a fixed width per field from the widest digit and anchor the timer's left edge to it so the white clock no longer moves as digits change. The frame counter is butted against the timer's live right edge so the two stay adjacent.
This PR fixes the horizontal jitter of the in-game clock by replacing per-frame right-anchored positioning with a stable left-anchored layout computed once when font resources are refreshed. The fix is correctly replicated across both the Generals/ and GeneralsMD/ codebases despite the PR TODO checkbox being left unchecked.
refreshGameTimeResources() now measures the widest digit (0–9), the colon, and the dot character using the active font, then stores m_gameTimeReservedWidth (6 × maxDigitWidth + 2 × colonWidth for HH:MM:SS) and m_gameTimeFrameReservedWidth (dotWidth + 2 × maxDigitWidth for .NN). These values are computed once per font change, not every frame.
drawGameTime() anchors the timer's left edge to screenWidth − position.x − reservedTotal, eliminating per-frame left-edge variation. The frame counter is butted against the live right edge of the timer text, so it remains visually adjacent while the total block stays within the reserved bounds.
Confidence Score: 5/5
Safe to merge — the change is a targeted, well-scoped fix that only affects the positioning arithmetic in drawGameTime() and the one-time measurement step in refreshGameTimeResources().
The reserved-width calculation correctly accounts for all characters in the HH:MM:SS format (6 digits + 2 colons) and the .NN frame suffix (dot + 2 digits). The total block is bounded to exactly the reserved area so it cannot overflow or go off-screen. Per-frame logic is unchanged except for replacing two live-measured offsets with pre-computed constants, which is strictly safer. Both Generals and GeneralsMD are updated identically.
Adds width measurement for digits, colon, and dot in refreshGameTimeResources(), stores reserved widths, and uses them in drawGameTime() to anchor the timer's left edge; frame counter is placed at the live right edge of the timer text.
Adds the same two reserved-width member fields as the GeneralsMD header, maintaining existing alignment style.
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["refreshGameTimeResources()\ncalled on font change"] --> B["Measure widest digit width\n(iterate '0'–'9' via getWidth)"]
B --> C["Measure colon width\nand dot width"]
C --> D["Store m_gameTimeReservedWidth\n= 6×maxDigitWidth + 2×colonWidth"]
C --> E["Store m_gameTimeFrameReservedWidth\n= dotWidth + 2×maxDigitWidth"]
D --> F["drawGameTime()\ncalled every frame"]
E --> F
F --> G["Set timer text: HH:MM:SS\nSet frame text: .NN"]
G --> H["Compute horizontalTimerOffset\n= screenW − posX − reservedTotal\n(STABLE — no live measurement)"]
H --> I["Compute horizontalFrameOffset\n= timerOffset + liveTimerWidth\n(frame butts against timer text)"]
I --> J["Draw timer at timerOffset\nDraw frame at frameOffset"]
bobtista
added
Bug
Something is not working right, typically is user facing
Minor
Severity: Minor < Major < Critical < Blocker
Platform
Work towards platform support, such as Linux, MacOS
labels
Jul 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
BugSomething is not working right, typically is user facingMinorSeverity: Minor < Major < Critical < BlockerPlatformWork towards platform support, such as Linux, MacOS
1 participant
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses #2859
drawGameTime() positioned the top-right clock by subtracting live-measured text width every frame, right-anchored to the screen edge. With the proportional Tahoma font, digit widths change as the time ticks (and the .NN frame counter changes every frame), so the whole timer shifted a pixel or two each frame.
Reserve a fixed width per field from the widest digit and anchor the timer's left edge to it so the white clock no longer moves as digits change. The frame counter is butted against the timer's live right edge so the two stay adjacent.
TODO: