Glass panels: flash at full rate when unfocused + red Panic/Eject button

Two glass-panel indicator fixes reported by playtesters.

1. FLASH SLOW UNLESS FOCUSED.  The per-display panel windows repaint off a
   62ms WM_TIMER, and Windows coalesces/throttles timer + paint messages for a
   window that is in the BACKGROUND (unfocused) -- so with the game window
   holding focus the panels' lamp flash (a repaint-driven animation) crawled,
   and giving a panel focus un-throttled it.  (My earlier surround fix drew in
   the main D3D frame and never touched these separate windows.)  New
   BTGlassPanels_Tick(), called once per frame from the main render loop
   (L4VIDEO), drives a synchronous InvalidateRect+UpdateWindow at the ~16Hz
   flash cadence -- the main loop runs every frame regardless of which window
   has focus, and the forced paint bypasses the throttled timer-message path.
   The WM_TIMER stays for its one-shot re-snap.

2. RED PANIC/EJECT.  0x3D is the Panic/Eject button; on the blue flight panel
   it was just another blue block.  The shared flight-grid geometry (L4RIOBANK)
   now tags 0x3D as colorClass 0 (red); L4GLASSWIN's AdoptBank maps colorClass
   0 -> ClrRed explicitly (the flight bank's ClrBlue default no longer swallows
   it), and the surround (L4VB16) already renders non-blue/yellow as red -- so
   the eject stands out red in both the surround and the exploded window.

Verified: Release links clean (40 tolerated /FORCE externals only); exploded
panels boot + run 13s no crash under the per-frame repaint pump; riobank dump
confirms 0x3d class=0 (red), neighbours class=2 (blue).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-08-04 19:28:11 -05:00
co-authored by Claude Opus 4.8
parent f99003cf50
commit 7d112ce309
4 changed files with 68 additions and 2 deletions
+43 -1
View File
@@ -190,7 +190,9 @@ static void
GButton &b = w.buttons[w.buttonCount++];
b.address = src.address;
b.color = (src.colorClass == 1) ? ClrYellow
: (src.colorClass == 2) ? ClrBlue : color;
: (src.colorClass == 2) ? ClrBlue
: (src.colorClass == 0) ? ClrRed // 0 = red (MFD, and the red Panic/Eject 0x3D)
: color;
b.rect.left = src.x + dx;
b.rect.top = src.y + dy;
b.rect.right = src.x + dx + src.w;
@@ -1050,3 +1052,43 @@ void
if (subFont) { DeleteObject(subFont); subFont = NULL; }
if (gStage) { delete[] gStage; gStage = NULL; }
}
//###########################################################################
// Per-frame repaint pump (2026-08-04, "indicators flash slowly unless focused").
//
// These windows repaint off a 62 ms WM_TIMER. Windows COALESCES/THROTTLES timer
// AND paint messages for a window that is in the BACKGROUND (not focused) -- so
// when the game window (or another app) holds focus, the panel's WM_TIMER slows
// to a crawl and the lamp FLASH (a repaint-driven animation: BTLampBrightnessOf
// alternates the shade off GetTickCount every paint) drags. Giving the panel
// focus un-throttles its timer, which is exactly what playtesters saw.
//
// Fix: drive the repaint from the MAIN render loop (BTGlassPanels_Tick, called
// once per frame from L4VIDEO), gated to the same ~16 Hz flash cadence. The main
// loop runs every frame while the game is up regardless of which window has focus,
// and InvalidateRect + UpdateWindow forces a SYNCHRONOUS WM_PAINT -- bypassing the
// throttled timer-message path entirely. The WM_TIMER stays (it still owns the
// one-shot re-snap); a focused window just repaints from whichever fires first.
//###########################################################################
void
BTGlassPanels_Tick()
{
if (gWinCount == 0)
return;
static unsigned long sLastPaint = 0;
unsigned long now = GetTickCount();
if (now - sLastPaint < (unsigned long)RepaintMilliseconds)
return;
sLastPaint = now;
for (int i = 0; i < gWinCount; ++i)
{
if (gWins[i].hwnd != NULL)
{
InvalidateRect(gWins[i].hwnd, NULL, FALSE);
UpdateWindow(gWins[i].hwnd); // synchronous paint, not the throttled queue
}
}
}