]> git.mxchange.org Git - simgear.git/commitdiff
Fix new livery code
authortimoore <timoore>
Thu, 24 Apr 2008 22:06:06 +0000 (22:06 +0000)
committertimoore <timoore>
Thu, 24 Apr 2008 22:06:06 +0000 (22:06 +0000)
It turns out that the database pager causes the texture image to be
unloaded after it is applied, so the image and its file name may not
be available for doing the livery substitution. Ask a work around we
set the name of the texture to its file name.

simgear/scene/model/ModelRegistry.cxx
simgear/scene/model/ModelRegistry.hxx
simgear/scene/util/NodeAndDrawableVisitor.hxx

index a1f49f2a911d9e51013c7935d75ec59bc9f0c057..fcff15eb1d8c5ab950fc60c018c6b66707db1c36 100644 (file)
@@ -79,11 +79,57 @@ private:
   ref_ptr<Referenced> mReferenced;
 };
 
+// Set the name of a Texture to the simple name of its image
+// file. This can be used to do livery substitution after the image
+// has been deallocated.
+class TextureNameVisitor  : public NodeAndDrawableVisitor {
+public:
+    TextureNameVisitor(NodeVisitor::TraversalMode tm = NodeVisitor::TRAVERSE_ALL_CHILDREN) :
+        NodeAndDrawableVisitor(tm)
+    {
+    }
+
+    virtual void apply(Node& node)
+    {
+        nameTextures(node.getStateSet());
+        traverse(node);
+    }
+
+    virtual void apply(Drawable& drawable)
+    {
+        nameTextures(drawable.getStateSet());
+    }
+protected:
+    void nameTextures(StateSet* stateSet)
+    {
+        if (!stateSet)
+            return;
+        int numUnits = stateSet->getTextureAttributeList().size();
+        for (int i = 0; i < numUnits; ++i) {
+            StateAttribute* attr
+                = stateSet->getTextureAttribute(i, StateAttribute::TEXTURE);
+            Texture2D* texture = dynamic_cast<Texture2D*>(attr);
+            if (!texture || !texture->getName().empty())
+                continue;
+            const Image *image = texture->getImage();
+            if (!image)
+                continue;
+            texture->setName(image->getFileName());
+        }
+    }
+};
+
 // Change the StateSets of a model to hold different textures based on
 // a livery path.
+
 class TextureUpdateVisitor : public NodeAndDrawableVisitor {
 public:
-    TextureUpdateVisitor(const FilePathList& pathList) : _pathList(pathList) {}
+    TextureUpdateVisitor(const FilePathList& pathList) :
+        NodeAndDrawableVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN),
+        _pathList(pathList)
+    {
+    }
+    
     virtual void apply(Node& node)
     {
         StateSet* stateSet = cloneStateSet(node.getStateSet());
@@ -98,7 +144,7 @@ public:
         if (stateSet)
             drawable.setStateSet(stateSet);
     }
-    // Copied whole from Mathias' earlier SGTextureUpdateVisitor
+    // Copied from Mathias' earlier SGTextureUpdateVisitor
 protected:
     Texture2D* textureReplace(int unit, const StateAttribute* attr)
     {
@@ -107,24 +153,27 @@ protected:
         if (!texture)
             return 0;
     
-        const Image* image = texture->getImage(0);
-        if (!image)
-            return 0;
+        const Image* image = texture->getImage();
+        const string* fullFilePath = 0;
+        if (image) {
+            // The currently loaded file name
+            fullFilePath = &image->getFileName();
 
-        // The currently loaded file name
-        const string& fullFilePath = image->getFileName();
+        } else {
+            fullFilePath = &texture->getName();
+        }
         // The short name
-        string fileName = getSimpleFileName(fullFilePath);
+        string fileName = getSimpleFileName(*fullFilePath);
+        if (fileName.empty())
+            return 0;
         // The name that should be found with the current database path
         string fullLiveryFile = findFileInPath(fileName, _pathList);
         // If it is empty or they are identical then there is nothing to do
-        if (fullLiveryFile.empty() || fullLiveryFile == fullFilePath)
+        if (fullLiveryFile.empty() || fullLiveryFile == *fullFilePath)
             return 0;
-
         Image* newImage = readImageFile(fullLiveryFile);
         if (!newImage)
             return 0;
-
         CopyOp copyOp(CopyOp::DEEP_COPY_ALL & ~CopyOp::DEEP_COPY_IMAGES);
         Texture2D* newTexture = static_cast<Texture2D*>(copyOp(texture));
         if (!newTexture) {
@@ -134,6 +183,7 @@ protected:
             return newTexture;
         }
     }
+    
     StateSet* cloneStateSet(const StateSet* stateSet)
     {
         typedef pair<int, Texture2D*> Tex2D;
@@ -262,6 +312,14 @@ struct OptionsPusher {
 };
 } // namespace
 
+Node* DefaultProcessPolicy::process(Node* node, const string& filename,
+                                    const ReaderWriter::Options* opt)
+{
+    TextureNameVisitor nameVisitor;
+    node->accept(nameVisitor);
+    return node;
+}
+
 ReaderWriter::ReadResult
 ModelRegistry::readImage(const string& fileName,
                          const ReaderWriter::Options* opt)
index e14292680f9d4808c58eaf9db4b8a183874d5994..14231763f83ace872f2d3689d1a921d9632e01c3 100644 (file)
@@ -128,10 +128,7 @@ protected:
 struct DefaultProcessPolicy {
     DefaultProcessPolicy(const std::string& extension) {}
     osg::Node* process(osg::Node* node, const std::string& filename,
-                       const osgDB::ReaderWriter::Options* opt)
-    {
-        return node;
-    }
+                       const osgDB::ReaderWriter::Options* opt);
 };
 
 struct DefaultCachePolicy {
index cb780d9311fdb3b6a8ab8413dfdb4e419e0ff074..7f4d8c29b0fa607990a46f5dc0fd04015dc2b1fd 100644 (file)
@@ -31,9 +31,9 @@ namespace simgear
 class NodeAndDrawableVisitor : public osg::NodeVisitor
 {
 public:
-    NodeAndDrawableVisitor(osg::NodeVisitor::TraversalMode tm = osg::NodeVisitor::TRAVERSE_NONE);
+    NodeAndDrawableVisitor(osg::NodeVisitor::TraversalMode tm);
     NodeAndDrawableVisitor(osg::NodeVisitor::VisitorType type,
-                           osg::NodeVisitor::TraversalMode tm = osg::NodeVisitor::TRAVERSE_NONE);
+                           osg::NodeVisitor::TraversalMode tm);
     virtual ~NodeAndDrawableVisitor();
     using osg::NodeVisitor::apply;
     virtual void apply(osg::Node& node);