diff --git a/projects/VC7.1/SimGear.vcproj b/projects/VC7.1/SimGear.vcproj
index f9c17d42..96ddc4ce 100755
--- a/projects/VC7.1/SimGear.vcproj
+++ b/projects/VC7.1/SimGear.vcproj
@@ -1163,6 +1163,12 @@
+
+
+
+
diff --git a/simgear/scene/model/ModelRegistry.cxx b/simgear/scene/model/ModelRegistry.cxx
index 5d123109..a1f49f2a 100644
--- a/simgear/scene/model/ModelRegistry.cxx
+++ b/simgear/scene/model/ModelRegistry.cxx
@@ -19,6 +19,8 @@
#include "ModelRegistry.hxx"
#include
+#include
+#include
#include
@@ -41,6 +43,7 @@
#include
#include
#include
+#include
#include
#include
@@ -76,71 +79,94 @@ private:
ref_ptr mReferenced;
};
-// Visitor for
-class SGTextureUpdateVisitor : public SGTextureStateAttributeVisitor {
+// Change the StateSets of a model to hold different textures based on
+// a livery path.
+class TextureUpdateVisitor : public NodeAndDrawableVisitor {
public:
- SGTextureUpdateVisitor(const FilePathList& pathList) :
- mPathList(pathList)
- { }
- Texture2D* textureReplace(int unit,
- StateSet::RefAttributePair& refAttr)
- {
- Texture2D* texture;
- texture = dynamic_cast(refAttr.first.get());
- if (!texture)
- return 0;
-
- ref_ptr image = texture->getImage(0);
- if (!image)
- return 0;
-
- // The currently loaded file name
- string fullFilePath = image->getFileName();
- // The short name
- string fileName = getSimpleFileName(fullFilePath);
- // The name that should be found with the current database path
- string fullLiveryFile = findFileInPath(fileName, mPathList);
- // If it is empty or they are identical then there is nothing to do
- if (fullLiveryFile.empty() || fullLiveryFile == fullFilePath)
- return 0;
-
- image = readImageFile(fullLiveryFile);
- if (!image)
- return 0;
-
- CopyOp copyOp(CopyOp::DEEP_COPY_ALL & ~CopyOp::DEEP_COPY_IMAGES);
- texture = static_cast(copyOp(texture));
- if (!texture)
- return 0;
- texture->setImage(image.get());
- return texture;
- }
- virtual void apply(StateSet* stateSet)
- {
- if (!stateSet)
- return;
-
- // get a copy that we can safely modify the statesets values.
- StateSet::TextureAttributeList attrList;
- attrList = stateSet->getTextureAttributeList();
- for (unsigned unit = 0; unit < attrList.size(); ++unit) {
- StateSet::AttributeList::iterator i = attrList[unit].begin();
- while (i != attrList[unit].end()) {
- Texture2D* texture = textureReplace(unit, i->second);
- if (texture) {
- stateSet->removeTextureAttribute(unit, i->second.first.get());
- stateSet->setTextureAttribute(unit, texture, i->second.second);
- stateSet->setTextureMode(unit, GL_TEXTURE_2D, StateAttribute::ON);
- }
- ++i;
- }
+ TextureUpdateVisitor(const FilePathList& pathList) : _pathList(pathList) {}
+ virtual void apply(Node& node)
+ {
+ StateSet* stateSet = cloneStateSet(node.getStateSet());
+ if (stateSet)
+ node.setStateSet(stateSet);
+ traverse(node);
}
- }
+ virtual void apply(Drawable& drawable)
+ {
+ StateSet* stateSet = cloneStateSet(drawable.getStateSet());
+ if (stateSet)
+ drawable.setStateSet(stateSet);
+ }
+ // Copied whole from Mathias' earlier SGTextureUpdateVisitor
+protected:
+ Texture2D* textureReplace(int unit, const StateAttribute* attr)
+ {
+ const Texture2D* texture = dynamic_cast(attr);
+
+ if (!texture)
+ return 0;
+
+ const Image* image = texture->getImage(0);
+ if (!image)
+ return 0;
+
+ // The currently loaded file name
+ const string& fullFilePath = image->getFileName();
+ // The short name
+ string fileName = getSimpleFileName(fullFilePath);
+ // 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)
+ return 0;
+
+ Image* newImage = readImageFile(fullLiveryFile);
+ if (!newImage)
+ return 0;
+
+ CopyOp copyOp(CopyOp::DEEP_COPY_ALL & ~CopyOp::DEEP_COPY_IMAGES);
+ Texture2D* newTexture = static_cast(copyOp(texture));
+ if (!newTexture) {
+ return 0;
+ } else {
+ newTexture->setImage(newImage);
+ return newTexture;
+ }
+ }
+ StateSet* cloneStateSet(const StateSet* stateSet)
+ {
+ typedef pair Tex2D;
+ vector newTextures;
+ StateSet* result = 0;
+
+ if (!stateSet)
+ return 0;
+ int numUnits = stateSet->getTextureAttributeList().size();
+ if (numUnits > 0) {
+ for (int i = 0; i < numUnits; ++i) {
+ const StateAttribute* attr
+ = stateSet->getTextureAttribute(i, StateAttribute::TEXTURE);
+ Texture2D* newTexture = textureReplace(i, attr);
+ if (newTexture)
+ newTextures.push_back(Tex2D(i, newTexture));
+ }
+ if (!newTextures.empty()) {
+ result = static_cast(stateSet->clone(CopyOp()));
+ for (vector::iterator i = newTextures.begin();
+ i != newTextures.end();
+ ++i) {
+ result->setTextureAttribute(i->first, i->second);
+ }
+ }
+ }
+ return result;
+ }
private:
- FilePathList mPathList;
+ FilePathList _pathList;
};
+
class SGTexCompressionVisitor : public SGTextureStateAttributeVisitor {
public:
virtual void apply(int, StateSet::RefAttributePair& refAttr)
@@ -352,8 +378,9 @@ osg::Node* DefaultCopyPolicy::copy(osg::Node* model, const string& fileName,
res->addObserver(databaseReference);
// Update liveries
- SGTextureUpdateVisitor liveryUpdate(opt->getDatabasePathList());
+ TextureUpdateVisitor liveryUpdate(opt->getDatabasePathList());
res->accept(liveryUpdate);
+
return res;
}
diff --git a/simgear/scene/util/Makefile.am b/simgear/scene/util/Makefile.am
index 121900a5..28af3fdc 100644
--- a/simgear/scene/util/Makefile.am
+++ b/simgear/scene/util/Makefile.am
@@ -14,6 +14,7 @@ include_HEADERS = \
SGStateAttributeVisitor.hxx \
SGTextureStateAttributeVisitor.hxx \
SGUpdateVisitor.hxx \
+ NodeAndDrawableVisitor.hxx \
QuadTreeBuilder.hxx \
RenderConstants.hxx \
StateAttributeFactory.hxx \
@@ -26,6 +27,7 @@ libsgutil_a_SOURCES = \
SGSceneUserData.cxx \
SGStateAttributeVisitor.cxx \
SGTextureStateAttributeVisitor.cxx \
+ NodeAndDrawableVisitor.cxx \
StateAttributeFactory.cxx \
QuadTreeBuilder.cxx
diff --git a/simgear/scene/util/NodeAndDrawableVisitor.cxx b/simgear/scene/util/NodeAndDrawableVisitor.cxx
new file mode 100644
index 00000000..257171c7
--- /dev/null
+++ b/simgear/scene/util/NodeAndDrawableVisitor.cxx
@@ -0,0 +1,73 @@
+/* -*-c++-*-
+ *
+ * Copyright (C) 2008 Tim Moore
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#include
+#include
+
+#include "NodeAndDrawableVisitor.hxx"
+
+namespace simgear
+{
+using namespace osg;
+
+NodeAndDrawableVisitor::NodeAndDrawableVisitor(NodeVisitor::TraversalMode tm) :
+ NodeVisitor(tm)
+{
+}
+
+NodeAndDrawableVisitor::NodeAndDrawableVisitor(NodeVisitor::VisitorType type,
+ NodeVisitor::TraversalMode tm) :
+ NodeVisitor(type, tm)
+{
+}
+
+NodeAndDrawableVisitor::~NodeAndDrawableVisitor()
+{
+}
+
+void NodeAndDrawableVisitor::apply(Node& node)
+{
+ traverse(node);
+}
+
+void NodeAndDrawableVisitor::apply(Drawable& Drawable)
+{
+}
+
+void NodeAndDrawableVisitor::traverse(Node& node)
+{
+ TraversalMode tm = getTraversalMode();
+ if (tm == TRAVERSE_NONE) {
+ return;
+ } else if (tm == TRAVERSE_PARENTS) {
+ NodeVisitor::traverse(node);
+ return;
+ }
+ Geode* geode = dynamic_cast(&node);
+ if (geode) {
+ unsigned numDrawables = geode->getNumDrawables();
+ for (unsigned i = 0; i < numDrawables; ++i)
+ apply(*geode->getDrawable(i));
+ } else {
+ NodeVisitor::traverse(node);
+ }
+}
+}
diff --git a/simgear/scene/util/NodeAndDrawableVisitor.hxx b/simgear/scene/util/NodeAndDrawableVisitor.hxx
new file mode 100644
index 00000000..cb780d93
--- /dev/null
+++ b/simgear/scene/util/NodeAndDrawableVisitor.hxx
@@ -0,0 +1,51 @@
+/* -*-c++-*-
+ *
+ * Copyright (C) 2008 Tim Moore
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+#ifndef SIMGEAR_NODEANDDRAWABLEVISITOR_HXX
+#define SIMGEAR_NODEANDDRAWABLEVISITOR_HXX 1
+
+#include
+#include
+
+namespace simgear
+{
+/** A node visitor that descends into Drawables too.
+ */
+class NodeAndDrawableVisitor : public osg::NodeVisitor
+{
+public:
+ NodeAndDrawableVisitor(osg::NodeVisitor::TraversalMode tm = osg::NodeVisitor::TRAVERSE_NONE);
+ NodeAndDrawableVisitor(osg::NodeVisitor::VisitorType type,
+ osg::NodeVisitor::TraversalMode tm = osg::NodeVisitor::TRAVERSE_NONE);
+ virtual ~NodeAndDrawableVisitor();
+ using osg::NodeVisitor::apply;
+ virtual void apply(osg::Node& node);
+ /** Visit a Drawable node. Note that you cannot write an apply()
+ method with an argument that is a subclass of Drawable and expect
+ it to be called, because this visitor can't add the double dispatch
+ machinery of NodeVisitor to the existing OSG Drawable subclasses.
+ */
+ virtual void apply(osg::Drawable& drawable);
+ // hides NodeVisitor::traverse
+ void traverse(osg::Node& node);
+};
+
+}
+#endif
diff --git a/simgear/screen/TestRenderTexture.cpp b/simgear/screen/TestRenderTexture.cpp
index 490e41e9..2c7fc236 100644
--- a/simgear/screen/TestRenderTexture.cpp
+++ b/simgear/screen/TestRenderTexture.cpp
@@ -16,6 +16,7 @@
#include
#include
+#include
void Reshape(int w, int h);