From 775ee130a7c32e36cb7d3277ef08f2acf15e2ab5 Mon Sep 17 00:00:00 2001 From: Cyd Date: Sun, 12 Jul 2026 14:40:32 -0500 Subject: [PATCH] Default layout now emulates the pod interior [ MFD UL ] [ MFD UC ] [ MFD UR ] [ plasma (reduced) ][ main screen (centered) ] [ MFD LL ] [ Map ] [ MFD LR ] SVGA16 moves the main game window into the middle band (centered under the MFD columns) and shrinks the plasma glass to fill the space at its left via a new PlasmaScreen::Position hook (the glass paint stretches to the client area, so resizing rescales it). Lower row sits below the main screen band. Co-Authored-By: Claude Fable 5 --- MUNGA_L4/L4PLASMASCREEN.cpp | 32 +++++++++++++++++++ MUNGA_L4/L4PLASMASCREEN.h | 9 ++++++ MUNGA_L4/L4VB16.cpp | 62 +++++++++++++++++++++++++++++-------- 3 files changed, 90 insertions(+), 13 deletions(-) diff --git a/MUNGA_L4/L4PLASMASCREEN.cpp b/MUNGA_L4/L4PLASMASCREEN.cpp index 66388b5..03918b3 100644 --- a/MUNGA_L4/L4PLASMASCREEN.cpp +++ b/MUNGA_L4/L4PLASMASCREEN.cpp @@ -61,6 +61,33 @@ namespace //############################ PlasmaScreen ############################## //######################################################################## +PlasmaScreen *PlasmaScreen::activeInstance = NULL; + +void + PlasmaScreen::Position(int x, int y, int client_width, int client_height) +{ + if (activeInstance == NULL || activeInstance->window == NULL) + { + return; + } + + DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; + RECT bounds; + bounds.left = 0; + bounds.top = 0; + bounds.right = client_width; + bounds.bottom = client_height; + AdjustWindowRect(&bounds, style, FALSE); + + SetWindowPos( + (HWND) activeInstance->window, NULL, + x, y, + bounds.right - bounds.left, + bounds.bottom - bounds.top, + SWP_NOZORDER | SWP_NOACTIVATE + ); +} + PlasmaScreen::PlasmaScreen(): Video8BitBuffered(plasmaWidth, plasmaHeight) { @@ -119,6 +146,10 @@ PlasmaScreen::~PlasmaScreen() { Check_Pointer(this); + if (activeInstance == this) + { + activeInstance = NULL; + } if (window != NULL) { RemovePropA((HWND) window, "PlasmaBitmapInfo"); @@ -219,6 +250,7 @@ void SetPropA((HWND) window, "PlasmaBitmapInfo", bitmapInfo); SetPropA((HWND) window, "PlasmaPixels", pixelBuffer->Data.MapPointer); ShowWindow((HWND) window, SW_SHOWNOACTIVATE); + activeInstance = this; } else { diff --git a/MUNGA_L4/L4PLASMASCREEN.h b/MUNGA_L4/L4PLASMASCREEN.h index 063ecef..fb3faa9 100644 --- a/MUNGA_L4/L4PLASMASCREEN.h +++ b/MUNGA_L4/L4PLASMASCREEN.h @@ -37,7 +37,16 @@ public: void WaitForUpdate(); + // Reposition/resize the live glass (client-area size; the paint + // stretches to fit, so this also rescales it). Used by SVGA16's + // split-view layout; no-op when no plasma screen exists. + static void + Position(int x, int y, int client_width, int client_height); + protected: + static PlasmaScreen + *activeInstance; + void CreateGlassWindow(); diff --git a/MUNGA_L4/L4VB16.cpp b/MUNGA_L4/L4VB16.cpp index 67c0fb4..9495f9f 100644 --- a/MUNGA_L4/L4VB16.cpp +++ b/MUNGA_L4/L4VB16.cpp @@ -3,6 +3,7 @@ #include "l4vb16.h" #include "l4mfdview.h" +#include "l4plasmascreen.h" #include "../munga/gaugrend.h" #include "L4VIDEO.h" #include "DXUtils.h" @@ -3858,14 +3859,49 @@ SVGA16::SVGA16( int cell_h = (init_height * scale_percent) / 100; int frame_h = GetSystemMetrics(SM_CYCAPTION) + 2 * GetSystemMetrics(SM_CYFIXEDFRAME); int frame_w = 2 * GetSystemMetrics(SM_CXFIXEDFRAME); - int grid_x = init_width + frame_w; - // The pod stacks its displays vertically: upper MFDs above the - // viewscreen, weapon MFDs + secondary below it. On the desktop - // the upper row sits level with the main screen's top and the - // lower row drops below its bottom edge, so the main screen - // reads as the middle band. - int row2_y = (int) L4Application::GetScreenHeight(); + //--------------------------------------------------------------- + // Emulate the pod interior: + // [ MFD UL ] [ MFD UC ] [ MFD UR ] + // [ plasma (reduced) ][ main screen (centered) ] + // [ MFD LL ] [ Map ] [ MFD LR ] + // The main game window is moved into the middle band; the plasma + // glass shrinks to fill the space at its left. + //--------------------------------------------------------------- + int strip_h = cell_h / 8; + if (strip_h < 18) strip_h = 18; + if (strip_h > 40) strip_h = 40; + int mfd_extra_h = 2 * (strip_h + 8); + + int col_span = cell_w + frame_w; + int row_w = 3 * col_span; + int band_y = cell_h + mfd_extra_h + frame_h; // below the upper row + + int main_w = (int) L4Application::GetScreenWidth(); + int main_h = (int) L4Application::GetScreenHeight(); + int main_x = (row_w - main_w) / 2; + if (main_x < 0) main_x = 0; + + HWND main_window = ApplicationManager::GetCurrentManager()->GetHWnd(); + if (main_window != NULL) + { + SetWindowPos(main_window, NULL, main_x, band_y, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); + } + + // plasma: reduced to fit left of the main screen, centered + // vertically in the band (128x32 glass aspect) + int plasma_avail = main_x - 12; + if (plasma_avail >= 128) + { + int glass_w = plasma_avail; + int glass_h = glass_w / 4; + PlasmaScreen::Position( + 4, band_y + (main_h - glass_h - frame_h) / 2, + glass_w, glass_h); + } + + int lower_y = band_y + main_h; //--------------------------------------------------------------- // Button banks per display (addresses per vRIO CockpitLayout, @@ -3876,23 +3912,23 @@ SVGA16::SVGA16( //--------------------------------------------------------------- splitView[SplitMFDUpperLeft] = new MFDSplitView( "MFD upper left", init_width, init_height, - cell_w, cell_h, grid_x, 0, + cell_w, cell_h, 0, 0, MFDSplitView::MFDStrips, 0x2F); splitView[SplitMFDUpperCenter] = new MFDSplitView( "MFD upper center", init_width, init_height, - cell_w, cell_h, grid_x + (cell_w + frame_w), 0, + cell_w, cell_h, col_span, 0, MFDSplitView::MFDStrips, 0x27); splitView[SplitMFDUpperRight] = new MFDSplitView( "MFD upper right", init_width, init_height, - cell_w, cell_h, grid_x + 2 * (cell_w + frame_w), 0, + cell_w, cell_h, 2 * col_span, 0, MFDSplitView::MFDStrips, 0x37); splitView[SplitMFDLowerLeft] = new MFDSplitView( "MFD lower left", init_width, init_height, - cell_w, cell_h, grid_x, row2_y, + cell_w, cell_h, 0, lower_y, MFDSplitView::MFDStrips, 0x0F); splitView[SplitMFDLowerRight] = new MFDSplitView( "MFD lower right", init_width, init_height, - cell_w, cell_h, grid_x + 2 * (cell_w + frame_w), row2_y, + cell_w, cell_h, 2 * col_span, lower_y, MFDSplitView::MFDStrips, 0x07); // map is portrait: source rotated 90 degrees clockwise; shift left // by one side-button column so the GLASS (not the window) centers @@ -3903,7 +3939,7 @@ SVGA16::SVGA16( splitView[SplitMap] = new MFDSplitView( "Map", init_height, init_width, cell_h, cell_w, - grid_x + (cell_w + frame_w) + (cell_w - cell_h) / 2 - (map_col_w + 8), row2_y, + col_span + (cell_w - cell_h) / 2 - (map_col_w + 8), lower_y, MFDSplitView::SideColumns, 0x10, 0x18); DEBUG_STREAM << "SVGA16: split views active - 5 MFD windows + rotated map, cockpit buttons on (scale "