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:
@@ -190,7 +190,9 @@ static void
|
|||||||
GButton &b = w.buttons[w.buttonCount++];
|
GButton &b = w.buttons[w.buttonCount++];
|
||||||
b.address = src.address;
|
b.address = src.address;
|
||||||
b.color = (src.colorClass == 1) ? ClrYellow
|
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.left = src.x + dx;
|
||||||
b.rect.top = src.y + dy;
|
b.rect.top = src.y + dy;
|
||||||
b.rect.right = src.x + dx + src.w;
|
b.rect.right = src.x + dx + src.w;
|
||||||
@@ -1050,3 +1052,43 @@ void
|
|||||||
if (subFont) { DeleteObject(subFont); subFont = NULL; }
|
if (subFont) { DeleteObject(subFont); subFont = NULL; }
|
||||||
if (gStage) { delete[] gStage; gStage = 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -258,7 +258,10 @@ void
|
|||||||
int row = i / columns;
|
int row = i / columns;
|
||||||
int x = originX + column * (cw + gap);
|
int x = originX + column * (cw + gap);
|
||||||
int y = originY + row * (ch + gap);
|
int y = originY + row * (ch + gap);
|
||||||
Push(out, baseAddress + i, x, y, cw, ch, 2,
|
// Flight blocks are blue (colorClass 2), EXCEPT the Panic/Eject at 0x3D:
|
||||||
|
// red (colorClass 0) so the eject stands out on the blue panel.
|
||||||
|
int cc = (baseAddress + i == 0x3D) ? 0 : 2;
|
||||||
|
Push(out, baseAddress + i, x, y, cw, ch, cc,
|
||||||
(inert != 0) ? inert[i] : 0,
|
(inert != 0) ? inert[i] : 0,
|
||||||
(labels != 0) ? labels[i] : 0);
|
(labels != 0) ? labels[i] : 0);
|
||||||
GrowBounds(out, x, y, cw, ch);
|
GrowBounds(out, x, y, cw, ch);
|
||||||
|
|||||||
@@ -8952,6 +8952,17 @@ void DPLRenderer::ExecuteImplementation(RendererComplexity, RendererOrigin::Inte
|
|||||||
extern void BTGaugeWindowRenderAndPresent(LPDIRECT3DDEVICE9 device);
|
extern void BTGaugeWindowRenderAndPresent(LPDIRECT3DDEVICE9 device);
|
||||||
BTGaugeWindowRenderAndPresent(mDevice);
|
BTGaugeWindowRenderAndPresent(mDevice);
|
||||||
|
|
||||||
|
#ifdef BT_GLASS
|
||||||
|
// Drive the per-display glass panels' repaint from the (always-running) main
|
||||||
|
// loop so their lamp flash keeps animating when they're in the background --
|
||||||
|
// Windows throttles an unfocused window's own WM_TIMER ("indicators flash
|
||||||
|
// slowly unless you focus that window"). No-op unless the panels are up.
|
||||||
|
{
|
||||||
|
extern void BTGlassPanels_Tick();
|
||||||
|
BTGlassPanels_Tick();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// DIAG (turn-hitch hunt): draw CPU is _rt0..here; Present blocks on the GPU.
|
// DIAG (turn-hitch hunt): draw CPU is _rt0..here; Present blocks on the GPU.
|
||||||
LARGE_INTEGER _rt1; QueryPerformanceCounter(&_rt1);
|
LARGE_INTEGER _rt1; QueryPerformanceCounter(&_rt1);
|
||||||
// COCKPIT LETTERBOX: uniform-scale the canvas into the client (NULL = the
|
// COCKPIT LETTERBOX: uniform-scale the canvas into the client (NULL = the
|
||||||
|
|||||||
@@ -31,6 +31,16 @@ void
|
|||||||
void
|
void
|
||||||
BTGlassPanels_Destroy();
|
BTGlassPanels_Destroy();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Per-frame repaint pump. Call once per frame from the main render loop so the
|
||||||
|
// per-display windows' lamp flash keeps animating even when they are in the
|
||||||
|
// background (Windows throttles a background window's own WM_TIMER; this drives a
|
||||||
|
// synchronous repaint at the flash cadence instead). No-op unless the windows
|
||||||
|
// are up. See the note at the definition (L4GLASSWIN.cpp).
|
||||||
|
//
|
||||||
|
void
|
||||||
|
BTGlassPanels_Tick();
|
||||||
|
|
||||||
//
|
//
|
||||||
// True when BT_GLASS_PANELS mode is selected (default ON under `-platform
|
// True when BT_GLASS_PANELS mode is selected (default ON under `-platform
|
||||||
// glass`, OFF otherwise). Read by the render loop / L4VB16 dev-composite to
|
// glass`, OFF otherwise). Read by the render loop / L4VB16 dev-composite to
|
||||||
|
|||||||
Reference in New Issue
Block a user