Also guard against duplicate init of cppbind wrapped classes.
void postinitNasalGUI(naRef globals, naContext c)
{
- NasalFileDialog::init("gui._FileDialog")
- .member("title", &FGFileDialog::getTitle, &FGFileDialog::setTitle)
- .member("button", &FGFileDialog::getButton, &FGFileDialog::setButton)
- .member("directory", &FGFileDialog::getDirectory, &FGFileDialog::setDirectory)
- .member("show_hidden", &FGFileDialog::showHidden, &FGFileDialog::setShowHidden)
- .member("placeholder", &FGFileDialog::getPlaceholder, &FGFileDialog::setPlaceholderName)
- .member("pattern", &FGFileDialog::filterPatterns, &FGFileDialog::setFilterPatterns)
- .method("open", &FGFileDialog::exec)
- .method("close", &FGFileDialog::close)
- .method("setCallback", &FGFileDialog::setCallbackFromNasal);
-
+ if (!NasalFileDialog::isInit()) {
+ NasalFileDialog::init("gui._FileDialog")
+ .member("title", &FGFileDialog::getTitle, &FGFileDialog::setTitle)
+ .member("button", &FGFileDialog::getButton, &FGFileDialog::setButton)
+ .member("directory", &FGFileDialog::getDirectory, &FGFileDialog::setDirectory)
+ .member("show_hidden", &FGFileDialog::showHidden, &FGFileDialog::setShowHidden)
+ .member("placeholder", &FGFileDialog::getPlaceholder, &FGFileDialog::setPlaceholderName)
+ .member("pattern", &FGFileDialog::filterPatterns, &FGFileDialog::setFilterPatterns)
+ .method("open", &FGFileDialog::exec)
+ .method("close", &FGFileDialog::close)
+ .method("setCallback", &FGFileDialog::setCallbackFromNasal);
+ }
+
nasal::Hash guiModule = nasal::Hash(globals, c).get<nasal::Hash>("gui");
guiModule.set("FILE_DIALOG_OPEN_FILE", (int) FGFileDialog::USE_OPEN_FILE);
naRef initNasalCanvas(naRef globals, naContext c)
{
- NasalEvent::init("canvas.Event")
+ if (!NasalEvent::isInit()) {
+
+ NasalEvent::init("canvas.Event")
.member("type", &sc::Event::getTypeString)
.member("target", &sc::Event::getTarget)
.member("currentTarget", &sc::Event::getCurrentTarget)
.bases<NasalElement>()
.member("_node_ghost", &elementGetNode<canvas::Window>)
.method("_getCanvasDecoration", &canvas::Window::getCanvasDecoration);
-
+ }
+
nasal::Hash globals_module(globals, c),
canvas_module = globals_module.createHash("canvas");
//------------------------------------------------------------------------------
naRef initNasalHTTP(naRef globals, naContext c)
{
+ if (!NasalRequest::isInit()) {
+
using simgear::HTTP::Request;
NasalRequest::init("http.Request")
.member("url", &Request::url)
.bases<NasalRequest>()
.member("response", &MemoryRequest::responseBody);
+ }
+
nasal::Hash globals_module(globals, c),
http = globals_module.createHash("http");
int _gcSaveKey;
};
+
class NasalFPDelegateFactory : public FlightPlan::DelegateFactory
{
public:
_gcSaveKey = _nasal->gcSave(_func);
}
- ~NasalFPDelegateFactory()
+ virtual ~NasalFPDelegateFactory()
{
_nasal->gcRelease(_gcSaveKey);
}
int _gcSaveKey;
};
+static std::vector<NasalFPDelegateFactory*> static_nasalDelegateFactories;
+
+void shutdownNasalPositioned()
+{
+ std::vector<NasalFPDelegateFactory*>::iterator it;
+ for (it = static_nasalDelegateFactories.begin();
+ it != static_nasalDelegateFactories.end(); ++it)
+ {
+ FlightPlan::unregisterDelegateFactory(*it);
+ delete (*it);
+ }
+ static_nasalDelegateFactories.clear();
+}
+
static naRef f_registerFPDelegate(naContext c, naRef me, int argc, naRef* args)
{
if ((argc < 1) || !naIsFunc(args[0])) {
NasalFPDelegateFactory* factory = new NasalFPDelegateFactory(args[0]);
FlightPlan::registerDelegateFactory(factory);
-
+ static_nasalDelegateFactories.push_back(factory);
return naNil();
}
naRef initNasalPositioned(naRef globals, naContext c);
naRef initNasalPositioned_cppbind(naRef globals, naContext c);
void postinitNasalPositioned(naRef globals, naContext c);
+void shutdownNasalPositioned();
#endif // of SCRIPTING_NASAL_POSITIONED_HXX
//------------------------------------------------------------------------------
naRef initNasalPositioned_cppbind(naRef globalsRef, naContext c)
{
+ if (!NasalPositioned::isInit()) {
+
NasalPositioned::init("Positioned")
.member("id", &FGPositioned::ident)
.member("ident", &FGPositioned::ident) // TODO to we really need id and ident?
.method("getStar", &FGAirport::findSTARWithIdent)
.method("getIAP", &FGAirport::findApproachWithIdent)
.method("tostring", &FGAirport::toString);
+ }
nasal::Hash globals(globalsRef, c),
positioned( globals.createHash("positioned") );
FGNasalSys::~FGNasalSys()
{
nasalSys = 0;
- map<int, FGNasalListener *>::iterator it, end = _listener.end();
- for(it = _listener.begin(); it != end; ++it)
- delete it->second;
-
- naFreeContext(_context);
- _globals = naNil();
- _string = naNil();
}
bool FGNasalSys::parseAndRun(const char* sourceCode)
class NasalCommand : public SGCommandMgr::Command
{
public:
- NasalCommand(FGNasalSys* sys, naRef f) :
+ NasalCommand(FGNasalSys* sys, naRef f, const std::string& name) :
_sys(sys),
- _func(f)
+ _func(f),
+ _name(name)
{
+ globals->get_commands()->addCommandObject(_name, this);
_gcRoot = sys->gcSave(f);
}
FGNasalSys* _sys;
naRef _func;
int _gcRoot;
+ std::string _name;
};
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);
+ nasalSys->addCommand(args[1], naStr_data(args[0]));
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;
+ if ((argc < 1) || !naIsString(args[0]))
+ naRuntimeError(c, "bad argument to removecommand()");
+ globals->get_commands()->removeCommand(naStr_data(args[0]));
return naNil();
}
initNasalCondition(_globals, _context);
initNasalHTTP(_globals, _context);
- NasalTimerObj::init("Timer")
- .method("start", &TimerObj::start)
- .method("stop", &TimerObj::stop)
- .method("restart", &TimerObj::restart)
- .member("singleShot", &TimerObj::isSingleShot, &TimerObj::setSingleShot)
- .member("isRunning", &TimerObj::isRunning);
-
+ if (!NasalTimerObj::isInit()) {
+ NasalTimerObj::init("Timer")
+ .method("start", &TimerObj::start)
+ .method("stop", &TimerObj::stop)
+ .method("restart", &TimerObj::restart)
+ .member("singleShot", &TimerObj::isSingleShot, &TimerObj::setSingleShot)
+ .member("isRunning", &TimerObj::isRunning);
+ }
+
// Now load the various source files in the Nasal directory
simgear::Dir nasalDir(SGPath(globals->get_fg_root(), "Nasal"));
loadScriptDirectory(nasalDir);
postinitNasalGUI(_globals, _context);
}
+void FGNasalSys::shutdown()
+{
+ shutdownNasalPositioned();
+
+ map<int, FGNasalListener *>::iterator it, end = _listener.end();
+ for(it = _listener.begin(); it != end; ++it)
+ delete it->second;
+ _listener.clear();
+
+ NasalCommandDict::iterator j = _commands.begin();
+ for (; j != _commands.end(); ++j) {
+ globals->get_commands()->removeCommand(j->first);
+ }
+ _commands.clear();
+
+ naClearSaved();
+
+ _string = naNil(); // will be freed by _context
+ naFreeContext(_context);
+
+ //setWatchedRef(_globals);
+
+ // remove the recursive reference in globals
+ hashset(_globals, "globals", naNil());
+ _globals = naNil();
+
+ naGC();
+
+}
+
naRef FGNasalSys::wrappedPropsNode(SGPropertyNode* aProps)
{
static naRef wrapNodeFunc = naNil();
_unloadList.push(data);
}
+void FGNasalSys::addCommand(naRef func, const std::string& name)
+{
+ if (_commands.find(name) != _commands.end()) {
+ SG_LOG(SG_NASAL, SG_WARN, "duplicate add of command:" << name);
+ return;
+ }
+
+ NasalCommand* cmd = new NasalCommand(this, func, name);
+ _commands[name] = cmd;
+}
+
+void FGNasalSys::removeCommand(const std::string& name)
+{
+ NasalCommandDict::iterator it = _commands.find(name);
+ if (it == _commands.end()) {
+ SG_LOG(SG_NASAL, SG_WARN, "remove of unknwon command:" << name);
+ return;
+ }
+
+ // will delete the NasalCommand instance
+ globals->get_commands()->removeCommand(name);
+ _commands.erase(it);
+}
+
//////////////////////////////////////////////////////////////////////////
// FGNasalListener class.
class FGNasalListener;
class SGCondition;
class FGNasalModelData;
+class NasalCommand;
namespace simgear { class BufferedLogCallback; }
FGNasalSys();
virtual ~FGNasalSys();
virtual void init();
+ virtual void shutdown();
+
virtual void update(double dt);
// Loads a nasal script from an external file and inserts it as a
void deleteModule(const char* moduleName);
+ void addCommand(naRef func, const std::string& name);
+ void removeCommand(const std::string& name);
+
/**
* Set member of specified hash to given value
*/
SGPropertyNode_ptr _cmdArg;
simgear::BufferedLogCallback* _log;
+
+ typedef std::map<std::string, NasalCommand*> NasalCommandDict;
+ NasalCommandDict _commands;
public:
void handleTimer(NasalTimer* t);
};