#ifndef OSG_NODEVISITOR #define OSG_NODEVISITOR 1 #include #include namespace osg { class Geode; class Billboard; class LightSource; class Group; class Transform; class LOD; class Sequence; class Switch; class Impostor; /** Visitor for type safe operations on osg::Node's. Based on GOF's Visitor pattern.*/ class SG_EXPORT NodeVisitor : public Referenced { public: enum TraversalMode { TRAVERSE_NONE, TRAVERSE_PARENTS, TRAVERSE_ALL_CHILDREN, TRAVERSE_ACTIVE_CHILDREN, TRAVERSE_VISITOR }; NodeVisitor(TraversalMode tm=TRAVERSE_NONE); virtual ~NodeVisitor(); /** Method to call to reset visitor. Useful for your visitor accumulates state during a traversal, and you plan to resuse the visitor. To flush that state for the next traversal than call reset() prior to each traversal.*/ virtual void reset() {} /** Set the traversal number. Typically used to denote the frame count.*/ inline void setTraversalNumber(const int fn) { _traversalNumber = fn; } /** Get the traversal number. Typically used to denote the frame count.*/ inline const int getTraversalNumber() const { return _traversalNumber; } /** Set the FrameStamp that this traversal is assoicated with.*/ inline void setFrameStamp(FrameStamp* fs) { _frameStamp = fs; } /** Get the FrameStamp that this traversal is assoicated with.*/ inline const FrameStamp* getFrameStamp() const { return _frameStamp.get(); } /** Set the TraversalMask of this NodeVisitor. * The TraversalMask is used by the NodeVisitor::validNodeMask() method * to determine whether to operate on a node and its subgraph. * validNodeMask() is called automaticaly in the Node::accept() method before * any call to NodeVisitor::apply(), apply() is only ever called if validNodeMask * returns true. Note, if NodeVisitor::_traversalMask is 0 then all operations * will be swithced off for all nodes. Whereas setting both _traversalMask and * _nodeMaskOverride to 0xffffffff will allow a visitor to work on all nodes * regardless of their own Node::_nodeMask state.*/ inline void setTraversalMask(const Node::NodeMask mask) { _traversalMask = mask; } /** Get the TraversalMask.*/ inline const Node::NodeMask getTraversalMask() const { return _traversalMask; } /** Set the NodeMaskOverride mask. * Used in validNodeMask() to determine whether to operate on a node or its * subgraph, by OR'ing NodeVisitor::_nodeMaskOverride with the Node's own Node::_nodeMask. * Typically used to force on nodes which may have * been switched off by their own Node::_nodeMask.*/ inline void setNodeMaskOverride(const Node::NodeMask mask) { _nodeMaskOverride = mask; } /** Get the NodeMaskOverride mask.*/ inline const Node::NodeMask getNodeMaskOverride() const { return _nodeMaskOverride; } /** Method to called by Node and its subclass' Node::accept() method, if the result is true * to be used to cull operations of nodes and their subgraphs. * Return true if the result of a bit wise and of the NodeVisitor::_traversalMask * with the bit or between NodeVistor::_nodeMaskOverride and the Node::_nodeMask. * default values for _traversalMask is 0xffffffff, _nodeMaskOverride is 0x0, * and osg::Node::_nodeMask is 0xffffffff. */ inline const bool validNodeMask(const osg::Node& node) const { return (getTraversalMask() & (getNodeMaskOverride() | node.getNodeMask()))!=0; } /** Set the traversal mode for Node::traverse() to use when deciding which children of a node to traverse. If a NodeVisitor has been attached via setTraverseVisitor() and the new mode is not TRAVERSE_VISITOR then the attached visitor is detached. Default mode is TRAVERSE_NONE.*/ void setTraversalMode(const TraversalMode mode); /** Get the traversal mode.*/ inline const TraversalMode getTraversalMode() const { return _traversalMode; } /** Set a visitor to handle traversal. Overides the traverse mode setting it to TRAVERSAL_VISITOR.*/ void setTraversalVisitor(NodeVisitor* nv); /** Get the traversal visitor, returns NULL if none is attached.*/ NodeVisitor* getTraversalVisitor() { return _traversalVisitor.get(); } /** Inline method for handling traversal of a nodes. If you intend to use the visitor for actively traversing the scene graph then make sure the accept() methods call this method unless they handle traversal directly.*/ void traverse(Node& node) { if (_traversalVisitor.valid()) node.accept(*_traversalVisitor); else if (_traversalMode==TRAVERSE_PARENTS) node.ascend(*this); else if (_traversalMode!=TRAVERSE_NONE) node.traverse(*this); } virtual void apply(Node& node) { traverse(node);} virtual void apply(Geode& node) { apply((Node&)node); } virtual void apply(Billboard& node) { apply((Geode&)node); } virtual void apply(LightSource& node){ apply((Node&)node); } virtual void apply(Group& node) { apply((Node&)node); } virtual void apply(Transform& node) { apply((Group&)node); } virtual void apply(Switch& node) { apply((Group&)node); } virtual void apply(Sequence& node) { apply((Group&)node); } virtual void apply(LOD& node) { apply((Group&)node); } virtual void apply(Impostor& node) { apply((LOD&)node); } protected: int _traversalNumber; ref_ptr _frameStamp; ref_ptr _traversalVisitor; TraversalMode _traversalMode; Node::NodeMask _traversalMask; Node::NodeMask _nodeMaskOverride; }; /** Convinience functor for assisting visiting of arrays of osg::Node's.*/ struct NodeAcceptOp { NodeVisitor& _nv; NodeAcceptOp(NodeVisitor& nv):_nv(nv) {} void operator () (Node* node) { node->accept(_nv); } void operator () (ref_ptr node) { node->accept(_nv); } }; }; #endif