Files
RP412/MUNGA_L4/L4MFDVIEW.h
T
CydandClaude Fable 5 6b43971d2d Cockpit scales both ways and re-fits on resize, aspect locked
The canvas was capped at 100%, so a bigger monitor got a 1920x1080
cockpit in the corner of the screen and maximising did nothing - the
layout only ran once at startup.

Now the fit is one uniform scale with no ceiling, recomputed whenever
the window changes size (maximise, restore, drag), and the canvas is
centred in whatever client area it gets. Uniform scale is what locks
the aspect: a wider-than-16:9 desktop letterboxes with even black bars
instead of stretching the cockpit. Panes gained Resize() so the glass
and its button banks re-scale with the canvas; the pixel buffers keep
their native source resolution.

Scaling up is free quality on the MFDs - their glass is a downscale of
a native 640x480 channel until about 200%.

Verified on the 3440x1392 ultrawide: opens at 125% (2400x1350) instead
of 100%, maximises to 126% centred with even bars, a 1884x661 window
fits 61% letterboxed left/right, 1084x961 fits 56% letterboxed top/
bottom, and a 2584x1461 client scales up to 134%.

The 3D still renders at -res and D3D stretches it to the canvas, so
raise -res to match a large screen for 1:1 pixels; start-windowed.bat
and the README say so.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 12:41:47 -05:00

145 lines
3.5 KiB
C++

#pragma once
#include "..\munga\style.h"
//########################################################################
//############################ MFDSplitView ##############################
//########################################################################
//
// One desktop window showing a single cockpit display, used by SVGA16's
// split mode (L4MFDSPLIT=1). The pod hardware packed the five monochrome
// MFDs into the color channels of two video outputs and mounted the map
// display rotated; on a desktop each display gets its own window instead.
//
// Each window also carries its display's physical button bank, exactly
// as mounted in the pod (geometry per vRIO's CockpitLayout):
// - MFDs: a 4x2 cluster - 4 red buttons above the glass, 4 below,
// RIO addresses descending from the cluster anchor (top-left = hi).
// - The map ("secondary screen"): 6 amber buttons down each side -
// Secondary 0x10-0x15 on the left, Screen 0x18-0x1D on the right
// (the remaining column addresses are Tesla relays, not buttons).
// Buttons light from the lamp state the game commands (via PadRIO) and
// press/release RIO units with the mouse.
//
// SVGA16 fills Pixels() (32bpp top-down, sourceWidth x sourceHeight as
// passed - already swapped by the caller for the rotated map) and calls
// Repaint(). Closing a view window just hides it.
//
class MFDSplitView
{
public:
enum ButtonStyle
{
NoButtons = 0,
MFDStrips, // 4 above + 4 below, addresses descend from anchorA
SideColumns // 6 per side; anchorA = left base, anchorB = right base
};
// With a parent, the view is created as a chrome-less child window
// inside the single cockpit window (x/y in parent client coords);
// without one it is its own draggable desktop window.
MFDSplitView(
const char *title,
int source_width,
int source_height,
int display_width,
int display_height,
int x,
int y,
ButtonStyle button_style = NoButtons,
int anchorA = 0,
int anchorB = 0,
void *parent = 0
);
int
ClientWidth() const
{ return clientWidth; }
int
ClientHeight() const
{ return clientHeight; }
// Move the pane (child mode: parent client coords). Panes overlap
// the viewscreen like the pod's bezels, so exact placement happens
// after construction from the measured client sizes.
void
SetPosition(int x, int y);
// Re-scale the glass (cockpit resized): the source buffer is
// unchanged, only the destination size and the button geometry
// derived from it.
void
Resize(int display_width, int display_height);
~MFDSplitView();
Logical
TestInstance() const;
unsigned long *
Pixels()
{ return pixels; }
void
Repaint();
// Window-procedure callbacks (public for the registered WndProc)
void
Paint();
void
MouseDown(int x, int y);
void
MouseUp();
protected:
void
LayoutButtons(
ButtonStyle button_style,
int anchorA,
int anchorB,
int display_width,
int display_height,
int *client_width,
int *client_height
);
struct ScreenButton
{
int unit;
int x, y, w, h;
int amber; // 0 = red family, 1 = amber family
};
enum { maxButtons = 20 };
void
*window; // HWND
void
*blitHeader; // BITMAPINFOHEADER for StretchDIBits
unsigned long
*pixels;
int
sourceWidth,
sourceHeight;
int
displayX, displayY,
displayW, displayH;
int
clientWidth, clientHeight;
ScreenButton
buttons[maxButtons];
int
buttonCount;
int
pressedIndex;
// kept so the bank can be rebuilt when the cockpit re-scales
ButtonStyle
buttonStyle;
int
buttonAnchorA,
buttonAnchorB;
};