OpenWalnut 1.2.5
|
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 #include <set> 00027 00028 #include <osg/ShapeDrawable> 00029 #include <osg/MatrixTransform> 00030 #include <osg/Geode> 00031 00032 #include "WGEGroupNode.h" 00033 00034 WGEGroupNode::WGEGroupNode(): 00035 osg::MatrixTransform(), 00036 m_childOperationQueueDirty( false ), 00037 m_removeAll( false ) 00038 { 00039 setDataVariance( osg::Object::DYNAMIC ); 00040 00041 // setup an update callback 00042 m_nodeUpdater = osg::ref_ptr< SafeUpdaterCallback >( new SafeUpdaterCallback() ); 00043 addUpdateCallback( m_nodeUpdater ); 00044 00045 osg::Matrix m; 00046 m.makeIdentity(); 00047 setMatrix( m ); 00048 } 00049 00050 WGEGroupNode::~WGEGroupNode() 00051 { 00052 // cleanup 00053 } 00054 00055 void WGEGroupNode::insert( osg::ref_ptr< osg::Node > node ) 00056 { 00057 boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_childOperationQueueLock ); 00058 m_childOperationQueue.push( boost::shared_ptr< ChildOperation >( new ChildOperation( INSERT, node ) ) ); 00059 m_childOperationQueueDirty = true; 00060 lock.unlock(); 00061 } 00062 00063 void WGEGroupNode::remove( osg::ref_ptr< osg::Node > node ) 00064 { 00065 boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_childOperationQueueLock ); 00066 m_childOperationQueue.push( boost::shared_ptr< ChildOperation >( new ChildOperation( REMOVE, node ) ) ); 00067 m_childOperationQueueDirty = true; 00068 lock.unlock(); 00069 } 00070 00071 void WGEGroupNode::remove_if( boost::shared_ptr< WGEGroupNode::NodePredicate > predicate ) 00072 { 00073 boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_childOperationQueueLock ); 00074 m_childOperationQueue.push( boost::shared_ptr< ChildOperation >( new ChildOperation( REMOVE_IF, predicate ) ) ); 00075 m_childOperationQueueDirty = true; 00076 lock.unlock(); 00077 } 00078 00079 void WGEGroupNode::clear() 00080 { 00081 boost::unique_lock<boost::shared_mutex> lock = boost::unique_lock<boost::shared_mutex>( m_childOperationQueueLock ); 00082 m_childOperationQueue.push( boost::shared_ptr< ChildOperation >( new ChildOperation( CLEAR, osg::ref_ptr< osg::Node >() ) ) ); 00083 // this encodes the remove all feature 00084 m_childOperationQueueDirty = true; 00085 lock.unlock(); 00086 } 00087 00088 void WGEGroupNode::SafeUpdaterCallback::operator()( osg::Node* node, osg::NodeVisitor* nv ) 00089 { 00090 // the node also is a WGEGroupNode 00091 WGEGroupNode* rootNode = static_cast< WGEGroupNode* >( node ); 00092 00093 // write lock the insertion list 00094 boost::unique_lock<boost::shared_mutex> lock; 00095 00096 // write lock the removal list 00097 if( rootNode->m_childOperationQueueDirty ) 00098 { 00099 lock = boost::unique_lock<boost::shared_mutex>( rootNode->m_childOperationQueueLock ); 00100 // insert/remove children which requested it 00101 while( !rootNode->m_childOperationQueue.empty() ) 00102 { 00103 // remove or insert or remove all? 00104 if( rootNode->m_childOperationQueue.front()->m_operation == INSERT ) 00105 { 00106 // add specified child 00107 rootNode->addChild( rootNode->m_childOperationQueue.front()->m_item ); 00108 } 00109 00110 if( rootNode->m_childOperationQueue.front()->m_operation == REMOVE ) 00111 { 00112 // remove specified child 00113 rootNode->removeChild( rootNode->m_childOperationQueue.front()->m_item ); 00114 } 00115 00116 if( rootNode->m_childOperationQueue.front()->m_operation == REMOVE_IF ) 00117 { 00118 // remove children where m_predicate is true 00119 for( size_t i = 0; i < rootNode->getNumChildren(); ) 00120 { 00121 if( ( *rootNode->m_childOperationQueue.front()->m_predicate )( rootNode->getChild( i ) ) ) 00122 { 00123 // remove item but do not increment index 00124 rootNode->removeChild( i ); 00125 } 00126 00127 // this was not removed. Go to next one. 00128 ++i; 00129 } 00130 } 00131 00132 if( rootNode->m_childOperationQueue.front()->m_operation == CLEAR ) 00133 { 00134 // remove all 00135 rootNode->removeChild( 0, rootNode->getNumChildren() ); 00136 } 00137 00138 // pop item 00139 rootNode->m_childOperationQueue.pop(); 00140 } 00141 00142 rootNode->dirtyBound(); 00143 00144 // all children added/removed -> clear 00145 rootNode->m_childOperationQueueDirty = false; 00146 rootNode->m_removeAll = false; 00147 00148 lock.unlock(); 00149 } 00150 00151 // forward the call 00152 traverse( node, nv ); 00153 } 00154