00001 #ifndef SIMGEAR_SPLICINGVISITOR_HXX
00002 #define SIMGEAR_SPLICINGVISITOR_HXX 1
00003
00004 #include <cstddef>
00005 #include <map>
00006 #include <vector>
00007 #include <osg/NodeVisitor>
00008 #include <osg/Group>
00009
00010 namespace simgear
00011 {
00012 class SplicingVisitor : public osg::NodeVisitor
00013 {
00014 public:
00015 META_NodeVisitor(simgear,SplicingVisitor);
00016 SplicingVisitor();
00017 virtual ~SplicingVisitor() {}
00018 virtual void reset();
00019 osg::NodeList traverse(osg::Node& node);
00020 using osg::NodeVisitor::apply;
00021 virtual void apply(osg::Node& node);
00022 virtual void apply(osg::Group& node);
00023 template<typename T>
00024 static T* copyIfNeeded(T& node, const osg::NodeList& children);
00025 template<typename T>
00026 static T* copy(T& node, const osg::NodeList& children);
00034 osg::Group* pushResultNode(osg::Group* node, osg::Group* newNode,
00035 const osg::NodeList& children);
00042 osg::Node* pushResultNode(osg::Node* node, osg::Node* newNode);
00046 osg::Node* pushNode(osg::Node* node);
00047 osg::Node* getResult();
00048 osg::Node* getNewNode(osg::Node& node)
00049 {
00050 return getNewNode(&node);
00051 }
00052 osg::Node* getNewNode(osg::Node* node);
00053 bool recordNewNode(osg::Node* oldNode, osg::Node* newNode);
00054 osg::NodeList& getResults() { return _childStack.back(); }
00055 protected:
00056 std::vector<osg::NodeList> _childStack;
00057 typedef std::map<osg::ref_ptr<osg::Node>, osg::ref_ptr<osg::Node> > NodeMap;
00058 NodeMap _visited;
00059 };
00060
00061 template<typename T>
00062 T* SplicingVisitor::copyIfNeeded(T& node, const osg::NodeList& children)
00063 {
00064 bool copyNeeded = false;
00065 if (node.getNumChildren() == children.size()) {
00066 for (std::size_t i = 0; i < children.size(); ++i)
00067 if (node.getChild(i) != children[i].get()) {
00068 copyNeeded = true;
00069 break;
00070 }
00071 } else {
00072 copyNeeded = true;
00073 }
00074 if (copyNeeded)
00075 return copy(node, children);
00076 else
00077 return &node;
00078 }
00079
00080 template<typename T>
00081 T* SplicingVisitor::copy(T& node, const osg::NodeList& children)
00082 {
00083 T* result = osg::clone(&node, osg::CopyOp::SHALLOW_COPY);
00084 result->removeChildren(0, result->getNumChildren());
00085 for (osg::NodeList::const_iterator itr = children.begin(),
00086 end = children.end();
00087 itr != end;
00088 ++itr)
00089 result->addChild(itr->get());
00090 return result;
00091 }
00092 }
00093 #endif