]> git.mxchange.org Git - flightgear.git/commitdiff
Support optional Nasal modules in fgdata/Nasal/MyModuleFoo
authorThorstenB <brehmt@gmail.com>
Sat, 2 Apr 2011 13:13:29 +0000 (15:13 +0200)
committerThorstenB <brehmt@gmail.com>
Sat, 2 Apr 2011 13:15:59 +0000 (15:15 +0200)
- Allow structuring generic Nasal sources into modules (i.e. support
  separate source folders for multiplayer/local weather/... sources)
- Option to enable/disable loading of generic Nasal modules (i.e we only
  need to load stuff that is really needed/enabled).
- Provide basic loading sequence: subfolders are strictly loaded _after_
  the base directory. So submodules can rely on .nas-scripts like math.nas,
  io.nas, debug.nas, ... to be already loaded - dropping the need for
  awkward listeners/timers to delay module initialization (loading order
  within Nasal/*.nas is still random)

src/Scripting/NasalSys.cxx
src/Scripting/NasalSys.hxx

index 1f952b325c25d05a11dba82efdd76414290bc375..72a99bc93219eb5744d820be72d3f9e5131878cf 100644 (file)
@@ -737,12 +737,15 @@ void FGNasalSys::init()
 
     // Now load the various source files in the Nasal directory
     simgear::Dir nasalDir(SGPath(globals->get_fg_root(), "Nasal"));
-    simgear::PathList scripts = nasalDir.children(simgear::Dir::TYPE_FILE, ".nas");
-    
-    for (unsigned int i=0; i<scripts.size(); ++i) {
-      SGPath fullpath(scripts[i]);
-      SGPath file = fullpath.file();
-      loadModule(fullpath, file.base().c_str());
+    loadScriptDirectory(nasalDir);
+
+    // Add modules in Nasal subdirectories to property tree
+    simgear::PathList directories = nasalDir.children(simgear::Dir::TYPE_DIR+
+            simgear::Dir::NO_DOT_OR_DOTDOT, "");
+    for (unsigned int i=0; i<directories.size(); ++i) {
+        simgear::Dir dir(directories[i]);
+        simgear::PathList scripts = dir.children(simgear::Dir::TYPE_FILE, ".nas");
+        addModule(directories[i].file(), scripts);
     }
 
     // set signal and remove node to avoid restoring at reinit
@@ -777,6 +780,37 @@ void FGNasalSys::update(double)
     _context = naNewContext();
 }
 
+// Loads all scripts in given directory 
+void FGNasalSys::loadScriptDirectory(simgear::Dir nasalDir)
+{
+    simgear::PathList scripts = nasalDir.children(simgear::Dir::TYPE_FILE, ".nas");
+    for (unsigned int i=0; i<scripts.size(); ++i) {
+      SGPath fullpath(scripts[i]);
+      SGPath file = fullpath.file();
+      loadModule(fullpath, file.base().c_str());
+    }
+}
+
+// Create module with list of scripts
+void FGNasalSys::addModule(string moduleName, simgear::PathList scripts)
+{
+    if (scripts.size()>0)
+    {
+        SGPropertyNode* nasal = globals->get_props()->getNode("nasal");
+        SGPropertyNode* module_node = nasal->getChild(moduleName,0,true);
+        for (unsigned int i=0; i<scripts.size(); ++i) {
+            SGPropertyNode* pFileNode = module_node->getChild("file",i,true);
+            pFileNode->setStringValue(scripts[i].c_str());
+        }
+        if (!module_node->hasChild("enabled",0))
+        {
+            SGPropertyNode* node = module_node->getChild("enabled",0,true);
+            node->setBoolValue(true);
+            node->setAttribute(SGPropertyNode::USERARCHIVE,true);
+        }
+    }
+}
+
 // Loads the scripts found under /nasal in the global tree
 void FGNasalSys::loadPropertyScripts()
 {
@@ -785,33 +819,51 @@ void FGNasalSys::loadPropertyScripts()
 
     for(int i=0; i<nasal->nChildren(); i++) {
         SGPropertyNode* n = nasal->getChild(i);
+        bool is_loaded = false;
 
         const char* module = n->getName();
         if(n->hasChild("module"))
             module = n->getStringValue("module");
-
-        // allow multiple files to be specified within a single
-        // Nasal module tag
-        int j = 0;
-        SGPropertyNode *fn;
-        bool file_specified = false;
-        while((fn = n->getChild("file", j)) != NULL) {
-            file_specified = true;
-            const char* file = fn->getStringValue();
-            SGPath p = globals->resolve_maybe_aircraft_path(file);
-            loadModule(p, module);
-            j++;
+        if (n->getBoolValue("enabled",true))
+        {
+            // allow multiple files to be specified within a single
+            // Nasal module tag
+            int j = 0;
+            SGPropertyNode *fn;
+            bool file_specified = false;
+            while((fn = n->getChild("file", j)) != NULL) {
+                file_specified = true;
+                const char* file = fn->getStringValue();
+                SGPath p(file);
+                if (!p.isAbsolute() || !p.exists())
+                {
+                    p = globals->resolve_maybe_aircraft_path(file);
+                }
+                loadModule(p, module);
+                j++;
+            }
+    
+            const char* src = n->getStringValue("script");
+            if(!n->hasChild("script")) src = 0; // Hrm...
+            if(src)
+                createModule(module, n->getPath().c_str(), src, strlen(src));
+    
+            if(!file_specified && !src)
+            {
+                // module no longer exists - clear the archived "enable" flag
+                n->setAttribute(SGPropertyNode::USERARCHIVE,false);
+                SGPropertyNode* node = n->getChild("enabled",0,false);
+                if (node)
+                    node->setAttribute(SGPropertyNode::USERARCHIVE,false);
+
+                SG_LOG(SG_NASAL, SG_ALERT, "Nasal error: " <<
+                        "no <file> or <script> defined in " <<
+                        "/nasal/" << module);
+            }
+            else
+                is_loaded = true;
         }
-
-        const char* src = n->getStringValue("script");
-        if(!n->hasChild("script")) src = 0; // Hrm...
-        if(src)
-            createModule(module, n->getPath().c_str(), src, strlen(src));
-
-        if(!file_specified && !src)
-            SG_LOG(SG_NASAL, SG_ALERT, "Nasal error: " <<
-                   "no <file> or <script> defined in " <<
-                   "/nasal/" << module);
+        n->setBoolValue("loaded",is_loaded);
     }
 }
 
index 6d64e5097ba66f3ddfd4dd01902178c047bae76d..c65316ac3c1bcd415e9c73f3cf951735f8a18f07 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <simgear/misc/sg_path.hxx>
 #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>
@@ -85,6 +86,8 @@ private:
     static int _listenerId;
 
     void loadPropertyScripts();
+    void loadScriptDirectory(simgear::Dir nasalDir);
+    void addModule(string moduleName, simgear::PathList scripts);
     void hashset(naRef hash, const char* key, naRef val);
     void logError(naContext);
     naRef parse(const char* filename, const char* buf, int len);