diff --git a/simgear/scene/model/SGReaderWriterXML.cxx b/simgear/scene/model/SGReaderWriterXML.cxx index 4c6304ac..3cc13eb9 100644 --- a/simgear/scene/model/SGReaderWriterXML.cxx +++ b/simgear/scene/model/SGReaderWriterXML.cxx @@ -56,7 +56,7 @@ using namespace std; using namespace simgear; using namespace osg; -static osg::Node * +static std::tuple sgLoad3DModel_internal(const SGPath& path, const osgDB::Options* options, SGPropertyNode *overlay = 0); @@ -88,8 +88,10 @@ SGReaderWriterXML::readNode(const std::string& name, if (!p.exists()) { return ReadResult::FILE_NOT_FOUND; } - - result=sgLoad3DModel_internal(p, options); + + static std::tuple retval; + int num_anims; + std::tie(num_anims, result) = sgLoad3DModel_internal(p, options); } catch (const sg_exception &t) { SG_LOG(SG_INPUT, SG_ALERT, "Failed to load model: " << t.getFormattedMessage() << "\n\tfrom:" << fileName); @@ -160,13 +162,13 @@ void makeEffectAnimations(PropertyList& animation_nodes, SGPropertyNode* typeProp = animProp->getChild("type"); if (!typeProp) continue; - + const char* typeString = typeProp->getStringValue(); if (!strcmp(typeString, "material")) { effectProp = SGMaterialAnimation::makeEffectProperties(animProp); } else if (!strcmp(typeString, "shader")) { - + SGPropertyNode* shaderProp = animProp->getChild("shader"); if (!shaderProp || strcmp(shaderProp->getStringValue(), "chrome")) continue; @@ -215,7 +217,7 @@ private: osg::Node::NodeMask nodeMaskSet; osg::Node::NodeMask nodeMaskClear; }; - + } namespace { @@ -229,7 +231,7 @@ namespace { return (typeString == "pick") || (typeString == "knob") || (typeString == "slider") || (typeString == "touch"); } }; - + bool removeNamedNode(osg::Group* aGroup, const std::string& aName) { int nKids = aGroup->getNumChildren(); @@ -240,28 +242,28 @@ namespace { return true; } } - + for (int i = 0; i < nKids; i++) { osg::Group* childGroup = aGroup->getChild(i)->asGroup(); if (!childGroup) continue; - + if (removeNamedNode(childGroup, aName)) return true; } // of child groups traversal - + return false; } } -static osg::Node * +static std::tuple sgLoad3DModel_internal(const SGPath& path, const osgDB::Options* dbOptions, SGPropertyNode *overlay) { if (!path.exists()) { SG_LOG(SG_INPUT, SG_ALERT, "Failed to load file: \"" << path << "\""); - return NULL; + return std::make_tuple(0, (osg::Node *) NULL); } osg::ref_ptr options; @@ -270,19 +272,20 @@ sgLoad3DModel_internal(const SGPath& path, SGPath modelpath(path); SGPath texturepath(path); SGPath modelDir(modelpath.dir()); - + int animationcount = 0; + SGSharedPtr prop_root = options->getPropertyNode(); if (!prop_root.valid()) prop_root = new SGPropertyNode; // The model data appear to be only used in the topmost model osg::ref_ptr data = options->getModelData(); options->setModelData(0); - + osg::ref_ptr model; osg::ref_ptr group; SGPropertyNode_ptr props = new SGPropertyNode; bool previewMode = (dbOptions->getPluginStringData("SimGear::PREVIEW") == "ON"); - + // Check for an XML wrapper if (modelpath.extension() == "xml") { try { @@ -296,9 +299,9 @@ sgLoad3DModel_internal(const SGPath& path, copyProperties(overlay, props); if (previewMode && props->hasChild("nopreview")) { - return NULL; + return std::make_tuple(0, (osg::Node *) NULL); } - + if (props->hasValue("/path")) { string modelPathStr = props->getStringValue("/path"); modelpath = SGModelLib::findDataFile(modelPathStr, NULL, modelDir); @@ -399,9 +402,9 @@ sgLoad3DModel_internal(const SGPath& path, SGPath submodelpath; osg::ref_ptr submodel; - + string subPathStr = sub_props->getStringValue("path"); - SGPath submodelPath = SGModelLib::findDataFile(subPathStr, + SGPath submodelPath = SGModelLib::findDataFile(subPathStr, NULL, modelDir); if (submodelPath.isNull()) { @@ -419,14 +422,16 @@ sgLoad3DModel_internal(const SGPath& path, } try { - submodel = sgLoad3DModel_internal(submodelPath, options.get(), + int num_anims; + std::tie(num_anims, submodel) = sgLoad3DModel_internal(submodelPath, options.get(), sub_props->getNode("overlay")); + animationcount += num_anims; } catch (const sg_exception &t) { SG_LOG(SG_INPUT, SG_ALERT, "Failed to load submodel: " << t.getFormattedMessage() << "\n\tfrom:" << t.getOrigin()); continue; } - + if (!submodel) continue; @@ -491,7 +496,7 @@ sgLoad3DModel_internal(const SGPath& path, if (i==0) { if (!texturepath.extension().empty()) texturepath = texturepath.dir(); - + options2->setDatabasePath(texturepath.local8BitStr()); } group->addChild(Particles::appendParticles(particle_nodes[i], @@ -510,13 +515,13 @@ sgLoad3DModel_internal(const SGPath& path, PropertyList effect_nodes = props->getChildren("effect"); PropertyList animation_nodes = props->getChildren("animation"); - + if (previewMode) { PropertyList::iterator it; it = std::remove_if(animation_nodes.begin(), animation_nodes.end(), ExcludeInPreview()); animation_nodes.erase(it, animation_nodes.end()); } - + // Some material animations (eventually all) are actually effects. makeEffectAnimations(animation_nodes, effect_nodes); { @@ -543,13 +548,15 @@ sgLoad3DModel_internal(const SGPath& path, /// OSGFIXME: duh, why not only model????? SGAnimation::animate(modelData); } - + + animationcount += animation_nodes.size(); + if (!needTransform && group->getNumChildren() < 2) { model = group->getChild(0); group->removeChild(model.get()); if (data.valid()) data->modelLoaded(modelpath.utf8Str(), props, model.get()); - return model.release(); + return std::make_tuple(animationcount, model.release()); } if (data.valid()) data->modelLoaded(modelpath.utf8Str(), props, group.get()); @@ -559,6 +566,7 @@ sgLoad3DModel_internal(const SGPath& path, osgDB::writeNodeFile(*group, outputfile); } - return group.release(); -} + SG_LOG(SG_GENERAL, SG_DEBUG, "Model " << path << " animation count: " << animationcount); + return std::make_tuple(animationcount, group.release()); +}