X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FMain%2Ffg_props.cxx;h=6a54db66515efc2e9ba5185b9fdd5df2a3db79c7;hb=446b200edc9590ec1e0231e64084905f2bc8a5b9;hp=30c337e9a4f77a4f50b36e1c9a2373a9d3434bb9;hpb=e1dd52d38aa91e17060e642c6d090556bc2d4d46;p=flightgear.git diff --git a/src/Main/fg_props.cxx b/src/Main/fg_props.cxx index 30c337e9a..6a54db665 100644 --- a/src/Main/fg_props.cxx +++ b/src/Main/fg_props.cxx @@ -1,8 +1,8 @@ -// fg_props.cxx -- support for +// fg_props.cxx -- support for FlightGear properties. // -// Written by David Megginson, started November 1999. +// Written by David Megginson, started 2000. // -// Copyright (C) 1999, 2000 David Megginson - david@megginson.com +// Copyright (C) 2000, 2001 David Megginson - david@megginson.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -16,26 +16,618 @@ // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -#include
+#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "globals.hxx" #include "fg_props.hxx" -using std::istream; -using std::ostream; + +static bool winding_ccw = true; // FIXME: temporary + +static bool fdm_data_logging = false; // FIXME: temporary + +static bool frozen = false; // FIXME: temporary + +using std::string; + +//////////////////////////////////////////////////////////////////////// +// Default property bindings (not yet handled by any module). +//////////////////////////////////////////////////////////////////////// + +struct LogClassMapping { + sgDebugClass c; + string name; + LogClassMapping(sgDebugClass cc, string nname) { c = cc; name = nname; } +}; + +LogClassMapping log_class_mappings [] = { + LogClassMapping(SG_NONE, "none"), + LogClassMapping(SG_TERRAIN, "terrain"), + LogClassMapping(SG_ASTRO, "astro"), + LogClassMapping(SG_FLIGHT, "flight"), + LogClassMapping(SG_INPUT, "input"), + LogClassMapping(SG_GL, "gl"), + LogClassMapping(SG_VIEW, "view"), + LogClassMapping(SG_COCKPIT, "cockpit"), + LogClassMapping(SG_GENERAL, "general"), + LogClassMapping(SG_MATH, "math"), + LogClassMapping(SG_EVENT, "event"), + LogClassMapping(SG_AIRCRAFT, "aircraft"), + LogClassMapping(SG_AUTOPILOT, "autopilot"), + LogClassMapping(SG_IO, "io"), + LogClassMapping(SG_CLIPPER, "clipper"), + LogClassMapping(SG_NETWORK, "network"), + LogClassMapping(SG_INSTR, "instrumentation"), + LogClassMapping(SG_SYSTEMS, "systems"), + LogClassMapping(SG_UNDEFD, "") +}; + + +/** + * Get the logging classes. + */ +static const char * +getLoggingClasses () +{ + sgDebugClass classes = logbuf::get_log_classes(); + static string result; + result = ""; + for (int i = 0; log_class_mappings[i].c != SG_UNDEFD; i++) { + if ((classes&log_class_mappings[i].c) > 0) { + if (!result.empty()) + result += '|'; + result += log_class_mappings[i].name; + } + } + return result.c_str(); +} + + +static void +addLoggingClass (const string &name) +{ + sgDebugClass classes = logbuf::get_log_classes(); + for (int i = 0; log_class_mappings[i].c != SG_UNDEFD; i++) { + if (name == log_class_mappings[i].name) { + logbuf::set_log_classes(sgDebugClass(classes|log_class_mappings[i].c)); + return; + } + } + SG_LOG(SG_GENERAL, SG_WARN, "Unknown logging class: " << name); +} + + +/** + * Set the logging classes. + */ +static void +setLoggingClasses (const char * c) +{ + string classes = c; + logbuf::set_log_classes(SG_NONE); + + if (classes == "none") { + SG_LOG(SG_GENERAL, SG_INFO, "Disabled all logging classes"); + return; + } + + if (classes.empty() || classes == "all") { // default + logbuf::set_log_classes(SG_ALL); + SG_LOG(SG_GENERAL, SG_INFO, "Enabled all logging classes: " + << getLoggingClasses()); + return; + } + + string rest = classes; + string name = ""; + int sep = rest.find('|'); + while (sep > 0) { + name = rest.substr(0, sep); + rest = rest.substr(sep+1); + addLoggingClass(name); + sep = rest.find('|'); + } + addLoggingClass(rest); + SG_LOG(SG_GENERAL, SG_INFO, "Set logging classes to " + << getLoggingClasses()); +} + + +/** + * Get the logging priority. + */ +static const char * +getLoggingPriority () +{ + switch (logbuf::get_log_priority()) { + case SG_BULK: + return "bulk"; + case SG_DEBUG: + return "debug"; + case SG_INFO: + return "info"; + case SG_WARN: + return "warn"; + case SG_ALERT: + return "alert"; + default: + SG_LOG(SG_GENERAL, SG_WARN, "Internal: Unknown logging priority number: " + << logbuf::get_log_priority()); + return "unknown"; + } +} + + +/** + * Set the logging priority. + */ +static void +setLoggingPriority (const char * p) +{ + if (p == 0) + return; + string priority = p; + if (priority == "bulk") { + logbuf::set_log_priority(SG_BULK); + } else if (priority == "debug") { + logbuf::set_log_priority(SG_DEBUG); + } else if (priority.empty() || priority == "info") { // default + logbuf::set_log_priority(SG_INFO); + } else if (priority == "warn") { + logbuf::set_log_priority(SG_WARN); + } else if (priority == "alert") { + logbuf::set_log_priority(SG_ALERT); + } else { + SG_LOG(SG_GENERAL, SG_WARN, "Unknown logging priority " << priority); + } + SG_LOG(SG_GENERAL, SG_DEBUG, "Logging priority is " << getLoggingPriority()); +} + + +/** + * Return the current frozen state. + */ +static bool +getFreeze () +{ + return frozen; +} + + +/** + * Set the current frozen state. + */ +static void +setFreeze (bool f) +{ + frozen = f; + + // Stop sound on a pause + SGSoundMgr *smgr = (SGSoundMgr *)globals->get_subsystem("soundmgr"); + if ( smgr != NULL ) { + if ( f ) { + smgr->suspend(); + } else if (!fgGetBool("/sim/sound/pause")) { + smgr->resume(); + } + } +} + + +/** + * Return the number of milliseconds elapsed since simulation started. + */ +static double +getElapsedTime_sec () +{ + return globals->get_sim_time_sec(); +} + + +/** + * Return the current Zulu time. + */ +static const char * +getDateString () +{ + static char buf[64]; // FIXME + struct tm * t = globals->get_time_params()->getGmt(); + sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d", + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); + return buf; +} + + +/** + * Set the current Zulu time. + */ +static void +setDateString (const char * date_string) +{ + static const SGPropertyNode *cur_time_override + = fgGetNode("/sim/time/cur-time-override", true); + + SGTime * st = globals->get_time_params(); + struct tm * current_time = st->getGmt(); + struct tm new_time; + + // Scan for basic ISO format + // YYYY-MM-DDTHH:MM:SS + int ret = sscanf(date_string, "%d-%d-%dT%d:%d:%d", + &(new_time.tm_year), &(new_time.tm_mon), + &(new_time.tm_mday), &(new_time.tm_hour), + &(new_time.tm_min), &(new_time.tm_sec)); + + // Be pretty picky about this, so + // that strange things don't happen + // if the save file has been edited + // by hand. + if (ret != 6) { + SG_LOG(SG_INPUT, SG_WARN, "Date/time string " << date_string + << " not in YYYY-MM-DDTHH:MM:SS format; skipped"); + return; + } + + // OK, it looks like we got six + // values, one way or another. + new_time.tm_year -= 1900; + new_time.tm_mon -= 1; + + // Now, tell flight gear to use + // the new time. This was far + // too difficult, by the way. + long int warp = + mktime(&new_time) - mktime(current_time) + globals->get_warp(); + double lon = current_aircraft.fdm_state->get_Longitude(); + double lat = current_aircraft.fdm_state->get_Latitude(); + globals->set_warp(warp); + st->update(lon, lat, cur_time_override->getLongValue(), warp); +} + +/** + * Return the GMT as a string. + */ +static const char * +getGMTString () +{ + static char buf[16]; + struct tm *t = globals->get_time_params()->getGmt(); + snprintf(buf, 16, "%.2d:%.2d:%.2d", + t->tm_hour, t->tm_min, t->tm_sec); + return buf; +} + +/** + * Return the magnetic variation + */ +static double +getMagVar () +{ + return globals->get_mag()->get_magvar() * SGD_RADIANS_TO_DEGREES; +} + + +/** + * Return the magnetic dip + */ +static double +getMagDip () +{ + return globals->get_mag()->get_magdip() * SGD_RADIANS_TO_DEGREES; +} + + +/** + * Return the current heading in degrees. + */ +static double +getHeadingMag () +{ + double magheading; + magheading = current_aircraft.fdm_state->get_Psi() * SGD_RADIANS_TO_DEGREES - getMagVar(); + if (magheading < 0) magheading += 360; + return magheading; +} + +static long +getWarp () +{ + return globals->get_warp(); +} + +static void +setWarp (long warp) +{ + globals->set_warp(warp); +} + +static long +getWarpDelta () +{ + return globals->get_warp_delta(); +} + +static void +setWarpDelta (long delta) +{ + globals->set_warp_delta(delta); +} + +static bool +getWindingCCW () +{ + return winding_ccw; +} + +static void +setWindingCCW (bool state) +{ + winding_ccw = state; + if ( winding_ccw ) + glFrontFace ( GL_CCW ); + else + glFrontFace ( GL_CW ); +} + +static bool +getFDMDataLogging () +{ + return fdm_data_logging; +} + +static void +setFDMDataLogging (bool state) +{ + // kludge; no getter or setter available + if (state != fdm_data_logging) { + fgToggleFDMdataLogging(); + fdm_data_logging = state; + } +} + +static const char * +getLongitudeString () +{ + static SGConstPropertyNode_ptr n = fgGetNode("/position/longitude-deg", true); + static SGConstPropertyNode_ptr f = fgGetNode("/sim/lon-lat-format", true); + static char buf[32]; + double d = n->getDoubleValue(); + int format = f->getIntValue(); + char c = d < 0.0 ? 'W' : 'E'; + + if (format == 0) { + snprintf(buf, 32, "%3.6f%c", d, c); + + } else if (format == 1) { + // dd mm.mmm' (DMM-Format) -- uses a round-off factor tailored to the + // required precision of the minutes field (three decimal places), + // preventing minute values of 60. + double deg = fabs(d) + 5.0E-4 / 60.0; + double min = fabs(deg - int(deg)) * 60.0 - 4.999E-4; + snprintf(buf, 32, "%d*%06.3f%c", int(d < 0.0 ? -deg : deg), min, c); + + } else { + // mm'ss.s'' (DMS-Format) -- uses a round-off factor tailored to the + // required precision of the seconds field (one decimal place), + // preventing second values of 60. + double deg = fabs(d) + 0.05 / 3600.0; + double min = (deg - int(deg)) * 60.0; + double sec = (min - int(min)) * 60.0 - 0.049; + snprintf(buf, 32, "%d*%02d %04.1f%c", int(d < 0.0 ? -deg : deg), + int(min), fabs(sec), c); + } + buf[31] = '\0'; + return buf; +} + +static const char * +getLatitudeString () +{ + static SGConstPropertyNode_ptr n = fgGetNode("/position/latitude-deg", true); + static SGConstPropertyNode_ptr f = fgGetNode("/sim/lon-lat-format", true); + static char buf[32]; + double d = n->getDoubleValue(); + int format = f->getIntValue(); + char c = d < 0.0 ? 'S' : 'N'; + + if (format == 0) { + snprintf(buf, 32, "%3.6f%c", d, c); + + } else if (format == 1) { + double deg = fabs(d) + 5.0E-4 / 60.0; + double min = fabs(deg - int(deg)) * 60.0 - 4.999E-4; + snprintf(buf, 32, "%d*%06.3f%c", int(d < 0.0 ? -deg : deg), min, c); + + } else { + double deg = fabs(d) + 0.05 / 3600.0; + double min = (deg - int(deg)) * 60.0; + double sec = (min - int(min)) * 60.0 - 0.049; + snprintf(buf, 32, "%d*%02d %04.1f%c", int(d < 0.0 ? -deg : deg), + int(min), fabs(sec), c); + } + buf[31] = '\0'; + return buf; +} + + + + +//////////////////////////////////////////////////////////////////////// +// Tie the properties. +//////////////////////////////////////////////////////////////////////// + +FGProperties::FGProperties () +{ +} + +FGProperties::~FGProperties () +{ +} + +void +FGProperties::init () +{ +} + +void +FGProperties::bind () +{ + // Simulation + fgTie("/sim/logging/priority", getLoggingPriority, setLoggingPriority); + fgTie("/sim/logging/classes", getLoggingClasses, setLoggingClasses); + fgTie("/sim/freeze/master", getFreeze, setFreeze); + + fgTie("/sim/time/elapsed-sec", getElapsedTime_sec); + fgTie("/sim/time/gmt", getDateString, setDateString); + fgSetArchivable("/sim/time/gmt"); + fgTie("/sim/time/gmt-string", getGMTString); + + // Position + fgTie("/position/latitude-string", getLatitudeString); + fgTie("/position/longitude-string", getLongitudeString); + + // Orientation + fgTie("/orientation/heading-magnetic-deg", getHeadingMag); + + fgTie("/environment/magnetic-variation-deg", getMagVar); + fgTie("/environment/magnetic-dip-deg", getMagDip); + + fgTie("/sim/time/warp", getWarp, setWarp, false); + fgTie("/sim/time/warp-delta", getWarpDelta, setWarpDelta); + + // Misc. Temporary junk. + fgTie("/sim/temp/winding-ccw", getWindingCCW, setWindingCCW, false); + fgTie("/sim/temp/fdm-data-logging", getFDMDataLogging, setFDMDataLogging); +} + +void +FGProperties::unbind () +{ + // Simulation + fgUntie("/sim/logging/priority"); + fgUntie("/sim/logging/classes"); + fgUntie("/sim/freeze/master"); + + fgUntie("/sim/time/elapsed-sec"); + fgUntie("/sim/time/gmt"); + fgUntie("/sim/time/gmt-string"); + // Position + fgUntie("/position/latitude-string"); + fgUntie("/position/longitude-string"); + + // Orientation + fgUntie("/orientation/heading-magnetic-deg"); + + // Environment + fgUntie("/environment/magnetic-variation-deg"); + fgUntie("/environment/magnetic-dip-deg"); + + fgUntie("/sim/time/warp"); + fgUntie("/sim/time/warp-delta"); + + // Misc. Temporary junk. + fgUntie("/sim/temp/winding-ccw"); + fgUntie("/sim/temp/full-screen"); + fgUntie("/sim/temp/fdm-data-logging"); +} + +void +FGProperties::update (double dt) +{ + static SGPropertyNode_ptr offset = fgGetNode("/sim/time/local-offset", true); + offset->setIntValue(globals->get_time_params()->get_local_offset()); + + + // utc date/time + static SGPropertyNode_ptr uyear = fgGetNode("/sim/time/utc/year", true); + static SGPropertyNode_ptr umonth = fgGetNode("/sim/time/utc/month", true); + static SGPropertyNode_ptr uday = fgGetNode("/sim/time/utc/day", true); + static SGPropertyNode_ptr uhour = fgGetNode("/sim/time/utc/hour", true); + static SGPropertyNode_ptr umin = fgGetNode("/sim/time/utc/minute", true); + static SGPropertyNode_ptr usec = fgGetNode("/sim/time/utc/second", true); + static SGPropertyNode_ptr uwday = fgGetNode("/sim/time/utc/weekday", true); + static SGPropertyNode_ptr udsec = fgGetNode("/sim/time/utc/day-seconds", true); + + struct tm *u = globals->get_time_params()->getGmt(); + uyear->setIntValue(u->tm_year + 1900); + umonth->setIntValue(u->tm_mon + 1); + uday->setIntValue(u->tm_mday); + uhour->setIntValue(u->tm_hour); + umin->setIntValue(u->tm_min); + usec->setIntValue(u->tm_sec); + uwday->setIntValue(u->tm_wday); + + udsec->setIntValue(u->tm_hour * 3600 + u->tm_min * 60 + u->tm_sec); + + + // real local date/time + static SGPropertyNode_ptr ryear = fgGetNode("/sim/time/real/year", true); + static SGPropertyNode_ptr rmonth = fgGetNode("/sim/time/real/month", true); + static SGPropertyNode_ptr rday = fgGetNode("/sim/time/real/day", true); + static SGPropertyNode_ptr rhour = fgGetNode("/sim/time/real/hour", true); + static SGPropertyNode_ptr rmin = fgGetNode("/sim/time/real/minute", true); + static SGPropertyNode_ptr rsec = fgGetNode("/sim/time/real/second", true); + static SGPropertyNode_ptr rwday = fgGetNode("/sim/time/real/weekday", true); + + time_t real = time(0); + struct tm *r = localtime(&real); + ryear->setIntValue(r->tm_year + 1900); + rmonth->setIntValue(r->tm_mon + 1); + rday->setIntValue(r->tm_mday); + rhour->setIntValue(r->tm_hour); + rmin->setIntValue(r->tm_min); + rsec->setIntValue(r->tm_sec); + rwday->setIntValue(r->tm_wday); +} + + + +//////////////////////////////////////////////////////////////////////// +// Save and restore. +//////////////////////////////////////////////////////////////////////// /** * Save the current state of the simulator to a stream. */ bool -fgSaveFlight (ostream &output) +fgSaveFlight (std::ostream &output, bool write_all) { - return writeProperties(output, globals->get_props()); + + fgSetBool("/sim/presets/onground", false); + fgSetArchivable("/sim/presets/onground"); + fgSetBool("/sim/presets/trim", false); + fgSetArchivable("/sim/presets/trim"); + fgSetString("/sim/presets/speed-set", "UVW"); + fgSetArchivable("/sim/presets/speed-set"); + + try { + writeProperties(output, globals->get_props(), write_all); + } catch (const sg_exception &e) { + guiErrorMessage("Error saving flight: ", e); + return false; + } + return true; } @@ -43,19 +635,200 @@ fgSaveFlight (ostream &output) * Restore the current state of the simulator from a stream. */ bool -fgLoadFlight (istream &input) +fgLoadFlight (std::istream &input) { SGPropertyNode props; - if (readProperties(input, &props)) { - copyProperties(&props, globals->get_props()); - // When loading a flight, make it the - // new initial state. - globals->saveInitialState(); - } else { - FG_LOG(FG_INPUT, FG_ALERT, "Error restoring flight; aborted"); + try { + readProperties(input, &props); + } catch (const sg_exception &e) { + guiErrorMessage("Error reading saved flight: ", e); return false; } + + fgSetBool("/sim/presets/onground", false); + fgSetBool("/sim/presets/trim", false); + fgSetString("/sim/presets/speed-set", "UVW"); + + copyProperties(&props, globals->get_props()); + // When loading a flight, make it the + // new initial state. + globals->saveInitialState(); + return true; } -// end of fg_props.cxx +bool +fgLoadProps (const char * path, SGPropertyNode * props, bool in_fg_root, int default_mode) +{ + string fullpath; + if (in_fg_root) { + SGPath loadpath(globals->get_fg_root()); + loadpath.append(path); + fullpath = loadpath.str(); + } else { + fullpath = path; + } + + try { + readProperties(fullpath, props, default_mode); + } catch (const sg_exception &e) { + guiErrorMessage("Error reading properties: ", e); + return false; + } + return true; +} + + + +//////////////////////////////////////////////////////////////////////// +// Property convenience functions. +//////////////////////////////////////////////////////////////////////// + +SGPropertyNode * +fgGetNode (const char * path, bool create) +{ + return globals->get_props()->getNode(path, create); +} + +SGPropertyNode * +fgGetNode (const char * path, int index, bool create) +{ + return globals->get_props()->getNode(path, index, create); +} + +bool +fgHasNode (const char * path) +{ + return (fgGetNode(path, false) != 0); +} + +void +fgAddChangeListener (SGPropertyChangeListener * listener, const char * path) +{ + fgGetNode(path, true)->addChangeListener(listener); +} + +void +fgAddChangeListener (SGPropertyChangeListener * listener, + const char * path, int index) +{ + fgGetNode(path, index, true)->addChangeListener(listener); +} + +bool +fgGetBool (const char * name, bool defaultValue) +{ + return globals->get_props()->getBoolValue(name, defaultValue); +} + +int +fgGetInt (const char * name, int defaultValue) +{ + return globals->get_props()->getIntValue(name, defaultValue); +} + +int +fgGetLong (const char * name, long defaultValue) +{ + return globals->get_props()->getLongValue(name, defaultValue); +} + +float +fgGetFloat (const char * name, float defaultValue) +{ + return globals->get_props()->getFloatValue(name, defaultValue); +} + +double +fgGetDouble (const char * name, double defaultValue) +{ + return globals->get_props()->getDoubleValue(name, defaultValue); +} + +const char * +fgGetString (const char * name, const char * defaultValue) +{ + return globals->get_props()->getStringValue(name, defaultValue); +} + +bool +fgSetBool (const char * name, bool val) +{ + return globals->get_props()->setBoolValue(name, val); +} + +bool +fgSetInt (const char * name, int val) +{ + return globals->get_props()->setIntValue(name, val); +} + +bool +fgSetLong (const char * name, long val) +{ + return globals->get_props()->setLongValue(name, val); +} + +bool +fgSetFloat (const char * name, float val) +{ + return globals->get_props()->setFloatValue(name, val); +} + +bool +fgSetDouble (const char * name, double val) +{ + return globals->get_props()->setDoubleValue(name, val); +} + +bool +fgSetString (const char * name, const char * val) +{ + return globals->get_props()->setStringValue(name, val); +} + +void +fgSetArchivable (const char * name, bool state) +{ + SGPropertyNode * node = globals->get_props()->getNode(name); + if (node == 0) + SG_LOG(SG_GENERAL, SG_DEBUG, + "Attempt to set archive flag for non-existant property " + << name); + else + node->setAttribute(SGPropertyNode::ARCHIVE, state); +} + +void +fgSetReadable (const char * name, bool state) +{ + SGPropertyNode * node = globals->get_props()->getNode(name); + if (node == 0) + SG_LOG(SG_GENERAL, SG_DEBUG, + "Attempt to set read flag for non-existant property " + << name); + else + node->setAttribute(SGPropertyNode::READ, state); +} + +void +fgSetWritable (const char * name, bool state) +{ + SGPropertyNode * node = globals->get_props()->getNode(name); + if (node == 0) + SG_LOG(SG_GENERAL, SG_DEBUG, + "Attempt to set write flag for non-existant property " + << name); + else + node->setAttribute(SGPropertyNode::WRITE, state); +} + +void +fgUntie (const char * name) +{ + if (!globals->get_props()->untie(name)) + SG_LOG(SG_GENERAL, SG_WARN, "Failed to untie property " << name); +} + + +// end of fg_props.cxx