OpenWalnut  1.4.0
WGEGroupNode.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WGEGROUPNODE_H
26 #define WGEGROUPNODE_H
27 
28 #include <queue>
29 
30 #include <boost/thread.hpp>
31 
32 #include <osg/MatrixTransform>
33 #include <osg/NodeCallback>
34 
35 #include "../common/WPredicateHelper.h"
36 
37 
38 /**
39  * Class to wrap around the osg Group node and providing a thread safe add/removal mechanism. Please be sure to use
40  * addUpdateCallback() to set your own update callbacks instead of setUpdateCallback, as this class already has set a callback,
41  * which would be overwritten by a subsequent call to setUpdateCallback(). It is derived from osg::MatrixTransform to allow easy transformations
42  * of a whole bunch of nodes.
43  *
44  * \ingroup GE
45  */
46 class WGEGroupNode: public osg::MatrixTransform
47 {
48 public:
49  /**
50  * Default constructor.
51  */
52  WGEGroupNode();
53 
54  /**
55  * Adds the specified node to the child list of this node in a safe manner. OSG officially requires nodes to be added
56  * exclusively during update callbacks. Using this method it is ensured to be added during update cycle.
57  *
58  * \param node the node to add.
59  *
60  * \note the node may not be added instantly. So do not assume that containsNode ( node ) will return true.
61  */
62  void insert( osg::ref_ptr< osg::Node > node );
63 
64  /**
65  * Removes the specified node from this group in a thread safe manner. It returns if the node has been removed.
66  *
67  * \param node the node to remove
68  */
69  void remove( osg::ref_ptr< osg::Node > node );
70 
71  /**
72  * The base type of predicate. Use a specific WPredicateHelper::ArbitraryPredicate instance. For details, see
73  * \ref WPredicateHelper::ArbitraryPredicateBase.
74  */
76 
77  /**
78  * Removes a node if the specified predicate evaluates to true.
79  * \see WPredicateHelper::ArbitraryPredicate for details.
80  *
81  * \param predicate the predicate.
82  */
83  void remove_if( boost::shared_ptr< WGEGroupNode::NodePredicate > predicate );
84 
85  /**
86  * Removes all children from this node.
87  */
88  void clear();
89 
90 protected:
91  /**
92  * Destructor.
93  */
94  virtual ~WGEGroupNode();
95 
96  /**
97  * Update callback which inserts and removes nodes from m_childRemovalQueue and m_childInsertionQueue to the group node.
98  * This ensures thread safe modification of the osg root node.
99  */
100  class SafeUpdaterCallback : public osg::NodeCallback
101  {
102  public:
103  /**
104  * Callback method called by the NodeVisitor when visiting a node.
105  * This inserts and removes enqueued nodes from this group node instance.
106  *
107  * \param node the node calling this update
108  * \param nv The node visitor which performs the traversal. Should be an
109  * update visitor.
110  */
111  virtual void operator()( osg::Node* node, osg::NodeVisitor* nv );
112  };
113 
114  /**
115  * Node callback used to update this root node.
116  */
117  osg::ref_ptr< SafeUpdaterCallback > m_nodeUpdater;
118 
119  /**
120  * The type of operation to perform.
121  */
122  typedef enum
123  {
124  INSERT = 0, //! insert the specified node
125  REMOVE, //! remove the specified node
126  REMOVE_IF, //! remove all items where the predicate evaluates to true
127  CLEAR //! clear group node completely
128  }
130 
131  /**
132  * A struct denoting an operation on this group. The operation itself, as well as the item and predicate are stored.
133  */
135  {
136  /**
137  * Constructs instance and fills members properly.
138  *
139  * \param what the operation to make
140  * \param item the child to delete
141  */
142  ChildOperation( ChildOperationType what, osg::ref_ptr< osg::Node > item ):
143  m_operation( what ),
144  m_item( item ),
145  m_predicate()
146  {
147  };
148 
149  /**
150  * Constructs instance and fills members properly.
151  *
152  * \param what the operation to make
153  * \param predicate the predicate to use for conditional operations (REMOVE_IF)
154  */
155  ChildOperation( ChildOperationType what, boost::shared_ptr< NodePredicate > predicate ):
156  m_operation( what ),
157  m_item(),
158  m_predicate( predicate )
159  {
160  };
161 
162  ChildOperationType m_operation; //!< the operation to take
163  osg::ref_ptr< osg::Node > m_item; //!< the item to delete/add
164  boost::shared_ptr< NodePredicate > m_predicate; //!< the predicate used by conditional operations
165  };
166 
167  /**
168  * Queue of childs that need to be added/removed during the next update cycle. It is a pair per operation, where the bool is denoting removal
169  * or insertion.
170  */
171  std::queue< boost::shared_ptr< ChildOperation > > m_childOperationQueue;
172 
173  /**
174  * Lock used for inserting and removing childs into the child insertion/removal queue.
175  */
176  boost::shared_mutex m_childOperationQueueLock;
177 
178  /**
179  * Flag denoting whether the m_childOperationQueue should be considered during the next update of the node.
180  */
182 
183  /**
184  * True whenever all child nodes should be removed.
185  */
187 
188 private:
189 };
190 
191 #endif // WGEGROUPNODE_H
192