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