]> git.mxchange.org Git - flightgear.git/blobdiff - src/Scripting/NasalSys.cxx
Refactor FG_HOME init, so we can log sooner.
[flightgear.git] / src / Scripting / NasalSys.cxx
index a1de1e79452588230bf1838f29cd1f0e68533055..6ae142a75ed123adecc74afaa6bce954b2eaf8a6 100644 (file)
@@ -3,6 +3,10 @@
 #  include "config.h"
 #endif
 
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
 #ifdef HAVE_SYS_TIME_H
 #  include <sys/time.h>  // gettimeofday
 #endif
@@ -13,7 +17,6 @@
 #include <sys/stat.h>
 #include <fstream>
 #include <sstream>
-#include <algorithm> // for std::sort
 
 #include <simgear/nasal/nasal.h>
 #include <simgear/props/props.hxx>
 #include "NasalSys.hxx"
 #include "NasalPositioned.hxx"
 #include "NasalCanvas.hxx"
+#include "NasalClipboard.hxx"
+#include "NasalCondition.hxx"
+#include "NasalString.hxx"
 
 #include <Main/globals.hxx>
 #include <Main/util.hxx>
 #include <Main/fg_props.hxx>
 
+
 using std::map;
 
+void postinitNasalGUI(naRef globals, naContext c);
+
 static FGNasalSys* nasalSys = 0;
 
 // Listener class for loading Nasal modules on demand
@@ -96,11 +105,26 @@ FGNasalSys::FGNasalSys()
     nasalSys = this;
     _context = 0;
     _globals = naNil();
+    _string = naNil();
     _gcHash = naNil();
     _nextGCKey = 0; // Any value will do
     _callCount = 0;
 }
 
+// Utility.  Sets a named key in a hash by C string, rather than nasal
+// string object.
+void FGNasalSys::hashset(naRef hash, const char* key, naRef val)
+{
+    naRef s = naNewString(_context);
+    naStr_fromdata(s, (char*)key, strlen(key));
+    naHash_set(hash, s, val);
+}
+
+void FGNasalSys::globalsSet(const char* key, naRef val)
+{
+  hashset(_globals, key, val);
+}
+
 naRef FGNasalSys::call(naRef code, int argc, naRef* args, naRef locals)
 {
   return callMethod(code, naNil(), argc, args, locals);
@@ -136,6 +160,7 @@ FGNasalSys::~FGNasalSys()
 
     naFreeContext(_context);
     _globals = naNil();
+    _string = naNil();
 }
 
 bool FGNasalSys::parseAndRun(const char* sourceCode)
@@ -170,15 +195,6 @@ FGNasalScript* FGNasalSys::parseScript(const char* src, const char* name)
     return script;
 }
 
-// Utility.  Sets a named key in a hash by C string, rather than nasal
-// string object.
-void FGNasalSys::hashset(naRef hash, const char* key, naRef val)
-{
-    naRef s = naNewString(_context);
-    naStr_fromdata(s, (char*)key, strlen(key));
-    naHash_set(hash, s, val);
-}
-
 // The get/setprop functions accept a *list* of strings and walk
 // through the property tree with them to find the appropriate node.
 // This allows a Nasal object to hold onto a property path and use it
@@ -218,7 +234,7 @@ static naRef f_getprop(naContext c, naRef me, int argc, naRef* args)
     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();
         }
@@ -273,7 +289,7 @@ static naRef f_setprop(naContext c, naRef me, int argc, naRef* args)
             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");
             }
             
@@ -302,6 +318,27 @@ static naRef f_print(naContext c, naRef me, int argc, naRef* args)
     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.
@@ -492,6 +529,7 @@ static struct { const char* name; naCFunction func; } funcs[] = {
     { "getprop",   f_getprop },
     { "setprop",   f_setprop },
     { "print",     f_print },
+    { "logprint",  f_logprint },
     { "_fgcommand", f_fgcommand },
     { "settimer",  f_settimer },
     { "_setlistener", f_setlistener },
@@ -538,8 +576,6 @@ void FGNasalSys::init()
         hashset(_globals, funcs[i].name,
                 naNewFunc(_context, naNewCCode(_context, funcs[i].func)));
 
-
-  
     // And our SGPropertyNode wrapper
     hashset(_globals, "props", genPropsModule());
 
@@ -549,8 +585,15 @@ void FGNasalSys::init()
     _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);
+    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"));
@@ -576,10 +619,14 @@ void FGNasalSys::init()
   
     // 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;
@@ -622,10 +669,8 @@ bool pathSortPredicate(const SGPath& p1, const SGPath& p2)
 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();