OpenSceneGraph/include/osg/NodeVisitor

159 lines
6.4 KiB
Plaintext
Raw Normal View History

2001-01-11 00:32:10 +08:00
#ifndef OSG_NODEVISITOR
#define OSG_NODEVISITOR 1
#include <osg/Node>
2001-09-22 10:42:08 +08:00
#include <osg/FrameStamp>
2001-01-11 00:32:10 +08:00
namespace osg {
class Geode;
class Billboard;
class LightSource;
class Group;
class Transform;
2001-01-11 00:32:10 +08:00
class LOD;
class Sequence;
class Switch;
class Impostor;
2001-01-11 00:32:10 +08:00
/** 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() {}
2001-01-11 00:32:10 +08:00
2001-09-22 10:42:08 +08:00
/** 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;
}
2001-01-11 00:32:10 +08:00
/** 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);
2001-09-22 10:42:08 +08:00
2001-01-11 00:32:10 +08:00
/** Get the traversal mode.*/
inline const TraversalMode getTraversalMode() const { return _traversalMode; }
2001-01-11 00:32:10 +08:00
/** 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(); }
2001-01-11 00:32:10 +08:00
2001-09-22 10:42:08 +08:00
/** Inline method for handling traversal of a nodes.
2001-01-11 00:32:10 +08:00
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);
2001-01-11 00:32:10 +08:00
}
virtual void apply(Node& node) { traverse(node);}
2001-01-11 00:32:10 +08:00
virtual void apply(Geode& node) { apply((Node&)node); }
virtual void apply(Billboard& node) { apply((Geode&)node); }
2001-01-11 00:32:10 +08:00
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); }
2001-01-11 00:32:10 +08:00
protected:
2001-09-22 10:42:08 +08:00
int _traversalNumber;
ref_ptr<FrameStamp> _frameStamp;
ref_ptr<NodeVisitor> _traversalVisitor;
2001-09-22 10:42:08 +08:00
TraversalMode _traversalMode;
2001-09-22 10:42:08 +08:00
Node::NodeMask _traversalMask;
Node::NodeMask _nodeMaskOverride;
2001-01-11 00:32:10 +08:00
};
/** 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) { node->accept(_nv); }
};
};
#endif