Commit d36b6143 authored by Jan Möbius's avatar Jan Möbius
Browse files

Dennis:

Added-support-for-enter-leave-action-functions

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@5396 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 4d613a66
......@@ -60,22 +60,66 @@ namespace SceneGraph {
//== CLASS DEFINITION =========================================================
/** Template functions to check if an action has enter or leave member functions
**/
/** Traverse the scenegraph starting at the node \c _node and apply
the action \c action to each node. When arriving at a node, its
BaseNode::enter() function is called, then \c _action is applied
and the node's children are traversed. After that the
BaseNode::leave() method is called.
template<bool C, typename T = void>
struct enable_if {
typedef T type;
};
\see ACG::SceneGraph::BaseNode
**/
template<typename T>
struct enable_if<false, T> { };
#define HAS_MEM_FUNC(func) \
template<typename T, typename Sign> \
struct has_##func { \
template <typename U, U> struct type_check; \
template <typename _1> static char (& chk(type_check<Sign, &_1::func> *))[1]; \
template <typename > static char (& chk(...))[2]; \
static bool const value = sizeof(chk<T>(0)) == 1; \
};
HAS_MEM_FUNC(enter)
// if the enter function is implemented
template<typename Action>
typename enable_if<has_enter <Action, void (Action::*) (BaseNode *) >::value, void>::type
if_has_enter(Action &_action, BaseNode *_node) {
_action.enter (_node);
}
// if the enter function isn't implemented
template<typename Action>
typename enable_if<!has_enter <Action, void (Action::*) (BaseNode *) >::value, void>::type
if_has_enter(Action &, BaseNode *) {
}
HAS_MEM_FUNC(leave)
// if the enter function is implemented
template<typename Action>
typename enable_if<has_leave <Action, void (Action::*) (BaseNode *) >::value, void>::type
if_has_leave(Action &_action, BaseNode *_node) {
_action.leave (_node);
}
// if the enter function isn't implemented
template<typename Action>
typename enable_if<!has_enter <Action, void (Action::*) (BaseNode *) >::value, void>::type
if_has_leave(Action &, BaseNode *) {
}
//----------------------------------------------------------------------------
/** Traverse the scenegraph starting at the node \c _node and apply
the action \c _action to each node. This traversal function will call the
enter/leave functions of the action if they have been implemented.
**/
template <class Action>
void
traverse( BaseNode* _node,
Action& _action,
GLState& _state,
unsigned int _drawmode=DrawModes::DEFAULT)
traverse( BaseNode* _node, Action& _action )
{
if (_node)
{
......@@ -84,79 +128,100 @@ traverse( BaseNode* _node,
if (status != BaseNode::HideSubtree)
{
unsigned int drawmode = ((_node->drawMode() == DrawModes::DEFAULT) ?
_drawmode : _node->drawMode());
if (_node->status() != BaseNode::HideNode)
{
_node->enter(_state, drawmode);
if_has_enter (_action, _node);
if (_node->traverseMode() & BaseNode::NodeFirst)
process_children &= _action(_node, _state);
process_children &= _action(_node);
}
if (process_children)
{
BaseNode::ChildIter cIt, cEnd(_node->childrenEnd());
for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt)
BaseNode::ChildIter cIt, cEnd(_node->childrenEnd());
for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt)
if (~(*cIt)->traverseMode() & BaseNode::SecondPass)
traverse(*cIt, _action, _state, _drawmode);
traverse(*cIt, _action);
for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt)
if ((*cIt)->traverseMode() & BaseNode::SecondPass)
traverse(*cIt, _action, _state, _drawmode);
traverse(*cIt, _action);
}
if (_node->status() != BaseNode::HideNode)
{
if (_node->traverseMode() & BaseNode::ChildrenFirst)
_action(_node, _state);
_node->leave(_state, drawmode);
_action(_node);
if_has_leave (_action, _node);
}
}
}
}
//----------------------------------------------------------------------------
/** Traverse the scenegraph starting at the node \c _node and apply
the action \c _action to each node. This traversal function does
\b not call then BaseNode::enter() and BaseNode::leave() methods
and therefore doesn't need the \c GLState& reference.
/** This is a meta action class that is used to wrap an action from the
traverse( BaseNode*, Action&, GLState&, unsigned int) into the
traverse( BaseNode*, Action&) function
**/
template <class Action>
void
traverse( BaseNode* _node, Action& _action )
class MetaAction
{
if (_node)
{
BaseNode::StatusMode status(_node->status());
bool process_children(status != BaseNode::HideChildren);
public:
MetaAction (Action & _action, GLState& _state, unsigned int _drawmode) :
action_(_action),
state_(_state),
drawmode_(_drawmode)
{
}
if (status != BaseNode::HideSubtree)
bool operator()(BaseNode* _node)
{
if (_node->status() != BaseNode::HideNode &&
_node->traverseMode() & BaseNode::NodeFirst)
process_children &= _action(_node);
return action_(_node, state_);
}
if (process_children)
{
BaseNode::ChildIter cIt, cEnd(_node->childrenEnd());
for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt)
if (~(*cIt)->traverseMode() & BaseNode::SecondPass)
traverse(*cIt, _action);
for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt)
if ((*cIt)->traverseMode() & BaseNode::SecondPass)
traverse(*cIt, _action);
}
void enter (BaseNode *_node)
{
unsigned int drawmode = ((_node->drawMode() == DrawModes::DEFAULT) ?
drawmode_ : _node->drawMode());
_node->enter(state_, drawmode);
}
if (_node->status() != BaseNode::HideNode &&
_node->traverseMode() & BaseNode::ChildrenFirst)
_action(_node);
void leave (BaseNode *_node)
{
unsigned int drawmode = ((_node->drawMode() == DrawModes::DEFAULT) ?
drawmode_ : _node->drawMode());
_node->leave(state_, drawmode);
}
}
}
private:
Action &action_;
GLState &state_;
unsigned int drawmode_;
};
//----------------------------------------------------------------------------
/** Traverse the scenegraph starting at the node \c _node and apply
the action \c action to each node. When arriving at a node, its
BaseNode::enter() function is called, then \c _action is applied
and the node's children are traversed. After that the
BaseNode::leave() method is called.
\see ACG::SceneGraph::BaseNode
**/
template <class Action>
void
traverse( BaseNode* _node,
Action& _action,
GLState& _state,
unsigned int _drawmode=DrawModes::DEFAULT)
{
MetaAction<Action> action (_action, _state, _drawmode);
traverse (_node, action);
}
//----------------------------------------------------------------------------
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment