Cockpit surround: composite the gauges around the 3D view (default desktop layout)
Under BT_DEV_GAUGES the DEFAULT is now the pod-faithful cockpit surround: the 3D world CENTERED with the six gauge surfaces composited AROUND it in the single main window at 1/2 native scale, plus clickable RIO button lamps. Iterated as a visual reference with the user, then landed in the engine. - L4VB16.cpp/.h: BTCockpitLayout + BTCockpitComputeLayout (layout single source of truth, computed from the backbuffer canvas); BTDrawCockpitPanels (band fill -> button lamp quads -> 9-entry surface loop, phosphor-green mono / amber palette sec, Eng-sibling slot map -> GDI-atlas flight labels; D3DSBT_ALL state-block isolation = the floating-rocks trap); BTCockpitMouseDown/Up (client->bb hit-test + glass press/release/right-latch contract); BTApplyWorldViewport + DevGaugeDocked cockpit branches; shared BTLampBrightnessOf inline. Hooked at the top of BTDrawGaugeInset (before BT_SHOT, so shots include it). - btl4main.cpp: glass preset (cockpit default, per-display panels opt-in); mode resolution -> gBTGaugeCockpit with work-area-clamped window sizing (-res = view size); WndProc WM_L/RBUTTON routing. - L4VIDEO.cpp: BTWorldAspectOf cockpit branch (view rect on-screen aspect). - L4VIDRND.cpp: CameraShipHUDRenderable::Render made viewport-relative. Buttons = the L4GLASSWIN address banks x0.5 (Heat 0x2F, Mfd2 0x27, Comm 0x37, Mfd1 0x0F, Mfd3 0x07 red; radar rails 0x10-0x1B yellow; flight 0x38-0x47 blue, labeled). Full rect is the hit target; the surface draws over it so only the lamp edge shows. Precedence: BT_GLASS_PANELS=1 stands cockpit down > BT_COCKPIT=1 > _WINDOW/_DOCK opt-out > cockpit default; BT_COCKPIT=0 = dock-bottom. Green tunable via BT_COCKPIT_TINT. Renders in ALL builds; only the PadRIO click/lamp seam is BT_GLASS-gated. Verified (awaiting playtest): both build/ + build-glass/ compile (0 error C); glass BT_SHOT matches the mockup; 500-click storm during a live mission survived (Gitea #18 Receiver-gap fix holds); BT_COCKPIT=0 dock-bottom unregressed; BT_GLASS_PANELS=1 stands cockpit down; pod build renders the panels. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
5ba5697a08
commit
129b27499d
+97
-24
@@ -106,6 +106,32 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
// GetAsyncKeyState per frame instead (with a foreground guard), which
|
||||
// is immune to message stealing.
|
||||
return 0;
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
// COCKPIT SURROUND: route clicks on the composited panel buttons to the
|
||||
// RIO (glass build) via the layout hit-test. No-op in other modes.
|
||||
{
|
||||
extern int gBTGaugeCockpit;
|
||||
extern int BTCockpitMouseDown(int, int, int, int, int);
|
||||
if (gBTGaugeCockpit)
|
||||
{
|
||||
RECT rc; GetClientRect(hWnd, &rc);
|
||||
int consumed = BTCockpitMouseDown(
|
||||
(int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam),
|
||||
(int)(rc.right - rc.left), (int)(rc.bottom - rc.top),
|
||||
uMsg == WM_RBUTTONDOWN);
|
||||
if (consumed && uMsg == WM_LBUTTONDOWN)
|
||||
SetCapture(hWnd); // a release outside the button still clears it
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
case WM_LBUTTONUP:
|
||||
{
|
||||
extern int gBTGaugeCockpit;
|
||||
extern void BTCockpitMouseUp(void);
|
||||
if (gBTGaugeCockpit) { BTCockpitMouseUp(); ReleaseCapture(); }
|
||||
}
|
||||
return 0;
|
||||
case WM_SIZE:
|
||||
// Window-resize aspect fix (task #20): rebuild the projection for the
|
||||
// new client aspect so the scene doesn't stretch fat/skinny (the D3D9
|
||||
@@ -330,19 +356,27 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
{
|
||||
// GLASS profile (dev tooling, step 2e): the desktop cockpit --
|
||||
// PadRIO input (XInput+keyboard, content\bindings.txt), the
|
||||
// on-screen clickable button panel, the dev-composited MFD
|
||||
// surfaces (dock-bottom default; BT_DEV_GAUGES_WINDOW=1 separate
|
||||
// window / BT_DEV_GAUGES_DOCK=1 overlay inset), and the desktop
|
||||
// plasma window. Each only when not already set, so a developer
|
||||
// env overrides the preset.
|
||||
// dev-composited MFD surfaces, and the desktop plasma window.
|
||||
// Each only when not already set, so a developer env overrides.
|
||||
if (getenv("L4CONTROLS") == NULL) putenv("L4CONTROLS=PAD,KEYBOARD");
|
||||
if (getenv("BT_DEV_GAUGES") == NULL) putenv("BT_DEV_GAUGES=1");
|
||||
if (getenv("L4PLASMA") == NULL) putenv("L4PLASMA=SCREEN");
|
||||
if (getenv("BT_PAD_PANEL") == NULL) putenv("BT_PAD_PANEL=1");
|
||||
// Break the secondary displays into per-display windows (surface + its RIO
|
||||
// bank around it). Set BT_GLASS_PANELS=0 to fall back to the single
|
||||
// combined pad panel + docked gauge strip.
|
||||
if (getenv("BT_GLASS_PANELS") == NULL) putenv("BT_GLASS_PANELS=1");
|
||||
|
||||
// DEFAULT LAYOUT = the COCKPIT SURROUND (single window: the six gauge
|
||||
// surfaces + clickable button lamps composited AROUND the centered 3D
|
||||
// view). Opt out with BT_COCKPIT=0 (dock-bottom strip) or
|
||||
// BT_GLASS_PANELS=1 (the per-display windows). When cockpit is the
|
||||
// default the buttons live IN the main window, so no separate pad/panel
|
||||
// window is created (leave BT_PAD_PANEL / BT_GLASS_PANELS unset).
|
||||
int cockpitDefault = 1;
|
||||
if (getenv("BT_COCKPIT") && getenv("BT_COCKPIT")[0] == '0') cockpitDefault = 0;
|
||||
if (getenv("BT_GLASS_PANELS") && getenv("BT_GLASS_PANELS")[0] != '0') cockpitDefault = 0;
|
||||
if (getenv("BT_DEV_GAUGES_WINDOW") || getenv("BT_DEV_GAUGES_DOCK")) cockpitDefault = 0;
|
||||
if (!cockpitDefault)
|
||||
{
|
||||
if (getenv("BT_PAD_PANEL") == NULL) putenv("BT_PAD_PANEL=1");
|
||||
if (getenv("BT_GLASS_PANELS") == NULL) putenv("BT_GLASS_PANELS=1");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
@@ -562,29 +596,68 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
// restores the old separate MFD window.
|
||||
{
|
||||
extern int gBTGaugeDockBottom;
|
||||
extern int gBTGaugeCockpit;
|
||||
extern int gBTCockpitCanvasW, gBTCockpitCanvasH;
|
||||
extern int BTGaugeStripHeightFor(int width);
|
||||
extern void BTCockpitCanvasFor(int viewW, int viewH, int *cw, int *ch);
|
||||
// BT_GLASS_PANELS breaks the gauges into their own per-display windows, so
|
||||
// the world window keeps its normal size (no bottom strip).
|
||||
// the world window keeps its normal size (no cockpit / bottom strip).
|
||||
int glassOwnsGauges = 0;
|
||||
#ifdef BT_GLASS
|
||||
{ extern int BTGlassPanelsActive(); glassOwnsGauges = BTGlassPanelsActive(); }
|
||||
#endif
|
||||
if (!glassOwnsGauges &&
|
||||
getenv("BT_DEV_GAUGES") != 0 && getenv("BT_DEV_GAUGES_WINDOW") == 0)
|
||||
if (!glassOwnsGauges && getenv("BT_DEV_GAUGES") != 0)
|
||||
{
|
||||
gBTGaugeDockBottom = 1;
|
||||
// Readability default (user-reported: the strip at 800 wide is a
|
||||
// 0.6x downscale, hard to read): a WIDER world region (the
|
||||
// projection is aspect-correct for any shape) buys strip pixels --
|
||||
// 1100x600 world + 1100x400 strip = a 1000-tall window that fits a
|
||||
// 1080p desktop with the panel at 83% of design size. -res still
|
||||
// overrides both.
|
||||
if (strstr(lpCmdLine ? lpCmdLine : "", "-res") == 0)
|
||||
// Mode resolution (precedence): explicit BT_COCKPIT > separate-window /
|
||||
// legacy-inset opt-out > COCKPIT SURROUND default under BT_DEV_GAUGES.
|
||||
int cockpitOn;
|
||||
const char *ck = getenv("BT_COCKPIT");
|
||||
if (ck != NULL)
|
||||
cockpitOn = (ck[0] != '0');
|
||||
else
|
||||
cockpitOn = (getenv("BT_DEV_GAUGES_WINDOW") == 0 &&
|
||||
getenv("BT_DEV_GAUGES_DOCK") == 0);
|
||||
|
||||
if (cockpitOn)
|
||||
{
|
||||
winW = 1100;
|
||||
winH = 600;
|
||||
gBTGaugeCockpit = 1;
|
||||
// -res W H = the WORLD VIEW size in cockpit mode; default 900x500.
|
||||
int viewW = 900, viewH = 500;
|
||||
if (strstr(lpCmdLine ? lpCmdLine : "", "-res") != 0) { viewW = winW; viewH = winH; }
|
||||
// Clamp the CANVAS to the work area (minus the window frame): shrink
|
||||
// viewH (floor 400) then viewW (floor 640) until it fits (1080p tight).
|
||||
RECT wa = { 0, 0, 1920, 1080 };
|
||||
SystemParametersInfo(SPI_GETWORKAREA, 0, &wa, 0);
|
||||
RECT fr = { 0, 0, 1000, 1000 };
|
||||
AdjustWindowRect(&fr, WS_OVERLAPPEDWINDOW, FALSE);
|
||||
int availW = (wa.right - wa.left) - ((fr.right - fr.left) - 1000);
|
||||
int availH = (wa.bottom - wa.top) - ((fr.bottom - fr.top) - 1000);
|
||||
int cw, ch;
|
||||
BTCockpitCanvasFor(viewW, viewH, &cw, &ch);
|
||||
while (ch > availH && viewH > 400) { viewH -= 20; BTCockpitCanvasFor(viewW, viewH, &cw, &ch); }
|
||||
while (cw > availW && viewW > 640) { viewW -= 20; BTCockpitCanvasFor(viewW, viewH, &cw, &ch); }
|
||||
winW = cw; winH = ch;
|
||||
gBTCockpitCanvasW = winW; // windowed backbuffer = client canvas
|
||||
gBTCockpitCanvasH = winH;
|
||||
std::cout << "[cockpit] view " << viewW << "x" << viewH
|
||||
<< " canvas " << winW << "x" << winH << std::endl << std::flush;
|
||||
}
|
||||
else if (getenv("BT_DEV_GAUGES_WINDOW") == 0)
|
||||
{
|
||||
gBTGaugeDockBottom = 1;
|
||||
// Readability default (user-reported: the strip at 800 wide is a
|
||||
// 0.6x downscale, hard to read): a WIDER world region (the
|
||||
// projection is aspect-correct for any shape) buys strip pixels --
|
||||
// 1100x600 world + 1100x400 strip = a 1000-tall window that fits a
|
||||
// 1080p desktop with the panel at 83% of design size. -res still
|
||||
// overrides both.
|
||||
if (strstr(lpCmdLine ? lpCmdLine : "", "-res") == 0)
|
||||
{
|
||||
winW = 1100;
|
||||
winH = 600;
|
||||
}
|
||||
winH += BTGaugeStripHeightFor(winW);
|
||||
}
|
||||
winH += BTGaugeStripHeightFor(winW);
|
||||
}
|
||||
}
|
||||
RECT wr = { 0, 0, winW, winH };
|
||||
|
||||
Reference in New Issue
Block a user