diff --git a/projects/VC7.1/SimGear.vcproj b/projects/VC7.1/SimGear.vcproj
index 36dc8e09..bc1a2b66 100755
--- a/projects/VC7.1/SimGear.vcproj
+++ b/projects/VC7.1/SimGear.vcproj
@@ -1231,6 +1231,12 @@
+
+
+
+
diff --git a/projects/VC90/SimGear.vcproj b/projects/VC90/SimGear.vcproj
index bf0336bb..eab43855 100644
--- a/projects/VC90/SimGear.vcproj
+++ b/projects/VC90/SimGear.vcproj
@@ -1785,6 +1785,14 @@
RelativePath="..\..\simgear\scene\util\SGUpdateVisitor.hxx"
>
+
+
+
+
diff --git a/simgear/scene/util/Makefile.am b/simgear/scene/util/Makefile.am
index 567ec697..8ac69565 100644
--- a/simgear/scene/util/Makefile.am
+++ b/simgear/scene/util/Makefile.am
@@ -18,6 +18,7 @@ include_HEADERS = \
PrimitiveUtils.hxx \
QuadTreeBuilder.hxx \
RenderConstants.hxx \
+ SplicingVisitor.hxx \
StateAttributeFactory.hxx \
VectorArrayAdapter.hxx
@@ -30,6 +31,7 @@ libsgutil_a_SOURCES = \
SGTextureStateAttributeVisitor.cxx \
NodeAndDrawableVisitor.cxx \
PrimitiveUtils.cxx \
+ SplicingVisitor.cxx \
StateAttributeFactory.cxx \
QuadTreeBuilder.cxx
diff --git a/simgear/scene/util/SplicingVisitor.cxx b/simgear/scene/util/SplicingVisitor.cxx
new file mode 100644
index 00000000..66558377
--- /dev/null
+++ b/simgear/scene/util/SplicingVisitor.cxx
@@ -0,0 +1,113 @@
+#include "SplicingVisitor.hxx"
+
+namespace simgear
+{
+using namespace osg;
+
+SplicingVisitor::SplicingVisitor()
+ : NodeVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN)
+{
+ _childStack.push_back(NodeList());
+}
+
+void SplicingVisitor::reset()
+{
+ _childStack.clear();
+ NodeVisitor::reset();
+}
+
+NodeList SplicingVisitor::traverse(Node& node)
+{
+ NodeList result;
+ _childStack.push_back(NodeList());
+ NodeVisitor::traverse(node);
+ result = _childStack.back();
+ _childStack.pop_back();
+ return result;
+}
+void SplicingVisitor::apply(Node& node)
+{
+ NodeVisitor::traverse(node);
+ pushNode(&node);
+}
+
+void SplicingVisitor::apply(Group& node)
+{
+ if (pushNode(getNewNode(node)))
+ return;
+ pushResultNode(&node, &node, traverse(node));
+}
+
+Group* SplicingVisitor::pushResultNode(Group* node, Group* newNode,
+ const NodeList& children)
+{
+ ref_ptr result;
+ if (node == newNode) {
+ result = copyIfNeeded(*node, children);
+ } else {
+ result = newNode;
+ for (NodeList::const_iterator itr = children.begin(), end = children.end();
+ itr != end;
+ ++itr)
+ result->addChild(itr->get());
+ }
+ _childStack.back().push_back(result);
+ recordNewNode(node, result);
+ return result;
+}
+
+Node* SplicingVisitor::pushResultNode(Node* node, Node* newNode)
+{
+ _childStack.back().push_back(newNode);
+ recordNewNode(node, newNode);
+ return newNode;
+}
+
+Node* SplicingVisitor::pushNode(Node* node)
+{
+ if (node)
+ _childStack.back().push_back(node);
+ return node;
+}
+
+Node* SplicingVisitor::getResult()
+{
+ NodeList& top = _childStack.at(0);
+ if (top.empty()) {
+ return 0;
+ } else if (top.size() == 1) {
+ return top[0].get();
+ } else {
+ Group* result = new Group;
+ for (NodeList::iterator itr = top.begin(), end = top.end();
+ itr != end;
+ ++itr)
+ result->addChild(itr->get());
+ return result;
+ }
+}
+
+Node* SplicingVisitor::getNewNode(osg::Node* node)
+{
+ ref_ptr tmpPtr(node);
+ NodeMap::iterator itr;
+ try {
+ itr = _visited.find(tmpPtr);
+ }
+ catch (...) {
+ tmpPtr.release();
+ throw;
+ }
+ if (itr == _visited.end())
+ return 0;
+ else
+ return itr->second.get();
+}
+
+bool SplicingVisitor::recordNewNode(osg::Node* oldNode, osg::Node* newNode)
+{
+ ref_ptr oldTmp(oldNode);
+ ref_ptr newTmp(newNode);
+ return _visited.insert(std::make_pair(oldTmp, newTmp)).second;
+}
+}
diff --git a/simgear/scene/util/SplicingVisitor.hxx b/simgear/scene/util/SplicingVisitor.hxx
new file mode 100644
index 00000000..8757e941
--- /dev/null
+++ b/simgear/scene/util/SplicingVisitor.hxx
@@ -0,0 +1,93 @@
+#ifndef SIMGEAR_SPLICINGVISITOR_HXX
+#define SIMGEAR_SPLICINGVISITOR_HXX 1
+
+#include
+#include