]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/model/SGReaderWriterXML.cxx
support osgText in models. See docs/README.osgtext for details
[simgear.git] / simgear / scene / model / SGReaderWriterXML.cxx
index abdac8d0f68e43ba0fff2ecaf6680e5b35279ab5..31c0c56dddaf42ad27e0589a78851e9a30cc2539 100644 (file)
 #include "animation.hxx"
 #include "particles.hxx"
 #include "model.hxx"
-
-#include "SGReaderWriterXMLOptions.hxx"
-#include "SGReaderWriterXML.hxx"
+#include "SGText.hxx"
 
 using namespace simgear;
 
 static osg::Node *
-sgLoad3DModel_internal(const string &path,
-                       SGPropertyNode *prop_root,
-                       SGModelData *data = 0,
-                       osg::Node *(*load_panel)(SGPropertyNode *) = 0,
+sgLoad3DModel_internal(const std::string& path,
+                       const osgDB::ReaderWriter::Options* options,
                        SGPropertyNode *overlay = 0);
 
-const char* SGReaderWriterXML::className() const
+
+SGReaderWriterXML::SGReaderWriterXML()
 {
-    return "XML database reader";
+    supportsExtension("xml", "SimGear xml database format");
 }
 
-bool SGReaderWriterXML::acceptsExtension(const std::string& extension) const
+SGReaderWriterXML::~SGReaderWriterXML()
 {
-    return (osgDB::equalCaseInsensitive(extension, "xml"));
+}
+
+const char* SGReaderWriterXML::className() const
+{
+    return "XML database reader";
 }
 
 osgDB::ReaderWriter::ReadResult
 SGReaderWriterXML::readNode(const std::string& fileName,
                             const osgDB::ReaderWriter::Options* options) const
 {
-    // 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;
-    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();
-
     osg::Node *result=0;
-
     try {
-        result=sgLoad3DModel_internal(fileName, prop_root, model_data, load_panel);
+        result=sgLoad3DModel_internal(fileName, options);
     } catch (const sg_throwable &t) {
         SG_LOG(SG_INPUT, SG_ALERT, "Failed to load model: " << t.getFormattedMessage());
         result=new osg::Node;
@@ -130,34 +107,47 @@ private:
 
 static osg::Node *
 sgLoad3DModel_internal(const string &path,
-                       SGPropertyNode *prop_root,
-                       SGModelData *data,
-                       osg::Node *(*load_panel)(SGPropertyNode *),
+                       const osgDB::ReaderWriter::Options* options_,
                        SGPropertyNode *overlay)
 {
-    if ( !prop_root ) {
-        SG_LOG(SG_GENERAL, SG_ALERT, "prop_root NULL: " << path);
+    const SGReaderWriterXMLOptions* xmlOptions;
+    xmlOptions = dynamic_cast<const SGReaderWriterXMLOptions*>(options_);
+
+    SGSharedPtr<SGPropertyNode> prop_root;
+    osg::Node *(*load_panel)(SGPropertyNode *)=0;
+    osg::ref_ptr<SGModelData> data;
+
+    if (xmlOptions) {
+        prop_root = xmlOptions->getPropRoot();
+        load_panel = xmlOptions->getLoadPanel();
+        data = xmlOptions->getModelData();
+    }
+    if (!prop_root) {
+        prop_root = new SGPropertyNode;
     }
 
-    string fg_root=osgDB::Registry::instance()->getDataFilePathList().front();
+    osgDB::FilePathList filePathList;
+    filePathList = osgDB::Registry::instance()->getDataFilePathList();
+    filePathList.push_front(std::string());
+
+    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)
@@ -179,14 +169,15 @@ sgLoad3DModel_internal(const string &path,
             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(*options_);
+    options->setPropRoot(prop_root);
+    options->setLoadPanel(load_panel);
 
     // 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());
@@ -203,6 +194,7 @@ sgLoad3DModel_internal(const string &path,
     if (offsets) {
         needTransform=true;
         osg::MatrixTransform *alignmainmodel = new osg::MatrixTransform;
+        alignmainmodel->setDataVariance(osg::Object::STATIC);
         osg::Matrix res_matrix;
         res_matrix.makeRotate(
             offsets->getFloatValue("pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS,
@@ -238,8 +230,12 @@ sgLoad3DModel_internal(const string &path,
         } else {
             submodelpath = submodelFileName;
         }
+        osg::ref_ptr<SGReaderWriterXMLOptions> options;
+        options = new SGReaderWriterXMLOptions(*options_);
+        options->setPropRoot(prop_root);
+        options->setLoadPanel(load_panel);
         try {
-            submodel = sgLoad3DModel_internal(submodelpath.str(), prop_root, 0, load_panel,
+            submodel = sgLoad3DModel_internal(submodelpath.str(), options.get(),
                                               sub_props->getNode("overlay"));
         } catch (const sg_throwable &t) {
             SG_LOG(SG_INPUT, SG_ALERT, "Failed to load submodel: " << t.getFormattedMessage());
@@ -251,6 +247,7 @@ sgLoad3DModel_internal(const string &path,
         if (offs) {
             osg::Matrix res_matrix;
             osg::ref_ptr<osg::MatrixTransform> align = new osg::MatrixTransform;
+            align->setDataVariance(osg::Object::STATIC);
             res_matrix.makeIdentity();
             res_matrix.makeRotate(
                 offs->getDoubleValue("pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS,
@@ -290,7 +287,7 @@ sgLoad3DModel_internal(const string &path,
             SG_LOG(SG_INPUT, SG_DEBUG, "Loading a panel");
             osg::ref_ptr<osg::Node> panel = load_panel(panel_nodes[i]);
             if (panel_nodes[i]->hasValue("name"))
-                panel->setName((char *)panel_nodes[i]->getStringValue("name"));
+                panel->setName(panel_nodes[i]->getStringValue("name"));
             group->addChild(panel.get());
         }
     }
@@ -299,7 +296,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());
@@ -309,9 +306,12 @@ sgLoad3DModel_internal(const string &path,
                         options.get()));
     }
 
-    if (data) {
-        data->setProps(props);
-        group->setUserData(data);
+    std::vector<SGPropertyNode_ptr> text_nodes;
+    text_nodes = props->getChildren("text");
+    for (unsigned i = 0; i < text_nodes.size(); ++i) {
+        group->addChild(SGText::appendText(text_nodes[i],
+                        prop_root,
+                        options.get()));
     }
 
     std::vector<SGPropertyNode_ptr> animation_nodes;
@@ -321,17 +321,20 @@ 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());
+        if (data.valid())
+            data->modelLoaded(modelpath.str(), props, model.get());
         return model.release();
     }
+    if (data.valid())
+        data->modelLoaded(modelpath.str(), props, group.get());
+    if (props->hasChild("debug-outfile")) {
+        std::string outputfile = props->getStringValue("debug-outfile",
+                                 "debug-model.osg");
+        osgDB::writeNodeFile(*group, outputfile);
+    }
 
     return group.release();
 }