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>
248 lines
7.0 KiB
C++
248 lines
7.0 KiB
C++
//===========================================================================//
|
|
// File: l4app.hpp //
|
|
// Project: MUNGA Brick: L4Application //
|
|
// Contents: Interface specification for L4Application //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 01/21/95 ECH Initial coding. //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1994, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide. //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#pragma once
|
|
|
|
#include "..\munga\app.h"
|
|
#include "..\munga\APPMGR.h"
|
|
|
|
class DPLRenderer;
|
|
class L4AudioRenderer;
|
|
class L4GaugeRenderer;
|
|
class L4NetworkManager;
|
|
class LBE4ControlsManager;
|
|
class L4IcomManager;
|
|
|
|
//##########################################################################
|
|
//######################## L4Application #############################
|
|
//##########################################################################
|
|
|
|
class L4Application:
|
|
public Application
|
|
{
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Construction, Destruction, and Testing
|
|
//
|
|
public:
|
|
L4Application(
|
|
HINSTANCE hInstance,
|
|
HWND hWnd,
|
|
ResourceFile *resource_file,
|
|
ApplicationID application_ID,
|
|
ClassID class_ID=L4ApplicationClassID,
|
|
SharedData &shared_data=DefaultData
|
|
);
|
|
~L4Application();
|
|
|
|
Logical
|
|
TestInstance() const;
|
|
|
|
static Derivation *GetClassDerivations();
|
|
static SharedData DefaultData;
|
|
|
|
bool IsDead() {return mIsDead;}
|
|
void SetIsDead(bool isDead) {mIsDead = isDead;}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Command line parsing
|
|
//
|
|
public:
|
|
typedef Logical
|
|
(*TokenParser)(int *argument, int argc, LPWSTR argv[]);
|
|
static Logical
|
|
ParseToken(
|
|
int *argument,
|
|
int argc,
|
|
LPWSTR argv[]
|
|
);
|
|
static Logical
|
|
ParseCommandLine(
|
|
int argc,
|
|
LPWSTR argv[],
|
|
TokenParser parser = &L4Application::ParseToken
|
|
);
|
|
|
|
static int GetMissionReviewMode() { return missionReviewMode; }
|
|
static HINSTANCE GetAppInstance() { return mhInstance; }
|
|
static HWND GetMainWindow() { return ghWnd; }
|
|
static unsigned int GetScreenWidth() { return mScreenWidth; }
|
|
static unsigned int GetScreenHeight() { return mScreenHeight; }
|
|
static bool GetFullscreen() { return mFullscreen; }
|
|
// -fit: borderless window filling the monitor, with the render size
|
|
// chosen to match the cockpit canvas it will be presented into.
|
|
static bool GetFitDisplay() { return mFitDisplay; }
|
|
static Logical GetSeeSolids() { return seeSolids; }
|
|
static unsigned long GetNetworkCommonFlatAddress() { return networkCommonFlatAddress; }
|
|
// The front end's multiplayer path turns network mode on at launch
|
|
// time (the owner pod meshes like any other pod); command-line -net
|
|
// keeps working exactly as before.
|
|
static void SetNetworkCommonFlatAddress(unsigned long address) { networkCommonFlatAddress = address; }
|
|
static CString GetEggNotationFileName() { return eggNotationFileName; }
|
|
// the in-game front end builds an egg and injects it here
|
|
static void SetEggNotationFileName(const char *name) { eggNotationFileName = name; }
|
|
static CString GetSpoolFileName() { return spoolFileName; }
|
|
static CString GetRIOPlaybackFileName() { return rioPlaybackFileName; }
|
|
static CString GetRIORecordingFileName() { return rioRecordingFileName; }
|
|
|
|
protected:
|
|
// Pick mScreenWidth/mScreenHeight from the monitor. Runs after the
|
|
// whole command line is parsed, so an explicit -res always wins no
|
|
// matter which side of -fit it appears on.
|
|
static void ChooseFitResolution();
|
|
|
|
static HINSTANCE mhInstance;
|
|
static unsigned int mScreenWidth;
|
|
static unsigned int mScreenHeight;
|
|
static bool mFullscreen;
|
|
static bool mFitDisplay;
|
|
static bool mResExplicit;
|
|
static Logical seeSolids;
|
|
static CString eggNotationFileName;
|
|
static CString spoolFileName;
|
|
static unsigned long networkCommonFlatAddress;
|
|
static int missionReviewMode;
|
|
static CString rioPlaybackFileName;
|
|
static CString rioRecordingFileName;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execution control
|
|
//
|
|
public:
|
|
void
|
|
Initialize();
|
|
void
|
|
InitializeTillConsole();
|
|
|
|
Entity*
|
|
MakeAndLinkViewpointEntity(Entity__MakeMessage *message);
|
|
|
|
Entity*
|
|
MakeViewpointEntity(Entity__MakeMessage *message);
|
|
|
|
void
|
|
Terminate();
|
|
|
|
void
|
|
TeslaCoil(Logical lights_on);
|
|
|
|
void
|
|
PilotIllumination(Logical lights_on); // includes 'Tesla coil'
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Module accesors
|
|
//
|
|
public:
|
|
DPLRenderer*
|
|
GetVideoRenderer();
|
|
|
|
L4AudioRenderer*
|
|
GetAudioRenderer();
|
|
|
|
L4GaugeRenderer*
|
|
GetGaugeRenderer();
|
|
|
|
L4NetworkManager*
|
|
GetNetworkManager()
|
|
{return (L4NetworkManager*)Application::GetNetworkManager();}
|
|
LBE4ControlsManager*
|
|
GetControlsManager()
|
|
{return (LBE4ControlsManager*)Application::GetControlsManager();}
|
|
L4IcomManager*
|
|
GetIntercomManager()
|
|
{return (L4IcomManager*)Application::GetIntercomManager();}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Public data
|
|
//
|
|
public:
|
|
char
|
|
*divisionParameters;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Module Creation
|
|
//
|
|
protected:
|
|
ModeManager*
|
|
MakeModeManager();
|
|
|
|
ControlsManager*
|
|
MakeControlsManager();
|
|
|
|
IcomManager*
|
|
MakeIntercomManager();
|
|
|
|
NetworkManager*
|
|
MakeNetworkManager();
|
|
|
|
VideoRenderer*
|
|
MakeVideoRenderer();
|
|
|
|
AudioRenderer*
|
|
MakeAudioRenderer();
|
|
|
|
GaugeRenderer*
|
|
MakeGaugeRenderer(int *secondaryIndex, int *aux1Index, int *aux2Index);
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Message Support
|
|
//
|
|
public:
|
|
enum
|
|
{
|
|
LightsOutMessageID = Application::NextMessageID,
|
|
NextMessageID
|
|
};
|
|
|
|
static const HandlerEntry
|
|
MessageHandlerEntries[];
|
|
//static MessageHandlerSet MessageHandlers;
|
|
static MessageHandlerSet& GetMessageHandlers();
|
|
|
|
void
|
|
LightsOutMessageHandler(Receiver::Message *message);
|
|
void
|
|
RunMissionMessageHandler(RunMissionMessage *message);
|
|
void
|
|
StopMissionMessageHandler(StopMissionMessage *message);
|
|
void // HACK - the 'int' is actually 'ControlsKey'
|
|
KeyCommandMessageHandler(ReceiverDataMessageOf<int> *message);
|
|
|
|
private:
|
|
bool mIsDead;
|
|
};
|
|
|
|
extern L4Application * &l4_application;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~ L4Application inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
inline DPLRenderer*
|
|
L4Application::GetVideoRenderer()
|
|
{
|
|
Check(this);
|
|
return (DPLRenderer*)videoRenderer;
|
|
}
|
|
|
|
inline L4AudioRenderer*
|
|
L4Application::GetAudioRenderer()
|
|
{
|
|
Check(this);
|
|
return (L4AudioRenderer*)audioRenderer;
|
|
}
|
|
|
|
inline L4GaugeRenderer*
|
|
L4Application::GetGaugeRenderer()
|
|
{
|
|
Check(this);
|
|
return (L4GaugeRenderer*)gaugeRenderer;
|
|
} |