X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FScripting%2FNasalModelData.cxx;h=20df177ad590e39d97bd7e808606be37ddfe3944;hb=36f7ef93aa4a08a2bb37d04cb1fac0424105e895;hp=82fd3b69c6d40b1df8cc6b268afceb848c6180a1;hpb=7b663cd7f7aaceb185a5970b5ea43f8445cc58f1;p=flightgear.git diff --git a/src/Scripting/NasalModelData.cxx b/src/Scripting/NasalModelData.cxx index 82fd3b69c..20df177ad 100644 --- a/src/Scripting/NasalModelData.cxx +++ b/src/Scripting/NasalModelData.cxx @@ -1,70 +1,202 @@ #include "NasalModelData.hxx" +#include "NasalSys.hxx" +#include
+#include
+#include +#include +#include +#include #include -#include "NasalSys.hxx" -#include
+#include + +#include +#include +#include // for strlen // FGNasalModelData class. If sgLoad3DModel() is called with a pointer to // such a class, then it lets modelLoaded() run the script, and the // destructor the script. The latter happens when the model branch // is removed from the scene graph. -unsigned int FGNasalModelData::_module_id = 0; +unsigned int FGNasalModelData::_max_module_id = 0; +FGNasalModelDataList FGNasalModelData::_loaded_models; + +typedef osg::ref_ptr NodeRef; +typedef nasal::Ghost 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, + SGPropertyNode *prop, + SGPropertyNode* load, + SGPropertyNode* unload, + osg::Node* branch ): + _path(path), + _root(root), _prop(prop), + _load(load), _unload(unload), + _branch(branch), + _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"); - - 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); } +//------------------------------------------------------------------------------ void FGNasalModelData::unload() { if (_module.empty()) return; - + FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal"); if(!nasalSys) { SG_LOG(SG_NASAL, SG_WARN, "Trying to run an script " "without Nasal subsystem present."); return; } - + SG_LOG(SG_NASAL, SG_DEBUG, "Unloading nasal module " << _module.c_str()); - + if (_unload) { const char *s = _unload->getStringValue(); nasalSys->createModule(_module.c_str(), _module.c_str(), s, strlen(s), _root); } - + nasalSys->deleteModule(_module.c_str()); } -void FGNasalModelDataProxy::modelLoaded(const std::string& path, SGPropertyNode *prop, - osg::Node *) +//------------------------------------------------------------------------------ +osg::Node* FGNasalModelData::getNode() +{ + return _branch.get(); +} + +//------------------------------------------------------------------------------ +FGNasalModelData* FGNasalModelData::getByModuleId(unsigned int id) +{ + FGNasalModelDataList::iterator it = std::find_if + ( + _loaded_models.begin(), + _loaded_models.end(), + boost::bind(&FGNasalModelData::_module_id, _1) == id + ); + + if( it != _loaded_models.end() ) + return *it; + + return 0; +} + +//------------------------------------------------------------------------------ +FGNasalModelDataProxy::~FGNasalModelDataProxy() { FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal"); - if(!nasalSys) { - SG_LOG(SG_NASAL, SG_WARN, "Trying to run a script " - "without Nasal subsystem present."); + // when necessary, register Nasal module to be destroyed/unloaded + // in the main thread. + if ((_data.valid())&&(nasalSys)) + nasalSys->registerToUnload(_data); +} + +//------------------------------------------------------------------------------ +void FGNasalModelDataProxy::modelLoaded( const std::string& path, + SGPropertyNode *prop, + osg::Node *branch ) +{ + if( fgGetBool("/sim/disable-embedded-nasal") ) return; - } - + if(!prop) return; @@ -72,23 +204,26 @@ void FGNasalModelDataProxy::modelLoaded(const std::string& path, SGPropertyNode 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); + + _data = new FGNasalModelData(_root, path, prop, load, unload, branch); // register Nasal module to be created and loaded in the main thread. nasalSys->registerToLoad(_data); } - -FGNasalModelDataProxy::~FGNasalModelDataProxy() -{ - FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal"); - // when necessary, register Nasal module to be destroyed/unloaded - // in the main thread. - if ((_data.valid())&&(nasalSys)) - nasalSys->registerToUnload(_data); -}