Cockpit: buttons under the glass, -fit, and player display layout

Button banks
  The exploded diagnostic view was still display-only - it predates the
  button work - so it now builds the same banks as the cockpit, with
  the pod arrangement laid out from the panes measured sizes rather
  than a hardcoded 640/480 grid (the banks make each window bigger than
  its glass, and the bottom row hung off the work area otherwise).

  The map side columns were spread height/6 from the top, but the maps
  own legend grid is not sixths: measured off the bitmap it starts 13
  rows down with six 102-tall cells on a 105 pitch. Every button sat
  high of its label, worst at the bottom. Each buttons top and bottom
  now come off that grid separately and are subtracted - scaling a
  height directly would let rounding drift them back out of step on a
  resized cockpit.

  Depth 100 to 240: against the 480 glass the two banks meet in the
  middle bar the strips, so practically the whole display is a press
  target. This mattered most in the cockpit, where the panes are small
  enough that the halfway clamp governs - at 100 the MFDs had a 110px
  dead band straight through the middle of the glass.

-fit (also spelled -windowed-fullscreen)
  Borderless over the whole monitor, with the render size chosen to
  match. The cockpit presents the 3D into a viewscreen that fills its
  canvas, so the right -res is that canvas at the scale the cockpit
  will settle on; computing it with identical arithmetic makes the
  stretch a copy. On the 3440x1440 panel that is 133% and -res 2553
  1436, against 125% for the windowed path that pays for the taskbar.

  The pick runs after the whole command line, so an explicit -res wins
  from either side of -fit. Capped at 3840x2160. Cockpit mode only -
  mode 0 has to stay playable on real pod hardware and mode 2 is a dev
  view - so those get the resolution and keep their windows.

Display layout, in environ.ini
  L4MFDSCALE sizes all five MFDs, L4MFDSCALE_UL and friends override
  any one of them, L4RADARSCALE the radar, and L4RADARPOS puts the
  radar bottom centre, in either bottom corner, or halfway up either
  side. Scaling is applied in canvas units before the canvas is fitted
  to the window, so a number means the same thing on every monitor.

  Sizing each display separately let the clamps become exact rather
  than one conservative rule for all five: what limits a display is its
  actual neighbour. Which neighbour that is depends on the radar, so
  the clamps follow it - on the bottom edge it clears the one MFD above
  its column, but centred on a side it has one above AND below and
  grows from the middle both ways, so it must clear the taller twice
  over. Clamping shrinks uniformly; these are photographs of real
  instruments and a one-axis clamp would squash them.

Verified on the ultrawide: all five radar positions, per-display and
group scaling with the clamps biting, -fit with and without an explicit
-res, and the button geometry measured back off the screen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-25 14:05:02 -05:00
co-authored by Claude Fable 5
parent 6b43971d2d
commit 8dc6605a07
5 changed files with 687 additions and 68 deletions
+80 -1
View File
@@ -94,6 +94,8 @@ HINSTANCE L4Application::mhInstance = NULL;
unsigned int L4Application::mScreenWidth = 800;
unsigned int L4Application::mScreenHeight = 600;
bool L4Application::mFullscreen = true;
bool L4Application::mFitDisplay = false;
bool L4Application::mResExplicit = false;
Logical L4Application::seeSolids = False;
CString L4Application::eggNotationFileName;
CString L4Application::spoolFileName;
@@ -205,6 +207,7 @@ Logical
{
mScreenWidth = atoi(W2A(argv[++(*arguement)]));
mScreenHeight = atoi(W2A(argv[++(*arguement)]));
mResExplicit = true;
}
else
{
@@ -217,18 +220,88 @@ Logical
mFullscreen = false;
}
//-------------------------------------------------------------------
// -fit: borderless window over the whole monitor, and a render size
// picked to match. Spelled out as -windowed-fullscreen too, since
// that is what the rest of the world calls it.
//-------------------------------------------------------------------
else if (
!stricmp(W2A(argv[*arguement]), "-fit") ||
!stricmp(W2A(argv[*arguement]), "-windowed-fullscreen")
)
{
mFullscreen = false;
mFitDisplay = true;
}
else if (
!stricmp(W2A(argv[*arguement]), "-h") || !stricmp(W2A(argv[*arguement]), "-help")
)
{
DEBUG_STREAM << "\n" << argv[0] <<
" -egg <filename> -net <memory_address> -solids -h -help\n";
" -egg <filename> -net <memory_address> -solids -h -help\n"
" -windowed windowed, title bar and all\n"
" -fit borderless over the whole monitor,\n"
" render size chosen to match\n"
" (long form: -windowed-fullscreen)\n"
" -res <width> <height> explicit render size; overrides the\n"
" size -fit would have picked\n";
return False;
}
return True;
}
//
//#############################################################################
// ChooseFitResolution
//#############################################################################
//
// The cockpit presents the 3D into a viewscreen that fills its 1920x1080
// canvas, and that canvas is fitted to the window at one uniform scale.
// So the render size that lands 1:1 on screen is the canvas at the same
// scale the cockpit will choose - work it out with identical arithmetic
// here and the stretch becomes a copy.
//
void
L4Application::ChooseFitResolution()
{
int monitor_w = GetSystemMetrics(SM_CXSCREEN);
int monitor_h = GetSystemMetrics(SM_CYSCREEN);
if (monitor_w <= 0 || monitor_h <= 0)
{
return;
}
const int canvas_w = 1920;
const int canvas_h = 1080;
int fit_w = (monitor_w * 100) / canvas_w;
int fit_h = (monitor_h * 100) / canvas_h;
int scale = (fit_w < fit_h) ? fit_w : fit_h;
if (scale < 25) scale = 25;
unsigned int width = (canvas_w * scale) / 100;
unsigned int height = (canvas_h * scale) / 100;
//-------------------------------------------------------------------
// A 1995 engine on a 5K panel would be asked for a back buffer well
// past anything it was built for; cap and let D3D scale the last bit.
//-------------------------------------------------------------------
if (width > 3840)
{
width = 3840;
height = 2160;
}
mScreenWidth = width;
mScreenHeight = height;
DEBUG_STREAM << "L4Application: -fit chose -res " << width << " "
<< height << " (" << scale << "% canvas) for the "
<< monitor_w << "x" << monitor_h << " monitor\n" << std::flush;
}
//
//#############################################################################
// ParseCommandLine
@@ -270,6 +343,12 @@ Logical
}
}
}
// after the whole line, so -res wins from either side of -fit
if (mFitDisplay && !mResExplicit)
{
ChooseFitResolution();
}
return True;
}