#ifndef OSG_NODEVISITOR #define OSG_NODEVISITOR 1 #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 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 passing 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: ref_ptr _traversalVisitor; TraversalMode _traversalMode; }; /** 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