diff --git a/src/AIModel/AIBase.cxx b/src/AIModel/AIBase.cxx index bbc1510bf..999659c64 100644 --- a/src/AIModel/AIBase.cxx +++ b/src/AIModel/AIBase.cxx @@ -43,6 +43,7 @@ #include
#include #include +#include #include #include "AIBase.hxx" diff --git a/src/GUI/FGPUIDialog.cxx b/src/GUI/FGPUIDialog.cxx index 33cbc5288..5620ae0fc 100644 --- a/src/GUI/FGPUIDialog.cxx +++ b/src/GUI/FGPUIDialog.cxx @@ -25,6 +25,8 @@ #include "FGFontCache.hxx" #include "FGColor.hxx" +using std::string; + enum format_type { f_INVALID, f_INT, f_LONG, f_FLOAT, f_DOUBLE, f_STRING }; static const int FORMAT_BUFSIZE = 255; static const int RESIZE_MARGIN = 7; @@ -204,7 +206,7 @@ struct GUIInfo FGPUIDialog *dialog; SGPropertyNode_ptr node; - vector bindings; + std::vector bindings; int key; string label, legend, text, format; format_type fmt_type; @@ -1153,7 +1155,7 @@ FGPUIDialog::setupObject (puObject *object, SGPropertyNode *props) } SGPropertyNode *dest = fgGetNode("/sim/bindings/gui", true); - vector bindings = props->getChildren("binding"); + std::vector bindings = props->getChildren("binding"); if (bindings.size() > 0) { info->key = props->getIntValue("keynum", -1); if (props->hasValue("key")) @@ -1485,7 +1487,7 @@ fgValueList::make_list() vname = _props->getStringValue("property-name"); } - vector value_nodes = values->getChildren(vname); + std::vector value_nodes = values->getChildren(vname); _list = new char *[value_nodes.size() + 1]; unsigned int i; for (i = 0; i < value_nodes.size(); i++) { diff --git a/src/Input/FGEventInput.cxx b/src/Input/FGEventInput.cxx index 071323414..495de3453 100644 --- a/src/Input/FGEventInput.cxx +++ b/src/Input/FGEventInput.cxx @@ -36,6 +36,7 @@ using simgear::PropertyList; using std::cout; using std::endl; using std::map; +using std::string; FGEventSetting::FGEventSetting( SGPropertyNode_ptr base ) : value(0.0) diff --git a/src/Input/FGJoystickInput.cxx b/src/Input/FGJoystickInput.cxx index c2d300964..b15649cda 100644 --- a/src/Input/FGJoystickInput.cxx +++ b/src/Input/FGJoystickInput.cxx @@ -133,11 +133,11 @@ void FGJoystickInput::init() if (configMap.hasConfiguration(name)) { named = configMap.configurationForDeviceName(name); - string source = named->getStringValue("source", "user defined"); + std::string source = named->getStringValue("source", "user defined"); SG_LOG(SG_INPUT, SG_INFO, "... found joystick: " << source); } else if ((named = configMap.configurationForDeviceName("default"))) { - string source = named->getStringValue("source", "user defined"); + std::string source = named->getStringValue("source", "user defined"); SG_LOG(SG_INPUT, SG_INFO, "No config found for joystick \"" << name << "\"\nUsing default: \"" << source << '"'); @@ -205,7 +205,7 @@ void FGJoystickInput::postinit() // std::ostringstream str; str << "__js" << i; - string module = str.str(); + std::string module = str.str(); nasalsys->createModule(module.c_str(), module.c_str(), "", 0); PropertyList nasal = js_node->getChildren("nasal"); diff --git a/src/Input/FGKeyboardInput.cxx b/src/Input/FGKeyboardInput.cxx index 3f5bdfcb2..fbbadd249 100644 --- a/src/Input/FGKeyboardInput.cxx +++ b/src/Input/FGKeyboardInput.cxx @@ -101,7 +101,7 @@ void FGKeyboardInput::init() void FGKeyboardInput::postinit() { SG_LOG(SG_INPUT, SG_DEBUG, "Initializing key bindings"); - string module = "__kbd"; + std::string module = "__kbd"; SGPropertyNode * key_nodes = fgGetNode("/input/keyboard"); if (key_nodes == NULL) { SG_LOG(SG_INPUT, SG_WARN, "No key bindings (/input/keyboard)!!"); diff --git a/src/Scenery/tilemgr.cxx b/src/Scenery/tilemgr.cxx index 22efc3da3..298b05c50 100644 --- a/src/Scenery/tilemgr.cxx +++ b/src/Scenery/tilemgr.cxx @@ -43,6 +43,7 @@ #include #include #include +#include #include "scenery.hxx" #include "SceneryPager.hxx" diff --git a/src/Scripting/CMakeLists.txt b/src/Scripting/CMakeLists.txt index de71090b1..586d4a4a7 100644 --- a/src/Scripting/CMakeLists.txt +++ b/src/Scripting/CMakeLists.txt @@ -8,15 +8,18 @@ set(SOURCES NasalClipboard.cxx NasalCondition.cxx NasalString.cxx + NasalModelData.cxx ) set(HEADERS NasalSys.hxx + NasalSys_private.hxx NasalPositioned.hxx NasalCanvas.hxx NasalClipboard.hxx NasalCondition.hxx NasalString.hxx + NasalModelData.hxx ) if(WIN32) diff --git a/src/Scripting/NasalModelData.cxx b/src/Scripting/NasalModelData.cxx new file mode 100644 index 000000000..82fd3b69c --- /dev/null +++ b/src/Scripting/NasalModelData.cxx @@ -0,0 +1,94 @@ + +#include "NasalModelData.hxx" + +#include + +#include "NasalSys.hxx" +#include
+ + +// FGNasalModelData class. If sgLoad3DModel() is called with a pointer to +// such a class, then it lets modelLoaded() run the script, and the +// destructor the script. The latter happens when the model branch +// is removed from the scene graph. + +unsigned int FGNasalModelData::_module_id = 0; + +void FGNasalModelData::load() +{ + std::stringstream m; + m << "__model" << _module_id++; + _module = m.str(); + + SG_LOG(SG_NASAL, SG_DEBUG, "Loading nasal module " << _module.c_str()); + + const char *s = _load ? _load->getStringValue() : ""; + FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal"); + + naRef arg[2]; + arg[0] = nasalSys->propNodeGhost(_root); + arg[1] = nasalSys->propNodeGhost(_prop); + nasalSys->createModule(_module.c_str(), _path.c_str(), s, strlen(s), + _root, 2, arg); +} + +void FGNasalModelData::unload() +{ + if (_module.empty()) + return; + + FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal"); + if(!nasalSys) { + SG_LOG(SG_NASAL, SG_WARN, "Trying to run an script " + "without Nasal subsystem present."); + return; + } + + SG_LOG(SG_NASAL, SG_DEBUG, "Unloading nasal module " << _module.c_str()); + + if (_unload) + { + const char *s = _unload->getStringValue(); + nasalSys->createModule(_module.c_str(), _module.c_str(), s, strlen(s), _root); + } + + nasalSys->deleteModule(_module.c_str()); +} + +void FGNasalModelDataProxy::modelLoaded(const std::string& path, SGPropertyNode *prop, + osg::Node *) +{ + FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal"); + if(!nasalSys) { + SG_LOG(SG_NASAL, SG_WARN, "Trying to run a script " + "without Nasal subsystem present."); + return; + } + + if(!prop) + return; + + SGPropertyNode *nasal = prop->getNode("nasal"); + if(!nasal) + return; + + SGPropertyNode* load = nasal->getNode("load"); + SGPropertyNode* unload = nasal->getNode("unload"); + + if ((!load) && (!unload)) + return; + + _data = new FGNasalModelData(_root, path, prop, load, unload); + + // register Nasal module to be created and loaded in the main thread. + nasalSys->registerToLoad(_data); +} + +FGNasalModelDataProxy::~FGNasalModelDataProxy() +{ + FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal"); + // when necessary, register Nasal module to be destroyed/unloaded + // in the main thread. + if ((_data.valid())&&(nasalSys)) + nasalSys->registerToUnload(_data); +} diff --git a/src/Scripting/NasalModelData.hxx b/src/Scripting/NasalModelData.hxx new file mode 100644 index 000000000..ea472451b --- /dev/null +++ b/src/Scripting/NasalModelData.hxx @@ -0,0 +1,74 @@ +// Copyright (C) 2013 James Turner +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifndef NASAL_MODEL_DATA_HXX +#define NASAL_MODEL_DATA_HXX + +#include +#include + +using std::string; + +/** Nasal model data container. + * load and unload methods must be run in main thread (not thread-safe). */ +class FGNasalModelData : public SGReferenced +{ +public: + /** Constructor to be run in an arbitrary thread. */ + FGNasalModelData(SGPropertyNode *root, const string& path, SGPropertyNode *prop, + SGPropertyNode* load, SGPropertyNode* unload) : + _path(path), + _root(root), _prop(prop), + _load(load), _unload(unload) + { + } + + /** Load hook. Always call from inside the main loop. */ + void load(); + + /** Unload hook. Always call from inside the main loop. */ + void unload(); + +private: + static unsigned int _module_id; + + string _module, _path; + SGPropertyNode_ptr _root, _prop; + SGConstPropertyNode_ptr _load, _unload; +}; + +/** Thread-safe proxy for FGNasalModelData. + * modelLoaded/destroy methods only register the requested + * operation. Actual (un)loading of Nasal module is deferred + * and done in the main loop. */ +class FGNasalModelDataProxy : public simgear::SGModelData +{ +public: + FGNasalModelDataProxy(SGPropertyNode *root = 0) : + _root(root), _data(0) + { + } + + ~FGNasalModelDataProxy(); + + void modelLoaded(const string& path, SGPropertyNode *prop, osg::Node *); + +protected: + SGPropertyNode_ptr _root; + SGSharedPtr _data; +}; + +#endif // of NASAL_MODEL_DATA_HXX diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx index 537adf1f5..cc99763f5 100644 --- a/src/Scripting/NasalSys.cxx +++ b/src/Scripting/NasalSys.cxx @@ -30,6 +30,8 @@ #include #include "NasalSys.hxx" +#include "NasalSys_private.hxx" +#include "NasalModelData.hxx" #include "NasalPositioned.hxx" #include "NasalCanvas.hxx" #include "NasalClipboard.hxx" @@ -178,6 +180,7 @@ bool FGNasalSys::parseAndRun(const char* sourceCode) return true; } +#if 0 FGNasalScript* FGNasalSys::parseScript(const char* src, const char* name) { FGNasalScript* script = new FGNasalScript(); @@ -199,6 +202,7 @@ FGNasalScript* FGNasalSys::parseScript(const char* src, const char* name) script->_gcKey = gcSave(script->_code); return script; } +#endif // The get/setprop functions accept a *list* of strings and walk // through the property tree with them to find the appropriate node. @@ -339,7 +343,11 @@ static naRef f_logprint(naContext c, naRef me, int argc, naRef* args) if(naIsNil(s)) continue; buf += naStr_data(s); } - SG_LOG(SG_NASAL, (sgDebugPriority)(int) priority.num, buf); +// use the nasal source file and line for the message location, since +// that's more useful than the location here! + sglog().log(SG_NASAL, (sgDebugPriority)(int) priority.num, + naStr_data(naGetSourceFile(c, 0)), + naGetLine(c, 0), buf); return naNum(buf.length()); } @@ -475,6 +483,60 @@ static naRef f_resolveDataPath(naContext c, naRef me, int argc, naRef* args) return naStr_fromdata(naNewString(c), const_cast(pdata), strlen(pdata)); } +class NasalCommand : public SGCommandMgr::Command +{ +public: + NasalCommand(FGNasalSys* sys, naRef f) : + _sys(sys), + _func(f) + { + _gcRoot = sys->gcSave(f); + } + + virtual ~NasalCommand() + { + _sys->gcRelease(_gcRoot); + } + + virtual bool operator()(const SGPropertyNode* aNode) + { + _sys->setCmdArg(const_cast(aNode)); + naRef args[1]; + args[0] = _sys->cmdArgGhost(); + + _sys->callMethod(_func, naNil(), 1, args, naNil() /* locals */); + + return true; + } + +private: + FGNasalSys* _sys; + naRef _func; + int _gcRoot; +}; + +static naRef f_addCommand(naContext c, naRef me, int argc, naRef* args) +{ + if(argc != 2 || !naIsString(args[0]) || !naIsFunc(args[1])) + naRuntimeError(c, "bad arguments to addcommand()"); + + naRef func = args[1]; + NasalCommand* cmd = new NasalCommand(nasalSys, func); + globals->get_commands()->addCommandObject(naStr_data(args[0]), cmd); + return naNil(); +} + +static naRef f_removeCommand(naContext c, naRef me, int argc, naRef* args) +{ + SGCommandMgr::Command* cmd = globals->get_commands()->getCommand(naStr_data(args[0])); + + // SGCommandMgr::Command* cmd = globals->get_commands()->removeCommand(naStr_data(args[0])) + + delete cmd; + + return naNil(); +} + // Parse XML file. // parsexml( [, [, [, [, ]]]]); // @@ -539,6 +601,8 @@ static struct { const char* name; naCFunction func; } funcs[] = { { "settimer", f_settimer }, { "_setlistener", f_setlistener }, { "removelistener", f_removelistener }, + { "addcommand", f_addCommand }, + { "removecommand", f_removeCommand }, { "_cmdarg", f_cmdarg }, { "_interpolate", f_interpolate }, { "rand", f_rand }, @@ -556,6 +620,11 @@ naRef FGNasalSys::cmdArgGhost() return propNodeGhost(_cmdArg); } +void FGNasalSys::setCmdArg(SGPropertyNode* aNode) +{ + _cmdArg = aNode; +} + void FGNasalSys::init() { int i; @@ -1034,6 +1103,15 @@ naRef FGNasalSys::removeListener(naContext c, int argc, naRef* args) return naNum(_listener.size()); } +void FGNasalSys::registerToLoad(FGNasalModelData *data) +{ + _loadList.push(data); +} + +void FGNasalSys::registerToUnload(FGNasalModelData *data) +{ + _unloadList.push(data); +} // FGNasalListener class. @@ -1132,90 +1210,6 @@ bool FGNasalListener::changed(SGPropertyNode* node) } } - - -// FGNasalModelData class. If sgLoad3DModel() is called with a pointer to -// such a class, then it lets modelLoaded() run the script, and the -// destructor the script. The latter happens when the model branch -// is removed from the scene graph. - -unsigned int FGNasalModelData::_module_id = 0; - -void FGNasalModelData::load() -{ - std::stringstream m; - m << "__model" << _module_id++; - _module = m.str(); - - SG_LOG(SG_NASAL, SG_DEBUG, "Loading nasal module " << _module.c_str()); - - const char *s = _load ? _load->getStringValue() : ""; - - naRef arg[2]; - arg[0] = nasalSys->propNodeGhost(_root); - arg[1] = nasalSys->propNodeGhost(_prop); - nasalSys->createModule(_module.c_str(), _path.c_str(), s, strlen(s), - _root, 2, arg); -} - -void FGNasalModelData::unload() -{ - if (_module.empty()) - return; - - if(!nasalSys) { - SG_LOG(SG_NASAL, SG_WARN, "Trying to run an script " - "without Nasal subsystem present."); - return; - } - - SG_LOG(SG_NASAL, SG_DEBUG, "Unloading nasal module " << _module.c_str()); - - if (_unload) - { - const char *s = _unload->getStringValue(); - nasalSys->createModule(_module.c_str(), _module.c_str(), s, strlen(s), _root); - } - - nasalSys->deleteModule(_module.c_str()); -} - -void FGNasalModelDataProxy::modelLoaded(const string& path, SGPropertyNode *prop, - osg::Node *) -{ - if(!nasalSys) { - SG_LOG(SG_NASAL, SG_WARN, "Trying to run a script " - "without Nasal subsystem present."); - return; - } - - if(!prop) - return; - - SGPropertyNode *nasal = prop->getNode("nasal"); - if(!nasal) - return; - - SGPropertyNode* load = nasal->getNode("load"); - SGPropertyNode* unload = nasal->getNode("unload"); - - if ((!load) && (!unload)) - return; - - _data = new FGNasalModelData(_root, path, prop, load, unload); - - // register Nasal module to be created and loaded in the main thread. - nasalSys->registerToLoad(_data); -} - -FGNasalModelDataProxy::~FGNasalModelDataProxy() -{ - // when necessary, register Nasal module to be destroyed/unloaded - // in the main thread. - if ((_data.valid())&&(nasalSys)) - nasalSys->registerToUnload(_data); -} - // NasalXMLVisitor class: handles EasyXML visitor callback for parsexml() // NasalXMLVisitor::NasalXMLVisitor(naContext c, int argc, naRef* args) : diff --git a/src/Scripting/NasalSys.hxx b/src/Scripting/NasalSys.hxx index 7fa3fb7ae..a5adff44e 100644 --- a/src/Scripting/NasalSys.hxx +++ b/src/Scripting/NasalSys.hxx @@ -5,9 +5,8 @@ #include #include #include -#include -#include #include +#include #include @@ -15,58 +14,10 @@ class FGNasalScript; class FGNasalListener; class SGCondition; +class FGNasalModelData; namespace simgear { class BufferedLogCallback; } -/** Nasal model data container. - * load and unload methods must be run in main thread (not thread-safe). */ -class FGNasalModelData : public SGReferenced -{ -public: - /** Constructor to be run in an arbitrary thread. */ - FGNasalModelData(SGPropertyNode *root, const string& path, SGPropertyNode *prop, - SGPropertyNode* load, SGPropertyNode* unload) : - _path(path), - _root(root), _prop(prop), - _load(load), _unload(unload) - { - } - - /** Load hook. Always call from inside the main loop. */ - void load(); - - /** Unload hook. Always call from inside the main loop. */ - void unload(); - -private: - static unsigned int _module_id; - - string _module, _path; - SGPropertyNode_ptr _root, _prop; - SGConstPropertyNode_ptr _load, _unload; -}; - -/** Thread-safe proxy for FGNasalModelData. - * modelLoaded/destroy methods only register the requested - * operation. Actual (un)loading of Nasal module is deferred - * and done in the main loop. */ -class FGNasalModelDataProxy : public simgear::SGModelData -{ -public: - FGNasalModelDataProxy(SGPropertyNode *root = 0) : - _root(root), _data(0) - { - } - - ~FGNasalModelDataProxy(); - - void modelLoaded(const string& path, SGPropertyNode *prop, osg::Node *); - -protected: - SGPropertyNode_ptr _root; - SGSharedPtr _data; -}; - SGPropertyNode* ghostToPropNode(naRef ref); SGCondition* conditionGhost(naRef r); @@ -94,7 +45,7 @@ public: // this function. The "name" argument specifies the "file name" // for the source code that will be printed in Nasal stack traces // on error. - FGNasalScript* parseScript(const char* src, const char* name=0); + // FGNasalScript* parseScript(const char* src, const char* name=0); // Implementation of the settimer extension function void setTimer(naContext c, int argc, naRef* args); @@ -106,6 +57,8 @@ public: // Returns a ghost wrapper for the current _cmdArg naRef cmdArgGhost(); + void setCmdArg(SGPropertyNode* aNode); + // Callbacks for command and timer bindings virtual bool handleCommand( const char* moduleName, const char* fileName, @@ -135,8 +88,8 @@ public: naRef propNodeGhost(SGPropertyNode* handle); - void registerToLoad(FGNasalModelData* data) { _loadList.push(data);} - void registerToUnload(FGNasalModelData* data) { _unloadList.push(data);} + void registerToLoad(FGNasalModelData* data); + void registerToUnload(FGNasalModelData* data); // can't call this 'globals' due to naming clash naRef nasalGlobals() const @@ -159,7 +112,7 @@ public: simgear::BufferedLogCallback* log() const { return _log; } private: - friend class FGNasalScript; + //friend class FGNasalScript; friend class FGNasalListener; friend class FGNasalModuleListener; @@ -181,13 +134,14 @@ private: // Listener std::map _listener; - vector _dead_listener; + std::vector _dead_listener; + static int _listenerId; void loadPropertyScripts(); void loadPropertyScripts(SGPropertyNode* n); void loadScriptDirectory(simgear::Dir nasalDir); - void addModule(string moduleName, simgear::PathList scripts); + void addModule(std::string moduleName, simgear::PathList scripts); void logError(naContext); naRef parse(const char* filename, const char* buf, int len); naRef genPropsModule(); @@ -207,7 +161,7 @@ public: void handleTimer(NasalTimer* t); }; - +#if 0 class FGNasalScript { public: ~FGNasalScript() { _nas->gcRelease(_gcKey); } @@ -217,61 +171,14 @@ public: naCall(_nas->_context, _code, 0, &n, naNil(), naNil()); return naGetError(_nas->_context) == 0; } - + + FGNasalSys* sys() const { return _nas; } private: friend class FGNasalSys; naRef _code; int _gcKey; FGNasalSys* _nas; }; - - -class FGNasalListener : public SGPropertyChangeListener { -public: - FGNasalListener(SGPropertyNode* node, naRef code, FGNasalSys* nasal, - int key, int id, int init, int type); - - virtual ~FGNasalListener(); - virtual void valueChanged(SGPropertyNode* node); - virtual void childAdded(SGPropertyNode* parent, SGPropertyNode* child); - virtual void childRemoved(SGPropertyNode* parent, SGPropertyNode* child); - -private: - bool changed(SGPropertyNode* node); - void call(SGPropertyNode* which, naRef mode); - - friend class FGNasalSys; - SGPropertyNode_ptr _node; - naRef _code; - int _gcKey; - int _id; - FGNasalSys* _nas; - int _init; - int _type; - unsigned int _active; - bool _dead; - long _last_int; - double _last_float; - string _last_string; -}; - - -class NasalXMLVisitor : public XMLVisitor { -public: - NasalXMLVisitor(naContext c, int argc, naRef* args); - virtual ~NasalXMLVisitor() { naFreeContext(_c); } - - virtual void startElement(const char* tag, const XMLAttributes& a); - virtual void endElement(const char* tag); - virtual void data(const char* str, int len); - virtual void pi(const char* target, const char* data); - -private: - void call(naRef func, int num, naRef a = naNil(), naRef b = naNil()); - naRef make_string(const char* s, int n = -1); - - naContext _c; - naRef _start_element, _end_element, _data, _pi; -}; +#endif #endif // __NASALSYS_HXX diff --git a/src/Scripting/NasalSys_private.hxx b/src/Scripting/NasalSys_private.hxx new file mode 100644 index 000000000..225af03cf --- /dev/null +++ b/src/Scripting/NasalSys_private.hxx @@ -0,0 +1,71 @@ +// Copyright (C) 2013 James Turner// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifndef __NASALSYS_PRIVATE_HXX +#define __NASALSYS_PRIVATE_HXX + +#include +#include +#include + +class FGNasalListener : public SGPropertyChangeListener { +public: + FGNasalListener(SGPropertyNode* node, naRef code, FGNasalSys* nasal, + int key, int id, int init, int type); + + virtual ~FGNasalListener(); + virtual void valueChanged(SGPropertyNode* node); + virtual void childAdded(SGPropertyNode* parent, SGPropertyNode* child); + virtual void childRemoved(SGPropertyNode* parent, SGPropertyNode* child); + +private: + bool changed(SGPropertyNode* node); + void call(SGPropertyNode* which, naRef mode); + + friend class FGNasalSys; + SGPropertyNode_ptr _node; + naRef _code; + int _gcKey; + int _id; + FGNasalSys* _nas; + int _init; + int _type; + unsigned int _active; + bool _dead; + long _last_int; + double _last_float; + string _last_string; +}; + + +class NasalXMLVisitor : public XMLVisitor { +public: + NasalXMLVisitor(naContext c, int argc, naRef* args); + virtual ~NasalXMLVisitor() { naFreeContext(_c); } + + virtual void startElement(const char* tag, const XMLAttributes& a); + virtual void endElement(const char* tag); + virtual void data(const char* str, int len); + virtual void pi(const char* target, const char* data); + +private: + void call(naRef func, int num, naRef a = naNil(), naRef b = naNil()); + naRef make_string(const char* s, int n = -1); + + naContext _c; + naRef _start_element, _end_element, _data, _pi; +}; + +#endif // of __NASALSYS_PRIVATE_HXX