OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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 <set>
27 
28 #include <osg/ShapeDrawable>
29 #include <osg/MatrixTransform>
30 #include <osg/Geode>
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  boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_childOperationQueueLock );
58  m_childOperationQueue.push( boost::shared_ptr< ChildOperation >( new ChildOperation( INSERT, node ) ) );
60  lock.unlock();
61 }
62 
63 void WGEGroupNode::remove( osg::ref_ptr< osg::Node > node )
64 {
65  boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_childOperationQueueLock );
66  m_childOperationQueue.push( boost::shared_ptr< ChildOperation >( new ChildOperation( REMOVE, node ) ) );
68  lock.unlock();
69 }
70 
71 void WGEGroupNode::remove_if( boost::shared_ptr< WGEGroupNode::NodePredicate > predicate )
72 {
73  boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_childOperationQueueLock );
74  m_childOperationQueue.push( boost::shared_ptr< ChildOperation >( new ChildOperation( REMOVE_IF, predicate ) ) );
76  lock.unlock();
77 }
78 
80 {
81  boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_childOperationQueueLock );
82  m_childOperationQueue.push( boost::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  boost::unique_lock<boost::shared_mutex> lock;
95 
96  // write lock the removal list
97  if( rootNode->m_childOperationQueueDirty )
98  {
99  lock = boost::unique_lock<boost::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