]> git.mxchange.org Git - simgear.git/blob - simgear/scene/util/SplicingVisitor.hxx
accomodate changes to osgDB::DatabasePager interface
[simgear.git] / simgear / scene / util / SplicingVisitor.hxx
1 #ifndef SIMGEAR_SPLICINGVISITOR_HXX
2 #define SIMGEAR_SPLICINGVISITOR_HXX 1
3
4 #include <cstddef>
5 #include <map>
6 #include <vector>
7 #include <osg/NodeVisitor>
8 #include <osg/Group>
9
10 namespace simgear
11 {
12 class SplicingVisitor : public osg::NodeVisitor
13 {
14 public:
15     META_NodeVisitor(simgear,SplicingVisitor);
16     SplicingVisitor();
17     virtual ~SplicingVisitor() {}
18     virtual void reset();
19     osg::NodeList traverse(osg::Node& node);
20     using osg::NodeVisitor::apply;
21     virtual void apply(osg::Node& node);
22     virtual void apply(osg::Group& node);
23     template<typename T>
24     static T* copyIfNeeded(T& node, const osg::NodeList& children);
25     template<typename T>
26     static T* copy(T& node, const osg::NodeList& children);
27     /**
28      * Push the result of processing this node.
29      *
30      * If the child list is not equal to the node's current children,
31      * make a copy of the node. Record the (possibly new) node which
32      * should be the returned result if the node is visited again.
33      */
34     osg::Group* pushResultNode(osg::Group* node, osg::Group* newNode,
35                                const osg::NodeList& children);
36     /**
37      * Push the result of processing this node.
38      *
39      * Record the (possibly new) node which should be the returned
40      * result if the node is visited again.
41      */
42     osg::Node* pushResultNode(osg::Node* node, osg::Node* newNode);
43     /**
44      * Push some node onto the list of result nodes.
45      */
46     osg::Node* pushNode(osg::Node* node);
47     osg::Node* getResult();
48     osg::Node* getNewNode(osg::Node& node)
49     {
50         return getNewNode(&node);
51     }
52     osg::Node* getNewNode(osg::Node* node);
53     bool recordNewNode(osg::Node* oldNode, osg::Node* newNode);
54     osg::NodeList& getResults() { return _childStack.back(); }
55 protected:
56     std::vector<osg::NodeList> _childStack;
57     typedef std::map<osg::ref_ptr<osg::Node>, osg::ref_ptr<osg::Node> > NodeMap;
58     NodeMap _visited;
59 };
60
61 template<typename T>
62 T* SplicingVisitor::copyIfNeeded(T& node, const osg::NodeList& children)
63 {
64     bool copyNeeded = false;
65     if (node.getNumChildren() == children.size()) {
66         for (std::size_t i = 0; i < children.size(); ++i)
67             if (node.getChild(i) != children[i].get()) {
68                 copyNeeded = true;
69                 break;
70             }
71     } else {
72         copyNeeded = true;
73     }
74     if (copyNeeded)
75         return copy(node, children);
76     else
77         return &node;
78 }
79
80 template<typename T>
81 T* SplicingVisitor::copy(T& node, const osg::NodeList& children)
82 {
83     T* result = osg::clone(&node, osg::CopyOp::SHALLOW_COPY);
84     result->removeChildren(0, result->getNumChildren());
85     for (osg::NodeList::const_iterator itr = children.begin(),
86              end = children.end();
87          itr != end;
88          ++itr)
89         result->addChild(itr->get());
90     return result;
91 }
92 }
93 #endif