]> git.mxchange.org Git - flightgear.git/blob - src/Main/fg_props.cxx
6d584b09b2b30488b6abe77aa9055a5505101dc8
[flightgear.git] / src / Main / fg_props.cxx
1 // fg_props.cxx -- support for FlightGear properties.
2 //
3 // Written by David Megginson, started 2000.
4 //
5 // Copyright (C) 2000, 2001 David Megginson - david@megginson.com
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 #ifdef HAVE_CONFIG_H
24 #  include <simgear/compiler.h>
25 #endif
26
27 #include STL_IOSTREAM
28
29 #include <Autopilot/newauto.hxx>
30 #include <Aircraft/aircraft.hxx>
31 #include <Time/tmp.hxx>
32 #include <FDM/UIUCModel/uiuc_aircraftdir.h>
33 #ifndef FG_OLD_WEATHER
34 #  include <WeatherCM/FGLocalWeatherDatabase.h>
35 #else
36 #  include <Weather/weather.hxx>
37 #endif
38 #include <Objects/matlib.hxx>
39
40 #include "fgfs.hxx"
41 #include "fg_props.hxx"
42
43 #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
44 SG_USING_STD(istream);
45 SG_USING_STD(ostream);
46 #endif
47
48 static double getWindNorth ();
49 static double getWindEast ();
50 static double getWindDown ();
51
52 // Allow the view to be set from two axes (i.e. a joystick hat)
53 // This needs to be in FGViewer itself, somehow.
54 static double axisLong = 0.0;
55 static double axisLat = 0.0;
56
57 static bool winding_ccw = false; // FIXME: temporary
58
59 static bool fdm_data_logging = false; // FIXME: temporary
60
61
62 /**
63  * Utility function.
64  */
65 static inline void
66 _set_view_from_axes ()
67 {
68                                 // Take no action when hat is centered
69   if ( ( axisLong <  0.01 ) &&
70        ( axisLong > -0.01 ) &&
71        ( axisLat  <  0.01 ) &&
72        ( axisLat  > -0.01 )
73      )
74     return;
75
76   double viewDir = 999;
77
78   /* Do all the quick and easy cases */
79   if (axisLong < 0) {           // Longitudinal axis forward
80     if (axisLat == axisLong)
81       viewDir = 45;
82     else if (axisLat == - axisLong)
83       viewDir = 315;
84     else if (axisLat == 0)
85       viewDir = 0;
86   } else if (axisLong > 0) {    // Longitudinal axis backward
87     if (axisLat == - axisLong)
88       viewDir = 135;
89     else if (axisLat == axisLong)
90       viewDir = 225;
91     else if (axisLat == 0)
92       viewDir = 180;
93   } else if (axisLong == 0) {   // Longitudinal axis neutral
94     if (axisLat < 0)
95       viewDir = 90;
96     else if (axisLat > 0)
97       viewDir = 270;
98     else return; /* And assertion failure maybe? */
99   }
100
101   /* Do all the difficult cases */
102   if ( viewDir > 900 )
103     viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axisLat, -axisLong );
104   if ( viewDir < -1 ) viewDir += 360;
105
106 //  SG_LOG(SG_INPUT, SG_ALERT, "Joystick Lat=" << axisLat << "   and Long="
107 //      << axisLong << "  gave angle=" << viewDir );
108
109   globals->get_current_view()->set_goal_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
110 //   globals->get_current_view()->set_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
111 }
112
113 \f
114 ////////////////////////////////////////////////////////////////////////
115 // Default property bindings (not yet handled by any module).
116 ////////////////////////////////////////////////////////////////////////
117
118
119 /**
120  * Get the pause state of the sim.
121  */
122 static bool
123 getFreeze ()
124 {
125   return globals->get_freeze();
126 }
127
128
129 /**
130  * Set the pause state of the sim.
131  */
132 static void
133 setFreeze (bool freeze)
134 {
135   globals->set_freeze(freeze);
136 }
137
138 /**
139  * Return the current aircraft directory (UIUC) as a string.
140  */
141 static string 
142 getAircraftDir ()
143 {
144   return aircraft_dir;
145 }
146
147
148 /**
149  * Set the current aircraft directory (UIUC).
150  */
151 static void
152 setAircraftDir (string dir)
153 {
154   if (getAircraftDir() != dir) {
155     aircraft_dir = dir;
156 //     needReinit(); FIXME!!
157   }
158 }
159
160
161 /**
162  * Get the current view offset in degrees.
163  */
164 static double
165 getViewOffset ()
166 {
167   return (globals->get_current_view()
168           ->get_view_offset() * SGD_RADIANS_TO_DEGREES);
169 }
170
171
172 static void
173 setViewOffset (double offset)
174 {
175   globals->get_current_view()->set_view_offset(offset * SGD_DEGREES_TO_RADIANS);
176 }
177
178 static double
179 getGoalViewOffset ()
180 {
181   return (globals->get_current_view()
182           ->get_goal_view_offset() * SGD_RADIANS_TO_DEGREES);
183 }
184
185 static void
186 setGoalViewOffset (double offset)
187 {
188     while ( offset < 0 ) {
189         offset += 360.0;
190     }
191     while ( offset > 360.0 ) {
192         offset -= 360.0;
193     }
194     // Snap to center if we are close
195     if ( fabs(offset) < 1.0 ||  fabs(offset) > 359.0 ) {
196         offset = 0.0;
197     }
198
199     globals->get_current_view()
200         ->set_goal_view_offset(offset * SGD_DEGREES_TO_RADIANS);
201 }
202
203
204 /**
205  * Return the current Zulu time.
206  */
207 static string 
208 getDateString ()
209 {
210   string out;
211   char buf[64];
212   struct tm * t = globals->get_time_params()->getGmt();
213   sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d",
214           t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
215           t->tm_hour, t->tm_min, t->tm_sec);
216   out = buf;
217   return out;
218 }
219
220
221 /**
222  * Set the current Zulu time.
223  */
224 static void
225 setDateString (string date_string)
226 {
227   SGTime * st = globals->get_time_params();
228   struct tm * current_time = st->getGmt();
229   struct tm new_time;
230
231                                 // Scan for basic ISO format
232                                 // YYYY-MM-DDTHH:MM:SS
233   int ret = sscanf(date_string.c_str(), "%d-%d-%dT%d:%d:%d",
234                    &(new_time.tm_year), &(new_time.tm_mon),
235                    &(new_time.tm_mday), &(new_time.tm_hour),
236                    &(new_time.tm_min), &(new_time.tm_sec));
237
238                                 // Be pretty picky about this, so
239                                 // that strange things don't happen
240                                 // if the save file has been edited
241                                 // by hand.
242   if (ret != 6) {
243     SG_LOG(SG_INPUT, SG_ALERT, "Date/time string " << date_string
244            << " not in YYYY-MM-DDTHH:MM:SS format; skipped");
245     return;
246   }
247
248                                 // OK, it looks like we got six
249                                 // values, one way or another.
250   new_time.tm_year -= 1900;
251   new_time.tm_mon -= 1;
252
253                                 // Now, tell flight gear to use
254                                 // the new time.  This was far
255                                 // too difficult, by the way.
256   long int warp =
257     mktime(&new_time) - mktime(current_time) + globals->get_warp();
258   double lon = current_aircraft.fdm_state->get_Longitude();
259   double lat = current_aircraft.fdm_state->get_Latitude();
260   globals->set_warp(warp);
261   st->update(lon, lat, warp);
262   fgUpdateSkyAndLightingParams();
263 }
264
265 /**
266  * Return the GMT as a string.
267  */
268 static string 
269 getGMTString ()
270 {
271   string out;
272   char buf[16];
273   struct tm * t = globals->get_time_params()->getGmt();
274   sprintf(buf, " %.2d:%.2d:%.2d",
275           t->tm_hour, t->tm_min, t->tm_sec);
276   out = buf;
277   return out;
278 }
279
280
281 /**
282  * Get the texture rendering state.
283  */
284 static bool
285 getTextures ()
286 {
287   return (material_lib.get_step() == 0);
288 }
289
290
291 /**
292  * Set the texture rendering state.
293  */
294 static void
295 setTextures (bool textures)
296 {
297   if (textures)
298     material_lib.set_step(0);
299   else
300     material_lib.set_step(1);
301 }
302
303
304 /**
305  * Return the magnetic variation
306  */
307 static double
308 getMagVar ()
309 {
310   return globals->get_mag()->get_magvar() * SGD_RADIANS_TO_DEGREES;
311 }
312
313
314 /**
315  * Return the magnetic dip
316  */
317 static double
318 getMagDip ()
319 {
320   return globals->get_mag()->get_magdip() * SGD_RADIANS_TO_DEGREES;
321 }
322
323
324 /**
325  * Return the current heading in degrees.
326  */
327 static double
328 getHeadingMag ()
329 {
330   return current_aircraft.fdm_state->get_Psi() * SGD_RADIANS_TO_DEGREES - getMagVar();
331 }
332
333
334 /**
335  * Return the current engine0 rpm
336  */
337 static double
338 getRPM ()
339 {
340   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
341       return current_aircraft.fdm_state->get_engine(0)->get_RPM();
342   } else {
343       return 0.0;
344   }
345 }
346
347
348 /**
349  * Return the current engine0 EGT.
350  */
351 static double
352 getEGT ()
353 {
354   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
355       return current_aircraft.fdm_state->get_engine(0)->get_EGT();
356   } else {
357       return 0.0;
358   }
359 }
360
361 /**
362  * Return the current engine0 CHT.
363  */
364 static double
365 getCHT ()
366 {
367   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
368       return current_aircraft.fdm_state->get_engine(0)->get_CHT();
369   } else {
370       return 0.0;
371   }
372 }
373
374 /**
375  * Return the current engine0 Manifold Pressure.
376  */
377 static double
378 getMP ()
379 {
380   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
381       return current_aircraft.fdm_state->get_engine(0)->get_Manifold_Pressure();
382   } else {
383       return 0.0;
384   }
385 }
386
387
388 /**
389  * Return the current engine0 fuel flow
390  */
391 static double
392 getFuelFlow ()
393 {
394   if ( current_aircraft.fdm_state->get_engine(0) != NULL ) {
395       return current_aircraft.fdm_state->get_engine(0)->get_Fuel_Flow();
396   } else {
397       return 0.0;
398   }
399 }
400
401 /**
402  * Return the fuel level in tank 1
403  */
404 static double
405 getTank1Fuel ()
406 {
407   return current_aircraft.fdm_state->get_Tank1Fuel();
408 }
409
410 static void
411 setTank1Fuel ( double gals )
412 {
413   current_aircraft.fdm_state->set_Tank1Fuel( gals );
414 }
415
416 /**
417  * Return the fuel level in tank 2
418  */
419 static double
420 getTank2Fuel ()
421 {
422   return current_aircraft.fdm_state->get_Tank2Fuel();
423 }
424
425 static void
426 setTank2Fuel ( double gals )
427 {
428   current_aircraft.fdm_state->set_Tank2Fuel( gals );
429 }
430
431
432 /**
433  * Get the autopilot altitude lock (true=on).
434  */
435 static bool
436 getAPAltitudeLock ()
437 {
438     return (current_autopilot->get_AltitudeEnabled() &&
439             current_autopilot->get_AltitudeMode()
440             == FGAutopilot::FG_ALTITUDE_LOCK);
441 }
442
443
444 /**
445  * Set the autopilot altitude lock (true=on).
446  */
447 static void
448 setAPAltitudeLock (bool lock)
449 {
450   current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
451   current_autopilot->set_AltitudeEnabled(lock);
452 }
453
454
455 /**
456  * Get the autopilot target altitude in feet.
457  */
458 static double
459 getAPAltitude ()
460 {
461   return current_autopilot->get_TargetAltitude() * SG_METER_TO_FEET;
462 }
463
464
465 /**
466  * Set the autopilot target altitude in feet.
467  */
468 static void
469 setAPAltitude (double altitude)
470 {
471     current_autopilot->set_TargetAltitude( altitude * SG_FEET_TO_METER );
472 }
473
474 /**
475  * Get the autopilot altitude lock (true=on).
476  */
477 static bool
478 getAPGSLock ()
479 {
480     return (current_autopilot->get_AltitudeEnabled() &&
481             (current_autopilot->get_AltitudeMode()
482              == FGAutopilot::FG_ALTITUDE_GS1));
483 }
484
485
486 /**
487  * Set the autopilot altitude lock (true=on).
488  */
489 static void
490 setAPGSLock (bool lock)
491 {
492   current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_GS1);
493   current_autopilot->set_AltitudeEnabled(lock);
494 }
495
496
497 /**
498  * Get the autopilot terrain lock (true=on).
499  */
500 static bool
501 getAPTerrainLock ()
502 {
503     return (current_autopilot->get_AltitudeEnabled() &&
504             (current_autopilot->get_AltitudeMode()
505              == FGAutopilot::FG_ALTITUDE_TERRAIN));
506 }
507
508
509 /**
510  * Set the autopilot terrain lock (true=on).
511  */
512 static void
513 setAPTerrainLock (bool lock)
514 {
515   current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_TERRAIN);
516   current_autopilot->set_AltitudeEnabled(lock);
517 }
518
519
520 /**
521  * Get the autopilot target altitude in feet.
522  */
523 static double
524 getAPClimb ()
525 {
526   return current_autopilot->get_TargetClimbRate() * SG_METER_TO_FEET;
527 }
528
529
530 /**
531  * Set the autopilot target altitude in feet.
532  */
533 static void
534 setAPClimb (double rate)
535 {
536     current_autopilot->set_TargetClimbRate( rate * SG_FEET_TO_METER );
537 }
538
539
540 /**
541  * Get the autopilot heading lock (true=on).
542  */
543 static bool
544 getAPHeadingLock ()
545 {
546     return
547       (current_autopilot->get_HeadingEnabled() &&
548        current_autopilot->get_HeadingMode() == DEFAULT_AP_HEADING_LOCK);
549 }
550
551
552 /**
553  * Set the autopilot heading lock (true=on).
554  */
555 static void
556 setAPHeadingLock (bool lock)
557 {
558     if (lock) {
559         current_autopilot->set_HeadingMode(DEFAULT_AP_HEADING_LOCK);
560         current_autopilot->set_HeadingEnabled(true);
561     } else {
562         current_autopilot->set_HeadingEnabled(false);
563     }
564 }
565
566
567 /**
568  * Get the autopilot heading bug in degrees.
569  */
570 static double
571 getAPHeadingBug ()
572 {
573   return current_autopilot->get_DGTargetHeading();
574 }
575
576
577 /**
578  * Set the autopilot heading bug in degrees.
579  */
580 static void
581 setAPHeadingBug (double heading)
582 {
583   current_autopilot->set_DGTargetHeading( heading );
584 }
585
586
587 /**
588  * Get the autopilot wing leveler lock (true=on).
589  */
590 static bool
591 getAPWingLeveler ()
592 {
593     return
594       (current_autopilot->get_HeadingEnabled() &&
595        current_autopilot->get_HeadingMode() == FGAutopilot::FG_TC_HEADING_LOCK);
596 }
597
598
599 /**
600  * Set the autopilot wing leveler lock (true=on).
601  */
602 static void
603 setAPWingLeveler (bool lock)
604 {
605     if (lock) {
606         current_autopilot->set_HeadingMode(FGAutopilot::FG_TC_HEADING_LOCK);
607         current_autopilot->set_HeadingEnabled(true);
608     } else {
609         current_autopilot->set_HeadingEnabled(false);
610     }
611 }
612
613 /**
614  * Return true if the autopilot is locked to NAV1.
615  */
616 static bool
617 getAPNAV1Lock ()
618 {
619   return
620     (current_autopilot->get_HeadingEnabled() &&
621      current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
622 }
623
624
625 /**
626  * Set the autopilot NAV1 lock.
627  */
628 static void
629 setAPNAV1Lock (bool lock)
630 {
631   if (lock) {
632     current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
633     current_autopilot->set_HeadingEnabled(true);
634   } else if (current_autopilot->get_HeadingMode() ==
635              FGAutopilot::FG_HEADING_NAV1) {
636     current_autopilot->set_HeadingEnabled(false);
637   }
638 }
639
640 /**
641  * Get the autopilot autothrottle lock.
642  */
643 static bool
644 getAPAutoThrottleLock ()
645 {
646   return current_autopilot->get_AutoThrottleEnabled();
647 }
648
649
650 /**
651  * Set the autothrottle lock.
652  */
653 static void
654 setAPAutoThrottleLock (bool lock)
655 {
656   current_autopilot->set_AutoThrottleEnabled(lock);
657 }
658
659
660 // kludge
661 static double
662 getAPRudderControl ()
663 {
664     if (getAPHeadingLock())
665         return current_autopilot->get_TargetHeading();
666     else
667         return controls.get_rudder();
668 }
669
670 // kludge
671 static void
672 setAPRudderControl (double value)
673 {
674     if (getAPHeadingLock()) {
675         SG_LOG(SG_GENERAL, SG_DEBUG, "setAPRudderControl " << value );
676         value -= current_autopilot->get_TargetHeading();
677         current_autopilot->HeadingAdjust(value < 0.0 ? -1.0 : 1.0);
678     } else {
679         controls.set_rudder(value);
680     }
681 }
682
683 // kludge
684 static double
685 getAPElevatorControl ()
686 {
687   if (getAPAltitudeLock())
688       return current_autopilot->get_TargetAltitude();
689   else
690     return controls.get_elevator();
691 }
692
693 // kludge
694 static void
695 setAPElevatorControl (double value)
696 {
697     if (getAPAltitudeLock()) {
698         SG_LOG(SG_GENERAL, SG_DEBUG, "setAPElevatorControl " << value );
699         value -= current_autopilot->get_TargetAltitude();
700         current_autopilot->AltitudeAdjust(value < 0.0 ? 100.0 : -100.0);
701     } else {
702         controls.set_elevator(value);
703     }
704 }
705
706 // kludge
707 static double
708 getAPThrottleControl ()
709 {
710   if (getAPAutoThrottleLock())
711     return 0.0;                 // always resets
712   else
713     return controls.get_throttle(0);
714 }
715
716 // kludge
717 static void
718 setAPThrottleControl (double value)
719 {
720   if (getAPAutoThrottleLock())
721     current_autopilot->AutoThrottleAdjust(value < 0.0 ? -0.01 : 0.01);
722   else
723     controls.set_throttle(0, value);
724 }
725
726
727 /**
728  * Get the current visibility (meters).
729  */
730 static double
731 getVisibility ()
732 {
733 #ifndef FG_OLD_WEATHER
734   return WeatherDatabase->getWeatherVisibility();
735 #else
736   return current_weather.get_visibility();
737 #endif
738 }
739
740
741 /**
742  * Set the current visibility (meters).
743  */
744 static void
745 setVisibility (double visibility)
746 {
747 #ifndef FG_OLD_WEATHER
748   WeatherDatabase->setWeatherVisibility(visibility);
749 #else
750   current_weather.set_visibility(visibility);
751 #endif
752 }
753
754 /**
755  * Get the current wind north velocity (feet/second).
756  */
757 static double
758 getWindNorth ()
759 {
760   return current_aircraft.fdm_state->get_V_north_airmass();
761 }
762
763
764 /**
765  * Set the current wind north velocity (feet/second).
766  */
767 static void
768 setWindNorth (double speed)
769 {
770   current_aircraft.fdm_state
771     ->set_Velocities_Local_Airmass(speed, getWindEast(), getWindDown());
772 }
773
774
775 /**
776  * Get the current wind east velocity (feet/second).
777  */
778 static double
779 getWindEast ()
780 {
781   return current_aircraft.fdm_state->get_V_east_airmass();
782 }
783
784
785 /**
786  * Set the current wind east velocity (feet/second).
787  */
788 static void
789 setWindEast (double speed)
790 {
791   cout << "Set wind-east to " << speed << endl;
792   current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
793                                                            speed,
794                                                            getWindDown());
795 }
796
797
798 /**
799  * Get the current wind down velocity (feet/second).
800  */
801 static double
802 getWindDown ()
803 {
804   return current_aircraft.fdm_state->get_V_down_airmass();
805 }
806
807
808 /**
809  * Set the current wind down velocity (feet/second).
810  */
811 static void
812 setWindDown (double speed)
813 {
814   current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
815                                                            getWindEast(),
816                                                            speed);
817 }
818
819 static double
820 getFOV ()
821 {
822   return globals->get_current_view()->get_fov();
823 }
824
825 static void
826 setFOV (double fov)
827 {
828   globals->get_current_view()->set_fov( fov );
829 }
830
831 static long
832 getWarp ()
833 {
834   return globals->get_warp();
835 }
836
837 static void
838 setWarp (long warp)
839 {
840   globals->set_warp(warp);
841 }
842
843 static long
844 getWarpDelta ()
845 {
846   return globals->get_warp_delta();
847 }
848
849 static void
850 setWarpDelta (long delta)
851 {
852   globals->set_warp_delta(delta);
853 }
854
855 static void
856 setViewAxisLong (double axis)
857 {
858   axisLong = axis;
859 }
860
861 static void
862 setViewAxisLat (double axis)
863 {
864   axisLat = axis;
865 }
866
867 static bool
868 getWindingCCW ()
869 {
870   return winding_ccw;
871 }
872
873 static void
874 setWindingCCW (bool state)
875 {
876   winding_ccw = state;
877   if ( winding_ccw )
878     glFrontFace ( GL_CCW );
879   else
880     glFrontFace ( GL_CW );
881 }
882
883 static bool
884 getFullScreen ()
885 {
886 #if defined(FX) && !defined(WIN32)
887   return global_fullscreen;
888 #else
889   return false;
890 #endif
891 }
892
893 static void
894 setFullScreen (bool state)
895 {
896 #if defined(FX) && !defined(WIN32)
897   global_fullscreen = state;
898 #  if defined(XMESA_FX_FULLSCREEN) && defined(XMESA_FX_WINDOW)
899   XMesaSetFXmode( global_fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW );
900 #  endif
901 #endif
902 }
903
904 static bool
905 getFDMDataLogging ()
906 {
907   return fdm_data_logging;
908 }
909
910 static void
911 setFDMDataLogging (bool state)
912 {
913                                 // kludge; no getter or setter available
914   if (state != fdm_data_logging) {
915     fgToggleFDMdataLogging();
916     fdm_data_logging = state;
917   }
918 }
919
920
921 \f
922 ////////////////////////////////////////////////////////////////////////
923 // Tie the properties.
924 ////////////////////////////////////////////////////////////////////////
925
926 void
927 fgInitProps ()
928 {
929                                 // Simulation
930   fgTie("/sim/freeze", getFreeze, setFreeze);
931   fgTie("/sim/aircraft-dir", getAircraftDir, setAircraftDir);
932   fgTie("/sim/view/offset-deg", getViewOffset, setViewOffset);
933   fgSetArchivable("/sim/view/offset-deg");
934   fgTie("/sim/view/goal-offset-deg", getGoalViewOffset, setGoalViewOffset);
935   fgSetArchivable("/sim/view/goal-offset-deg");
936   fgTie("/sim/time/gmt", getDateString, setDateString);
937   fgSetArchivable("/sim/time/gmt");
938   fgTie("/sim/time/gmt-string", getGMTString);
939   fgTie("/sim/rendering/textures", getTextures, setTextures);
940
941                                 // Orientation
942   fgTie("/orientation/heading-magnetic-deg", getHeadingMag);
943
944                                 // Engine
945   fgTie("/engines/engine[0]/rpm", getRPM);
946   fgTie("/engines/engine[0]/egt-degf", getEGT);
947   fgTie("/engines/engine[0]/cht-degf", getCHT);
948   fgTie("/engines/engine[0]/mp-osi", getMP);
949   fgTie("/engines/engine[0]/fuel-flow-gph", getFuelFlow);
950
951   //consumables
952   fgTie("/consumables/fuel/tank[0]/level-gal_us",
953         getTank1Fuel, setTank1Fuel, false);
954   fgSetArchivable("/consumables/fuel/tank[0]/level-gal_us");
955   fgTie("/consumables/fuel/tank[1]/level-gal_us",
956         getTank2Fuel, setTank2Fuel, false);
957   fgSetArchivable("/consumables/fuel/tank[1]/level-gal_us");
958
959                                 // Autopilot
960   fgTie("/autopilot/locks/altitude", getAPAltitudeLock, setAPAltitudeLock);
961   fgSetArchivable("/autopilot/locks/altitude");
962   fgTie("/autopilot/settings/altitude-ft", getAPAltitude, setAPAltitude);
963   fgSetArchivable("/autopilot/settings/altitude-ft");
964   fgTie("/autopilot/locks/glide-slope", getAPGSLock, setAPGSLock);
965   fgSetArchivable("/autopilot/locks/glide-slope");
966   fgTie("/autopilot/locks/terrain", getAPTerrainLock, setAPTerrainLock);
967   fgSetArchivable("/autopilot/locks/terrain");
968   fgTie("/autopilot/settings/climb-rate-fpm", getAPClimb, setAPClimb, false);
969   fgSetArchivable("/autopilot/settings/climb-rate-fpm");
970   fgTie("/autopilot/locks/heading", getAPHeadingLock, setAPHeadingLock);
971   fgSetArchivable("/autopilot/locks/heading");
972   fgTie("/autopilot/settings/heading-bug-deg",
973         getAPHeadingBug, setAPHeadingBug, false);
974   fgSetArchivable("/autopilot/settings/heading-bug-deg");
975   fgTie("/autopilot/locks/wing-leveler", getAPWingLeveler, setAPWingLeveler);
976   fgSetArchivable("/autopilot/locks/wing-leveler");
977   fgTie("/autopilot/locks/nav[0]", getAPNAV1Lock, setAPNAV1Lock);
978   fgSetArchivable("/autopilot/locks/nav[0]");
979   fgTie("/autopilot/locks/auto-throttle",
980         getAPAutoThrottleLock, setAPAutoThrottleLock);
981   fgSetArchivable("/autopilot/locks/auto-throttle");
982   fgTie("/autopilot/control-overrides/rudder",
983         getAPRudderControl, setAPRudderControl);
984   fgSetArchivable("/autopilot/control-overrides/rudder");
985   fgTie("/autopilot/control-overrides/elevator",
986         getAPElevatorControl, setAPElevatorControl);
987   fgSetArchivable("/autopilot/control-overrides/elevator");
988   fgTie("/autopilot/control-overrides/throttle",
989         getAPThrottleControl, setAPThrottleControl);
990   fgSetArchivable("/autopilot/control-overrides/throttle");
991
992                                 // Environment
993   fgTie("/environment/visibility-m", getVisibility, setVisibility);
994   fgSetArchivable("/environment/visibility-m");
995   fgTie("/environment/wind-north-fps", getWindNorth, setWindNorth);
996   fgSetArchivable("/environment/wind-north-fps");
997   fgTie("/environment/wind-east-fps", getWindEast, setWindEast);
998   fgSetArchivable("/environment/wind-east-fps");
999   fgTie("/environment/wind-down-fps", getWindDown, setWindDown);
1000   fgSetArchivable("/environment/wind-down-fps");
1001
1002   fgTie("/environment/magnetic-variation-deg", getMagVar);
1003   fgTie("/environment/magnetic-dip-deg", getMagDip);
1004
1005                                 // View
1006   fgTie("/sim/field-of-view", getFOV, setFOV);
1007   fgSetArchivable("/sim/field-of-view");
1008   fgTie("/sim/time/warp", getWarp, setWarp, false);
1009   fgTie("/sim/time/warp-delta", getWarpDelta, setWarpDelta);
1010   fgTie("/sim/view/axes/long", (double(*)())0, setViewAxisLong);
1011   fgTie("/sim/view/axes/lat", (double(*)())0, setViewAxisLat);
1012
1013                                 // Misc. Temporary junk.
1014   fgTie("/sim/temp/winding-ccw", getWindingCCW, setWindingCCW);
1015   fgTie("/sim/temp/full-screen", getFullScreen, setFullScreen);
1016   fgTie("/sim/temp/fdm-data-logging", getFDMDataLogging, setFDMDataLogging);
1017         
1018 }
1019
1020
1021 void
1022 fgUpdateProps ()
1023 {
1024   _set_view_from_axes();
1025 }
1026
1027
1028 \f
1029 ////////////////////////////////////////////////////////////////////////
1030 // Save and restore.
1031 ////////////////////////////////////////////////////////////////////////
1032
1033
1034 /**
1035  * Save the current state of the simulator to a stream.
1036  */
1037 bool
1038 fgSaveFlight (ostream &output)
1039 {
1040   return writeProperties(output, globals->get_props());
1041 }
1042
1043
1044 /**
1045  * Restore the current state of the simulator from a stream.
1046  */
1047 bool
1048 fgLoadFlight (istream &input)
1049 {
1050   SGPropertyNode props;
1051   if (readProperties(input, &props)) {
1052     copyProperties(&props, globals->get_props());
1053                                 // When loading a flight, make it the
1054                                 // new initial state.
1055     globals->saveInitialState();
1056   } else {
1057     SG_LOG(SG_INPUT, SG_ALERT, "Error restoring flight; aborted");
1058     return false;
1059   }
1060
1061   return true;
1062 }
1063
1064 // end of fg_props.cxx