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 {
126 LogClassMapping(sgDebugClass cc, string nname) { c = cc; name = nname; }
129 LogClassMapping log_class_mappings [] = {
130 LogClassMapping(SG_NONE, "none"),
131 LogClassMapping(SG_TERRAIN, "terrain"),
132 LogClassMapping(SG_ASTRO, "astro"),
133 LogClassMapping(SG_FLIGHT, "flight"),
134 LogClassMapping(SG_INPUT, "input"),
135 LogClassMapping(SG_GL, "gl"),
136 LogClassMapping(SG_VIEW, "view"),
137 LogClassMapping(SG_COCKPIT, "cockpit"),
138 LogClassMapping(SG_GENERAL, "general"),
139 LogClassMapping(SG_MATH, "math"),
140 LogClassMapping(SG_EVENT, "event"),
141 LogClassMapping(SG_AIRCRAFT, "aircraft"),
142 LogClassMapping(SG_AUTOPILOT, "autopilot"),
143 LogClassMapping(SG_IO, "io"),
144 LogClassMapping(SG_CLIPPER, "clipper"),
145 LogClassMapping(SG_NETWORK, "network"),
146 LogClassMapping(SG_UNDEFD, "")
151 * Get the logging classes.
156 sgDebugClass classes = logbuf::get_log_classes();
158 for (int i = 0; log_class_mappings[i].c != SG_UNDEFD; i++) {
159 if ((classes&log_class_mappings[i].c) > 0) {
160 if (result != (string)"")
162 result += log_class_mappings[i].name;
169 static void addLoggingClass (const string &name)
171 sgDebugClass classes = logbuf::get_log_classes();
172 for (int i = 0; log_class_mappings[i].c != SG_UNDEFD; i++) {
173 if (name == log_class_mappings[i].name) {
174 logbuf::set_log_classes(sgDebugClass(classes|log_class_mappings[i].c));
178 SG_LOG(SG_GENERAL, SG_ALERT, "Unknown logging class: " << name);
183 * Set the logging classes.
186 setLoggingClasses (string classes)
188 logbuf::set_log_classes(SG_NONE);
190 if (classes == "none") {
191 SG_LOG(SG_GENERAL, SG_INFO, "Disabled all logging classes");
195 if (classes == "" || classes == "all") { // default
196 logbuf::set_log_classes(SG_ALL);
197 SG_LOG(SG_GENERAL, SG_INFO, "Enabled all logging classes: "
198 << getLoggingClasses());
202 string rest = classes;
204 int sep = rest.find('|');
206 name = rest.substr(0, sep);
207 rest = rest.substr(sep+1);
208 addLoggingClass(name);
209 sep = rest.find('|');
211 addLoggingClass(rest);
212 SG_LOG(SG_GENERAL, SG_INFO, "Set logging classes to "
213 << getLoggingClasses());
218 * Get the logging priority.
221 getLoggingPriority ()
223 switch (logbuf::get_log_priority()) {
235 SG_LOG(SG_GENERAL, SG_WARN, "Internal: Unknown logging priority number: "
236 << logbuf::get_log_priority());
243 * Set the logging priority.
246 setLoggingPriority (string priority)
248 if (priority == "bulk") {
249 logbuf::set_log_priority(SG_BULK);
250 } else if (priority == "debug") {
251 logbuf::set_log_priority(SG_DEBUG);
252 } else if (priority == "" || priority == "info") { // default
253 logbuf::set_log_priority(SG_INFO);
254 } else if (priority == "warn") {
255 logbuf::set_log_priority(SG_WARN);
256 } else if (priority == "alert") {
257 logbuf::set_log_priority(SG_ALERT);
259 SG_LOG(SG_GENERAL, SG_WARN, "Unknown logging priority " << priority);
261 SG_LOG(SG_GENERAL, SG_INFO, "Logging priority is " << getLoggingPriority());
266 * Get the pause state of the sim.
271 return globals->get_freeze();
276 * Set the pause state of the sim.
279 setFreeze (bool freeze)
281 globals->set_freeze(freeze);
285 * Return the current aircraft directory (UIUC) as a string.
295 * Set the current aircraft directory (UIUC).
298 setAircraftDir (string dir)
300 if (getAircraftDir() != dir) {
302 // needReinit(); FIXME!!
308 * Get the current view offset in degrees.
313 return (globals->get_current_view()
314 ->get_view_offset() * SGD_RADIANS_TO_DEGREES);
319 setViewOffset (double offset)
321 globals->get_current_view()->set_view_offset(offset * SGD_DEGREES_TO_RADIANS);
327 return (globals->get_current_view()
328 ->get_goal_view_offset() * SGD_RADIANS_TO_DEGREES);
332 setGoalViewOffset (double offset)
334 while ( offset < 0 ) {
337 while ( offset > 360.0 ) {
340 // Snap to center if we are close
341 if ( fabs(offset) < 1.0 || fabs(offset) > 359.0 ) {
345 globals->get_current_view()
346 ->set_goal_view_offset(offset * SGD_DEGREES_TO_RADIANS);
351 * Pilot position offset from CG.
354 getPilotPositionXOffset ()
356 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
357 float * offset = pilot_view->get_pilot_offset();
362 setPilotPositionXOffset (float x)
364 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
365 float * offset = pilot_view->get_pilot_offset();
366 pilot_view->set_pilot_offset(x, offset[1], offset[2]);
370 getPilotPositionYOffset ()
372 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
373 float * offset = pilot_view->get_pilot_offset();
378 setPilotPositionYOffset (float y)
380 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
381 float * offset = pilot_view->get_pilot_offset();
382 pilot_view->set_pilot_offset(offset[0], y, offset[2]);
386 getPilotPositionZOffset ()
388 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
389 float * offset = pilot_view->get_pilot_offset();
394 setPilotPositionZOffset (float z)
396 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
397 float * offset = pilot_view->get_pilot_offset();
398 pilot_view->set_pilot_offset(offset[0], offset[1], z);
403 * Return the current Zulu time.
410 struct tm * t = globals->get_time_params()->getGmt();
411 sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d",
412 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
413 t->tm_hour, t->tm_min, t->tm_sec);
420 * Set the current Zulu time.
423 setDateString (string date_string)
425 SGTime * st = globals->get_time_params();
426 struct tm * current_time = st->getGmt();
429 // Scan for basic ISO format
430 // YYYY-MM-DDTHH:MM:SS
431 int ret = sscanf(date_string.c_str(), "%d-%d-%dT%d:%d:%d",
432 &(new_time.tm_year), &(new_time.tm_mon),
433 &(new_time.tm_mday), &(new_time.tm_hour),
434 &(new_time.tm_min), &(new_time.tm_sec));
436 // Be pretty picky about this, so
437 // that strange things don't happen
438 // if the save file has been edited
441 SG_LOG(SG_INPUT, SG_ALERT, "Date/time string " << date_string
442 << " not in YYYY-MM-DDTHH:MM:SS format; skipped");
446 // OK, it looks like we got six
447 // values, one way or another.
448 new_time.tm_year -= 1900;
449 new_time.tm_mon -= 1;
451 // Now, tell flight gear to use
452 // the new time. This was far
453 // too difficult, by the way.
455 mktime(&new_time) - mktime(current_time) + globals->get_warp();
456 double lon = current_aircraft.fdm_state->get_Longitude();
457 double lat = current_aircraft.fdm_state->get_Latitude();
458 globals->set_warp(warp);
459 st->update(lon, lat, warp);
460 fgUpdateSkyAndLightingParams();
464 * Return the GMT as a string.
471 struct tm * t = globals->get_time_params()->getGmt();
472 sprintf(buf, " %.2d:%.2d:%.2d",
473 t->tm_hour, t->tm_min, t->tm_sec);
480 * Get the texture rendering state.
485 return (material_lib.get_step() == 0);
490 * Set the texture rendering state.
493 setTextures (bool textures)
496 material_lib.set_step(0);
498 material_lib.set_step(1);
503 * Return the magnetic variation
508 return globals->get_mag()->get_magvar() * SGD_RADIANS_TO_DEGREES;
513 * Return the magnetic dip
518 return globals->get_mag()->get_magdip() * SGD_RADIANS_TO_DEGREES;
523 * Return the current heading in degrees.
528 return current_aircraft.fdm_state->get_Psi() * SGD_RADIANS_TO_DEGREES - getMagVar();
533 * Return the fuel level in tank 1
538 return current_aircraft.fdm_state->get_Tank1Fuel();
542 setTank1Fuel ( double gals )
544 current_aircraft.fdm_state->set_Tank1Fuel( gals );
548 * Return the fuel level in tank 2
553 return current_aircraft.fdm_state->get_Tank2Fuel();
557 setTank2Fuel ( double gals )
559 current_aircraft.fdm_state->set_Tank2Fuel( gals );
564 * Get the autopilot altitude lock (true=on).
569 return (current_autopilot->get_AltitudeEnabled() &&
570 current_autopilot->get_AltitudeMode()
571 == FGAutopilot::FG_ALTITUDE_LOCK);
576 * Set the autopilot altitude lock (true=on).
579 setAPAltitudeLock (bool lock)
581 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
582 current_autopilot->set_AltitudeEnabled(lock);
587 * Get the autopilot target altitude in feet.
592 return current_autopilot->get_TargetAltitude() * SG_METER_TO_FEET;
597 * Set the autopilot target altitude in feet.
600 setAPAltitude (double altitude)
602 current_autopilot->set_TargetAltitude( altitude * SG_FEET_TO_METER );
606 * Get the autopilot altitude lock (true=on).
611 return (current_autopilot->get_AltitudeEnabled() &&
612 (current_autopilot->get_AltitudeMode()
613 == FGAutopilot::FG_ALTITUDE_GS1));
618 * Set the autopilot altitude lock (true=on).
621 setAPGSLock (bool lock)
623 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_GS1);
624 current_autopilot->set_AltitudeEnabled(lock);
629 * Get the autopilot terrain lock (true=on).
634 return (current_autopilot->get_AltitudeEnabled() &&
635 (current_autopilot->get_AltitudeMode()
636 == FGAutopilot::FG_ALTITUDE_TERRAIN));
641 * Set the autopilot terrain lock (true=on).
644 setAPTerrainLock (bool lock)
646 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_TERRAIN);
647 current_autopilot->set_AltitudeEnabled(lock);
648 current_autopilot->set_TargetAGL(
649 current_aircraft.fdm_state->get_Altitude_AGL() * SG_FEET_TO_METER
651 cout << "Target AGL = "
652 << current_aircraft.fdm_state->get_Altitude_AGL() * SG_FEET_TO_METER
658 * Get the autopilot target altitude in feet.
663 return current_autopilot->get_TargetClimbRate() * SG_METER_TO_FEET;
668 * Set the autopilot target altitude in feet.
671 setAPClimb (double rate)
673 current_autopilot->set_TargetClimbRate( rate * SG_FEET_TO_METER );
678 * Get the autopilot heading lock (true=on).
684 (current_autopilot->get_HeadingEnabled() &&
685 current_autopilot->get_HeadingMode() == DEFAULT_AP_HEADING_LOCK);
690 * Set the autopilot heading lock (true=on).
693 setAPHeadingLock (bool lock)
696 current_autopilot->set_HeadingMode(DEFAULT_AP_HEADING_LOCK);
697 current_autopilot->set_HeadingEnabled(true);
699 current_autopilot->set_HeadingEnabled(false);
705 * Get the autopilot heading bug in degrees.
710 return current_autopilot->get_DGTargetHeading();
715 * Set the autopilot heading bug in degrees.
718 setAPHeadingBug (double heading)
720 current_autopilot->set_DGTargetHeading( heading );
725 * Get the autopilot wing leveler lock (true=on).
731 (current_autopilot->get_HeadingEnabled() &&
732 current_autopilot->get_HeadingMode() == FGAutopilot::FG_TC_HEADING_LOCK);
737 * Set the autopilot wing leveler lock (true=on).
740 setAPWingLeveler (bool lock)
743 current_autopilot->set_HeadingMode(FGAutopilot::FG_TC_HEADING_LOCK);
744 current_autopilot->set_HeadingEnabled(true);
746 current_autopilot->set_HeadingEnabled(false);
751 * Return true if the autopilot is locked to NAV1.
757 (current_autopilot->get_HeadingEnabled() &&
758 current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
763 * Set the autopilot NAV1 lock.
766 setAPNAV1Lock (bool lock)
769 current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
770 current_autopilot->set_HeadingEnabled(true);
771 } else if (current_autopilot->get_HeadingMode() ==
772 FGAutopilot::FG_HEADING_NAV1) {
773 current_autopilot->set_HeadingEnabled(false);
778 * Get the autopilot autothrottle lock.
781 getAPAutoThrottleLock ()
783 return current_autopilot->get_AutoThrottleEnabled();
788 * Set the autothrottle lock.
791 setAPAutoThrottleLock (bool lock)
793 current_autopilot->set_AutoThrottleEnabled(lock);
799 getAPRudderControl ()
801 if (getAPHeadingLock())
802 return current_autopilot->get_TargetHeading();
804 return globals->get_controls()->get_rudder();
809 setAPRudderControl (double value)
811 if (getAPHeadingLock()) {
812 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPRudderControl " << value );
813 value -= current_autopilot->get_TargetHeading();
814 current_autopilot->HeadingAdjust(value < 0.0 ? -1.0 : 1.0);
816 globals->get_controls()->set_rudder(value);
822 getAPElevatorControl ()
824 if (getAPAltitudeLock())
825 return current_autopilot->get_TargetAltitude();
827 return globals->get_controls()->get_elevator();
832 setAPElevatorControl (double value)
834 if (getAPAltitudeLock()) {
835 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPElevatorControl " << value );
836 value -= current_autopilot->get_TargetAltitude();
837 current_autopilot->AltitudeAdjust(value < 0.0 ? 100.0 : -100.0);
839 globals->get_controls()->set_elevator(value);
845 getAPThrottleControl ()
847 if (getAPAutoThrottleLock())
848 return 0.0; // always resets
850 return globals->get_controls()->get_throttle(0);
855 setAPThrottleControl (double value)
857 if (getAPAutoThrottleLock())
858 current_autopilot->AutoThrottleAdjust(value < 0.0 ? -0.01 : 0.01);
860 globals->get_controls()->set_throttle(FGControls::ALL_ENGINES, value);
865 * Get the current visibility (meters).
870 #ifndef FG_OLD_WEATHER
871 return WeatherDatabase->getWeatherVisibility();
873 return current_weather.get_visibility();
879 * Set the current visibility (meters).
882 setVisibility (double visibility)
884 #ifndef FG_OLD_WEATHER
885 WeatherDatabase->setWeatherVisibility(visibility);
887 current_weather.set_visibility(visibility);
892 * Get the current wind north velocity (feet/second).
897 return current_aircraft.fdm_state->get_V_north_airmass();
902 * Set the current wind north velocity (feet/second).
905 setWindNorth (double speed)
907 current_aircraft.fdm_state
908 ->set_Velocities_Local_Airmass(speed, getWindEast(), getWindDown());
913 * Get the current wind east velocity (feet/second).
918 return current_aircraft.fdm_state->get_V_east_airmass();
923 * Set the current wind east velocity (feet/second).
926 setWindEast (double speed)
928 cout << "Set wind-east to " << speed << endl;
929 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
936 * Get the current wind down velocity (feet/second).
941 return current_aircraft.fdm_state->get_V_down_airmass();
946 * Set the current wind down velocity (feet/second).
949 setWindDown (double speed)
951 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
957 * Set the current engine0 running flag.
960 setRunningFlag (bool flag)
962 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
963 current_aircraft.fdm_state->get_engine(0)->set_Running_Flag( flag );
968 * Set the current engine0 cranking flag.
970 //Although there is no real reason to want to tell the engine that it is cranking,
971 //this is currently necessary to avoid the cranking sound being played
972 //before the engine inits.
974 setCrankingFlag (bool flag)
976 if ( current_aircraft.fdm_state->get_num_engines() > 0 ) {
977 current_aircraft.fdm_state->get_engine(0)->set_Cranking_Flag( flag );
984 return globals->get_current_view()->get_fov();
991 globals->get_current_view()->set_fov( fov );
998 return globals->get_warp();
1004 globals->set_warp(warp);
1010 return globals->get_warp_delta();
1014 setWarpDelta (long delta)
1016 globals->set_warp_delta(delta);
1020 setViewAxisLong (double axis)
1026 setViewAxisLat (double axis)
1038 setWindingCCW (bool state)
1040 winding_ccw = state;
1042 glFrontFace ( GL_CCW );
1044 glFrontFace ( GL_CW );
1050 #if defined(FX) && !defined(WIN32)
1051 return global_fullscreen;
1058 setFullScreen (bool state)
1060 #if defined(FX) && !defined(WIN32)
1061 global_fullscreen = state;
1062 # if defined(XMESA_FX_FULLSCREEN) && defined(XMESA_FX_WINDOW)
1063 XMesaSetFXmode( global_fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW );
1069 getFDMDataLogging ()
1071 return fdm_data_logging;
1075 setFDMDataLogging (bool state)
1077 // kludge; no getter or setter available
1078 if (state != fdm_data_logging) {
1079 fgToggleFDMdataLogging();
1080 fdm_data_logging = state;
1085 ////////////////////////////////////////////////////////////////////////
1086 // Tie the properties.
1087 ////////////////////////////////////////////////////////////////////////
1093 fgTie("/sim/logging/priority", getLoggingPriority, setLoggingPriority);
1094 fgTie("/sim/logging/classes", getLoggingClasses, setLoggingClasses);
1095 fgTie("/sim/freeze", getFreeze, setFreeze);
1096 fgTie("/sim/aircraft-dir", getAircraftDir, setAircraftDir);
1097 fgTie("/sim/view/offset-deg", getViewOffset, setViewOffset, false);
1098 fgSetArchivable("/sim/view/offset-deg");
1099 fgTie("/sim/view/goal-offset-deg", getGoalViewOffset, setGoalViewOffset, false);
1100 fgSetArchivable("/sim/view/goal-offset-deg");
1101 fgTie("/sim/view/pilot/x-offset-m",
1102 getPilotPositionXOffset, setPilotPositionXOffset);
1103 fgSetArchivable("/sim/view/pilot/x-offset-m");
1104 fgTie("/sim/view/pilot/y-offset-m",
1105 getPilotPositionYOffset, setPilotPositionYOffset);
1106 fgSetArchivable("/sim/view/pilot/y-offset-m");
1107 fgTie("/sim/view/pilot/z-offset-m",
1108 getPilotPositionZOffset, setPilotPositionZOffset);
1109 fgSetArchivable("/sim/view/pilot/z-offset-m");
1110 fgTie("/sim/time/gmt", getDateString, setDateString);
1111 fgSetArchivable("/sim/time/gmt");
1112 fgTie("/sim/time/gmt-string", getGMTString);
1113 fgTie("/sim/rendering/textures", getTextures, setTextures);
1116 fgTie("/orientation/heading-magnetic-deg", getHeadingMag);
1119 fgTie("/consumables/fuel/tank[0]/level-gal_us",
1120 getTank1Fuel, setTank1Fuel, false);
1121 fgSetArchivable("/consumables/fuel/tank[0]/level-gal_us");
1122 fgTie("/consumables/fuel/tank[1]/level-gal_us",
1123 getTank2Fuel, setTank2Fuel, false);
1124 fgSetArchivable("/consumables/fuel/tank[1]/level-gal_us");
1127 fgTie("/autopilot/locks/altitude", getAPAltitudeLock, setAPAltitudeLock);
1128 fgSetArchivable("/autopilot/locks/altitude");
1129 fgTie("/autopilot/settings/altitude-ft", getAPAltitude, setAPAltitude);
1130 fgSetArchivable("/autopilot/settings/altitude-ft");
1131 fgTie("/autopilot/locks/glide-slope", getAPGSLock, setAPGSLock);
1132 fgSetArchivable("/autopilot/locks/glide-slope");
1133 fgTie("/autopilot/locks/terrain", getAPTerrainLock, setAPTerrainLock);
1134 fgSetArchivable("/autopilot/locks/terrain");
1135 fgTie("/autopilot/settings/agl-ft", getAPAltitude, setAPAltitude);
1136 fgSetArchivable("/autopilot/settings/agl-ft");
1137 fgTie("/autopilot/settings/climb-rate-fpm", getAPClimb, setAPClimb, false);
1138 fgSetArchivable("/autopilot/settings/climb-rate-fpm");
1139 fgTie("/autopilot/locks/heading", getAPHeadingLock, setAPHeadingLock);
1140 fgSetArchivable("/autopilot/locks/heading");
1141 fgTie("/autopilot/settings/heading-bug-deg",
1142 getAPHeadingBug, setAPHeadingBug, false);
1143 fgSetArchivable("/autopilot/settings/heading-bug-deg");
1144 fgTie("/autopilot/locks/wing-leveler", getAPWingLeveler, setAPWingLeveler);
1145 fgSetArchivable("/autopilot/locks/wing-leveler");
1146 fgTie("/autopilot/locks/nav[0]", getAPNAV1Lock, setAPNAV1Lock);
1147 fgSetArchivable("/autopilot/locks/nav[0]");
1148 fgTie("/autopilot/locks/auto-throttle",
1149 getAPAutoThrottleLock, setAPAutoThrottleLock);
1150 fgSetArchivable("/autopilot/locks/auto-throttle");
1151 fgTie("/autopilot/control-overrides/rudder",
1152 getAPRudderControl, setAPRudderControl);
1153 fgSetArchivable("/autopilot/control-overrides/rudder");
1154 fgTie("/autopilot/control-overrides/elevator",
1155 getAPElevatorControl, setAPElevatorControl);
1156 fgSetArchivable("/autopilot/control-overrides/elevator");
1157 fgTie("/autopilot/control-overrides/throttle",
1158 getAPThrottleControl, setAPThrottleControl);
1159 fgSetArchivable("/autopilot/control-overrides/throttle");
1162 fgTie("/environment/visibility-m", getVisibility, setVisibility);
1163 fgSetArchivable("/environment/visibility-m");
1164 fgTie("/environment/wind-north-fps", getWindNorth, setWindNorth);
1165 fgSetArchivable("/environment/wind-north-fps");
1166 fgTie("/environment/wind-east-fps", getWindEast, setWindEast);
1167 fgSetArchivable("/environment/wind-east-fps");
1168 fgTie("/environment/wind-down-fps", getWindDown, setWindDown);
1169 fgSetArchivable("/environment/wind-down-fps");
1171 fgTie("/environment/magnetic-variation-deg", getMagVar);
1172 fgTie("/environment/magnetic-dip-deg", getMagDip);
1175 fgTie("/sim/field-of-view", getFOV, setFOV);
1176 fgSetArchivable("/sim/field-of-view");
1177 fgTie("/sim/time/warp", getWarp, setWarp, false);
1178 fgTie("/sim/time/warp-delta", getWarpDelta, setWarpDelta);
1179 fgTie("/sim/view/axes/long", (double(*)())0, setViewAxisLong);
1180 fgTie("/sim/view/axes/lat", (double(*)())0, setViewAxisLat);
1182 // Misc. Temporary junk.
1183 fgTie("/sim/temp/winding-ccw", getWindingCCW, setWindingCCW, false);
1184 fgTie("/sim/temp/full-screen", getFullScreen, setFullScreen);
1185 fgTie("/sim/temp/fdm-data-logging", getFDMDataLogging, setFDMDataLogging);
1193 _set_view_from_axes();
1198 ////////////////////////////////////////////////////////////////////////
1199 // Save and restore.
1200 ////////////////////////////////////////////////////////////////////////
1204 * Save the current state of the simulator to a stream.
1207 fgSaveFlight (ostream &output)
1210 writeProperties(output, globals->get_props());
1211 } catch (const sg_exception &e) {
1212 guiErrorMessage("Error saving flight: ", e);
1220 * Restore the current state of the simulator from a stream.
1223 fgLoadFlight (istream &input)
1225 SGPropertyNode props;
1227 readProperties(input, &props);
1228 } catch (const sg_exception &e) {
1229 guiErrorMessage("Error reading saved flight: ", e);
1232 copyProperties(&props, globals->get_props());
1233 // When loading a flight, make it the
1234 // new initial state.
1235 globals->saveInitialState();
1241 ////////////////////////////////////////////////////////////////////////
1242 // Implementation of FGCondition.
1243 ////////////////////////////////////////////////////////////////////////
1245 FGCondition::FGCondition ()
1249 FGCondition::~FGCondition ()
1255 ////////////////////////////////////////////////////////////////////////
1256 // Implementation of FGPropertyCondition.
1257 ////////////////////////////////////////////////////////////////////////
1259 FGPropertyCondition::FGPropertyCondition (const string &propname)
1260 : _node(fgGetNode(propname, true))
1264 FGPropertyCondition::~FGPropertyCondition ()
1270 ////////////////////////////////////////////////////////////////////////
1271 // Implementation of FGNotCondition.
1272 ////////////////////////////////////////////////////////////////////////
1274 FGNotCondition::FGNotCondition (FGCondition * condition)
1275 : _condition(condition)
1279 FGNotCondition::~FGNotCondition ()
1285 FGNotCondition::test () const
1287 return !(_condition->test());
1292 ////////////////////////////////////////////////////////////////////////
1293 // Implementation of FGAndCondition.
1294 ////////////////////////////////////////////////////////////////////////
1296 FGAndCondition::FGAndCondition ()
1300 FGAndCondition::~FGAndCondition ()
1302 for (unsigned int i = 0; i < _conditions.size(); i++)
1303 delete _conditions[i];
1307 FGAndCondition::test () const
1309 int nConditions = _conditions.size();
1310 for (int i = 0; i < nConditions; i++) {
1311 if (!_conditions[i]->test())
1318 FGAndCondition::addCondition (FGCondition * condition)
1320 _conditions.push_back(condition);
1325 ////////////////////////////////////////////////////////////////////////
1326 // Implementation of FGOrCondition.
1327 ////////////////////////////////////////////////////////////////////////
1329 FGOrCondition::FGOrCondition ()
1333 FGOrCondition::~FGOrCondition ()
1335 for (unsigned int i = 0; i < _conditions.size(); i++)
1336 delete _conditions[i];
1340 FGOrCondition::test () const
1342 int nConditions = _conditions.size();
1343 for (int i = 0; i < nConditions; i++) {
1344 if (_conditions[i]->test())
1351 FGOrCondition::addCondition (FGCondition * condition)
1353 _conditions.push_back(condition);
1358 ////////////////////////////////////////////////////////////////////////
1359 // Implementation of FGComparisonCondition.
1360 ////////////////////////////////////////////////////////////////////////
1363 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
1365 switch (left->getType()) {
1366 case SGPropertyNode::BOOL: {
1367 bool v1 = left->getBoolValue();
1368 bool v2 = right->getBoolValue();
1370 return FGComparisonCondition::LESS_THAN;
1372 return FGComparisonCondition::GREATER_THAN;
1374 return FGComparisonCondition::EQUALS;
1377 case SGPropertyNode::INT: {
1378 int v1 = left->getIntValue();
1379 int v2 = right->getIntValue();
1381 return FGComparisonCondition::LESS_THAN;
1383 return FGComparisonCondition::GREATER_THAN;
1385 return FGComparisonCondition::EQUALS;
1388 case SGPropertyNode::LONG: {
1389 long v1 = left->getLongValue();
1390 long v2 = right->getLongValue();
1392 return FGComparisonCondition::LESS_THAN;
1394 return FGComparisonCondition::GREATER_THAN;
1396 return FGComparisonCondition::EQUALS;
1399 case SGPropertyNode::FLOAT: {
1400 float v1 = left->getFloatValue();
1401 float v2 = right->getFloatValue();
1403 return FGComparisonCondition::LESS_THAN;
1405 return FGComparisonCondition::GREATER_THAN;
1407 return FGComparisonCondition::EQUALS;
1410 case SGPropertyNode::DOUBLE: {
1411 double v1 = left->getDoubleValue();
1412 double v2 = right->getDoubleValue();
1414 return FGComparisonCondition::LESS_THAN;
1416 return FGComparisonCondition::GREATER_THAN;
1418 return FGComparisonCondition::EQUALS;
1421 case SGPropertyNode::STRING:
1422 case SGPropertyNode::NONE:
1423 case SGPropertyNode::UNSPECIFIED: {
1424 string v1 = left->getStringValue();
1425 string v2 = right->getStringValue();
1427 return FGComparisonCondition::LESS_THAN;
1429 return FGComparisonCondition::GREATER_THAN;
1431 return FGComparisonCondition::EQUALS;
1435 throw sg_exception("Unrecognized node type");
1440 FGComparisonCondition::FGComparisonCondition (Type type, bool reverse)
1449 FGComparisonCondition::~FGComparisonCondition ()
1451 delete _right_value;
1455 FGComparisonCondition::test () const
1457 // Always fail if incompletely specified
1458 if (_left_property == 0 ||
1459 (_right_property == 0 && _right_value == 0))
1462 // Get LESS_THAN, EQUALS, or GREATER_THAN
1464 doComparison(_left_property,
1465 (_right_property != 0 ? _right_property : _right_value));
1467 return (cmp == _type);
1469 return (cmp != _type);
1473 FGComparisonCondition::setLeftProperty (const string &propname)
1475 _left_property = fgGetNode(propname, true);
1479 FGComparisonCondition::setRightProperty (const string &propname)
1481 delete _right_value;
1483 _right_property = fgGetNode(propname, true);
1487 FGComparisonCondition::setRightValue (const SGPropertyNode *node)
1489 _right_property = 0;
1490 delete _right_value;
1491 _right_value = new SGPropertyNode(*node);
1496 ////////////////////////////////////////////////////////////////////////
1497 // Read a condition and use it if necessary.
1498 ////////////////////////////////////////////////////////////////////////
1500 // Forward declaration
1501 static FGCondition * readCondition (const SGPropertyNode * node);
1503 static FGCondition *
1504 readPropertyCondition (const SGPropertyNode * node)
1506 return new FGPropertyCondition(node->getStringValue());
1509 static FGCondition *
1510 readNotCondition (const SGPropertyNode * node)
1512 int nChildren = node->nChildren();
1513 for (int i = 0; i < nChildren; i++) {
1514 const SGPropertyNode * child = node->getChild(i);
1515 FGCondition * condition = readCondition(child);
1517 return new FGNotCondition(condition);
1519 SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition");
1523 static FGCondition *
1524 readAndConditions (const SGPropertyNode * node)
1526 FGAndCondition * andCondition = new FGAndCondition;
1527 int nChildren = node->nChildren();
1528 for (int i = 0; i < nChildren; i++) {
1529 const SGPropertyNode * child = node->getChild(i);
1530 FGCondition * condition = readCondition(child);
1532 andCondition->addCondition(condition);
1534 return andCondition;
1537 static FGCondition *
1538 readOrConditions (const SGPropertyNode * node)
1540 FGOrCondition * orCondition = new FGOrCondition;
1541 int nChildren = node->nChildren();
1542 for (int i = 0; i < nChildren; i++) {
1543 const SGPropertyNode * child = node->getChild(i);
1544 FGCondition * condition = readCondition(child);
1546 orCondition->addCondition(condition);
1551 static FGCondition *
1552 readComparison (const SGPropertyNode * node,
1553 FGComparisonCondition::Type type,
1556 FGComparisonCondition * condition = new FGComparisonCondition(type, reverse);
1557 condition->setLeftProperty(node->getStringValue("property[0]"));
1558 if (node->hasValue("property[1]"))
1559 condition->setRightProperty(node->getStringValue("property[1]"));
1561 condition->setRightValue(node->getChild("value", 0));
1566 static FGCondition *
1567 readCondition (const SGPropertyNode * node)
1569 const string &name = node->getName();
1570 if (name == "property")
1571 return readPropertyCondition(node);
1572 else if (name == "not")
1573 return readNotCondition(node);
1574 else if (name == "and")
1575 return readAndConditions(node);
1576 else if (name == "or")
1577 return readOrConditions(node);
1578 else if (name == "less-than")
1579 return readComparison(node, FGComparisonCondition::LESS_THAN, false);
1580 else if (name == "less-than-equals")
1581 return readComparison(node, FGComparisonCondition::GREATER_THAN, true);
1582 else if (name == "greater-than")
1583 return readComparison(node, FGComparisonCondition::GREATER_THAN, false);
1584 else if (name == "greater-than-equals")
1585 return readComparison(node, FGComparisonCondition::LESS_THAN, true);
1586 else if (name == "equals")
1587 return readComparison(node, FGComparisonCondition::EQUALS, false);
1588 else if (name == "not-equals")
1589 return readComparison(node, FGComparisonCondition::EQUALS, true);
1596 ////////////////////////////////////////////////////////////////////////
1597 // Implementation of FGConditional.
1598 ////////////////////////////////////////////////////////////////////////
1600 FGConditional::FGConditional ()
1605 FGConditional::~FGConditional ()
1611 FGConditional::setCondition (FGCondition * condition)
1614 _condition = condition;
1618 FGConditional::test () const
1620 return ((_condition == 0) || _condition->test());
1625 // The top-level is always an implicit 'and' group
1627 fgReadCondition (const SGPropertyNode * node)
1629 return readAndConditions(node);
1633 // end of fg_props.cxx