OpenWalnut  1.5.0dev
WGEGroupNode.cpp
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 #include <iostream>
26 #include <memory>
27 
28 #include <osg/Geode>
29 #include <osg/MatrixTransform>
30 #include <osg/ShapeDrawable>
31 
32 #include "WGEGroupNode.h"
33 
35  osg::MatrixTransform(),
36  m_childOperationQueueDirty( false ),
37  m_removeAll( false )
38 {
39  setDataVariance( osg::Object::DYNAMIC );
40 
41  // setup an update callback
42  m_nodeUpdater = osg::ref_ptr< SafeUpdaterCallback >( new SafeUpdaterCallback() );
43  addUpdateCallback( m_nodeUpdater );
44 
45  osg::Matrix m;
46  m.makeIdentity();
47  setMatrix( m );
48 }
49 
51 {
52  // cleanup
53 }
54 
55 void WGEGroupNode::insert( osg::ref_ptr< osg::Node > node )
56 {
57  std::unique_lock<std::shared_mutex> lock = std::unique_lock<std::shared_mutex>( m_childOperationQueueLock );
58  m_childOperationQueue.push( std::shared_ptr< ChildOperation >( new ChildOperation( INSERT, node ) ) );
60  lock.unlock();
61 }
62 
63 void WGEGroupNode::remove( osg::ref_ptr< osg::Node > node )
64 {
65  std::unique_lock<std::shared_mutex> lock = std::unique_lock<std::shared_mutex>( m_childOperationQueueLock );
66  m_childOperationQueue.push( std::shared_ptr< ChildOperation >( new ChildOperation( REMOVE, node ) ) );
68  lock.unlock();
69 }
70 
71 void WGEGroupNode::remove_if( std::shared_ptr< WGEGroupNode::NodePredicate > predicate )
72 {
73  std::unique_lock<std::shared_mutex> lock = std::unique_lock<std::shared_mutex>( m_childOperationQueueLock );
74  m_childOperationQueue.push( std::shared_ptr< ChildOperation >( new ChildOperation( REMOVE_IF, predicate ) ) );
76  lock.unlock();
77 }
78 
80 {
81  std::unique_lock<std::shared_mutex> lock = std::unique_lock<std::shared_mutex>( m_childOperationQueueLock );
82  m_childOperationQueue.push( std::shared_ptr< ChildOperation >( new ChildOperation( CLEAR, osg::ref_ptr< osg::Node >() ) ) );
83  // this encodes the remove all feature
85  lock.unlock();
86 }
87 
88 void WGEGroupNode::SafeUpdaterCallback::operator()( osg::Node* node, osg::NodeVisitor* nv )
89 {
90  // the node also is a WGEGroupNode
91  WGEGroupNode* rootNode = static_cast< WGEGroupNode* >( node );
92 
93  // write lock the insertion list
94  std::unique_lock<std::shared_mutex> lock;
95 
96  // write lock the removal list
97  if( rootNode->m_childOperationQueueDirty )
98  {
99  lock = std::unique_lock<std::shared_mutex>( rootNode->m_childOperationQueueLock );
100  // insert/remove children which requested it
101  while( !rootNode->m_childOperationQueue.empty() )
102  {
103  // remove or insert or remove all?
104  if( rootNode->m_childOperationQueue.front()->m_operation == INSERT )
105  {
106  // add specified child
107  rootNode->addChild( rootNode->m_childOperationQueue.front()->m_item );
108  }
109 
110  if( rootNode->m_childOperationQueue.front()->m_operation == REMOVE )
111  {
112  // remove specified child
113  rootNode->removeChild( rootNode->m_childOperationQueue.front()->m_item );
114  }
115 
116  if( rootNode->m_childOperationQueue.front()->m_operation == REMOVE_IF )
117  {
118  // remove children where m_predicate is true
119  for( size_t i = 0; i < rootNode->getNumChildren(); )
120  {
121  if( ( *rootNode->m_childOperationQueue.front()->m_predicate )( rootNode->getChild( i ) ) )
122  {
123  // remove item but do not increment index
124  rootNode->removeChild( i );
125  }
126 
127  // this was not removed. Go to next one.
128  ++i;
129  }
130  }
131 
132  if( rootNode->m_childOperationQueue.front()->m_operation == CLEAR )
133  {
134  // remove all
135  rootNode->removeChild( 0, rootNode->getNumChildren() );
136  }
137 
138  // pop item
139  rootNode->m_childOperationQueue.pop();
140  }
141 
142  rootNode->dirtyBound();
143 
144  // all children added/removed -> clear
145  rootNode->m_childOperationQueueDirty = false;
146  rootNode->m_removeAll = false;
147 
148  lock.unlock();
149  }
150 
151  // forward the call
152  traverse( node, nv );
153 }
154 
Update callback which inserts and removes nodes from m_childRemovalQueue and m_childInsertionQueue to...
Definition: WGEGroupNode.h:102
virtual void operator()(osg::Node *node, osg::NodeVisitor *nv)
Callback method called by the NodeVisitor when visiting a node.
Class to wrap around the osg Group node and providing a thread safe add/removal mechanism.
Definition: WGEGroupNode.h:48
void remove_if(std::shared_ptr< WGEGroupNode::NodePredicate > predicate)
Removes a node if the specified predicate evaluates to true.
bool m_childOperationQueueDirty
Flag denoting whether the m_childOperationQueue should be considered during the next update of the no...
Definition: WGEGroupNode.h:182
virtual ~WGEGroupNode()
Destructor.
std::queue< std::shared_ptr< ChildOperation > > m_childOperationQueue
Queue of childs that need to be added/removed during the next update cycle.
Definition: WGEGroupNode.h:172
std::shared_mutex m_childOperationQueueLock
Lock used for inserting and removing childs into the child insertion/removal queue.
Definition: WGEGroupNode.h:177
void remove(osg::ref_ptr< osg::Node > node)
Removes the specified node from this group in a thread safe manner.
bool m_removeAll
True whenever all child nodes should be removed.
Definition: WGEGroupNode.h:187
osg::ref_ptr< SafeUpdaterCallback > m_nodeUpdater
Node callback used to update this root node.
Definition: WGEGroupNode.h:118
WGEGroupNode()
Default constructor.
@ CLEAR
remove all items where the predicate evaluates to true
Definition: WGEGroupNode.h:128
@ REMOVE_IF
remove the specified node
Definition: WGEGroupNode.h:127
@ REMOVE
insert the specified node
Definition: WGEGroupNode.h:126
void clear()
Removes all children from this node.
void insert(osg::ref_ptr< osg::Node > node)
Adds the specified node to the child list of this node in a safe manner.
A struct denoting an operation on this group.
Definition: WGEGroupNode.h:136