1 // fg_props.cxx -- support for FlightGear properties.
3 // Written by David Megginson, started 2000.
5 // Copyright (C) 2000, 2001 David Megginson - david@megginson.com
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 # include <simgear/compiler.h>
27 #include <simgear/misc/exception.hxx>
31 #include <ATC/ATCdisplay.hxx>
32 #include <Autopilot/newauto.hxx>
33 #include <Aircraft/aircraft.hxx>
34 #include <Time/tmp.hxx>
35 #include <FDM/UIUCModel/uiuc_aircraftdir.h>
36 #ifndef FG_NEW_ENVIRONMENT
37 # include <WeatherCM/FGLocalWeatherDatabase.h>
39 # include <Environment/environment.hxx>
40 #endif // FG_NEW_ENVIRONMENT
41 #include <Objects/matlib.hxx>
45 #include "globals.hxx"
47 #include "fg_props.hxx"
48 #include "viewmgr.hxx"
50 #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
51 SG_USING_STD(istream);
52 SG_USING_STD(ostream);
55 #if !defined(FG_NEW_ENVIRONMENT)
56 static double getWindNorth ();
57 static double getWindEast ();
58 static double getWindDown ();
59 #endif // FG_NEW_ENVIRONMENT
61 // Allow the view to be set from two axes (i.e. a joystick hat)
62 // This needs to be in FGViewer itself, somehow.
63 static double axisLong = 0.0;
64 static double axisLat = 0.0;
66 static bool winding_ccw = true; // FIXME: temporary
68 static bool fdm_data_logging = false; // FIXME: temporary
75 _set_view_from_axes ()
77 // Take no action when hat is centered
78 if ( ( axisLong < 0.01 ) &&
79 ( axisLong > -0.01 ) &&
87 /* Do all the quick and easy cases */
88 if (axisLong < 0) { // Longitudinal axis forward
89 if (axisLat == axisLong)
91 else if (axisLat == - axisLong)
93 else if (axisLat == 0)
95 } else if (axisLong > 0) { // Longitudinal axis backward
96 if (axisLat == - axisLong)
98 else if (axisLat == axisLong)
100 else if (axisLat == 0)
102 } else if (axisLong == 0) { // Longitudinal axis neutral
105 else if (axisLat > 0)
107 else return; /* And assertion failure maybe? */
110 /* Do all the difficult cases */
112 viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axisLat, -axisLong );
113 if ( viewDir < -1 ) viewDir += 360;
115 // SG_LOG(SG_INPUT, SG_ALERT, "Joystick Lat=" << axisLat << " and Long="
116 // << axisLong << " gave angle=" << viewDir );
118 globals->get_current_view()->set_goal_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
119 // globals->get_current_view()->set_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
123 ////////////////////////////////////////////////////////////////////////
124 // Default property bindings (not yet handled by any module).
125 ////////////////////////////////////////////////////////////////////////
127 struct LogClassMapping {
130 LogClassMapping(sgDebugClass cc, string nname) { c = cc; name = nname; }
133 LogClassMapping log_class_mappings [] = {
134 LogClassMapping(SG_NONE, "none"),
135 LogClassMapping(SG_TERRAIN, "terrain"),
136 LogClassMapping(SG_ASTRO, "astro"),
137 LogClassMapping(SG_FLIGHT, "flight"),
138 LogClassMapping(SG_INPUT, "input"),
139 LogClassMapping(SG_GL, "gl"),
140 LogClassMapping(SG_VIEW, "view"),
141 LogClassMapping(SG_COCKPIT, "cockpit"),
142 LogClassMapping(SG_GENERAL, "general"),
143 LogClassMapping(SG_MATH, "math"),
144 LogClassMapping(SG_EVENT, "event"),
145 LogClassMapping(SG_AIRCRAFT, "aircraft"),
146 LogClassMapping(SG_AUTOPILOT, "autopilot"),
147 LogClassMapping(SG_IO, "io"),
148 LogClassMapping(SG_CLIPPER, "clipper"),
149 LogClassMapping(SG_NETWORK, "network"),
150 LogClassMapping(SG_UNDEFD, "")
155 * Get the logging classes.
160 sgDebugClass classes = logbuf::get_log_classes();
162 for (int i = 0; log_class_mappings[i].c != SG_UNDEFD; i++) {
163 if ((classes&log_class_mappings[i].c) > 0) {
164 if (result != (string)"")
166 result += log_class_mappings[i].name;
173 static void addLoggingClass (const string &name)
175 sgDebugClass classes = logbuf::get_log_classes();
176 for (int i = 0; log_class_mappings[i].c != SG_UNDEFD; i++) {
177 if (name == log_class_mappings[i].name) {
178 logbuf::set_log_classes(sgDebugClass(classes|log_class_mappings[i].c));
182 SG_LOG(SG_GENERAL, SG_ALERT, "Unknown logging class: " << name);
187 * Set the logging classes.
190 setLoggingClasses (string classes)
192 logbuf::set_log_classes(SG_NONE);
194 if (classes == "none") {
195 SG_LOG(SG_GENERAL, SG_INFO, "Disabled all logging classes");
199 if (classes == "" || classes == "all") { // default
200 logbuf::set_log_classes(SG_ALL);
201 SG_LOG(SG_GENERAL, SG_INFO, "Enabled all logging classes: "
202 << getLoggingClasses());
206 string rest = classes;
208 int sep = rest.find('|');
210 name = rest.substr(0, sep);
211 rest = rest.substr(sep+1);
212 addLoggingClass(name);
213 sep = rest.find('|');
215 addLoggingClass(rest);
216 SG_LOG(SG_GENERAL, SG_INFO, "Set logging classes to "
217 << getLoggingClasses());
222 * Get the logging priority.
225 getLoggingPriority ()
227 switch (logbuf::get_log_priority()) {
239 SG_LOG(SG_GENERAL, SG_WARN, "Internal: Unknown logging priority number: "
240 << logbuf::get_log_priority());
247 * Set the logging priority.
250 setLoggingPriority (string priority)
252 if (priority == "bulk") {
253 logbuf::set_log_priority(SG_BULK);
254 } else if (priority == "debug") {
255 logbuf::set_log_priority(SG_DEBUG);
256 } else if (priority == "" || priority == "info") { // default
257 logbuf::set_log_priority(SG_INFO);
258 } else if (priority == "warn") {
259 logbuf::set_log_priority(SG_WARN);
260 } else if (priority == "alert") {
261 logbuf::set_log_priority(SG_ALERT);
263 SG_LOG(SG_GENERAL, SG_WARN, "Unknown logging priority " << priority);
265 SG_LOG(SG_GENERAL, SG_INFO, "Logging priority is " << getLoggingPriority());
271 * Get the pause state of the sim.
276 return globals->get_freeze();
281 * Set the pause state of the sim.
284 setFreeze (bool freeze)
286 globals->set_freeze(freeze);
289 current_atcdisplay->CancelRepeatingMessage();
290 current_atcdisplay->RegisterRepeatingMessage("**** SIM IS FROZEN **** SIM IS FROZEN ****");
293 current_atcdisplay->CancelRepeatingMessage();
299 * Return the current aircraft directory (UIUC) as a string.
309 * Set the current aircraft directory (UIUC).
312 setAircraftDir (string dir)
314 if (getAircraftDir() != dir) {
316 // needReinit(); FIXME!!
322 * Get the current view offset in degrees.
327 return (globals->get_current_view()
328 ->get_view_offset() * SGD_RADIANS_TO_DEGREES);
333 setViewOffset (double offset)
335 globals->get_current_view()->set_view_offset(offset * SGD_DEGREES_TO_RADIANS);
341 return (globals->get_current_view()
342 ->get_goal_view_offset() * SGD_RADIANS_TO_DEGREES);
346 setGoalViewOffset (double offset)
348 while ( offset < 0 ) {
351 while ( offset > 360.0 ) {
354 // Snap to center if we are close
355 if ( fabs(offset) < 1.0 || fabs(offset) > 359.0 ) {
359 globals->get_current_view()
360 ->set_goal_view_offset(offset * SGD_DEGREES_TO_RADIANS);
364 * Get the current view tilt in degrees.
369 return (globals->get_current_view()
370 ->get_view_tilt() * SGD_RADIANS_TO_DEGREES);
375 setViewTilt (double tilt)
377 globals->get_current_view()->set_view_tilt(tilt * SGD_DEGREES_TO_RADIANS);
383 return (globals->get_current_view()
384 ->get_goal_view_tilt() * SGD_RADIANS_TO_DEGREES);
388 setGoalViewTilt (double tilt)
393 while ( tilt > 360.0 ) {
396 // Snap to center if we are close
397 if ( fabs(tilt) < 1.0 || fabs(tilt) > 359.0 ) {
401 globals->get_current_view()
402 ->set_goal_view_tilt(tilt * SGD_DEGREES_TO_RADIANS);
407 * Pilot position offset from CG.
410 getPilotPositionXOffset ()
412 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
413 float * offset = pilot_view->get_pilot_offset();
418 setPilotPositionXOffset (float x)
420 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
421 float * offset = pilot_view->get_pilot_offset();
422 pilot_view->set_pilot_offset(x, offset[1], offset[2]);
426 getPilotPositionYOffset ()
428 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
429 float * offset = pilot_view->get_pilot_offset();
434 setPilotPositionYOffset (float y)
436 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
437 float * offset = pilot_view->get_pilot_offset();
438 pilot_view->set_pilot_offset(offset[0], y, offset[2]);
442 getPilotPositionZOffset ()
444 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
445 float * offset = pilot_view->get_pilot_offset();
450 setPilotPositionZOffset (float z)
452 FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
453 float * offset = pilot_view->get_pilot_offset();
454 pilot_view->set_pilot_offset(offset[0], offset[1], z);
459 * Return the current Zulu time.
466 struct tm * t = globals->get_time_params()->getGmt();
467 sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d",
468 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
469 t->tm_hour, t->tm_min, t->tm_sec);
476 * Set the current Zulu time.
479 setDateString (string date_string)
481 static const SGPropertyNode *cur_time_override
482 = fgGetNode("/sim/time/cur-time-override", true);
484 SGTime * st = globals->get_time_params();
485 struct tm * current_time = st->getGmt();
488 // Scan for basic ISO format
489 // YYYY-MM-DDTHH:MM:SS
490 int ret = sscanf(date_string.c_str(), "%d-%d-%dT%d:%d:%d",
491 &(new_time.tm_year), &(new_time.tm_mon),
492 &(new_time.tm_mday), &(new_time.tm_hour),
493 &(new_time.tm_min), &(new_time.tm_sec));
495 // Be pretty picky about this, so
496 // that strange things don't happen
497 // if the save file has been edited
500 SG_LOG(SG_INPUT, SG_ALERT, "Date/time string " << date_string
501 << " not in YYYY-MM-DDTHH:MM:SS format; skipped");
505 // OK, it looks like we got six
506 // values, one way or another.
507 new_time.tm_year -= 1900;
508 new_time.tm_mon -= 1;
510 // Now, tell flight gear to use
511 // the new time. This was far
512 // too difficult, by the way.
514 mktime(&new_time) - mktime(current_time) + globals->get_warp();
515 double lon = current_aircraft.fdm_state->get_Longitude();
516 double lat = current_aircraft.fdm_state->get_Latitude();
517 globals->set_warp(warp);
518 st->update(lon, lat, cur_time_override->getLongValue(), warp);
519 fgUpdateSkyAndLightingParams();
523 * Return the GMT as a string.
530 struct tm *t = globals->get_time_params()->getGmt();
531 sprintf(buf, " %.2d:%.2d:%.2d",
532 t->tm_hour, t->tm_min, t->tm_sec);
533 // cout << t << " " << buf << endl;
540 * Get the texture rendering state.
545 return (material_lib.get_step() == 0);
550 * Set the texture rendering state.
553 setTextures (bool textures)
556 material_lib.set_step(0);
558 material_lib.set_step(1);
563 * Return the magnetic variation
568 return globals->get_mag()->get_magvar() * SGD_RADIANS_TO_DEGREES;
573 * Return the magnetic dip
578 return globals->get_mag()->get_magdip() * SGD_RADIANS_TO_DEGREES;
583 * Return the current heading in degrees.
588 return current_aircraft.fdm_state->get_Psi() * SGD_RADIANS_TO_DEGREES - getMagVar();
593 * Get the autopilot altitude lock (true=on).
598 return (current_autopilot->get_AltitudeEnabled() &&
599 current_autopilot->get_AltitudeMode()
600 == FGAutopilot::FG_ALTITUDE_LOCK);
605 * Set the autopilot altitude lock (true=on).
608 setAPAltitudeLock (bool lock)
611 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
612 if (current_autopilot->get_AltitudeMode() == FGAutopilot::FG_ALTITUDE_LOCK)
613 current_autopilot->set_AltitudeEnabled(lock);
618 * Get the autopilot target altitude in feet.
623 return current_autopilot->get_TargetAltitude() * SG_METER_TO_FEET;
628 * Set the autopilot target altitude in feet.
631 setAPAltitude (double altitude)
633 current_autopilot->set_TargetAltitude( altitude * SG_FEET_TO_METER );
637 * Get the autopilot altitude lock (true=on).
642 return (current_autopilot->get_AltitudeEnabled() &&
643 (current_autopilot->get_AltitudeMode()
644 == FGAutopilot::FG_ALTITUDE_GS1));
649 * Set the autopilot altitude lock (true=on).
652 setAPGSLock (bool lock)
655 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_GS1);
656 if (current_autopilot->get_AltitudeMode() == FGAutopilot::FG_ALTITUDE_GS1)
657 current_autopilot->set_AltitudeEnabled(lock);
662 * Get the autopilot terrain lock (true=on).
667 return (current_autopilot->get_AltitudeEnabled() &&
668 (current_autopilot->get_AltitudeMode()
669 == FGAutopilot::FG_ALTITUDE_TERRAIN));
674 * Set the autopilot terrain lock (true=on).
677 setAPTerrainLock (bool lock)
680 current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_TERRAIN);
682 ->set_TargetAGL(current_aircraft.fdm_state->get_Altitude_AGL() *
684 cout << "Target AGL = "
685 << current_aircraft.fdm_state->get_Altitude_AGL() * SG_FEET_TO_METER
688 if (current_autopilot->get_AltitudeMode() == FGAutopilot::FG_ALTITUDE_TERRAIN)
689 current_autopilot->set_AltitudeEnabled(lock);
694 * Get the autopilot target altitude in feet.
699 return current_autopilot->get_TargetClimbRate() * SG_METER_TO_FEET;
704 * Set the autopilot target altitude in feet.
707 setAPClimb (double rate)
709 current_autopilot->set_TargetClimbRate( rate * SG_FEET_TO_METER );
714 * Get the autopilot heading lock (true=on).
720 (current_autopilot->get_HeadingEnabled() &&
721 current_autopilot->get_HeadingMode() == DEFAULT_AP_HEADING_LOCK);
726 * Set the autopilot heading lock (true=on).
729 setAPHeadingLock (bool lock)
732 current_autopilot->set_HeadingMode(DEFAULT_AP_HEADING_LOCK);
733 if (current_autopilot->get_HeadingMode() == DEFAULT_AP_HEADING_LOCK)
734 current_autopilot->set_HeadingEnabled(lock);
739 * Get the autopilot heading bug in degrees.
744 return current_autopilot->get_DGTargetHeading();
749 * Set the autopilot heading bug in degrees.
752 setAPHeadingBug (double heading)
754 current_autopilot->set_DGTargetHeading( heading );
759 * Get the autopilot wing leveler lock (true=on).
765 (current_autopilot->get_HeadingEnabled() &&
766 current_autopilot->get_HeadingMode() == FGAutopilot::FG_TC_HEADING_LOCK);
771 * Set the autopilot wing leveler lock (true=on).
774 setAPWingLeveler (bool lock)
777 current_autopilot->set_HeadingMode(FGAutopilot::FG_TC_HEADING_LOCK);
778 if (current_autopilot->get_HeadingMode() == FGAutopilot::FG_TC_HEADING_LOCK)
779 current_autopilot->set_HeadingEnabled(lock);
783 * Return true if the autopilot is locked to NAV1.
789 (current_autopilot->get_HeadingEnabled() &&
790 current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
795 * Set the autopilot NAV1 lock.
798 setAPNAV1Lock (bool lock)
801 current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
802 if (current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1)
803 current_autopilot->set_HeadingEnabled(lock);
807 * Get the autopilot autothrottle lock.
810 getAPAutoThrottleLock ()
812 return current_autopilot->get_AutoThrottleEnabled();
817 * Set the autothrottle lock.
820 setAPAutoThrottleLock (bool lock)
822 current_autopilot->set_AutoThrottleEnabled(lock);
828 getAPRudderControl ()
830 if (getAPHeadingLock())
831 return current_autopilot->get_TargetHeading();
833 return globals->get_controls()->get_rudder();
838 setAPRudderControl (double value)
840 if (getAPHeadingLock()) {
841 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPRudderControl " << value );
842 value -= current_autopilot->get_TargetHeading();
843 current_autopilot->HeadingAdjust(value < 0.0 ? -1.0 : 1.0);
845 globals->get_controls()->set_rudder(value);
851 getAPElevatorControl ()
853 if (getAPAltitudeLock())
854 return current_autopilot->get_TargetAltitude();
856 return globals->get_controls()->get_elevator();
861 setAPElevatorControl (double value)
863 if (value != 0 && getAPAltitudeLock()) {
864 SG_LOG(SG_GENERAL, SG_DEBUG, "setAPElevatorControl " << value );
865 value -= current_autopilot->get_TargetAltitude();
866 current_autopilot->AltitudeAdjust(value < 0.0 ? 100.0 : -100.0);
868 globals->get_controls()->set_elevator(value);
874 getAPThrottleControl ()
876 if (getAPAutoThrottleLock())
877 return 0.0; // always resets
879 return globals->get_controls()->get_throttle(0);
884 setAPThrottleControl (double value)
886 if (getAPAutoThrottleLock())
887 current_autopilot->AutoThrottleAdjust(value < 0.0 ? -0.01 : 0.01);
889 globals->get_controls()->set_throttle(FGControls::ALL_ENGINES, value);
893 #if !defined(FG_NEW_ENVIRONMENT)
896 * Get the current visibility (meters).
901 return WeatherDatabase->getWeatherVisibility();
906 * Set the current visibility (meters).
909 setVisibility (double visibility)
911 WeatherDatabase->setWeatherVisibility(visibility);
915 * Get the current wind north velocity (feet/second).
920 return current_aircraft.fdm_state->get_V_north_airmass();
925 * Set the current wind north velocity (feet/second).
928 setWindNorth (double speed)
930 current_aircraft.fdm_state
931 ->set_Velocities_Local_Airmass(speed, getWindEast(), getWindDown());
936 * Get the current wind east velocity (feet/second).
941 return current_aircraft.fdm_state->get_V_east_airmass();
946 * Set the current wind east velocity (feet/second).
949 setWindEast (double speed)
951 cout << "Set wind-east to " << speed << endl;
952 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
959 * Get the current wind down velocity (feet/second).
964 return current_aircraft.fdm_state->get_V_down_airmass();
969 * Set the current wind down velocity (feet/second).
972 setWindDown (double speed)
974 current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
979 #endif // FG_NEW_ENVIRONMENT
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 globals->get_fullscreen();
1058 setFullScreen (bool state)
1060 #if defined(FX) && !defined(WIN32)
1061 globals->set_fullscreen(state);
1062 # if defined(XMESA_FX_FULLSCREEN) && defined(XMESA_FX_WINDOW)
1063 XMesaSetFXmode( state ? 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 fgTie("/sim/view/tilt-deg", getViewTilt, setViewTilt, false);
1101 fgSetArchivable("/sim/view/tilt-deg");
1102 fgTie("/sim/view/goal-tilt-deg", getGoalViewTilt, setGoalViewTilt, false);
1103 fgSetArchivable("/sim/view/goal-offset-deg");
1104 fgTie("/sim/view/pilot/x-offset-m",
1105 getPilotPositionXOffset, setPilotPositionXOffset);
1106 fgSetArchivable("/sim/view/pilot/x-offset-m");
1107 fgTie("/sim/view/pilot/y-offset-m",
1108 getPilotPositionYOffset, setPilotPositionYOffset);
1109 fgSetArchivable("/sim/view/pilot/y-offset-m");
1110 fgTie("/sim/view/pilot/z-offset-m",
1111 getPilotPositionZOffset, setPilotPositionZOffset);
1112 fgSetArchivable("/sim/view/pilot/z-offset-m");
1113 fgTie("/sim/time/gmt", getDateString, setDateString);
1114 fgSetArchivable("/sim/time/gmt");
1115 fgTie("/sim/time/gmt-string", getGMTString);
1116 fgTie("/sim/rendering/textures", getTextures, setTextures);
1119 fgTie("/orientation/heading-magnetic-deg", getHeadingMag);
1122 fgTie("/autopilot/locks/altitude", getAPAltitudeLock, setAPAltitudeLock);
1123 fgSetArchivable("/autopilot/locks/altitude");
1124 fgTie("/autopilot/settings/altitude-ft", getAPAltitude, setAPAltitude);
1125 fgSetArchivable("/autopilot/settings/altitude-ft");
1126 fgTie("/autopilot/locks/glide-slope", getAPGSLock, setAPGSLock);
1127 fgSetArchivable("/autopilot/locks/glide-slope");
1128 fgTie("/autopilot/locks/terrain", getAPTerrainLock, setAPTerrainLock);
1129 fgSetArchivable("/autopilot/locks/terrain");
1130 fgTie("/autopilot/settings/climb-rate-fpm", getAPClimb, setAPClimb, false);
1131 fgSetArchivable("/autopilot/settings/climb-rate-fpm");
1132 fgTie("/autopilot/locks/heading", getAPHeadingLock, setAPHeadingLock);
1133 fgSetArchivable("/autopilot/locks/heading");
1134 fgTie("/autopilot/settings/heading-bug-deg",
1135 getAPHeadingBug, setAPHeadingBug);
1136 fgSetArchivable("/autopilot/settings/heading-bug-deg");
1137 fgTie("/autopilot/locks/wing-leveler", getAPWingLeveler, setAPWingLeveler);
1138 fgSetArchivable("/autopilot/locks/wing-leveler");
1139 fgTie("/autopilot/locks/nav[0]", getAPNAV1Lock, setAPNAV1Lock);
1140 fgSetArchivable("/autopilot/locks/nav[0]");
1141 fgTie("/autopilot/locks/auto-throttle",
1142 getAPAutoThrottleLock, setAPAutoThrottleLock);
1143 fgSetArchivable("/autopilot/locks/auto-throttle");
1144 fgTie("/autopilot/control-overrides/rudder",
1145 getAPRudderControl, setAPRudderControl);
1146 fgSetArchivable("/autopilot/control-overrides/rudder");
1147 fgTie("/autopilot/control-overrides/elevator",
1148 getAPElevatorControl, setAPElevatorControl);
1149 fgSetArchivable("/autopilot/control-overrides/elevator");
1150 fgTie("/autopilot/control-overrides/throttle",
1151 getAPThrottleControl, setAPThrottleControl);
1152 fgSetArchivable("/autopilot/control-overrides/throttle");
1155 #if !defined(FG_NEW_ENVIRONMENT)
1156 fgTie("/environment/visibility-m", getVisibility, setVisibility);
1157 fgSetArchivable("/environment/visibility-m");
1158 fgTie("/environment/wind-north-fps", getWindNorth, setWindNorth);
1159 fgSetArchivable("/environment/wind-north-fps");
1160 fgTie("/environment/wind-east-fps", getWindEast, setWindEast);
1161 fgSetArchivable("/environment/wind-east-fps");
1162 fgTie("/environment/wind-down-fps", getWindDown, setWindDown);
1163 fgSetArchivable("/environment/wind-down-fps");
1166 fgTie("/environment/magnetic-variation-deg", getMagVar);
1167 fgTie("/environment/magnetic-dip-deg", getMagDip);
1170 fgTie("/sim/field-of-view", getFOV, setFOV);
1171 fgSetArchivable("/sim/field-of-view");
1172 fgTie("/sim/time/warp", getWarp, setWarp, false);
1173 fgTie("/sim/time/warp-delta", getWarpDelta, setWarpDelta);
1174 fgTie("/sim/view/axes/long", (double(*)())0, setViewAxisLong);
1175 fgTie("/sim/view/axes/lat", (double(*)())0, setViewAxisLat);
1177 // Misc. Temporary junk.
1178 fgTie("/sim/temp/winding-ccw", getWindingCCW, setWindingCCW, false);
1179 fgTie("/sim/temp/full-screen", getFullScreen, setFullScreen);
1180 fgTie("/sim/temp/fdm-data-logging", getFDMDataLogging, setFDMDataLogging);
1188 _set_view_from_axes();
1193 ////////////////////////////////////////////////////////////////////////
1194 // Save and restore.
1195 ////////////////////////////////////////////////////////////////////////
1199 * Save the current state of the simulator to a stream.
1202 fgSaveFlight (ostream &output)
1205 writeProperties(output, globals->get_props());
1206 } catch (const sg_exception &e) {
1207 guiErrorMessage("Error saving flight: ", e);
1215 * Restore the current state of the simulator from a stream.
1218 fgLoadFlight (istream &input)
1220 SGPropertyNode props;
1222 readProperties(input, &props);
1223 } catch (const sg_exception &e) {
1224 guiErrorMessage("Error reading saved flight: ", e);
1227 copyProperties(&props, globals->get_props());
1228 // When loading a flight, make it the
1229 // new initial state.
1230 globals->saveInitialState();
1236 ////////////////////////////////////////////////////////////////////////
1237 // Implementation of FGCondition.
1238 ////////////////////////////////////////////////////////////////////////
1240 FGCondition::FGCondition ()
1244 FGCondition::~FGCondition ()
1250 ////////////////////////////////////////////////////////////////////////
1251 // Implementation of FGPropertyCondition.
1252 ////////////////////////////////////////////////////////////////////////
1254 FGPropertyCondition::FGPropertyCondition (const string &propname)
1255 : _node(fgGetNode(propname, true))
1259 FGPropertyCondition::~FGPropertyCondition ()
1265 ////////////////////////////////////////////////////////////////////////
1266 // Implementation of FGNotCondition.
1267 ////////////////////////////////////////////////////////////////////////
1269 FGNotCondition::FGNotCondition (FGCondition * condition)
1270 : _condition(condition)
1274 FGNotCondition::~FGNotCondition ()
1280 FGNotCondition::test () const
1282 return !(_condition->test());
1287 ////////////////////////////////////////////////////////////////////////
1288 // Implementation of FGAndCondition.
1289 ////////////////////////////////////////////////////////////////////////
1291 FGAndCondition::FGAndCondition ()
1295 FGAndCondition::~FGAndCondition ()
1297 for (unsigned int i = 0; i < _conditions.size(); i++)
1298 delete _conditions[i];
1302 FGAndCondition::test () const
1304 int nConditions = _conditions.size();
1305 for (int i = 0; i < nConditions; i++) {
1306 if (!_conditions[i]->test())
1313 FGAndCondition::addCondition (FGCondition * condition)
1315 _conditions.push_back(condition);
1320 ////////////////////////////////////////////////////////////////////////
1321 // Implementation of FGOrCondition.
1322 ////////////////////////////////////////////////////////////////////////
1324 FGOrCondition::FGOrCondition ()
1328 FGOrCondition::~FGOrCondition ()
1330 for (unsigned int i = 0; i < _conditions.size(); i++)
1331 delete _conditions[i];
1335 FGOrCondition::test () const
1337 int nConditions = _conditions.size();
1338 for (int i = 0; i < nConditions; i++) {
1339 if (_conditions[i]->test())
1346 FGOrCondition::addCondition (FGCondition * condition)
1348 _conditions.push_back(condition);
1353 ////////////////////////////////////////////////////////////////////////
1354 // Implementation of FGComparisonCondition.
1355 ////////////////////////////////////////////////////////////////////////
1358 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
1360 switch (left->getType()) {
1361 case SGPropertyNode::BOOL: {
1362 bool v1 = left->getBoolValue();
1363 bool v2 = right->getBoolValue();
1365 return FGComparisonCondition::LESS_THAN;
1367 return FGComparisonCondition::GREATER_THAN;
1369 return FGComparisonCondition::EQUALS;
1372 case SGPropertyNode::INT: {
1373 int v1 = left->getIntValue();
1374 int v2 = right->getIntValue();
1376 return FGComparisonCondition::LESS_THAN;
1378 return FGComparisonCondition::GREATER_THAN;
1380 return FGComparisonCondition::EQUALS;
1383 case SGPropertyNode::LONG: {
1384 long v1 = left->getLongValue();
1385 long v2 = right->getLongValue();
1387 return FGComparisonCondition::LESS_THAN;
1389 return FGComparisonCondition::GREATER_THAN;
1391 return FGComparisonCondition::EQUALS;
1394 case SGPropertyNode::FLOAT: {
1395 float v1 = left->getFloatValue();
1396 float v2 = right->getFloatValue();
1398 return FGComparisonCondition::LESS_THAN;
1400 return FGComparisonCondition::GREATER_THAN;
1402 return FGComparisonCondition::EQUALS;
1405 case SGPropertyNode::DOUBLE: {
1406 double v1 = left->getDoubleValue();
1407 double v2 = right->getDoubleValue();
1409 return FGComparisonCondition::LESS_THAN;
1411 return FGComparisonCondition::GREATER_THAN;
1413 return FGComparisonCondition::EQUALS;
1416 case SGPropertyNode::STRING:
1417 case SGPropertyNode::NONE:
1418 case SGPropertyNode::UNSPECIFIED: {
1419 string v1 = left->getStringValue();
1420 string v2 = right->getStringValue();
1422 return FGComparisonCondition::LESS_THAN;
1424 return FGComparisonCondition::GREATER_THAN;
1426 return FGComparisonCondition::EQUALS;
1430 throw sg_exception("Unrecognized node type");
1435 FGComparisonCondition::FGComparisonCondition (Type type, bool reverse)
1444 FGComparisonCondition::~FGComparisonCondition ()
1446 delete _right_value;
1450 FGComparisonCondition::test () const
1452 // Always fail if incompletely specified
1453 if (_left_property == 0 ||
1454 (_right_property == 0 && _right_value == 0))
1457 // Get LESS_THAN, EQUALS, or GREATER_THAN
1459 doComparison(_left_property,
1460 (_right_property != 0 ? _right_property : _right_value));
1462 return (cmp == _type);
1464 return (cmp != _type);
1468 FGComparisonCondition::setLeftProperty (const string &propname)
1470 _left_property = fgGetNode(propname, true);
1474 FGComparisonCondition::setRightProperty (const string &propname)
1476 delete _right_value;
1478 _right_property = fgGetNode(propname, true);
1482 FGComparisonCondition::setRightValue (const SGPropertyNode *node)
1484 _right_property = 0;
1485 delete _right_value;
1486 _right_value = new SGPropertyNode(*node);
1491 ////////////////////////////////////////////////////////////////////////
1492 // Read a condition and use it if necessary.
1493 ////////////////////////////////////////////////////////////////////////
1495 // Forward declaration
1496 static FGCondition * readCondition (const SGPropertyNode * node);
1498 static FGCondition *
1499 readPropertyCondition (const SGPropertyNode * node)
1501 return new FGPropertyCondition(node->getStringValue());
1504 static FGCondition *
1505 readNotCondition (const SGPropertyNode * node)
1507 int nChildren = node->nChildren();
1508 for (int i = 0; i < nChildren; i++) {
1509 const SGPropertyNode * child = node->getChild(i);
1510 FGCondition * condition = readCondition(child);
1512 return new FGNotCondition(condition);
1514 SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition");
1518 static FGCondition *
1519 readAndConditions (const SGPropertyNode * node)
1521 FGAndCondition * andCondition = new FGAndCondition;
1522 int nChildren = node->nChildren();
1523 for (int i = 0; i < nChildren; i++) {
1524 const SGPropertyNode * child = node->getChild(i);
1525 FGCondition * condition = readCondition(child);
1527 andCondition->addCondition(condition);
1529 return andCondition;
1532 static FGCondition *
1533 readOrConditions (const SGPropertyNode * node)
1535 FGOrCondition * orCondition = new FGOrCondition;
1536 int nChildren = node->nChildren();
1537 for (int i = 0; i < nChildren; i++) {
1538 const SGPropertyNode * child = node->getChild(i);
1539 FGCondition * condition = readCondition(child);
1541 orCondition->addCondition(condition);
1546 static FGCondition *
1547 readComparison (const SGPropertyNode * node,
1548 FGComparisonCondition::Type type,
1551 FGComparisonCondition * condition = new FGComparisonCondition(type, reverse);
1552 condition->setLeftProperty(node->getStringValue("property[0]"));
1553 if (node->hasValue("property[1]"))
1554 condition->setRightProperty(node->getStringValue("property[1]"));
1556 condition->setRightValue(node->getChild("value", 0));
1561 static FGCondition *
1562 readCondition (const SGPropertyNode * node)
1564 const string &name = node->getName();
1565 if (name == "property")
1566 return readPropertyCondition(node);
1567 else if (name == "not")
1568 return readNotCondition(node);
1569 else if (name == "and")
1570 return readAndConditions(node);
1571 else if (name == "or")
1572 return readOrConditions(node);
1573 else if (name == "less-than")
1574 return readComparison(node, FGComparisonCondition::LESS_THAN, false);
1575 else if (name == "less-than-equals")
1576 return readComparison(node, FGComparisonCondition::GREATER_THAN, true);
1577 else if (name == "greater-than")
1578 return readComparison(node, FGComparisonCondition::GREATER_THAN, false);
1579 else if (name == "greater-than-equals")
1580 return readComparison(node, FGComparisonCondition::LESS_THAN, true);
1581 else if (name == "equals")
1582 return readComparison(node, FGComparisonCondition::EQUALS, false);
1583 else if (name == "not-equals")
1584 return readComparison(node, FGComparisonCondition::EQUALS, true);
1591 ////////////////////////////////////////////////////////////////////////
1592 // Implementation of FGConditional.
1593 ////////////////////////////////////////////////////////////////////////
1595 FGConditional::FGConditional ()
1600 FGConditional::~FGConditional ()
1606 FGConditional::setCondition (FGCondition * condition)
1609 _condition = condition;
1613 FGConditional::test () const
1615 return ((_condition == 0) || _condition->test());
1620 // The top-level is always an implicit 'and' group
1622 fgReadCondition (const SGPropertyNode * node)
1624 return readAndConditions(node);
1628 // end of fg_props.cxx