]> git.mxchange.org Git - flightgear.git/blob - src/Main/keyboard.cxx
MSVC++ changes contributed by Geoff McLane.
[flightgear.git] / src / Main / keyboard.cxx
1 // keyboard.cxx -- handle GLUT keyboard events
2 //
3 // Written by Curtis Olson, started May 1997.
4 //
5 // Copyright (C) 1997 - 1999  Curtis L. Olson  - curt@flightgear.org
6 //
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.
11 //
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.
16 //
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.
20 //
21 // $Id$
22
23
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27
28 #ifdef HAVE_WINDOWS_H
29 #  include <windows.h>                     
30 #endif
31
32 #include <simgear/compiler.h>
33
34 #include <GL/glut.h>
35 #include <GL/gl.h>
36
37 #if defined(FX) && defined(XMESA)
38 #include <GL/xmesa.h>
39 #endif
40
41 #include <stdio.h>
42 #include <stdlib.h>
43
44 #include STL_FSTREAM
45
46 #include <plib/pu.h>            // plib include
47
48 #include <simgear/constants.h>
49 #include <simgear/debug/logstream.hxx>
50 #include <simgear/misc/sg_path.hxx>
51
52 #include <Aircraft/aircraft.hxx>
53 #include <Autopilot/auto_gui.hxx>
54 #include <Autopilot/newauto.hxx>
55 #include <Cockpit/hud.hxx>
56 #include <Cockpit/panel.hxx>
57 #include <Cockpit/panel_io.hxx>
58 #include <GUI/gui.h>
59 #include <Scenery/tilemgr.hxx>
60 #include <Objects/matlib.hxx>
61 #include <Time/light.hxx>
62 #include <Time/tmp.hxx>
63
64 #ifndef FG_OLD_WEATHER
65 #  include <WeatherCM/FGLocalWeatherDatabase.h>
66 #else
67 #  include <Weather/weather.hxx>
68 #endif
69
70 #include "bfi.hxx"
71 #include "globals.hxx"
72 #include "keyboard.hxx"
73 #include "fg_props.hxx"
74 #include "options.hxx"
75                                 // From main.cxx
76 extern void fgReshape( int width, int height );
77
78
79 #ifdef BOOL
80 #error A sloppy coder has defined BOOL as a macro!
81 #undef BOOL
82 #endif
83
84
85 /**
86  * Fire a user-defined key binding.
87  *
88  * <p>This function is temporary; eventually, all of the keyboard,
89  * joystick, and mouse support should migrate into a common Input
90  * module.</p>
91  *
92  * @param binding The property node for the binding.
93  */
94 static void
95 doBinding (const SGPropertyNode * binding)
96 {
97   const string &action = binding->getStringValue("action", "");
98   const string &control = binding->getStringValue("control", "");
99   bool repeatable = binding->getBoolValue("repeatable", false);
100   int step = binding->getIntValue("step", 0.0);
101
102   if (control == "") {
103     SG_LOG(SG_INPUT, SG_ALERT, "No control specified for key "
104            << binding->getIndex());
105     return;
106   }
107
108   else if (action == "") {
109     SG_LOG(SG_INPUT, SG_ALERT, "No action specified for key "
110            << binding->getIndex());
111     return;
112   }
113
114   else if (action == "switch") {
115     SG_LOG(SG_INPUT, SG_INFO, "Toggling value of " << control);
116     fgSetBool(control, !fgGetBool(control));
117   }
118
119   else if (action == "adjust") {
120     const SGValue * step = binding->getValue("value");
121     if (step == 0) {
122       SG_LOG(SG_INPUT, SG_ALERT, "No step supplied for adjust action for key "
123              << binding->getIndex());
124       return;
125     }
126     SGValue * target = fgGetValue(control, true);
127                                 // Use the target's type...
128     switch (target->getType()) {
129     case SGValue::BOOL:
130     case SGValue::INT:
131       target->setIntValue(target->getIntValue() + step->getIntValue());
132       break;
133     case SGValue::LONG:
134       target->setLongValue(target->getLongValue() + step->getLongValue());
135       break;
136     case SGValue::FLOAT:
137       target->setFloatValue(target->getFloatValue() + step->getFloatValue());
138       break;
139     case SGValue::DOUBLE:
140     case SGValue::UNKNOWN:      // treat unknown as a double
141       target->setDoubleValue(target->getDoubleValue()
142                              + step->getDoubleValue());
143       break;
144     case SGValue::STRING:
145       SG_LOG(SG_INPUT, SG_ALERT, "Failed attempt to adjust string property "
146              << control);
147       break;
148     }
149   }
150
151   else if (action == "assign") {
152     const SGValue * value = binding->getValue("value");
153     if (value == 0) {
154       SG_LOG(SG_INPUT, SG_ALERT, "No value supplied for assign action for key "
155              << binding->getIndex());
156       return;
157     }
158     SGValue * target = fgGetValue(control, true);
159                                 // Use the target's type...
160     switch (target->getType()) {
161     case SGValue::BOOL:
162       target->setBoolValue(value->getBoolValue());
163       break;
164     case SGValue::INT:
165       target->setIntValue(value->getIntValue());
166       break;
167     case SGValue::LONG:
168       target->setLongValue(value->getLongValue());
169       break;
170     case SGValue::FLOAT:
171       target->setFloatValue(value->getFloatValue());
172       break;
173     case SGValue::DOUBLE:
174       target->setDoubleValue(value->getDoubleValue());
175       break;
176     case SGValue::STRING:
177       target->setStringValue(value->getStringValue());
178       break;
179     case SGValue::UNKNOWN:
180       target->setUnknownValue(value->getStringValue());
181       break;
182     }
183   }
184
185   else {
186     SG_LOG(SG_INPUT, SG_ALERT, "Unknown action " << action
187            << " for key " << binding->getIndex());
188   }
189 }
190
191
192 /**
193  * Keyboard event handler for Glut.
194  *
195  * @param k The integer value for the key pressed.
196  * @param x (unused)
197  * @param y (unused)
198  */
199 void GLUTkey(unsigned char k, int x, int y) {
200     float fov, tmp;
201     static bool winding_ccw = true;
202     int speed;
203
204                                 // First, check for a user override.
205     const SGPropertyNode * binding = globals->get_props()
206       ->getNode("/input/keyboard/", true)->getChild("key", int(k));
207     if (binding != 0) {
208       doBinding(binding);
209       return;
210     }
211
212                                 // Use the old, default actions.
213     FGInterface *f = current_aircraft.fdm_state;
214     FGViewer *v = globals->get_current_view();
215
216     SG_LOG( SG_INPUT, SG_DEBUG, "Key hit = " << k );
217     if ( puKeyboard(k, PU_DOWN) ) {
218         return;
219     }
220
221     if ( GLUT_ACTIVE_ALT && glutGetModifiers() ) {
222         SG_LOG( SG_INPUT, SG_DEBUG, " SHIFTED" );
223         switch (k) {
224         case 1: // Ctrl-A key
225             current_autopilot->set_AltitudeMode( 
226                   FGAutopilot::FG_ALTITUDE_LOCK );
227             current_autopilot->set_AltitudeEnabled(
228                   ! current_autopilot->get_AltitudeEnabled()
229                 );
230             return;
231         case 7: // Ctrl-G key
232             current_autopilot->set_AltitudeMode( 
233                   FGAutopilot::FG_ALTITUDE_GS1 );
234             current_autopilot->set_AltitudeEnabled(
235                   ! current_autopilot->get_AltitudeEnabled()
236                 );
237             return;
238         case 8: // Ctrl-H key
239             current_autopilot->set_HeadingMode(
240                   FGAutopilot::FG_TC_HEADING_LOCK );
241             current_autopilot->set_HeadingEnabled(
242                   ! current_autopilot->get_HeadingEnabled()
243                 );
244             return;
245         case 14: // Ctrl-N key
246             current_autopilot->set_HeadingMode( 
247                   FGAutopilot::FG_HEADING_NAV1 );
248             current_autopilot->set_HeadingEnabled(
249                   ! current_autopilot->get_HeadingEnabled()
250                 );
251             return;
252         case 18: // Ctrl-R key
253             // temporary
254             winding_ccw = !winding_ccw;
255             if ( winding_ccw ) {
256                 glFrontFace ( GL_CCW );
257             } else {
258                 glFrontFace ( GL_CW );
259             }
260             return;
261         case 19: // Ctrl-S key
262             current_autopilot->set_AutoThrottleEnabled(
263                   ! current_autopilot->get_AutoThrottleEnabled()
264                 );
265             return;
266         case 20: // Ctrl-T key
267             current_autopilot->set_AltitudeMode( 
268                   FGAutopilot::FG_ALTITUDE_TERRAIN );
269             current_autopilot->set_AltitudeEnabled(
270                   ! current_autopilot->get_AltitudeEnabled()
271                 );
272             return;
273         case 21: // Ctrl-U key
274             // add 1000' of emergency altitude.  Possibly good for 
275             // unflipping yourself :-)
276             {
277                 double alt = cur_fdm_state->get_Altitude() + 1000;
278                 fgFDMForceAltitude( fgGetString("/sim/flight-model"), 
279                                     alt * SG_FEET_TO_METER );
280             }
281             return;
282         case 49: // numeric keypad 1
283             v->set_goal_view_offset( SGD_PI * 0.75 );
284             return;
285         case 50: // numeric keypad 2
286             v->set_goal_view_offset( SGD_PI );
287             return;
288         case 51: // numeric keypad 3
289             v->set_goal_view_offset( SGD_PI * 1.25 );
290             return;
291         case 52: // numeric keypad 4
292             v->set_goal_view_offset( SGD_PI * 0.50 );
293             return;
294         case 54: // numeric keypad 6
295             v->set_goal_view_offset( SGD_PI * 1.50 );
296             return;
297         case 55: // numeric keypad 7
298             v->set_goal_view_offset( SGD_PI * 0.25 );
299             return;
300         case 56: // numeric keypad 8
301             v->set_goal_view_offset( 0.00 );
302             return;
303         case 57: // numeric keypad 9
304             v->set_goal_view_offset( SGD_PI * 1.75 );
305             return;
306         case 65: // A key
307             speed = fgGetInt("/sim/speed-up");
308             speed--;
309             if ( speed < 1 ) {
310                 speed = 1;
311             }
312             fgSetInt("/sim/speed-up", speed);
313             return;
314         case 72: // H key
315             HUD_brightkey( true );
316             return;
317         case 73: // I key
318             // Minimal Hud
319             fgHUDInit2(&current_aircraft);
320             return;
321         case 77: // M key
322             globals->inc_warp( -60 );
323             fgUpdateSkyAndLightingParams();
324             return;
325         case 80: // P key
326             if (fgGetBool("/sim/panel/visibility"))
327               fgSetBool("/sim/panel/visibility", false);
328             else
329               fgSetBool("/sim/panel/visibility", true);
330             fgReshape(fgGetInt("/sim/startup/xsize"),
331                       fgGetInt("/sim/startup/ysize"));
332             break;
333         case 84: // T key
334             globals->inc_warp_delta( -30 );
335             fgUpdateSkyAndLightingParams();
336             return;
337         case 87: // W key
338 #if defined(FX) && !defined(WIN32)
339             global_fullscreen = ( !global_fullscreen );
340 #  if defined(XMESA_FX_FULLSCREEN) && defined(XMESA_FX_WINDOW)
341             XMesaSetFXmode( global_fullscreen ? 
342                             XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW );
343 #  endif
344 #endif
345             return;
346         case 88: // X key
347             fov = globals->get_current_view()->get_fov();
348             fov *= 1.05;
349             if ( fov > FG_FOV_MAX ) {
350                 fov = FG_FOV_MAX;
351             }
352             globals->get_current_view()->set_fov(fov);
353             // v->force_update_fov_math();
354             return;
355         case 90: // Z key
356 #ifndef FG_OLD_WEATHER
357             tmp = WeatherDatabase->getWeatherVisibility();
358             tmp /= 1.10;
359             WeatherDatabase->setWeatherVisibility( tmp );
360 #else
361             tmp = current_weather.get_visibility();   // in meters
362             tmp /= 1.10;
363             current_weather.set_visibility( tmp );
364 #endif
365             return;
366         }
367     } else {
368         SG_LOG( SG_INPUT, SG_DEBUG, "" );
369         switch (k) {
370         case 50: // numeric keypad 2
371             if ( current_autopilot->get_AltitudeEnabled() ) {
372                 current_autopilot->AltitudeAdjust( 100 );
373             } else {
374                 controls.move_elevator(-0.05);
375             }
376             return;
377         case 56: // numeric keypad 8
378             if ( current_autopilot->get_AltitudeEnabled() ) {
379                 current_autopilot->AltitudeAdjust( -100 );
380             } else {
381                 controls.move_elevator(0.05);
382             }
383             return;
384         case 49: // numeric keypad 1
385             controls.move_elevator_trim(-0.001);
386             return;
387         case 55: // numeric keypad 7
388             controls.move_elevator_trim(0.001);
389             return;
390         case 52: // numeric keypad 4
391             controls.move_aileron(-0.05);
392             return;
393         case 54: // numeric keypad 6
394             controls.move_aileron(0.05);
395             return;
396         case 48: // numeric keypad Ins
397             if ( current_autopilot->get_HeadingEnabled() ) {
398                 current_autopilot->HeadingAdjust( -1 );
399             } else {
400                 controls.move_rudder(-0.05);
401             }
402             return;
403         case 13: // numeric keypad Enter
404             if ( current_autopilot->get_HeadingEnabled() ) {
405                 current_autopilot->HeadingAdjust( 1 );
406             } else {
407                 controls.move_rudder(0.05);
408             }
409             return;
410         case 53: // numeric keypad 5
411             controls.set_aileron(0.0);
412             controls.set_elevator(0.0);
413             controls.set_rudder(0.0);
414             return;
415         case 57: // numeric keypad 9 (Pg Up)
416             if ( current_autopilot->get_AutoThrottleEnabled() ) {
417                 current_autopilot->AutoThrottleAdjust( 5 );
418             } else {
419                 controls.move_throttle( FGControls::ALL_ENGINES, 0.01 );
420             }
421             return;
422         case 51: // numeric keypad 3 (Pg Dn)
423             if ( current_autopilot->get_AutoThrottleEnabled() ) {
424                 current_autopilot->AutoThrottleAdjust( -5 );
425             } else {
426                 controls.move_throttle( FGControls::ALL_ENGINES, -0.01 );
427             }
428             return;
429         case 91: // [ key
430             controls.move_flaps(-0.34);
431             SG_LOG( SG_INPUT, SG_INFO,
432                     "Set flaps to " << controls.get_flaps() );
433             return;
434         case 93: // ] key
435             controls.move_flaps(0.34);
436             SG_LOG( SG_INPUT, SG_INFO,
437                     "Set flaps to " << controls.get_flaps() );
438             return;
439         case 97: // a key
440             speed = fgGetInt("/sim/speed-up");
441             speed++;
442             fgSetInt("/sim/speed-up", speed);
443             return;
444         case 98: // b key
445             int b_ret;
446             double b_set;
447             b_ret = int( controls.get_brake( 0 ) );
448             b_set = double(!b_ret);
449             controls.set_brake( FGControls::ALL_WHEELS, b_set);
450             return;
451         case 44: // , key
452             if (controls.get_brake(0) > 0.0) {
453                 controls.set_brake(0, 0.0);
454             } else {
455                 controls.set_brake(0, 1.0);
456             }
457             return;
458         case 46: // . key
459             if (controls.get_brake(1) > 0.0) {
460                 controls.set_brake(1, 0.0);
461             } else {
462                 controls.set_brake(1, 1.0);
463             }
464             return;
465         case 104: // h key
466             HUD_masterswitch( true );
467             return;
468         case 105: // i key
469             fgHUDInit(&current_aircraft);  // normal HUD
470             return;
471         case 109: // m key
472             globals->inc_warp( 60 );
473             fgUpdateSkyAndLightingParams();
474             return;
475         case 112: // p key
476             globals->set_freeze( ! globals->get_freeze() );
477
478             {
479                 SGBucket p( f->get_Longitude() * SGD_RADIANS_TO_DEGREES,
480                             f->get_Latitude() * SGD_RADIANS_TO_DEGREES );
481                 SGPath tile_path( globals->get_fg_root() );
482                 tile_path.append( "Scenery" );
483                 tile_path.append( p.gen_base_path() );
484                 tile_path.append( p.gen_index_str() );
485
486                 // printf position and attitude information
487                 SG_LOG( SG_INPUT, SG_INFO,
488                         "Lon = " << f->get_Longitude() * SGD_RADIANS_TO_DEGREES
489                         << "  Lat = " << f->get_Latitude() * SGD_RADIANS_TO_DEGREES
490                         << "  Altitude = " << f->get_Altitude() * SG_FEET_TO_METER
491                         );
492                 SG_LOG( SG_INPUT, SG_INFO,
493                         "Heading = " << f->get_Psi() * SGD_RADIANS_TO_DEGREES 
494                         << "  Roll = " << f->get_Phi() * SGD_RADIANS_TO_DEGREES
495                         << "  Pitch = " << f->get_Theta() * SGD_RADIANS_TO_DEGREES );
496                 SG_LOG( SG_INPUT, SG_INFO, tile_path.c_str());
497             }
498             return;
499         case 116: // t key
500             globals->inc_warp_delta( 30 );
501             fgUpdateSkyAndLightingParams();
502             return;
503         case 118: // v key
504             // handles GUI state as well as Viewer LookAt Direction
505             CenterView();
506             globals->set_current_view( globals->get_viewmgr()->next_view() );
507             fgReshape( fgGetInt("/sim/startup/xsize"),
508                        fgGetInt("/sim/startup/ysize") );
509             return;
510         case 120: // x key
511             fov = globals->get_current_view()->get_fov();
512             fov /= 1.05;
513             if ( fov < FG_FOV_MIN ) {
514                 fov = FG_FOV_MIN;
515             }
516             globals->get_current_view()->set_fov(fov);
517             // v->force_update_fov_math();
518             return;
519         case 122: // z key
520 #ifndef FG_OLD_WEATHER
521             tmp = WeatherDatabase->getWeatherVisibility();
522             tmp *= 1.10;
523             WeatherDatabase->setWeatherVisibility( tmp );
524 #else
525             tmp = current_weather.get_visibility();   // in meters
526             tmp *= 1.10;
527             current_weather.set_visibility( tmp );
528 #endif
529             return;
530         case 27: // ESC
531             // if( fg_DebugOutput ) {
532             //   fclose( fg_DebugOutput );
533             // }
534             SG_LOG( SG_INPUT, SG_ALERT, 
535                     "Program exit requested." );
536             ConfirmExitDialog();
537             return;
538         }
539     }
540 }
541
542
543 // Handle "special" keyboard events
544 void GLUTspecialkey(int k, int x, int y) {
545     FGViewer *v = globals->get_current_view();
546
547     SG_LOG( SG_INPUT, SG_DEBUG, "Special key hit = " << k );
548
549     if ( puKeyboard(k + PU_KEY_GLUT_SPECIAL_OFFSET, PU_DOWN) ) {
550         return;
551     }
552
553     if ( GLUT_ACTIVE_SHIFT && glutGetModifiers() ) {
554         SG_LOG( SG_INPUT, SG_DEBUG, " SHIFTED" );
555         switch (k) {
556         case GLUT_KEY_F1: {
557             ifstream input("fgfs.sav");
558             if (input.good() && fgLoadFlight(input)) {
559                 input.close();
560                 SG_LOG(SG_INPUT, SG_INFO, "Restored flight from fgfs.sav");
561             } else {
562                 SG_LOG(SG_INPUT, SG_ALERT, "Cannot load flight from fgfs.sav");
563             }
564             return;
565         }
566         case GLUT_KEY_F2: {
567             SG_LOG(SG_INPUT, SG_INFO, "Saving flight");
568             cerr << "Opening output stream" << endl;
569             ofstream output("fgfs.sav");
570             cerr << "output stream opened" << endl;
571             if (output.good() && fgSaveFlight(output)) {
572                 output.close();
573                 SG_LOG(SG_INPUT, SG_INFO, "Saved flight to fgfs.sav");
574             } else {
575                 SG_LOG(SG_INPUT, SG_ALERT, "Cannot save flight to fgfs.sav");
576             }
577             return;
578         }
579         case GLUT_KEY_F3: {
580             string panel_path =
581                 fgGetString("/sim/panel/path", "Panels/Default/default.xml");
582             FGPanel * new_panel = fgReadPanel(panel_path);
583             if (new_panel == 0) {
584                 SG_LOG(SG_INPUT, SG_ALERT,
585                        "Error reading new panel from " << panel_path);
586                 return;
587             }
588             SG_LOG(SG_INPUT, SG_INFO, "Loaded new panel from " << panel_path);
589             current_panel->unbind();
590             delete current_panel;
591             current_panel = new_panel;
592             return;
593         }
594         case GLUT_KEY_F4: {
595             SGPath props_path(globals->get_fg_root());
596             props_path.append("preferences.xml");
597             SG_LOG(SG_INPUT, SG_INFO, "Rereading global preferences");
598             if (!readProperties(props_path.str(), globals->get_props())) {
599                 SG_LOG(SG_INPUT, SG_ALERT,
600                        "Failed to reread global preferences from "
601                        << props_path.str());
602             } else {
603                 SG_LOG(SG_INPUT, SG_INFO, "Finished Reading global preferences");
604             }
605             return;
606         }
607         case GLUT_KEY_F5: {
608             current_panel->setYOffset(current_panel->getYOffset() - 5);
609             fgReshape(fgGetInt("/sim/startup/xsize"),
610                       fgGetInt("/sim/startup/ysize"));
611             return;
612         }
613         case GLUT_KEY_F6: {
614             current_panel->setYOffset(current_panel->getYOffset() + 5);
615             fgReshape(fgGetInt("/sim/startup/xsize"),
616                       fgGetInt("/sim/startup/ysize"));
617             return;
618         }
619         case GLUT_KEY_F7: {
620             current_panel->setXOffset(current_panel->getXOffset() - 5);
621             return;
622         }
623         case GLUT_KEY_F8: {
624             current_panel->setXOffset(current_panel->getXOffset() + 5);
625             return;
626         }
627         // case GLUT_KEY_F9: {
628         //     return;
629         // }
630         case GLUT_KEY_F10: {
631             fgToggleFDMdataLogging();
632             return;
633         }
634         // case GLUT_KEY_F11: {
635         //     return;
636         // }
637         // case GLUT_KEY_F12: {
638         //     return;
639         // }
640         case GLUT_KEY_END: // numeric keypad 1
641             v->set_goal_view_offset( SGD_PI * 0.75 );
642             return;
643         case GLUT_KEY_DOWN: // numeric keypad 2
644             v->set_goal_view_offset( SGD_PI );
645             return;
646         case GLUT_KEY_PAGE_DOWN: // numeric keypad 3
647             v->set_goal_view_offset( SGD_PI * 1.25 );
648             return;
649         case GLUT_KEY_LEFT: // numeric keypad 4
650             v->set_goal_view_offset( SGD_PI * 0.50 );
651             return;
652         case GLUT_KEY_RIGHT: // numeric keypad 6
653             v->set_goal_view_offset( SGD_PI * 1.50 );
654             return;
655         case GLUT_KEY_HOME: // numeric keypad 7
656             v->set_goal_view_offset( SGD_PI * 0.25 );
657             return;
658         case GLUT_KEY_UP: // numeric keypad 8
659             v->set_goal_view_offset( 0.00 );
660             return;
661         case GLUT_KEY_PAGE_UP: // numeric keypad 9
662             v->set_goal_view_offset( SGD_PI * 1.75 );
663             return;
664         }
665     } else {
666         SG_LOG( SG_INPUT, SG_DEBUG, "" );
667         switch (k) {
668         case GLUT_KEY_F2: // F2 Reload Tile Cache...
669             {
670                 bool freeze = globals->get_freeze();
671                 SG_LOG(SG_INPUT, SG_INFO, "ReIniting TileCache");
672                 if ( !freeze ) 
673                     globals->set_freeze( true );
674                 BusyCursor(0);
675                 if ( global_tile_mgr.init() ) {
676                     // Load the local scenery data
677                     global_tile_mgr.update( 
678                         cur_fdm_state->get_Longitude() * SGD_RADIANS_TO_DEGREES,
679                         cur_fdm_state->get_Latitude() * SGD_RADIANS_TO_DEGREES );
680                 } else {
681                     SG_LOG( SG_GENERAL, SG_ALERT, 
682                             "Error in Tile Manager initialization!" );
683                     exit(-1);
684                 }
685                 BusyCursor(1);
686                 if ( !freeze )
687                    globals->set_freeze( false );
688                 return;
689             }
690         case GLUT_KEY_F3: // F3 Take a screen shot
691             fgDumpSnapShot();
692             return;
693         case GLUT_KEY_F4: // F4 Update lighting manually
694             fgUpdateSkyAndLightingParams();
695             return;
696         case GLUT_KEY_F6: // F6 toggles Autopilot target location
697             if ( current_autopilot->get_HeadingMode() !=
698                  FGAutopilot::FG_HEADING_WAYPOINT ) {
699                 current_autopilot->set_HeadingMode(
700                     FGAutopilot::FG_HEADING_WAYPOINT );
701                 current_autopilot->set_HeadingEnabled( true );
702             } else {
703                 current_autopilot->set_HeadingMode(
704                     FGAutopilot::FG_TC_HEADING_LOCK );
705             }
706             return;
707         case GLUT_KEY_F8: {// F8 toggles fog ... off fastest nicest...
708             const string &fog = fgGetString("/sim/rendering/fog");
709             if (fog == "disabled") {
710               fgSetString("/sim/rendering/fog", "fastest");
711               SG_LOG(SG_INPUT, SG_INFO, "Fog enabled, hint=fastest");
712             } else if (fog == "fastest") {
713               fgSetString("/sim/rendering/fog", "nicest");
714               SG_LOG(SG_INPUT, SG_INFO, "Fog enabled, hint=nicest");
715             } else if (fog == "nicest") {
716               fgSetString("/sim/rendering/fog", "disabled");
717               SG_LOG(SG_INPUT, SG_INFO, "Fog disabled");
718             } else {
719               fgSetString("/sim/rendering/fog", "disabled");
720               SG_LOG(SG_INPUT, SG_ALERT, "Unrecognized fog type "
721                      << fog << ", changed to 'disabled'");
722             }
723             return;
724         }
725         case GLUT_KEY_F9: // F9 toggles textures on and off...
726             SG_LOG( SG_INPUT, SG_INFO, "Toggling texture" );
727             if ( fgGetBool("/sim/rendering/textures")) {
728                 fgSetBool("/sim/rendering/textures", false);
729                 material_lib.set_step( 1 );
730             } else {
731                 fgSetBool("/sim/rendering/textures", true);
732                 material_lib.set_step( 0 );
733             }
734             return;
735         case GLUT_KEY_F10: // F10 toggles menu on and off...
736             SG_LOG(SG_INPUT, SG_INFO, "Invoking call back function");
737             guiToggleMenu();
738             return;
739         case GLUT_KEY_F11: // F11 Altitude Dialog.
740             SG_LOG(SG_INPUT, SG_INFO, "Invoking Altitude call back function");
741             NewAltitude( NULL );
742             return;
743         case GLUT_KEY_F12: // F12 Heading Dialog...
744             SG_LOG(SG_INPUT, SG_INFO, "Invoking Heading call back function");
745             NewHeading( NULL );
746             return;
747         case GLUT_KEY_UP:
748             if ( current_autopilot->get_AltitudeEnabled() ) {
749                 current_autopilot->AltitudeAdjust( -100 );
750             } else {
751                 controls.move_elevator(0.05);
752             }
753             return;
754         case GLUT_KEY_DOWN:
755             if ( current_autopilot->get_AltitudeEnabled() ) {
756                 current_autopilot->AltitudeAdjust( 100 );
757             } else {
758                 controls.move_elevator(-0.05);
759             }
760             return;
761         case GLUT_KEY_LEFT:
762             controls.move_aileron(-0.05);
763             return;
764         case GLUT_KEY_RIGHT:
765             controls.move_aileron(0.05);
766             return;
767         case GLUT_KEY_HOME: // numeric keypad 1
768             controls.move_elevator_trim(0.001);
769             return;
770         case GLUT_KEY_END: // numeric keypad 7
771             controls.move_elevator_trim(-0.001);
772             return;
773         case GLUT_KEY_INSERT: // numeric keypad Ins
774             if ( current_autopilot->get_HeadingEnabled() ) {
775                 current_autopilot->HeadingAdjust( -1 );
776             } else {
777                 controls.move_rudder(-0.05);
778             }
779             return;
780         case 13: // numeric keypad Enter
781             if ( current_autopilot->get_HeadingEnabled() ) {
782                 current_autopilot->HeadingAdjust( 1 );
783             } else {
784                 controls.move_rudder(0.05);
785             }
786             return;
787         case 53: // numeric keypad 5
788             controls.set_aileron(0.0);
789             controls.set_elevator(0.0);
790             controls.set_rudder(0.0);
791             return;
792         case GLUT_KEY_PAGE_UP: // numeric keypad 9 (Pg Up)
793             if ( current_autopilot->get_AutoThrottleEnabled() ) {
794                 current_autopilot->AutoThrottleAdjust( 5 );
795             } else {
796                 controls.move_throttle( FGControls::ALL_ENGINES, 0.01 );
797             }
798             return;
799         case GLUT_KEY_PAGE_DOWN: // numeric keypad 3 (Pg Dn)
800             if ( current_autopilot->get_AutoThrottleEnabled() ) {
801                 current_autopilot->AutoThrottleAdjust( -5 );
802             } else {
803                 controls.move_throttle( FGControls::ALL_ENGINES, -0.01 );
804             }
805             return;
806         }
807     }
808 }
809
810