1
//---------------------------------------------------------------------------
3
// Project: OpenWalnut ( http://www.openwalnut.org )
5
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6
// For more information see http://www.openwalnut.org/copying
8
// This file is part of OpenWalnut.
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.
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.
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/>.
23
//---------------------------------------------------------------------------
28
#include <osg/ShapeDrawable>
29
#include <osg/MatrixTransform>
32
#include "WGEGroupNode.h"
34
WGEGroupNode::WGEGroupNode():
35
osg::MatrixTransform(),
36
m_childOperationQueueDirty( false ),
39
setDataVariance( osg::Object::DYNAMIC );
41
// setup an update callback
42
m_nodeUpdater = osg::ref_ptr< SafeUpdaterCallback >( new SafeUpdaterCallback() );
43
addUpdateCallback( m_nodeUpdater );
50
WGEGroupNode::~WGEGroupNode()
55
void WGEGroupNode::insert( osg::ref_ptr< osg::Node > node )
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 ) ) );
59
m_childOperationQueueDirty = true;
63
void WGEGroupNode::remove( osg::ref_ptr< osg::Node > node )
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 ) ) );
67
m_childOperationQueueDirty = true;
71
void WGEGroupNode::remove_if( boost::shared_ptr< WGEGroupNode::NodePredicate > predicate )
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 ) ) );
75
m_childOperationQueueDirty = true;
79
void WGEGroupNode::clear()
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
84
m_childOperationQueueDirty = true;
88
void WGEGroupNode::SafeUpdaterCallback::operator()( osg::Node* node, osg::NodeVisitor* nv )
90
// the node also is a WGEGroupNode
91
WGEGroupNode* rootNode = static_cast< WGEGroupNode* >( node );
93
// write lock the insertion list
94
boost::unique_lock<boost::shared_mutex> lock;
96
// write lock the removal list
97
if( rootNode->m_childOperationQueueDirty )
99
lock = boost::unique_lock<boost::shared_mutex>( rootNode->m_childOperationQueueLock );
100
// insert/remove children which requested it
101
while( !rootNode->m_childOperationQueue.empty() )
103
// remove or insert or remove all?
104
if( rootNode->m_childOperationQueue.front()->m_operation == INSERT )
106
// add specified child
107
rootNode->addChild( rootNode->m_childOperationQueue.front()->m_item );
110
if( rootNode->m_childOperationQueue.front()->m_operation == REMOVE )
112
// remove specified child
113
rootNode->removeChild( rootNode->m_childOperationQueue.front()->m_item );
116
if( rootNode->m_childOperationQueue.front()->m_operation == REMOVE_IF )
118
// remove children where m_predicate is true
119
for( size_t i = 0; i < rootNode->getNumChildren(); )
121
if( ( *rootNode->m_childOperationQueue.front()->m_predicate )( rootNode->getChild( i ) ) )
123
// remove item but do not increment index
124
rootNode->removeChild( i );
127
// this was not removed. Go to next one.
132
if( rootNode->m_childOperationQueue.front()->m_operation == CLEAR )
135
rootNode->removeChild( 0, rootNode->getNumChildren() );
139
rootNode->m_childOperationQueue.pop();
142
rootNode->dirtyBound();
144
// all children added/removed -> clear
145
rootNode->m_childOperationQueueDirty = false;
146
rootNode->m_removeAll = false;
152
traverse( node, nv );