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 ////////////////////////////////////////////////////////////////////////
123 struct LogClassMapping {
128 LogClassMapping log_class_mappings [] = {
130 {SG_TERRAIN, "terrain"},
132 {SG_FLIGHT, "flight"},
136 {SG_COCKPIT, "cockpit"},
137 {SG_GENERAL, "general"},
140 {SG_AIRCRAFT, "aircraft"},
141 {SG_AUTOPILOT, "autopilot"},
143 {SG_CLIPPER, "clipper"},
144 {SG_NETWORK, "network"},
150 * Get the logging classes.
155 sgDebugClass classes = logbuf::get_log_classes();
157 for (int i = 0; log_class_mappings[i].c != SG_UNDEFD; i++) {
158 if ((classes&log_class_mappings[i].c) > 0) {
161 result += log_class_mappings[i].name;
168 static void addLoggingClass (const string &name)
170 sgDebugClass classes = logbuf::get_log_classes();
171 for (int i = 0; log_class_mappings[i].c != SG_UNDEFD; i++) {
172 if (name == log_class_mappings[i].name) {
173 logbuf::set_log_classes(sgDebugClass(classes|log_class_mappings[i].c));
177 SG_LOG(SG_GENERAL, SG_ALERT, "Unknown logging class: " << name);
182 * Set the logging classes.
185 setLoggingClasses (string classes)
187 logbuf::set_log_classes(SG_NONE);
189 if (classes == "none") {
190 SG_LOG(SG_GENERAL, SG_INFO, "Disabled all logging classes");
194 if (classes == "" || classes == "all") { // default
195 logbuf::set_log_classes(SG_ALL);
196 SG_LOG(SG_GENERAL, SG_INFO, "Enabled all logging classes: "
197 << getLoggingClasses());
201 string rest = classes;
203 int sep = rest.find('|');
205 name = rest.substr(0, sep);
206 rest = rest.substr(sep+1);
207 addLoggingClass(name);
208 sep = rest.find('|');
210 addLoggingClass(rest);
211 SG_LOG(SG_GENERAL, SG_INFO, "Set logging classes to "
212 << getLoggingClasses());
217 * Get the logging priority.
220 getLoggingPriority ()
222 switch (logbuf::get_log_priority()) {
234 SG_LOG(SG_GENERAL, SG_WARN, "Internal: Unknown logging priority number: "
235 << logbuf::get_log_priority());
242 * Set the logging priority.
245 setLoggingPriority (string priority)
247 if (priority == "bulk") {
248 logbuf::set_log_priority(SG_BULK);
249 } else if (priority == "debug") {
250 logbuf::set_log_priority(SG_DEBUG);
251 } else if (priority == "" || priority == "info") { // default
252 logbuf::set_log_priority(SG_INFO);
253 } else if (priority == "warn") {
254 logbuf::set_log_priority(SG_WARN);
255 } else if (priority == "alert") {
256 logbuf::set_log_priority(SG_ALERT);
258 SG_LOG(SG_GENERAL, SG_WARN, "Unknown logging priority " << priority);
260 SG_LOG(SG_GENERAL, SG_INFO, "Logging priority is " << getLoggingPriority());
265 * Get the pause state of the sim.
270 return globals->get_freeze();
275 * Set the pause state of the sim.
278 setFreeze (bool freeze)
280 globals->set_freeze(freeze);
284 * Return the current aircraft directory (UIUC) as a string.
294 * Set the current aircraft directory (UIUC).
297 setAircraftDir (string dir)
299 if (getAircraftDir() != dir) {
301 // needReinit(); FIXME!!
307 * Get the current view offset in degrees.
312 return (globals->get_current_view()
313 ->get_view_offset() * SGD_RADIANS_TO_DEGREES);
318 setViewOffset (double offset)
320 globals->get_current_view()->set_view_offset(offset * SGD_DEGREES_TO_RADIANS);
326 return (globals->get_current_view()
327 ->get_goal_view_offset() * SGD_RADIANS_TO_DEGREES);
331 setGoalViewOffset (double offset)
333 while ( offset < 0 ) {
336 while ( offset > 360.0 ) {
339 // Snap to center if we are close
340 if ( fabs(offset) < 1.0 || fabs(offset) > 359.0 ) {
344 globals->get_current_view()
345 ->set_goal_view_offset(offset * SGD_DEGREES_TO_RADIANS);
350 * Pilot position offset from CG.
353 getPilotPositionXOffset ()
355 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
356 float * offset = pilot_view->get_pilot_offset();
361 setPilotPositionXOffset (float x)
363 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
364 float * offset = pilot_view->get_pilot_offset();
365 pilot_view->set_pilot_offset(x, offset[1], offset[2]);
369 getPilotPositionYOffset ()
371 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
372 float * offset = pilot_view->get_pilot_offset();
377 setPilotPositionYOffset (float y)
379 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
380 float * offset = pilot_view->get_pilot_offset();
381 pilot_view->set_pilot_offset(offset[0], y, offset[2]);
385 getPilotPositionZOffset ()
387 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
388 float * offset = pilot_view->get_pilot_offset();
393 setPilotPositionZOffset (float z)
395 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
396 float * offset = pilot_view->get_pilot_offset();
397 pilot_view->set_pilot_offset(offset[0], offset[1], z);
402 * Return the current Zulu time.
409 struct tm * t = globals->get_time_params()->getGmt();
410 sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d",
411 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
412 t->tm_hour, t->tm_min, t->tm_sec);
419 * Set the current Zulu time.
422 setDateString (string date_string)
424 SGTime * st = globals->get_time_params();
425 struct tm * current_time = st->getGmt();
428 // Scan for basic ISO format
429 // YYYY-MM-DDTHH:MM:SS
430 int ret = sscanf(date_string.c_str(), "%d-%d-%dT%d:%d:%d",
431 &(new_time.tm_year), &(new_time.tm_mon),
432 &(new_time.tm_mday), &(new_time.tm_hour),
433 &(new_time.tm_min), &(new_time.tm_sec));
435 // Be pretty picky about this, so
436 // that strange things don't happen
437 // if the save file has been edited
440 SG_LOG(SG_INPUT, SG_ALERT, "Date/time string " << date_string
441 << " not in YYYY-MM-DDTHH:MM:SS format; skipped");
445 // OK, it looks like we got six
446 // values, one way or another.
447 new_time.tm_year -= 1900;
448 new_time.tm_mon -= 1;
450 // Now, tell flight gear to use
451 // the new time. This was far
452 // too difficult, by the way.
454 mktime(&new_time) - mktime(current_time) + globals->get_warp();
455 double lon = current_aircraft.fdm_state->get_Longitude();
456 double lat = current_aircraft.fdm_state->get_Latitude();
457 globals->set_warp(warp);
458 st->update(lon, lat, warp);
459 fgUpdateSkyAndLightingParams();
463 * Return the GMT as a string.
470 struct tm * t = globals->get_time_params()->getGmt();
471 sprintf(buf, " %.2d:%.2d:%.2d",
472 t->tm_hour, t->tm_min, t->tm_sec);
479 * Get the texture rendering state.
484 return (material_lib.get_step() == 0);
489 * Set the texture rendering state.
492 setTextures (bool textures)
495 material_lib.set_step(0);
497 material_lib.set_step(1);
502 * Return the magnetic variation
507 return globals->get_mag()->get_magvar() * SGD_RADIANS_TO_DEGREES;
512 * Return the magnetic dip
517 return globals->get_mag()->get_magdip() * SGD_RADIANS_TO_DEGREES;
522 * Return the current heading in degrees.
527 return current_aircraft.fdm_state->get_Psi() * SGD_RADIANS_TO_DEGREES - getMagVar();
532 * Return the current engine0 rpm
537 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
538 return current_aircraft.fdm_state->get_engine(0)->get_RPM();
546 * Return the current engine0 EGT.
551 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
552 return current_aircraft.fdm_state->get_engine(0)->get_EGT();
559 * Return the current engine0 CHT.
564 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
565 return current_aircraft.fdm_state->get_engine(0)->get_CHT();
572 * Return the current engine0 Oil Temp.
577 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
578 return current_aircraft.fdm_state->get_engine(0)->get_Oil_Temp();
585 * Return the current engine0 Manifold Pressure.
590 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
591 return current_aircraft.fdm_state->get_engine(0)->get_Manifold_Pressure();
599 * Return the current engine0 fuel flow
604 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
605 return current_aircraft.fdm_state->get_engine(0)->get_Fuel_Flow();
612 * Return the current engine0 running flag
617 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
618 return current_aircraft.fdm_state->get_engine(0)->get_Running_Flag();
625 * Return the current engine0 cranking flag
630 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
631 return current_aircraft.fdm_state->get_engine(0)->get_Cranking_Flag();
638 * Return the fuel level in tank 1
643 return current_aircraft.fdm_state->get_Tank1Fuel();
647 setTank1Fuel ( double gals )
649 current_aircraft.fdm_state->set_Tank1Fuel( gals );
653 * Return the fuel level in tank 2
658 return current_aircraft.fdm_state->get_Tank2Fuel();
662 setTank2Fuel ( double gals )
664 current_aircraft.fdm_state->set_Tank2Fuel( gals );
669 * Get the autopilot altitude lock (true=on).
674 return (current_autopilot->get_AltitudeEnabled() &&
675 current_autopilot->get_AltitudeMode()
676 == FGAutopilot::FG_ALTITUDE_LOCK);
681 * Set the autopilot altitude lock (true=on).
684 setAPAltitudeLock (bool lock)
686 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
687 current_autopilot->set_AltitudeEnabled(lock);
692 * Get the autopilot target altitude in feet.
697 return current_autopilot->get_TargetAltitude() * SG_METER_TO_FEET;
702 * Set the autopilot target altitude in feet.
705 setAPAltitude (double altitude)
707 current_autopilot->set_TargetAltitude( altitude * SG_FEET_TO_METER );
711 * Get the autopilot altitude lock (true=on).
716 return (current_autopilot->get_AltitudeEnabled() &&
717 (current_autopilot->get_AltitudeMode()
718 == FGAutopilot::FG_ALTITUDE_GS1));
723 * Set the autopilot altitude lock (true=on).
726 setAPGSLock (bool lock)
728 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_GS1);
729 current_autopilot->set_AltitudeEnabled(lock);
734 * Get the autopilot terrain lock (true=on).
739 return (current_autopilot->get_AltitudeEnabled() &&
740 (current_autopilot->get_AltitudeMode()
741 == FGAutopilot::FG_ALTITUDE_TERRAIN));
746 * Set the autopilot terrain lock (true=on).
749 setAPTerrainLock (bool lock)
751 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_TERRAIN);
752 current_autopilot->set_AltitudeEnabled(lock);
753 current_autopilot->set_TargetAGL(
754 current_aircraft.fdm_state->get_Altitude_AGL() * SG_FEET_TO_METER
756 cout << "Target AGL = "
757 << current_aircraft.fdm_state->get_Altitude_AGL() * SG_FEET_TO_METER
763 * Get the autopilot target altitude in feet.
768 return current_autopilot->get_TargetClimbRate() * SG_METER_TO_FEET;
773 * Set the autopilot target altitude in feet.
776 setAPClimb (double rate)
778 current_autopilot->set_TargetClimbRate( rate * SG_FEET_TO_METER );
783 * Get the autopilot heading lock (true=on).
789 (current_autopilot->get_HeadingEnabled() &&
790 current_autopilot->get_HeadingMode() == DEFAULT_AP_HEADING_LOCK);
795 * Set the autopilot heading lock (true=on).
798 setAPHeadingLock (bool lock)
801 current_autopilot->set_HeadingMode(DEFAULT_AP_HEADING_LOCK);
802 current_autopilot->set_HeadingEnabled(true);
804 current_autopilot->set_HeadingEnabled(false);
810 * Get the autopilot heading bug in degrees.
815 return current_autopilot->get_DGTargetHeading();
820 * Set the autopilot heading bug in degrees.
823 setAPHeadingBug (double heading)
825 current_autopilot->set_DGTargetHeading( heading );
830 * Get the autopilot wing leveler lock (true=on).
836 (current_autopilot->get_HeadingEnabled() &&
837 current_autopilot->get_HeadingMode() == FGAutopilot::FG_TC_HEADING_LOCK);
842 * Set the autopilot wing leveler lock (true=on).
845 setAPWingLeveler (bool lock)
848 current_autopilot->set_HeadingMode(FGAutopilot::FG_TC_HEADING_LOCK);
849 current_autopilot->set_HeadingEnabled(true);
851 current_autopilot->set_HeadingEnabled(false);
856 * Return true if the autopilot is locked to NAV1.
862 (current_autopilot->get_HeadingEnabled() &&
863 current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
868 * Set the autopilot NAV1 lock.
871 setAPNAV1Lock (bool lock)
874 current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
875 current_autopilot->set_HeadingEnabled(true);
876 } else if (current_autopilot->get_HeadingMode() ==
877 FGAutopilot::FG_HEADING_NAV1) {
878 current_autopilot->set_HeadingEnabled(false);
883 * Get the autopilot autothrottle lock.
886 getAPAutoThrottleLock ()
888 return current_autopilot->get_AutoThrottleEnabled();
893 * Set the autothrottle lock.
896 setAPAutoThrottleLock (bool lock)
898 current_autopilot->set_AutoThrottleEnabled(lock);
904 getAPRudderControl ()
906 if (getAPHeadingLock())
907 return current_autopilot->get_TargetHeading();
909 return globals->get_controls()->get_rudder();
914 setAPRudderControl (double value)
916 if (getAPHeadingLock()) {
917 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPRudderControl " << value );
918 value -= current_autopilot->get_TargetHeading();
919 current_autopilot->HeadingAdjust(value < 0.0 ? -1.0 : 1.0);
921 globals->get_controls()->set_rudder(value);
927 getAPElevatorControl ()
929 if (getAPAltitudeLock())
930 return current_autopilot->get_TargetAltitude();
932 return globals->get_controls()->get_elevator();
937 setAPElevatorControl (double value)
939 if (getAPAltitudeLock()) {
940 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPElevatorControl " << value );
941 value -= current_autopilot->get_TargetAltitude();
942 current_autopilot->AltitudeAdjust(value < 0.0 ? 100.0 : -100.0);
944 globals->get_controls()->set_elevator(value);
950 getAPThrottleControl ()
952 if (getAPAutoThrottleLock())
953 return 0.0; // always resets
955 return globals->get_controls()->get_throttle(0);
960 setAPThrottleControl (double value)
962 if (getAPAutoThrottleLock())
963 current_autopilot->AutoThrottleAdjust(value < 0.0 ? -0.01 : 0.01);
965 globals->get_controls()->set_throttle(0, value);
970 * Get the current visibility (meters).
975 #ifndef FG_OLD_WEATHER
976 return WeatherDatabase->getWeatherVisibility();
978 return current_weather.get_visibility();
984 * Set the current visibility (meters).
987 setVisibility (double visibility)
989 #ifndef FG_OLD_WEATHER
990 WeatherDatabase->setWeatherVisibility(visibility);
992 current_weather.set_visibility(visibility);
997 * Get the current wind north velocity (feet/second).
1002 return current_aircraft.fdm_state->get_V_north_airmass();
1007 * Set the current wind north velocity (feet/second).
1010 setWindNorth (double speed)
1012 current_aircraft.fdm_state
1013 ->set_Velocities_Local_Airmass(speed, getWindEast(), getWindDown());
1018 * Get the current wind east velocity (feet/second).
1023 return current_aircraft.fdm_state->get_V_east_airmass();
1028 * Set the current wind east velocity (feet/second).
1031 setWindEast (double speed)
1033 cout << "Set wind-east to " << speed << endl;
1034 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
1041 * Get the current wind down velocity (feet/second).
1046 return current_aircraft.fdm_state->get_V_down_airmass();
1051 * Set the current wind down velocity (feet/second).
1054 setWindDown (double speed)
1056 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
1062 * Set the current engine0 running flag.
1065 setRunningFlag (bool flag)
1067 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
1068 current_aircraft.fdm_state->get_engine(0)->set_Running_Flag( flag );
1073 * Set the current engine0 cranking flag.
1075 //Although there is no real reason to want to tell the engine that it is cranking,
1076 //this is currently necessary to avoid the cranking sound being played
1077 //before the engine inits.
1079 setCrankingFlag (bool flag)
1081 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
1082 current_aircraft.fdm_state->get_engine(0)->set_Cranking_Flag( flag );
1089 return globals->get_current_view()->get_fov();
1096 globals->get_current_view()->set_fov( fov );
1103 return globals->get_warp();
1109 globals->set_warp(warp);
1115 return globals->get_warp_delta();
1119 setWarpDelta (long delta)
1121 globals->set_warp_delta(delta);
1125 setViewAxisLong (double axis)
1131 setViewAxisLat (double axis)
1143 setWindingCCW (bool state)
1145 winding_ccw = state;
1147 glFrontFace ( GL_CCW );
1149 glFrontFace ( GL_CW );
1155 #if defined(FX) && !defined(WIN32)
1156 return global_fullscreen;
1163 setFullScreen (bool state)
1165 #if defined(FX) && !defined(WIN32)
1166 global_fullscreen = state;
1167 # if defined(XMESA_FX_FULLSCREEN) && defined(XMESA_FX_WINDOW)
1168 XMesaSetFXmode( global_fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW );
1174 getFDMDataLogging ()
1176 return fdm_data_logging;
1180 setFDMDataLogging (bool state)
1182 // kludge; no getter or setter available
1183 if (state != fdm_data_logging) {
1184 fgToggleFDMdataLogging();
1185 fdm_data_logging = state;
1190 ////////////////////////////////////////////////////////////////////////
1191 // Tie the properties.
1192 ////////////////////////////////////////////////////////////////////////
1198 fgTie("/sim/logging/priority", getLoggingPriority, setLoggingPriority);
1199 fgTie("/sim/logging/classes", getLoggingClasses, setLoggingClasses);
1200 fgTie("/sim/freeze", getFreeze, setFreeze);
1201 fgTie("/sim/aircraft-dir", getAircraftDir, setAircraftDir);
1202 fgTie("/sim/view/offset-deg", getViewOffset, setViewOffset);
1203 fgSetArchivable("/sim/view/offset-deg");
1204 fgTie("/sim/view/goal-offset-deg", getGoalViewOffset, setGoalViewOffset);
1205 fgSetArchivable("/sim/view/goal-offset-deg");
1206 fgTie("/sim/view/pilot/x-offset-m",
1207 getPilotPositionXOffset, setPilotPositionXOffset);
1208 fgSetArchivable("/sim/view/pilot/x-offset-m");
1209 fgTie("/sim/view/pilot/y-offset-m",
1210 getPilotPositionYOffset, setPilotPositionYOffset);
1211 fgSetArchivable("/sim/view/pilot/y-offset-m");
1212 fgTie("/sim/view/pilot/z-offset-m",
1213 getPilotPositionZOffset, setPilotPositionZOffset);
1214 fgSetArchivable("/sim/view/pilot/z-offset-m");
1215 fgTie("/sim/time/gmt", getDateString, setDateString);
1216 fgSetArchivable("/sim/time/gmt");
1217 fgTie("/sim/time/gmt-string", getGMTString);
1218 fgTie("/sim/rendering/textures", getTextures, setTextures);
1221 fgTie("/orientation/heading-magnetic-deg", getHeadingMag);
1224 fgTie("/engines/engine[0]/rpm", getRPM);
1225 fgTie("/engines/engine[0]/egt-degf", getEGT);
1226 fgTie("/engines/engine[0]/cht-degf", getCHT);
1227 fgTie("/engines/engine[0]/oil-temperature-degf", getOilTemp);
1228 fgTie("/engines/engine[0]/mp-osi", getMP);
1229 fgTie("/engines/engine[0]/fuel-flow-gph", getFuelFlow);
1230 fgTie("/engines/engine[0]/running", getRunningFlag, setRunningFlag);
1231 fgTie("/engines/engine[0]/cranking", getCrankingFlag, setCrankingFlag);
1234 fgTie("/consumables/fuel/tank[0]/level-gal_us",
1235 getTank1Fuel, setTank1Fuel, false);
1236 fgSetArchivable("/consumables/fuel/tank[0]/level-gal_us");
1237 fgTie("/consumables/fuel/tank[1]/level-gal_us",
1238 getTank2Fuel, setTank2Fuel, false);
1239 fgSetArchivable("/consumables/fuel/tank[1]/level-gal_us");
1242 fgTie("/autopilot/locks/altitude", getAPAltitudeLock, setAPAltitudeLock);
1243 fgSetArchivable("/autopilot/locks/altitude");
1244 fgTie("/autopilot/settings/altitude-ft", getAPAltitude, setAPAltitude);
1245 fgSetArchivable("/autopilot/settings/altitude-ft");
1246 fgTie("/autopilot/locks/glide-slope", getAPGSLock, setAPGSLock);
1247 fgSetArchivable("/autopilot/locks/glide-slope");
1248 fgTie("/autopilot/locks/terrain", getAPTerrainLock, setAPTerrainLock);
1249 fgSetArchivable("/autopilot/locks/terrain");
1250 fgTie("/autopilot/settings/agl-ft", getAPAltitude, setAPAltitude);
1251 fgSetArchivable("/autopilot/settings/agl-ft");
1252 fgTie("/autopilot/settings/climb-rate-fpm", getAPClimb, setAPClimb, false);
1253 fgSetArchivable("/autopilot/settings/climb-rate-fpm");
1254 fgTie("/autopilot/locks/heading", getAPHeadingLock, setAPHeadingLock);
1255 fgSetArchivable("/autopilot/locks/heading");
1256 fgTie("/autopilot/settings/heading-bug-deg",
1257 getAPHeadingBug, setAPHeadingBug, false);
1258 fgSetArchivable("/autopilot/settings/heading-bug-deg");
1259 fgTie("/autopilot/locks/wing-leveler", getAPWingLeveler, setAPWingLeveler);
1260 fgSetArchivable("/autopilot/locks/wing-leveler");
1261 fgTie("/autopilot/locks/nav[0]", getAPNAV1Lock, setAPNAV1Lock);
1262 fgSetArchivable("/autopilot/locks/nav[0]");
1263 fgTie("/autopilot/locks/auto-throttle",
1264 getAPAutoThrottleLock, setAPAutoThrottleLock);
1265 fgSetArchivable("/autopilot/locks/auto-throttle");
1266 fgTie("/autopilot/control-overrides/rudder",
1267 getAPRudderControl, setAPRudderControl);
1268 fgSetArchivable("/autopilot/control-overrides/rudder");
1269 fgTie("/autopilot/control-overrides/elevator",
1270 getAPElevatorControl, setAPElevatorControl);
1271 fgSetArchivable("/autopilot/control-overrides/elevator");
1272 fgTie("/autopilot/control-overrides/throttle",
1273 getAPThrottleControl, setAPThrottleControl);
1274 fgSetArchivable("/autopilot/control-overrides/throttle");
1277 fgTie("/environment/visibility-m", getVisibility, setVisibility);
1278 fgSetArchivable("/environment/visibility-m");
1279 fgTie("/environment/wind-north-fps", getWindNorth, setWindNorth);
1280 fgSetArchivable("/environment/wind-north-fps");
1281 fgTie("/environment/wind-east-fps", getWindEast, setWindEast);
1282 fgSetArchivable("/environment/wind-east-fps");
1283 fgTie("/environment/wind-down-fps", getWindDown, setWindDown);
1284 fgSetArchivable("/environment/wind-down-fps");
1286 fgTie("/environment/magnetic-variation-deg", getMagVar);
1287 fgTie("/environment/magnetic-dip-deg", getMagDip);
1290 fgTie("/sim/field-of-view", getFOV, setFOV);
1291 fgSetArchivable("/sim/field-of-view");
1292 fgTie("/sim/time/warp", getWarp, setWarp, false);
1293 fgTie("/sim/time/warp-delta", getWarpDelta, setWarpDelta);
1294 fgTie("/sim/view/axes/long", (double(*)())0, setViewAxisLong);
1295 fgTie("/sim/view/axes/lat", (double(*)())0, setViewAxisLat);
1297 // Misc. Temporary junk.
1298 fgTie("/sim/temp/winding-ccw", getWindingCCW, setWindingCCW, false);
1299 fgTie("/sim/temp/full-screen", getFullScreen, setFullScreen);
1300 fgTie("/sim/temp/fdm-data-logging", getFDMDataLogging, setFDMDataLogging);
1308 _set_view_from_axes();
1313 ////////////////////////////////////////////////////////////////////////
1314 // Save and restore.
1315 ////////////////////////////////////////////////////////////////////////
1319 * Save the current state of the simulator to a stream.
1322 fgSaveFlight (ostream &output)
1325 writeProperties(output, globals->get_props());
1326 } catch (const sg_exception &e) {
1327 guiErrorMessage("Error saving flight: ", e);
1335 * Restore the current state of the simulator from a stream.
1338 fgLoadFlight (istream &input)
1340 SGPropertyNode props;
1342 readProperties(input, &props);
1343 } catch (const sg_exception &e) {
1344 guiErrorMessage("Error reading saved flight: ", e);
1347 copyProperties(&props, globals->get_props());
1348 // When loading a flight, make it the
1349 // new initial state.
1350 globals->saveInitialState();
1356 ////////////////////////////////////////////////////////////////////////
1357 // Implementation of FGCondition.
1358 ////////////////////////////////////////////////////////////////////////
1360 FGCondition::FGCondition ()
1364 FGCondition::~FGCondition ()
1370 ////////////////////////////////////////////////////////////////////////
1371 // Implementation of FGPropertyCondition.
1372 ////////////////////////////////////////////////////////////////////////
1374 FGPropertyCondition::FGPropertyCondition (const string &propname)
1375 : _node(fgGetNode(propname, true))
1379 FGPropertyCondition::~FGPropertyCondition ()
1385 ////////////////////////////////////////////////////////////////////////
1386 // Implementation of FGNotCondition.
1387 ////////////////////////////////////////////////////////////////////////
1389 FGNotCondition::FGNotCondition (FGCondition * condition)
1390 : _condition(condition)
1394 FGNotCondition::~FGNotCondition ()
1400 FGNotCondition::test () const
1402 return !(_condition->test());
1407 ////////////////////////////////////////////////////////////////////////
1408 // Implementation of FGAndCondition.
1409 ////////////////////////////////////////////////////////////////////////
1411 FGAndCondition::FGAndCondition ()
1415 FGAndCondition::~FGAndCondition ()
1417 for (unsigned int i = 0; i < _conditions.size(); i++)
1418 delete _conditions[i];
1422 FGAndCondition::test () const
1424 int nConditions = _conditions.size();
1425 for (int i = 0; i < nConditions; i++) {
1426 if (!_conditions[i]->test())
1433 FGAndCondition::addCondition (FGCondition * condition)
1435 _conditions.push_back(condition);
1440 ////////////////////////////////////////////////////////////////////////
1441 // Implementation of FGOrCondition.
1442 ////////////////////////////////////////////////////////////////////////
1444 FGOrCondition::FGOrCondition ()
1448 FGOrCondition::~FGOrCondition ()
1450 for (unsigned int i = 0; i < _conditions.size(); i++)
1451 delete _conditions[i];
1455 FGOrCondition::test () const
1457 int nConditions = _conditions.size();
1458 for (int i = 0; i < nConditions; i++) {
1459 if (_conditions[i]->test())
1466 FGOrCondition::addCondition (FGCondition * condition)
1468 _conditions.push_back(condition);
1473 ////////////////////////////////////////////////////////////////////////
1474 // Implementation of FGComparisonCondition.
1475 ////////////////////////////////////////////////////////////////////////
1478 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
1480 switch (left->getType()) {
1481 case SGPropertyNode::BOOL: {
1482 bool v1 = left->getBoolValue();
1483 bool v2 = right->getBoolValue();
1485 return FGComparisonCondition::LESS_THAN;
1487 return FGComparisonCondition::GREATER_THAN;
1489 return FGComparisonCondition::EQUALS;
1492 case SGPropertyNode::INT: {
1493 int v1 = left->getIntValue();
1494 int v2 = right->getIntValue();
1496 return FGComparisonCondition::LESS_THAN;
1498 return FGComparisonCondition::GREATER_THAN;
1500 return FGComparisonCondition::EQUALS;
1503 case SGPropertyNode::LONG: {
1504 long v1 = left->getLongValue();
1505 long v2 = right->getLongValue();
1507 return FGComparisonCondition::LESS_THAN;
1509 return FGComparisonCondition::GREATER_THAN;
1511 return FGComparisonCondition::EQUALS;
1514 case SGPropertyNode::FLOAT: {
1515 float v1 = left->getFloatValue();
1516 float v2 = right->getFloatValue();
1518 return FGComparisonCondition::LESS_THAN;
1520 return FGComparisonCondition::GREATER_THAN;
1522 return FGComparisonCondition::EQUALS;
1525 case SGPropertyNode::DOUBLE: {
1526 double v1 = left->getDoubleValue();
1527 double v2 = right->getDoubleValue();
1529 return FGComparisonCondition::LESS_THAN;
1531 return FGComparisonCondition::GREATER_THAN;
1533 return FGComparisonCondition::EQUALS;
1536 case SGPropertyNode::STRING:
1537 case SGPropertyNode::NONE:
1538 case SGPropertyNode::UNSPECIFIED: {
1539 string v1 = left->getStringValue();
1540 string v2 = right->getStringValue();
1542 return FGComparisonCondition::LESS_THAN;
1544 return FGComparisonCondition::GREATER_THAN;
1546 return FGComparisonCondition::EQUALS;
1550 throw sg_exception("Unrecognized node type");
1555 FGComparisonCondition::FGComparisonCondition (Type type, bool reverse)
1564 FGComparisonCondition::~FGComparisonCondition ()
1566 delete _right_value;
1570 FGComparisonCondition::test () const
1572 // Always fail if incompletely specified
1573 if (_left_property == 0 ||
1574 (_right_property == 0 && _right_value == 0))
1577 // Get LESS_THAN, EQUALS, or GREATER_THAN
1579 doComparison(_left_property,
1580 (_right_property != 0 ? _right_property : _right_value));
1582 return (cmp == _type);
1584 return (cmp != _type);
1588 FGComparisonCondition::setLeftProperty (const string &propname)
1590 _left_property = fgGetNode(propname, true);
1594 FGComparisonCondition::setRightProperty (const string &propname)
1596 delete _right_value;
1598 _right_property = fgGetNode(propname, true);
1602 FGComparisonCondition::setRightValue (const SGPropertyNode *node)
1604 _right_property = 0;
1605 delete _right_value;
1606 _right_value = new SGPropertyNode(*node);
1611 ////////////////////////////////////////////////////////////////////////
1612 // Read a condition and use it if necessary.
1613 ////////////////////////////////////////////////////////////////////////
1615 // Forward declaration
1616 static FGCondition * readCondition (const SGPropertyNode * node);
1618 static FGCondition *
1619 readPropertyCondition (const SGPropertyNode * node)
1621 return new FGPropertyCondition(node->getStringValue());
1624 static FGCondition *
1625 readNotCondition (const SGPropertyNode * node)
1627 int nChildren = node->nChildren();
1628 for (int i = 0; i < nChildren; i++) {
1629 const SGPropertyNode * child = node->getChild(i);
1630 FGCondition * condition = readCondition(child);
1632 return new FGNotCondition(condition);
1634 SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition");
1638 static FGCondition *
1639 readAndConditions (const SGPropertyNode * node)
1641 FGAndCondition * andCondition = new FGAndCondition;
1642 int nChildren = node->nChildren();
1643 for (int i = 0; i < nChildren; i++) {
1644 const SGPropertyNode * child = node->getChild(i);
1645 FGCondition * condition = readCondition(child);
1647 andCondition->addCondition(condition);
1649 return andCondition;
1652 static FGCondition *
1653 readOrConditions (const SGPropertyNode * node)
1655 FGOrCondition * orCondition = new FGOrCondition;
1656 int nChildren = node->nChildren();
1657 for (int i = 0; i < nChildren; i++) {
1658 const SGPropertyNode * child = node->getChild(i);
1659 FGCondition * condition = readCondition(child);
1661 orCondition->addCondition(condition);
1666 static FGCondition *
1667 readComparison (const SGPropertyNode * node,
1668 FGComparisonCondition::Type type,
1671 FGComparisonCondition * condition = new FGComparisonCondition(type, reverse);
1672 condition->setLeftProperty(node->getStringValue("property[0]"));
1673 if (node->hasValue("property[1]"))
1674 condition->setRightProperty(node->getStringValue("property[1]"));
1676 condition->setRightValue(node->getChild("value", 0));
1681 static FGCondition *
1682 readCondition (const SGPropertyNode * node)
1684 const string &name = node->getName();
1685 if (name == "property")
1686 return readPropertyCondition(node);
1687 else if (name == "not")
1688 return readNotCondition(node);
1689 else if (name == "and")
1690 return readAndConditions(node);
1691 else if (name == "or")
1692 return readOrConditions(node);
1693 else if (name == "less-than")
1694 return readComparison(node, FGComparisonCondition::LESS_THAN, false);
1695 else if (name == "less-than-equals")
1696 return readComparison(node, FGComparisonCondition::GREATER_THAN, true);
1697 else if (name == "greater-than")
1698 return readComparison(node, FGComparisonCondition::GREATER_THAN, false);
1699 else if (name == "greater-than-equals")
1700 return readComparison(node, FGComparisonCondition::LESS_THAN, true);
1701 else if (name == "equals")
1702 return readComparison(node, FGComparisonCondition::EQUALS, false);
1703 else if (name == "not-equals")
1704 return readComparison(node, FGComparisonCondition::EQUALS, true);
1711 ////////////////////////////////////////////////////////////////////////
1712 // Implementation of FGConditional.
1713 ////////////////////////////////////////////////////////////////////////
1715 FGConditional::FGConditional ()
1720 FGConditional::~FGConditional ()
1726 FGConditional::setCondition (FGCondition * condition)
1729 _condition = condition;
1733 FGConditional::test () const
1735 return ((_condition == 0) || _condition->test());
1740 // The top-level is always an implicit 'and' group
1742 fgReadCondition (const SGPropertyNode * node)
1744 return readAndConditions(node);
1748 // end of fg_props.cxx