#include <Main/globals.hxx>
#include <Scenery/scenery.hxx>
#include <Scripting/NasalSys.hxx>
+#include <Scripting/NasalModelData.hxx>
#include <Sound/fg_fx.hxx>
#include "AIBase.hxx"
#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;
FGPUIDialog *dialog;
SGPropertyNode_ptr node;
- vector <SGBinding *> bindings;
+ std::vector <SGBinding *> bindings;
int key;
string label, legend, text, format;
format_type fmt_type;
}
SGPropertyNode *dest = fgGetNode("/sim/bindings/gui", true);
- vector<SGPropertyNode_ptr> bindings = props->getChildren("binding");
+ std::vector<SGPropertyNode_ptr> bindings = props->getChildren("binding");
if (bindings.size() > 0) {
info->key = props->getIntValue("keynum", -1);
if (props->hasValue("key"))
vname = _props->getStringValue("property-name");
}
- vector<SGPropertyNode_ptr> value_nodes = values->getChildren(vname);
+ std::vector<SGPropertyNode_ptr> value_nodes = values->getChildren(vname);
_list = new char *[value_nodes.size() + 1];
unsigned int i;
for (i = 0; i < value_nodes.size(); i++) {
using std::cout;
using std::endl;
using std::map;
+using std::string;
FGEventSetting::FGEventSetting( SGPropertyNode_ptr base ) :
value(0.0)
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 << '"');
//
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");
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)!!");
#include <Viewer/renderer.hxx>
#include <Viewer/splash.hxx>
#include <Scripting/NasalSys.hxx>
+#include <Scripting/NasalModelData.hxx>
#include "scenery.hxx"
#include "SceneryPager.hxx"
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)
--- /dev/null
+
+#include "NasalModelData.hxx"
+
+#include <simgear/debug/logstream.hxx>
+
+#include "NasalSys.hxx"
+#include <Main/globals.hxx>
+
+
+// FGNasalModelData class. If sgLoad3DModel() is called with a pointer to
+// such a class, then it lets modelLoaded() run the <load> script, and the
+// destructor the <unload> 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 <unload> 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 <load> 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);
+}
--- /dev/null
+// 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 <simgear/nasal/nasal.h>
+#include <simgear/scene/model/modellib.hxx>
+
+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<FGNasalModelData> _data;
+};
+
+#endif // of NASAL_MODEL_DATA_HXX
#include <simgear/debug/BufferedLogCallback.hxx>
#include "NasalSys.hxx"
+#include "NasalSys_private.hxx"
+#include "NasalModelData.hxx"
#include "NasalPositioned.hxx"
#include "NasalCanvas.hxx"
#include "NasalClipboard.hxx"
return true;
}
+#if 0
FGNasalScript* FGNasalSys::parseScript(const char* src, const char* name)
{
FGNasalScript* script = new FGNasalScript();
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.
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());
}
return naStr_fromdata(naNewString(c), const_cast<char*>(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<SGPropertyNode*>(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(<path> [, <start-tag> [, <end-tag> [, <data> [, <pi>]]]]);
//
{ "settimer", f_settimer },
{ "_setlistener", f_setlistener },
{ "removelistener", f_removelistener },
+ { "addcommand", f_addCommand },
+ { "removecommand", f_removeCommand },
{ "_cmdarg", f_cmdarg },
{ "_interpolate", f_interpolate },
{ "rand", f_rand },
return propNodeGhost(_cmdArg);
}
+void FGNasalSys::setCmdArg(SGPropertyNode* aNode)
+{
+ _cmdArg = aNode;
+}
+
void FGNasalSys::init()
{
int i;
return naNum(_listener.size());
}
+void FGNasalSys::registerToLoad(FGNasalModelData *data)
+{
+ _loadList.push(data);
+}
+
+void FGNasalSys::registerToUnload(FGNasalModelData *data)
+{
+ _unloadList.push(data);
+}
// FGNasalListener class.
}
}
-
-
-// FGNasalModelData class. If sgLoad3DModel() is called with a pointer to
-// such a class, then it lets modelLoaded() run the <load> script, and the
-// destructor the <unload> 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 <unload> 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 <load> 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) :
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/misc/sg_dir.hxx>
#include <simgear/nasal/nasal.h>
-#include <simgear/scene/model/modellib.hxx>
-#include <simgear/xml/easyxml.hxx>
#include <simgear/threads/SGQueue.hxx>
+#include <simgear/props/props.hxx>
#include <map>
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<FGNasalModelData> _data;
-};
-
SGPropertyNode* ghostToPropNode(naRef ref);
SGCondition* conditionGhost(naRef r);
// 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);
// 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,
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
simgear::BufferedLogCallback* log() const
{ return _log; }
private:
- friend class FGNasalScript;
+ //friend class FGNasalScript;
friend class FGNasalListener;
friend class FGNasalModuleListener;
// Listener
std::map<int, FGNasalListener *> _listener;
- vector<FGNasalListener *> _dead_listener;
+ std::vector<FGNasalListener *> _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();
void handleTimer(NasalTimer* t);
};
-
+#if 0
class FGNasalScript {
public:
~FGNasalScript() { _nas->gcRelease(_gcKey); }
naCall(_nas->_context, _code, 0, &n, naNil(), naNil());
return naGetError(_nas->_context) == 0;
}
-
-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);
-
+
+ FGNasalSys* sys() const { return _nas; }
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
--- /dev/null
+// 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 <simgear/props/props.hxx>
+#include <simgear/nasal/nasal.h>
+#include <simgear/xml/easyxml.hxx>
+
+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