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