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