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