OpenWalnut 1.2.5

WGEGroupNode.cpp

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 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends