The pod's secondary/radar cockpit surface now renders as an inset in the 800x600 dev window under BT_DEV_GAUGES: radar/tactical grid, SPEED/HEADING/ MAGNETIC/PROP dials, and the color-coded ARMOR DAMAGE mech schematic -- real gauge content (nzSec=27247), composited from the shared CPU pixelBuffer. Composite pass (engine): SVGA16::DrawDevInset palette-expands the secondary plane into a MANAGED texture on the MAIN device and draws an XYZRHW inset quad; BTDrawGaugeInset() reaches the gauge renderer's 'sec' port and is called from DPLRenderer::ExecuteImplementation as the last draw before EndScene. Three reconstruction bugs fixed to get real content: 1. BTL4Application::MakeGaugeRenderer signature mismatch (REAL fix): the reconstructed no-arg override only HID the 2007-engine's widened 3-arg virtual MakeGaugeRenderer(int*,int*,int*), so the engine built a base L4GaugeRenderer whose ctor never parsed gauge/l4gauge.cfg -> empty symbol table -> "undefined label 'bhk1Init'" -> no ports/gauges. Matched the 3-arg signature so it truly overrides (args ignored; BT is fullscreen). Same bug class as the BTL4GaugeRenderer(false,NULL,NULL,NULL) ctor fix. 2. Parse hung on undefined primitives (gated dev accommodation): the BT gauge primitive table (BTL4MethodDescription) is still a stub, so an unknown primitive -> ReportParsingError -> Fail() -> a MODAL dialog freezing the parse. Under BT_DEV_GAUGES, skip the unknown primitive's params so labels register and the base "configure" primitive builds the ports. 3. Gauge widgets AV on NULL data bindings (gated): NumericDisplayScalar's NULL value_pointer -> GaugeConnectionDirectOf ctor deref (bind NULL->static zero); RankAndScore::Execute derefs unreconstructed game state (Gauge::GuardedExecute SEH wrapper -> Disable(True) on first fault). All guards gated on BT_DEV_GAUGES: default DEV un-regressed (TARGET DESTROYED, 0 crashes) and the pod path is byte-unchanged (strict Fail, no guards). Remaining (docs/GAUGE_COMPOSITE.md): the real gauge WIDGET reconstruction (BTL4MethodDescription method table + gauge->game-state data bindings), then Step 2 (RP<->BT MFD port-name reconcile) + Step 3 (2-window layout). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
430 lines
11 KiB
C++
430 lines
11 KiB
C++
#pragma once
|
|
|
|
#include "style.h"
|
|
|
|
typedef unsigned int GaugeRate;
|
|
class GaugeRenderer;
|
|
class GaugeBase;
|
|
class GraphicGaugeBackground;
|
|
class Gauge;
|
|
class GraphicGauge;
|
|
class GaugeConnection;
|
|
class Entity;
|
|
class GaugeAlarmManager;
|
|
|
|
#include "mode.h"
|
|
#include "slot.h"
|
|
#include "chain.h"
|
|
#include "receiver.h"
|
|
#include "graph2d.h"
|
|
|
|
//#########################################################################
|
|
//############################# GaugeBase #################################
|
|
//#########################################################################
|
|
class GaugeBase :
|
|
public Node
|
|
{
|
|
friend class GaugeRenderer;
|
|
//----------------------------------------------------------------------
|
|
// Constructor
|
|
//----------------------------------------------------------------------
|
|
protected:
|
|
GaugeBase(
|
|
ModeMask mode_mask,
|
|
GaugeRenderer *renderer,
|
|
unsigned int owner_ID,
|
|
const char *identification_string
|
|
);
|
|
//----------------------------------------------------------------------
|
|
// Destructor
|
|
//----------------------------------------------------------------------
|
|
public:
|
|
virtual ~GaugeBase();
|
|
//----------------------------------------------------------------------
|
|
// Test methods
|
|
//----------------------------------------------------------------------
|
|
Logical
|
|
TestInstance() const;
|
|
//----------------------------------------------------------------------
|
|
// Update methods
|
|
//----------------------------------------------------------------------
|
|
virtual void
|
|
BecameActive(),
|
|
BecameInactive(),
|
|
Inactivate(),
|
|
UpdateProfile(Scalar frame_percentage),
|
|
ReportProfile();
|
|
|
|
virtual Logical
|
|
Update(GaugeRate rate_mask);
|
|
|
|
virtual void
|
|
LinkToEntity(Entity *entity),
|
|
NotifyOfNewInterestingEntity(Entity *entity),
|
|
NotifyOfBecomingUninterestingEntity(Entity *entity);
|
|
|
|
virtual int
|
|
DiscernTier();
|
|
|
|
//----------------------------------------------------------------------
|
|
// Public data
|
|
//----------------------------------------------------------------------
|
|
public:
|
|
Logical
|
|
alreadyActivatedFlag; // This is really a visibility flag.
|
|
// Active/inactive lists are more like
|
|
// "should get redrawn" lists
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// Protected data
|
|
//----------------------------------------------------------------------
|
|
protected:
|
|
Logical
|
|
stayInactive; // used by GaugeRenderer during activation
|
|
unsigned int
|
|
ownerID;
|
|
ModeMask
|
|
modeMask;
|
|
GaugeRenderer
|
|
*renderer;
|
|
const char
|
|
*identificationString;
|
|
};
|
|
|
|
//#########################################################################
|
|
//########################### GaugeBackground #############################
|
|
//#########################################################################
|
|
class GaugeBackground :
|
|
public GaugeBase
|
|
{
|
|
protected:
|
|
GaugeBackground(
|
|
ModeMask mode_mask,
|
|
GaugeRenderer *renderer,
|
|
unsigned int owner_ID,
|
|
const char *identification_string = "GraphicGaugeBackground"
|
|
);
|
|
};
|
|
|
|
//#########################################################################
|
|
//######################## GraphicGaugeBackground #########################
|
|
//#########################################################################
|
|
class GraphicGaugeBackground :
|
|
public GaugeBackground
|
|
{
|
|
protected:
|
|
GraphicGaugeBackground(
|
|
ModeMask mode_mask,
|
|
GaugeRenderer *renderer,
|
|
unsigned int owner_ID,
|
|
int graphics_port_number,
|
|
const char *identification_string = "GraphicGaugeBackground"
|
|
);
|
|
//----------------------------------------------------------------------
|
|
// Protected data
|
|
//----------------------------------------------------------------------
|
|
GraphicsView
|
|
localView;
|
|
};
|
|
|
|
//#########################################################################
|
|
//########################## GaugeConnection ##############################
|
|
//#########################################################################
|
|
|
|
// The GaugeConnection object maintains one instance of a mapping from
|
|
// a value in some location to a parameter for a gauge.
|
|
|
|
class GaugeConnection :
|
|
public Plug
|
|
{
|
|
friend class Gauge;
|
|
|
|
public:
|
|
GaugeConnection(int parameter_ID);
|
|
~GaugeConnection();
|
|
|
|
Logical
|
|
TestInstance() const;
|
|
|
|
protected:
|
|
virtual void ShowInstance(char *indent);
|
|
virtual void Update();
|
|
|
|
int parameterID;
|
|
};
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GaugeConnectionDirectOf ~~~~~~~~~~~~~~~~~~
|
|
|
|
template <class T> class GaugeConnectionDirectOf:
|
|
public GaugeConnection
|
|
{
|
|
friend class Gauge;
|
|
|
|
public:
|
|
GaugeConnectionDirectOf(
|
|
int parameter_ID,
|
|
T* data_destination,
|
|
T* data_source
|
|
);
|
|
~GaugeConnectionDirectOf();
|
|
Logical
|
|
TestInstance() const;
|
|
|
|
protected:
|
|
void
|
|
Update();
|
|
|
|
void
|
|
ShowInstance(char *indent);
|
|
|
|
T *dataSource;
|
|
T *dataDestination;
|
|
};
|
|
|
|
template <class T> GaugeConnectionDirectOf<T>::GaugeConnectionDirectOf(
|
|
int parameter_ID,
|
|
T* data_destination,
|
|
T* data_source
|
|
):
|
|
GaugeConnection(parameter_ID),
|
|
dataSource(data_source),
|
|
dataDestination(data_destination)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Pointer(data_destination);
|
|
|
|
//
|
|
// BT DEV-GAUGES bring-up: some gauge widgets bind to mech data sources that
|
|
// are not reconstructed yet, so the attribute resolves to a NULL data_source
|
|
// (see the "(Scalar *) is VERY dangerous!" note in L4GAUGE.cpp). Rather than
|
|
// AV here (and later in Update()), bind to a static zero so the gauge simply
|
|
// reads 0. Gated on BT_DEV_GAUGES so the POD path is byte-unchanged.
|
|
//
|
|
if (data_source == NULL)
|
|
{
|
|
static int s_devGauges = -1;
|
|
if (s_devGauges < 0)
|
|
s_devGauges = (getenv("BT_DEV_GAUGES") != NULL) ? 1 : 0;
|
|
if (s_devGauges)
|
|
{
|
|
static T s_gaugeNullSource = T();
|
|
dataSource = &s_gaugeNullSource;
|
|
data_source = &s_gaugeNullSource;
|
|
}
|
|
}
|
|
Check_Pointer(data_source);
|
|
|
|
*dataDestination = *dataSource;
|
|
Verify(*dataDestination == *dataSource);
|
|
Check(this);
|
|
}
|
|
|
|
template <class T> GaugeConnectionDirectOf<T>::~GaugeConnectionDirectOf()
|
|
{}
|
|
|
|
template <class T> void
|
|
GaugeConnectionDirectOf<T>::Update()
|
|
{
|
|
Check(this);
|
|
Check_Pointer(dataSource);
|
|
Check_Pointer(dataDestination);
|
|
*dataDestination = *dataSource;
|
|
Verify(*dataDestination == *dataSource);
|
|
Check(this);
|
|
}
|
|
|
|
template <class T> void
|
|
GaugeConnectionDirectOf<T>::ShowInstance(char *indent)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(dataSource);
|
|
Check_Pointer(dataDestination);
|
|
std::cout << indent << "GaugeConnectionDirectOf:\n";
|
|
|
|
std::cout << indent << "...dataSource at" <<
|
|
dataSource << "=" << *dataSource << "\n";
|
|
std::cout << indent << "...dataDestination at" <<
|
|
dataSource << "\n" << std::flush;
|
|
GaugeConnection::ShowInstance(indent);
|
|
}
|
|
|
|
template <class T> Logical
|
|
GaugeConnectionDirectOf<T>::TestInstance() const
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Pointer(dataSource);
|
|
Check_Pointer(dataDestination);
|
|
return Plug::TestInstance();
|
|
}
|
|
|
|
|
|
//#########################################################################
|
|
//################################# Gauge #################################
|
|
//#########################################################################
|
|
|
|
class Gauge :
|
|
public GaugeBase
|
|
{
|
|
public:
|
|
enum
|
|
{
|
|
gaugeRate_A=0xFFFF, // every frame
|
|
|
|
gaugeRate_B=0xAAAA, // every other frame
|
|
gaugeRate_C=0x5555,
|
|
|
|
gaugeRate_D=0x8888, // every 4th frame
|
|
gaugeRate_E=0x4444,
|
|
gaugeRate_F=0x2222,
|
|
gaugeRate_G=0x1111,
|
|
|
|
gaugeRate_H=0x8080, // every 8th frame
|
|
gaugeRate_I=0x4040,
|
|
gaugeRate_J=0x2020,
|
|
gaugeRate_K=0x1010,
|
|
gaugeRate_L=0x0808,
|
|
gaugeRate_M=0x0404,
|
|
gaugeRate_N=0x0202,
|
|
gaugeRate_O=0x0101,
|
|
|
|
gaugeRate_P=0x8000, // every 16th frame
|
|
gaugeRate_Q=0x4000,
|
|
gaugeRate_R=0x2000,
|
|
gaugeRate_S=0x1000,
|
|
gaugeRate_T=0x0800,
|
|
gaugeRate_U=0x0400,
|
|
gaugeRate_V=0x0200,
|
|
gaugeRate_W=0x0100,
|
|
gaugeRate_X=0x0080,
|
|
gaugeRate_Y=0x0040,
|
|
gaugeRate_Z=0x0020,
|
|
gaugeRate_Z0=0x0010,
|
|
gaugeRate_Z1=0x0008,
|
|
gaugeRate_Z2=0x0004,
|
|
gaugeRate_Z3=0x0002,
|
|
gaugeRate_Z4=0x0001
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
// Public static methods and data
|
|
//----------------------------------------------------------------------
|
|
static GaugeRate
|
|
rateTable[31];
|
|
|
|
static GaugeRate
|
|
NextFirstTierGaugeRate(), // returns either B,C
|
|
NextSecondTierGaugeRate(), // returns DEFG
|
|
NextThirdTierGaugeRate(), // returns HIJKLMNO
|
|
NextFourthTierGaugeRate(); // returns PQRSTUVWXYZ
|
|
|
|
static GaugeRate
|
|
ConvertIndexToRate(int index);
|
|
|
|
//----------------------------------------------------------------------
|
|
// Constructor method
|
|
//----------------------------------------------------------------------
|
|
Gauge(
|
|
GaugeRate new_rate,
|
|
ModeMask mode_mask,
|
|
GaugeRenderer *renderer,
|
|
unsigned int owner_ID,
|
|
const char *identification_string = "Gauge"
|
|
);
|
|
//----------------------------------------------------------------------
|
|
// Destructor method
|
|
//----------------------------------------------------------------------
|
|
~Gauge();
|
|
//----------------------------------------------------------------------
|
|
// Test methods
|
|
//----------------------------------------------------------------------
|
|
Logical
|
|
TestInstance() const;
|
|
void
|
|
ShowInstance(char *indent);
|
|
int
|
|
DiscernTier();
|
|
static Logical
|
|
TestClass();
|
|
//----------------------------------------------------------------------
|
|
// Connection methods
|
|
//----------------------------------------------------------------------
|
|
virtual void
|
|
AddConnection(GaugeConnection *connection),
|
|
RemoveConnection(int parameter_ID),
|
|
RemoveAllConnections();
|
|
|
|
//----------------------------------------------------------------------
|
|
// Update methods
|
|
//----------------------------------------------------------------------
|
|
void
|
|
Disable(Logical disable_state);
|
|
Logical
|
|
Update(GaugeRate rate_mask);
|
|
protected:
|
|
virtual void
|
|
Execute(); // Execute internal processes to display the gauge
|
|
|
|
// BT DEV-GAUGES bring-up: SEH wrapper around Execute() so a gauge whose
|
|
// game-state data binding isn't reconstructed yet is skipped (not crashed).
|
|
// Returns False if Execute() raised a structured exception (e.g. an AV).
|
|
Logical
|
|
GuardedExecute();
|
|
//----------------------------------------------------------------------
|
|
// Protected data
|
|
//----------------------------------------------------------------------
|
|
protected:
|
|
GaugeRate
|
|
rate,
|
|
oldRate;
|
|
ChainOf<GaugeConnection*>
|
|
instanceList;
|
|
//---------------------------------------
|
|
// Profiling data
|
|
//---------------------------------------
|
|
void
|
|
UpdateProfile(Scalar frame_percentage),
|
|
ReportProfile();
|
|
|
|
Scalar
|
|
profileFramePercentage,
|
|
profileMaxFramePercentage;
|
|
int
|
|
profileCycles;
|
|
};
|
|
|
|
//#########################################################################
|
|
//############################# GraphicGauge ##############################
|
|
//#########################################################################
|
|
|
|
class GraphicGauge :
|
|
public Gauge
|
|
{
|
|
public:
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// Public methods
|
|
//----------------------------------------------------------------------
|
|
//
|
|
GraphicGauge(
|
|
GaugeRate new_rate,
|
|
ModeMask mode_mask,
|
|
GaugeRenderer *renderer,
|
|
unsigned int owner_ID,
|
|
int graphics_port_number,
|
|
const char *identification_string = "GraphicGauge"
|
|
);
|
|
~GraphicGauge();
|
|
|
|
Logical
|
|
TestInstance() const;
|
|
|
|
void
|
|
ShowInstance(char *indent);
|
|
//----------------------------------------------------------------------
|
|
// Public data
|
|
//----------------------------------------------------------------------
|
|
GraphicsView
|
|
localView;
|
|
};
|