#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 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 *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; ipixelMap8Bin.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 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 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; ipixelMap8Bin.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 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 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; icenter, 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; idirection.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 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(0, ¤tScale, scale_value_pointer); Register_Object(connection); AddConnection(connection); connection = new GaugeConnectionDirectOf( 0, ¤tPositionPointer, position_pointer); Register_Object(connection); AddConnection(connection); connection = new GaugeConnectionDirectOf( 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 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 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 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; iExtractFromEntity(entity, worldToView); } //---------------------------------------------------------- // Generate display positions //---------------------------------------------------------- NavName::CalculatePositions(nameArray, count); //---------------------------------------------------------- // Draw names //---------------------------------------------------------- for( i=0, nav_name=nameArray; iDraw(&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 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 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 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 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; ibitMapBin.Release(font_name); Check_Fpu(); } Ranking::~Ranking() { Test_Tell("Ranking destructor\n" << std::flush); Check(this); int i; // //----------------------------------------------------------- // Delete sub-gauges //----------------------------------------------------------- // for(i=0; iForceUpdate(); } } } 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 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; iErase(&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; iErase(&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; iErase(&localView); previousChannel[i] = Icom::undefinedChannel; } } } else { for(i=0; iErase(&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 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 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(); }