]> git.mxchange.org Git - simgear.git/blob - simgear/scene/util/SplicingVisitor.cxx
Fix VS2010 lack of fminf
[simgear.git] / simgear / scene / util / SplicingVisitor.cxx
1 #include "SplicingVisitor.hxx"
2
3 namespace simgear
4 {
5 using namespace osg;
6
7 SplicingVisitor::SplicingVisitor()
8     : NodeVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN)
9 {
10     _childStack.push_back(NodeList());
11 }
12
13 void SplicingVisitor::reset()
14 {
15     _childStack.clear();
16     NodeVisitor::reset();
17 }
18
19 NodeList SplicingVisitor::traverse(osg::Node& node)
20 {
21     NodeList result;
22     _childStack.push_back(NodeList());
23     NodeVisitor::traverse(node);
24     result = _childStack.back();
25     _childStack.pop_back();
26     return result;
27 }
28 void SplicingVisitor::apply(osg::Node& node)
29 {
30     NodeVisitor::traverse(node);
31     pushNode(&node);
32 }
33
34 void SplicingVisitor::apply(osg::Group& node)
35 {
36     if (pushNode(getNewNode(node)))
37         return;
38     pushResultNode(&node, &node, traverse(node));
39 }
40
41 osg::Group* SplicingVisitor::pushResultNode( osg::Group* node,
42                                              osg::Group* newNode,
43                                              const osg::NodeList& children )
44 {
45     ref_ptr<Group> result;
46     if (node == newNode) {
47         result = copyIfNeeded(*node, children);
48     } else {
49         result = newNode;
50         for (NodeList::const_iterator itr = children.begin(), end = children.end();
51              itr != end;
52              ++itr)
53             result->addChild(itr->get());
54     }
55     _childStack.back().push_back(result);
56     recordNewNode(node, result.get());
57     return result.get();
58 }
59
60 osg::Node* SplicingVisitor::pushResultNode(osg::Node* node, osg::Node* newNode)
61 {
62     _childStack.back().push_back(newNode);
63     recordNewNode(node, newNode);
64     return newNode;
65 }
66
67 osg::Node* SplicingVisitor::pushNode(osg::Node* node)
68 {
69     if (node)
70         _childStack.back().push_back(node);
71     return node;
72 }
73
74 osg::Node* SplicingVisitor::getResult()
75 {
76     NodeList& top = _childStack.at(0);
77     if (top.empty()) {
78         return 0;
79     } else if (top.size() == 1) {
80         return top[0].get();
81     } else {
82         Group* result = new Group;
83         for (NodeList::iterator itr = top.begin(), end = top.end();
84              itr != end;
85              ++itr)
86             result->addChild(itr->get());
87         return result;
88     }
89 }
90
91 osg::Node* SplicingVisitor::getNewNode(osg::Node* node)
92 {
93     ref_ptr<Node> tmpPtr(node);
94     NodeMap::iterator itr;
95     try {
96         itr = _visited.find(tmpPtr);
97     }
98     catch (...) {
99         tmpPtr.release();
100         throw;
101     }
102     if (itr == _visited.end())
103         return 0;
104     else
105         return itr->second.get();
106 }
107
108 bool SplicingVisitor::recordNewNode(osg::Node* oldNode, osg::Node* newNode)
109 {
110     ref_ptr<Node> oldTmp(oldNode);
111     ref_ptr<Node> newTmp(newNode);
112     return _visited.insert(std::make_pair(oldTmp, newTmp)).second;
113 }
114 }