# include "config.h"
#endif
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h> // gettimeofday
#endif
#include <sys/stat.h>
#include <fstream>
#include <sstream>
-#include <algorithm> // for std::sort
#include <simgear/nasal/nasal.h>
#include <simgear/props/props.hxx>
#include "NasalPositioned.hxx"
#include "NasalCanvas.hxx"
#include "NasalClipboard.hxx"
+#include "NasalCondition.hxx"
+#include "NasalString.hxx"
#include <Main/globals.hxx>
#include <Main/util.hxx>
using std::map;
+void postinitNasalGUI(naRef globals, naContext c);
+
static FGNasalSys* nasalSys = 0;
// Listener class for loading Nasal modules on demand
nasalSys = this;
_context = 0;
_globals = naNil();
+ _string = naNil();
_gcHash = naNil();
_nextGCKey = 0; // Any value will do
_callCount = 0;
naFreeContext(_context);
_globals = naNil();
+ _string = naNil();
}
bool FGNasalSys::parseAndRun(const char* sourceCode)
case props::DOUBLE:
{
double dv = p->getDoubleValue();
- if (osg::isNaN(dv)) {
+ if (SGMisc<double>::isNaN(dv)) {
SG_LOG(SG_NASAL, SG_ALERT, "Nasal getprop: property " << p->getPath() << " is NaN");
return naNil();
}
if(naIsNil(n))
naRuntimeError(c, "setprop() value is not string or number");
- if (osg::isNaN(n.num)) {
+ if (SGMisc<double>::isNaN(n.num)) {
naRuntimeError(c, "setprop() passed a NaN");
}
return naNum(buf.length());
}
+// logprint() extension function. Same as above, all arguments after the
+// first argument are concatenated. Argument 0 is the log-level, matching
+// sgDebugPriority.
+static naRef f_logprint(naContext c, naRef me, int argc, naRef* args)
+{
+ if (argc < 1)
+ naRuntimeError(c, "no prioirty argument to logprint()");
+
+ naRef priority = args[0];
+ string buf;
+ int n = argc;
+ for(int i=1; i<n; i++) {
+ naRef s = naStringValue(c, args[i]);
+ if(naIsNil(s)) continue;
+ buf += naStr_data(s);
+ }
+ SG_LOG(SG_NASAL, (sgDebugPriority)(int) priority.num, buf);
+ return naNum(buf.length());
+}
+
+
// fgcommand() extension function. Executes a named command via the
// FlightGear command manager. Takes a single property node name as
// an argument.
{ "getprop", f_getprop },
{ "setprop", f_setprop },
{ "print", f_print },
+ { "logprint", f_logprint },
{ "_fgcommand", f_fgcommand },
{ "settimer", f_settimer },
{ "_setlistener", f_setlistener },
hashset(_globals, funcs[i].name,
naNewFunc(_context, naNewCCode(_context, funcs[i].func)));
-
-
// And our SGPropertyNode wrapper
hashset(_globals, "props", genPropsModule());
_gcHash = naNewHash(_context);
hashset(_globals, "__gcsave", _gcHash);
+ // Add string methods
+ _string = naInit_string(_context);
+ naSave(_context, _string);
+ initNasalString(_globals, _string, _context, _gcHash);
+
initNasalPositioned(_globals, _context, _gcHash);
- initNasalCanvas(_globals, _context, _gcHash);
NasalClipboard::init(this);
-
+ initNasalCanvas(_globals, _context, _gcHash);
+ 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);
// now Nasal modules are loaded, we can do some delayed work
postinitNasalPositioned(_globals, _context);
+ postinitNasalGUI(_globals, _context);
}
void FGNasalSys::update(double)
{
+ if( NasalClipboard::getInstance() )
+ NasalClipboard::getInstance()->update();
+
if(!_dead_listener.empty()) {
vector<FGNasalListener *>::iterator it, end = _dead_listener.end();
for(it = _dead_listener.begin(); it != end; ++it) delete *it;
void FGNasalSys::loadScriptDirectory(simgear::Dir nasalDir)
{
simgear::PathList scripts = nasalDir.children(simgear::Dir::TYPE_FILE, ".nas");
- // sort scripts, avoid loading sequence effects due to file system's
- // random directory order
- std::sort(scripts.begin(), scripts.end(), pathSortPredicate);
-
+ // Note: simgear::Dir already reports file entries in a deterministic order,
+ // so a fixed loading sequence is guaranteed (same for every user)
for (unsigned int i=0; i<scripts.size(); ++i) {
SGPath fullpath(scripts[i]);
SGPath file = fullpath.file();