#ifdef HAVE_CONFIG_H # include <config.h> #endif #ifdef HAVE_WINDOWS_H # include <windows.h> #endif #include <stdlib.h> #include <string.h> #include <Aircraft/aircraft.hxx> #include <Debug/fg_debug.h> #include <Include/fg_constants.h> #include <Math/fg_random.h> #include <Math/mat3.h> #include <Math/polar3d.hxx> #include <Scenery/scenery.hxx> #include <Time/fg_timer.hxx> #include "hud.hxx" //====================== Top of HudLadder Class ======================= HudLadder :: HudLadder( int x, int y, UINT width, UINT height, DBLFNPTR ptch_source, DBLFNPTR roll_source, double span_units, double major_div, double minor_div, UINT screen_hole, UINT lbl_pos, bool working) : dual_instr_item( x, y, width, height, ptch_source, roll_source, working, HUDS_RIGHT), width_units ( span_units ), div_units ( major_div < 0? -major_div: major_div ), minor_div ( minor_div ), label_pos ( lbl_pos ), scr_hole ( screen_hole ), vmax ( span_units/2 ), vmin ( -vmax ) { if( !width_units ) { width_units = 45; } factor = (double)get_span() / (double) width_units; } HudLadder :: ~HudLadder() { } HudLadder :: HudLadder( const HudLadder & image ) : dual_instr_item( (dual_instr_item &) image), width_units ( image.width_units ), div_units ( image.div_units ), label_pos ( image.label_pos ), scr_hole ( image.scr_hole ), vmax ( image.vmax ), vmin ( image.vmin ), factor ( image.factor ) { } HudLadder & HudLadder :: operator = ( const HudLadder & rhs ) { if( !(this == &rhs)) { (dual_instr_item &)(*this) = (dual_instr_item &)rhs; width_units = rhs.width_units; div_units = rhs.div_units; label_pos = rhs.label_pos; scr_hole = rhs.scr_hole; vmax = rhs.vmax; vmin = rhs.vmin; factor = rhs.factor; } return *this; } // // Draws a climb ladder in the center of the HUD // void HudLadder :: draw( void ) { double roll_value; double pitch_value; int marker_y; int x_ini; int x_end; int y_ini; int y_end; int new_x_ini; int new_x_end; int new_y_ini; int new_y_end; int i; POINT centroid = get_centroid(); RECT box = get_location(); int scr_min = box.top; int half_span = box.right >> 1; char TextLadder[80]; int condition; int label_length; roll_value = current_ch2(); GLfloat sinRoll = sin( roll_value ); GLfloat cosRoll = cos( roll_value ); pitch_value = current_ch1() * RAD_TO_DEG; vmin = pitch_value - (double)width_units/2.0; vmax = pitch_value + (double)width_units/2.0; // Box the target. drawOneLine( centroid.x - 5, centroid.y, centroid.x, centroid.y + 5); drawOneLine( centroid.x, centroid.y + 5, centroid.x + 5, centroid.y); drawOneLine( centroid.x + 5, centroid.y, centroid.x, centroid.y - 5); drawOneLine( centroid.x, centroid.y - 5, centroid.x - 5, centroid.y); for( i=(int)vmin; i<=(int)vmax; i++ ) { // Through integer pitch values... condition = 1; if( condition ) { marker_y = centroid.y + (int)(((double)(i - pitch_value) * factor) + .5); if( div_units ) { if( !(i % div_units )) { // At integral multiple of div sprintf( TextLadder, "%d", i ); label_length = strlen( TextLadder ); if( scr_hole == 0 ) { if( i ) { x_ini = centroid.x - half_span; } else { // Make zero point wider on left x_ini = centroid.x - half_span - 10; } y_ini = marker_y; x_end = centroid.x + half_span; y_end = marker_y; new_x_ini = centroid.x + (int)( (x_ini - centroid.x) * cosRoll - (y_ini - centroid.y) * sinRoll); new_y_ini = centroid.y + (int)( \ (x_ini - centroid.x) * sinRoll + \ (y_ini - centroid.y) * cosRoll); new_x_end = centroid.x + (int)( \ (x_end - centroid.x) * cosRoll - \ (y_end - centroid.y) * sinRoll); new_y_end = centroid.y + (int)( \ (x_end - centroid.x) * sinRoll + \ (y_end - centroid.y) * cosRoll); if( i >= 0 ) { // Above zero draw solid lines drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end ); } else { // Below zero draw dashed lines. glEnable(GL_LINE_STIPPLE); glLineStipple( 1, 0x00FF ); drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end ); glDisable(GL_LINE_STIPPLE); } // Calculate the position of the left text and write it. new_x_ini = centroid.x + (int)( (x_ini - 8 * label_length- 4 - centroid.x) * cosRoll - (y_ini - 4 ) * sinRoll); new_y_ini = centroid.y + (int)( (x_ini - 8 * label_length- 4 - centroid.x) * sinRoll + (y_ini - 4 - centroid.y) * cosRoll); strokeString( new_x_ini , new_y_ini , TextLadder, GLUT_STROKE_ROMAN, roll_value ); // Calculate the position of the right text and write it. new_x_end = centroid.x + (int)( \ (x_end + 24 - 8 * label_length - centroid.x) * cosRoll - \ (y_end - 4 - centroid.y) * sinRoll); new_y_end = centroid.y + (int)( \ (x_end + 24 - 8 * label_length - centroid.x) * sinRoll + \ (y_end - 4 - centroid.y) * cosRoll); strokeString( new_x_end, new_y_end, TextLadder, GLUT_STROKE_ROMAN, roll_value ); } else { // Draw ladder with space in the middle of the lines // Start by calculating the points and drawing the // left side lines. if( i != 0 ) { x_ini = centroid.x - half_span; } else { x_ini = centroid.x - half_span - 10; } y_ini = marker_y; x_end = centroid.x - half_span + scr_hole/2; y_end = marker_y; new_x_end = centroid.x+ (int)( \ (x_end - centroid.x) * cosRoll -\ (y_end - centroid.y) * sinRoll); new_y_end = centroid.y+ (int)( \ (x_end - centroid.x) * sinRoll +\ (y_end - centroid.y) * cosRoll); new_x_ini = centroid.x + (int)( \ (x_ini - centroid.x) * cosRoll -\ (y_ini - centroid.y) * sinRoll); new_y_ini = centroid.y + (int)( \ (x_ini - centroid.x) * sinRoll +\ (y_ini - centroid.y) * cosRoll); if( i >= 0 ) { drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end ); } else { glEnable(GL_LINE_STIPPLE); glLineStipple( 1, 0x00FF ); drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end ); glDisable(GL_LINE_STIPPLE); } // Now calculate the location of the left side label using // the previously calculated start of the left side line. x_ini = x_ini - (label_length + 32 + centroid.x); if( i < 0) { x_ini -= 8; } else { if( i == 0 ) { x_ini += 20; } } y_ini = y_ini - ( 4 + centroid.y); new_x_ini = centroid.x + (int)(x_ini * cosRoll - y_ini * sinRoll); new_y_ini = centroid.y + (int)(x_ini * sinRoll + y_ini * cosRoll); strokeString( new_x_ini , new_y_ini , TextLadder, GLUT_STROKE_MONO_ROMAN, roll_value ); // Now calculate and draw the right side line location x_ini = centroid.x + half_span - scr_hole/2; y_ini = marker_y; if( i != 0 ) { x_end = centroid.x + half_span; } else { x_end = centroid.x + half_span + 10; } y_end = marker_y; new_x_ini = centroid.x + (int)( \ (x_ini-centroid.x)*cosRoll -\ (y_ini-centroid.y)*sinRoll); new_y_ini = centroid.y + (int)( \ (x_ini-centroid.x)*sinRoll +\ (y_ini-centroid.y)*cosRoll); new_x_end = centroid.x + (int)( \ (x_end-centroid.x)*cosRoll -\ (y_end-centroid.y)*sinRoll); new_y_end = centroid.y + (int)( \ (x_end-centroid.x)*sinRoll +\ (y_end-centroid.y)*cosRoll); if( i >= 0 ) { drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end ); } else { glEnable(GL_LINE_STIPPLE); glLineStipple( 1, 0x00FF ); drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end ); glDisable(GL_LINE_STIPPLE); } // Calculate the location and draw the right side label // using the end of the line as previously calculated. x_end -= centroid.x + label_length - 24; if( i < 0 ) { x_end -= 8; } y_end = marker_y - ( 4 + centroid.y); new_x_end = centroid.x + (int)( (GLfloat)x_end * cosRoll - (GLfloat)y_end * sinRoll); new_y_end = centroid.y + (int)( (GLfloat)x_end * sinRoll + (GLfloat)y_end * cosRoll); strokeString( new_x_end, new_y_end, TextLadder, GLUT_STROKE_MONO_ROMAN, roll_value ); } } } } } }