]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/model/SGReaderWriterXML.cxx
Provide something more sensible for the properties root
[simgear.git] / simgear / scene / model / SGReaderWriterXML.cxx
index b952248ad13b065fadb856cb05acc8bb07431e5a..f3fb644ba3ebdb49c07782d092bd0b4779de41c2 100644 (file)
@@ -20,6 +20,7 @@
 #  include <simgear_config.h>
 #endif
 
+#include <osg/MatrixTransform>
 #include <osgDB/WriteFile>
 #include <osgDB/Registry>
 #include <osg/Switch>
 
 using namespace simgear;
 
-osg::Node *
+static osg::Node *
 sgLoad3DModel_internal(const string &path,
                        SGPropertyNode *prop_root,
-                       SGModelData *data=0,
-                       osg::Node *(*load_panel)(SGPropertyNode *) = 0);
+                       SGModelData *data = 0,
+                       osg::Node *(*load_panel)(SGPropertyNode *) = 0,
+                       SGPropertyNode *overlay = 0);
 
-const char* SGReaderWriterXML::className() const
+
+SGReaderWriterXML::SGReaderWriterXML()
+{
+    supportsExtension("xml", "SimGear xml database format");
+}
+
+SGReaderWriterXML::~SGReaderWriterXML()
 {
-    return "XML database reader";
 }
 
-bool SGReaderWriterXML::acceptsExtension(const std::string& extension) const
+const char* SGReaderWriterXML::className() const
 {
-    return (osgDB::equalCaseInsensitive(extension, "xml"));
+    return "XML database reader";
 }
 
 osgDB::ReaderWriter::ReadResult
@@ -68,26 +75,21 @@ SGReaderWriterXML::readNode(const std::string& fileName,
 {
     // SG_LOG(SG_GENERAL, SG_ALERT, "SGReaderWriterXML::readNode(" << fileName << ")");
 
-    std::string ext = osgDB::getLowerCaseFileExtension(fileName);
-    if (!acceptsExtension(ext))
-        return ReadResult::FILE_NOT_HANDLED;
-
     const SGReaderWriterXMLOptions* xmlOptions
     = dynamic_cast<const SGReaderWriterXMLOptions*>(options);
 
-    string fg_root;
-    SGPropertyNode *prop_root=0;
+    SGSharedPtr<SGPropertyNode> prop_root;
     osg::Node *(*load_panel)(SGPropertyNode *)=0;
     SGModelData *model_data=0;
-    SGPath externalTexturePath;
 
     if (xmlOptions) {
         prop_root = xmlOptions->getPropRoot();
         load_panel = xmlOptions->getLoadPanel();
         model_data = xmlOptions->getModelData();
     }
-
-    fg_root=osgDB::Registry::instance()->getDataFilePathList().front();
+    if (!prop_root) {
+        prop_root = new SGPropertyNode;
+    }
 
     osg::Node *result=0;
 
@@ -126,33 +128,44 @@ private:
     SGSharedPtr<SGCondition> mCondition;
 };
 
-osg::Node *
+static osg::Node *
 sgLoad3DModel_internal(const string &path,
                        SGPropertyNode *prop_root,
                        SGModelData *data,
-                       osg::Node *(*load_panel)(SGPropertyNode *))
+                       osg::Node *(*load_panel)(SGPropertyNode *),
+                       SGPropertyNode *overlay)
 {
-    string fg_root=osgDB::Registry::instance()->getDataFilePathList().front();
+    if ( !prop_root ) {
+        SG_LOG(SG_GENERAL, SG_ALERT, "prop_root NULL: " << path);
+    }
+
+    osgDB::FilePathList filePathList;
+    filePathList = osgDB::Registry::instance()->getDataFilePathList();
+    filePathList.push_front(osgDB::convertFileNameToNativeStyle("/"));
+
+    SGPath modelpath = osgDB::findFileInPath(path, filePathList);
+    if (modelpath.str().empty()) {
+        SG_LOG(SG_INPUT, SG_ALERT, "Failed to load file: \"" << path << "\"");
+        return 0;
+    }
+    SGPath texturepath = modelpath;
+
     osg::ref_ptr<osg::Node> model;
     osg::ref_ptr<osg::Group> group;
     SGPropertyNode_ptr props = new SGPropertyNode;
 
-    // Load the 3D object itself
-    SGPath modelpath = path, texturepath = path;
-    if ( !ulIsAbsolutePathName( path.c_str() ) ) {
-        SGPath tmp = fg_root;
-        tmp.append(modelpath.str());
-        modelpath = texturepath = tmp;
-    }
-
     // Check for an XML wrapper
-    if (modelpath.str().substr(modelpath.str().size() - 4, 4) == ".xml") {
-        try {
+    if (modelpath.extension() == "xml") {
+       try {
             readProperties(modelpath.str(), props);
         } catch (const sg_throwable &t) {
-            SG_LOG(SG_INPUT, SG_ALERT, "Failed to load xml: " << t.getFormattedMessage());
+            SG_LOG(SG_INPUT, SG_ALERT, "Failed to load xml: "
+                   << t.getFormattedMessage());
             throw;
         }
+        if (overlay)
+            copyProperties(overlay, props);
+
         if (props->hasValue("/path")) {
             modelpath = modelpath.dir();
             modelpath.append(props->getStringValue("/path"));
@@ -163,16 +176,19 @@ sgLoad3DModel_internal(const string &path,
         } else {
             model = new osg::Node;
         }
+
+        SGPropertyNode *mp = props->getNode("multiplay");
+        if (mp && prop_root && prop_root->getParent())
+            copyProperties(mp, prop_root);
     }
 
-    osg::ref_ptr<osgDB::ReaderWriter::Options> options
-    = new osgDB::ReaderWriter::Options(*osgDB::Registry::instance()
-                                       ->getOptions());
+    osg::ref_ptr<SGReaderWriterXMLOptions> options
+    = new SGReaderWriterXMLOptions(*osgDB::Registry::instance()->getOptions());
 
     // Assume that textures are in
     // the same location as the XML file.
     if (!model) {
-        if (texturepath.extension() != "")
+        if (!texturepath.extension().empty())
             texturepath = texturepath.dir();
 
         options->setDatabasePath(texturepath.str());
@@ -225,7 +241,8 @@ sgLoad3DModel_internal(const string &path,
             submodelpath = submodelFileName;
         }
         try {
-            submodel = sgLoad3DModel_internal(submodelpath.str(), prop_root, 0, load_panel);
+            submodel = sgLoad3DModel_internal(submodelpath.str(), prop_root, 0, load_panel,
+                                              sub_props->getNode("overlay"));
         } catch (const sg_throwable &t) {
             SG_LOG(SG_INPUT, SG_ALERT, "Failed to load submodel: " << t.getFormattedMessage());
             throw;
@@ -284,7 +301,7 @@ sgLoad3DModel_internal(const string &path,
     particle_nodes = props->getChildren("particlesystem");
     for (unsigned i = 0; i < particle_nodes.size(); ++i) {
         if (i==0) {
-            if (texturepath.extension() != "")
+            if (!texturepath.extension().empty())
                 texturepath = texturepath.dir();
 
             options->setDatabasePath(texturepath.str());
@@ -295,10 +312,7 @@ sgLoad3DModel_internal(const string &path,
     }
 
     if (data) {
-        SGPropertyNode *nasal = props->getNode("nasal", false);
-        data->setProps(nasal);
-        group->setUserData(data);
-        //data->modelLoaded(path, nasal, group.get());
+        options->setModelData(data);
     }
 
     std::vector<SGPropertyNode_ptr> animation_nodes;
@@ -308,17 +322,17 @@ sgLoad3DModel_internal(const string &path,
         SGAnimation::animate(group.get(), animation_nodes[i], prop_root,
                              options.get());
 
-    if (props->hasChild("debug-outfile")) {
-        std::string outputfile = props->getStringValue("debug-outfile",
-                                 "debug-model.osg");
-        osgDB::writeNodeFile(*group, outputfile);
-    }
     if (!needTransform && group->getNumChildren() < 2) {
         model = group->getChild(0);
         group->removeChild(model.get());
         model->setUserData(group->getUserData());
         return model.release();
     }
+    if (props->hasChild("debug-outfile")) {
+        std::string outputfile = props->getStringValue("debug-outfile",
+                                 "debug-model.osg");
+        osgDB::writeNodeFile(*group, outputfile);
+    }
 
     return group.release();
 }