fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / Action / Base / OSGAction.cpp
blob66666c5e444a7d7587d9357d7db828394cb9ee16
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright 2000 by OpenSG Forum *
6 * *
7 * contact: {reiners|vossg}@igd.fhg.de, jbehr@zgdv.de *
8 * *
9 \*---------------------------------------------------------------------------*/
10 /*---------------------------------------------------------------------------*\
11 * License *
12 * *
13 * *
14 * *
15 * *
16 * *
17 \*---------------------------------------------------------------------------*/
18 /*---------------------------------------------------------------------------*\
19 * Changes *
20 * *
21 * *
22 * *
23 * *
24 * *
25 * *
26 \*---------------------------------------------------------------------------*/
28 //---------------------------------------------------------------------------
29 // Includes
30 //---------------------------------------------------------------------------
32 #include <cstdlib>
33 #include <cstdio>
35 #include "OSGConfig.h"
37 #include "OSGLog.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>
47 OSG_USING_NAMESPACE
50 /***************************************************************************\
51 * Description *
52 \***************************************************************************/
54 /*! \class OSG::Action
55 \ingroup GrpSystemAction
57 The action base class.
61 /***************************************************************************\
62 * Types *
63 \***************************************************************************/
65 /***************************************************************************\
66 * Class variables *
67 \***************************************************************************/
70 Action *Action::_prototype = NULL;
72 Action::FunctorStore *Action::_defaultEnterFunctors = NULL;
73 Action::FunctorStore *Action::_defaultLeaveFunctors = NULL;
75 /***************************************************************************\
76 * Class methods *
77 \***************************************************************************/
81 /*-------------------------------------------------------------------------*\
82 - public -
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)
115 _prototype = proto;
118 Action *Action::getPrototype(void)
120 return _prototype;
123 /*-------------------------------------------------------------------------*\
124 - protected -
125 \*-------------------------------------------------------------------------*/
128 /*-------------------------------------------------------------------------*\
129 - private -
130 \*-------------------------------------------------------------------------*/
134 /***************************************************************************\
135 * Instance methods *
136 \***************************************************************************/
138 /*-------------------------------------------------------------------------*\
139 - public -
140 \*-------------------------------------------------------------------------*/
142 /*------------- constructors & destructors --------------------------------*/
144 /** \brief Constructor
147 Action::Action(void) :
148 Inherited ( ),
149 _enterFunctors( ),
150 _leaveFunctors( ),
151 _actNode (NULL ),
152 _actParent (NULL ),
153 _actList (NULL ),
154 _useNewList (false ),
155 _newList ( ),
156 _travMask (TypeTraits<UInt32>::BitsSet),
157 _sTravMask ( ),
158 _nodeEnterCB ( ),
159 _nodeLeaveCB ( )
161 if(_defaultEnterFunctors)
162 _enterFunctors = *_defaultEnterFunctors;
164 if(_defaultLeaveFunctors)
165 _leaveFunctors = *_defaultLeaveFunctors;
168 /** \brief Copy-Constructor
171 Action::Action(const Action &source) :
172 Inherited (source ),
173 _enterFunctors(source._enterFunctors ),
174 _leaveFunctors(source._leaveFunctors ),
175 _actNode (NULL ),
176 _actParent (NULL ),
177 _actList (NULL ),
178 _useNewList (false ),
179 _newList ( ),
180 _travMask (source._travMask ),
181 _sTravMask ( ),
182 _nodeEnterCB (source._nodeEnterCB ),
183 _nodeLeaveCB (source._nodeLeaveCB )
188 /** \brief create a new action
191 Action::ObjTransitPtr Action::create(void)
193 ObjTransitPtr act(NULL);
195 if(_prototype)
197 act = new Action(*_prototype);
199 else
201 act = new Action();
204 return act;
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)
254 return res;
256 // call the given nodes
258 for(; begin != end; ++begin)
260 if(*begin == NULL)
262 SWARNING << "apply: encountered NullNode!" << std::endl;
263 return Quit;
265 else
267 res = recurse(*begin);
269 if(res != Continue)
270 break;
274 // call the stop function and its' returns
275 res = callStop(res);
277 return res;
280 Action::ResultE Action::apply(Node * const node)
282 if(node == NULL)
284 SWARNING << "apply: node is Null!" << std::endl;
285 return Quit;
288 std::vector<Node *> nodeList;
290 nodeList.push_back(node);
292 return apply(nodeList.begin(), nodeList.end());
298 // recursion calling
300 Action::ResultE Action::recurse(Node * const node)
302 if(node == NULL)
303 return Continue;
305 if((node->getTravMask() & getTravMask()) == 0x0000)
307 return Continue;
310 #if OSG_1_COMPAT
311 if(node->getOcclusionMask() & 1)
312 return Continue;
313 #endif
315 NodeCore *core = node->getCore();
317 if(core == NULL)
319 SWARNING << "Action::recurse: core is NULL, "
320 << "aborting traversal." << std::endl;
321 return Quit;
324 Action::ResultE result = Continue;
326 _actList = NULL;
327 _actNode = node;
328 _actParent = node;
330 _newList.clear();
332 _useNewList = false;
334 if(_nodeEnterCB != NULL)
335 result = _nodeEnterCB(node, this);
337 if(result != Continue)
339 if(result == Skip)
340 return Continue;
342 return result;
345 result = callEnter(node->getCore());
347 _actNode = node;
348 _actParent = node;
350 if(result != Continue)
352 if(result == Skip)
353 return Continue;
355 return result;
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)
374 break;
378 _actNode = node;
379 _actParent = node;
381 if(result == Continue)
383 result = callLeave(node->getCore());
385 else
387 callLeave(node->getCore());
390 _actNode = node;
391 _actParent = node;
393 if(_nodeLeaveCB != NULL)
394 _nodeLeaveCB(node, this);
396 if(result == Skip)
397 return Continue;
399 return result;
402 Action::ResultE Action::recurseNoCallback(Node * const node)
404 if(node == NULL)
405 return Continue;
407 if((node->getTravMask() & getTravMask()) == 0x0000)
409 return Continue;
412 NodeCore *core = node->getCore();
414 if(core == NULL)
416 SWARNING << "Action::recurseNoCallback: core is NULL, "
417 << "aborting traversal." << std::endl;
418 return Quit;
421 Action::ResultE result = Action::Continue;
423 _actList = NULL;
424 _actNode = node;
425 _actParent = node;
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)
444 break;
448 _actNode = node;
449 _actParent = node;
451 if(result == Skip)
452 return Continue;
454 return result;
457 Action::ResultE Action::recurseMultiCoreFrom(Node * const node,
458 MultiCore * const mcore,
459 NodeCore * const from )
461 if(node == NULL)
462 return Continue;
464 if((node->getTravMask() & getTravMask()) == 0x0000)
466 return Continue;
469 OSG_ASSERT(node->getCore() == mcore);
471 Action::ResultE result = Continue;
473 _actList = NULL;
474 _actNode = node;
475 _actParent = node;
477 result = mcore->actionEnterFrom(this, from);
479 _actNode = node;
480 _actParent = node;
482 if(result != Continue)
484 if(result == Skip)
485 return Continue;
487 return result;
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)
506 break;
510 _actNode = node;
511 _actParent = node;
513 if(result == Continue)
515 result = mcore->actionLeaveFrom(this, from);
517 else
519 mcore->actionLeaveFrom(this, from);
522 _actNode = node;
523 _actParent = node;
525 if(result == Skip)
526 return Continue;
528 return result;
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)
553 break;
556 _actList = NULL;
558 return result;
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
602 _newList.clear();
604 if((res = start()) != Continue)
605 return res;
607 // got some nodes? call them
609 if(! _newList.empty())
610 res = callNewList();
612 // return the result
614 return res;
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
623 _newList.clear();
625 if((res = stop(res)) != Continue)
626 return res;
628 if(! _newList.empty())
629 res = callNewList();
631 return res;
634 // default start/stop, does nothing
636 Action::ResultE Action::start(void)
638 while(_sTravMask.empty() == false)
639 _sTravMask.pop();
641 return Continue;
644 Action::ResultE Action::stop(ResultE res)
646 return res;
649 /*-------------------------- assignment -----------------------------------*/
651 /** \brief assignment
654 Action& Action::operator = (const Action &source)
656 if (this == &source)
657 return *this;
659 return *this;
662 /*-------------------------- comparison -----------------------------------*/
664 /** \brief assignment
667 bool Action::operator < (const Action &other)
669 return this < &other;
672 /** \brief equal
675 bool Action::operator == (const Action &OSG_CHECK_ARG(other))
677 return false;
680 /** \brief unequal
683 bool Action::operator != (const Action &other)
685 return ! (*this == other);
689 /*-------------------------------------------------------------------------*\
690 - protected -
691 \*-------------------------------------------------------------------------*/
693 Action::FunctorStore *Action::getDefaultEnterFunctors(void)
695 return _defaultEnterFunctors;
698 Action::FunctorStore *Action::getDefaultLeaveFunctors(void)
700 return _defaultLeaveFunctors;
704 /*-------------------------------------------------------------------------*\
705 - private -
706 \*-------------------------------------------------------------------------*/
708 // default Action function: just call all kids
710 Action::ResultE Action::_defaultEnterFunction(NodeCore * const,
711 Action * )
713 return Continue;
716 Action::ResultE Action::_defaultLeaveFunction(NodeCore * const,
717 Action * )
719 return Continue;
722 /*************** Functions ******************/
724 OSG_BEGIN_NAMESPACE
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)
742 break;
745 return res;
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)
761 break;
764 return res;
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;
775 res = func(node);
777 if(node == NULL)
778 return Action::Continue;
780 RootGroup *pRGroup = dynamic_cast<RootGroup *>(node->getCore());
782 switch(res)
784 case Action::Skip:
785 return Action::Continue;
787 case Action::Continue:
789 if(pRGroup != NULL && pRGroup->getRoot() != NULL)
791 return traverse(pRGroup->getRoot(), func);
793 else
795 return traverse(*(node->getMFChildren()),
796 func );
799 break;
801 default:
802 break;
805 return res;
808 /*! Simple tree traversal function. Calls enter before entering a node,
809 leave after leaving.
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)
826 break;
829 return res;
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)
846 break;
849 return res;
853 /*! Simple tree traversal function. Calls enter before entering a node,
854 leave after leaving.
857 Action::ResultE traverse(Node * const node,
858 TraverseEnterFunctor enter,
859 TraverseLeaveFunctor leave)
861 Action::ResultE res = Action::Continue;
863 res = enter(node);
865 RootGroup *pRGroup = dynamic_cast<RootGroup *>(node->getCore());
867 switch(res)
869 case Action::Skip:
870 res = Action::Continue;
871 break;
873 case Action::Continue:
875 if(pRGroup != NULL && pRGroup->getRoot() != NULL)
877 res = traverse(pRGroup->getRoot(), enter, leave);
879 else
881 res = traverse(*(node->getMFChildren()),
882 enter,
883 leave );
886 break;
887 default:
888 break;
891 res = leave(node, res);
893 return res;
896 OSG_END_NAMESPACE