]> git.mxchange.org Git - flightgear.git/blobdiff - src/Scripting/NasalModelData.cxx
canvas::Text: expose more text/cursor methods to Nasal.
[flightgear.git] / src / Scripting / NasalModelData.cxx
index 24033c527f69d559b4cf640592cd13ed64cc72d3..e4f22692ba399d6c64fbbce248dc9e759fadbcce 100644 (file)
@@ -1,8 +1,16 @@
 
 #include "NasalModelData.hxx"
 #include "NasalSys.hxx"
+#include <Main/fg_props.hxx>
 #include <Main/globals.hxx>
 
+#include <osg/Transform>
+#include <osg/observer_ptr>
+
+#include <simgear/math/SGMath.hxx>
+#include <simgear/nasal/cppbind/Ghost.hxx>
+#include <simgear/scene/util/OsgDebug.hxx>
+#include <simgear/scene/util/OsgMath.hxx>
 #include <simgear/debug/logstream.hxx>
 
 #include <boost/bind.hpp>
 unsigned int FGNasalModelData::_max_module_id = 0;
 FGNasalModelDataList FGNasalModelData::_loaded_models;
 
+typedef osg::ref_ptr<osg::Node> NodeRef;
+typedef nasal::Ghost<NodeRef> NasalNode;
+
+/**
+ * Get position (lat, lon, elevation) and orientation (heading, pitch, roll) of
+ * model.
+ */
+static naRef f_node_getPose( const osg::Node& node,
+                             const nasal::CallContext& ctx )
+{
+  osg::NodePathList parent_paths = node.getParentalNodePaths();
+  for( osg::NodePathList::const_iterator path = parent_paths.begin();
+                                         path != parent_paths.end();
+                                       ++path )
+  {
+    osg::Matrix local_to_world = osg::computeLocalToWorld(*path);
+    if( !local_to_world.valid() )
+      continue;
+
+    SGGeod coord = SGGeod::fromCart( toSG(local_to_world.getTrans()) );
+    if( !coord.isValid() )
+      continue;
+
+    osg::Matrix local_frame = makeZUpFrameRelative(coord),
+                inv_local;
+    inv_local.invert_4x3(local_frame);
+    local_to_world.postMult(inv_local);
+
+    SGQuatd rotate = toSG(local_to_world.getRotate());
+    double hdg, pitch, roll;
+    rotate.getEulerDeg(hdg, pitch, roll);
+
+    nasal::Hash pose(ctx.to_nasal(coord), ctx.c);
+    pose.set("heading", hdg);
+    pose.set("pitch", pitch);
+    pose.set("roll", roll);
+    return pose.get_naRef();
+  }
+
+  return naNil();
+}
+
 //------------------------------------------------------------------------------
 FGNasalModelData::FGNasalModelData( SGPropertyNode *root,
                                     const std::string& path,
@@ -32,35 +82,56 @@ FGNasalModelData::FGNasalModelData( SGPropertyNode *root,
   _module_id( _max_module_id++ )
 {
   _loaded_models.push_back(this);
+
+  SG_LOG
+  (
+    SG_NASAL,
+    SG_INFO,
+    "New model with attached script(s) "
+    "(branch = " << branch << ","
+    " path = " << simgear::getNodePathString(branch) << ")"
+  );
 }
 
 //------------------------------------------------------------------------------
 FGNasalModelData::~FGNasalModelData()
 {
   _loaded_models.remove(this);
+
+  SG_LOG
+  (
+    SG_NASAL,
+    SG_INFO,
+    "Removed model with script(s) (branch = " << _branch.get() << ")"
+  );
 }
 
 //------------------------------------------------------------------------------
 void FGNasalModelData::load()
 {
-    std::stringstream m;
-    m << "__model" << _module_id;
-    _module = m.str();
-    
-    SG_LOG(SG_NASAL, SG_DEBUG, "Loading nasal module " << _module.c_str());
-    
-    const char *s = _load ? _load->getStringValue() : "";
-    FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
-    
-    // Add _module_id to script local hash to allow placing canvasses on objects
-    // inside the model.
-    nasalSys->getGlobals().createHash(_module).set("_module_id", _module_id);
-
-    naRef arg[2];
-    arg[0] = nasalSys->propNodeGhost(_root);
-    arg[1] = nasalSys->propNodeGhost(_prop);
-    nasalSys->createModule(_module.c_str(), _path.c_str(), s, strlen(s),
-                           _root, 2, arg);
+  std::stringstream m;
+  m << "__model" << _module_id;
+  _module = m.str();
+
+  SG_LOG(SG_NASAL, SG_DEBUG, "Loading nasal module " << _module.c_str());
+
+  const char *s = _load ? _load->getStringValue() : "";
+  FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
+
+  // Add _module_id to script local hash to allow placing canvasses on objects
+  // inside the model.
+  nasal::Hash module = nasalSys->getGlobals().createHash(_module);
+  module.set("_module_id", _module_id);
+
+  NasalNode::init("osg.Node")
+      .method("getPose", &f_node_getPose);
+  module.set("_model", _branch);
+
+  naRef arg[2];
+  arg[0] = nasalSys->propNodeGhost(_root);
+  arg[1] = nasalSys->propNodeGhost(_prop);
+  nasalSys->createModule(_module.c_str(), _path.c_str(), s, strlen(s),
+                         _root, 2, arg);
 }
 
 //------------------------------------------------------------------------------
@@ -90,7 +161,7 @@ void FGNasalModelData::unload()
 //------------------------------------------------------------------------------
 osg::Node* FGNasalModelData::getNode()
 {
-  return _branch;
+  return _branch.get();
 }
 
 //------------------------------------------------------------------------------
@@ -124,13 +195,9 @@ void FGNasalModelDataProxy::modelLoaded( const std::string& path,
                                          SGPropertyNode *prop,
                                          osg::Node *branch )
 {
-    FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
-    if(!nasalSys) {
-        SG_LOG(SG_NASAL, SG_WARN, "Trying to run a <load> script "
-               "without Nasal subsystem present.");
+    if( fgGetBool("/sim/disable-embedded-nasal") )
         return;
-    }
-    
+
     if(!prop)
         return;
     
@@ -138,12 +205,24 @@ void FGNasalModelDataProxy::modelLoaded( const std::string& path,
     if(!nasal)
         return;
     
+    FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
+    if(!nasalSys)
+    {
+        SG_LOG
+        (
+          SG_NASAL,
+          SG_WARN,
+          "Can not load model script(s) (Nasal subsystem not available)."
+        );
+        return;
+    }
+
     SGPropertyNode* load   = nasal->getNode("load");
     SGPropertyNode* unload = nasal->getNode("unload");
     
     if ((!load) && (!unload))
         return;
-    
+
     _data = new FGNasalModelData(_root, path, prop, load, unload, branch);
     
     // register Nasal module to be created and loaded in the main thread.