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