fixed: gcc8 compile issues
[opensg.git] / Source / Base / FieldContainer / Node / OSGNode.cpp
blob0188c36fcba469bcd40b930990684f9641cdf627
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2003 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
40 // Includes
41 //---------------------------------------------------------------------------
43 #include <cstdlib>
44 #include <cstdio>
46 #include "OSGConfig.h"
48 #include "OSGLog.h"
49 #include "OSGNode.h"
50 #include "OSGNodeCore.h"
52 #include "OSGTypeBasePredicates.h"
53 #include "OSGReflexiveContainerTypePredicates.h"
55 #include "boost/bind.hpp"
57 #ifdef WIN32 // turn of 'this' : used in base member initializer lits warning
58 #pragma warning(disable:4355)
59 #endif
61 OSG_BEGIN_NAMESPACE
63 /***************************************************************************\
64 * Description *
65 \***************************************************************************/
67 /*! \class OSG::Node
68 Node describe the hierarchical tree structure of the scenegraph. Every Node
69 can have at most one parent and one core (something derived from
70 NodeCore), but an arbitrary number of children.
73 /***************************************************************************\
74 * Field Description *
75 \***************************************************************************/
77 /*! \var BoxVolume Node::_sfVolume
78 The bounding volume of this node. It contains all the nodes children and
79 is described in this nodes coordinate system.
82 /*! \var UInt32 Node::_sfTravMask
83 The traversal mask is used to selectively exclude subtrees of the scenegraph
84 from traversal operations (e.g. GraphOps, RenderAction). Only if
85 the bitwise AND of the operation's and node's mask is non-zero the node
86 (and it's subtree) considered.
89 /*! \var NodeParentPtr Node::_sfParent
90 The node's single parent.
93 /*! \var NodePtr Node::_mfChildren
94 The node's children.
97 /*! \var NodeCorePtr Node::_sfCore
100 void Node::classDescInserter(TypeObject &oType)
102 FieldDescriptionBase *pDesc = NULL;
104 pDesc = new SFBoxVolume::Description(
105 SFBoxVolume::getClassType(),
106 "volume",
107 "Bounding volume for the node.",
108 OSG_RC_FIELD_DESC(Node::Volume),
109 false,
110 Field::SFDefaultFlags,
111 static_cast<FieldEditMethodSig>(&Node::editHandleVolume),
112 static_cast<FieldGetMethodSig >(&Node::getHandleVolume ));
114 oType.addInitialDesc(pDesc);
117 pDesc = new SFUInt32::Description(
118 SFUInt32::getClassType(),
119 "travMask",
120 "Traversal mask for the node.",
121 OSG_RC_FIELD_DESC(Node::TravMask),
122 false,
123 Field::SFDefaultFlags,
124 static_cast<FieldEditMethodSig>(&Node::editHandleTravMask),
125 static_cast<FieldGetMethodSig >(&Node::getHandleTravMask ));
127 oType.addInitialDesc(pDesc);
130 pDesc = new SFParentNodePtr::Description(
131 SFParentNodePtr::getClassType(),
132 "parent",
133 "This node's parent.",
134 OSG_RC_FIELD_DESC(Node::Parent),
135 true,
136 Field::SFDefaultFlags,
137 static_cast<FieldEditMethodSig>(&Node::invalidEditField),
138 static_cast<FieldGetMethodSig >(&Node::getHandleParent ));
140 oType.addInitialDesc(pDesc);
143 pDesc = new SFUnrecChildNodeCorePtr::Description(
144 SFUnrecChildNodeCorePtr::getClassType(),
145 "core",
146 "The core to use for this node.",
147 OSG_RC_FIELD_DESC(Node::Core),
148 false,
149 (Field::SFDefaultFlags | Field::FStdAccess),
150 static_cast<FieldEditMethodSig>(&Node::editHandleCore),
151 static_cast<FieldGetMethodSig >(&Node::getHandleCore ));
153 oType.addInitialDesc(pDesc);
156 pDesc = new MFUnrecChildNodePtr::Description(
157 MFUnrecChildNodePtr::getClassType(),
158 "children",
159 "A list of our children in the scene graph.",
160 OSG_RC_FIELD_DESC(Node::Children),
161 false,
162 (Field::MFDefaultFlags | Field::FNullCheckAccess),
163 static_cast<FieldEditMethodSig>(&Node::editHandleChildren),
164 static_cast<FieldGetMethodSig >(&Node::getHandleChildren));
166 oType.addInitialDesc(pDesc);
169 Node::TypeObject Node::_type(
170 Node ::getClassname(),
171 Inherited::getClassname(),
172 "Node",
174 reinterpret_cast<PrototypeCreateF>(&Node::createEmptyLocal),
175 NULL,
176 NULL,
177 reinterpret_cast<InitalInsertDescFunc>(
178 reinterpret_cast<void *>(&Node::classDescInserter)),
179 false,
183 OSG_FIELD_CONTAINER_DEF(Node)
187 /*-------------------------------------------------------------------------*/
188 /* Children */
190 void Node::addChild(Node * const childP)
192 if(childP != NULL)
194 // do the ref early, to prevent destroys on getParent(a)->addChild(a)
196 editMField(ChildrenFieldMask, _mfChildren);
198 _mfChildren.push_back(childP);
202 void Node::addChild(NodeTransitPtr childP)
204 if(childP != NULL)
206 editMField(ChildrenFieldMask, _mfChildren);
208 NodeUnrecPtr tmpChild = childP;
210 _mfChildren.push_back(tmpChild);
214 /*! Insert child node into child list.
215 * Upon completion, getChild(childIndex) will return the new child.
216 * (ie. child is at childIndex pos in list)
217 * All other children after childIndex are moved back in list.
218 * If childP is Null, does nothing.
220 * \warning childP is not ranged checked. Out of range values will have undefined behavior.
221 * \param childIndex The location in the list to put the new child.
222 * \param childP Pointer to the child to insert.
224 void Node::insertChild(UInt32 childIndex, Node * const childP)
226 OSG_ASSERT((childIndex <= getNChildren()) && "Child index out of range");
228 if(childP != NULL)
231 editMField(ChildrenFieldMask, _mfChildren);
233 MFUnrecChildNodePtr::iterator childIt = _mfChildren.begin_nc();
235 childIt += childIndex;
237 _mfChildren.insert(childIt, childP);
241 void Node::replaceChild(UInt32 childIndex, Node * const childP)
243 const Node *pThis = this;
245 if(childP != NULL &&
246 childIndex < pThis->_mfChildren.size() &&
247 childP != pThis->_mfChildren[childIndex] )
249 editMField(ChildrenFieldMask, _mfChildren);
251 _mfChildren.replace(childIndex, childP);
255 //! return true on success, false on child not found
257 bool Node::replaceChildBy(Node * const childP,
258 Node * const newChildP)
260 if(newChildP != NULL && childP != newChildP)
262 Int32 childIdx = findChild(childP);
264 if(childIdx != -1)
266 // do the ref early, to prevent destroys on
267 editMField(ChildrenFieldMask, _mfChildren);
269 _mfChildren.replace(childIdx, newChildP);
271 return true;
275 return false;
278 Int32 Node::findChild(Node * const childP) const
280 UInt32 index;
282 for(index = 0; index < _mfChildren.size(); index++)
284 if( _mfChildren[index] == childP)
285 break;
288 if(index < _mfChildren.size())
290 return index;
292 else
294 return -1;
298 void Node::subChild(Node * const childP)
300 Int32 childIdx = findChild(childP);
302 if(childIdx != -1)
304 editMField(ChildrenFieldMask, _mfChildren);
306 // MFUnrecChildNodePtr::iterator childIt = _mfChildren.begin_nc();
308 // childIt += childIdx;
310 _mfChildren.erase(childIdx);
312 else
314 SWARNING << "Node(" << this << ")::subChild: " << childP
315 << " is not one of my children!" << std::endl;
319 void Node::subChild(UInt32 childIndex)
321 if(childIndex < _mfChildren.size())
323 editMField(ChildrenFieldMask, _mfChildren);
325 // MFUnrecChildNodePtr::iterator childIt = _mfChildren.begin_nc();
327 // childIt += childIndex;
329 _mfChildren.erase(childIndex);
333 void Node::clearChildren(void)
335 editMField(ChildrenFieldMask, _mfChildren);
337 _mfChildren.clear();
340 SizeT Node::getBinSize(ConstFieldMaskArg whichField)
342 SizeT returnValue = Inherited::getBinSize(whichField);
344 if(FieldBits::NoField != (VolumeFieldMask & whichField))
346 returnValue += _sfVolume.getBinSize();
349 if(FieldBits::NoField != (TravMaskFieldMask & whichField))
351 returnValue += _sfTravMask.getBinSize();
354 if(FieldBits::NoField != (ParentFieldMask & whichField))
356 returnValue += _sfParent.getBinSize();
359 if(FieldBits::NoField != (ChildrenFieldMask & whichField))
361 returnValue += _mfChildren.getBinSize();
364 if(FieldBits::NoField != (CoreFieldMask & whichField))
366 returnValue += _sfCore.getBinSize();
369 return returnValue;
372 void Node::copyToBin(BinaryDataHandler &pMem,
373 ConstFieldMaskArg whichField)
375 Inherited::copyToBin(pMem, whichField);
377 if(FieldBits::NoField != (VolumeFieldMask & whichField))
379 _sfVolume.copyToBin(pMem);
382 if(FieldBits::NoField != (TravMaskFieldMask & whichField))
384 _sfTravMask.copyToBin(pMem);
387 if(FieldBits::NoField != (ParentFieldMask & whichField))
389 _sfParent.copyToBin(pMem);
392 if(FieldBits::NoField != (ChildrenFieldMask & whichField))
394 _mfChildren.copyToBin(pMem);
397 if(FieldBits::NoField != (CoreFieldMask & whichField))
399 _sfCore.copyToBin(pMem);
403 void Node::copyFromBin(BinaryDataHandler &pMem,
404 ConstFieldMaskArg whichField)
406 Inherited::copyFromBin(pMem, whichField);
408 if(FieldBits::NoField != (VolumeFieldMask & whichField))
410 _sfVolume.copyFromBin(pMem);
413 if(FieldBits::NoField != (TravMaskFieldMask & whichField))
415 _sfTravMask.copyFromBin(pMem);
418 if(FieldBits::NoField != (ParentFieldMask & whichField))
420 _sfParent.copyFromBin(pMem);
423 if(FieldBits::NoField != (ChildrenFieldMask & whichField))
425 _mfChildren.copyFromBin(pMem);
428 if(FieldBits::NoField != (CoreFieldMask & whichField))
430 _sfCore.copyFromBin(pMem);
434 /*-------------------------------------------------------------------------*/
435 /* Get Transformation */
437 Matrix Node::getToWorld(void)
439 Matrix tmp;
441 getToWorld(tmp);
443 return tmp;
446 void Node::getToWorld(Matrix &result)
448 if(getParent() != NULL)
450 getParent()->getToWorld(result);
452 else
454 result.setIdentity();
457 if(getCore() != NULL)
458 getCore()->accumulateMatrix(result);
461 /*-------------------------------------------------------------------------*/
462 /* Volume */
464 void Node::getWorldVolume(BoxVolume &result)
466 Matrix m;
468 if(getParent() != NULL)
470 getParent()->getToWorld(m);
472 else
474 m.setIdentity();
477 updateVolume();
479 result = getVolume();
480 result.transform(m);
483 void Node::updateVolume(void)
485 // still valid or static, nothing to do
486 if(_sfVolume.getValue().isValid () == true ||
487 _sfVolume.getValue().isStatic() == true ||
488 getTravMask() == 0x0000 )
490 return;
493 // be careful to not change the real volume. If two threads
494 // are updating the same aspect this will lead to chaos
496 BoxVolume vol = _sfVolume.getValue();
498 MFUnrecChildNodePtr::const_iterator cIt =
499 this->getMFChildren()->begin();
500 MFUnrecChildNodePtr::const_iterator cEnd =
501 this->getMFChildren()->end();
503 vol.setEmpty();
505 for(; cIt != cEnd; ++cIt)
507 if(*cIt != NULL && (*cIt)->getTravMask())
509 (*cIt)->updateVolume();
510 vol.extendBy((*cIt)->getVolume());
514 // test for null core. Shouldn't happen, but just in case...
515 if(getCore() != NULL)
517 getCore()->adjustVolume(vol);
520 // don't propagate the static flag from children
521 vol.setStatic(false);
523 editSField(VolumeFieldMask);
525 _sfVolume.setValue(vol);
528 /*-------------------------------------------------------------------------*/
529 /* Constructors */
531 Node::Node(void) :
532 Inherited ( ),
533 _sfVolume ( ),
534 _sfParent (NULL ),
535 _mfChildren(this,
536 ChildrenFieldId,
537 Node::ParentFieldId ),
538 _sfCore (NULL,
539 this,
540 CoreFieldId,
541 NodeCore::ParentsFieldId ),
542 _sfTravMask(TypeTraits<UInt32>::getMax())
543 #ifdef OSG_1_COMPAT
544 ,_occlusionMask(0)
545 #endif
549 Node::Node(const Node &source) :
550 Inherited (source ),
551 _sfVolume ( ),
553 _sfParent (NULL ),
554 _mfChildren (this,
555 ChildrenFieldId,
556 Node::ParentFieldId ),
558 _sfCore (NULL,
559 this,
560 CoreFieldId,
561 NodeCore::ParentsFieldId ),
563 _sfTravMask (source._sfTravMask )
564 #ifdef OSG_1_COMPAT
565 ,_occlusionMask(source._occlusionMask)
566 #endif
569 /*-------------------------------------------------------------------------*/
570 /* Destructor */
572 Node::~Node(void)
576 bool Node::linkParent (FieldContainer * const pParent,
577 UInt16 const childFieldId,
578 UInt16 const parentFieldId)
580 if(parentFieldId == ParentFieldId)
582 Node *pTypedParent = dynamic_cast<Node *>(pParent);
584 if(pTypedParent != NULL)
586 Node *pOldParent = _sfParent.getValue ();
588 if(pOldParent != NULL)
590 pOldParent->unlinkChild(this, ChildrenFieldId);
593 editSField(ParentFieldMask);
595 _sfParent.setValue(pTypedParent, childFieldId);
597 return true;
600 return false;
603 return Inherited::linkParent(pParent, childFieldId, parentFieldId);
606 bool Node::unlinkParent(FieldContainer * const pParent,
607 UInt16 const parentFieldId)
609 if(parentFieldId == ParentFieldId)
611 Node *pTypedParent = dynamic_cast<Node *>(pParent);
613 if(pTypedParent != NULL)
615 if(_sfParent.getValue() == pTypedParent)
617 editSField(ParentFieldMask);
619 _sfParent.setValue(NULL, 0xFFFF);
621 return true;
624 SWARNING << "Child ([" << this
625 << "] id [" << this->getId()
626 << "] type [" << this->getType().getCName()
627 << "] parentFieldId [" << parentFieldId
628 << "]) - Parent ([" << pParent
629 << "] id [" << pParent->getId()
630 << "] type [" << pParent->getType().getCName()
631 << "]): link inconsistent!"
632 << std::endl;
635 return false;
638 return Inherited::unlinkParent(pParent, parentFieldId);
641 bool Node::unlinkChild (FieldContainer * const pChild,
642 UInt16 const childFieldId )
644 if(childFieldId == ChildrenFieldId)
646 Node *pTypedChild = dynamic_cast<Node *>(pChild);
648 if(pTypedChild != NULL)
650 Int32 iChildIdx = _mfChildren.findIndex(pTypedChild);
652 if(iChildIdx != -1)
654 editMField(ParentFieldMask, _mfChildren);
656 _mfChildren.erase(iChildIdx);
658 return true;
661 SWARNING << "Parent ([" << this
662 << "] id [" << this->getId()
663 << "] type [" << this->getType().getCName()
664 << "] childFieldId [" << childFieldId
665 << "]) - Child ([" << pChild
666 << "] id [" << pChild->getId()
667 << "] type [" << pChild->getType().getCName()
668 << "]): link inconsistent!"
669 << std::endl;
671 return false;
674 return false;
677 if(childFieldId == CoreFieldId)
679 NodeCore *pTypedChild = dynamic_cast<NodeCore *>(pChild);
681 if(pTypedChild != NULL)
683 if(_sfCore.getValue() == pTypedChild)
685 editSField(CoreFieldMask);
687 _sfCore.setValue(NULL);
689 return true;
692 SWARNING << "Parent ([" << this
693 << "] id [" << this->getId()
694 << "] type [" << this->getType().getCName()
695 << "] childFieldId [" << childFieldId
696 << "]) - Child ([" << pChild
697 << "] id [" << pChild->getId()
698 << "] type [" << pChild->getType().getCName()
699 << "]): link inconsistent!"
700 << std::endl;
702 return false;
705 return false;
708 return Inherited::unlinkChild(pChild, childFieldId);
711 void Node::invalidateVolume(void)
713 BoxVolume &vol = _sfVolume.getValue();
715 if(vol.isInvalidated() == false && vol.isStatic() == false)
717 editSField(VolumeFieldMask);
719 vol.invalidate();
721 if(getParent() != NULL)
723 getParent()->invalidateVolume();
729 void Node::changed(ConstFieldMaskArg whichField,
730 UInt32 origin,
731 BitVector details )
733 Inherited::changed(whichField, origin, details);
735 if(whichField & (CoreFieldMask | ChildrenFieldMask))
737 invalidateVolume();
740 if(whichField & TravMaskFieldMask)
742 if(getParent() != NULL)
744 getParent()->invalidateVolume();
746 else
748 invalidateVolume();
753 void Node::dump( UInt32 uiIndent,
754 const BitVector bvFlags ) const
756 UInt32 i;
758 indentLog(uiIndent, PLOG);
760 PLOG << "Node"
761 << "("
762 << this->getId()
763 << ") : "
764 << _mfChildren.size()
765 << " children | "
766 // << _attachmentMap.getValue().size()
767 << " attachments | "
768 << "Parent : ";
770 if(_sfParent.getValue() != NULL)
772 PLOG << _sfParent.getValue()->getId() << " | ";
774 else
776 PLOG << "NULL | ";
779 PLOG << std::hex << this << std::dec << std::endl;
781 indentLog(uiIndent, PLOG);
783 PLOG << "[" << std::endl;
785 indentLog(uiIndent + 4, PLOG);
787 PLOG << "Box : " << _sfVolume.getValue() << std::endl;
789 if(_sfCore.getValue() != NULL)
791 _sfCore.getValue()->dump(uiIndent + 4, bvFlags);
793 else
795 indentLog(uiIndent + 4, PLOG);
796 PLOG << "Core : " << "NULL" << std::endl;
799 Inherited::dump(uiIndent + 4, bvFlags);
801 indentLog(uiIndent, PLOG);
802 PLOG << "]" << std::endl;
804 indentLog(uiIndent, PLOG);
806 PLOG << "{" << std::endl;
808 for(i = 0; i < _mfChildren.size(); i++)
810 _mfChildren[i]->dump(uiIndent + 4, bvFlags);
811 PLOG << std::endl;
815 indentLog(uiIndent, PLOG);
817 PLOG << "}" << std::endl;
820 /*-------------------------------------------------------------------------*/
821 /* Assignment */
823 SFBoxVolume *Node::editSFVolume(void)
825 editSField(VolumeFieldMask);
827 return &_sfVolume;
830 const SFBoxVolume *Node::getSFVolume(void) const
832 return &_sfVolume;
835 SFUInt32 *Node::editSFTravMask(void)
837 editSField(TravMaskFieldMask);
839 return &_sfTravMask;
842 const SFUInt32 *Node::getSFTravMask(void) const
844 return &_sfTravMask;
847 const SFParentNodePtr *Node::getSFParent(void) const
849 return &_sfParent;
852 const SFUnrecChildNodeCorePtr *Node::getSFCore(void) const
854 return &_sfCore;
857 const MFUnrecChildNodePtr *Node::getMFChildren(void) const
859 return &_mfChildren;
862 #ifdef OSG_MT_CPTR_ASPECT
863 FieldContainer *Node::createAspectCopy(const FieldContainer *pRefAspect) const
865 Node *returnValue = NULL;
867 newAspectCopy(returnValue,
868 dynamic_cast<const Node *>(pRefAspect),
869 dynamic_cast<const Node *>(this));
871 return returnValue;
873 #endif
875 #ifdef OSG_MT_CPTR_ASPECT
876 void Node::execSyncV( FieldContainer &oFrom,
877 ConstFieldMaskArg whichField,
878 AspectOffsetStore &oOffsets,
879 ConstFieldMaskArg syncMode ,
880 const UInt32 uiSyncInfo)
882 this->execSync(static_cast<Node *>(&oFrom),
883 whichField,
884 oOffsets,
885 syncMode,
886 uiSyncInfo);
888 #endif
890 EditFieldHandlePtr Node::editHandleVolume(void)
892 SFBoxVolume::EditHandlePtr returnValue(
893 new SFBoxVolume::EditHandle(
894 &_sfVolume,
895 this->getType().getFieldDesc(VolumeFieldId),
896 this));
898 editSField(VolumeFieldMask);
900 return returnValue;
903 GetFieldHandlePtr Node::getHandleVolume(void) const
905 SFBoxVolume::GetHandlePtr returnValue(
906 new SFBoxVolume::GetHandle(
907 &_sfVolume,
908 this->getType().getFieldDesc(VolumeFieldId),
909 const_cast<Node *>(this)));
911 return returnValue;
914 EditFieldHandlePtr Node::editHandleTravMask(void)
916 SFUInt32::EditHandlePtr returnValue(
917 new SFUInt32::EditHandle(
918 &_sfTravMask,
919 this->getType().getFieldDesc(TravMaskFieldId),
920 this));
922 editSField(TravMaskFieldMask);
924 return returnValue;
927 GetFieldHandlePtr Node::getHandleTravMask(void) const
929 SFUInt32::GetHandlePtr returnValue(
930 new SFUInt32::GetHandle(
931 &_sfTravMask,
932 this->getType().getFieldDesc(TravMaskFieldId),
933 const_cast<Node *>(this)));
935 return returnValue;
938 GetFieldHandlePtr Node::getHandleParent(void) const
940 SFParentNodePtr::GetHandlePtr returnValue(
941 new SFParentNodePtr::GetHandle(
942 &_sfParent,
943 this->getType().getFieldDesc(ParentFieldId),
944 const_cast<Node *>(this)));
946 return returnValue;
949 EditFieldHandlePtr Node::editHandleCore(void)
951 SFUnrecChildNodeCorePtr::EditHandlePtr returnValue(
952 new SFUnrecChildNodeCorePtr::EditHandle(
953 &_sfCore,
954 this->getType().getFieldDesc(CoreFieldId),
955 this));
957 typedef void (Node::*SetCoreF)(NodeCore * const);
959 SetCoreF fFunc = &Node::setCore;
961 returnValue->setSetMethod(boost::bind(fFunc, this, _1));
963 editSField(CoreFieldMask);
965 return returnValue;
968 GetFieldHandlePtr Node::getHandleCore(void) const
970 SFUnrecChildNodeCorePtr::GetHandlePtr returnValue(
971 new SFUnrecChildNodeCorePtr::GetHandle(
972 &_sfCore,
973 this->getType().getFieldDesc(CoreFieldId),
974 const_cast<Node *>(this)));
976 return returnValue;
979 EditFieldHandlePtr Node::editHandleChildren(void)
981 MFUnrecChildNodePtr::EditHandlePtr returnValue(
982 new MFUnrecChildNodePtr::EditHandle(
983 &_mfChildren,
984 this->getType().getFieldDesc(ChildrenFieldId),
985 this));
987 typedef void (Node::*AddChildF)(Node * const);
989 AddChildF fFunc = &Node::addChild;
991 returnValue->setAddMethod(boost::bind(fFunc, this, _1));
993 editMField(ChildrenFieldMask, _mfChildren);
995 return returnValue;
998 GetFieldHandlePtr Node::getHandleChildren(void) const
1000 MFUnrecChildNodePtr::GetHandlePtr returnValue(
1001 new MFUnrecChildNodePtr::GetHandle(
1002 &_mfChildren,
1003 this->getType().getFieldDesc(ChildrenFieldId),
1004 const_cast<Node *>(this)));
1006 return returnValue;
1009 void Node::resolveLinks(void)
1011 Inherited::resolveLinks();
1013 editSField(CoreFieldMask);
1014 _sfCore.setValue(NULL);
1016 editMField(ChildrenFieldMask, _mfChildren);
1017 _mfChildren.clear();
1020 /*---------------------------------------------------------------------*/
1021 /*! \name Node cloning */
1022 /*! \{ */
1024 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1025 especially NodeCores, are shared, only if a container's type name is in
1026 \a cloneTypeNames or if it belonfs to a group in \a cloneGroupNames it is
1027 cloned. If a container's type is in \a ignoreTypeNames or belongs to a
1028 group in \a ignoreGroupNames it is ignored altogether.
1030 \param[in] rootNode Root of the scene to clone.
1031 \param[in] cloneTypeNames List of type names that are cloned.
1032 \param[in] ignoreTypeNames List of type names that are ignored.
1033 \param[in] cloneGroupNames List of group names that are cloned.
1034 \param[in] ignoreGroupNames LIst of group names that are ignored.
1035 \return The root Node of the cloned scene.
1037 \ingroup GrpBaseFieldContainerNodes
1038 \relatesalso Node
1041 NodeTransitPtr cloneTree(const OSG::Node *rootNode,
1042 const std::vector<std::string> &cloneTypeNames,
1043 const std::vector<std::string> &ignoreTypeNames,
1044 const std::vector<std::string> &cloneGroupNames,
1045 const std::vector<std::string> &ignoreGroupNames)
1047 std::vector<const ReflexiveContainerType *> cloneTypes;
1048 std::vector<const ReflexiveContainerType *> ignoreTypes;
1049 std::vector<UInt16> cloneGroupIds;
1050 std::vector<UInt16> ignoreGroupIds;
1052 appendTypesVector (cloneTypeNames, cloneTypes );
1053 appendTypesVector (ignoreTypeNames, ignoreTypes );
1054 appendGroupsVector(cloneGroupNames, cloneGroupIds );
1055 appendGroupsVector(ignoreGroupNames, ignoreGroupIds);
1057 return cloneTree(rootNode, cloneTypes, ignoreTypes,
1058 cloneGroupIds, ignoreGroupIds);
1061 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1062 especially NodeCores, are shared, only if a container's group id is in
1063 \a cloneGroupIds it is cloned. If a container's group id is in
1064 \a ignoreGroupIds it is ignored altogether.
1066 \param[in] rootNode Root of the scene to clone.
1067 \param[in] cloneGroupIds List of group ids, whose members are cloned.
1068 \param[in] ignoreGroupIds List of group ids, whose members are ignored.
1069 \return The root Node of the cloned scene.
1071 \ingroup GrpBaseFieldContainerNodes
1072 \relatesalso Node
1075 NodeTransitPtr cloneTree(const OSG::Node *rootNode,
1076 const std::vector<OSG::UInt16> &cloneGroupIds,
1077 const std::vector<OSG::UInt16> &ignoreGroupIds)
1079 std::vector<const ReflexiveContainerType *> cloneTypes;
1080 std::vector<const ReflexiveContainerType *> ignoreTypes;
1082 return cloneTree(rootNode, cloneTypes, ignoreTypes,
1083 cloneGroupIds, ignoreGroupIds);
1086 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1087 especially NodeCores, are shared, only if a container's type name is in
1088 \a cloneTypesString it is cloned. If a container's type is in
1089 \a ignoreTypesString it is ignored altogether.
1091 \param[in] rootNode Root of the scene to clone.
1092 \param[in] cloneTypesString Comma separated string of type names that are
1093 cloned instead of shared.
1094 \param[in] ignoreTypesString Comma separated string of type names that are
1095 ignored.
1096 \return The root Node of the cloned scene.
1098 \ingroup GrpBaseFieldContainerNodes
1099 \relatesalso Node
1102 NodeTransitPtr cloneTree(const OSG::Node *rootNode,
1103 const std::string &cloneTypesString,
1104 const std::string &ignoreTypesString)
1106 std::vector<const ReflexiveContainerType *> cloneTypes;
1107 std::vector<const ReflexiveContainerType *> ignoreTypes;
1108 std::vector<UInt16> cloneGroupIds;
1109 std::vector<UInt16> ignoreGroupIds;
1111 appendTypesString(cloneTypesString, cloneTypes);
1112 appendTypesString(ignoreTypesString, ignoreTypes);
1114 return cloneTree(rootNode, cloneTypes, ignoreTypes,
1115 cloneGroupIds, ignoreGroupIds);
1118 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1119 especially NodeCores, are shared, only if a container's type is in
1120 \a cloneTypes of belongs to a group in \a cloneGroupIds it is cloned.
1121 If a container's type is in \a ignoreTypes or belongs to a group in
1122 \a ignoreGroupIds it is ignored altogether.
1124 \param[in] rootNode Root of the scene to clone.
1125 \param[in] cloneTypes List of types to clone instead of share.
1126 \param[in] ignoreTypes List of types to ignore.
1127 \param[in] cloneGroupIds List of group ids, whose members are cloned.
1128 \param[in] ignoreGroupIds List of group ids, whose members are ignored.
1129 \return The root Node of the cloned scene.
1131 \ingroup GrpBaseFieldContainerNodes
1132 \relatesalso Node
1135 NodeTransitPtr cloneTree(
1136 const OSG::Node *rootNode,
1137 const std::vector<const OSG::ReflexiveContainerType *> &cloneTypes,
1138 const std::vector<const OSG::ReflexiveContainerType *> &ignoreTypes,
1139 const std::vector<OSG::UInt16> &cloneGroupIds,
1140 const std::vector<OSG::UInt16> &ignoreGroupIds)
1142 NodeUnrecPtr rootClone(NULL);
1144 if(rootNode != NULL)
1146 NodeUnrecPtr childClone;
1147 NodeCore *core = rootNode->getCore();
1149 rootClone = Node::create();
1150 rootClone->setTravMask(rootNode->getTravMask());
1152 cloneAttachments(rootNode, rootClone,
1153 cloneTypes, ignoreTypes,
1154 cloneGroupIds, ignoreGroupIds);
1156 if(core != NULL)
1158 NodeCoreUnrecPtr coreClone = NULL;
1159 const FieldContainerType &coreType = core->getType();
1161 // test if core type should NOT be ignored
1162 if(!TypePredicates::typeInGroupIds(
1163 ignoreGroupIds.begin(),
1164 ignoreGroupIds.end(), coreType) &&
1165 !TypePredicates::typeDerivedFrom(
1166 ignoreTypes.begin(),
1167 ignoreTypes.end(), coreType) )
1169 // test if core should cloned
1170 if(TypePredicates::typeInGroupIds (
1171 cloneGroupIds.begin(),
1172 cloneGroupIds.end(), coreType) ||
1173 TypePredicates::typeDerivedFrom(
1174 cloneTypes.begin(),
1175 cloneTypes.end(), coreType) )
1177 // clone core
1178 coreClone =
1179 dynamic_pointer_cast<NodeCore>(
1180 deepClone(core,
1181 cloneTypes, ignoreTypes,
1182 cloneGroupIds, ignoreGroupIds));
1184 else
1186 // share core
1187 coreClone = core;
1191 rootClone->setCore(coreClone);
1194 for(UInt32 i = 0; i < rootNode->getNChildren(); ++i)
1196 childClone = cloneTree(rootNode->getChild(i),
1197 cloneTypes, ignoreTypes,
1198 cloneGroupIds, ignoreGroupIds);
1200 rootClone->addChild(childClone);
1204 return NodeTransitPtr(rootClone);
1207 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1208 especially NodeCores, are cloned, only if a container's type name is in
1209 \a shareTypeNames or if it belonfs to a group in \a shareGroupNames it is
1210 shared. If a container's type is in \a ignoreTypeNames or belongs to a
1211 group in \a ignoreGroupNames it is ignored altogether.
1213 \param[in] rootNode Root of the scene to clone.
1214 \param[in] shareTypeNames List of type names that are shared.
1215 \param[in] ignoreTypeNames List of type names that are ignored.
1216 \param[in] shareGroupNames List of group names that are shared.
1217 \param[in] ignoreGroupNames LIst of group names that are ignored.
1218 \return The root Node of the cloned scene.
1220 \ingroup GrpBaseFieldContainerNodes
1221 \relatesalso Node
1224 NodeTransitPtr deepCloneTree(const OSG::Node *rootNode,
1225 const std::vector<std::string> &shareTypeNames,
1226 const std::vector<std::string> &ignoreTypeNames,
1227 const std::vector<std::string> &shareGroupNames,
1228 const std::vector<std::string> &ignoreGroupNames)
1230 std::vector<const ReflexiveContainerType *> shareTypes;
1231 std::vector<const ReflexiveContainerType *> ignoreTypes;
1232 std::vector<UInt16> shareGroupIds;
1233 std::vector<UInt16> ignoreGroupIds;
1235 appendTypesVector (shareTypeNames, shareTypes );
1236 appendTypesVector (ignoreTypeNames, ignoreTypes );
1237 appendGroupsVector(shareGroupNames, shareGroupIds );
1238 appendGroupsVector(ignoreGroupNames, ignoreGroupIds);
1240 return deepCloneTree(rootNode, shareTypes, ignoreTypes,
1241 shareGroupIds, ignoreGroupIds);
1244 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1245 especially NodeCores, are cloned, only if a container's group id is in
1246 \a shareGroupIds it is shared. If a container's group id is in
1247 \a ignoreGroupIds it is ignored altogether.
1249 \param[in] rootNode Root of the scene to clone.
1250 \param[in] shareGroupIds List of group ids, whose members are shared.
1251 \param[in] ignoreGroupIds List of group ids, whose members are ignored.
1252 \return The root Node of the cloned scene.
1254 \ingroup GrpBaseFieldContainerNodes
1255 \relatesalso Node
1258 NodeTransitPtr deepCloneTree(const OSG::Node *rootNode,
1259 const std::vector<OSG::UInt16> &shareGroupIds,
1260 const std::vector<OSG::UInt16> &ignoreGroupIds)
1262 std::vector<const ReflexiveContainerType *> shareTypes;
1263 std::vector<const ReflexiveContainerType *> ignoreTypes;
1265 return deepCloneTree(rootNode, shareTypes, ignoreTypes,
1266 shareGroupIds, ignoreGroupIds);
1269 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1270 especially NodeCores, are cloned, only if a container's type name is in
1271 \a shareTypesString it is shared. If a container's type is in
1272 \a ignoreTypesString it is ignored altogether.
1274 \param[in] rootNode Root of the scene to clone.
1275 \param[in] shareTypesString Comma separated string of type names that are
1276 shared instead of cloned.
1277 \param[in] ignoreTypesString Comma separated string of type names that are
1278 ignored.
1279 \return The root Node of the cloned scene.
1281 \ingroup GrpBaseFieldContainerNodes
1282 \relatesalso Node
1285 NodeTransitPtr deepCloneTree(const Node *rootNode,
1286 const std::string &shareTypesString,
1287 const std::string &ignoreTypesString)
1289 std::vector<const ReflexiveContainerType *> shareTypes;
1290 std::vector<const ReflexiveContainerType *> ignoreTypes;
1291 std::vector<UInt16> shareGroupIds;
1292 std::vector<UInt16> ignoreGroupIds;
1294 appendTypesString(shareTypesString, shareTypes);
1295 appendTypesString(ignoreTypesString, ignoreTypes);
1297 return deepCloneTree(rootNode, shareTypes, ignoreTypes,
1298 shareGroupIds, ignoreGroupIds);
1301 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1302 especially NodeCores, are cloned, only if a container's type is in
1303 \a shareTypes of belongs to a group in \a shareGroupIds it is shared.
1304 If a container's type is in \a ignoreTypes or belongs to a group in
1305 \a ignoreGroupIds it is ignored altogether.
1307 \param[in] rootNode Root of the scene to clone.
1308 \param[in] shareTypes List of types to share instead of clone.
1309 \param[in] ignoreTypes List of types to ignore.
1310 \param[in] shareGroupIds List of group ids, whose members are shared.
1311 \param[in] ignoreGroupIds List of group ids, whose members are ignored.
1312 \return The root Node of the cloned scene.
1314 \ingroup GrpBaseFieldContainerNodes
1315 \relatesalso Node
1318 NodeTransitPtr deepCloneTree(
1319 const OSG::Node *rootNode,
1320 const std::vector<const OSG::ReflexiveContainerType *> &shareTypes,
1321 const std::vector<const OSG::ReflexiveContainerType *> &ignoreTypes,
1322 const std::vector<OSG::UInt16> &shareGroupIds,
1323 const std::vector<OSG::UInt16> &ignoreGroupIds)
1325 NodeUnrecPtr rootClone(NULL);
1327 if(rootNode != NULL)
1329 NodeUnrecPtr childClone;
1330 NodeCore *core = rootNode->getCore();
1332 rootClone = Node::create();
1333 rootClone->setTravMask(rootNode->getTravMask());
1335 deepCloneAttachments(rootNode, rootClone,
1336 shareTypes, ignoreTypes,
1337 shareGroupIds, ignoreGroupIds);
1339 if(core != NULL)
1341 NodeCoreUnrecPtr coreClone(NULL);
1342 const FieldContainerType &coreType = core->getType();
1344 // test if core type should NOT be ignored
1345 if(!TypePredicates::typeInGroupIds (
1346 ignoreGroupIds.begin(),
1347 ignoreGroupIds.end(), coreType) &&
1348 !TypePredicates::typeDerivedFrom(
1349 ignoreTypes.begin(),
1350 ignoreTypes.end(), coreType) )
1352 // test if core should be shared
1353 if(TypePredicates::typeInGroupIds (
1354 shareGroupIds.begin(),
1355 shareGroupIds.end(), coreType) ||
1356 TypePredicates::typeDerivedFrom(
1357 shareTypes.begin(),
1358 shareTypes.end(), coreType) )
1360 // share core
1361 coreClone = core;
1363 else
1365 // clone core
1366 coreClone =
1367 dynamic_pointer_cast<NodeCore>(
1368 deepClone(core,
1369 shareTypes, ignoreTypes,
1370 shareGroupIds, ignoreGroupIds));
1374 rootClone->setCore(coreClone);
1377 for(UInt32 i = 0; i < rootNode->getNChildren(); ++i)
1379 childClone = deepCloneTree(rootNode->getChild(i),
1380 shareTypes, ignoreTypes,
1381 shareGroupIds, ignoreGroupIds);
1383 rootClone->addChild(childClone);
1387 return NodeTransitPtr(rootClone);
1390 /*! \} */
1391 /*---------------------------------------------------------------------*/
1393 OSG_END_NAMESPACE