Imports the current Win32 source for the pod-racing game 'Red Planet', built on the MUNGA engine and its L4 (Win32/DirectX) platform layer: - MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend - RP / RP_L4: Red Planet game logic and Win32 application - DivLoader, Setup1: asset loader and installer project - lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies Removed stale Subversion metadata and added .gitignore/.gitattributes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3824 lines
94 KiB
C++
3824 lines
94 KiB
C++
#include "rpl4.h"
|
|
#pragma hdrstop
|
|
|
|
#define PRELOAD_ART
|
|
|
|
# include "rpl4gaug.h"
|
|
# include "rpl4grnd.h"
|
|
# include "rpl4mode.h"
|
|
# include "rpl4mppr.h"
|
|
# include "..\munga_l4\l4gauge.h"
|
|
# include "..\munga_l4\l4gauima.h"
|
|
# include "..\munga_l4\l4vb8.h"
|
|
# include "..\munga_l4\l4ctrl.h"
|
|
# include "..\munga_l4\l4icom.h"
|
|
# include "..\rp\rpplayer.h"
|
|
# include "..\munga\terrain.h"
|
|
# include "..\munga\mission.h"
|
|
# include "..\rp\vtv.h"
|
|
# include "..\munga\nttmgr.h"
|
|
# include "..\munga\app.h"
|
|
|
|
// #define LOCAL_TEST
|
|
|
|
#if defined(LOCAL_TEST)
|
|
# define Test_Tell(n) std::cout << n
|
|
#else
|
|
# define Test_Tell(n)
|
|
#endif
|
|
|
|
union quickCompare
|
|
{
|
|
char ascii[4];
|
|
long bytes4;
|
|
};
|
|
|
|
struct colorTable
|
|
{
|
|
quickCompare name;
|
|
int colorValue;
|
|
};
|
|
|
|
static colorTable
|
|
colorLookUp[] =
|
|
{
|
|
{ {"Aqu"} , 1 },
|
|
{ {"Bla"} , 2 },
|
|
{ {"Blu"} , 3 },
|
|
{ {"Gre"} , 4 },
|
|
{ {"Pin"} , 5 },
|
|
{ {"Pur"} , 6 },
|
|
{ {"Red"} , 7 },
|
|
{ {"Whi"} , 8 },
|
|
{ {"Yel"} , 9 },
|
|
{ {"xxx"} , -1}
|
|
};
|
|
|
|
int
|
|
determineEntityColor(Entity *entity, Entity */*local_entity*/)
|
|
{
|
|
|
|
const char
|
|
*color_name;
|
|
quickCompare
|
|
compare;
|
|
colorTable
|
|
*colors;
|
|
|
|
if (entity->IsDerivedFrom(*VTV::GetClassDerivations()))
|
|
{
|
|
color_name = ((VTV *) entity)->vehicleColor;
|
|
compare.ascii[0] = *color_name++;
|
|
compare.ascii[1] = *color_name++;
|
|
compare.ascii[2] = *color_name;
|
|
compare.ascii[3] = '\0';
|
|
|
|
for (colors=colorLookUp; colors->colorValue >0; ++colors)
|
|
{
|
|
if (colors->name.bytes4 == compare.bytes4)
|
|
{
|
|
Check_Fpu();
|
|
return colors->colorValue;
|
|
}
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
return 255;
|
|
}
|
|
|
|
Scalar
|
|
generateRelativeYaw(Scalar my_yaw, Vector3D &relative_position)
|
|
{
|
|
Vector3D
|
|
delta = relative_position,
|
|
unit;
|
|
//---------------------------------------------------------
|
|
// Generate unit vector pointing towards 'other'
|
|
//---------------------------------------------------------
|
|
delta.y = 0.0; // this may induce an error if delta_y is large
|
|
// (but I think we can live with it)
|
|
|
|
Scalar
|
|
length = delta.Length();
|
|
|
|
if (Small_Enough(length))
|
|
{
|
|
unit.x = 0.0;
|
|
unit.y = 0.0;
|
|
unit.z = -1.0;
|
|
}
|
|
else
|
|
{
|
|
unit = delta;
|
|
unit /= length;
|
|
Check_Fpu();
|
|
}
|
|
//---------------------------------------------------------
|
|
// Generate angle in radians
|
|
//---------------------------------------------------------
|
|
SinCosPair
|
|
sc_pair(unit.x, unit.z);
|
|
|
|
Radian
|
|
angle;
|
|
|
|
angle = sc_pair;
|
|
Check_Fpu();
|
|
//---------------------------------------------------------
|
|
// Get relative angle
|
|
//---------------------------------------------------------
|
|
angle -= my_yaw;
|
|
angle.Normalize();
|
|
Check_Fpu();
|
|
|
|
return angle;
|
|
}
|
|
|
|
static char
|
|
*nameCopy(const char *old_name)
|
|
{
|
|
Check_Pointer(old_name);
|
|
|
|
char
|
|
*copy = new char[strlen(old_name)+1];
|
|
Register_Pointer(copy);
|
|
strcpy(copy, old_name);
|
|
|
|
return copy;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Compass
|
|
//*****************************************************************************
|
|
MethodDescription
|
|
Compass::methodDescription =
|
|
{
|
|
"compass",
|
|
Compass::Make,
|
|
{
|
|
{ ParameterDescription::typeRate, NULL }, // rate ID
|
|
{ ParameterDescription::typeModeMask, NULL },// mode mask
|
|
{ ParameterDescription::typeInteger, NULL }, // NWES radius
|
|
{ ParameterDescription::typeColor, NULL }, // bg color
|
|
{ ParameterDescription::typeString, NULL }, // 'N' pixelmap
|
|
{ ParameterDescription::typeString, NULL }, // 'W' pixelmap
|
|
{ ParameterDescription::typeString, NULL }, // 'S' pixelmap
|
|
{ ParameterDescription::typeString, NULL }, // 'E' pixelmap
|
|
{ ParameterDescription::typeString, NULL }, // Bug pixelmap
|
|
PARAMETER_DESCRIPTION_END,
|
|
}
|
|
};
|
|
|
|
Logical
|
|
Compass::Make(
|
|
int display_port_index,
|
|
Vector2DOf<int> position,
|
|
Entity */*entity*/,
|
|
GaugeRenderer *gauge_renderer
|
|
)
|
|
{
|
|
Test_Tell("Compass::Make\n");
|
|
Check(gauge_renderer);
|
|
|
|
ParameterDescription
|
|
*parameterList = methodDescription.parameterList;
|
|
|
|
# if DEBUG_LEVEL > 0
|
|
parameterList[0].CheckIt(ParameterDescription::typeRate); // group ID
|
|
parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask
|
|
parameterList[2].CheckIt(ParameterDescription::typeInteger); // radius
|
|
parameterList[3].CheckIt(ParameterDescription::typeColor); // bg color
|
|
parameterList[4].CheckIt(ParameterDescription::typeString); // 'N' pixmap
|
|
parameterList[5].CheckIt(ParameterDescription::typeString); // 'W' pixmap
|
|
parameterList[6].CheckIt(ParameterDescription::typeString); // 'S' pixmap
|
|
parameterList[7].CheckIt(ParameterDescription::typeString); // 'E' pixmap
|
|
parameterList[8].CheckIt(ParameterDescription::typeString); // Bug pixmap
|
|
# endif
|
|
|
|
# if DEBUG_LEVEL > 0
|
|
Compass
|
|
*compass =
|
|
# endif
|
|
new Compass(
|
|
parameterList[0].data.rate,
|
|
parameterList[1].data.modeMask,
|
|
(L4GaugeRenderer *) gauge_renderer,
|
|
0, //unsigned int owner_ID
|
|
display_port_index, //int graphics_port_number
|
|
position.x,
|
|
position.y,
|
|
parameterList[2].data.integer,// NWES radius
|
|
parameterList[3].data.color, // bg color
|
|
parameterList[4].data.string, // 'N' pixelmap
|
|
parameterList[5].data.string, // 'W' pixelmap
|
|
parameterList[6].data.string, // 'S' pixelmap
|
|
parameterList[7].data.string, // 'E' pixelmap
|
|
parameterList[8].data.string // Bug pixelmap
|
|
);
|
|
Register_Object(compass);
|
|
//----------------------------------------------------------
|
|
// Make sure the icons were properly placed in the warehouse
|
|
//----------------------------------------------------------
|
|
Check(gauge_renderer);
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
|
|
Check(warehouse);
|
|
|
|
for(int i=4; i<=8; ++i)
|
|
{
|
|
if (warehouse->pixelMap8Bin.Get(parameterList[i].data.string) == NULL)
|
|
{
|
|
Test_Tell(
|
|
"Compass::Missing icon '" << parameterList[i].data.string <<
|
|
"'\n"
|
|
);
|
|
Check_Fpu();
|
|
return False;
|
|
}
|
|
else
|
|
{
|
|
warehouse->pixelMap8Bin.Release(parameterList[i].data.string);
|
|
}
|
|
}
|
|
//--------------------------------------------------------
|
|
// Everything's ok
|
|
//--------------------------------------------------------
|
|
Test_Tell("Compass::Make OK\n");
|
|
Check_Fpu();
|
|
return True;
|
|
}
|
|
|
|
void
|
|
prepCompassMap(
|
|
L4Warehouse *warehouse,
|
|
const char *image_name,
|
|
Vector2DOf<int> *offset
|
|
)
|
|
{
|
|
Check(warehouse);
|
|
|
|
//-------------------------------------------------------------
|
|
// Get the images and mark them as permanent!
|
|
// Because we record the graphics operations, the indicated
|
|
// images must be permanently located at the same address
|
|
// in order for the recorder to play back properly!
|
|
//-------------------------------------------------------------
|
|
PixelMap8
|
|
*image = warehouse->pixelMap8Bin.Get(image_name);
|
|
if (image != NULL)
|
|
{
|
|
Check(image);
|
|
|
|
offset->x = image->Data.Size.x >> 1;
|
|
offset->y = image->Data.Size.y >> 1;
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
// *DANGER* HEAVY-DUTY WARNING *DANGER*
|
|
//
|
|
// This object records graphics operations for
|
|
// later playback!
|
|
//
|
|
// Any graphic entities (such as bitmaps or gaugeImages)
|
|
// that are used here MUST be locked at the SAME address
|
|
// at playback time or the playback will crash HARD.
|
|
//
|
|
// *DANGER CONSIDER YOURSELF WARNED *DANGER*
|
|
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
|
|
Compass::Compass(
|
|
GaugeRate rate,
|
|
ModeMask mode_mask,
|
|
L4GaugeRenderer *new_renderer,
|
|
unsigned int owner_ID,
|
|
int graphics_port_number,
|
|
|
|
int center_x, int center_y,
|
|
int new_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
|
|
):
|
|
GraphicGauge(
|
|
rate,
|
|
mode_mask,
|
|
new_renderer,
|
|
owner_ID,
|
|
graphics_port_number,
|
|
identification_string
|
|
)
|
|
{
|
|
Check_Pointer(this);
|
|
|
|
// graphics_port may be NULL!
|
|
|
|
localView.SetOrigin(center_x, center_y);
|
|
|
|
radius = new_radius;
|
|
backgroundColor = background_color;
|
|
renderer = new_renderer;
|
|
Check(renderer);
|
|
|
|
//-------------------------------------------------
|
|
// Make local copies of image names
|
|
//-------------------------------------------------
|
|
imageName[northIndex]= nameCopy(north_map_name);
|
|
imageName[westIndex] = nameCopy(west_map_name);
|
|
imageName[southIndex]= nameCopy(south_map_name);
|
|
imageName[eastIndex] = nameCopy(east_map_name);
|
|
imageName[bugIndex] = nameCopy(bug_map_name);
|
|
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) renderer->warehousePointer;
|
|
Check(warehouse);
|
|
|
|
prepCompassMap(warehouse, north_map_name, &offset[northIndex]);
|
|
prepCompassMap(warehouse, west_map_name, &offset[westIndex]);
|
|
prepCompassMap(warehouse, south_map_name, &offset[southIndex]);
|
|
prepCompassMap(warehouse, east_map_name, &offset[eastIndex]);
|
|
prepCompassMap(warehouse, bug_map_name, &offset[bugIndex]);
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
Compass::~Compass()
|
|
{
|
|
Check(this);
|
|
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) renderer->warehousePointer;
|
|
Check(warehouse);
|
|
//-------------------------------------------------
|
|
// Delete local copies of image names
|
|
//-------------------------------------------------
|
|
for(int i=0; i<numberOfItems; ++i)
|
|
{
|
|
warehouse->pixelMap8Bin.Release(imageName[i]);
|
|
|
|
Unregister_Pointer(imageName[i]);
|
|
delete[] imageName[i];
|
|
imageName[i] = NULL;
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
Compass::TestInstance() const
|
|
{
|
|
return GraphicGauge::TestInstance();
|
|
}
|
|
|
|
void
|
|
Compass::ShowInstance(char *indent)
|
|
{
|
|
Check(this);
|
|
|
|
std::cout << indent << "Compass:\n";
|
|
|
|
char
|
|
temp[80];
|
|
|
|
Str_Copy(temp,indent, 80);
|
|
Str_Cat(temp,"...", 80);
|
|
|
|
// std::cout << temp << "backgroundColor=" << backgroundColor << "\n";
|
|
// std::cout << temp << "foregroundColor=" << foregroundColor << "\n";
|
|
// std::cout << temp << "numberOfDigits =" << numberOfDigits << "\n";
|
|
GraphicGauge::ShowInstance(temp);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
Compass::BecameActive()
|
|
{
|
|
Check(this);
|
|
|
|
previousPosition.x = -999.0;
|
|
previousPosition.y = -999.0;
|
|
}
|
|
|
|
void
|
|
Compass::Execute()
|
|
{
|
|
Check(this);
|
|
|
|
int
|
|
i;
|
|
|
|
Logical
|
|
bug_is_blanked;
|
|
|
|
Entity
|
|
*viewing_entity = renderer->GetLinkedEntity();
|
|
if (viewing_entity != NULL)
|
|
{
|
|
Check(viewing_entity);
|
|
|
|
YawPitchRoll
|
|
currentHeading;
|
|
currentHeading = viewing_entity->localOrigin.angularPosition;
|
|
|
|
SinCosPair
|
|
sc_pair;
|
|
sc_pair = currentHeading.yaw.angle;
|
|
|
|
Vector2DOf<int>
|
|
north_vector;
|
|
north_vector.x = (int) (radius*sc_pair.sine + .5);
|
|
north_vector.y = (int) (radius*sc_pair.cosine + .5);
|
|
|
|
if (
|
|
(north_vector.x != previousPosition.x) ||
|
|
(north_vector.y != previousPosition.y)
|
|
)
|
|
{
|
|
previousPosition.x = north_vector.x;
|
|
previousPosition.y = north_vector.y;
|
|
|
|
Vector2DOf<int>
|
|
position[numberOfItems];
|
|
//---------------------------------------------------------
|
|
// Get new compass positions
|
|
//---------------------------------------------------------
|
|
position[northIndex] = north_vector;
|
|
|
|
position[eastIndex].x = north_vector.y;
|
|
position[eastIndex].y = -north_vector.x;
|
|
|
|
position[southIndex].x = -north_vector.x;
|
|
position[southIndex].y = -north_vector.y;
|
|
|
|
position[westIndex].x = -north_vector.y;
|
|
position[westIndex].y = north_vector.x;
|
|
//---------------------------------------------------------
|
|
// Get new bug position
|
|
//---------------------------------------------------------
|
|
bug_is_blanked = True;
|
|
|
|
RPPlayer
|
|
*bugged_player = (RPPlayer *) viewing_entity->GetPlayerLink();
|
|
|
|
if (bugged_player != NULL)
|
|
{
|
|
Check(bugged_player);
|
|
Entity
|
|
*bug_entity = bugged_player->goalEntity;
|
|
|
|
if (bug_entity != NULL)
|
|
{
|
|
Check(bug_entity);
|
|
|
|
if (imageName[bugIndex] != NULL)
|
|
{
|
|
Vector3D
|
|
delta;
|
|
delta.Subtract(
|
|
bug_entity->localOrigin.linearPosition,
|
|
viewing_entity->localOrigin.linearPosition
|
|
);
|
|
|
|
Scalar
|
|
bug_yaw = generateRelativeYaw(
|
|
currentHeading.yaw.angle,
|
|
delta
|
|
);
|
|
|
|
sc_pair = bug_yaw;
|
|
|
|
position[bugIndex].x = (int) (radius*sc_pair.sine + .5);
|
|
position[bugIndex].y = -(int) (radius*sc_pair.cosine + .5);
|
|
|
|
bug_is_blanked = False;
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------
|
|
// Erase old compass
|
|
//---------------------------------------------------------
|
|
previousDrawing.Draw(&localView,backgroundColor);
|
|
previousDrawing.Clear();
|
|
//---------------------------------------------------------
|
|
// Draw new compass
|
|
//---------------------------------------------------------
|
|
Check(renderer);
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) renderer->warehousePointer;
|
|
Check(warehouse);
|
|
|
|
localView.AttachRecorder(&previousDrawing);
|
|
for(i=0; i<numberOfItems; ++i)
|
|
{
|
|
//---------------------------------------------------
|
|
// Get, lock pixel map from warehouse
|
|
//---------------------------------------------------
|
|
PixelMap8
|
|
*icon = warehouse->pixelMap8Bin.Get(imageName[i]);
|
|
//---------------------------------------------------
|
|
// Draw the icon
|
|
//---------------------------------------------------
|
|
if (icon != NULL)
|
|
{
|
|
if (bug_is_blanked && (i == bugIndex))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
position[i].x -= offset[i].x;
|
|
position[i].y -= offset[i].y;
|
|
|
|
localView.MoveToAbsolute(
|
|
position[i].x,
|
|
position[i].y
|
|
);
|
|
|
|
localView.DrawPixelMap8(
|
|
False,
|
|
0,
|
|
icon
|
|
);
|
|
}
|
|
//---------------------------------------------------
|
|
// Release pixel map from warehouse
|
|
//---------------------------------------------------
|
|
warehouse->pixelMap8Bin.Release(imageName[i]);
|
|
}
|
|
localView.DetachRecorder();
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// ThreatIndicator
|
|
//*****************************************************************************
|
|
MethodDescription
|
|
ThreatIndicator::methodDescription =
|
|
{
|
|
"threat",
|
|
ThreatIndicator::Make,
|
|
{
|
|
{ ParameterDescription::typeRate, NULL }, // rate ID
|
|
{ ParameterDescription::typeModeMask, NULL },// mode mask
|
|
{ ParameterDescription::typeInteger, NULL }, // inner radius
|
|
{ ParameterDescription::typeInteger, NULL }, // outer radius
|
|
{ ParameterDescription::typeColor, NULL }, // background
|
|
{ ParameterDescription::typeColor, NULL }, // teamcolor
|
|
{ ParameterDescription::typeColor, NULL }, // othercolor
|
|
{ ParameterDescription::typeScalar, NULL }, // view radius
|
|
PARAMETER_DESCRIPTION_END
|
|
}
|
|
};
|
|
|
|
Logical
|
|
ThreatIndicator::Make(
|
|
int display_port_index,
|
|
Vector2DOf<int> position,
|
|
Entity */*entity*/,
|
|
GaugeRenderer *gauge_renderer
|
|
)
|
|
{
|
|
Test_Tell("ThreatIndicator::Make\n");
|
|
Check(gauge_renderer);
|
|
|
|
ParameterDescription
|
|
*parameterList = methodDescription.parameterList;
|
|
|
|
# if DEBUG_LEVEL > 0
|
|
parameterList[0].CheckIt(ParameterDescription::typeRate); // group ID
|
|
parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask
|
|
parameterList[2].CheckIt(ParameterDescription::typeInteger);// inner radius
|
|
parameterList[3].CheckIt(ParameterDescription::typeInteger);// outer radius
|
|
parameterList[4].CheckIt(ParameterDescription::typeColor); // background
|
|
parameterList[5].CheckIt(ParameterDescription::typeColor); // team color
|
|
parameterList[6].CheckIt(ParameterDescription::typeColor); // other color
|
|
parameterList[7].CheckIt(ParameterDescription::typeScalar); // view radius
|
|
# endif
|
|
|
|
# if DEBUG_LEVEL > 0
|
|
ThreatIndicator
|
|
*threat_indicator =
|
|
# endif
|
|
new ThreatIndicator(
|
|
parameterList[0].data.rate,
|
|
parameterList[1].data.modeMask,
|
|
(L4GaugeRenderer *) gauge_renderer,
|
|
0, //unsigned int owner_ID
|
|
display_port_index, //int graphics_port_number
|
|
position.x, position.y,
|
|
parameterList[2].data.integer, //inner radius
|
|
parameterList[3].data.integer, //outer radius
|
|
parameterList[4].data.color, //bg color
|
|
parameterList[5].data.color, //team color
|
|
parameterList[6].data.color, //other color
|
|
parameterList[7].data.scalar //view radius
|
|
);
|
|
|
|
Register_Object(threat_indicator);
|
|
|
|
Test_Tell("ThreatIndicator::Make OK\n");
|
|
Check_Fpu();
|
|
return True;
|
|
}
|
|
|
|
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
// *DANGER* HEAVY-DUTY WARNING *DANGER*
|
|
//
|
|
// This object records graphics operations for
|
|
// later playback!
|
|
//
|
|
// Any graphic entities (such as bitmaps or gaugeImages)
|
|
// that are used here MUST be locked at the SAME address
|
|
// at playback time or the playback will crash HARD.
|
|
//
|
|
// *DANGER CONSIDER YOURSELF WARNED *DANGER*
|
|
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
|
|
ThreatIndicator::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
|
|
):
|
|
GraphicGauge(
|
|
rate,
|
|
mode_mask,
|
|
renderer,
|
|
owner_ID,
|
|
graphics_port_number,
|
|
identification_string
|
|
)
|
|
{
|
|
Check_Pointer(this);
|
|
|
|
// graphics_port may be NULL!
|
|
|
|
localView.SetOrigin(center_x, center_y);
|
|
|
|
viewRadius = sensing_radius;
|
|
topClosingVelocity = 75.0; // in KPH, arbitrary choice
|
|
|
|
innerRadius = inner_radius;
|
|
outerRadius = outer_radius;
|
|
|
|
backgroundColor = bg_color;
|
|
teamColor = team_color;
|
|
otherColor = other_color;
|
|
|
|
operatingPhase = 0;
|
|
Check_Fpu();
|
|
}
|
|
|
|
ThreatIndicator::~ThreatIndicator()
|
|
{
|
|
Check(this);
|
|
|
|
// base class deletes all connections in Gauge::~Gauge
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
ThreatIndicator::TestInstance() const
|
|
{
|
|
return GraphicGauge::TestInstance();
|
|
}
|
|
|
|
void
|
|
ThreatIndicator::ShowInstance(char *indent)
|
|
{
|
|
Check(this);
|
|
|
|
std::cout << indent << "ThreatIndicator:\n";
|
|
|
|
char
|
|
temp[80];
|
|
|
|
Str_Copy(temp,indent, 80);
|
|
Str_Cat(temp,"...", 80);
|
|
|
|
// std::cout << temp << "backgroundColor=" << backgroundColor << "\n";
|
|
// std::cout << temp << "foregroundColor=" << foregroundColor << "\n";
|
|
// std::cout << temp << "numberOfDigits =" << numberOfDigits << "\n";
|
|
GraphicGauge::ShowInstance(temp);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
ThreatIndicator::BecameActive()
|
|
{
|
|
Check(this);
|
|
// This empty method is required to override GaugeBase::BecameActive(),
|
|
// which immediately complains and deactivates the gauge.
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
ThreatIndicator::Execute()
|
|
{
|
|
Check(this);
|
|
|
|
switch(operatingPhase++)
|
|
{
|
|
case 0:
|
|
Select();
|
|
break;
|
|
|
|
case 1:
|
|
//-----------------------------------------------------------
|
|
// Erase old threat display
|
|
//-----------------------------------------------------------
|
|
previousDrawing.Draw(&localView, backgroundColor);
|
|
previousDrawing.Clear();
|
|
//-----------------------------------------------------------
|
|
// Draw new threat display
|
|
//-----------------------------------------------------------
|
|
localView.AttachRecorder(&previousDrawing);
|
|
Draw();
|
|
localView.DetachRecorder();
|
|
// deliberately falls through into default case
|
|
|
|
default:
|
|
operatingPhase = 0;
|
|
break;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
ThreatIndicator::Select()
|
|
{
|
|
Test_Tell("ThreatIndicator::Select\n");
|
|
Check(this);
|
|
|
|
Point3D
|
|
viewing_position;
|
|
|
|
Entity
|
|
*viewing_entity = renderer->GetLinkedEntity();
|
|
Check(viewing_entity);
|
|
|
|
viewing_position = viewing_entity->localOrigin.linearPosition;
|
|
|
|
movingEntityList.Clear();
|
|
renderer->GetMovingEntitiesWithinBounds(
|
|
&movingEntityList,
|
|
viewing_position.x-viewRadius, -32768.0, viewing_position.z-viewRadius,
|
|
viewing_position.x+viewRadius, 32768.0, viewing_position.z+viewRadius
|
|
);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
ThreatIndicator::Draw()
|
|
{
|
|
Test_Tell("ThreatIndicator::Draw\n");
|
|
Check(this);
|
|
|
|
Entity
|
|
*entity,
|
|
*viewing_entity = renderer->GetLinkedEntity();
|
|
Check(viewing_entity);
|
|
|
|
YawPitchRoll
|
|
currentHeading;
|
|
|
|
ChainIteratorOf<Entity*>
|
|
i(movingEntityList.GetInstanceList());
|
|
|
|
Vector3D
|
|
my_velocity = ((Mover *)viewing_entity)->worldLinearVelocity,
|
|
my_position = viewing_entity->localOrigin.linearPosition,
|
|
relative_position,
|
|
relative_velocity,
|
|
unit_position;
|
|
|
|
Scalar
|
|
// HACK - calculate delta_radius at initialization instead!
|
|
delta_radius = innerRadius - outerRadius,
|
|
speed_factor,
|
|
distance,
|
|
distance_factor,
|
|
dot_product,
|
|
threat_yaw,
|
|
threat_assessment;
|
|
|
|
int
|
|
color;
|
|
|
|
//-------------------------------------------------------
|
|
// Get player (for team ID if martian football)
|
|
//-------------------------------------------------------
|
|
RPPlayer
|
|
*player = (RPPlayer *) viewing_entity->GetPlayerLink();
|
|
Check(player);
|
|
# if DEBUG_LEVEL == 0
|
|
if (player == NULL)
|
|
{
|
|
DEBUG_STREAM << "ThreatIndicator has been SABOTAGED!\n" << std::flush;
|
|
DEBUG_STREAM << "player = NULL!\n" << std::flush;
|
|
return;
|
|
}
|
|
# endif
|
|
//-------------------------------------------------------
|
|
// Get current heading
|
|
//-------------------------------------------------------
|
|
currentHeading = viewing_entity->localOrigin.angularPosition;
|
|
|
|
//-------------------------------------------------------
|
|
// Attempt to display all entities
|
|
//-------------------------------------------------------
|
|
while ((entity=i.ReadAndNext()) != NULL)
|
|
{
|
|
Check(entity);
|
|
# if DEBUG_LEVEL == 0
|
|
if (entity == NULL)
|
|
{
|
|
DEBUG_STREAM << "ThreatIndicator has been SABOTAGED!\n" << std::flush;
|
|
DEBUG_STREAM << "entity = NULL!\n" << std::flush;
|
|
break;
|
|
}
|
|
# endif
|
|
|
|
//-------------------------------------------------------
|
|
// Make sure it's a VTV
|
|
//-------------------------------------------------------
|
|
if (! entity->IsDerivedFrom(*VTV::GetClassDerivations()))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//-------------------------------------------------------
|
|
// Show all VTV's except us
|
|
//-------------------------------------------------------
|
|
if (entity != viewing_entity)
|
|
{
|
|
//-----------------------------------------------------------
|
|
// Generate relative position
|
|
//-----------------------------------------------------------
|
|
relative_position.Subtract(
|
|
entity->localOrigin.linearPosition,
|
|
viewing_entity->localOrigin.linearPosition
|
|
);
|
|
//-----------------------------------------------------------
|
|
// Generate distance, discard if too distant
|
|
//-----------------------------------------------------------
|
|
distance = relative_position.Length();
|
|
if (distance < viewRadius)
|
|
{
|
|
//-----------------------------------------------------------
|
|
// Generate threat assessment
|
|
//-----------------------------------------------------------
|
|
threat_assessment = 0.0;
|
|
//-----------------------------------------
|
|
// Assessment source #1: too close
|
|
// (anything too close is dangerous)
|
|
//-----------------------------------------
|
|
# define CLOSE_THREAT_RADIUS 200.0
|
|
|
|
if (distance <= CLOSE_THREAT_RADIUS)
|
|
{
|
|
threat_assessment +=
|
|
(CLOSE_THREAT_RADIUS-distance)/CLOSE_THREAT_RADIUS;
|
|
}
|
|
//-----------------------------------------
|
|
// Assessment source #1: closing with us
|
|
// (anything closing with us is dangerous)
|
|
//-----------------------------------------
|
|
//--------------------------------
|
|
// Normalize the position, but
|
|
// make sure that we handle a
|
|
// zero-length vector correctly.
|
|
//--------------------------------
|
|
if (Small_Enough(distance))
|
|
{
|
|
unit_position.x = 0.0;
|
|
unit_position.y = 0.0;
|
|
unit_position.z = -1.0;
|
|
}
|
|
else
|
|
{
|
|
unit_position = relative_position;
|
|
unit_position /= distance;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//--------------------------------
|
|
// Generate relative velocity
|
|
// (TOWARDS the threat)
|
|
//--------------------------------
|
|
relative_velocity.Subtract(
|
|
((Mover *) entity)->worldLinearVelocity,
|
|
my_velocity
|
|
);
|
|
|
|
dot_product = -(unit_position * relative_velocity);
|
|
if (dot_product > 0.0)
|
|
{
|
|
//----------------------------------
|
|
// Faster is greather threat
|
|
// Closer is greater threat
|
|
//
|
|
// Note that the speed_factor
|
|
// is allowed to go above 1.0.
|
|
// This allows distant, very
|
|
// fast objects to be shown
|
|
// as serious threats.
|
|
// topClosingVelocity set in creator
|
|
//----------------------------------
|
|
# if DEBUG_LEVEL == 0
|
|
if (Small_Enough(topClosingVelocity))
|
|
{
|
|
DEBUG_STREAM << "ThreatIndicator has been SABOTAGED!\n" << std::flush;
|
|
DEBUG_STREAM << "topClosingVelocity = " << topClosingVelocity << "\n" << std::flush;
|
|
}
|
|
# endif
|
|
Verify(!Small_Enough(topClosingVelocity));
|
|
speed_factor = dot_product/topClosingVelocity;
|
|
Check_Fpu();
|
|
|
|
# if DEBUG_LEVEL == 0
|
|
if (Small_Enough(viewRadius))
|
|
{
|
|
DEBUG_STREAM << "ThreatIndicator has been SABOTAGED!\n" << std::flush;
|
|
DEBUG_STREAM << "viewRadius = " << viewRadius << "\n" << std::flush;
|
|
}
|
|
# endif
|
|
Verify(!Small_Enough(viewRadius));
|
|
distance_factor = 1.0 - (distance/viewRadius);
|
|
Check_Fpu();
|
|
|
|
threat_assessment +=
|
|
distance_factor * speed_factor;
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// Display only if assessment > 0
|
|
//-----------------------------------------------------------
|
|
if (threat_assessment > 0.0)
|
|
{
|
|
//-----------------------------------------------------------
|
|
// Draw the threat indicator
|
|
//-----------------------------------------------------------
|
|
threat_yaw = generateRelativeYaw(
|
|
currentHeading.yaw.angle,
|
|
relative_position
|
|
);
|
|
|
|
SinCosPair
|
|
sc_pair;
|
|
sc_pair = -threat_yaw;
|
|
// HACK - I don't know why the (-) is needed, but it is.
|
|
// cpb 8-21-95
|
|
Check_Fpu();
|
|
|
|
if (threat_assessment > 1.0)
|
|
{
|
|
threat_assessment = 1.0;
|
|
}
|
|
Scalar
|
|
show_radius = outerRadius+(delta_radius*threat_assessment),
|
|
|
|
orthogonal_x = sc_pair.cosine * 3.0,
|
|
orthogonal_y = -sc_pair.sine * 3.0,
|
|
|
|
threat_outer_x = sc_pair.sine * -outerRadius,
|
|
threat_outer_y = sc_pair.cosine * -outerRadius,
|
|
|
|
threat_inner_x = sc_pair.sine * -show_radius,
|
|
threat_inner_y = sc_pair.cosine * -show_radius;
|
|
Check_Fpu();
|
|
|
|
if (player->playerType == RPPlayer::GeneralPlayerType)
|
|
{
|
|
color = otherColor; // no friends in death race!
|
|
}
|
|
else
|
|
{
|
|
RPPlayer
|
|
*other_player = (RPPlayer *) entity->GetPlayerLink();
|
|
|
|
Check(other_player);
|
|
# if DEBUG_LEVEL == 0
|
|
if (other_player == NULL)
|
|
{
|
|
DEBUG_STREAM << "ThreatIndicator has been SABOTAGED!\n" << std::flush;
|
|
DEBUG_STREAM << "other_player = NULL!\n" << std::flush;
|
|
break;
|
|
}
|
|
# endif
|
|
|
|
if (other_player->teamID == player->teamID)
|
|
{
|
|
color = teamColor;
|
|
}
|
|
else
|
|
{
|
|
color = otherColor;
|
|
}
|
|
}
|
|
localView.SetColor(color);
|
|
|
|
localView.MoveToAbsolute(
|
|
(int) (threat_outer_x + orthogonal_x + .5),
|
|
(int) (threat_outer_y + orthogonal_y + .5)
|
|
);
|
|
localView.DrawLineToAbsolute(
|
|
(int) (threat_inner_x + .5),
|
|
(int) (threat_inner_y + .5)
|
|
);
|
|
localView.DrawLineToAbsolute(
|
|
(int) (threat_outer_x - orthogonal_x + .5),
|
|
(int) (threat_outer_y - orthogonal_y + .5)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// NavName
|
|
//*****************************************************************************
|
|
//----------------------------------------------------------
|
|
// A vector between each pair of objects is created,
|
|
// normalized, and then weighted according to the INVERSE
|
|
// of the vector length. This will cause closer pairs
|
|
// of objects to generate larger "repelling" vectors, and
|
|
// farther pairs of objects to generate smaller " repelling"
|
|
// vectors.
|
|
//
|
|
// These 'repelling" vectors are then summed for each object.
|
|
// The summed vectors then tend to point AWAY from
|
|
// 'nearer' objects. These summed vectors are
|
|
// again normalized and multiplied by a fixed distance to
|
|
// generate the center position for a name bitmap.
|
|
//----------------------------------------------------------
|
|
|
|
void
|
|
NavName::ExtractFromEntity(Entity *entity, AffineMatrix &worldToView)
|
|
{
|
|
Check(this);
|
|
Check(entity);
|
|
|
|
Player
|
|
*player;
|
|
//-------------------------------------
|
|
// Get pointer to bitmap
|
|
//-------------------------------------
|
|
player = entity->playerLink;
|
|
Check(application);
|
|
Mission *current_mission = application->GetCurrentMission();
|
|
Check(current_mission);
|
|
|
|
if (player == NULL)
|
|
{
|
|
nameBitmap = NULL;
|
|
}
|
|
else
|
|
{
|
|
nameBitmap =
|
|
current_mission->GetSmallNameBitmap(player->playerBitmapIndex);
|
|
Check(nameBitmap);
|
|
}
|
|
//-------------------------------------
|
|
// Generate screen position
|
|
//-------------------------------------
|
|
center.Multiply(
|
|
entity->localOrigin.linearPosition,
|
|
worldToView
|
|
);
|
|
//-------------------------------------
|
|
// Get color
|
|
//-------------------------------------
|
|
color = determineEntityColor(entity);
|
|
//-------------------------------------
|
|
// Clear direction vector
|
|
//-------------------------------------
|
|
direction.x = 0.0;
|
|
direction.y = 0.0;
|
|
direction.z = 0.0;
|
|
}
|
|
|
|
void
|
|
NavName::CalculatePositions(NavName *array, int count)
|
|
{
|
|
Check_Pointer(array);
|
|
|
|
int
|
|
i;
|
|
NavName
|
|
*this_nav_name;
|
|
Vector3D
|
|
delta;
|
|
#if 0 // QUICK PATCH TO REMOVE "FLOATING" NAMES
|
|
int
|
|
i;
|
|
NavName
|
|
*that_nav_name;
|
|
Scalar
|
|
distance;
|
|
#endif
|
|
//----------------------------------------------------------
|
|
// Build NavName weighted direction vectors
|
|
//----------------------------------------------------------
|
|
for(
|
|
i=0, this_nav_name=array;
|
|
i<count;
|
|
++i,++this_nav_name
|
|
)
|
|
{
|
|
Check(this_nav_name);
|
|
#if 0 // QUICK PATCH TO REMOVE "FLOATING" NAMES
|
|
for(
|
|
j=i+1, that_nav_name=&array[j];
|
|
j<count;
|
|
++j,++that_nav_name
|
|
)
|
|
{
|
|
//-------------------------------------
|
|
// Get delta, length
|
|
//-------------------------------------
|
|
delta.Subtract(this_nav_name->center, that_nav_name->center);
|
|
|
|
distance = delta.Length();
|
|
//-------------------------------------
|
|
// Normalize the delta, and
|
|
// multiply by inverse distance
|
|
// (i.e., divide by distance squared)
|
|
//-------------------------------------
|
|
distance *= distance;
|
|
|
|
if (!Small_Enough(distance))
|
|
{
|
|
delta /= distance;
|
|
}
|
|
//-------------------------------------
|
|
// Sum the vectors for each navName
|
|
//-------------------------------------
|
|
this_nav_name->direction += delta;
|
|
that_nav_name->direction -= delta;
|
|
}
|
|
#else
|
|
this_nav_name->direction.x = -1.0;
|
|
this_nav_name->direction.y = 0.0;
|
|
this_nav_name->direction.z = 0.0;
|
|
#endif
|
|
}
|
|
#if 0 // QUICK PATCH TO REMOVE "FLOATING" NAMES
|
|
//----------------------------------------------------------
|
|
// Normalize the directions
|
|
//----------------------------------------------------------
|
|
for(
|
|
i=0, this_nav_name=array;
|
|
i<count;
|
|
++i,++this_nav_name
|
|
)
|
|
{
|
|
Check(this_nav_name);
|
|
//--------------------------------------
|
|
// Normalize the vectors in the xz plane
|
|
//--------------------------------------
|
|
this_nav_name->direction.y = 0.0; // force to xz plane
|
|
distance = this_nav_name->direction.Length();
|
|
|
|
if (Small_Enough(distance))
|
|
{
|
|
this_nav_name->direction.x = -1.0;
|
|
this_nav_name->direction.z = 0.0;
|
|
}
|
|
else
|
|
{
|
|
this_nav_name->direction /= distance;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void
|
|
NavName::Draw(GraphicsView *graphics_view, Scalar radius_multiplier)
|
|
{
|
|
Check(this);
|
|
Check(graphics_view);
|
|
|
|
if (nameBitmap != NULL)
|
|
{
|
|
//----------------------------------------
|
|
// Set 'radius'
|
|
//----------------------------------------
|
|
direction *= (nameBitmap->Data.Size.x >> 1) * radius_multiplier;
|
|
//----------------------------------------
|
|
// Change from screen to world coordinates
|
|
//----------------------------------------
|
|
direction.y = -direction.z;
|
|
center.y = -center.z;
|
|
//----------------------------------------
|
|
// Center the bitmap
|
|
//----------------------------------------
|
|
direction.x -= nameBitmap->Data.Size.x >> 1;
|
|
direction.y -= nameBitmap->Data.Size.y >> 1;
|
|
//----------------------------------------
|
|
// Finally, draw it!
|
|
//----------------------------------------
|
|
graphics_view->MoveToAbsolute(
|
|
(int) (center.x + direction.x + .5),
|
|
(int) (center.y + direction.y + .5)
|
|
);
|
|
|
|
graphics_view->SetColor(color);
|
|
graphics_view->DrawBitMap(0, nameBitmap);
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// NavDisplay
|
|
//*****************************************************************************
|
|
MethodDescription
|
|
NavDisplay::methodDescription =
|
|
{
|
|
"nav",
|
|
NavDisplay::Make,
|
|
{
|
|
{ ParameterDescription::typeRate, NULL }, // rate ID
|
|
{ ParameterDescription::typeModeMask, NULL }, // mode mask
|
|
{ ParameterDescription::typeVector, NULL }, // size
|
|
{ ParameterDescription::typeColor, NULL }, // background
|
|
{ ParameterDescription::typeColor, NULL }, // static
|
|
{ ParameterDescription::typeAttribute, NULL }, // scale
|
|
{ ParameterDescription::typeAttribute, NULL }, // lin pos
|
|
{ ParameterDescription::typeAttribute, NULL }, // ang pos
|
|
PARAMETER_DESCRIPTION_END
|
|
}
|
|
};
|
|
|
|
Logical
|
|
NavDisplay::Make(
|
|
int display_port_index,
|
|
Vector2DOf<int> position,
|
|
Entity */*entity*/,
|
|
GaugeRenderer *gauge_renderer
|
|
)
|
|
{
|
|
Test_Tell("NavDisplay::Make\n");
|
|
Check(gauge_renderer);
|
|
|
|
ParameterDescription
|
|
*parameterList = methodDescription.parameterList;
|
|
|
|
# if DEBUG_LEVEL > 0
|
|
parameterList[0].CheckIt(ParameterDescription::typeRate); // group ID
|
|
parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask
|
|
parameterList[2].CheckIt(ParameterDescription::typeVector); // size
|
|
parameterList[3].CheckIt(ParameterDescription::typeColor); // bg
|
|
parameterList[4].CheckIt(ParameterDescription::typeColor); // bg
|
|
parameterList[5].CheckIt(ParameterDescription::typeAttribute); // scale
|
|
parameterList[6].CheckIt(ParameterDescription::typeAttribute); // lin pos
|
|
parameterList[7].CheckIt(ParameterDescription::typeAttribute); // ang pos
|
|
# endif
|
|
|
|
# if DEBUG_LEVEL > 0
|
|
NavDisplay
|
|
*nav_display =
|
|
# endif
|
|
new NavDisplay(
|
|
parameterList[0].data.rate,
|
|
parameterList[1].data.modeMask,
|
|
(L4GaugeRenderer *) gauge_renderer,
|
|
0, // owner_ID
|
|
display_port_index, // graphics_port_number
|
|
position.x,
|
|
position.y,
|
|
position.x + parameterList[2].data.vector.x,
|
|
position.y + parameterList[2].data.vector.y,
|
|
parameterList[3].data.color, // bg
|
|
parameterList[4].data.color, // static objects
|
|
(Scalar *) parameterList[5].data.attributePointer,
|
|
(Point3D **) parameterList[6].data.attributePointer,
|
|
(Quaternion **) parameterList[7].data.attributePointer,
|
|
False
|
|
|
|
// HACK!!!! The casts above are VERY dangerous!
|
|
);
|
|
|
|
Register_Object(nav_display);
|
|
|
|
Test_Tell("NavDisplay::Make OK\n");
|
|
Check_Fpu();
|
|
return True;
|
|
}
|
|
|
|
NavDisplay::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,
|
|
const char *identification_string
|
|
):
|
|
GraphicGauge(
|
|
rate,
|
|
mode_mask,
|
|
renderer,
|
|
owner_ID,
|
|
graphics_port_number,
|
|
identification_string
|
|
)
|
|
{
|
|
Test_Tell("NavDisplay::NavDisplay\n");
|
|
Check_Pointer(this);
|
|
|
|
// graphics_port may be NULL!
|
|
|
|
//
|
|
//-----------------------------------------------------------
|
|
// Set position of graphicsView within the graphicsPort
|
|
// (which also specifies the clipping and origin)
|
|
//-----------------------------------------------------------
|
|
//
|
|
Verify(right > left);
|
|
Verify(top > bottom);
|
|
localView.SetPositionWithinPort(left, bottom, right, top);
|
|
localView.SetOrigin((right-left)>>1, (top-bottom)>>1);
|
|
//
|
|
//-----------------------------------------------------------
|
|
// Initialize internal values
|
|
//-----------------------------------------------------------
|
|
//
|
|
backgroundColor = bg_color;
|
|
staticColor = static_color;
|
|
|
|
rockAndRoll = allow_rock_and_roll;
|
|
|
|
halfWidth = (right-left)>>1;
|
|
halfHeight = (top-bottom)>>1;
|
|
|
|
//
|
|
//-----------------------------------------------------------
|
|
// Build connections to values
|
|
//-----------------------------------------------------------
|
|
//
|
|
GaugeConnection
|
|
*connection;
|
|
|
|
connection = new
|
|
GaugeConnectionDirectOf<Scalar>(0, ¤tScale, scale_value_pointer);
|
|
Register_Object(connection);
|
|
AddConnection(connection);
|
|
|
|
connection = new
|
|
GaugeConnectionDirectOf<Point3D *>(
|
|
0, ¤tPositionPointer, position_pointer);
|
|
Register_Object(connection);
|
|
AddConnection(connection);
|
|
|
|
connection = new
|
|
GaugeConnectionDirectOf<Quaternion *>(
|
|
0, ¤tAngularPointer, angle_pointer);
|
|
Register_Object(connection);
|
|
AddConnection(connection);
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
NavDisplay::~NavDisplay()
|
|
{
|
|
Test_Tell("NavDisplay::~NavDisplay\n");
|
|
Check(this);
|
|
|
|
// base class deletes all connections in Gauge::~Gauge
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
NavDisplay::TestInstance() const
|
|
{
|
|
return GraphicGauge::TestInstance();
|
|
}
|
|
|
|
void
|
|
NavDisplay::ShowInstance(char *indent)
|
|
{
|
|
Check(this);
|
|
|
|
std::cout << indent << "ThreatIndicator:\n";
|
|
|
|
char
|
|
temp[80];
|
|
|
|
Str_Copy(temp,indent, 80);
|
|
Str_Cat(temp,"...", 80);
|
|
|
|
// std::cout << temp << "backgroundColor=" << backgroundColor << "\n";
|
|
// std::cout << temp << "foregroundColor=" << foregroundColor << "\n";
|
|
// std::cout << temp << "numberOfDigits =" << numberOfDigits << "\n";
|
|
GraphicGauge::ShowInstance(temp);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
NavDisplay::BecameActive()
|
|
{
|
|
Check(this);
|
|
|
|
operatingPhase = 0;
|
|
}
|
|
|
|
void
|
|
NavDisplay::Execute()
|
|
{
|
|
Test_Tell("NavDisplay::Execute\n");
|
|
Check(this);
|
|
Check(renderer);
|
|
|
|
Vector3D
|
|
scaling_vector;
|
|
Entity
|
|
*linked_entity;
|
|
LinearMatrix
|
|
temp;
|
|
|
|
switch(operatingPhase++)
|
|
{
|
|
case 0:
|
|
CalculateBounds();
|
|
break;
|
|
|
|
case 1:
|
|
SelectStatic();
|
|
break;
|
|
|
|
case 2:
|
|
SelectMoving();
|
|
break;
|
|
|
|
case 3:
|
|
temp.BuildIdentity();
|
|
//-----------------------------------------------------------
|
|
// Update worldToView transformation
|
|
//-----------------------------------------------------------
|
|
linked_entity = renderer->GetLinkedEntity();
|
|
//------------------------------------
|
|
// If pointer to position is null,
|
|
// use position of linked entity
|
|
//------------------------------------
|
|
if (currentPositionPointer == NULL)
|
|
{
|
|
if (linked_entity != NULL)
|
|
{
|
|
currentPositionPointer =
|
|
&linked_entity->localOrigin.linearPosition;
|
|
}
|
|
}
|
|
//------------------------------------
|
|
// Get inverse transform from viewer
|
|
//------------------------------------
|
|
if (currentPositionPointer != NULL)
|
|
{
|
|
{
|
|
Point3D
|
|
point;
|
|
point = *currentPositionPointer;
|
|
temp = point;
|
|
}
|
|
if (currentAngularPointer != NULL)
|
|
{
|
|
if (rockAndRoll)
|
|
{
|
|
Quaternion
|
|
quaternion;
|
|
quaternion = *currentAngularPointer;
|
|
|
|
temp = quaternion;
|
|
}
|
|
else
|
|
{
|
|
YawPitchRoll
|
|
currentHeading;
|
|
currentHeading = *currentAngularPointer;
|
|
|
|
SinCosPair
|
|
sin_cos_pair;
|
|
sin_cos_pair = currentHeading.yaw.angle/2.0;
|
|
|
|
Quaternion
|
|
quaternion(0.0, sin_cos_pair.sine, 0.0, sin_cos_pair.cosine);
|
|
|
|
temp = quaternion;
|
|
}
|
|
}
|
|
}
|
|
worldToView.Invert(temp);
|
|
//------------------------------------
|
|
// Scale the display
|
|
//------------------------------------
|
|
Verify(pixelsPerMeter > 0.0);
|
|
scaling_vector.x = pixelsPerMeter;
|
|
scaling_vector.y = pixelsPerMeter;
|
|
scaling_vector.z = pixelsPerMeter;
|
|
|
|
worldToView *= scaling_vector;
|
|
//
|
|
//-----------------------------------------------------------
|
|
// Update display
|
|
//-----------------------------------------------------------
|
|
//
|
|
previousDrawing.Draw(&localView, backgroundColor);
|
|
previousDrawing.Clear();
|
|
localView.AttachRecorder(&previousDrawing);
|
|
DrawStatic(worldToView);
|
|
DrawMoving(worldToView);
|
|
DrawNames(worldToView);
|
|
localView.DetachRecorder();
|
|
|
|
// deliberately falls through into default case
|
|
|
|
default:
|
|
operatingPhase = 0;
|
|
break;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
NavDisplay::CalculateBounds()
|
|
{
|
|
Test_Tell("NavDisplay::CalculateBounds\n");
|
|
Check(this);
|
|
|
|
Test_Tell("currentScale = " << currentScale << "\n");
|
|
|
|
if (currentScale <= 0.0)
|
|
{
|
|
Fail("NavDisplay::CalculateBounds detected currentScale <= 0.0");
|
|
currentScale = 1.0;
|
|
}
|
|
|
|
pixelsPerMeter = (halfWidth<<1)/currentScale;
|
|
|
|
Test_Tell("pixelsPerMeter = " << pixelsPerMeter << "\n");
|
|
Verify(pixelsPerMeter > 0.0);
|
|
|
|
metersPerPixel = 1.0 / pixelsPerMeter;
|
|
|
|
//------------------------------------------------------------
|
|
// Derivation of LODIndex:
|
|
//
|
|
// The LOD level for the gaugeImage is a very arbitrary value
|
|
// where 1.0 is the "normal" level of detail, with smaller
|
|
// numbers yielding "more" detail and larger numbers yielding
|
|
// "less" detail. If the LODIndex becomes greater than the
|
|
// largest value in the gaugeImage, the gaugeImage is not drawn.
|
|
//
|
|
// This code assumes that a "normal" level is N pixels per meter.
|
|
// Therefore,
|
|
// N pixel | meters
|
|
// LODIndex = ------------+----------
|
|
// meter | pixel
|
|
//------------------------------------------------------------
|
|
LODIndex = /*1.0* */ metersPerPixel; // N = 1.0 pixels/meter
|
|
|
|
Scalar
|
|
halfViewWidth(halfWidth/pixelsPerMeter),
|
|
halfViewHeight(halfHeight/pixelsPerMeter);
|
|
Test_Tell("halfViewWidth = " << halfViewWidth << "\n");
|
|
Test_Tell("halfViewHeight = " << halfViewHeight << "\n");
|
|
|
|
Point3D
|
|
viewing_position;
|
|
|
|
Entity
|
|
*viewing_entity = renderer->GetLinkedEntity();
|
|
Check(viewing_entity);
|
|
|
|
viewing_position = viewing_entity->localOrigin.linearPosition;
|
|
|
|
xMin = viewing_position.x - halfViewWidth;
|
|
xMax = viewing_position.x + halfViewWidth;
|
|
|
|
yMin = -32768.0;
|
|
yMax = 32768.0;
|
|
|
|
zMin = viewing_position.z - halfViewHeight;
|
|
zMax = viewing_position.z + halfViewHeight;
|
|
|
|
Test_Tell("x= " << xMin << "..." << xMax << "\n");
|
|
Test_Tell("y= " << yMin << "..." << yMax << "\n");
|
|
Test_Tell("z= " << zMin << "..." << zMax << "\n");
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
NavDisplay::SelectStatic()
|
|
{
|
|
Test_Tell("NavDisplay::SelectStatic\n");
|
|
Check(this);
|
|
|
|
staticEntityList.Clear();
|
|
renderer->GetStaticEntitiesWithinBounds(
|
|
&staticEntityList,
|
|
xMin, yMin, zMin,
|
|
xMax, yMax, zMax
|
|
);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
NavDisplay::SelectMoving()
|
|
{
|
|
Test_Tell("NavDisplay::SelectMoving\n");
|
|
Check(this);
|
|
|
|
movingEntityList.Clear();
|
|
renderer->GetMovingEntitiesWithinBounds(
|
|
&movingEntityList,
|
|
xMin, yMin, zMin,
|
|
xMax, yMax, zMax
|
|
);
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
NavDisplay::DrawStatic(AffineMatrix &worldToView)
|
|
{
|
|
Test_Tell("NavDisplay::DrawStatic\n");
|
|
Check(this);
|
|
|
|
Entity
|
|
*entity;
|
|
Point3D
|
|
zero,
|
|
pos;
|
|
AffineMatrix
|
|
localToView;
|
|
ChainIteratorOf<Entity*>
|
|
i(staticEntityList.GetInstanceList());
|
|
|
|
zero.x = 0.0;
|
|
zero.y = 0.0;
|
|
zero.z = 0.0;
|
|
|
|
Check(renderer);
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) renderer->warehousePointer;
|
|
Check(warehouse);
|
|
|
|
L4GaugeImage
|
|
*gauge_image;
|
|
|
|
while ((entity=i.ReadAndNext()) != NULL)
|
|
{
|
|
Check(entity);
|
|
|
|
//
|
|
//-----------------------------------------------------------
|
|
// Draw new image
|
|
//-----------------------------------------------------------
|
|
//
|
|
gauge_image = warehouse->
|
|
gaugeImageBin.GetIfAlreadyExists(entity->GetResourceID());
|
|
if (gauge_image != NULL)
|
|
{
|
|
Check(gauge_image);
|
|
|
|
localToView.Multiply(entity->localToWorld, worldToView);
|
|
|
|
gauge_image->Draw(
|
|
LODIndex,
|
|
metersPerPixel,
|
|
&localView,
|
|
staticColor,
|
|
(AffineMatrix &) localToView
|
|
);
|
|
|
|
warehouse->gaugeImageBin.Release(entity->GetResourceID());
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
NavDisplay::DrawMoving(AffineMatrix &worldToView)
|
|
{
|
|
Test_Tell("NavDisplay::DrawMoving\n");
|
|
Check(this);
|
|
|
|
Entity
|
|
*entity;
|
|
ChainIteratorOf<Entity*>
|
|
i(movingEntityList.GetInstanceList());
|
|
L4GaugeImage
|
|
*gauge_image;
|
|
AffineMatrix
|
|
localToView;
|
|
//----------------------------------------------------------
|
|
// Get warehouse
|
|
//----------------------------------------------------------
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) renderer->warehousePointer;
|
|
Check(warehouse);
|
|
|
|
//----------------------------------------------------------
|
|
// Draw moving entities
|
|
//----------------------------------------------------------
|
|
while ((entity=i.ReadAndNext()) != NULL)
|
|
{
|
|
Check(entity);
|
|
|
|
// if (entity != renderer->GetLinkedEntity())
|
|
{
|
|
//
|
|
//-----------------------------------------------------------
|
|
// Draw new image
|
|
//-----------------------------------------------------------
|
|
//
|
|
gauge_image = warehouse->
|
|
gaugeImageBin.GetIfAlreadyExists(entity->GetResourceID());
|
|
|
|
if (gauge_image != NULL)
|
|
{
|
|
Check(gauge_image);
|
|
|
|
localToView.Multiply(entity->localToWorld, worldToView);
|
|
|
|
gauge_image->Draw(
|
|
LODIndex,
|
|
metersPerPixel,
|
|
&localView,
|
|
determineEntityColor(entity),
|
|
localToView,
|
|
0 // bounding box color number: 0=no box
|
|
);
|
|
|
|
warehouse->gaugeImageBin.Release(entity->GetResourceID());
|
|
}
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
NavDisplay::DrawNames(AffineMatrix &worldToView)
|
|
{
|
|
Test_Tell("NavDisplay::DrawNames\n");
|
|
Check(this);
|
|
|
|
ChainIteratorOf<Entity*>
|
|
iterator(movingEntityList.GetInstanceList());
|
|
NavName
|
|
*nav_name;
|
|
int
|
|
i;
|
|
Entity
|
|
*entity;
|
|
|
|
int
|
|
count = iterator.GetSize();
|
|
|
|
if (count < 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (count > maximumNames)
|
|
{
|
|
count = maximumNames;
|
|
}
|
|
//----------------------------------------------------------
|
|
// Build NavName entries
|
|
//----------------------------------------------------------
|
|
for(
|
|
i=0, nav_name=nameArray;
|
|
i<count;
|
|
++i,++nav_name
|
|
)
|
|
{
|
|
//-------------------------------------
|
|
// Get entity
|
|
//-------------------------------------
|
|
entity=iterator.ReadAndNext();
|
|
if (entity == NULL)
|
|
{
|
|
Fail("NavDisplay::DrawNames - GetSize() lied!");
|
|
}
|
|
nav_name->ExtractFromEntity(entity, worldToView);
|
|
}
|
|
|
|
//----------------------------------------------------------
|
|
// Generate display positions
|
|
//----------------------------------------------------------
|
|
NavName::CalculatePositions(nameArray, count);
|
|
|
|
//----------------------------------------------------------
|
|
// Draw names
|
|
//----------------------------------------------------------
|
|
for(
|
|
i=0, nav_name=nameArray;
|
|
i<count;
|
|
++i,++nav_name
|
|
)
|
|
{
|
|
nav_name->Draw(&localView, 1.0);
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// GPS
|
|
//*****************************************************************************
|
|
MethodDescription
|
|
GPS::methodDescription =
|
|
{
|
|
"gps",
|
|
GPS::Make,
|
|
{
|
|
{ ParameterDescription::typeRate, NULL }, // rate ID
|
|
{ ParameterDescription::typeModeMask, NULL }, // mode mask
|
|
{ ParameterDescription::typeVector, NULL }, // size
|
|
{ ParameterDescription::typeScalar, NULL }, // LOD index
|
|
PARAMETER_DESCRIPTION_END
|
|
}
|
|
};
|
|
|
|
Logical
|
|
GPS::Make(
|
|
int display_port_index,
|
|
Vector2DOf<int> position,
|
|
Entity */*entity*/,
|
|
GaugeRenderer *gauge_renderer
|
|
)
|
|
{
|
|
Test_Tell("GPS::Make\n");
|
|
Check(gauge_renderer);
|
|
|
|
ParameterDescription
|
|
*parameterList = methodDescription.parameterList;
|
|
|
|
# if DEBUG_LEVEL > 0
|
|
parameterList[0].CheckIt(ParameterDescription::typeRate); // group ID
|
|
parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask
|
|
parameterList[2].CheckIt(ParameterDescription::typeVector); // size
|
|
parameterList[3].CheckIt(ParameterDescription::typeScalar); // LOD index
|
|
# endif
|
|
|
|
# if DEBUG_LEVEL > 0
|
|
GPS
|
|
*gps =
|
|
# endif
|
|
new GPS(
|
|
parameterList[0].data.rate,
|
|
parameterList[1].data.modeMask,
|
|
(L4GaugeRenderer *) gauge_renderer,
|
|
0, //unsigned int owner_ID
|
|
display_port_index, //int graphics_port_number
|
|
position.x,
|
|
position.y,
|
|
position.x + parameterList[2].data.vector.x,
|
|
position.y + parameterList[2].data.vector.y,
|
|
parameterList[3].data.scalar
|
|
);
|
|
|
|
Register_Object(gps);
|
|
|
|
Test_Tell("GPS::Make OK\n");
|
|
Check_Fpu();
|
|
return True;
|
|
}
|
|
|
|
GPS::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
|
|
) :
|
|
GraphicGauge(
|
|
rate,
|
|
mode_mask,
|
|
renderer,
|
|
owner_ID,
|
|
graphics_port_number,
|
|
identification_string
|
|
)
|
|
{
|
|
Test_Tell("GPS::GPS()\n");
|
|
Check_Pointer(this);
|
|
|
|
// graphics_port may be NULL!
|
|
|
|
width = right-left,
|
|
height = top-bottom;
|
|
Verify(width > 0);
|
|
Verify(height > 0);
|
|
|
|
LODIndex = LOD_index;
|
|
//-----------------------------------------------------------
|
|
// Set position of graphicsView within the graphicsPort
|
|
// (which also specifies the clipping and origin)
|
|
//-----------------------------------------------------------
|
|
localView.SetPositionWithinPort(left, bottom, right, top);
|
|
//-----------------------------------------------------------
|
|
// Create background pixelmap
|
|
//-----------------------------------------------------------
|
|
background = new Video8BitBuffered(width, height);
|
|
Register_Object(background);
|
|
needsStaticUpdate = True;
|
|
Check_Fpu();
|
|
}
|
|
|
|
GPS::~GPS()
|
|
{
|
|
Check(this);
|
|
|
|
Unregister_Object(background);
|
|
delete background;
|
|
background = NULL;
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
GPS::TestInstance() const
|
|
{
|
|
return GraphicGauge::TestInstance();
|
|
}
|
|
|
|
void
|
|
GPS::ShowInstance(char */*indent*/)
|
|
{
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
GPS::BecameActive()
|
|
{
|
|
Check(this);
|
|
numberOfMovingEntities = 0;
|
|
needsScreenUpdate = True;
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
GPS::NotifyOfNewInterestingEntity(Entity *entity)
|
|
{
|
|
Check(this);
|
|
Check(entity);
|
|
if (entity->IsDerivedFrom(*Terrain::GetClassDerivations()))
|
|
{
|
|
needsStaticUpdate = True;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
GPS::UpdateStaticEntities()
|
|
{
|
|
Check(this);
|
|
//-----------------------------------------------------------
|
|
// Calculate scale
|
|
//-----------------------------------------------------------
|
|
Scalar
|
|
minX, maxX, deltaX,
|
|
minY, maxY,
|
|
minZ, maxZ, deltaZ,
|
|
scaleX, scaleZ;
|
|
|
|
//----------------------------------------
|
|
// First, get bounds from staticEntityList
|
|
//----------------------------------------
|
|
Check(renderer);
|
|
renderer->GetStaticBounds(
|
|
&minX, &minY, &minZ,
|
|
&maxX, &maxY, &maxZ
|
|
);
|
|
//----------------------------------------
|
|
// Calculate X, Z scales
|
|
//----------------------------------------
|
|
deltaX = maxX - minX;
|
|
if (deltaX < 0)
|
|
{
|
|
deltaX = - deltaX;
|
|
}
|
|
if (deltaX != 0)
|
|
{
|
|
Verify(width > 0);
|
|
scaleX = deltaX/((Scalar) width);
|
|
}
|
|
else
|
|
{
|
|
scaleX = 1.0;
|
|
}
|
|
|
|
deltaZ = maxZ - minZ;
|
|
if (deltaZ < 0)
|
|
{
|
|
deltaZ = - deltaZ;
|
|
}
|
|
if (deltaZ > 0)
|
|
{
|
|
Verify(height > 0);
|
|
scaleZ = deltaZ/((Scalar) height);
|
|
}
|
|
else
|
|
{
|
|
scaleZ = 1.0;
|
|
}
|
|
//----------------------------------------
|
|
// Choose largest scaling value
|
|
// (such that entire map fits)
|
|
//----------------------------------------
|
|
metersPerPixel = (scaleX > scaleZ)? scaleX : scaleZ;
|
|
metersPerPixel *= 1.2; // allow for large objects at edges of map
|
|
//----------------------------------------
|
|
// Generate inverse as well
|
|
//----------------------------------------
|
|
Verify(!Small_Enough(metersPerPixel));
|
|
pixelsPerMeter = 1.0 / metersPerPixel;
|
|
|
|
//DEBUG_STREAM <<
|
|
// "GPS, dx=" << deltaX <<
|
|
// ", dz=" << deltaZ <<
|
|
// ", sx=" << scaleX <<
|
|
// ", sz=" << scaleZ <<
|
|
// ", metersPerPixel=" << metersPerPixel <<
|
|
// ", pixelsPerMeter=" << pixelsPerMeter <<
|
|
// "\n";
|
|
//----------------------------------------
|
|
// Generate centering offset
|
|
// (map is not necessarily symmetrical)
|
|
//----------------------------------------
|
|
centeringOffset.x = -(deltaX/2 + minX);
|
|
centeringOffset.y = 0.0;
|
|
centeringOffset.z = -(deltaZ/2 + minZ);
|
|
//-----------------------------------------------------------
|
|
// Rebuild background
|
|
//-----------------------------------------------------------
|
|
Check(background);
|
|
L4BytePort
|
|
backgroundPort(background, "background", 0);
|
|
Check(&backgroundPort);
|
|
|
|
GraphicsView
|
|
backgroundView(&backgroundPort);
|
|
Check(&backgroundView);
|
|
|
|
backgroundView.MoveToAbsolute(0, 0);
|
|
backgroundView.SetColor(0);
|
|
backgroundView.DrawFilledRectangleToAbsolute(width,height);
|
|
|
|
backgroundView.SetOrigin(width>>1, height>>1);
|
|
|
|
GaugeEntityList
|
|
staticEntityList;
|
|
renderer->GetStaticEntities(&staticEntityList);
|
|
|
|
ChainIteratorOf<Entity*>
|
|
i(staticEntityList.GetInstanceList());
|
|
|
|
Check(renderer);
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) renderer->warehousePointer;
|
|
Check(warehouse);
|
|
|
|
Entity
|
|
*entity;
|
|
L4GaugeImage
|
|
*gauge_image;
|
|
|
|
AffineMatrix
|
|
worldToView,
|
|
localToView;
|
|
|
|
Vector3D
|
|
scaling_vector;
|
|
//------------------------------------
|
|
// Scale the display
|
|
//------------------------------------
|
|
|
|
Verify(!Small_Enough(pixelsPerMeter));
|
|
|
|
scaling_vector.x = pixelsPerMeter;
|
|
scaling_vector.y = pixelsPerMeter;
|
|
scaling_vector.z = pixelsPerMeter;
|
|
|
|
worldToView.BuildIdentity();
|
|
worldToView *= centeringOffset; // translation
|
|
worldToView *= scaling_vector;
|
|
|
|
while ((entity=i.ReadAndNext()) != NULL)
|
|
{
|
|
Check(entity);
|
|
//-------------------------------------
|
|
// Draw image
|
|
//-------------------------------------
|
|
gauge_image = warehouse->
|
|
gaugeImageBin.GetIfAlreadyExists(entity->GetResourceID());
|
|
if (gauge_image != NULL)
|
|
{
|
|
Check(gauge_image);
|
|
|
|
localToView.Multiply(entity->localToWorld, worldToView);
|
|
|
|
gauge_image->Draw(
|
|
LODIndex, // value set by creator
|
|
metersPerPixel,
|
|
&backgroundView,
|
|
0, // default color
|
|
(AffineMatrix &) localToView
|
|
);
|
|
|
|
warehouse->gaugeImageBin.Release(entity->GetResourceID());
|
|
}
|
|
}
|
|
//-----------------------------------------------------------
|
|
// Redraw new background, restart moving entity display
|
|
//-----------------------------------------------------------
|
|
BecameActive();
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
void
|
|
GPS::Execute()
|
|
{
|
|
Check(this);
|
|
|
|
GaugeEntityList
|
|
movingEntityList;
|
|
GPSRecord
|
|
*gps_record;
|
|
int
|
|
size,
|
|
i;
|
|
|
|
enum
|
|
{
|
|
my_size=3,
|
|
your_size=2
|
|
};
|
|
|
|
//-----------------------------------------------------------
|
|
// Recreate background if it has changed
|
|
//-----------------------------------------------------------
|
|
if (needsStaticUpdate)
|
|
{
|
|
UpdateStaticEntities();
|
|
needsStaticUpdate = False;
|
|
}
|
|
//-----------------------------------------------------------
|
|
// Redraw background if needed
|
|
//-----------------------------------------------------------
|
|
if (needsScreenUpdate)
|
|
{
|
|
Check(background);
|
|
Check(background->pixelBuffer);
|
|
|
|
localView.MoveToAbsolute(0, 0);
|
|
localView.DrawPixelMap8(
|
|
True, // opaque
|
|
0, // rotation
|
|
background->pixelBuffer
|
|
);
|
|
|
|
needsScreenUpdate = False;
|
|
}
|
|
//-----------------------------------------------------------
|
|
// Erase old positions
|
|
//-----------------------------------------------------------
|
|
for(
|
|
i=numberOfMovingEntities, gps_record=previousGPSRecord;
|
|
i>0;
|
|
--i, ++gps_record
|
|
)
|
|
{
|
|
size = (gps_record->me)? my_size : your_size ;
|
|
|
|
localView.MoveToAbsolute(gps_record->x, gps_record->y);
|
|
localView.DrawPixelMap8(
|
|
True, // opaque
|
|
0, // rotation
|
|
background->pixelBuffer,
|
|
gps_record->x, // sx1
|
|
gps_record->y, // sy1
|
|
gps_record->x+size, // sx2
|
|
gps_record->y+size // sy2
|
|
);
|
|
}
|
|
//-----------------------------------------------------------
|
|
// Get new entity list
|
|
//-----------------------------------------------------------
|
|
movingEntityList.Clear();
|
|
renderer->GetMovingEntities(&movingEntityList);
|
|
//-----------------------------------------------------------
|
|
// Build new positions
|
|
//-----------------------------------------------------------
|
|
gps_record = previousGPSRecord;
|
|
numberOfMovingEntities = 0;
|
|
{
|
|
ChainIteratorOf<Entity*>
|
|
iterator(movingEntityList.GetInstanceList());
|
|
Entity
|
|
*entity;
|
|
RPPlayer
|
|
*player;
|
|
int
|
|
half_width = width >> 1,
|
|
half_height = height >> 1;
|
|
|
|
while((entity=iterator.ReadAndNext()) != NULL)
|
|
{
|
|
Check(entity);
|
|
//-----------------------------------------------------------
|
|
// Only show entities representing players
|
|
//-----------------------------------------------------------
|
|
player = (RPPlayer *)(entity->GetPlayerLink());
|
|
if (player != NULL)
|
|
{
|
|
Check(player);
|
|
|
|
gps_record->x = (int)
|
|
(
|
|
(
|
|
(entity->localOrigin.linearPosition.x+centeringOffset.x)
|
|
* pixelsPerMeter
|
|
)
|
|
+ .5 + half_width
|
|
);
|
|
gps_record->y = (int)
|
|
(
|
|
(
|
|
-(entity->localOrigin.linearPosition.z+centeringOffset.z)
|
|
* pixelsPerMeter
|
|
)
|
|
+ .5 + half_height
|
|
);
|
|
|
|
gps_record->me = (entity == renderer->GetLinkedEntity());
|
|
gps_record->color = determineEntityColor(entity);
|
|
|
|
++gps_record;
|
|
++numberOfMovingEntities;
|
|
if (numberOfMovingEntities >= max_moving_entities)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//-----------------------------------------------------------
|
|
// Draw new positions
|
|
//-----------------------------------------------------------
|
|
for(
|
|
i=numberOfMovingEntities, gps_record=previousGPSRecord;
|
|
i>0;
|
|
--i, ++gps_record
|
|
)
|
|
{
|
|
if (gps_record->me)
|
|
{
|
|
size = my_size;
|
|
localView.SetColor(gps_record->color + 0xC0); // flashes color
|
|
}
|
|
else
|
|
{
|
|
size = your_size;
|
|
localView.SetColor(gps_record->color);
|
|
}
|
|
|
|
localView.MoveToAbsolute(gps_record->x, gps_record->y);
|
|
localView.DrawFilledRectangleToRelative(size,size);
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//############################################################################
|
|
// Ranking
|
|
//############################################################################
|
|
|
|
# define FORCE_CHANNEL_UPDATE -1
|
|
|
|
MethodDescription
|
|
Ranking::methodDescription =
|
|
{
|
|
"ranking",
|
|
Ranking::Make,
|
|
{
|
|
{ ParameterDescription::typeRate, NULL }, // rate ID
|
|
{ ParameterDescription::typeModeMask, NULL }, // mode mask
|
|
{ ParameterDescription::typeString, NULL }, // font name
|
|
{ ParameterDescription::typeInteger, NULL }, // spacing
|
|
{ ParameterDescription::typeColor, NULL }, // score color
|
|
{ ParameterDescription::typeInteger, NULL }, // options
|
|
PARAMETER_DESCRIPTION_END
|
|
}
|
|
};
|
|
|
|
Logical
|
|
Ranking::Make(
|
|
int display_port_index,
|
|
Vector2DOf<int> position,
|
|
Entity */*entity*/,
|
|
GaugeRenderer * gauge_renderer
|
|
)
|
|
{
|
|
ParameterDescription
|
|
*parameterList = methodDescription.parameterList;
|
|
|
|
|
|
# if DEBUG_LEVEL > 0
|
|
parameterList[0].CheckIt(ParameterDescription::typeRate); // group ID
|
|
parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask
|
|
parameterList[2].CheckIt(ParameterDescription::typeString); // font name
|
|
parameterList[3].CheckIt(ParameterDescription::typeInteger); // spacing
|
|
parameterList[4].CheckIt(ParameterDescription::typeColor); // color
|
|
parameterList[5].CheckIt(ParameterDescription::typeInteger); // options
|
|
# endif
|
|
|
|
Test_Tell("Ranking::Make\n");
|
|
|
|
# if DEBUG_LEVEL > 0
|
|
Ranking
|
|
*ranking =
|
|
# endif
|
|
new Ranking(
|
|
parameterList[0].data.rate,
|
|
parameterList[1].data.modeMask,
|
|
(L4GaugeRenderer *) gauge_renderer,
|
|
0, // unsigned int owner_ID
|
|
display_port_index, // int graphics_port_number
|
|
position.x, position.y,
|
|
parameterList[2].data.string, // font name
|
|
parameterList[3].data.integer, // vertical spacing
|
|
parameterList[4].data.color, // numeric color
|
|
parameterList[5].data.integer // options
|
|
);
|
|
|
|
Register_Object(ranking);
|
|
|
|
//--------------------------------------------------------
|
|
// Make sure the font was properly placed in the warehouse
|
|
//--------------------------------------------------------
|
|
Check(gauge_renderer);
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
|
|
Check(warehouse);
|
|
|
|
if (warehouse->bitMapBin.Get(parameterList[2].data.string) == NULL)
|
|
{
|
|
Test_Tell("Ranking::Missing font\n");
|
|
Check_Fpu();
|
|
return False;
|
|
}
|
|
else
|
|
{
|
|
warehouse->bitMapBin.Release(parameterList[2].data.string);
|
|
}
|
|
//--------------------------------------------------------
|
|
// Everything's ok
|
|
//--------------------------------------------------------
|
|
Test_Tell("Ranking::Make OK\n");
|
|
Check_Fpu();
|
|
return True;
|
|
}
|
|
|
|
Ranking::Ranking(
|
|
GaugeRate rate,
|
|
ModeMask mode_mask,
|
|
L4GaugeRenderer *renderer,
|
|
unsigned int owner_ID,
|
|
int graphics_port_number,
|
|
int left, int top,
|
|
const char *font_name,
|
|
int new_spacing,
|
|
int numeric_color,
|
|
int new_options,
|
|
const char *identification_string
|
|
):
|
|
GraphicGauge(
|
|
rate,
|
|
mode_mask,
|
|
renderer,
|
|
owner_ID,
|
|
graphics_port_number,
|
|
identification_string
|
|
)
|
|
{
|
|
Test_Tell("Ranking creator\n" << std::flush);
|
|
Check_Pointer(this);
|
|
// graphics_port may be NULL!
|
|
|
|
spacing = new_spacing;
|
|
options = new_options;
|
|
x = left;
|
|
y = top - 32;
|
|
//-----------------------------------------------------------
|
|
// Get and lock font bitmap from warehouse
|
|
//-----------------------------------------------------------
|
|
Check(renderer);
|
|
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) renderer->warehousePointer;
|
|
Check(warehouse);
|
|
|
|
Check_Pointer(font_name);
|
|
BitMap
|
|
*font = warehouse->bitMapBin.Get(font_name);
|
|
|
|
Check(font);
|
|
//-----------------------------------------------------------
|
|
// Size/offset definitions
|
|
//-----------------------------------------------------------
|
|
# define width_of_bitmap 128
|
|
# define space_before_score 2
|
|
# define number_of_score_digits 8
|
|
# define space_before_channel 32
|
|
# define space_at_end_of_box 4
|
|
|
|
int
|
|
char_width = (font->Data.Size.x/NumericDisplay::totalDigitsPerFont);
|
|
int
|
|
score_width = char_width * number_of_score_digits;
|
|
int
|
|
channel_width = char_width;
|
|
int
|
|
score_offset = width_of_bitmap + space_before_score;
|
|
int
|
|
channel_offset = score_offset + score_width + space_before_channel;
|
|
|
|
//-----------------------------------------------------------
|
|
// Calculate box width
|
|
//-----------------------------------------------------------
|
|
width = width_of_bitmap + space_before_score +
|
|
score_width + space_at_end_of_box;
|
|
if (options & showIcomOption)
|
|
{
|
|
width += space_before_channel + channel_width;
|
|
}
|
|
//-----------------------------------------------------------
|
|
// Spawn off sub-instruments
|
|
//-----------------------------------------------------------
|
|
int
|
|
i,
|
|
bottom = y+3;
|
|
for(i=0; i<maximumDisplayedPlayers; ++i,bottom -= spacing)
|
|
{
|
|
numericDisplay[i] = new NumericDisplay(
|
|
warehouse,
|
|
x+score_offset, bottom,
|
|
font_name,
|
|
number_of_score_digits,
|
|
NumericDisplay::signedBlankedZerosFormat,
|
|
0,
|
|
numeric_color
|
|
);
|
|
Register_Object(numericDisplay[i]);
|
|
|
|
if (options & showIcomOption)
|
|
{
|
|
channelDisplay[i] = new NumericDisplay(
|
|
warehouse,
|
|
x+channel_offset, bottom,
|
|
font_name,
|
|
1,
|
|
NumericDisplay::unsignedFormat,
|
|
0,
|
|
numeric_color
|
|
);
|
|
Register_Object(channelDisplay[i]);
|
|
}
|
|
else
|
|
{
|
|
channelDisplay[i] = NULL;
|
|
}
|
|
}
|
|
//-----------------------------------------------------------
|
|
// Release the font bitmap from warehouse
|
|
//-----------------------------------------------------------
|
|
Check(warehouse);
|
|
Check_Pointer(font_name);
|
|
warehouse->bitMapBin.Release(font_name);
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
Ranking::~Ranking()
|
|
{
|
|
Test_Tell("Ranking destructor\n" << std::flush);
|
|
Check(this);
|
|
|
|
int
|
|
i;
|
|
//
|
|
//-----------------------------------------------------------
|
|
// Delete sub-gauges
|
|
//-----------------------------------------------------------
|
|
//
|
|
for(i=0; i<maximumDisplayedPlayers; ++i)
|
|
{
|
|
if (numericDisplay[i] != NULL)
|
|
{
|
|
Unregister_Object(numericDisplay[i]);
|
|
delete numericDisplay[i];
|
|
numericDisplay[i] = NULL;
|
|
}
|
|
if (channelDisplay[i] != NULL)
|
|
{
|
|
Unregister_Object(channelDisplay[i]);
|
|
delete channelDisplay[i];
|
|
channelDisplay[i] = NULL;
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
Logical
|
|
Ranking::TestInstance() const
|
|
{
|
|
return GraphicGauge::TestInstance();
|
|
}
|
|
|
|
void
|
|
Ranking::ShowInstance(char */*indent*/)
|
|
{
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
Ranking::LinkToEntity(Entity *entity)
|
|
{
|
|
Test_Tell("Ranking::LinkToEntity\n" << std::flush);
|
|
Check(this);
|
|
|
|
linkedEntity = entity;
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
Ranking::BecameActive()
|
|
{
|
|
Check(this);
|
|
|
|
previousRanking = 999;
|
|
previousIntercomEnabled = False;
|
|
//-------------------------------------------
|
|
// Clear the current array
|
|
//-------------------------------------------
|
|
for(int i=0; i<maximumDisplayedPlayers; ++i)
|
|
{
|
|
previousArray[i] = (Player *) -1;
|
|
previousScore[i] = -.001;
|
|
previousChannel[i] = FORCE_CHANNEL_UPDATE;
|
|
|
|
if (numericDisplay[i] != NULL)
|
|
{
|
|
Check(numericDisplay[i]);
|
|
numericDisplay[i]->ForceUpdate();
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
Ranking::Execute()
|
|
{
|
|
Test_Tell("Ranking::Execute\n" << std::flush);
|
|
Check(this);
|
|
|
|
Check(application);
|
|
Check(application->GetEntityManager());
|
|
|
|
EntityGroup
|
|
*all_players = application->GetEntityManager()->FindGroup("Players");
|
|
|
|
if (all_players != NULL)
|
|
{
|
|
Check(all_players);
|
|
|
|
Player
|
|
*player,
|
|
*currentArray[maximumDisplayedPlayers];
|
|
int
|
|
i,
|
|
bottom,
|
|
currentRanking;
|
|
|
|
Logical
|
|
intercomEnabled;
|
|
|
|
//-------------------------------------------
|
|
// Get 'our' placement & intercom status
|
|
//-------------------------------------------
|
|
if (linkedEntity == NULL)
|
|
{
|
|
currentRanking = -1;
|
|
intercomEnabled = False;
|
|
}
|
|
else
|
|
{
|
|
Check(linkedEntity);
|
|
player = linkedEntity->GetPlayerLink();
|
|
Check(player);
|
|
currentRanking = player->playerRanking;
|
|
|
|
Icom
|
|
*intercom = player->GetIntercom();
|
|
Check(intercom);
|
|
intercomEnabled = intercom->GetChannel() != Icom::undefinedChannel;
|
|
}
|
|
|
|
//-------------------------------------------
|
|
// Clear the current array
|
|
//-------------------------------------------
|
|
for(i=0; i<maximumDisplayedPlayers; ++i)
|
|
{
|
|
currentArray[i] = NULL;
|
|
}
|
|
//-------------------------------------------
|
|
// Build the current array
|
|
//-------------------------------------------
|
|
ChainIteratorOf<Node*>
|
|
iterator(all_players->groupMembers);
|
|
while((player=(Player *) iterator.ReadAndNext()) != NULL)
|
|
{
|
|
Check(player);
|
|
if (player->IsScoringPlayer())
|
|
{
|
|
if (player->playerRanking < maximumDisplayedPlayers)
|
|
{
|
|
Verify(player->playerRanking >= 0);
|
|
|
|
// HACK! Safety code for OPT version
|
|
if (player->playerRanking >= 0)
|
|
{
|
|
currentArray[player->playerRanking] = player;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//----------------------------------------------------------------------
|
|
// Compare to previousArray,
|
|
// draw names if order has changed
|
|
//----------------------------------------------------------------------
|
|
bottom = y;
|
|
for(i=0; i<maximumDisplayedPlayers; ++i,bottom-=spacing)
|
|
{
|
|
if (previousArray[i] != currentArray[i])
|
|
{
|
|
previousArray[i] = currentArray[i];
|
|
previousScore[i] = -1e23; // force score update
|
|
|
|
localView.MoveToAbsolute(x+1, bottom);
|
|
|
|
if (currentArray[i] == NULL)
|
|
{
|
|
//-------------------------------------------
|
|
// Erase name
|
|
//-------------------------------------------
|
|
localView.SetColor(0x00);
|
|
localView.DrawFilledRectangleToRelative(128,32);
|
|
//-------------------------------------------
|
|
// Erase score
|
|
//-------------------------------------------
|
|
Check(numericDisplay[i]);
|
|
numericDisplay[i]->Erase(&localView);
|
|
//-------------------------------------------
|
|
// Erase channel
|
|
//-------------------------------------------
|
|
if (channelDisplay[i] != NULL)
|
|
{
|
|
Check(channelDisplay[i]);
|
|
channelDisplay[i]->Erase(&localView);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Check(currentArray[i]);
|
|
//-------------------------------------------
|
|
// Draw name
|
|
//-------------------------------------------
|
|
Check(application);
|
|
Mission *current_mission = application->GetCurrentMission();
|
|
Check(current_mission);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get the nameBitmap out of the mission
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
BitMap *name_bitmap =
|
|
current_mission->
|
|
GetLargeNameBitmap(currentArray[i]->playerBitmapIndex);
|
|
|
|
if ( name_bitmap == NULL )
|
|
{
|
|
localView.SetColor(0x00);
|
|
localView.DrawFilledRectangleToRelative(128,32);
|
|
}
|
|
else
|
|
{
|
|
int
|
|
color = 255;
|
|
|
|
if (options & useTeamColorOption)
|
|
{
|
|
Entity
|
|
*entity = currentArray[i]->GetPlayerVehicle();
|
|
|
|
if (entity != NULL)
|
|
{
|
|
color = determineEntityColor(entity);
|
|
}
|
|
}
|
|
localView.SetColor(color);
|
|
|
|
localView.DrawBitMapOpaque(
|
|
0x00, // background
|
|
0, // rotation
|
|
name_bitmap
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//----------------------------------------------------------------------
|
|
// Draw scores if changed
|
|
//----------------------------------------------------------------------
|
|
for(i=0; i<maximumDisplayedPlayers; ++i)
|
|
{
|
|
RPPlayer
|
|
*rp_player = (RPPlayer *) currentArray[i];
|
|
|
|
if (rp_player == NULL)
|
|
{
|
|
numericDisplay[i]->Erase(&localView);
|
|
}
|
|
else
|
|
{
|
|
//-------------------------------------------
|
|
// Get truncated score (no rounding)
|
|
//-------------------------------------------
|
|
int
|
|
integer_score = (int) rp_player->currentScore;
|
|
Scalar
|
|
new_score = (Scalar) integer_score;
|
|
|
|
if (previousScore[i] != new_score)
|
|
{
|
|
previousScore[i] = new_score;
|
|
|
|
Check(numericDisplay[i]);
|
|
//-------------------------------------------
|
|
// Display scores for general players, or
|
|
// only the runners in Martian Football
|
|
//-------------------------------------------
|
|
switch(rp_player->playerType)
|
|
{
|
|
case RPPlayer::GeneralPlayerType:
|
|
if (i > currentRanking && !(options & showAllScoresOption))
|
|
{
|
|
numericDisplay[i]->Erase(&localView);
|
|
}
|
|
else
|
|
{
|
|
numericDisplay[i]->Draw(&localView, new_score);
|
|
}
|
|
break;
|
|
|
|
case RPPlayer::RunnerPlayerType:
|
|
numericDisplay[i]->Draw(&localView, new_score);
|
|
break;
|
|
|
|
default:
|
|
numericDisplay[i]->Erase(&localView);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//----------------------------------------------------------------------
|
|
// Draw channels if changed
|
|
//----------------------------------------------------------------------
|
|
if (options & showIcomOption)
|
|
{
|
|
Player
|
|
*this_player;
|
|
L4Icom
|
|
*this_intercom;
|
|
int
|
|
new_channel;
|
|
|
|
if (! intercomEnabled)
|
|
{
|
|
if (previousIntercomEnabled == True)
|
|
{
|
|
//--------------------------------------------
|
|
// We now have no intercom, clear channels
|
|
//--------------------------------------------
|
|
for(i=0; i<maximumDisplayedPlayers; ++i)
|
|
{
|
|
channelDisplay[i]->Erase(&localView);
|
|
previousChannel[i] = Icom::undefinedChannel;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i=0; i<maximumDisplayedPlayers; ++i)
|
|
{
|
|
Check(channelDisplay[i]);
|
|
|
|
if (currentArray[i] == NULL)
|
|
{
|
|
//--------------------------------------------
|
|
// No intercom to reference
|
|
//--------------------------------------------
|
|
if (previousChannel[i] != Icom::undefinedChannel)
|
|
{
|
|
channelDisplay[i]->Erase(&localView);
|
|
previousChannel[i] = Icom::undefinedChannel;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// HACK - eventually HIDE the channel if not the same team
|
|
|
|
//-------------------------------------------
|
|
// Get the channel number for the pilot
|
|
//-------------------------------------------
|
|
Check(currentArray[i]);
|
|
this_player = currentArray[i];
|
|
Check(this_player);
|
|
this_intercom = (L4Icom *) this_player->GetIntercom();
|
|
Check(this_intercom);
|
|
new_channel =
|
|
this_intercom->GetChannel() -
|
|
this_intercom->GetChannelOffset();
|
|
Verify(new_channel >= 0);
|
|
Verify(new_channel < 7);
|
|
//-------------------------------------------
|
|
// Update if changed
|
|
//-------------------------------------------
|
|
if (previousChannel[i] != new_channel)
|
|
{
|
|
previousChannel[i] = new_channel;
|
|
|
|
if (new_channel == Icom::undefinedChannel)
|
|
{
|
|
//-------------------------------------------
|
|
// Not on the 'com, clear channel number
|
|
//-------------------------------------------
|
|
channelDisplay[i]->Erase(&localView);
|
|
}
|
|
else
|
|
{
|
|
//-------------------------------------------
|
|
// On the 'com, display channel number
|
|
// (channels are internally 0..N, add one
|
|
// to match labels on display)
|
|
//-------------------------------------------
|
|
channelDisplay[i]->Draw(&localView, new_channel+1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------
|
|
// Update 'previousIntercomEnabled'
|
|
//---------------------------------
|
|
previousIntercomEnabled = intercomEnabled;
|
|
}
|
|
//----------------------------------------------------------------------
|
|
// Draw boxes if changed
|
|
//----------------------------------------------------------------------
|
|
if (previousRanking != currentRanking)
|
|
{
|
|
//---------------------------------
|
|
// Erase old box
|
|
//---------------------------------
|
|
if (previousRanking >= 0)
|
|
{
|
|
if (previousRanking < maximumDisplayedPlayers)
|
|
{
|
|
localView.SetColor(0x00);
|
|
localView.MoveToAbsolute(x,y-(previousRanking*spacing)-1);
|
|
localView.DrawRectangleToRelative(width,34);
|
|
}
|
|
}
|
|
//---------------------------------
|
|
// Draw new box
|
|
//---------------------------------
|
|
if (currentRanking >= 0)
|
|
{
|
|
if (currentRanking < maximumDisplayedPlayers)
|
|
{
|
|
localView.SetColor(255);
|
|
localView.MoveToAbsolute(x,y-(currentRanking*spacing)-1);
|
|
localView.DrawRectangleToRelative(width,34);
|
|
}
|
|
}
|
|
//---------------------------------
|
|
// Update 'previousRanking'
|
|
//---------------------------------
|
|
previousRanking = currentRanking;
|
|
}
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
//############################################################################
|
|
// ConfigMap
|
|
//############################################################################
|
|
|
|
MethodDescription
|
|
ConfigMap::methodDescription =
|
|
{
|
|
"configMap",
|
|
ConfigMap::Make,
|
|
{
|
|
{ ParameterDescription::typeRate, NULL }, // rate ID
|
|
{ ParameterDescription::typeModeMask, NULL },// mode mask
|
|
{ ParameterDescription::typeString, NULL }, // "unmapped" icon
|
|
{ ParameterDescription::typeString, NULL }, // "other" icon
|
|
{ ParameterDescription::typeString, NULL }, // "my" icon
|
|
{ ParameterDescription::typeString, NULL }, // "both" icon
|
|
PARAMETER_DESCRIPTION_END
|
|
}
|
|
};
|
|
|
|
Logical
|
|
ConfigMap::Make(
|
|
int display_port_index,
|
|
Vector2DOf<int> position,
|
|
Entity */*entity*/,
|
|
GaugeRenderer * gauge_renderer
|
|
)
|
|
{
|
|
ParameterDescription
|
|
*parameterList = methodDescription.parameterList;
|
|
|
|
|
|
# if DEBUG_LEVEL > 0
|
|
parameterList[0].CheckIt(ParameterDescription::typeRate); // group ID
|
|
parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask
|
|
parameterList[2].CheckIt(ParameterDescription::typeString); // "unmapped"
|
|
parameterList[3].CheckIt(ParameterDescription::typeString); // "other"
|
|
parameterList[4].CheckIt(ParameterDescription::typeString); // "my"
|
|
parameterList[5].CheckIt(ParameterDescription::typeString); // "both"
|
|
# endif
|
|
|
|
Test_Tell("ConfigMap::Make\n");
|
|
|
|
# if DEBUG_LEVEL > 0
|
|
ConfigMap
|
|
*config_map =
|
|
# endif
|
|
new ConfigMap(
|
|
parameterList[0].data.rate,
|
|
parameterList[1].data.modeMask,
|
|
(L4GaugeRenderer *) gauge_renderer,
|
|
0, // unsigned int owner_ID
|
|
display_port_index, // int graphics_port_number
|
|
position.x, position.y,
|
|
parameterList[2].data.string, // "unmapped" icon
|
|
parameterList[3].data.string, // "mapped to other" icon
|
|
parameterList[4].data.string, // "mapped exclusively to us" icon
|
|
parameterList[5].data.string // "mapped to us and others" icon
|
|
);
|
|
|
|
Register_Object(config_map);
|
|
//----------------------------------------------------------
|
|
// Make sure the icons were properly placed in the warehouse
|
|
//----------------------------------------------------------
|
|
Check(gauge_renderer);
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
|
|
Check(warehouse);
|
|
|
|
for(int i=2; i<=5; ++i)
|
|
{
|
|
if (warehouse->pixelMap8Bin.Get(parameterList[i].data.string) == NULL)
|
|
{
|
|
Test_Tell(
|
|
"ConfigMap::Missing icon'" << parameterList[i].data.string << "'\n"
|
|
);
|
|
Check_Fpu();
|
|
return False;
|
|
}
|
|
else
|
|
{
|
|
warehouse->pixelMap8Bin.Release(parameterList[i].data.string);
|
|
}
|
|
}
|
|
//--------------------------------------------------------
|
|
// Everything's ok
|
|
//--------------------------------------------------------
|
|
Test_Tell("ConfigMap::Make OK\n");
|
|
Check_Fpu();
|
|
return True;
|
|
}
|
|
|
|
ConfigMap::ConfigMap(
|
|
GaugeRate rate,
|
|
ModeMask mode_mask,
|
|
L4GaugeRenderer *renderer,
|
|
unsigned int owner_ID,
|
|
int graphics_port_number,
|
|
int left, int bottom,
|
|
const char *unmapped_icon,
|
|
const char *other_icon,
|
|
const char *my_icon,
|
|
const char *both_icon,
|
|
const char *identification_string
|
|
):
|
|
GraphicGauge(
|
|
rate,
|
|
mode_mask,
|
|
renderer,
|
|
owner_ID,
|
|
graphics_port_number,
|
|
identification_string
|
|
)
|
|
{
|
|
Test_Tell("ConfigMap creator\n" << std::flush);
|
|
Check_Pointer(this);
|
|
// graphics_port may be NULL!
|
|
|
|
//-------------------------------------------------
|
|
// Make local copies of image names
|
|
//-------------------------------------------------
|
|
iconName[0] = nameCopy(unmapped_icon);
|
|
iconName[1] = nameCopy(other_icon);
|
|
iconName[2] = nameCopy(my_icon);
|
|
iconName[3] = nameCopy(both_icon);
|
|
//-------------------------------------------------
|
|
// Preload images from warehouse
|
|
//-------------------------------------------------
|
|
# if defined(PRELOAD_ART)
|
|
{
|
|
int
|
|
i;
|
|
Check(renderer);
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) renderer->warehousePointer;
|
|
Check(warehouse);
|
|
|
|
for(i=0; i<4; ++i)
|
|
{
|
|
warehouse->pixelMap8Bin.Get(iconName[i]);
|
|
}
|
|
}
|
|
# endif
|
|
//-----------------------------------------------------------
|
|
// Initialize values
|
|
//-----------------------------------------------------------
|
|
# if DEBUG_LEVEL > 0
|
|
{
|
|
int
|
|
i;
|
|
for(i=0; i<4; ++i)
|
|
{
|
|
Check_Pointer(iconName[i]);
|
|
}
|
|
}
|
|
# endif
|
|
|
|
localView.SetOrigin(left, bottom);
|
|
|
|
linkedEntity = NULL;
|
|
Check_Fpu();
|
|
}
|
|
|
|
ConfigMap::~ConfigMap()
|
|
{
|
|
Test_Tell("ConfigMap destructor\n" << std::flush);
|
|
Check(this);
|
|
//-------------------------------------------------
|
|
// Unlock preloaded art
|
|
//-------------------------------------------------
|
|
# if defined(PRELOAD_ART)
|
|
{
|
|
int
|
|
i;
|
|
Check(renderer);
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) renderer->warehousePointer;
|
|
Check(warehouse);
|
|
|
|
for(i=0; i<4; ++i)
|
|
{
|
|
warehouse->pixelMap8Bin.Release(iconName[i]);
|
|
}
|
|
}
|
|
# endif
|
|
//-------------------------------------------------
|
|
// Delete local copies of image names
|
|
//-------------------------------------------------
|
|
for(int i=0; i<4; ++i)
|
|
{
|
|
Unregister_Pointer(iconName[i]);
|
|
delete[] iconName[i];
|
|
iconName[i] = NULL;
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
Logical
|
|
ConfigMap::TestInstance() const
|
|
{
|
|
return GraphicGauge::TestInstance();
|
|
}
|
|
|
|
void
|
|
ConfigMap::ShowInstance(char */*indent*/)
|
|
{
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
ConfigMap::LinkToEntity(Entity *entity)
|
|
{
|
|
Test_Tell("ConfigMap::LinkToEntity\n" << std::flush);
|
|
Check(this);
|
|
|
|
linkedEntity = entity;
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
ConfigMap::BecameActive()
|
|
{
|
|
Check(this);
|
|
|
|
int
|
|
i;
|
|
|
|
for(i=0; i<4; ++i)
|
|
{
|
|
previousState[i] = -1;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
struct ConfigSet
|
|
{
|
|
int yOffset;
|
|
int buttonNumber;
|
|
};
|
|
|
|
void
|
|
ConfigMap::Execute()
|
|
{
|
|
static ConfigSet
|
|
configSet[4] =
|
|
{
|
|
{ 0, LBE4ControlsManager::ButtonJoystickPinky },
|
|
{ 58, LBE4ControlsManager::ButtonJoystickThumbLow },
|
|
{ 118, LBE4ControlsManager::ButtonJoystickTrigger },
|
|
{ 178, LBE4ControlsManager::ButtonJoystickThumbHigh }
|
|
};
|
|
|
|
Test_Tell("ConfigMap::Execute\n" << std::flush);
|
|
Check(this);
|
|
|
|
if (linkedEntity == NULL)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// Get current preset mode mask
|
|
//-----------------------------------------------------------
|
|
L4VTVControlsMapper
|
|
*mapper = Cast_Object(
|
|
L4VTVControlsMapper*,
|
|
linkedEntity->GetSubsystem(VTV::ControlsMapperSubsystem)
|
|
);
|
|
Check(mapper);
|
|
|
|
ModeMask
|
|
preset_mode_mask = mapper->GetPresetModeMask();
|
|
//-----------------------------------------------------------
|
|
// Get pointer to controls
|
|
//-----------------------------------------------------------
|
|
Check(application);
|
|
LBE4ControlsManager
|
|
*controls = (LBE4ControlsManager *) application->GetControlsManager();
|
|
Check(controls);
|
|
//-----------------------------------------------------------
|
|
// Get warehouse pointer
|
|
//-----------------------------------------------------------
|
|
Check(renderer);
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) renderer->warehousePointer;
|
|
Check(warehouse);
|
|
//-----------------------------------------------------------
|
|
// Scan controls, searching for mapping changes
|
|
//-----------------------------------------------------------
|
|
int
|
|
i,
|
|
state;
|
|
|
|
for(i=0; i<4; ++i)
|
|
{
|
|
if (
|
|
(controls->activeDestination == NULL)
|
|
&&
|
|
(controls->activeMessageID == 0)
|
|
)
|
|
{
|
|
state = 0;
|
|
}
|
|
else
|
|
{
|
|
state = controls ->
|
|
buttonGroup[configSet[i].buttonNumber].
|
|
GetMapState(
|
|
controls->activeDestination,
|
|
controls->activeReceiver,
|
|
controls->activeMessageID,
|
|
preset_mode_mask
|
|
);
|
|
}
|
|
|
|
Verify(state >= 0);
|
|
Verify(state <= 3);
|
|
|
|
if (previousState[i] != state)
|
|
{
|
|
previousState[i] = state;
|
|
//--------------------------------------------------
|
|
// Get, lock icon from warehouse
|
|
//--------------------------------------------------
|
|
PixelMap8
|
|
*pixelmap = warehouse->pixelMap8Bin.Get(iconName[state]);
|
|
|
|
if (pixelmap != NULL)
|
|
{
|
|
//--------------------------------------------------
|
|
// Draw it
|
|
//--------------------------------------------------
|
|
localView.MoveToAbsolute(0, configSet[i].yOffset);
|
|
localView.DrawPixelMap8(
|
|
False, // opaque
|
|
0, // rotation
|
|
pixelmap
|
|
);
|
|
}
|
|
//--------------------------------------------------
|
|
// Release icon from warehouse
|
|
//--------------------------------------------------
|
|
Check(warehouse);
|
|
warehouse->pixelMap8Bin.Release(iconName[i]);
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
//*****************************************************************************
|
|
// MessageBoard
|
|
//*****************************************************************************
|
|
MethodDescription
|
|
MessageBoard::methodDescription =
|
|
{
|
|
"messageBoard",
|
|
MessageBoard::Make,
|
|
{
|
|
{ ParameterDescription::typeRate, NULL }, // rate ID
|
|
{ ParameterDescription::typeModeMask, NULL },// mode mask
|
|
{ ParameterDescription::typeVector, NULL }, // size
|
|
{ ParameterDescription::typeString, NULL }, // font
|
|
{ ParameterDescription::typeString, NULL }, // message map
|
|
{ ParameterDescription::typeColor, NULL }, // background
|
|
{ ParameterDescription::typeColor, NULL }, // background
|
|
PARAMETER_DESCRIPTION_END
|
|
}
|
|
};
|
|
|
|
Logical
|
|
MessageBoard::Make(
|
|
int display_port_index,
|
|
Vector2DOf<int> position,
|
|
Entity */*entity*/,
|
|
GaugeRenderer *gauge_renderer
|
|
)
|
|
{
|
|
Test_Tell("MessageBoard::Make\n");
|
|
Check(gauge_renderer);
|
|
|
|
ParameterDescription
|
|
*parameterList = methodDescription.parameterList;
|
|
|
|
# if DEBUG_LEVEL > 0
|
|
parameterList[0].CheckIt(ParameterDescription::typeRate); // group ID
|
|
parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask
|
|
parameterList[2].CheckIt(ParameterDescription::typeVector); // size
|
|
parameterList[3].CheckIt(ParameterDescription::typeString); // font
|
|
parameterList[4].CheckIt(ParameterDescription::typeString); // message map
|
|
parameterList[5].CheckIt(ParameterDescription::typeColor); // bg
|
|
parameterList[6].CheckIt(ParameterDescription::typeColor); // numeric
|
|
# endif
|
|
|
|
# if DEBUG_LEVEL > 0
|
|
MessageBoard
|
|
*annunciator =
|
|
# endif
|
|
new MessageBoard(
|
|
parameterList[0].data.rate,
|
|
parameterList[1].data.modeMask,
|
|
(L4GaugeRenderer *) gauge_renderer,
|
|
0, // unsigned int owner_ID
|
|
display_port_index, // int graphics_port_number
|
|
position.x, position.y,
|
|
position.x + parameterList[2].data.vector.x,
|
|
position.y + parameterList[2].data.vector.y,
|
|
parameterList[3].data.string, // font
|
|
parameterList[4].data.string, // message map
|
|
parameterList[5].data.color, // bg color
|
|
parameterList[6].data.color // numeric color
|
|
);
|
|
|
|
Register_Object(annunciator);
|
|
//----------------------------------------------------------
|
|
// Make sure the art was properly placed in the warehouse
|
|
//----------------------------------------------------------
|
|
Check(gauge_renderer);
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) gauge_renderer->warehousePointer;
|
|
Check(warehouse);
|
|
|
|
for(int i=3; i<=4; ++i)
|
|
{
|
|
if (warehouse->bitMapBin.Get(parameterList[i].data.string) == NULL)
|
|
{
|
|
Test_Tell(
|
|
"MessageBoard::Missing art '" <<
|
|
parameterList[i].data.string << "'\n"
|
|
);
|
|
Check_Fpu();
|
|
return False;
|
|
}
|
|
else
|
|
{
|
|
warehouse->bitMapBin.Release(parameterList[i].data.string);
|
|
}
|
|
}
|
|
//--------------------------------------------------------
|
|
// Everything's ok
|
|
//--------------------------------------------------------
|
|
Test_Tell("MessageBoard::Make\n");
|
|
Check_Fpu();
|
|
return True;
|
|
}
|
|
|
|
MessageBoard::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
|
|
):
|
|
GraphicGauge(
|
|
rate,
|
|
mode_mask,
|
|
renderer,
|
|
owner_ID,
|
|
graphics_port_number,
|
|
identification_string
|
|
)
|
|
{
|
|
Test_Tell("MessageBoard::MessageBoard\n");
|
|
Check_Pointer(this);
|
|
|
|
// graphics_port may be NULL!
|
|
|
|
Check_Pointer(font_name);
|
|
Check_Pointer(message_name);
|
|
|
|
//-----------------------------------------------------------
|
|
// Make local copy of image name
|
|
//-----------------------------------------------------------
|
|
messageName = nameCopy(message_name);
|
|
Check_Pointer(messageName);
|
|
//-----------------------------------------------------------
|
|
// Create warehouse pointer
|
|
//-----------------------------------------------------------
|
|
Check(renderer);
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) renderer->warehousePointer;
|
|
Check(warehouse);
|
|
//-----------------------------------------------------------
|
|
// Preload message bitmap
|
|
//-----------------------------------------------------------
|
|
# if defined(PRELOAD_ART)
|
|
warehouse->bitMapBin.Get(messageName);
|
|
# endif
|
|
//-----------------------------------------------------------
|
|
// Set position of graphicsView within the graphicsPort
|
|
// (which also specifies the clipping and origin)
|
|
//-----------------------------------------------------------
|
|
Verify(right > left);
|
|
Verify(top > bottom);
|
|
localView.SetPositionWithinPort(left, bottom, right, top);
|
|
//-----------------------------------------------------------
|
|
// Initialize internal values
|
|
//-----------------------------------------------------------
|
|
backgroundColor = bg_color;
|
|
linkedEntity = NULL;
|
|
//--------------------------------
|
|
// Get, lock font from warehouse
|
|
//--------------------------------
|
|
BitMap
|
|
*font = warehouse->bitMapBin.Get(font_name);
|
|
|
|
if (font == NULL)
|
|
{
|
|
fontHeight = 0;
|
|
}
|
|
else
|
|
{
|
|
fontHeight = font->Data.Size.y;
|
|
}
|
|
//-----------------------------------------------------------
|
|
// Create numeric display
|
|
//-----------------------------------------------------------
|
|
Check(renderer);
|
|
Check(renderer->warehousePointer);
|
|
numericDisplay = new NumericDisplay(
|
|
(L4Warehouse *) renderer->warehousePointer,
|
|
14, 0, // position relative to local origin
|
|
font_name,
|
|
8,
|
|
NumericDisplay::signedBlankedZerosFormat,
|
|
0,
|
|
numeric_color
|
|
);
|
|
Register_Object(numericDisplay);
|
|
|
|
//-----------------------------------------------------------
|
|
// Release font from warehouse
|
|
//-----------------------------------------------------------
|
|
Check(warehouse);
|
|
warehouse->bitMapBin.Release(font_name);
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
MessageBoard::~MessageBoard()
|
|
{
|
|
Test_Tell("MessageBoard::~MessageBoard\n");
|
|
Check(this);
|
|
//-------------------------------------------------
|
|
// Unlock preloaded art
|
|
//-------------------------------------------------
|
|
# if defined(PRELOAD_ART)
|
|
Check(renderer);
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) renderer->warehousePointer;
|
|
Check(warehouse);
|
|
warehouse->bitMapBin.Release(messageName);
|
|
# endif
|
|
//-------------------------------------------------
|
|
// Delete local copies of image name
|
|
//-------------------------------------------------
|
|
Unregister_Pointer(messageName);
|
|
delete[] messageName;
|
|
messageName = NULL;
|
|
//-----------------------------------------------------------
|
|
// Delete numeric display
|
|
//-----------------------------------------------------------
|
|
Unregister_Object(numericDisplay);
|
|
delete numericDisplay;
|
|
numericDisplay = NULL;
|
|
|
|
// base class deletes all connections in Gauge::~Gauge
|
|
Check_Fpu();
|
|
}
|
|
|
|
Logical
|
|
MessageBoard::TestInstance() const
|
|
{
|
|
return GraphicGauge::TestInstance();
|
|
}
|
|
|
|
void
|
|
MessageBoard::ShowInstance(char *indent)
|
|
{
|
|
Check(this);
|
|
|
|
std::cout << indent << "MessageBoard:\n";
|
|
|
|
char
|
|
temp[80];
|
|
|
|
Str_Copy(temp,indent, 80);
|
|
Str_Cat(temp,"...", 80);
|
|
|
|
std::cout << temp << "backgroundColor=" << backgroundColor << "\n";
|
|
std::cout << temp << "linkedEntity =" << linkedEntity << "\n";
|
|
std::cout << temp << "numericDisplay =" << numericDisplay << "\n";
|
|
GraphicGauge::ShowInstance(temp);
|
|
|
|
Str_Cat(temp,"...", 80);
|
|
Check(numericDisplay);
|
|
numericDisplay->ShowInstance(temp);
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
MessageBoard::BecameActive()
|
|
{
|
|
Test_Tell("MessageBoard::BecameActive\n" << std::flush);
|
|
Check(this);
|
|
|
|
previousPlayerPointer = (Player *) deliberatelyBogusPointerValue;
|
|
previousMessageType = -2;
|
|
previousValue = (Scalar) 2e-22;
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
MessageBoard::LinkToEntity(Entity *entity)
|
|
{
|
|
Test_Tell("MessageBoard::LinkToEntity\n" << std::flush);
|
|
Check(this);
|
|
|
|
linkedEntity = entity;
|
|
Check_Fpu();
|
|
}
|
|
|
|
void
|
|
MessageBoard::Execute()
|
|
{
|
|
Test_Tell("MessageBoard::Execute\n" << std::flush);
|
|
Check(this);
|
|
|
|
if (linkedEntity == NULL)
|
|
{
|
|
return;
|
|
}
|
|
Check(linkedEntity);
|
|
|
|
//--------------------------------------------------
|
|
// Get a pointer to the local player object
|
|
// (or else return)
|
|
//--------------------------------------------------
|
|
RPPlayer
|
|
*owner_player = (RPPlayer *) linkedEntity->GetPlayerLink();
|
|
|
|
if (owner_player == NULL)
|
|
{
|
|
return;
|
|
}
|
|
Check(owner_player);
|
|
//--------------------------------------------------
|
|
// Get message data
|
|
//--------------------------------------------------
|
|
Player
|
|
*message_player;
|
|
int
|
|
message_type;
|
|
Scalar
|
|
message_value;
|
|
|
|
{
|
|
RPPlayer__StatusMessage
|
|
*message_pointer = (RPPlayer__StatusMessage *)
|
|
owner_player->statusMessagePointer;
|
|
|
|
if (message_pointer == NULL)
|
|
{
|
|
message_player = NULL;
|
|
message_type = RPPlayer::RPStatusMessage::NoMessage;
|
|
message_value = 0.0;
|
|
}
|
|
else
|
|
{
|
|
Check_Pointer(message_pointer);
|
|
|
|
message_player = message_pointer->playerInvolved;
|
|
message_type = message_pointer->messageType;
|
|
message_value = message_pointer->damageAmount;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
// Draw player name
|
|
//
|
|
// Warning - previousPlayerPointer is deliberately
|
|
// set to an illegal value in BecameActive() in order
|
|
// to force the next 'if' statement to execute.
|
|
// This is safe because we never directly use
|
|
// previousPlayerPointer without loading first
|
|
// loading it from message_player.
|
|
//--------------------------------------------------
|
|
if (previousPlayerPointer != message_player)
|
|
{
|
|
localView.MoveToAbsolute(0,fontHeight+1);
|
|
|
|
if (message_player == NULL)
|
|
{
|
|
//------------------------------
|
|
// No player, erase area
|
|
//------------------------------
|
|
localView.SetColor(backgroundColor);
|
|
|
|
// Note: previousPlayerPointer cannot be null 'cuz message_player was
|
|
|
|
if (previousPlayerPointer == (Player *) deliberatelyBogusPointerValue)
|
|
{
|
|
//----------------------------------
|
|
// No previous name, clear rectangle
|
|
//----------------------------------
|
|
localView.DrawFilledRectangleToRelative(128,32);
|
|
}
|
|
else
|
|
{
|
|
//----------------------------------------
|
|
// Draw previous name in BG color to erase
|
|
//----------------------------------------
|
|
Check(previousPlayerPointer);
|
|
|
|
localView.DrawBitMap(
|
|
0, // rotation
|
|
(application->GetCurrentMission())->GetLargeNameBitmap(
|
|
previousPlayerPointer->playerBitmapIndex
|
|
)
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Check(message_player);
|
|
|
|
//------------------------------
|
|
// Get player vehicle color
|
|
//------------------------------
|
|
Check(message_player->GetPlayerVehicle());
|
|
localView.SetColor(
|
|
determineEntityColor(message_player->GetPlayerVehicle())
|
|
);
|
|
//------------------------------
|
|
// Get Bitmap from Mission
|
|
//------------------------------
|
|
Check(application);
|
|
Check(application->GetCurrentMission());
|
|
|
|
localView.DrawBitMapOpaque(
|
|
backgroundColor,
|
|
0, // rotation
|
|
(application->GetCurrentMission())->GetLargeNameBitmap(
|
|
message_player->playerBitmapIndex
|
|
)
|
|
);
|
|
}
|
|
previousPlayerPointer = message_player;
|
|
}
|
|
//--------------------------------------------------
|
|
// Draw message
|
|
//--------------------------------------------------
|
|
if (previousMessageType != message_type)
|
|
{
|
|
previousMessageType = message_type;
|
|
|
|
localView.MoveToAbsolute(0,fontHeight+(1+32));
|
|
|
|
if (previousMessageType < 0)
|
|
{
|
|
//--------------------------------------------------
|
|
// Whoops, 'no message'. Erase it.
|
|
//--------------------------------------------------
|
|
localView.SetColor(backgroundColor);
|
|
localView.DrawFilledRectangleToRelative(128,32);
|
|
}
|
|
else
|
|
{
|
|
//--------------------------------------------------
|
|
// Choose sub-map from larger image
|
|
//
|
|
// The messageMap is a bitmap consisting of a
|
|
// group of 32 128x32 messages arranged as
|
|
// (4 across) by (8 high):
|
|
//
|
|
// +--------+--------+--------+--------+
|
|
// | 28 | 29 | 30 | 31 |
|
|
// +--------+--------+--------+--------+
|
|
// ....
|
|
// +--------+--------+--------+--------+
|
|
// | 12 | 13 | 14 | 15 |
|
|
// +--------+--------+--------+--------+
|
|
// | 8 | 9 | 10 | 11 |
|
|
// +--------+--------+--------+--------+
|
|
// | 4 | 5 | 6 | 7 |
|
|
// +--------+--------+--------+--------+
|
|
// | 0 | 1 | 2 | 3 |
|
|
// +--------+--------+--------+--------+
|
|
// (origin (0,0) is lower left!)
|
|
//--------------------------------------------------
|
|
Verify(previousMessageType < 32);
|
|
|
|
int
|
|
sx = (previousMessageType & 3) << 7, // times 128
|
|
sy = (previousMessageType >> 2) << 5; // times 32
|
|
|
|
//-----------------------------------------------------------
|
|
// Get player vehicle color
|
|
//-----------------------------------------------------------
|
|
Check(owner_player->GetPlayerVehicle());
|
|
localView.SetColor(
|
|
determineEntityColor(owner_player->GetPlayerVehicle())
|
|
);
|
|
//-----------------------------------------------------------
|
|
// Get, lock image from warehouse
|
|
//-----------------------------------------------------------
|
|
Check(renderer);
|
|
L4Warehouse
|
|
*warehouse = (L4Warehouse *) renderer->warehousePointer;
|
|
Check(warehouse);
|
|
|
|
BitMap
|
|
*message_map = warehouse->bitMapBin.Get(messageName);
|
|
//-----------------------------------------------------------
|
|
// Draw it
|
|
//-----------------------------------------------------------
|
|
if (message_map != NULL)
|
|
{
|
|
Check(message_map);
|
|
|
|
localView.DrawBitMapOpaque(
|
|
backgroundColor,
|
|
0, // rotation
|
|
message_map,
|
|
sx, sy, sx+127, sy+31
|
|
);
|
|
}
|
|
//-----------------------------------------------------------
|
|
// Release image from warehouse
|
|
//-----------------------------------------------------------
|
|
Check(warehouse);
|
|
warehouse->bitMapBin.Release(messageName);
|
|
}
|
|
}
|
|
//--------------------------------------------------
|
|
// Draw numeric value
|
|
//--------------------------------------------------
|
|
if (previousValue != message_value)
|
|
{
|
|
previousValue = message_value;
|
|
Check(numericDisplay);
|
|
|
|
if ((previousValue > (Scalar) 1) || (previousValue < (Scalar) -1))
|
|
{
|
|
numericDisplay->Draw(&localView, previousValue);
|
|
}
|
|
else
|
|
{
|
|
numericDisplay->Erase(&localView);
|
|
}
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|