/
RegionWalkers.h
130 lines (112 loc) · 2.82 KB
/
RegionWalkers.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#ifndef REGIONWALKERS_H_
#define REGIONWALKERS_H_
namespace map {
/** greebo: Sets the "excluded" bit in the Node according to the given boolean.
*
* @exclude: set to TRUE if you want to exclude the node.
*/
inline void excludeNode(scene::INodePtr node, bool exclude)
{
if (!node->supportsStateFlag(scene::Node::eExcluded))
{
return;
}
if (exclude)
{
node->enable(scene::Node::eExcluded);
}
else {
node->disable(scene::Node::eExcluded);
}
}
/** greebo: Sets/resets the exclude bit on the visited node
*/
class ExcludeAllWalker :
public scene::NodeVisitor
{
bool _exclude;
public:
ExcludeAllWalker(bool exclude) :
_exclude(exclude)
{}
bool pre(const scene::INodePtr& node)
{
excludeNode(node, _exclude);
return true;
}
};
/** greebo: Sets the exclusion status of all the objects WITHIN the bounds.
*
* All the objects outside the bounds get their status set to the opposite.
*/
class ExcludeRegionedWalker :
public scene::NodeVisitor
{
bool _exclude;
// The reference to the currently active region bounds
AABB& _regionAABB;
public:
ExcludeRegionedWalker(bool exclude, AABB& regionAABB) :
_exclude(exclude),
_regionAABB(regionAABB)
{}
bool pre(const scene::INodePtr& node)
{
// Check whether the instance is within the region
bool contained = node->worldAABB().intersects(_regionAABB);
if (contained) {
// The contained stuff is set according to the _exclude parameter
excludeNode(node, _exclude);
}
else {
// This is an object outside the bounds, set it to !_exclude
// as the _exclude should apply to the objects within.
excludeNode(node, !_exclude);
}
// Traverse the children as well
return true;
}
};
/** greebo: This class is used indirectly by the map saving walker to save the region.
*
* The map saving walker calls a function RegionManager::traverseRegion() which
* traverses the given node with this walker.
*
* This ExcludeNonRegionedWalker again invokes the map saving walker, if the
* visited items are regioned only, of course.
*/
class ExcludeNonRegionedWalker :
public scene::NodeVisitor
{
scene::NodeVisitor& _walker;
mutable bool _skip;
public:
ExcludeNonRegionedWalker(scene::NodeVisitor& walker) :
_walker(walker),
_skip(false)
{}
virtual bool pre(const scene::INodePtr& node) {
// Don't save excluded nodes or the Scenegraph root
if (node->excluded() || node->isRoot()) {
_skip = true;
return false;
}
else {
// Item passed the check, call the given walker's pre() method.
_walker.pre(node);
}
return true;
}
virtual void post(const scene::INodePtr& node) {
if (_skip) {
// The node failed to pass the check in pre()
_skip = false;
}
else {
// The node passed the check in pre(), we have to call post() as well.
_walker.post(node);
}
}
};
} // namespace map
#endif /*REGIONWALKERS_H_*/