1 // hud.cxx -- hud defines and prototypes
3 // Written by Michele America, started September 1997.
5 // Copyright (C) 1997 Michele F. America - micheleamerica@geocities.com
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include <simgear/compiler.h>
24 #include <simgear/misc/exception.hxx>
38 # define exception c_exception
45 #include <stdio.h> // char related functions
46 #include <string.h> // strcmp()
48 #include <simgear/constants.h>
49 #include <simgear/debug/logstream.hxx>
50 #include <simgear/misc/props.hxx>
51 #include <simgear/misc/sg_path.hxx>
52 //#include <simgear/math/fg_random.h>
53 //#include <simgear/math/polar3d.hxx>
55 #include <Aircraft/aircraft.hxx>
56 #include <Autopilot/newauto.hxx>
58 #include <Main/globals.hxx>
59 #include <Main/fg_props.hxx>
61 #include <NetworkOLK/network.h>
63 #include <Scenery/scenery.hxx>
64 //#include <Time/fg_timer.hxx>
66 #if defined ( __sun__ ) || defined ( __sgi )
68 extern void *memmove(void *, const void *, size_t);
76 // The following routines obtain information concerning the aircraft's
77 // current state and return it to calling instrument display routines.
78 // They should eventually be member functions of the aircraft.
81 deque< instr_item * > HUD_deque;
83 fgTextList HUD_TextList;
84 fgLineList HUD_LineList;
85 fgLineList HUD_StippleLineList;
87 fntRenderer *HUDtext = 0;
88 float HUD_TextSize = 0;
92 static float hud_trans_alpha = 0.67f;
95 //$$$ begin - added, Neetha, 28 Nov 2k
103 static float span_units;
104 static float division_units;
105 static float minor_division = 0;
106 static UINT screen_hole;
109 static string loadfn;
111 static float maxValue;
112 static float minValue;
113 static float scaling;
114 static UINT major_divs;
115 static UINT minor_divs;
116 static UINT modulator;
117 static int dp_showing = 0;
118 static string label_format;
119 static string prelabel;
120 static string postlabel;
123 static float maxBankAngle;
124 static float maxSlipAngle;
125 static UINT gap_width;
126 static bool latitude;
127 static bool longitude;
128 static bool tick_bottom;
129 static bool tick_top;
130 static bool tick_right;
131 static bool tick_left;
132 static bool cap_bottom;
134 static bool cap_right;
135 static bool cap_left;
136 static float marker_off;
138 static bool enable_pointer;
139 static string type_pointer;
140 static bool frl_spot;
142 static bool vel_vector;
146 static bool climb_dive;
148 static float glide_slope_val;
149 static bool worm_energy;
150 static bool waypoint;
151 static string type_tick;//hud
152 static string length_tick;//hud
153 static bool label_box;//hud
154 static int digits; //suma
155 static float radius; //suma
156 static int divisions; //suma
157 static int zoom; //suma
158 static int zenith; //suma
159 static int nadir ; //suma
160 static int hat; //suma
161 static bool tsi; //suma
162 static float rad; //suma
165 static FLTFNPTR load_fn;
166 static fgLabelJust justification;
167 static const char *pre_label_string = 0;
168 static const char *post_label_string = 0;
170 int readHud( istream &input );
171 int readInstrument ( const SGPropertyNode * node);
172 static instr_item * readLadder ( const SGPropertyNode * node);
173 static instr_item * readCard ( const SGPropertyNode * node);
174 static instr_item * readLabel( const SGPropertyNode * node);
175 static instr_item * readTBI( const SGPropertyNode * node);
176 //$$$ end - added, Neetha, 28 Nov 2k
178 static void drawHUD();
179 static void fgUpdateHUDVirtual();
181 void fgHUDalphaInit( void );
187 locRECT( UINT left, UINT top, UINT right, UINT bottom);
188 RECT get_rect(void) { return rect;}
191 locRECT :: locRECT( UINT left, UINT top, UINT right, UINT bottom)
196 rect.bottom = bottom;
201 //========================= End of Class Implementations===================
204 // Constructs a HUD object and then adds in instruments. At the present
205 // the instruments are hard coded into the routine. Ultimately these need
206 // to be defined by the aircraft's instrumentation records so that the
207 // display for a Piper Cub doesn't show the speed range of a North American
208 // mustange and the engine readouts of a B36!
213 //$$$ begin - added, Neetha, 28 Nov 2k
215 readLadder(const SGPropertyNode * node)
220 name = node->getStringValue("name");
221 x = node->getIntValue("x");
222 y = node->getIntValue("y");
223 width = node->getIntValue("width");
224 height = node->getIntValue("height");
225 factor = node->getFloatValue("compression_factor");
226 span_units = node->getFloatValue("span_units");
227 division_units = node->getFloatValue("division_units");
228 screen_hole = node->getIntValue("screen_hole");
229 lbl_pos = node->getIntValue("lbl_pos");
230 frl_spot = node->getBoolValue("enable_frl",false);
231 target = node->getBoolValue("enable_target_spot",false);
232 vel_vector = node->getBoolValue("enable_velocity_vector",false);
233 drift = node->getBoolValue("enable_drift_marker",false);
234 alpha = node->getBoolValue("enable_alpha_bracket",false);
235 energy = node->getBoolValue("enable_energy_marker",false);
236 climb_dive = node->getBoolValue("enable_climb_dive_marker",false);
237 glide = node->getBoolValue("enable_glide_slope_marker",false);
238 glide_slope_val = node->getFloatValue("glide_slope",-4.0);
239 worm_energy = node->getBoolValue("enable_energy_marker",false);
240 waypoint = node->getBoolValue("enable_waypoint_marker",false);
241 working = node->getBoolValue("working");
242 zenith = node->getIntValue("zenith"); //suma
243 nadir = node->getIntValue("nadir"); //suma
244 hat = node->getIntValue("hat");
245 // The factor assumes a base of 55 degrees per 640 pixels.
246 // Invert to convert the "compression" factor to a
247 // pixels-per-degree number.
252 factor = (640./55.) / factor;
255 SG_LOG(SG_INPUT, SG_INFO, "Done reading instrument " << name);
257 p = (instr_item *) new HudLadder( name, x, y,
258 width, height, factor,
260 span_units, division_units, minor_division,
261 screen_hole, lbl_pos, frl_spot, target, vel_vector,
262 drift, alpha, energy, climb_dive,
263 glide, glide_slope_val, worm_energy,
264 waypoint, working, zenith, nadir, hat);
271 readCard(const SGPropertyNode * node)
276 name = node->getStringValue("name");
277 x = node->getIntValue("x");
278 y = node->getIntValue("y");
279 width = node->getIntValue("width");
280 height = node->getIntValue("height");
281 loadfn = node->getStringValue("loadfn");
282 options = node->getIntValue("options");
283 maxValue = node->getFloatValue("maxValue");
284 minValue = node->getFloatValue("minValue");
285 scaling = node->getFloatValue("disp_scaling");
286 major_divs = node->getIntValue("major_divs");
287 minor_divs = node->getIntValue("minor_divs");
288 modulator = node->getIntValue("modulator");
289 span_units = node->getFloatValue("value_span");
290 type = node->getStringValue("type");
291 tick_bottom = node->getBoolValue("tick_bottom",false);
292 tick_top = node->getBoolValue("tick_top",false);
293 tick_right = node->getBoolValue("tick_right",false);
294 tick_left = node->getBoolValue("tick_left",false);
295 cap_bottom = node->getBoolValue("cap_bottom",false);
296 cap_top = node->getBoolValue("cap_top",false);
297 cap_right = node->getBoolValue("cap_right",false);
298 cap_left = node->getBoolValue("cap_left",false);
299 marker_off = node->getFloatValue("marker_offset",0.0);
300 enable_pointer = node->getBoolValue("enable_pointer",true);
301 type_pointer = node->getStringValue("pointer_type");
302 type_tick = node->getStringValue("tick_type");//hud Can be 'circle' or 'line'
303 length_tick = node->getStringValue("tick_length");//hud For variable length
304 working = node->getBoolValue("working");
305 radius = node->getFloatValue("radius"); //suma
306 divisions = node->getIntValue("divisions"); //suma
307 zoom = node->getIntValue("zoom"); //suma
309 SG_LOG(SG_INPUT, SG_INFO, "Done reading instrument " << name);
313 span_units = maxValue - minValue;
316 if (loadfn=="anzg") {
318 } else if (loadfn=="heading") {
319 load_fn = get_heading;
320 } else if (loadfn=="aoa") {
322 } else if (loadfn=="climb") {
323 load_fn = get_climb_rate;
324 } else if (loadfn=="altitude") {
325 load_fn = get_altitude;
326 } else if (loadfn=="agl") {
328 } else if (loadfn=="speed") {
330 } else if (loadfn=="view_direction") {
331 load_fn = get_view_direction;
332 } else if (loadfn=="aileronval") {
333 load_fn = get_aileronval;
334 } else if (loadfn=="elevatorval") {
335 load_fn = get_elevatorval;
336 } else if (loadfn=="elevatortrimval") {
337 load_fn = get_elev_trimval;
338 } else if (loadfn=="rudderval") {
339 load_fn = get_rudderval;
340 } else if (loadfn=="throttleval") {
341 load_fn = get_throttleval;
345 if ( (type == "dial") | (type == "tape") ) {
346 p = (instr_item *) new hud_card( x,
354 major_divs, minor_divs,
378 p = (instr_item *) new gauge_instr( x, // x
382 load_fn, // data source
386 major_divs, minor_divs,
396 readLabel(const SGPropertyNode * node)
400 int font_size = (fgGetInt("/sim/startup/xsize") > 1000) ? HUD_FONT_LARGE : HUD_FONT_SMALL;
402 name = node->getStringValue("name");
403 x = node->getIntValue("x");
404 y = node->getIntValue("y");
405 width = node->getIntValue("width");
406 height = node->getIntValue("height");
407 loadfn = node->getStringValue("data_source");
408 label_format = node->getStringValue("label_format");
409 prelabel = node->getStringValue("pre_label_string");
410 postlabel = node->getStringValue("post_label_string");
411 scaling = node->getFloatValue("scale_data");
412 options = node->getIntValue("options");
413 justi = node->getIntValue("justification");
414 blinking = node->getIntValue("blinking");
415 latitude = node->getBoolValue("latitude",false);
416 longitude = node->getBoolValue("longitude",false);
417 label_box = node->getBoolValue("label_box",false);//hud
418 working = node->getBoolValue("working");
419 digits = node->getIntValue("digits"); //suma
422 SG_LOG(SG_INPUT, SG_INFO, "Done reading instrument " << name);
426 justification = LEFT_JUST;
429 justification = CENTER_JUST;
432 justification = RIGHT_JUST;
437 if ( prelabel == "NULL" ) {
438 pre_label_string = NULL;
440 if ( prelabel == "blank" ) {
441 pre_label_string = " ";
443 pre_label_string = prelabel.c_str();
447 if ( postlabel == "blank" ) {
448 post_label_string = " ";
450 if ( postlabel == "NULL" ) {
451 post_label_string = NULL;
453 if ( postlabel == "units" ) {
454 post_label_string = units;
456 post_label_string = postlabel.c_str();
461 if ( loadfn== "aux1" ) {
463 } else if ( loadfn == "aux2" ) {
465 } else if ( loadfn == "aux3" ) {
467 } else if ( loadfn == "aux4" ) {
469 } else if ( loadfn == "aux5" ) {
471 } else if ( loadfn == "aux6" ) {
473 } else if ( loadfn == "aux7" ) {
475 } else if ( loadfn == "aux8" ) {
477 } else if ( loadfn == "aux9" ) {
479 } else if ( loadfn == "aux10" ) {
481 } else if ( loadfn == "aux11" ) {
483 } else if ( loadfn == "aux12" ) {
485 } else if ( loadfn == "aux13" ) {
487 } else if ( loadfn == "aux14" ) {
489 } else if ( loadfn == "aux15" ) {
491 } else if ( loadfn == "aux16" ) {
493 } else if ( loadfn == "aux17" ) {
495 } else if ( loadfn == "aux18" ) {
497 } else if ( loadfn == "ax" ) {
499 } else if ( loadfn == "speed" ) {
501 } else if ( loadfn == "mach" ) {
503 } else if ( loadfn == "altitude" ) {
504 load_fn = get_altitude;
505 } else if ( loadfn == "agl" ) {
507 } else if ( loadfn == "framerate" ) {
508 load_fn = get_frame_rate;
509 } else if ( loadfn == "heading" ) {
510 load_fn = get_heading;
511 } else if ( loadfn == "fov" ) {
513 } else if ( loadfn == "vfc_tris_culled" ) {
514 load_fn = get_vfc_tris_culled;
515 } else if ( loadfn == "vfc_tris_drawn" ) {
516 load_fn = get_vfc_tris_drawn;
517 } else if ( loadfn == "aoa" ) {
519 } else if ( loadfn == "latitude" ) {
520 load_fn = get_latitude;
521 } else if ( loadfn == "anzg" ) {
523 } else if ( loadfn == "longitude" ) {
524 load_fn = get_longitude;
525 } else if (loadfn=="throttleval") {
526 load_fn = get_throttleval;
529 p = (instr_item *) new instr_label ( x,
534 label_format.c_str(),
552 readTBI(const SGPropertyNode * node)
557 name = node->getStringValue("name");
558 x = node->getIntValue("x");
559 y = node->getIntValue("y");
560 width = node->getIntValue("width");
561 height = node->getIntValue("height");
562 maxBankAngle = node->getFloatValue("maxBankAngle");
563 maxSlipAngle = node->getFloatValue("maxSlipAngle");
564 gap_width = node->getIntValue("gap_width");
565 working = node->getBoolValue("working");
566 tsi = node->getBoolValue("tsi"); //suma
567 rad = node->getFloatValue("rad"); //suma
569 SG_LOG(SG_INPUT, SG_INFO, "Done reading instrument " << name);
572 p = (instr_item *) new fgTBI_instr( x,
589 int readInstrument(const SGPropertyNode * node)
591 static const SGPropertyNode *startup_units_node
592 = fgGetNode("/sim/startup/units");
596 if ( !strcmp(startup_units_node->getStringValue(), "feet") ) {
597 strcpy(units, " ft");
602 const SGPropertyNode * ladder_group = node->getNode("ladders");
604 if (ladder_group != 0) {
605 int nLadders = ladder_group->nChildren();
606 for (int j = 0; j < nLadders; j++) {
608 HIptr = readLadder(ladder_group->getChild(j));
609 HUD_deque.insert( HUD_deque.begin(), HIptr);
614 const SGPropertyNode * card_group = node->getNode("cards");
615 if (card_group != 0) {
616 int nCards = card_group->nChildren();
617 for (int j = 0; j < nCards; j++) {
619 HIptr = readCard(card_group->getChild(j));
620 HUD_deque.insert( HUD_deque.begin(), HIptr);
625 const SGPropertyNode * label_group = node->getNode("labels");
626 if (label_group != 0) {
627 int nLabels = label_group->nChildren();
628 for (int j = 0; j < nLabels; j++) {
630 HIptr = readLabel(label_group->getChild(j));
631 HUD_deque.insert( HUD_deque.begin(), HIptr);
636 const SGPropertyNode * tbi_group = node->getNode("tbis");
637 if (tbi_group != 0) {
638 int nTbis = tbi_group->nChildren();
639 for (int j = 0; j < nTbis; j++) {
641 HIptr = readTBI(tbi_group->getChild(j));
642 HUD_deque.insert( HUD_deque.begin(), HIptr);
647 }//end readinstrument
650 int readHud( istream &input )
656 readProperties(input, &root);
657 } catch (const sg_exception &e) {
658 guiErrorMessage("Error reading HUD: ", e);
663 SG_LOG(SG_INPUT, SG_INFO, "Read properties for " <<
664 root.getStringValue("name"));
667 HUD_deque.erase( HUD_deque.begin(), HUD_deque.end()); // empty the HUD deque
670 SG_LOG(SG_INPUT, SG_INFO, "Reading Hud instruments");
672 const SGPropertyNode * instrument_group = root.getChild("instruments");
673 int nInstruments = instrument_group->nChildren();
675 for (int i = 0; i < nInstruments; i++) {
677 const SGPropertyNode * node = instrument_group->getChild(i);
679 SGPath path( globals->get_fg_root() );
680 path.append(node->getStringValue("path"));
682 SG_LOG(SG_INPUT, SG_INFO, "Reading Instrument "
687 SGPropertyNode root2;
689 readProperties(path.str(), &root2);
690 } catch (const sg_exception &e) {
691 guiErrorMessage("Error reading HUD instrument: ", e);
694 readInstrument(&root2);
701 int fgHUDInit( fgAIRCRAFT * /* current_aircraft */ )
706 SG_LOG( SG_COCKPIT, SG_INFO, "Initializing current aircraft HUD" );
709 fgGetString("/sim/hud/path", "Huds/Default/default.xml");
710 SGPath path(globals->get_fg_root());
711 path.append(hud_path);
713 ifstream input(path.c_str());
715 SG_LOG(SG_INPUT, SG_ALERT,
716 "Cannot read Hud configuration from " << path.str());
726 // this chunk of code is not necessarily thread safe if the
727 // compiler optimizer reorders these statements. Note that
728 // "delete ptr" does not set "ptr = NULL". We have to do that
730 fntRenderer *tmp = HUDtext;
735 // HUD_TextSize = fgGetInt("/sim/startup/xsize") / 60;
737 HUDtext = new fntRenderer();
738 HUDtext -> setFont ( guiFntHandle ) ;
739 HUDtext -> setPointSize ( HUD_TextSize ) ;
740 HUD_TextList.setFont( HUDtext );
742 return 0; // For now. Later we may use this for an error code.
746 int fgHUDInit2( fgAIRCRAFT * /* current_aircraft */ )
751 SG_LOG( SG_COCKPIT, SG_INFO, "Initializing current aircraft HUD" );
753 SGPath path(globals->get_fg_root());
754 path.append("Huds/Minimal/default.xml");
757 ifstream input(path.c_str());
759 SG_LOG(SG_INPUT, SG_ALERT,
760 "Cannot read Hud configuration from " << path.str());
766 return 0; // For now. Later we may use this for an error code.
769 //$$$ End - added, Neetha, 28 Nov 2k
771 static int global_day_night_switch = HUD_DAY;
773 void HUD_masterswitch( bool incr )
775 if ( fgGetBool("/sim/hud/visibility") ) {
776 if ( global_day_night_switch == HUD_DAY ) {
777 global_day_night_switch = HUD_NIGHT;
779 fgSetBool("/sim/hud/visibility", false);
782 fgSetBool("/sim/hud/visibility", true);
783 global_day_night_switch = HUD_DAY;
787 void HUD_brightkey( bool incr_bright )
789 instr_item *pHUDInstr = HUD_deque[0];
790 int brightness = pHUDInstr->get_brightness();
792 if( fgGetBool("/sim/hud/visibility") ) {
797 brightness = HUD_BRT_BLACK;
801 brightness = HUD_BRT_LIGHT;
805 brightness = HUD_BRT_MEDIUM;
809 brightness = HUD_BRT_DARK;
813 brightness = HUD_BRT_BLACK;
819 brightness = HUD_BRT_MEDIUM;
823 brightness = HUD_BRT_DARK;
827 brightness = HUD_BRT_BLACK;
831 brightness = HUD_BRT_LIGHT;
835 fgSetBool("/sim/hud/visibility", false);
839 fgSetBool("/sim/hud/visibility", true);
842 pHUDInstr->SetBrightness( brightness );
846 #define fgAP_CLAMP(val,min,max) ( (val) = (val) > (max) ? (max) : (val) < (min) ? (min) : (val) )
848 static puDialogBox *HUDalphaDialog;
849 static puText *HUDalphaText;
850 static puSlider *HUDalphaHS0;
851 //static puText *HUDtextText;
852 //static puSlider *HUDalphaHS1;
853 static char SliderText[2][ 8 ];
855 static void alpha_adj( puObject *hs ) {
858 hs-> getValue ( &val ) ;
859 fgAP_CLAMP ( val, 0.1, 1.0 ) ;
860 // printf ( "maxroll_adj( %p ) %f %f\n", hs, val, MaxRollAdjust * val ) ;
861 hud_trans_alpha = val;
862 sprintf( SliderText[ 0 ], "%05.2f", hud_trans_alpha );
863 HUDalphaText -> setLabel ( SliderText[ 0 ] ) ;
866 void fgHUDalphaAdjust( puObject * ) {
867 fgSetBool("/sim/hud/antialiased", true);
868 FG_PUSH_PUI_DIALOG( HUDalphaDialog );
871 static void goAwayHUDalphaAdjust (puObject *)
873 FG_POP_PUI_DIALOG( HUDalphaDialog );
876 static void cancelHUDalphaAdjust (puObject *)
878 fgSetBool("/sim/hud/antialiased", false);
879 FG_POP_PUI_DIALOG( HUDalphaDialog );
882 // Done once at system initialization
883 void fgHUDalphaInit( void ) {
885 // printf("fgHUDalphaInit\n");
886 #define HORIZONTAL FALSE
890 int DialogWidth = 240;
892 char Label[] = "HUD Adjuster";
895 int labelX = (DialogWidth / 2) -
896 ( puGetDefaultLabelFont().getStringWidth( Label ) / 2);
901 int slider_width = 220;
902 int slider_title_x = 15;
903 int slider_value_x = 160;
904 float slider_delta = 0.05f;
906 puFont HUDalphaLegendFont;
907 puFont HUDalphaLabelFont;
908 puGetDefaultFonts ( &HUDalphaLegendFont, &HUDalphaLabelFont );
910 HUDalphaDialog = new puDialogBox ( DialogX, DialogY ); {
911 int horiz_slider_height = HUDalphaLabelFont.getStringHeight() +
912 HUDalphaLabelFont.getStringDescender() +
913 PUSTR_TGAP + PUSTR_BGAP + 5;
916 HUDalphaFrame = new puFrame ( 0, 0, DialogWidth,
918 * horiz_slider_height ); */
921 HUDalphaDialogMessage = new puText ( labelX,
923 * horiz_slider_height );
924 HUDalphaDialogMessage -> setDefaultValue ( Label );
925 HUDalphaDialogMessage -> getDefaultValue ( &s );
926 HUDalphaDialogMessage -> setLabel ( s );
928 HUDalphaHS0 = new puSlider ( slider_x, slider_y,
929 slider_width, HORIZONTAL ) ;
930 HUDalphaHS0-> setDelta ( slider_delta ) ;
931 HUDalphaHS0-> setValue ( hud_trans_alpha ) ;
932 HUDalphaHS0-> setCBMode ( PUSLIDER_DELTA ) ;
933 HUDalphaHS0-> setCallback ( alpha_adj ) ;
936 HUDalphaTitle = new puText ( slider_title_x, slider_y ) ;
937 HUDalphaTitle-> setDefaultValue ( "Alpha" ) ;
938 HUDalphaTitle-> getDefaultValue ( &s ) ;
939 HUDalphaTitle-> setLabel ( s ) ;
941 HUDalphaText = new puText ( slider_value_x, slider_y ) ;
942 sprintf( SliderText[ 0 ], "%05.2f", hud_trans_alpha );
943 HUDalphaText-> setLabel ( SliderText[ 0 ] ) ;
946 HUDalphaOkButton = new puOneShot ( 10, 10, 60, 45 );
947 HUDalphaOkButton-> setLegend ( gui_msg_OK );
948 HUDalphaOkButton-> makeReturnDefault ( TRUE );
949 HUDalphaOkButton-> setCallback ( goAwayHUDalphaAdjust );
952 HUDalphaNoButton = new puOneShot ( 160, 10, 230, 45 );
953 HUDalphaNoButton-> setLegend ( gui_msg_CANCEL );
954 HUDalphaNoButton-> setCallback ( cancelHUDalphaAdjust );
956 FG_FINALIZE_PUI_DIALOG( HUDalphaDialog );
962 void fgHUDReshape(void) {
965 // this chunk of code is not necessarily thread safe if the
966 // compiler optimizer reorders these statements. Note that
967 // "delete ptr" does not set "ptr = NULL". We have to do that
969 fntRenderer *tmp = HUDtext;
974 HUD_TextSize = fgGetInt("/sim/startup/xsize") / 60;
976 HUDtext = new fntRenderer();
977 HUDtext -> setFont ( guiFntHandle ) ;
978 HUDtext -> setPointSize ( HUD_TextSize ) ;
979 HUD_TextList.setFont( HUDtext );
984 static void set_hud_color(float r, float g, float b) {
985 fgGetBool("/sim/hud/antialiased") ?
986 glColor4f(r,g,b,hud_trans_alpha) :
993 // Performs a once around the list of calls to instruments installed in
994 // the HUD object with requests for redraw. Kinda. It will when this is
997 void fgUpdateHUD( void ) {
1001 fgUpdateHUDVirtual();
1005 static const float normal_aspect = float(640) / float(480);
1006 // note: aspect_ratio is Y/X
1007 float current_aspect = 1.0f/globals->get_current_view()->get_aspect_ratio();
1008 if( current_aspect > normal_aspect ) {
1009 float aspect_adjust = current_aspect / normal_aspect;
1010 float adjust = 320.0f*aspect_adjust - 320.0f;
1011 fgUpdateHUD( -adjust, 0.0f, 640.0f+adjust, 480.0f );
1013 float aspect_adjust = normal_aspect / current_aspect;
1014 float adjust = 240.0f*aspect_adjust - 240.0f;
1015 fgUpdateHUD( 0.0f, -adjust, 640.0f, 480.0f+adjust );
1019 void fgUpdateHUDVirtual()
1021 FGViewer* view = globals->get_current_view();
1023 // Standard fgfs projection, with essentially meaningless clip
1024 // planes (we'll map the whole HUD plane to z=-1)
1025 glMatrixMode(GL_PROJECTION);
1028 gluPerspective(view->get_v_fov(), 1/view->get_aspect_ratio(), 0.1, 10);
1030 glMatrixMode(GL_MODELVIEW);
1034 // Standard fgfs view direction computation
1036 lookat[0] = -sin(SG_DEGREES_TO_RADIANS * view->getHeadingOffset_deg());
1037 lookat[1] = tan(SG_DEGREES_TO_RADIANS * view->getPitchOffset_deg());
1038 lookat[2] = -cos(SG_DEGREES_TO_RADIANS * view->getHeadingOffset_deg());
1039 if(fabs(lookat[1]) > 9999) lookat[1] = 9999; // FPU sanity
1040 gluLookAt(0, 0, 0, lookat[0], lookat[1], lookat[2], 0, 1, 0);
1042 // Map the -1:1 square to a 55.0x41.25 degree wide patch at z=1.
1043 // This is the default fgfs field of view, which the HUD files are
1044 // written to assume.
1045 float dx = 0.52056705; // tan(55/2)
1046 float dy = dx * 0.75; // assumes 4:3 aspect ratio
1048 m[0] = dx; m[4] = 0; m[ 8] = 0; m[12] = 0;
1049 m[1] = 0; m[5] = dy; m[ 9] = 0; m[13] = 0;
1050 m[2] = 0; m[6] = 0; m[10] = 1; m[14] = 0;
1051 m[3] = 0; m[7] = 0; m[11] = 0; m[15] = 1;
1054 // Convert the 640x480 "HUD standard" coordinate space to a square
1055 // about the origin in the range [-1:1] at depth of -1
1056 glScalef(1./320, 1./240, 1);
1057 glTranslatef(-320, -240, -1);
1062 // Clean up our mess
1063 glMatrixMode(GL_PROJECTION);
1065 glMatrixMode(GL_MODELVIEW);
1069 void fgUpdateHUD( GLfloat x_start, GLfloat y_start,
1070 GLfloat x_end, GLfloat y_end )
1072 glMatrixMode(GL_PROJECTION);
1075 gluOrtho2D(x_start, x_end, y_start, y_end);
1077 glMatrixMode(GL_MODELVIEW);
1083 glMatrixMode(GL_PROJECTION);
1085 glMatrixMode(GL_MODELVIEW);
1091 if( !HUD_deque.size() ) { // Trust everyone, but ALWAYS cut the cards!
1095 HUD_TextList.erase();
1096 HUD_LineList.erase();
1097 // HUD_StippleLineList.erase();
1099 glDisable(GL_DEPTH_TEST);
1100 glDisable(GL_LIGHTING);
1102 static const SGPropertyNode * antialiased_node
1103 = fgGetNode("/sim/hud/antialiased");
1105 if( antialiased_node->getBoolValue() ) {
1106 glEnable(GL_LINE_SMOOTH);
1107 // glEnable(GL_BLEND);
1108 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
1109 glHint(GL_LINE_SMOOTH_HINT,GL_DONT_CARE);
1115 if( global_day_night_switch == HUD_DAY) {
1116 switch (HUD_deque[0]->get_brightness())
1119 set_hud_color (0.1f, 0.9f, 0.1f);
1122 case HUD_BRT_MEDIUM:
1123 set_hud_color (0.1f, 0.7f, 0.0f);
1127 set_hud_color (0.0f, 0.6f, 0.0f);
1131 set_hud_color( 0.0f, 0.0f, 0.0f);
1135 set_hud_color (0.1f, 0.9f, 0.1f);
1138 if( global_day_night_switch == HUD_NIGHT) {
1139 switch (HUD_deque[0]->get_brightness())
1142 set_hud_color (0.9f, 0.1f, 0.1f);
1145 case HUD_BRT_MEDIUM:
1146 set_hud_color (0.7f, 0.0f, 0.1f);
1150 set_hud_color (0.6f, 0.0f, 0.0f);
1154 set_hud_color( 0.0f, 0.0f, 0.0f);
1158 set_hud_color (0.6f, 0.0f, 0.0f);
1160 } else { // Just in case default
1161 set_hud_color (0.1f, 0.9f, 0.1f);
1165 for_each(HUD_deque.begin(), HUD_deque.end(), HUDdraw());
1167 HUD_TextList.add( fgText(40, 10, get_formated_gmt_time(), 0) );
1169 #ifdef FG_NETWORK_OLK
1170 if ( net_hud_display ) {
1177 // char scratch[128];
1178 // HUD_TextList.add( fgText( "AUTOPILOT", 20, apY) );
1180 FGAutopilot *AP = globals->get_autopilot();
1182 if( AP->get_HeadingEnabled() ) {
1183 HUD_TextList.add( fgText( 40, apY, AP->get_TargetHeadingStr()) );
1186 if( AP->get_AltitudeEnabled() ) {
1187 HUD_TextList.add( fgText( 40, apY, AP->get_TargetAltitudeStr()) );
1190 if( AP->get_HeadingMode() == FGAutopilot::FG_HEADING_WAYPOINT )
1192 if ( strlen( AP->get_TargetWP1Str() ) ) {
1193 HUD_TextList.add( fgText( 40, apY, AP->get_TargetWP1Str() ) );
1196 if ( strlen( AP->get_TargetWP2Str() ) ) {
1197 HUD_TextList.add( fgText( 40, apY, AP->get_TargetWP2Str() ) );
1200 if ( strlen( AP->get_TargetWP3Str() ) ) {
1201 HUD_TextList.add( fgText( 40, apY, AP->get_TargetWP3Str() ) );
1206 HUD_TextList.draw();
1208 HUD_LineList.draw();
1210 // glEnable(GL_LINE_STIPPLE);
1211 // glLineStipple( 1, 0x00FF );
1212 // HUD_StippleLineList.draw();
1213 // glDisable(GL_LINE_STIPPLE);
1215 if( antialiased_node->getBoolValue() ) {
1216 // glDisable(GL_BLEND);
1217 glDisable(GL_LINE_SMOOTH);
1221 glEnable(GL_DEPTH_TEST);
1222 glEnable(GL_LIGHTING);