1 /*---------------------------------------------------------------------------*\
5 * Copyright 2000 by OpenSG Forum *
7 * contact: {reiners|vossg}@igd.fhg.de, jbehr@zgdv.de *
9 \*---------------------------------------------------------------------------*/
10 /*---------------------------------------------------------------------------*\
17 \*---------------------------------------------------------------------------*/
18 /*---------------------------------------------------------------------------*\
26 \*---------------------------------------------------------------------------*/
28 //---------------------------------------------------------------------------
30 //---------------------------------------------------------------------------
35 #include "OSGConfig.h"
38 #include "OSGFieldContainer.h"
39 #include "OSGMultiCore.h"
40 #include "OSGNodeCore.h"
41 #include "OSGAction.h"
42 #include "OSGRootGroup.h"
44 //#define BOOST_MEM_FN_ENABLE_CDECL
45 #include <boost/bind.hpp>
50 /***************************************************************************\
52 \***************************************************************************/
54 /*! \class OSG::Action
55 \ingroup GrpSystemAction
57 The action base class.
61 /***************************************************************************\
63 \***************************************************************************/
65 /***************************************************************************\
67 \***************************************************************************/
70 Action
*Action::_prototype
= NULL
;
72 Action::FunctorStore
*Action::_defaultEnterFunctors
= NULL
;
73 Action::FunctorStore
*Action::_defaultLeaveFunctors
= NULL
;
75 /***************************************************************************\
77 \***************************************************************************/
81 /*-------------------------------------------------------------------------*\
83 \*-------------------------------------------------------------------------*/
85 void Action::registerEnterDefault(const FieldContainerType
&type
,
86 const Action::Functor
&func
)
88 if(_defaultEnterFunctors
== NULL
)
89 _defaultEnterFunctors
= new FunctorStore
;
91 while(type
.getId() >= _defaultEnterFunctors
->size())
93 _defaultEnterFunctors
->push_back(&Action::_defaultEnterFunction
);
96 (*_defaultEnterFunctors
)[type
.getId()] = func
;
99 void Action::registerLeaveDefault(const FieldContainerType
&type
,
100 const Action::Functor
&func
)
102 if(_defaultLeaveFunctors
== NULL
)
103 _defaultLeaveFunctors
= new FunctorStore
;
105 while(type
.getId() >= _defaultLeaveFunctors
->size())
107 _defaultLeaveFunctors
->push_back(&Action::_defaultLeaveFunction
);
110 (*_defaultLeaveFunctors
)[type
.getId()] = func
;
113 void Action::setPrototype(Action
*proto
)
118 Action
*Action::getPrototype(void)
123 /*-------------------------------------------------------------------------*\
125 \*-------------------------------------------------------------------------*/
128 /*-------------------------------------------------------------------------*\
130 \*-------------------------------------------------------------------------*/
134 /***************************************************************************\
136 \***************************************************************************/
138 /*-------------------------------------------------------------------------*\
140 \*-------------------------------------------------------------------------*/
142 /*------------- constructors & destructors --------------------------------*/
144 /** \brief Constructor
147 Action::Action(void) :
154 _useNewList (false ),
156 _travMask (TypeTraits
<UInt32
>::BitsSet
),
161 if(_defaultEnterFunctors
)
162 _enterFunctors
= *_defaultEnterFunctors
;
164 if(_defaultLeaveFunctors
)
165 _leaveFunctors
= *_defaultLeaveFunctors
;
168 /** \brief Copy-Constructor
171 Action::Action(const Action
&source
) :
173 _enterFunctors(source
._enterFunctors
),
174 _leaveFunctors(source
._leaveFunctors
),
178 _useNewList (false ),
180 _travMask (source
._travMask
),
182 _nodeEnterCB (source
._nodeEnterCB
),
183 _nodeLeaveCB (source
._nodeLeaveCB
)
188 /** \brief create a new action
191 Action::ObjTransitPtr
Action::create(void)
193 ObjTransitPtr
act(NULL
);
197 act
= new Action(*_prototype
);
207 /** \brief Destructor
210 Action::~Action(void)
214 /*------------------------------ access -----------------------------------*/
216 /*---------------------------- properties ---------------------------------*/
218 /*-------------------------- your_category---------------------------------*/
220 void Action::registerEnterFunction(const FieldContainerType
&type
,
221 const Action::Functor
&func
)
223 while(type
.getId() >= _enterFunctors
.size())
225 _enterFunctors
.push_back(&Action::_defaultEnterFunction
);
228 _enterFunctors
[type
.getId()] = func
;
231 void Action::registerLeaveFunction(const FieldContainerType
&type
,
232 const Action::Functor
&func
)
234 while(type
.getId() >= _leaveFunctors
.size())
236 _leaveFunctors
.push_back(&Action::_defaultLeaveFunction
);
239 _leaveFunctors
[type
.getId()] = func
;
244 // application entry points
246 Action::ResultE
Action::apply(std::vector
<Node
*>::iterator begin
,
247 std::vector
<Node
*>::iterator end
)
249 Action::ResultE res
= Continue
;
251 // call the start function and its' returns
253 if((res
= callStart()) != Continue
)
256 // call the given nodes
258 for(; begin
!= end
; ++begin
)
262 SWARNING
<< "apply: encountered NullNode!" << std::endl
;
267 res
= recurse(*begin
);
274 // call the stop function and its' returns
280 Action::ResultE
Action::apply(Node
* const node
)
284 SWARNING
<< "apply: node is Null!" << std::endl
;
288 std::vector
<Node
*> nodeList
;
290 nodeList
.push_back(node
);
292 return apply(nodeList
.begin(), nodeList
.end());
300 Action::ResultE
Action::recurse(Node
* const node
)
305 if((node
->getTravMask() & getTravMask()) == 0x0000)
311 if(node
->getOcclusionMask() & 1)
315 NodeCore
*core
= node
->getCore();
319 SWARNING
<< "Action::recurse: core is NULL, "
320 << "aborting traversal." << std::endl
;
324 Action::ResultE result
= Continue
;
334 if(_nodeEnterCB
!= NULL
)
335 result
= _nodeEnterCB(node
, this);
337 if(result
!= Continue
)
345 result
= callEnter(node
->getCore());
350 if(result
!= Continue
)
358 if(! _newList
.empty())
360 result
= callNewList();
362 else if(! _useNewList
) // new list is empty, but not used?
364 Node::MFChildrenType::const_iterator cIt
=
365 node
->getMFChildren()->begin();
366 Node::MFChildrenType::const_iterator cEnd
=
367 node
->getMFChildren()->end ();
369 for(; cIt
!= cEnd
; ++cIt
)
371 result
= recurse(*cIt
);
373 if(result
!= Continue
)
381 if(result
== Continue
)
383 result
= callLeave(node
->getCore());
387 callLeave(node
->getCore());
393 if(_nodeLeaveCB
!= NULL
)
394 _nodeLeaveCB(node
, this);
402 Action::ResultE
Action::recurseNoCallback(Node
* const node
)
407 if((node
->getTravMask() & getTravMask()) == 0x0000)
412 NodeCore
*core
= node
->getCore();
416 SWARNING
<< "Action::recurseNoCallback: core is NULL, "
417 << "aborting traversal." << std::endl
;
421 Action::ResultE result
= Action::Continue
;
427 if(! _newList
.empty())
429 result
= callNewList();
431 else if(! _useNewList
) // new list is empty, but not used?
433 Node::MFChildrenType::const_iterator cIt
=
434 node
->getMFChildren()->begin();
436 Node::MFChildrenType::const_iterator cEnd
=
437 node
->getMFChildren()->end ();
439 for( ; cIt
!= cEnd
; ++cIt
)
441 result
= recurse(*cIt
);
443 if(result
!= Continue
)
457 Action::ResultE
Action::recurseMultiCoreFrom(Node
* const node
,
458 MultiCore
* const mcore
,
459 NodeCore
* const from
)
464 if((node
->getTravMask() & getTravMask()) == 0x0000)
469 OSG_ASSERT(node
->getCore() == mcore
);
471 Action::ResultE result
= Continue
;
477 result
= mcore
->actionEnterFrom(this, from
);
482 if(result
!= Continue
)
490 if(! _newList
.empty())
492 result
= callNewList();
494 else if(! _useNewList
) // new list is empty, but not used?
496 Node::MFChildrenType::const_iterator it
=
497 node
->getMFChildren()->begin();
498 Node::MFChildrenType::const_iterator en
=
499 node
->getMFChildren()->end ();
501 for(; it
!= en
; ++it
)
503 result
= recurse(*it
);
505 if(result
!= Continue
)
513 if(result
== Continue
)
515 result
= mcore
->actionLeaveFrom(this, from
);
519 mcore
->actionLeaveFrom(this, from
);
532 // call the _newList objects
533 Action::ResultE
Action::callNewList(void)
535 ResultE result
= Continue
;
537 // need to make a copy, because the one in the action is cleared
539 std::vector
<Node
*> nodeList
;
541 nodeList
.swap(_newList
);
543 std::vector
<Node
*>::iterator it
= nodeList
.begin();
544 std::vector
<Node
*>::iterator en
= nodeList
.end();
546 _actList
= &nodeList
;
548 for(; it
!= en
; ++it
)
550 result
= recurse(*it
);
552 if(result
!= Continue
)
562 // call the start function and its results
564 Action::ResultE
Action::callStart(void)
566 ResultE res
= Continue
;
567 FunctorStore
*defaultEnter
= getDefaultEnterFunctors();
568 FunctorStore
*defaultLeave
= getDefaultLeaveFunctors();
570 // new default enter functor registered since this action was created
571 if(defaultEnter
!= NULL
&&
572 _enterFunctors
.size() < defaultEnter
->size())
574 _enterFunctors
.reserve(defaultEnter
->size());
576 FunctorStoreConstIt fIt
= defaultEnter
->begin() + _enterFunctors
.size();
577 FunctorStoreConstIt fEnd
= defaultEnter
->end ();
579 for(; fIt
!= fEnd
; ++fIt
)
581 _enterFunctors
.push_back(*fIt
);
585 // new default leave functor registered since this action was created
586 if(defaultLeave
!= NULL
&&
587 _leaveFunctors
.size() < defaultLeave
->size())
589 _leaveFunctors
.reserve(defaultLeave
->size());
591 FunctorStoreConstIt fIt
= defaultLeave
->begin() + _leaveFunctors
.size();
592 FunctorStoreConstIt fEnd
= defaultLeave
->end ();
594 for(; fIt
!= fEnd
; ++fIt
)
596 _leaveFunctors
.push_back(*fIt
);
600 // call the start and see if it returns some nodes
604 if((res
= start()) != Continue
)
607 // got some nodes? call them
609 if(! _newList
.empty())
617 // call the stop function and its results
619 Action::ResultE
Action::callStop(ResultE res
)
621 // call the start and see if it returns some nodes
625 if((res
= stop(res
)) != Continue
)
628 if(! _newList
.empty())
634 // default start/stop, does nothing
636 Action::ResultE
Action::start(void)
638 while(_sTravMask
.empty() == false)
644 Action::ResultE
Action::stop(ResultE res
)
649 /*-------------------------- assignment -----------------------------------*/
651 /** \brief assignment
654 Action
& Action::operator = (const Action
&source
)
662 /*-------------------------- comparison -----------------------------------*/
664 /** \brief assignment
667 bool Action::operator < (const Action
&other
)
669 return this < &other
;
675 bool Action::operator == (const Action
&OSG_CHECK_ARG(other
))
683 bool Action::operator != (const Action
&other
)
685 return ! (*this == other
);
689 /*-------------------------------------------------------------------------*\
691 \*-------------------------------------------------------------------------*/
693 Action::FunctorStore
*Action::getDefaultEnterFunctors(void)
695 return _defaultEnterFunctors
;
698 Action::FunctorStore
*Action::getDefaultLeaveFunctors(void)
700 return _defaultLeaveFunctors
;
704 /*-------------------------------------------------------------------------*\
706 \*-------------------------------------------------------------------------*/
708 // default Action function: just call all kids
710 Action::ResultE
Action::_defaultEnterFunction(NodeCore
* const,
716 Action::ResultE
Action::_defaultLeaveFunction(NodeCore
* const,
722 /*************** Functions ******************/
726 /*! Simple tree traversal function. Calls func for every node encountered
729 Action::ResultE
traverse(const std::vector
<Node
*> &nodeList
,
730 TraverseEnterFunctor func
)
732 Action::ResultE res
= Action::Continue
;
734 std::vector
<Node
*>::const_iterator it
= nodeList
.begin();
735 std::vector
<Node
*>::const_iterator en
= nodeList
.end ();
737 for(; it
!= en
; ++it
)
739 res
= traverse((*it
), func
);
741 if(res
== ActionBase::Quit
)
748 Action::ResultE
traverse(const MFUnrecChildNodePtr
&nodeList
,
749 TraverseEnterFunctor func
)
751 Action::ResultE res
= Action::Continue
;
753 MFUnrecChildNodePtr::const_iterator it
= nodeList
.begin();
754 MFUnrecChildNodePtr::const_iterator en
= nodeList
.end ();
756 for(; it
!= en
; ++it
)
758 res
= traverse((*it
), func
);
760 if(res
== ActionBase::Quit
)
767 /*! Simple tree traversal function. Calls func for every node encountered
770 Action::ResultE
traverse(Node
* const node
,
771 TraverseEnterFunctor func
)
773 Action::ResultE res
= Action::Continue
;
778 return Action::Continue
;
780 RootGroup
*pRGroup
= dynamic_cast<RootGroup
*>(node
->getCore());
785 return Action::Continue
;
787 case Action::Continue
:
789 if(pRGroup
!= NULL
&& pRGroup
->getRoot() != NULL
)
791 return traverse(pRGroup
->getRoot(), func
);
795 return traverse(*(node
->getMFChildren()),
808 /*! Simple tree traversal function. Calls enter before entering a node,
812 Action::ResultE
traverse(const std::vector
<Node
*> &nodeList
,
813 TraverseEnterFunctor enter
,
814 TraverseLeaveFunctor leave
)
816 Action::ResultE res
= Action::Continue
;
818 std::vector
<Node
*>::const_iterator it
= nodeList
.begin();
819 std::vector
<Node
*>::const_iterator en
= nodeList
.end ();
821 for(; it
!= en
; ++it
)
823 res
= traverse((*it
), enter
, leave
);
825 if(res
== Action::Quit
)
832 Action::ResultE
traverse(const MFUnrecChildNodePtr
&nodeList
,
833 TraverseEnterFunctor enter
,
834 TraverseLeaveFunctor leave
)
836 Action::ResultE res
= Action::Continue
;
838 MFUnrecChildNodePtr::const_iterator it
= nodeList
.begin();
839 MFUnrecChildNodePtr::const_iterator en
= nodeList
.end ();
841 for(; it
!= en
; ++it
)
843 res
= traverse((*it
), enter
, leave
);
845 if(res
== Action::Quit
)
853 /*! Simple tree traversal function. Calls enter before entering a node,
857 Action::ResultE
traverse(Node
* const node
,
858 TraverseEnterFunctor enter
,
859 TraverseLeaveFunctor leave
)
861 Action::ResultE res
= Action::Continue
;
865 RootGroup
*pRGroup
= dynamic_cast<RootGroup
*>(node
->getCore());
870 res
= Action::Continue
;
873 case Action::Continue
:
875 if(pRGroup
!= NULL
&& pRGroup
->getRoot() != NULL
)
877 res
= traverse(pRGroup
->getRoot(), enter
, leave
);
881 res
= traverse(*(node
->getMFChildren()),
891 res
= leave(node
, res
);