Files
CydandClaude Opus 4.8 4abbf8879f Initial import of Red Planet v4.10 Win32 source
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>
2026-06-30 07:59:51 -05:00

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, &currentScale, scale_value_pointer);
Register_Object(connection);
AddConnection(connection);
connection = new
GaugeConnectionDirectOf<Point3D *>(
0, &currentPositionPointer, position_pointer);
Register_Object(connection);
AddConnection(connection);
connection = new
GaugeConnectionDirectOf<Quaternion *>(
0, &currentAngularPointer, 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();
}