diff --git a/src/Scripting/CMakeLists.txt b/src/Scripting/CMakeLists.txt index 42692b55a..57ef20827 100644 --- a/src/Scripting/CMakeLists.txt +++ b/src/Scripting/CMakeLists.txt @@ -6,6 +6,7 @@ set(SOURCES NasalPositioned.cxx NasalCanvas.cxx NasalClipboard.cxx + NasalCondition.cxx ) set(HEADERS @@ -13,6 +14,7 @@ set(HEADERS NasalPositioned.hxx NasalCanvas.hxx NasalClipboard.hxx + NasalCondition.hxx ) if(WIN32) diff --git a/src/Scripting/NasalCondition.cxx b/src/Scripting/NasalCondition.cxx new file mode 100644 index 000000000..da796c533 --- /dev/null +++ b/src/Scripting/NasalCondition.cxx @@ -0,0 +1,115 @@ +// NasalCondition -- expose SGCondition to Nasal +// +// Written by James Turner, started 2012. +// +// Copyright (C) 2012 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. + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "NasalCondition.hxx" +#include "NasalSys.hxx" +#include
+ +#include +#include + +static void conditionGhostDestroy(void* g); + +naGhostType ConditionGhostType = { conditionGhostDestroy, "condition" }; + +static void hashset(naContext c, naRef hash, const char* key, naRef val) +{ + naRef s = naNewString(c); + naStr_fromdata(s, (char*)key, strlen(key)); + naHash_set(hash, s, val); +} + +SGCondition* conditionGhost(naRef r) +{ + if ((naGhost_type(r) == &ConditionGhostType)) + { + return (SGCondition*) naGhost_ptr(r); + } + + return 0; +} + +static void conditionGhostDestroy(void* g) +{ + SGCondition* cond = (SGCondition*)g; + if (!SGCondition::put(cond)) // unref + delete cond; +} + +static naRef conditionPrototype; + +naRef ghostForCondition(naContext c, const SGCondition* cond) +{ + if (!cond) { + return naNil(); + } + + SGCondition::get(cond); // take a ref + return naNewGhost(c, &ConditionGhostType, (void*) cond); +} + +static naRef f_condition_test(naContext c, naRef me, int argc, naRef* args) +{ + SGCondition* cond = conditionGhost(me); + if (!cond) { + naRuntimeError(c, "condition.test called on non-condition object"); + } + + return naNum(cond->test()); +} + +static naRef f_createCondition(naContext c, naRef me, int argc, naRef* args) +{ + SGPropertyNode* node = ghostToPropNode(args[0]); + SGPropertyNode* root = globals->get_props(); + if (argc > 1) { + root = ghostToPropNode(args[1]); + } + + SGCondition* cond = sgReadCondition(root, node); + return ghostForCondition(c, cond); +} + +// Table of extension functions. Terminate with zeros. +static struct { const char* name; naCFunction func; } funcs[] = { + { "_createCondition", f_createCondition }, + { 0, 0 } +}; + + +naRef initNasalCondition(naRef globals, naContext c, naRef gcSave) +{ + conditionPrototype = naNewHash(c); + hashset(c, gcSave, "conditionProto", conditionPrototype); + + hashset(c, conditionPrototype, "test", naNewFunc(c, naNewCCode(c, f_condition_test))); + for(int i=0; funcs[i].name; i++) { + hashset(c, globals, funcs[i].name, + naNewFunc(c, naNewCCode(c, funcs[i].func))); + } + + return naNil(); +} diff --git a/src/Scripting/NasalCondition.hxx b/src/Scripting/NasalCondition.hxx new file mode 100644 index 000000000..51b2661b6 --- /dev/null +++ b/src/Scripting/NasalCondition.hxx @@ -0,0 +1,34 @@ +// NasalCondition.hxx -- expose SGCondition to Nasal +// +// Written by James Turner, started 2012. +// +// Copyright (C) 2012 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 SCRIPTING_NASAL_CONDITION_HXX +#define SCRIPTING_NASAL_CONDITION_HXX + +#include + +// forward decls +class SGCondition; + +naRef ghostForCondition(naContext c, const SGCondition* cond); + +naRef initNasalCondition(naRef globals, naContext c, naRef gcSave); + +#endif // of SCRIPTING_NASAL_CONDITION_HXX + diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx index a3983015d..b38e0fbcd 100644 --- a/src/Scripting/NasalSys.cxx +++ b/src/Scripting/NasalSys.cxx @@ -29,6 +29,7 @@ #include "NasalPositioned.hxx" #include "NasalCanvas.hxx" #include "NasalClipboard.hxx" +#include "NasalCondition.hxx" #include
#include
@@ -559,7 +560,8 @@ void FGNasalSys::init() initNasalPositioned(_globals, _context, _gcHash); initNasalCanvas(_globals, _context, _gcHash); NasalClipboard::init(this); - + initNasalCondition(_globals, _context, _gcHash); + // Now load the various source files in the Nasal directory simgear::Dir nasalDir(SGPath(globals->get_fg_root(), "Nasal")); loadScriptDirectory(nasalDir); diff --git a/src/Scripting/NasalSys.hxx b/src/Scripting/NasalSys.hxx index 18ef05314..543484499 100644 --- a/src/Scripting/NasalSys.hxx +++ b/src/Scripting/NasalSys.hxx @@ -14,7 +14,7 @@ class FGNasalScript; class FGNasalListener; - +class SGCondition; /** Nasal model data container. * load and unload methods must be run in main thread (not thread-safe). */ @@ -65,6 +65,9 @@ protected: SGSharedPtr _data; }; +SGPropertyNode* ghostToPropNode(naRef ref); +SGCondition* conditionGhost(naRef r); + class FGNasalSys : public SGSubsystem { public: @@ -129,7 +132,7 @@ public: naRef callMethod(naRef code, naRef self, int argc, naRef* args, naRef locals); naRef propNodeGhost(SGPropertyNode* handle); - + void registerToLoad(FGNasalModelData* data) { _loadList.push(data);} void registerToUnload(FGNasalModelData* data) { _unloadList.push(data);} diff --git a/src/Scripting/nasal-props.cxx b/src/Scripting/nasal-props.cxx index 78a242877..1df4b0d42 100644 --- a/src/Scripting/nasal-props.cxx +++ b/src/Scripting/nasal-props.cxx @@ -45,6 +45,15 @@ naRef FGNasalSys::propNodeGhost(SGPropertyNode* handle) return propNodeGhostCreate(_context, handle); } +SGPropertyNode* ghostToPropNode(naRef ref) +{ + if (!naIsGhost(ref) || (naGhost_type(ref) != &PropNodeGhostType)) + return NULL; + + SGPropertyNode_ptr* pp = (SGPropertyNode_ptr*) naGhost_ptr(ref); + return pp->ptr(); +} + #define NASTR(s) s ? naStr_fromdata(naNewString(c),(char*)(s),strlen(s)) : naNil() //