Files
RP412/RP_L4/RPL4GAUG.h
T
CydandClaude Opus 5 1dd40be0a3 The map draws on every step of the rate wheel
The renderer walks a sixteen-step rate wheel: one step per full pass over
the gauge list, shifted right each pass and reset at the bottom. A gauge
redraws only on the step its configured rate names, so the map - on one
step - waited a whole turn of the wheel however cheap its redraw was.

With the frame budget fixed the wheel turns about fifty times a second
and one-in-sixteen would be tolerable. It is still the wrong shape for
the map: the thing a pilot reads to navigate should not be the display
that updates least often, and RP412MAPRATE says how many of the sixteen
steps it draws on. Sixteen by default, one for the old data-driven
behaviour. Each extra step costs one gauge's redraw against a pass that
runs ninety of them, which measured as nothing.

The write has to be QUALIFIED, and that is worth recording because it
cost hours. GPS's constructor takes its rate as a parameter also called
'rate', which shadows the inherited Gauge::rate for the whole body - so a
bare assignment sets the parameter and leaves the member holding whatever
the gauge data asked for. oldRate is not shadowed, so it took the value,
and the pair then disagreed: rate=2000, old=ffff. That looked exactly
like something writing the member from outside, and there is no such
writer - Gauge touches rate in three places, none of which can produce
that pair. A hardware write-watch on the member settled it by reporting
an address on the STACK.

Also here, the terrain-arrival work on the map background. It draws one
placement into the cached picture when the static bounds are unchanged,
and rebuilds the whole thing only when they move - the bounds set the
scale, and the scale is what everything already on the picture was drawn
at. It is honest to say this fires rarely: the logs show terrain arriving
in one burst at mission load, not streaming in as you drive, so the
incremental path is mostly insurance. What it does close is real, though
- departures now order a rebuild. Nothing listened for those before, and
they had been swept up by the rebuild the next ARRIVAL ordered, which on
a track whose terrain all arrives at load is a rebuild that never comes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 13:13:03 -05:00

598 lines
10 KiB
C++

#pragma once
#include "..\munga_l4\l4grend.h"
#include "..\munga_l4\l4gauge.h"
#include "..\munga\rotation.h"
#include "..\munga\random.h"
#include "..\munga\point3d.h"
//#########################################################################
//####################### Various gauge utilities #########################
//#########################################################################
extern int
determineEntityColor(Entity *entity, Entity *local_entity=NULL);
//#########################################################################
class Compass :
public GraphicGauge
{
public:
static MethodDescription
methodDescription;
static Logical
Make(
int display_port_index,
Vector2DOf<int> position,
Entity *entity,
GaugeRenderer *gauge_renderer
);
Compass(
GaugeRate rate,
ModeMask mode_mask,
L4GaugeRenderer *renderer,
unsigned int owner_ID,
int graphics_port_number,
int center_x, int center_y,
int radius,
int background_color,
const char *north_map_name,
const char *west_map_name,
const char *south_map_name,
const char *east_map_name,
const char *bug_map_name,
const char *identification_string = "Compass"
);
~Compass();
Logical
TestInstance() const;
void
ShowInstance(char *indent);
void
BecameActive();
void
Execute();
protected:
enum
{
northIndex = 0,
eastIndex,
southIndex,
westIndex,
bugIndex,
numberOfItems
};
char
*imageName[numberOfItems];
Vector2DOf<int>
offset[numberOfItems],
previousPosition;
int
radius,
backgroundColor;
L4GaugeRenderer
*renderer;
GraphicsViewRecord
previousDrawing;
};
class ThreatIndicator :
public GraphicGauge
{
public:
static MethodDescription
methodDescription;
static Logical
Make(
int display_port_index,
Vector2DOf<int> position,
Entity *entity,
GaugeRenderer *gauge_renderer
);
ThreatIndicator(
GaugeRate rate,
ModeMask mode_mask,
L4GaugeRenderer *renderer,
unsigned int owner_ID,
int graphics_port_number,
int center_x, int center_y,
int inner_radius,
int outer_radius,
int bg_color,
int team_color,
int other_color,
Scalar sensing_radius,
const char *identification_string = "ThreatIndicator"
);
~ThreatIndicator();
Logical
TestInstance() const;
void
ShowInstance(char *indent);
void
BecameActive(); // virtual function in 'GaugeBase'
void
Execute();
protected:
void
Select();
void
Draw();
Scalar
viewRadius,
topClosingVelocity;
int
innerRadius,
outerRadius,
backgroundColor,
teamColor,
otherColor,
operatingPhase;
GaugeEntityList
movingEntityList;
GraphicsViewRecord
previousDrawing;
};
class NavDisplay;
class NavName SIGNATURED // Used exclusively by NavDisplay
{
friend class NavDisplay;
NavName()
{}
~NavName()
{}
Logical
TestInstance() const
{
return True;
}
protected:
void
ExtractFromEntity(Entity *entity, AffineMatrix &worldToView);
static void
CalculatePositions(NavName *array, int count);
void
Draw(GraphicsView *graphics_view, Scalar radius_multiplier);
Point3D
center;
Vector3D
direction;
BitMap
*nameBitmap;
int
color;
};
class NavDisplay :
public GraphicGauge
{
public:
static MethodDescription
methodDescription;
static Logical
Make(
int display_port_index,
Vector2DOf<int> position,
Entity *entity,
GaugeRenderer *gauge_renderer
);
NavDisplay(
GaugeRate rate,
ModeMask mode_mask,
L4GaugeRenderer *renderer,
unsigned int owner_ID,
int graphics_port_number,
int left, int bottom,
int right, int top,
int bg_color,
int static_color,
Scalar *scale_value_pointer,
Point3D **position_pointer,
Quaternion **angle_pointer,
Logical allow_rock_and_roll=False,
const char *identification_string = "NavDisplay"
);
~NavDisplay();
Logical
TestInstance() const;
void
ShowInstance(char *indent);
void
BecameActive();
void
Execute();
protected:
void
CalculateBounds();
void
SelectStatic();
void
SelectMoving();
void
DrawStatic(AffineMatrix &worldToView);
void
DrawMoving(AffineMatrix &worldToView);
void
DrawNames(AffineMatrix &worldToView);
enum
{
maximumNames = 16
};
NavName
nameArray[maximumNames];
Scalar
currentScale;
Point3D *
currentPositionPointer;
Quaternion *
currentAngularPointer;
Scalar
LODIndex,
pixelsPerMeter,
metersPerPixel,
xMin,
yMin,
zMin,
xMax,
yMax,
zMax;
AffineMatrix
worldToView;
int
operatingPhase,
backgroundColor,
staticColor,
halfWidth,
halfHeight;
Logical
rockAndRoll;
GaugeEntityList
staticEntityList,
movingEntityList;
GraphicsViewRecord
previousDrawing;
};
class GPS :
public GraphicGauge
{
struct GPSRecord
{
int x, y, color;
Logical me;
};
public:
static MethodDescription
methodDescription;
static Logical
Make(
int display_port_index,
Vector2DOf<int> position,
Entity *entity,
GaugeRenderer *gauge_renderer
);
GPS(
GaugeRate rate,
ModeMask mode_mask,
L4GaugeRenderer *renderer,
unsigned int owner_ID,
int graphics_port_number,
int left, int bottom,
int right, int top,
Scalar LOD_index,
const char *identification_string = "GPS"
);
~GPS();
Logical
TestInstance() const;
void
ShowInstance(char *indent);
void
BecameActive(); // virtual function in 'GaugeBase'
void
NotifyOfNewInterestingEntity(Entity *entity);
//
// Terrain that leaves interest range is dropped from the map, and
// there is no way to un-draw one placement from a composited picture
// - so this is the one case that still costs a full rebuild.
//
void
NotifyOfBecomingUninterestingEntity(Entity *entity);
void
Execute();
protected:
void
UpdateStaticEntities();
//
// Draw one placement into the cached background, at the scale that
// background was built at. False if the entity has no GaugeImage and
// so never appears on the map at all - which on the big tracks is
// most of the terrain in them.
//
Logical
DrawStaticEntity(Entity *entity);
enum
{
max_moving_entities=32
};
Logical
needsStaticUpdate,
needsScreenUpdate,
// is there a picture worth adding a single placement to?
backgroundBuilt;
//
// The static bounds the background was last built for. They decide
// the scale, so terrain arriving inside them can be drawn onto the
// picture instead of forcing a new one - see
// GPS::NotifyOfNewInterestingEntity.
//
Scalar
builtMinX, builtMinY, builtMinZ,
builtMaxX, builtMaxY, builtMaxZ;
Scalar
LODIndex,
metersPerPixel,
pixelsPerMeter;
Point3D
centeringOffset;
int
width,
height,
numberOfMovingEntities;
GPSRecord
previousGPSRecord[max_moving_entities];
Video8BitBuffered
*background;
};
//#######################################################################
// Ranking
//#######################################################################
class Ranking :
public GraphicGauge
{
public:
static MethodDescription
methodDescription;
static Logical
Make(
int display_port_index,
Vector2DOf<int> position,
Entity *entity,
GaugeRenderer * gauge_renderer
);
Ranking(
GaugeRate rate,
ModeMask mode_mask,
L4GaugeRenderer *renderer,
unsigned int owner_ID,
int graphics_port_number,
int top, int left,
const char *font_name,
int spacing,
int numeric_color,
int new_options,
const char *identification_string = "Ranking"
);
~Ranking();
Logical
TestInstance() const;
void
ShowInstance(char *indent);
void
LinkToEntity(Entity *entity);
void
BecameActive();
void
Execute();
enum
{
useTeamColorOption=0x0001,
showAllScoresOption=0x0002,
showIcomOption=0x0004
};
protected:
char
*messageName;
enum
{
maximumDisplayedPlayers=8
};
Entity
*linkedEntity;
int
previousRanking;
int
x,
y,
options,
spacing,
width;
Player
*previousArray[maximumDisplayedPlayers];
Scalar
previousScore[maximumDisplayedPlayers];
NumericDisplay
*numericDisplay[maximumDisplayedPlayers];
Logical
previousIntercomEnabled;
int
previousChannel[maximumDisplayedPlayers];
NumericDisplay
*channelDisplay[maximumDisplayedPlayers];
};
//#######################################################################
// ConfigMap
//#######################################################################
class ConfigMap :
public GraphicGauge
{
public:
static MethodDescription
methodDescription;
static Logical
Make(
int display_port_index,
Vector2DOf<int> position,
Entity *entity,
GaugeRenderer * gauge_renderer
);
ConfigMap(
GaugeRate rate,
ModeMask mode_mask,
L4GaugeRenderer *renderer,
unsigned int owner_ID,
int graphics_port_number,
int top, int bottom,
const char *unmapped_icon,
const char *other_icon,
const char *my_icon,
const char *both_icon,
const char *identification_string = "ConfigMap"
);
~ConfigMap();
Logical
TestInstance() const;
void
ShowInstance(char *indent);
void
LinkToEntity(Entity *entity);
void
BecameActive();
void
Execute();
protected:
Entity
*linkedEntity;
char
*iconName[4];
int
previousState[4];
};
//#######################################################################
// MessageBoard
//#######################################################################
class MessageBoard :
public GraphicGauge
{
public:
static MethodDescription
methodDescription;
static Logical
Make(
int display_port_index,
Vector2DOf<int> position,
Entity *entity,
GaugeRenderer * gauge_renderer
);
MessageBoard(
GaugeRate rate,
ModeMask mode_mask,
L4GaugeRenderer *renderer,
unsigned int owner_ID,
int graphics_port_number,
int left, int bottom,
int right, int top,
const char *font_name,
const char *message_name,
int bg_color,
int numeric_color,
const char *identification_string = "MessageBoard"
);
~MessageBoard();
Logical
TestInstance() const;
void
ShowInstance(char *indent);
void
LinkToEntity(Entity *entity);
void
BecameActive();
void
Execute();
protected:
NumericDisplay
*numericDisplay;
Entity
*linkedEntity;
char
*messageName;
int
backgroundColor,
fontHeight;
enum
{
deliberatelyBogusPointerValue = -1
};
Player
*previousPlayerPointer;
int
previousMessageType;
Scalar
previousValue;
};