Expose pose of scenery models to Nasal load/unload scripts.
This allows Nasal code attached to scenery models access their world position and orientation by calling _model.getPose(). Also ensure models are attached to the scenegraph before Nasal load scripts are called. This ensures that the world position and orientation are available upon executing the load script.
This commit is contained in:
parent
eba03b5e46
commit
913727239d
4 changed files with 87 additions and 31 deletions
|
@ -3,8 +3,13 @@
|
||||||
#include "NasalSys.hxx"
|
#include "NasalSys.hxx"
|
||||||
#include <Main/globals.hxx>
|
#include <Main/globals.hxx>
|
||||||
|
|
||||||
|
#include <simgear/math/SGMath.hxx>
|
||||||
|
#include <simgear/nasal/cppbind/Ghost.hxx>
|
||||||
|
#include <simgear/scene/util/OsgMath.hxx>
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
|
#include <osg/Transform>
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -18,6 +23,48 @@
|
||||||
unsigned int FGNasalModelData::_max_module_id = 0;
|
unsigned int FGNasalModelData::_max_module_id = 0;
|
||||||
FGNasalModelDataList FGNasalModelData::_loaded_models;
|
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,
|
FGNasalModelData::FGNasalModelData( SGPropertyNode *root,
|
||||||
const std::string& path,
|
const std::string& path,
|
||||||
|
@ -54,7 +101,16 @@ void FGNasalModelData::load()
|
||||||
|
|
||||||
// Add _module_id to script local hash to allow placing canvasses on objects
|
// Add _module_id to script local hash to allow placing canvasses on objects
|
||||||
// inside the model.
|
// inside the model.
|
||||||
nasalSys->getGlobals().createHash(_module).set("_module_id", _module_id);
|
nasal::Hash module = nasalSys->getGlobals().createHash(_module);
|
||||||
|
module.set("_module_id", _module_id);
|
||||||
|
|
||||||
|
if( !NasalNode::isInit() )
|
||||||
|
{
|
||||||
|
NasalNode::init("osg.Node")
|
||||||
|
.method("getPose", &f_node_getPose);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.set("_model", NodeRef(_branch));
|
||||||
|
|
||||||
naRef arg[2];
|
naRef arg[2];
|
||||||
arg[0] = nasalSys->propNodeGhost(_root);
|
arg[0] = nasalSys->propNodeGhost(_root);
|
||||||
|
|
|
@ -76,16 +76,6 @@ naRef to_nasal_helper(naContext c, flightgear::Approach* iap)
|
||||||
return nasal::to_nasal(c, iap->ident());
|
return nasal::to_nasal(c, iap->ident());
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
naRef to_nasal_helper(naContext c, const SGGeod& pos)
|
|
||||||
{
|
|
||||||
nasal::Hash hash(c);
|
|
||||||
hash.set("lat", pos.getLatitudeDeg());
|
|
||||||
hash.set("lon", pos.getLongitudeDeg());
|
|
||||||
hash.set("elevation", pos.getElevationM());
|
|
||||||
return hash.get_naRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
static naRef f_navaid_course(naContext, FGNavRecord& nav)
|
static naRef f_navaid_course(naContext, FGNavRecord& nav)
|
||||||
{
|
{
|
||||||
|
|
|
@ -844,6 +844,9 @@ void FGNasalSys::update(double)
|
||||||
|
|
||||||
if (!_loadList.empty())
|
if (!_loadList.empty())
|
||||||
{
|
{
|
||||||
|
if( _delay_load )
|
||||||
|
_delay_load = false;
|
||||||
|
else
|
||||||
// process Nasal load hook (only one per update loop to avoid excessive lags)
|
// process Nasal load hook (only one per update loop to avoid excessive lags)
|
||||||
_loadList.pop()->load();
|
_loadList.pop()->load();
|
||||||
}
|
}
|
||||||
|
@ -1240,6 +1243,8 @@ naRef FGNasalSys::removeListener(naContext c, int argc, naRef* args)
|
||||||
|
|
||||||
void FGNasalSys::registerToLoad(FGNasalModelData *data)
|
void FGNasalSys::registerToLoad(FGNasalModelData *data)
|
||||||
{
|
{
|
||||||
|
if( _loadList.empty() )
|
||||||
|
_delay_load = true;
|
||||||
_loadList.push(data);
|
_loadList.push(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,6 +134,11 @@ private:
|
||||||
SGLockedQueue<SGSharedPtr<FGNasalModelData> > _loadList;
|
SGLockedQueue<SGSharedPtr<FGNasalModelData> > _loadList;
|
||||||
SGLockedQueue<SGSharedPtr<FGNasalModelData> > _unloadList;
|
SGLockedQueue<SGSharedPtr<FGNasalModelData> > _unloadList;
|
||||||
|
|
||||||
|
// Delay removing items of the _loadList to ensure the are already attached
|
||||||
|
// to the scene graph (eg. enables to retrieve world position in load
|
||||||
|
// callback).
|
||||||
|
bool _delay_load;
|
||||||
|
|
||||||
//
|
//
|
||||||
// FGTimer subclass for handling Nasal timer callbacks.
|
// FGTimer subclass for handling Nasal timer callbacks.
|
||||||
// See the implementation of the settimer() extension function for
|
// See the implementation of the settimer() extension function for
|
||||||
|
|
Loading…
Reference in a new issue