OpenWalnut
1.4.0
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #include <iostream> 00026 00027 #include <osg/ShapeDrawable> 00028 #include <osg/MatrixTransform> 00029 #include <osg/Geode> 00030 00031 #include "WGEGroupNode.h" 00032 00033 WGEGroupNode::WGEGroupNode(): 00034 osg::MatrixTransform(), 00035 m_childOperationQueueDirty( false ), 00036 m_removeAll( false ) 00037 { 00038 setDataVariance( osg::Object::DYNAMIC ); 00039 00040 // setup an update callback 00041 m_nodeUpdater = osg::ref_ptr< SafeUpdaterCallback >( new SafeUpdaterCallback() ); 00042 addUpdateCallback( m_nodeUpdater ); 00043 00044 osg::Matrix m; 00045 m.makeIdentity(); 00046 setMatrix( m ); 00047 } 00048 00049 WGEGroupNode::~WGEGroupNode() 00050 { 00051 // cleanup 00052 } 00053 00054 void WGEGroupNode::insert( osg::ref_ptr< osg::Node > node ) 00055 { 00056 boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_childOperationQueueLock ); 00057 m_childOperationQueue.push( boost::shared_ptr< ChildOperation >( new ChildOperation( INSERT, node ) ) ); 00058 m_childOperationQueueDirty = true; 00059 lock.unlock(); 00060 } 00061 00062 void WGEGroupNode::remove( osg::ref_ptr< osg::Node > node ) 00063 { 00064 boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_childOperationQueueLock ); 00065 m_childOperationQueue.push( boost::shared_ptr< ChildOperation >( new ChildOperation( REMOVE, node ) ) ); 00066 m_childOperationQueueDirty = true; 00067 lock.unlock(); 00068 } 00069 00070 void WGEGroupNode::remove_if( boost::shared_ptr< WGEGroupNode::NodePredicate > predicate ) 00071 { 00072 boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_childOperationQueueLock ); 00073 m_childOperationQueue.push( boost::shared_ptr< ChildOperation >( new ChildOperation( REMOVE_IF, predicate ) ) ); 00074 m_childOperationQueueDirty = true; 00075 lock.unlock(); 00076 } 00077 00078 void WGEGroupNode::clear() 00079 { 00080 boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_childOperationQueueLock ); 00081 m_childOperationQueue.push( boost::shared_ptr< ChildOperation >( new ChildOperation( CLEAR, osg::ref_ptr< osg::Node >() ) ) ); 00082 // this encodes the remove all feature 00083 m_childOperationQueueDirty = true; 00084 lock.unlock(); 00085 } 00086 00087 void WGEGroupNode::SafeUpdaterCallback::operator()( osg::Node* node, osg::NodeVisitor* nv ) 00088 { 00089 // the node also is a WGEGroupNode 00090 WGEGroupNode* rootNode = static_cast< WGEGroupNode* >( node ); 00091 00092 // write lock the insertion list 00093 boost::unique_lock<boost::shared_mutex> lock; 00094 00095 // write lock the removal list 00096 if( rootNode->m_childOperationQueueDirty ) 00097 { 00098 lock = boost::unique_lock<boost::shared_mutex>( rootNode->m_childOperationQueueLock ); 00099 // insert/remove children which requested it 00100 while( !rootNode->m_childOperationQueue.empty() ) 00101 { 00102 // remove or insert or remove all? 00103 if( rootNode->m_childOperationQueue.front()->m_operation == INSERT ) 00104 { 00105 // add specified child 00106 rootNode->addChild( rootNode->m_childOperationQueue.front()->m_item ); 00107 } 00108 00109 if( rootNode->m_childOperationQueue.front()->m_operation == REMOVE ) 00110 { 00111 // remove specified child 00112 rootNode->removeChild( rootNode->m_childOperationQueue.front()->m_item ); 00113 } 00114 00115 if( rootNode->m_childOperationQueue.front()->m_operation == REMOVE_IF ) 00116 { 00117 // remove children where m_predicate is true 00118 for( size_t i = 0; i < rootNode->getNumChildren(); ) 00119 { 00120 if( ( *rootNode->m_childOperationQueue.front()->m_predicate )( rootNode->getChild( i ) ) ) 00121 { 00122 // remove item but do not increment index 00123 rootNode->removeChild( i ); 00124 } 00125 00126 // this was not removed. Go to next one. 00127 ++i; 00128 } 00129 } 00130 00131 if( rootNode->m_childOperationQueue.front()->m_operation == CLEAR ) 00132 { 00133 // remove all 00134 rootNode->removeChild( 0, rootNode->getNumChildren() ); 00135 } 00136 00137 // pop item 00138 rootNode->m_childOperationQueue.pop(); 00139 } 00140 00141 rootNode->dirtyBound(); 00142 00143 // all children added/removed -> clear 00144 rootNode->m_childOperationQueueDirty = false; 00145 rootNode->m_removeAll = false; 00146 00147 lock.unlock(); 00148 } 00149 00150 // forward the call 00151 traverse( node, nv ); 00152 } 00153