OpenWalnut  1.4.0
WGEGroupNode.h
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 #ifndef WGEGROUPNODE_H
00026 #define WGEGROUPNODE_H
00027 
00028 #include <queue>
00029 
00030 #include <boost/thread.hpp>
00031 
00032 #include <osg/MatrixTransform>
00033 #include <osg/NodeCallback>
00034 
00035 #include "../common/WPredicateHelper.h"
00036 
00037 
00038 /**
00039  * Class to wrap around the osg Group node and providing a thread safe add/removal mechanism. Please be sure to use
00040  * addUpdateCallback() to set your own update callbacks instead of setUpdateCallback, as this class already has set a callback,
00041  * which would be overwritten by a subsequent call to setUpdateCallback(). It is derived from osg::MatrixTransform to allow easy transformations
00042  * of a whole bunch of nodes.
00043  *
00044  * \ingroup GE
00045  */
00046 class WGEGroupNode: public osg::MatrixTransform
00047 {
00048 public:
00049     /**
00050      * Default constructor.
00051      */
00052     WGEGroupNode();
00053 
00054     /**
00055      * Adds the specified node to the child list of this node in a safe manner. OSG officially requires nodes to be added
00056      * exclusively during update callbacks. Using this method it is ensured to be added during update cycle.
00057      *
00058      * \param node the node to add.
00059      *
00060      * \note the node may not be added instantly. So do not assume that containsNode ( node ) will return true.
00061      */
00062     void insert( osg::ref_ptr< osg::Node > node );
00063 
00064     /**
00065      * Removes the specified node from this group in a thread safe manner. It returns if the node has been removed.
00066      *
00067      * \param node the node to remove
00068      */
00069     void remove( osg::ref_ptr< osg::Node > node );
00070 
00071     /**
00072      * The base type of predicate. Use a specific WPredicateHelper::ArbitraryPredicate instance. For details, see
00073      * \ref WPredicateHelper::ArbitraryPredicateBase.
00074      */
00075     typedef WPredicateHelper::ArbitraryPredicateBase< osg::ref_ptr< osg::Node > const > NodePredicate;
00076 
00077     /**
00078      * Removes a node if the specified predicate evaluates to true.
00079      * \see WPredicateHelper::ArbitraryPredicate for details.
00080      *
00081      * \param predicate the predicate.
00082      */
00083     void remove_if( boost::shared_ptr< WGEGroupNode::NodePredicate > predicate );
00084 
00085     /**
00086      * Removes all children from this node.
00087      */
00088     void clear();
00089 
00090 protected:
00091     /**
00092      * Destructor.
00093      */
00094     virtual ~WGEGroupNode();
00095 
00096     /**
00097      * Update callback which inserts and removes nodes from m_childRemovalQueue and m_childInsertionQueue to the group node.
00098      * This ensures thread safe modification of the osg root node.
00099      */
00100     class SafeUpdaterCallback : public osg::NodeCallback
00101     {
00102     public:
00103         /**
00104          * Callback method called by the NodeVisitor when visiting a node.
00105          * This inserts and removes enqueued nodes from this group node instance.
00106          *
00107          * \param node the node calling this update
00108          * \param nv The node visitor which performs the traversal. Should be an
00109          * update visitor.
00110          */
00111         virtual void operator()( osg::Node* node, osg::NodeVisitor* nv );
00112     };
00113 
00114     /**
00115      * Node callback used to update this root node.
00116      */
00117     osg::ref_ptr< SafeUpdaterCallback > m_nodeUpdater;
00118 
00119     /**
00120      * The type of operation to perform.
00121      */
00122     typedef enum
00123     {
00124         INSERT = 0,         //! insert the specified node
00125         REMOVE,             //! remove the specified node
00126         REMOVE_IF,          //! remove all items where the predicate evaluates to true
00127         CLEAR               //! clear group node completely
00128     }
00129     ChildOperationType;
00130 
00131     /**
00132      * A struct denoting an operation on this group. The operation itself, as well as the item and predicate are stored.
00133      */
00134     struct ChildOperation
00135     {
00136         /**
00137          * Constructs instance and fills members properly.
00138          *
00139          * \param what the operation to make
00140          * \param item the child to delete
00141          */
00142         ChildOperation( ChildOperationType what, osg::ref_ptr< osg::Node > item ):
00143             m_operation( what ),
00144             m_item( item ),
00145             m_predicate()
00146         {
00147         };
00148 
00149         /**
00150          * Constructs instance and fills members properly.
00151          *
00152          * \param what the operation to make
00153          * \param predicate the predicate to use for conditional operations (REMOVE_IF)
00154          */
00155         ChildOperation( ChildOperationType what, boost::shared_ptr< NodePredicate > predicate ):
00156             m_operation( what ),
00157             m_item(),
00158             m_predicate( predicate )
00159         {
00160         };
00161 
00162         ChildOperationType m_operation;                     //!< the operation to take
00163         osg::ref_ptr< osg::Node > m_item;                   //!< the item to delete/add
00164         boost::shared_ptr< NodePredicate > m_predicate;     //!< the predicate used by conditional operations
00165     };
00166 
00167     /**
00168      * Queue of childs that need to be added/removed during the next update cycle. It is a pair per operation, where the bool is denoting removal
00169      * or insertion.
00170      */
00171     std::queue< boost::shared_ptr< ChildOperation > > m_childOperationQueue;
00172 
00173     /**
00174      * Lock used for inserting and removing childs into the child insertion/removal queue.
00175      */
00176     boost::shared_mutex m_childOperationQueueLock;
00177 
00178     /**
00179      * Flag denoting whether the m_childOperationQueue should be considered during the next update of the node.
00180      */
00181     bool m_childOperationQueueDirty;
00182 
00183     /**
00184      * True whenever all child nodes should be removed.
00185      */
00186     bool m_removeAll;
00187 
00188 private:
00189 };
00190 
00191 #endif  // WGEGROUPNODE_H
00192