1 // fg_props.cxx -- support for FlightGear properties.
3 // Written by David Megginson, started 2000.
5 // Copyright (C) 2000, 2001 David Megginson - david@megginson.com
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 # include <simgear/compiler.h>
27 #include <simgear/misc/exception.hxx>
31 #include <ATC/ATCdisplay.hxx>
32 #include <Autopilot/newauto.hxx>
33 #include <Aircraft/aircraft.hxx>
34 #include <Time/tmp.hxx>
35 #include <FDM/UIUCModel/uiuc_aircraftdir.h>
36 #ifndef FG_OLD_WEATHER
37 # include <WeatherCM/FGLocalWeatherDatabase.h>
39 # include <Weather/weather.hxx>
41 #include <Objects/matlib.hxx>
45 #include "globals.hxx"
47 #include "fg_props.hxx"
48 #include "viewmgr.hxx"
50 #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
51 SG_USING_STD(istream);
52 SG_USING_STD(ostream);
55 static double getWindNorth ();
56 static double getWindEast ();
57 static double getWindDown ();
59 // Allow the view to be set from two axes (i.e. a joystick hat)
60 // This needs to be in FGViewer itself, somehow.
61 static double axisLong = 0.0;
62 static double axisLat = 0.0;
64 static bool winding_ccw = true; // FIXME: temporary
66 static bool fdm_data_logging = false; // FIXME: temporary
73 _set_view_from_axes ()
75 // Take no action when hat is centered
76 if ( ( axisLong < 0.01 ) &&
77 ( axisLong > -0.01 ) &&
85 /* Do all the quick and easy cases */
86 if (axisLong < 0) { // Longitudinal axis forward
87 if (axisLat == axisLong)
89 else if (axisLat == - axisLong)
91 else if (axisLat == 0)
93 } else if (axisLong > 0) { // Longitudinal axis backward
94 if (axisLat == - axisLong)
96 else if (axisLat == axisLong)
98 else if (axisLat == 0)
100 } else if (axisLong == 0) { // Longitudinal axis neutral
103 else if (axisLat > 0)
105 else return; /* And assertion failure maybe? */
108 /* Do all the difficult cases */
110 viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axisLat, -axisLong );
111 if ( viewDir < -1 ) viewDir += 360;
113 // SG_LOG(SG_INPUT, SG_ALERT, "Joystick Lat=" << axisLat << " and Long="
114 // << axisLong << " gave angle=" << viewDir );
116 globals->get_current_view()->set_goal_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
117 // globals->get_current_view()->set_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
121 ////////////////////////////////////////////////////////////////////////
122 // Default property bindings (not yet handled by any module).
123 ////////////////////////////////////////////////////////////////////////
125 struct LogClassMapping {
128 LogClassMapping(sgDebugClass cc, string nname) { c = cc; name = nname; }
131 LogClassMapping log_class_mappings [] = {
132 LogClassMapping(SG_NONE, "none"),
133 LogClassMapping(SG_TERRAIN, "terrain"),
134 LogClassMapping(SG_ASTRO, "astro"),
135 LogClassMapping(SG_FLIGHT, "flight"),
136 LogClassMapping(SG_INPUT, "input"),
137 LogClassMapping(SG_GL, "gl"),
138 LogClassMapping(SG_VIEW, "view"),
139 LogClassMapping(SG_COCKPIT, "cockpit"),
140 LogClassMapping(SG_GENERAL, "general"),
141 LogClassMapping(SG_MATH, "math"),
142 LogClassMapping(SG_EVENT, "event"),
143 LogClassMapping(SG_AIRCRAFT, "aircraft"),
144 LogClassMapping(SG_AUTOPILOT, "autopilot"),
145 LogClassMapping(SG_IO, "io"),
146 LogClassMapping(SG_CLIPPER, "clipper"),
147 LogClassMapping(SG_NETWORK, "network"),
148 LogClassMapping(SG_UNDEFD, "")
153 * Get the logging classes.
158 sgDebugClass classes = logbuf::get_log_classes();
160 for (int i = 0; log_class_mappings[i].c != SG_UNDEFD; i++) {
161 if ((classes&log_class_mappings[i].c) > 0) {
162 if (result != (string)"")
164 result += log_class_mappings[i].name;
171 static void addLoggingClass (const string &name)
173 sgDebugClass classes = logbuf::get_log_classes();
174 for (int i = 0; log_class_mappings[i].c != SG_UNDEFD; i++) {
175 if (name == log_class_mappings[i].name) {
176 logbuf::set_log_classes(sgDebugClass(classes|log_class_mappings[i].c));
180 SG_LOG(SG_GENERAL, SG_ALERT, "Unknown logging class: " << name);
185 * Set the logging classes.
188 setLoggingClasses (string classes)
190 logbuf::set_log_classes(SG_NONE);
192 if (classes == "none") {
193 SG_LOG(SG_GENERAL, SG_INFO, "Disabled all logging classes");
197 if (classes == "" || classes == "all") { // default
198 logbuf::set_log_classes(SG_ALL);
199 SG_LOG(SG_GENERAL, SG_INFO, "Enabled all logging classes: "
200 << getLoggingClasses());
204 string rest = classes;
206 int sep = rest.find('|');
208 name = rest.substr(0, sep);
209 rest = rest.substr(sep+1);
210 addLoggingClass(name);
211 sep = rest.find('|');
213 addLoggingClass(rest);
214 SG_LOG(SG_GENERAL, SG_INFO, "Set logging classes to "
215 << getLoggingClasses());
220 * Get the logging priority.
223 getLoggingPriority ()
225 switch (logbuf::get_log_priority()) {
237 SG_LOG(SG_GENERAL, SG_WARN, "Internal: Unknown logging priority number: "
238 << logbuf::get_log_priority());
245 * Set the logging priority.
248 setLoggingPriority (string priority)
250 if (priority == "bulk") {
251 logbuf::set_log_priority(SG_BULK);
252 } else if (priority == "debug") {
253 logbuf::set_log_priority(SG_DEBUG);
254 } else if (priority == "" || priority == "info") { // default
255 logbuf::set_log_priority(SG_INFO);
256 } else if (priority == "warn") {
257 logbuf::set_log_priority(SG_WARN);
258 } else if (priority == "alert") {
259 logbuf::set_log_priority(SG_ALERT);
261 SG_LOG(SG_GENERAL, SG_WARN, "Unknown logging priority " << priority);
263 SG_LOG(SG_GENERAL, SG_INFO, "Logging priority is " << getLoggingPriority());
268 * Get the pause state of the sim.
273 return globals->get_freeze();
278 * Set the pause state of the sim.
281 setFreeze (bool freeze)
283 globals->set_freeze(freeze);
286 current_atcdisplay->CancelRepeatingMessage();
287 current_atcdisplay->RegisterRepeatingMessage("**** SIM IS FROZEN **** SIM IS FROZEN ****");
290 current_atcdisplay->CancelRepeatingMessage();
295 * Return the current aircraft directory (UIUC) as a string.
305 * Set the current aircraft directory (UIUC).
308 setAircraftDir (string dir)
310 if (getAircraftDir() != dir) {
312 // needReinit(); FIXME!!
318 * Get the current view offset in degrees.
323 return (globals->get_current_view()
324 ->get_view_offset() * SGD_RADIANS_TO_DEGREES);
329 setViewOffset (double offset)
331 globals->get_current_view()->set_view_offset(offset * SGD_DEGREES_TO_RADIANS);
337 return (globals->get_current_view()
338 ->get_goal_view_offset() * SGD_RADIANS_TO_DEGREES);
342 setGoalViewOffset (double offset)
344 while ( offset < 0 ) {
347 while ( offset > 360.0 ) {
350 // Snap to center if we are close
351 if ( fabs(offset) < 1.0 || fabs(offset) > 359.0 ) {
355 globals->get_current_view()
356 ->set_goal_view_offset(offset * SGD_DEGREES_TO_RADIANS);
361 * Pilot position offset from CG.
364 getPilotPositionXOffset ()
366 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
367 float * offset = pilot_view->get_pilot_offset();
372 setPilotPositionXOffset (float x)
374 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
375 float * offset = pilot_view->get_pilot_offset();
376 pilot_view->set_pilot_offset(x, offset[1], offset[2]);
380 getPilotPositionYOffset ()
382 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
383 float * offset = pilot_view->get_pilot_offset();
388 setPilotPositionYOffset (float y)
390 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
391 float * offset = pilot_view->get_pilot_offset();
392 pilot_view->set_pilot_offset(offset[0], y, offset[2]);
396 getPilotPositionZOffset ()
398 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
399 float * offset = pilot_view->get_pilot_offset();
404 setPilotPositionZOffset (float z)
406 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
407 float * offset = pilot_view->get_pilot_offset();
408 pilot_view->set_pilot_offset(offset[0], offset[1], z);
413 * Return the current Zulu time.
420 struct tm * t = globals->get_time_params()->getGmt();
421 sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d",
422 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
423 t->tm_hour, t->tm_min, t->tm_sec);
430 * Set the current Zulu time.
433 setDateString (string date_string)
435 SGTime * st = globals->get_time_params();
436 struct tm * current_time = st->getGmt();
439 // Scan for basic ISO format
440 // YYYY-MM-DDTHH:MM:SS
441 int ret = sscanf(date_string.c_str(), "%d-%d-%dT%d:%d:%d",
442 &(new_time.tm_year), &(new_time.tm_mon),
443 &(new_time.tm_mday), &(new_time.tm_hour),
444 &(new_time.tm_min), &(new_time.tm_sec));
446 // Be pretty picky about this, so
447 // that strange things don't happen
448 // if the save file has been edited
451 SG_LOG(SG_INPUT, SG_ALERT, "Date/time string " << date_string
452 << " not in YYYY-MM-DDTHH:MM:SS format; skipped");
456 // OK, it looks like we got six
457 // values, one way or another.
458 new_time.tm_year -= 1900;
459 new_time.tm_mon -= 1;
461 // Now, tell flight gear to use
462 // the new time. This was far
463 // too difficult, by the way.
465 mktime(&new_time) - mktime(current_time) + globals->get_warp();
466 double lon = current_aircraft.fdm_state->get_Longitude();
467 double lat = current_aircraft.fdm_state->get_Latitude();
468 globals->set_warp(warp);
469 st->update(lon, lat, warp);
470 fgUpdateSkyAndLightingParams();
474 * Return the GMT as a string.
481 struct tm * t = globals->get_time_params()->getGmt();
482 sprintf(buf, " %.2d:%.2d:%.2d",
483 t->tm_hour, t->tm_min, t->tm_sec);
490 * Get the texture rendering state.
495 return (material_lib.get_step() == 0);
500 * Set the texture rendering state.
503 setTextures (bool textures)
506 material_lib.set_step(0);
508 material_lib.set_step(1);
513 * Return the magnetic variation
518 return globals->get_mag()->get_magvar() * SGD_RADIANS_TO_DEGREES;
523 * Return the magnetic dip
528 return globals->get_mag()->get_magdip() * SGD_RADIANS_TO_DEGREES;
533 * Return the current heading in degrees.
538 return current_aircraft.fdm_state->get_Psi() * SGD_RADIANS_TO_DEGREES - getMagVar();
543 * Return the fuel level in tank 1
548 return current_aircraft.fdm_state->get_Tank1Fuel();
552 setTank1Fuel ( double gals )
554 current_aircraft.fdm_state->set_Tank1Fuel( gals );
558 * Return the fuel level in tank 2
563 return current_aircraft.fdm_state->get_Tank2Fuel();
567 setTank2Fuel ( double gals )
569 current_aircraft.fdm_state->set_Tank2Fuel( gals );
574 * Get the autopilot altitude lock (true=on).
579 return (current_autopilot->get_AltitudeEnabled() &&
580 current_autopilot->get_AltitudeMode()
581 == FGAutopilot::FG_ALTITUDE_LOCK);
586 * Set the autopilot altitude lock (true=on).
589 setAPAltitudeLock (bool lock)
592 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
593 if (current_autopilot->get_AltitudeMode() == FGAutopilot::FG_ALTITUDE_LOCK)
594 current_autopilot->set_AltitudeEnabled(lock);
599 * Get the autopilot target altitude in feet.
604 return current_autopilot->get_TargetAltitude() * SG_METER_TO_FEET;
609 * Set the autopilot target altitude in feet.
612 setAPAltitude (double altitude)
614 current_autopilot->set_TargetAltitude( altitude * SG_FEET_TO_METER );
618 * Get the autopilot altitude lock (true=on).
623 return (current_autopilot->get_AltitudeEnabled() &&
624 (current_autopilot->get_AltitudeMode()
625 == FGAutopilot::FG_ALTITUDE_GS1));
630 * Set the autopilot altitude lock (true=on).
633 setAPGSLock (bool lock)
636 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_GS1);
637 if (current_autopilot->get_AltitudeMode() == FGAutopilot::FG_ALTITUDE_GS1)
638 current_autopilot->set_AltitudeEnabled(lock);
643 * Get the autopilot terrain lock (true=on).
648 return (current_autopilot->get_AltitudeEnabled() &&
649 (current_autopilot->get_AltitudeMode()
650 == FGAutopilot::FG_ALTITUDE_TERRAIN));
655 * Set the autopilot terrain lock (true=on).
658 setAPTerrainLock (bool lock)
661 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_TERRAIN);
663 ->set_TargetAGL(current_aircraft.fdm_state->get_Altitude_AGL() *
665 cout << "Target AGL = "
666 << current_aircraft.fdm_state->get_Altitude_AGL() * SG_FEET_TO_METER
669 if (current_autopilot->get_AltitudeMode() == FGAutopilot::FG_ALTITUDE_TERRAIN)
670 current_autopilot->set_AltitudeEnabled(lock);
675 * Get the autopilot target altitude in feet.
680 return current_autopilot->get_TargetClimbRate() * SG_METER_TO_FEET;
685 * Set the autopilot target altitude in feet.
688 setAPClimb (double rate)
690 current_autopilot->set_TargetClimbRate( rate * SG_FEET_TO_METER );
695 * Get the autopilot heading lock (true=on).
701 (current_autopilot->get_HeadingEnabled() &&
702 current_autopilot->get_HeadingMode() == DEFAULT_AP_HEADING_LOCK);
707 * Set the autopilot heading lock (true=on).
710 setAPHeadingLock (bool lock)
713 current_autopilot->set_HeadingMode(DEFAULT_AP_HEADING_LOCK);
714 if (current_autopilot->get_HeadingMode() == DEFAULT_AP_HEADING_LOCK)
715 current_autopilot->set_HeadingEnabled(lock);
720 * Get the autopilot heading bug in degrees.
725 return current_autopilot->get_DGTargetHeading();
730 * Set the autopilot heading bug in degrees.
733 setAPHeadingBug (double heading)
735 current_autopilot->set_DGTargetHeading( heading );
740 * Get the autopilot wing leveler lock (true=on).
746 (current_autopilot->get_HeadingEnabled() &&
747 current_autopilot->get_HeadingMode() == FGAutopilot::FG_TC_HEADING_LOCK);
752 * Set the autopilot wing leveler lock (true=on).
755 setAPWingLeveler (bool lock)
758 current_autopilot->set_HeadingMode(FGAutopilot::FG_TC_HEADING_LOCK);
759 if (current_autopilot->get_HeadingMode() == FGAutopilot::FG_TC_HEADING_LOCK)
760 current_autopilot->set_HeadingEnabled(lock);
764 * Return true if the autopilot is locked to NAV1.
770 (current_autopilot->get_HeadingEnabled() &&
771 current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
776 * Set the autopilot NAV1 lock.
779 setAPNAV1Lock (bool lock)
782 current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
783 if (current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1)
784 current_autopilot->set_HeadingEnabled(lock);
788 * Get the autopilot autothrottle lock.
791 getAPAutoThrottleLock ()
793 return current_autopilot->get_AutoThrottleEnabled();
798 * Set the autothrottle lock.
801 setAPAutoThrottleLock (bool lock)
803 current_autopilot->set_AutoThrottleEnabled(lock);
809 getAPRudderControl ()
811 if (getAPHeadingLock())
812 return current_autopilot->get_TargetHeading();
814 return globals->get_controls()->get_rudder();
819 setAPRudderControl (double value)
821 if (getAPHeadingLock()) {
822 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPRudderControl " << value );
823 value -= current_autopilot->get_TargetHeading();
824 current_autopilot->HeadingAdjust(value < 0.0 ? -1.0 : 1.0);
826 globals->get_controls()->set_rudder(value);
832 getAPElevatorControl ()
834 if (getAPAltitudeLock())
835 return current_autopilot->get_TargetAltitude();
837 return globals->get_controls()->get_elevator();
842 setAPElevatorControl (double value)
844 if (value != 0 && getAPAltitudeLock()) {
845 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPElevatorControl " << value );
846 value -= current_autopilot->get_TargetAltitude();
847 current_autopilot->AltitudeAdjust(value < 0.0 ? 100.0 : -100.0);
849 globals->get_controls()->set_elevator(value);
855 getAPThrottleControl ()
857 if (getAPAutoThrottleLock())
858 return 0.0; // always resets
860 return globals->get_controls()->get_throttle(0);
865 setAPThrottleControl (double value)
867 if (getAPAutoThrottleLock())
868 current_autopilot->AutoThrottleAdjust(value < 0.0 ? -0.01 : 0.01);
870 globals->get_controls()->set_throttle(FGControls::ALL_ENGINES, value);
875 * Get the current visibility (meters).
880 #ifndef FG_OLD_WEATHER
881 return WeatherDatabase->getWeatherVisibility();
883 return current_weather.get_visibility();
889 * Set the current visibility (meters).
892 setVisibility (double visibility)
894 #ifndef FG_OLD_WEATHER
895 WeatherDatabase->setWeatherVisibility(visibility);
897 current_weather.set_visibility(visibility);
902 * Get the current wind north velocity (feet/second).
907 return current_aircraft.fdm_state->get_V_north_airmass();
912 * Set the current wind north velocity (feet/second).
915 setWindNorth (double speed)
917 current_aircraft.fdm_state
918 ->set_Velocities_Local_Airmass(speed, getWindEast(), getWindDown());
923 * Get the current wind east velocity (feet/second).
928 return current_aircraft.fdm_state->get_V_east_airmass();
933 * Set the current wind east velocity (feet/second).
936 setWindEast (double speed)
938 cout << "Set wind-east to " << speed << endl;
939 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
946 * Get the current wind down velocity (feet/second).
951 return current_aircraft.fdm_state->get_V_down_airmass();
956 * Set the current wind down velocity (feet/second).
959 setWindDown (double speed)
961 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
967 * Set the current engine0 running flag.
970 setRunningFlag (bool flag)
972 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
973 current_aircraft.fdm_state->get_engine(0)->set_Running_Flag( flag );
978 * Set the current engine0 cranking flag.
980 //Although there is no real reason to want to tell the engine that it is cranking,
981 //this is currently necessary to avoid the cranking sound being played
982 //before the engine inits.
984 setCrankingFlag (bool flag)
986 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
987 current_aircraft.fdm_state->get_engine(0)->set_Cranking_Flag( flag );
994 return globals->get_current_view()->get_fov();
1001 globals->get_current_view()->set_fov( fov );
1008 return globals->get_warp();
1014 globals->set_warp(warp);
1020 return globals->get_warp_delta();
1024 setWarpDelta (long delta)
1026 globals->set_warp_delta(delta);
1030 setViewAxisLong (double axis)
1036 setViewAxisLat (double axis)
1048 setWindingCCW (bool state)
1050 winding_ccw = state;
1052 glFrontFace ( GL_CCW );
1054 glFrontFace ( GL_CW );
1060 #if defined(FX) && !defined(WIN32)
1061 return globals->get_fullscreen();
1068 setFullScreen (bool state)
1070 #if defined(FX) && !defined(WIN32)
1071 globals->set_fullscreen(state);
1072 # if defined(XMESA_FX_FULLSCREEN) && defined(XMESA_FX_WINDOW)
1073 XMesaSetFXmode( state ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW );
1079 getFDMDataLogging ()
1081 return fdm_data_logging;
1085 setFDMDataLogging (bool state)
1087 // kludge; no getter or setter available
1088 if (state != fdm_data_logging) {
1089 fgToggleFDMdataLogging();
1090 fdm_data_logging = state;
1095 ////////////////////////////////////////////////////////////////////////
1096 // Tie the properties.
1097 ////////////////////////////////////////////////////////////////////////
1103 fgTie("/sim/logging/priority", getLoggingPriority, setLoggingPriority);
1104 fgTie("/sim/logging/classes", getLoggingClasses, setLoggingClasses);
1105 fgTie("/sim/freeze", getFreeze, setFreeze);
1106 fgTie("/sim/aircraft-dir", getAircraftDir, setAircraftDir);
1107 fgTie("/sim/view/offset-deg", getViewOffset, setViewOffset, false);
1108 fgSetArchivable("/sim/view/offset-deg");
1109 fgTie("/sim/view/goal-offset-deg", getGoalViewOffset, setGoalViewOffset, false);
1110 fgSetArchivable("/sim/view/goal-offset-deg");
1111 fgTie("/sim/view/pilot/x-offset-m",
1112 getPilotPositionXOffset, setPilotPositionXOffset);
1113 fgSetArchivable("/sim/view/pilot/x-offset-m");
1114 fgTie("/sim/view/pilot/y-offset-m",
1115 getPilotPositionYOffset, setPilotPositionYOffset);
1116 fgSetArchivable("/sim/view/pilot/y-offset-m");
1117 fgTie("/sim/view/pilot/z-offset-m",
1118 getPilotPositionZOffset, setPilotPositionZOffset);
1119 fgSetArchivable("/sim/view/pilot/z-offset-m");
1120 fgTie("/sim/time/gmt", getDateString, setDateString);
1121 fgSetArchivable("/sim/time/gmt");
1122 fgTie("/sim/time/gmt-string", getGMTString);
1123 fgTie("/sim/rendering/textures", getTextures, setTextures);
1126 fgTie("/orientation/heading-magnetic-deg", getHeadingMag);
1129 fgTie("/consumables/fuel/tank[0]/level-gal_us",
1130 getTank1Fuel, setTank1Fuel, false);
1131 fgSetArchivable("/consumables/fuel/tank[0]/level-gal_us");
1132 fgTie("/consumables/fuel/tank[1]/level-gal_us",
1133 getTank2Fuel, setTank2Fuel, false);
1134 fgSetArchivable("/consumables/fuel/tank[1]/level-gal_us");
1137 fgTie("/autopilot/locks/altitude", getAPAltitudeLock, setAPAltitudeLock);
1138 fgSetArchivable("/autopilot/locks/altitude");
1139 fgTie("/autopilot/settings/altitude-ft", getAPAltitude, setAPAltitude);
1140 fgSetArchivable("/autopilot/settings/altitude-ft");
1141 fgTie("/autopilot/locks/glide-slope", getAPGSLock, setAPGSLock);
1142 fgSetArchivable("/autopilot/locks/glide-slope");
1143 fgTie("/autopilot/locks/terrain", getAPTerrainLock, setAPTerrainLock);
1144 fgSetArchivable("/autopilot/locks/terrain");
1145 fgTie("/autopilot/settings/climb-rate-fpm", getAPClimb, setAPClimb, false);
1146 fgSetArchivable("/autopilot/settings/climb-rate-fpm");
1147 fgTie("/autopilot/locks/heading", getAPHeadingLock, setAPHeadingLock);
1148 fgSetArchivable("/autopilot/locks/heading");
1149 fgTie("/autopilot/settings/heading-bug-deg",
1150 getAPHeadingBug, setAPHeadingBug);
1151 fgSetArchivable("/autopilot/settings/heading-bug-deg");
1152 fgTie("/autopilot/locks/wing-leveler", getAPWingLeveler, setAPWingLeveler);
1153 fgSetArchivable("/autopilot/locks/wing-leveler");
1154 fgTie("/autopilot/locks/nav[0]", getAPNAV1Lock, setAPNAV1Lock);
1155 fgSetArchivable("/autopilot/locks/nav[0]");
1156 fgTie("/autopilot/locks/auto-throttle",
1157 getAPAutoThrottleLock, setAPAutoThrottleLock);
1158 fgSetArchivable("/autopilot/locks/auto-throttle");
1159 fgTie("/autopilot/control-overrides/rudder",
1160 getAPRudderControl, setAPRudderControl);
1161 fgSetArchivable("/autopilot/control-overrides/rudder");
1162 fgTie("/autopilot/control-overrides/elevator",
1163 getAPElevatorControl, setAPElevatorControl);
1164 fgSetArchivable("/autopilot/control-overrides/elevator");
1165 fgTie("/autopilot/control-overrides/throttle",
1166 getAPThrottleControl, setAPThrottleControl);
1167 fgSetArchivable("/autopilot/control-overrides/throttle");
1170 fgTie("/environment/visibility-m", getVisibility, setVisibility);
1171 fgSetArchivable("/environment/visibility-m");
1172 fgTie("/environment/wind-north-fps", getWindNorth, setWindNorth);
1173 fgSetArchivable("/environment/wind-north-fps");
1174 fgTie("/environment/wind-east-fps", getWindEast, setWindEast);
1175 fgSetArchivable("/environment/wind-east-fps");
1176 fgTie("/environment/wind-down-fps", getWindDown, setWindDown);
1177 fgSetArchivable("/environment/wind-down-fps");
1179 fgTie("/environment/magnetic-variation-deg", getMagVar);
1180 fgTie("/environment/magnetic-dip-deg", getMagDip);
1183 fgTie("/sim/field-of-view", getFOV, setFOV);
1184 fgSetArchivable("/sim/field-of-view");
1185 fgTie("/sim/time/warp", getWarp, setWarp, false);
1186 fgTie("/sim/time/warp-delta", getWarpDelta, setWarpDelta);
1187 fgTie("/sim/view/axes/long", (double(*)())0, setViewAxisLong);
1188 fgTie("/sim/view/axes/lat", (double(*)())0, setViewAxisLat);
1190 // Misc. Temporary junk.
1191 fgTie("/sim/temp/winding-ccw", getWindingCCW, setWindingCCW, false);
1192 fgTie("/sim/temp/full-screen", getFullScreen, setFullScreen);
1193 fgTie("/sim/temp/fdm-data-logging", getFDMDataLogging, setFDMDataLogging);
1201 _set_view_from_axes();
1206 ////////////////////////////////////////////////////////////////////////
1207 // Save and restore.
1208 ////////////////////////////////////////////////////////////////////////
1212 * Save the current state of the simulator to a stream.
1215 fgSaveFlight (ostream &output)
1218 writeProperties(output, globals->get_props());
1219 } catch (const sg_exception &e) {
1220 guiErrorMessage("Error saving flight: ", e);
1228 * Restore the current state of the simulator from a stream.
1231 fgLoadFlight (istream &input)
1233 SGPropertyNode props;
1235 readProperties(input, &props);
1236 } catch (const sg_exception &e) {
1237 guiErrorMessage("Error reading saved flight: ", e);
1240 copyProperties(&props, globals->get_props());
1241 // When loading a flight, make it the
1242 // new initial state.
1243 globals->saveInitialState();
1249 ////////////////////////////////////////////////////////////////////////
1250 // Implementation of FGCondition.
1251 ////////////////////////////////////////////////////////////////////////
1253 FGCondition::FGCondition ()
1257 FGCondition::~FGCondition ()
1263 ////////////////////////////////////////////////////////////////////////
1264 // Implementation of FGPropertyCondition.
1265 ////////////////////////////////////////////////////////////////////////
1267 FGPropertyCondition::FGPropertyCondition (const string &propname)
1268 : _node(fgGetNode(propname, true))
1272 FGPropertyCondition::~FGPropertyCondition ()
1278 ////////////////////////////////////////////////////////////////////////
1279 // Implementation of FGNotCondition.
1280 ////////////////////////////////////////////////////////////////////////
1282 FGNotCondition::FGNotCondition (FGCondition * condition)
1283 : _condition(condition)
1287 FGNotCondition::~FGNotCondition ()
1293 FGNotCondition::test () const
1295 return !(_condition->test());
1300 ////////////////////////////////////////////////////////////////////////
1301 // Implementation of FGAndCondition.
1302 ////////////////////////////////////////////////////////////////////////
1304 FGAndCondition::FGAndCondition ()
1308 FGAndCondition::~FGAndCondition ()
1310 for (unsigned int i = 0; i < _conditions.size(); i++)
1311 delete _conditions[i];
1315 FGAndCondition::test () const
1317 int nConditions = _conditions.size();
1318 for (int i = 0; i < nConditions; i++) {
1319 if (!_conditions[i]->test())
1326 FGAndCondition::addCondition (FGCondition * condition)
1328 _conditions.push_back(condition);
1333 ////////////////////////////////////////////////////////////////////////
1334 // Implementation of FGOrCondition.
1335 ////////////////////////////////////////////////////////////////////////
1337 FGOrCondition::FGOrCondition ()
1341 FGOrCondition::~FGOrCondition ()
1343 for (unsigned int i = 0; i < _conditions.size(); i++)
1344 delete _conditions[i];
1348 FGOrCondition::test () const
1350 int nConditions = _conditions.size();
1351 for (int i = 0; i < nConditions; i++) {
1352 if (_conditions[i]->test())
1359 FGOrCondition::addCondition (FGCondition * condition)
1361 _conditions.push_back(condition);
1366 ////////////////////////////////////////////////////////////////////////
1367 // Implementation of FGComparisonCondition.
1368 ////////////////////////////////////////////////////////////////////////
1371 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
1373 switch (left->getType()) {
1374 case SGPropertyNode::BOOL: {
1375 bool v1 = left->getBoolValue();
1376 bool v2 = right->getBoolValue();
1378 return FGComparisonCondition::LESS_THAN;
1380 return FGComparisonCondition::GREATER_THAN;
1382 return FGComparisonCondition::EQUALS;
1385 case SGPropertyNode::INT: {
1386 int v1 = left->getIntValue();
1387 int v2 = right->getIntValue();
1389 return FGComparisonCondition::LESS_THAN;
1391 return FGComparisonCondition::GREATER_THAN;
1393 return FGComparisonCondition::EQUALS;
1396 case SGPropertyNode::LONG: {
1397 long v1 = left->getLongValue();
1398 long v2 = right->getLongValue();
1400 return FGComparisonCondition::LESS_THAN;
1402 return FGComparisonCondition::GREATER_THAN;
1404 return FGComparisonCondition::EQUALS;
1407 case SGPropertyNode::FLOAT: {
1408 float v1 = left->getFloatValue();
1409 float v2 = right->getFloatValue();
1411 return FGComparisonCondition::LESS_THAN;
1413 return FGComparisonCondition::GREATER_THAN;
1415 return FGComparisonCondition::EQUALS;
1418 case SGPropertyNode::DOUBLE: {
1419 double v1 = left->getDoubleValue();
1420 double v2 = right->getDoubleValue();
1422 return FGComparisonCondition::LESS_THAN;
1424 return FGComparisonCondition::GREATER_THAN;
1426 return FGComparisonCondition::EQUALS;
1429 case SGPropertyNode::STRING:
1430 case SGPropertyNode::NONE:
1431 case SGPropertyNode::UNSPECIFIED: {
1432 string v1 = left->getStringValue();
1433 string v2 = right->getStringValue();
1435 return FGComparisonCondition::LESS_THAN;
1437 return FGComparisonCondition::GREATER_THAN;
1439 return FGComparisonCondition::EQUALS;
1443 throw sg_exception("Unrecognized node type");
1448 FGComparisonCondition::FGComparisonCondition (Type type, bool reverse)
1457 FGComparisonCondition::~FGComparisonCondition ()
1459 delete _right_value;
1463 FGComparisonCondition::test () const
1465 // Always fail if incompletely specified
1466 if (_left_property == 0 ||
1467 (_right_property == 0 && _right_value == 0))
1470 // Get LESS_THAN, EQUALS, or GREATER_THAN
1472 doComparison(_left_property,
1473 (_right_property != 0 ? _right_property : _right_value));
1475 return (cmp == _type);
1477 return (cmp != _type);
1481 FGComparisonCondition::setLeftProperty (const string &propname)
1483 _left_property = fgGetNode(propname, true);
1487 FGComparisonCondition::setRightProperty (const string &propname)
1489 delete _right_value;
1491 _right_property = fgGetNode(propname, true);
1495 FGComparisonCondition::setRightValue (const SGPropertyNode *node)
1497 _right_property = 0;
1498 delete _right_value;
1499 _right_value = new SGPropertyNode(*node);
1504 ////////////////////////////////////////////////////////////////////////
1505 // Read a condition and use it if necessary.
1506 ////////////////////////////////////////////////////////////////////////
1508 // Forward declaration
1509 static FGCondition * readCondition (const SGPropertyNode * node);
1511 static FGCondition *
1512 readPropertyCondition (const SGPropertyNode * node)
1514 return new FGPropertyCondition(node->getStringValue());
1517 static FGCondition *
1518 readNotCondition (const SGPropertyNode * node)
1520 int nChildren = node->nChildren();
1521 for (int i = 0; i < nChildren; i++) {
1522 const SGPropertyNode * child = node->getChild(i);
1523 FGCondition * condition = readCondition(child);
1525 return new FGNotCondition(condition);
1527 SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition");
1531 static FGCondition *
1532 readAndConditions (const SGPropertyNode * node)
1534 FGAndCondition * andCondition = new FGAndCondition;
1535 int nChildren = node->nChildren();
1536 for (int i = 0; i < nChildren; i++) {
1537 const SGPropertyNode * child = node->getChild(i);
1538 FGCondition * condition = readCondition(child);
1540 andCondition->addCondition(condition);
1542 return andCondition;
1545 static FGCondition *
1546 readOrConditions (const SGPropertyNode * node)
1548 FGOrCondition * orCondition = new FGOrCondition;
1549 int nChildren = node->nChildren();
1550 for (int i = 0; i < nChildren; i++) {
1551 const SGPropertyNode * child = node->getChild(i);
1552 FGCondition * condition = readCondition(child);
1554 orCondition->addCondition(condition);
1559 static FGCondition *
1560 readComparison (const SGPropertyNode * node,
1561 FGComparisonCondition::Type type,
1564 FGComparisonCondition * condition = new FGComparisonCondition(type, reverse);
1565 condition->setLeftProperty(node->getStringValue("property[0]"));
1566 if (node->hasValue("property[1]"))
1567 condition->setRightProperty(node->getStringValue("property[1]"));
1569 condition->setRightValue(node->getChild("value", 0));
1574 static FGCondition *
1575 readCondition (const SGPropertyNode * node)
1577 const string &name = node->getName();
1578 if (name == "property")
1579 return readPropertyCondition(node);
1580 else if (name == "not")
1581 return readNotCondition(node);
1582 else if (name == "and")
1583 return readAndConditions(node);
1584 else if (name == "or")
1585 return readOrConditions(node);
1586 else if (name == "less-than")
1587 return readComparison(node, FGComparisonCondition::LESS_THAN, false);
1588 else if (name == "less-than-equals")
1589 return readComparison(node, FGComparisonCondition::GREATER_THAN, true);
1590 else if (name == "greater-than")
1591 return readComparison(node, FGComparisonCondition::GREATER_THAN, false);
1592 else if (name == "greater-than-equals")
1593 return readComparison(node, FGComparisonCondition::LESS_THAN, true);
1594 else if (name == "equals")
1595 return readComparison(node, FGComparisonCondition::EQUALS, false);
1596 else if (name == "not-equals")
1597 return readComparison(node, FGComparisonCondition::EQUALS, true);
1604 ////////////////////////////////////////////////////////////////////////
1605 // Implementation of FGConditional.
1606 ////////////////////////////////////////////////////////////////////////
1608 FGConditional::FGConditional ()
1613 FGConditional::~FGConditional ()
1619 FGConditional::setCondition (FGCondition * condition)
1622 _condition = condition;
1626 FGConditional::test () const
1628 return ((_condition == 0) || _condition->test());
1633 // The top-level is always an implicit 'and' group
1635 fgReadCondition (const SGPropertyNode * node)
1637 return readAndConditions(node);
1641 // end of fg_props.cxx