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 <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>
38 # include <Weather/weather.hxx>
40 #include <Objects/matlib.hxx>
45 #include "fg_props.hxx"
46 #include "viewmgr.hxx"
48 #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
49 SG_USING_STD(istream);
50 SG_USING_STD(ostream);
53 static double getWindNorth ();
54 static double getWindEast ();
55 static double getWindDown ();
57 // Allow the view to be set from two axes (i.e. a joystick hat)
58 // This needs to be in FGViewer itself, somehow.
59 static double axisLong = 0.0;
60 static double axisLat = 0.0;
62 static bool winding_ccw = true; // FIXME: temporary
64 static bool fdm_data_logging = false; // FIXME: temporary
71 _set_view_from_axes ()
73 // Take no action when hat is centered
74 if ( ( axisLong < 0.01 ) &&
75 ( axisLong > -0.01 ) &&
83 /* Do all the quick and easy cases */
84 if (axisLong < 0) { // Longitudinal axis forward
85 if (axisLat == axisLong)
87 else if (axisLat == - axisLong)
89 else if (axisLat == 0)
91 } else if (axisLong > 0) { // Longitudinal axis backward
92 if (axisLat == - axisLong)
94 else if (axisLat == axisLong)
96 else if (axisLat == 0)
98 } else if (axisLong == 0) { // Longitudinal axis neutral
101 else if (axisLat > 0)
103 else return; /* And assertion failure maybe? */
106 /* Do all the difficult cases */
108 viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axisLat, -axisLong );
109 if ( viewDir < -1 ) viewDir += 360;
111 // SG_LOG(SG_INPUT, SG_ALERT, "Joystick Lat=" << axisLat << " and Long="
112 // << axisLong << " gave angle=" << viewDir );
114 globals->get_current_view()->set_goal_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
115 // globals->get_current_view()->set_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
119 ////////////////////////////////////////////////////////////////////////
120 // Default property bindings (not yet handled by any module).
121 ////////////////////////////////////////////////////////////////////////
125 * Get the pause state of the sim.
130 return globals->get_freeze();
135 * Set the pause state of the sim.
138 setFreeze (bool freeze)
140 globals->set_freeze(freeze);
144 * Return the current aircraft directory (UIUC) as a string.
154 * Set the current aircraft directory (UIUC).
157 setAircraftDir (string dir)
159 if (getAircraftDir() != dir) {
161 // needReinit(); FIXME!!
167 * Get the current view offset in degrees.
172 return (globals->get_current_view()
173 ->get_view_offset() * SGD_RADIANS_TO_DEGREES);
178 setViewOffset (double offset)
180 globals->get_current_view()->set_view_offset(offset * SGD_DEGREES_TO_RADIANS);
186 return (globals->get_current_view()
187 ->get_goal_view_offset() * SGD_RADIANS_TO_DEGREES);
191 setGoalViewOffset (double offset)
193 while ( offset < 0 ) {
196 while ( offset > 360.0 ) {
199 // Snap to center if we are close
200 if ( fabs(offset) < 1.0 || fabs(offset) > 359.0 ) {
204 globals->get_current_view()
205 ->set_goal_view_offset(offset * SGD_DEGREES_TO_RADIANS);
210 * Pilot position offset from CG.
213 getPilotPositionXOffset ()
215 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
216 float * offset = pilot_view->get_pilot_offset();
221 setPilotPositionXOffset (float x)
223 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
224 float * offset = pilot_view->get_pilot_offset();
225 pilot_view->set_pilot_offset(x, offset[1], offset[2]);
229 getPilotPositionYOffset ()
231 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
232 float * offset = pilot_view->get_pilot_offset();
237 setPilotPositionYOffset (float y)
239 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
240 float * offset = pilot_view->get_pilot_offset();
241 pilot_view->set_pilot_offset(offset[0], y, offset[2]);
245 getPilotPositionZOffset ()
247 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
248 float * offset = pilot_view->get_pilot_offset();
253 setPilotPositionZOffset (float z)
255 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
256 float * offset = pilot_view->get_pilot_offset();
257 pilot_view->set_pilot_offset(offset[0], offset[1], z);
262 * Return the current Zulu time.
269 struct tm * t = globals->get_time_params()->getGmt();
270 sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d",
271 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
272 t->tm_hour, t->tm_min, t->tm_sec);
279 * Set the current Zulu time.
282 setDateString (string date_string)
284 SGTime * st = globals->get_time_params();
285 struct tm * current_time = st->getGmt();
288 // Scan for basic ISO format
289 // YYYY-MM-DDTHH:MM:SS
290 int ret = sscanf(date_string.c_str(), "%d-%d-%dT%d:%d:%d",
291 &(new_time.tm_year), &(new_time.tm_mon),
292 &(new_time.tm_mday), &(new_time.tm_hour),
293 &(new_time.tm_min), &(new_time.tm_sec));
295 // Be pretty picky about this, so
296 // that strange things don't happen
297 // if the save file has been edited
300 SG_LOG(SG_INPUT, SG_ALERT, "Date/time string " << date_string
301 << " not in YYYY-MM-DDTHH:MM:SS format; skipped");
305 // OK, it looks like we got six
306 // values, one way or another.
307 new_time.tm_year -= 1900;
308 new_time.tm_mon -= 1;
310 // Now, tell flight gear to use
311 // the new time. This was far
312 // too difficult, by the way.
314 mktime(&new_time) - mktime(current_time) + globals->get_warp();
315 double lon = current_aircraft.fdm_state->get_Longitude();
316 double lat = current_aircraft.fdm_state->get_Latitude();
317 globals->set_warp(warp);
318 st->update(lon, lat, warp);
319 fgUpdateSkyAndLightingParams();
323 * Return the GMT as a string.
330 struct tm * t = globals->get_time_params()->getGmt();
331 sprintf(buf, " %.2d:%.2d:%.2d",
332 t->tm_hour, t->tm_min, t->tm_sec);
339 * Get the texture rendering state.
344 return (material_lib.get_step() == 0);
349 * Set the texture rendering state.
352 setTextures (bool textures)
355 material_lib.set_step(0);
357 material_lib.set_step(1);
362 * Return the magnetic variation
367 return globals->get_mag()->get_magvar() * SGD_RADIANS_TO_DEGREES;
372 * Return the magnetic dip
377 return globals->get_mag()->get_magdip() * SGD_RADIANS_TO_DEGREES;
382 * Return the current heading in degrees.
387 return current_aircraft.fdm_state->get_Psi() * SGD_RADIANS_TO_DEGREES - getMagVar();
392 * Return the current engine0 rpm
397 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
398 return current_aircraft.fdm_state->get_engine(0)->get_RPM();
406 * Return the current engine0 EGT.
411 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
412 return current_aircraft.fdm_state->get_engine(0)->get_EGT();
419 * Return the current engine0 CHT.
424 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
425 return current_aircraft.fdm_state->get_engine(0)->get_CHT();
432 * Return the current engine0 Oil Temp.
437 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
438 return current_aircraft.fdm_state->get_engine(0)->get_Oil_Temp();
445 * Return the current engine0 Manifold Pressure.
450 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
451 return current_aircraft.fdm_state->get_engine(0)->get_Manifold_Pressure();
459 * Return the current engine0 fuel flow
464 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
465 return current_aircraft.fdm_state->get_engine(0)->get_Fuel_Flow();
472 * Return the current engine0 running flag
477 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
478 return current_aircraft.fdm_state->get_engine(0)->get_Running_Flag();
485 * Return the current engine0 cranking flag
490 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
491 return current_aircraft.fdm_state->get_engine(0)->get_Cranking_Flag();
498 * Return the fuel level in tank 1
503 return current_aircraft.fdm_state->get_Tank1Fuel();
507 setTank1Fuel ( double gals )
509 current_aircraft.fdm_state->set_Tank1Fuel( gals );
513 * Return the fuel level in tank 2
518 return current_aircraft.fdm_state->get_Tank2Fuel();
522 setTank2Fuel ( double gals )
524 current_aircraft.fdm_state->set_Tank2Fuel( gals );
529 * Get the autopilot altitude lock (true=on).
534 return (current_autopilot->get_AltitudeEnabled() &&
535 current_autopilot->get_AltitudeMode()
536 == FGAutopilot::FG_ALTITUDE_LOCK);
541 * Set the autopilot altitude lock (true=on).
544 setAPAltitudeLock (bool lock)
546 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
547 current_autopilot->set_AltitudeEnabled(lock);
552 * Get the autopilot target altitude in feet.
557 return current_autopilot->get_TargetAltitude() * SG_METER_TO_FEET;
562 * Set the autopilot target altitude in feet.
565 setAPAltitude (double altitude)
567 current_autopilot->set_TargetAltitude( altitude * SG_FEET_TO_METER );
571 * Get the autopilot altitude lock (true=on).
576 return (current_autopilot->get_AltitudeEnabled() &&
577 (current_autopilot->get_AltitudeMode()
578 == FGAutopilot::FG_ALTITUDE_GS1));
583 * Set the autopilot altitude lock (true=on).
586 setAPGSLock (bool lock)
588 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_GS1);
589 current_autopilot->set_AltitudeEnabled(lock);
594 * Get the autopilot terrain lock (true=on).
599 return (current_autopilot->get_AltitudeEnabled() &&
600 (current_autopilot->get_AltitudeMode()
601 == FGAutopilot::FG_ALTITUDE_TERRAIN));
606 * Set the autopilot terrain lock (true=on).
609 setAPTerrainLock (bool lock)
611 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_TERRAIN);
612 current_autopilot->set_AltitudeEnabled(lock);
613 current_autopilot->set_TargetAGL(
614 current_aircraft.fdm_state->get_Altitude_AGL() * SG_FEET_TO_METER
616 cout << "Target AGL = "
617 << current_aircraft.fdm_state->get_Altitude_AGL() * SG_FEET_TO_METER
623 * Get the autopilot target altitude in feet.
628 return current_autopilot->get_TargetClimbRate() * SG_METER_TO_FEET;
633 * Set the autopilot target altitude in feet.
636 setAPClimb (double rate)
638 current_autopilot->set_TargetClimbRate( rate * SG_FEET_TO_METER );
643 * Get the autopilot heading lock (true=on).
649 (current_autopilot->get_HeadingEnabled() &&
650 current_autopilot->get_HeadingMode() == DEFAULT_AP_HEADING_LOCK);
655 * Set the autopilot heading lock (true=on).
658 setAPHeadingLock (bool lock)
661 current_autopilot->set_HeadingMode(DEFAULT_AP_HEADING_LOCK);
662 current_autopilot->set_HeadingEnabled(true);
664 current_autopilot->set_HeadingEnabled(false);
670 * Get the autopilot heading bug in degrees.
675 return current_autopilot->get_DGTargetHeading();
680 * Set the autopilot heading bug in degrees.
683 setAPHeadingBug (double heading)
685 current_autopilot->set_DGTargetHeading( heading );
690 * Get the autopilot wing leveler lock (true=on).
696 (current_autopilot->get_HeadingEnabled() &&
697 current_autopilot->get_HeadingMode() == FGAutopilot::FG_TC_HEADING_LOCK);
702 * Set the autopilot wing leveler lock (true=on).
705 setAPWingLeveler (bool lock)
708 current_autopilot->set_HeadingMode(FGAutopilot::FG_TC_HEADING_LOCK);
709 current_autopilot->set_HeadingEnabled(true);
711 current_autopilot->set_HeadingEnabled(false);
716 * Return true if the autopilot is locked to NAV1.
722 (current_autopilot->get_HeadingEnabled() &&
723 current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
728 * Set the autopilot NAV1 lock.
731 setAPNAV1Lock (bool lock)
734 current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
735 current_autopilot->set_HeadingEnabled(true);
736 } else if (current_autopilot->get_HeadingMode() ==
737 FGAutopilot::FG_HEADING_NAV1) {
738 current_autopilot->set_HeadingEnabled(false);
743 * Get the autopilot autothrottle lock.
746 getAPAutoThrottleLock ()
748 return current_autopilot->get_AutoThrottleEnabled();
753 * Set the autothrottle lock.
756 setAPAutoThrottleLock (bool lock)
758 current_autopilot->set_AutoThrottleEnabled(lock);
764 getAPRudderControl ()
766 if (getAPHeadingLock())
767 return current_autopilot->get_TargetHeading();
769 return globals->get_controls()->get_rudder();
774 setAPRudderControl (double value)
776 if (getAPHeadingLock()) {
777 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPRudderControl " << value );
778 value -= current_autopilot->get_TargetHeading();
779 current_autopilot->HeadingAdjust(value < 0.0 ? -1.0 : 1.0);
781 globals->get_controls()->set_rudder(value);
787 getAPElevatorControl ()
789 if (getAPAltitudeLock())
790 return current_autopilot->get_TargetAltitude();
792 return globals->get_controls()->get_elevator();
797 setAPElevatorControl (double value)
799 if (getAPAltitudeLock()) {
800 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPElevatorControl " << value );
801 value -= current_autopilot->get_TargetAltitude();
802 current_autopilot->AltitudeAdjust(value < 0.0 ? 100.0 : -100.0);
804 globals->get_controls()->set_elevator(value);
810 getAPThrottleControl ()
812 if (getAPAutoThrottleLock())
813 return 0.0; // always resets
815 return globals->get_controls()->get_throttle(0);
820 setAPThrottleControl (double value)
822 if (getAPAutoThrottleLock())
823 current_autopilot->AutoThrottleAdjust(value < 0.0 ? -0.01 : 0.01);
825 globals->get_controls()->set_throttle(0, value);
830 * Get the current visibility (meters).
835 #ifndef FG_OLD_WEATHER
836 return WeatherDatabase->getWeatherVisibility();
838 return current_weather.get_visibility();
844 * Set the current visibility (meters).
847 setVisibility (double visibility)
849 #ifndef FG_OLD_WEATHER
850 WeatherDatabase->setWeatherVisibility(visibility);
852 current_weather.set_visibility(visibility);
857 * Get the current wind north velocity (feet/second).
862 return current_aircraft.fdm_state->get_V_north_airmass();
867 * Set the current wind north velocity (feet/second).
870 setWindNorth (double speed)
872 current_aircraft.fdm_state
873 ->set_Velocities_Local_Airmass(speed, getWindEast(), getWindDown());
878 * Get the current wind east velocity (feet/second).
883 return current_aircraft.fdm_state->get_V_east_airmass();
888 * Set the current wind east velocity (feet/second).
891 setWindEast (double speed)
893 cout << "Set wind-east to " << speed << endl;
894 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
901 * Get the current wind down velocity (feet/second).
906 return current_aircraft.fdm_state->get_V_down_airmass();
911 * Set the current wind down velocity (feet/second).
914 setWindDown (double speed)
916 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
922 * Set the current engine0 running flag.
925 setRunningFlag (bool flag)
927 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
928 current_aircraft.fdm_state->get_engine(0)->set_Running_Flag( flag );
933 * Set the current engine0 cranking flag.
935 //Although there is no real reason to want to tell the engine that it is cranking,
936 //this is currently necessary to avoid the cranking sound being played
937 //before the engine inits.
939 setCrankingFlag (bool flag)
941 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
942 current_aircraft.fdm_state->get_engine(0)->set_Cranking_Flag( flag );
949 return globals->get_current_view()->get_fov();
956 globals->get_current_view()->set_fov( fov );
963 return globals->get_warp();
969 globals->set_warp(warp);
975 return globals->get_warp_delta();
979 setWarpDelta (long delta)
981 globals->set_warp_delta(delta);
985 setViewAxisLong (double axis)
991 setViewAxisLat (double axis)
1003 setWindingCCW (bool state)
1005 winding_ccw = state;
1007 glFrontFace ( GL_CCW );
1009 glFrontFace ( GL_CW );
1015 #if defined(FX) && !defined(WIN32)
1016 return global_fullscreen;
1023 setFullScreen (bool state)
1025 #if defined(FX) && !defined(WIN32)
1026 global_fullscreen = state;
1027 # if defined(XMESA_FX_FULLSCREEN) && defined(XMESA_FX_WINDOW)
1028 XMesaSetFXmode( global_fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW );
1034 getFDMDataLogging ()
1036 return fdm_data_logging;
1040 setFDMDataLogging (bool state)
1042 // kludge; no getter or setter available
1043 if (state != fdm_data_logging) {
1044 fgToggleFDMdataLogging();
1045 fdm_data_logging = state;
1050 ////////////////////////////////////////////////////////////////////////
1051 // Tie the properties.
1052 ////////////////////////////////////////////////////////////////////////
1058 fgTie("/sim/freeze", getFreeze, setFreeze);
1059 fgTie("/sim/aircraft-dir", getAircraftDir, setAircraftDir);
1060 fgTie("/sim/view/offset-deg", getViewOffset, setViewOffset);
1061 fgSetArchivable("/sim/view/offset-deg");
1062 fgTie("/sim/view/goal-offset-deg", getGoalViewOffset, setGoalViewOffset);
1063 fgSetArchivable("/sim/view/goal-offset-deg");
1064 fgTie("/sim/view/pilot/x-offset-m",
1065 getPilotPositionXOffset, setPilotPositionXOffset);
1066 fgSetArchivable("/sim/view/pilot/x-offset-m");
1067 fgTie("/sim/view/pilot/y-offset-m",
1068 getPilotPositionYOffset, setPilotPositionYOffset);
1069 fgSetArchivable("/sim/view/pilot/y-offset-m");
1070 fgTie("/sim/view/pilot/z-offset-m",
1071 getPilotPositionZOffset, setPilotPositionZOffset);
1072 fgSetArchivable("/sim/view/pilot/z-offset-m");
1073 fgTie("/sim/time/gmt", getDateString, setDateString);
1074 fgSetArchivable("/sim/time/gmt");
1075 fgTie("/sim/time/gmt-string", getGMTString);
1076 fgTie("/sim/rendering/textures", getTextures, setTextures);
1079 fgTie("/orientation/heading-magnetic-deg", getHeadingMag);
1082 fgTie("/engines/engine[0]/rpm", getRPM);
1083 fgTie("/engines/engine[0]/egt-degf", getEGT);
1084 fgTie("/engines/engine[0]/cht-degf", getCHT);
1085 fgTie("/engines/engine[0]/oil-temperature-degf", getOilTemp);
1086 fgTie("/engines/engine[0]/mp-osi", getMP);
1087 fgTie("/engines/engine[0]/fuel-flow-gph", getFuelFlow);
1088 fgTie("/engines/engine[0]/running", getRunningFlag, setRunningFlag);
1089 fgTie("/engines/engine[0]/cranking", getCrankingFlag, setCrankingFlag);
1092 fgTie("/consumables/fuel/tank[0]/level-gal_us",
1093 getTank1Fuel, setTank1Fuel, false);
1094 fgSetArchivable("/consumables/fuel/tank[0]/level-gal_us");
1095 fgTie("/consumables/fuel/tank[1]/level-gal_us",
1096 getTank2Fuel, setTank2Fuel, false);
1097 fgSetArchivable("/consumables/fuel/tank[1]/level-gal_us");
1100 fgTie("/autopilot/locks/altitude", getAPAltitudeLock, setAPAltitudeLock);
1101 fgSetArchivable("/autopilot/locks/altitude");
1102 fgTie("/autopilot/settings/altitude-ft", getAPAltitude, setAPAltitude);
1103 fgSetArchivable("/autopilot/settings/altitude-ft");
1104 fgTie("/autopilot/locks/glide-slope", getAPGSLock, setAPGSLock);
1105 fgSetArchivable("/autopilot/locks/glide-slope");
1106 fgTie("/autopilot/locks/terrain", getAPTerrainLock, setAPTerrainLock);
1107 fgSetArchivable("/autopilot/locks/terrain");
1108 fgTie("/autopilot/settings/agl-ft", getAPAltitude, setAPAltitude);
1109 fgSetArchivable("/autopilot/settings/agl-ft");
1110 fgTie("/autopilot/settings/climb-rate-fpm", getAPClimb, setAPClimb, false);
1111 fgSetArchivable("/autopilot/settings/climb-rate-fpm");
1112 fgTie("/autopilot/locks/heading", getAPHeadingLock, setAPHeadingLock);
1113 fgSetArchivable("/autopilot/locks/heading");
1114 fgTie("/autopilot/settings/heading-bug-deg",
1115 getAPHeadingBug, setAPHeadingBug, false);
1116 fgSetArchivable("/autopilot/settings/heading-bug-deg");
1117 fgTie("/autopilot/locks/wing-leveler", getAPWingLeveler, setAPWingLeveler);
1118 fgSetArchivable("/autopilot/locks/wing-leveler");
1119 fgTie("/autopilot/locks/nav[0]", getAPNAV1Lock, setAPNAV1Lock);
1120 fgSetArchivable("/autopilot/locks/nav[0]");
1121 fgTie("/autopilot/locks/auto-throttle",
1122 getAPAutoThrottleLock, setAPAutoThrottleLock);
1123 fgSetArchivable("/autopilot/locks/auto-throttle");
1124 fgTie("/autopilot/control-overrides/rudder",
1125 getAPRudderControl, setAPRudderControl);
1126 fgSetArchivable("/autopilot/control-overrides/rudder");
1127 fgTie("/autopilot/control-overrides/elevator",
1128 getAPElevatorControl, setAPElevatorControl);
1129 fgSetArchivable("/autopilot/control-overrides/elevator");
1130 fgTie("/autopilot/control-overrides/throttle",
1131 getAPThrottleControl, setAPThrottleControl);
1132 fgSetArchivable("/autopilot/control-overrides/throttle");
1135 fgTie("/environment/visibility-m", getVisibility, setVisibility);
1136 fgSetArchivable("/environment/visibility-m");
1137 fgTie("/environment/wind-north-fps", getWindNorth, setWindNorth);
1138 fgSetArchivable("/environment/wind-north-fps");
1139 fgTie("/environment/wind-east-fps", getWindEast, setWindEast);
1140 fgSetArchivable("/environment/wind-east-fps");
1141 fgTie("/environment/wind-down-fps", getWindDown, setWindDown);
1142 fgSetArchivable("/environment/wind-down-fps");
1144 fgTie("/environment/magnetic-variation-deg", getMagVar);
1145 fgTie("/environment/magnetic-dip-deg", getMagDip);
1148 fgTie("/sim/field-of-view", getFOV, setFOV);
1149 fgSetArchivable("/sim/field-of-view");
1150 fgTie("/sim/time/warp", getWarp, setWarp, false);
1151 fgTie("/sim/time/warp-delta", getWarpDelta, setWarpDelta);
1152 fgTie("/sim/view/axes/long", (double(*)())0, setViewAxisLong);
1153 fgTie("/sim/view/axes/lat", (double(*)())0, setViewAxisLat);
1155 // Misc. Temporary junk.
1156 fgTie("/sim/temp/winding-ccw", getWindingCCW, setWindingCCW, false);
1157 fgTie("/sim/temp/full-screen", getFullScreen, setFullScreen);
1158 fgTie("/sim/temp/fdm-data-logging", getFDMDataLogging, setFDMDataLogging);
1166 _set_view_from_axes();
1171 ////////////////////////////////////////////////////////////////////////
1172 // Save and restore.
1173 ////////////////////////////////////////////////////////////////////////
1177 * Save the current state of the simulator to a stream.
1180 fgSaveFlight (ostream &output)
1183 writeProperties(output, globals->get_props());
1184 } catch (const sg_exception &e) {
1185 guiErrorMessage("Error saving flight: ", e);
1193 * Restore the current state of the simulator from a stream.
1196 fgLoadFlight (istream &input)
1198 SGPropertyNode props;
1200 readProperties(input, &props);
1201 } catch (const sg_exception &e) {
1202 guiErrorMessage("Error reading saved flight: ", e);
1205 copyProperties(&props, globals->get_props());
1206 // When loading a flight, make it the
1207 // new initial state.
1208 globals->saveInitialState();
1214 ////////////////////////////////////////////////////////////////////////
1215 // Implementation of FGCondition.
1216 ////////////////////////////////////////////////////////////////////////
1218 FGCondition::FGCondition ()
1222 FGCondition::~FGCondition ()
1228 ////////////////////////////////////////////////////////////////////////
1229 // Implementation of FGPropertyCondition.
1230 ////////////////////////////////////////////////////////////////////////
1232 FGPropertyCondition::FGPropertyCondition (const string &propname)
1233 : _node(fgGetNode(propname, true))
1237 FGPropertyCondition::~FGPropertyCondition ()
1243 ////////////////////////////////////////////////////////////////////////
1244 // Implementation of FGNotCondition.
1245 ////////////////////////////////////////////////////////////////////////
1247 FGNotCondition::FGNotCondition (FGCondition * condition)
1248 : _condition(condition)
1252 FGNotCondition::~FGNotCondition ()
1258 FGNotCondition::test () const
1260 return !(_condition->test());
1265 ////////////////////////////////////////////////////////////////////////
1266 // Implementation of FGAndCondition.
1267 ////////////////////////////////////////////////////////////////////////
1269 FGAndCondition::FGAndCondition ()
1273 FGAndCondition::~FGAndCondition ()
1275 for (unsigned int i = 0; i < _conditions.size(); i++)
1276 delete _conditions[i];
1280 FGAndCondition::test () const
1282 int nConditions = _conditions.size();
1283 for (int i = 0; i < nConditions; i++) {
1284 if (!_conditions[i]->test())
1291 FGAndCondition::addCondition (FGCondition * condition)
1293 _conditions.push_back(condition);
1298 ////////////////////////////////////////////////////////////////////////
1299 // Implementation of FGOrCondition.
1300 ////////////////////////////////////////////////////////////////////////
1302 FGOrCondition::FGOrCondition ()
1306 FGOrCondition::~FGOrCondition ()
1308 for (unsigned int i = 0; i < _conditions.size(); i++)
1309 delete _conditions[i];
1313 FGOrCondition::test () const
1315 int nConditions = _conditions.size();
1316 for (int i = 0; i < nConditions; i++) {
1317 if (_conditions[i]->test())
1324 FGOrCondition::addCondition (FGCondition * condition)
1326 _conditions.push_back(condition);
1331 ////////////////////////////////////////////////////////////////////////
1332 // Implementation of FGComparisonCondition.
1333 ////////////////////////////////////////////////////////////////////////
1336 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
1338 switch (left->getType()) {
1339 case SGPropertyNode::BOOL: {
1340 bool v1 = left->getBoolValue();
1341 bool v2 = right->getBoolValue();
1343 return FGComparisonCondition::LESS_THAN;
1345 return FGComparisonCondition::GREATER_THAN;
1347 return FGComparisonCondition::EQUALS;
1350 case SGPropertyNode::INT: {
1351 int v1 = left->getIntValue();
1352 int v2 = right->getIntValue();
1354 return FGComparisonCondition::LESS_THAN;
1356 return FGComparisonCondition::GREATER_THAN;
1358 return FGComparisonCondition::EQUALS;
1361 case SGPropertyNode::LONG: {
1362 long v1 = left->getLongValue();
1363 long v2 = right->getLongValue();
1365 return FGComparisonCondition::LESS_THAN;
1367 return FGComparisonCondition::GREATER_THAN;
1369 return FGComparisonCondition::EQUALS;
1372 case SGPropertyNode::FLOAT: {
1373 float v1 = left->getFloatValue();
1374 float v2 = right->getFloatValue();
1376 return FGComparisonCondition::LESS_THAN;
1378 return FGComparisonCondition::GREATER_THAN;
1380 return FGComparisonCondition::EQUALS;
1383 case SGPropertyNode::DOUBLE: {
1384 double v1 = left->getDoubleValue();
1385 double v2 = right->getDoubleValue();
1387 return FGComparisonCondition::LESS_THAN;
1389 return FGComparisonCondition::GREATER_THAN;
1391 return FGComparisonCondition::EQUALS;
1394 case SGPropertyNode::STRING:
1395 case SGPropertyNode::NONE:
1396 case SGPropertyNode::UNSPECIFIED: {
1397 string v1 = left->getStringValue();
1398 string v2 = right->getStringValue();
1400 return FGComparisonCondition::LESS_THAN;
1402 return FGComparisonCondition::GREATER_THAN;
1404 return FGComparisonCondition::EQUALS;
1408 throw sg_exception("Unrecognized node type");
1413 FGComparisonCondition::FGComparisonCondition (Type type, bool reverse)
1422 FGComparisonCondition::~FGComparisonCondition ()
1424 delete _right_value;
1428 FGComparisonCondition::test () const
1430 // Always fail if incompletely specified
1431 if (_left_property == 0 ||
1432 (_right_property == 0 && _right_value == 0))
1435 // Get LESS_THAN, EQUALS, or GREATER_THAN
1437 doComparison(_left_property,
1438 (_right_property != 0 ? _right_property : _right_value));
1440 return (cmp == _type);
1442 return (cmp != _type);
1446 FGComparisonCondition::setLeftProperty (const string &propname)
1448 _left_property = fgGetNode(propname, true);
1452 FGComparisonCondition::setRightProperty (const string &propname)
1454 delete _right_value;
1456 _right_property = fgGetNode(propname, true);
1460 FGComparisonCondition::setRightValue (const SGPropertyNode *node)
1462 _right_property = 0;
1463 delete _right_value;
1464 _right_value = new SGPropertyNode(*node);
1469 ////////////////////////////////////////////////////////////////////////
1470 // Read a condition and use it if necessary.
1471 ////////////////////////////////////////////////////////////////////////
1473 // Forward declaration
1474 static FGCondition * readCondition (const SGPropertyNode * node);
1476 static FGCondition *
1477 readPropertyCondition (const SGPropertyNode * node)
1479 return new FGPropertyCondition(node->getStringValue());
1482 static FGCondition *
1483 readNotCondition (const SGPropertyNode * node)
1485 int nChildren = node->nChildren();
1486 for (int i = 0; i < nChildren; i++) {
1487 const SGPropertyNode * child = node->getChild(i);
1488 FGCondition * condition = readCondition(child);
1490 return new FGNotCondition(condition);
1492 SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition");
1496 static FGCondition *
1497 readAndConditions (const SGPropertyNode * node)
1499 FGAndCondition * andCondition = new FGAndCondition;
1500 int nChildren = node->nChildren();
1501 for (int i = 0; i < nChildren; i++) {
1502 const SGPropertyNode * child = node->getChild(i);
1503 FGCondition * condition = readCondition(child);
1505 andCondition->addCondition(condition);
1507 return andCondition;
1510 static FGCondition *
1511 readOrConditions (const SGPropertyNode * node)
1513 FGOrCondition * orCondition = new FGOrCondition;
1514 int nChildren = node->nChildren();
1515 for (int i = 0; i < nChildren; i++) {
1516 const SGPropertyNode * child = node->getChild(i);
1517 FGCondition * condition = readCondition(child);
1519 orCondition->addCondition(condition);
1524 static FGCondition *
1525 readComparison (const SGPropertyNode * node,
1526 FGComparisonCondition::Type type,
1529 FGComparisonCondition * condition = new FGComparisonCondition(type, reverse);
1530 condition->setLeftProperty(node->getStringValue("property[0]"));
1531 if (node->hasValue("property[1]"))
1532 condition->setRightProperty(node->getStringValue("property[1]"));
1534 condition->setRightValue(node->getChild("value", 0));
1539 static FGCondition *
1540 readCondition (const SGPropertyNode * node)
1542 const string &name = node->getName();
1543 if (name == "property")
1544 return readPropertyCondition(node);
1545 else if (name == "not")
1546 return readNotCondition(node);
1547 else if (name == "and")
1548 return readAndConditions(node);
1549 else if (name == "or")
1550 return readOrConditions(node);
1551 else if (name == "less-than")
1552 return readComparison(node, FGComparisonCondition::LESS_THAN, false);
1553 else if (name == "less-than-equals")
1554 return readComparison(node, FGComparisonCondition::GREATER_THAN, true);
1555 else if (name == "greater-than")
1556 return readComparison(node, FGComparisonCondition::GREATER_THAN, false);
1557 else if (name == "greater-than-equals")
1558 return readComparison(node, FGComparisonCondition::LESS_THAN, true);
1559 else if (name == "equals")
1560 return readComparison(node, FGComparisonCondition::EQUALS, false);
1561 else if (name == "not-equals")
1562 return readComparison(node, FGComparisonCondition::EQUALS, true);
1569 ////////////////////////////////////////////////////////////////////////
1570 // Implementation of FGConditional.
1571 ////////////////////////////////////////////////////////////////////////
1573 FGConditional::FGConditional ()
1578 FGConditional::~FGConditional ()
1584 FGConditional::setCondition (FGCondition * condition)
1587 _condition = condition;
1591 FGConditional::test () const
1593 return ((_condition == 0) || _condition->test());
1598 // The top-level is always an implicit 'and' group
1600 fgReadCondition (const SGPropertyNode * node)
1602 return readAndConditions(node);
1606 // end of fg_props.cxx