1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2003 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
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. *
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. *
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. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
46 #include "OSGConfig.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)
63 /***************************************************************************\
65 \***************************************************************************/
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 /***************************************************************************\
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
97 /*! \var NodeCorePtr Node::_sfCore
100 void Node::classDescInserter(TypeObject
&oType
)
102 FieldDescriptionBase
*pDesc
= NULL
;
104 pDesc
= new SFBoxVolume::Description(
105 SFBoxVolume::getClassType(),
107 "Bounding volume for the node.",
108 OSG_RC_FIELD_DESC(Node::Volume
),
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(),
120 "Traversal mask for the node.",
121 OSG_RC_FIELD_DESC(Node::TravMask
),
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(),
133 "This node's parent.",
134 OSG_RC_FIELD_DESC(Node::Parent
),
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(),
146 "The core to use for this node.",
147 OSG_RC_FIELD_DESC(Node::Core
),
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(),
159 "A list of our children in the scene graph.",
160 OSG_RC_FIELD_DESC(Node::Children
),
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(),
174 reinterpret_cast<PrototypeCreateF
>(&Node::createEmptyLocal
),
177 reinterpret_cast<InitalInsertDescFunc
>(&Node::classDescInserter
),
182 OSG_FIELD_CONTAINER_DEF(Node
)
186 /*-------------------------------------------------------------------------*/
189 void Node::addChild(Node
* const childP
)
193 // do the ref early, to prevent destroys on getParent(a)->addChild(a)
195 editMField(ChildrenFieldMask
, _mfChildren
);
197 _mfChildren
.push_back(childP
);
201 void Node::addChild(NodeTransitPtr childP
)
205 editMField(ChildrenFieldMask
, _mfChildren
);
207 NodeUnrecPtr tmpChild
= childP
;
209 _mfChildren
.push_back(tmpChild
);
213 /*! Insert child node into child list.
214 * Upon completion, getChild(childIndex) will return the new child.
215 * (ie. child is at childIndex pos in list)
216 * All other children after childIndex are moved back in list.
217 * If childP is Null, does nothing.
219 * \warning childP is not ranged checked. Out of range values will have undefined behavior.
220 * \param childIndex The location in the list to put the new child.
221 * \param childP Pointer to the child to insert.
223 void Node::insertChild(UInt32 childIndex
, Node
* const childP
)
225 OSG_ASSERT((childIndex
<= getNChildren()) && "Child index out of range");
230 editMField(ChildrenFieldMask
, _mfChildren
);
232 MFUnrecChildNodePtr::iterator childIt
= _mfChildren
.begin_nc();
234 childIt
+= childIndex
;
236 _mfChildren
.insert(childIt
, childP
);
240 void Node::replaceChild(UInt32 childIndex
, Node
* const childP
)
242 const Node
*pThis
= this;
245 childIndex
< pThis
->_mfChildren
.size() &&
246 childP
!= pThis
->_mfChildren
[childIndex
] )
248 editMField(ChildrenFieldMask
, _mfChildren
);
250 _mfChildren
.replace(childIndex
, childP
);
254 //! return true on success, false on child not found
256 bool Node::replaceChildBy(Node
* const childP
,
257 Node
* const newChildP
)
259 if(newChildP
!= NULL
&& childP
!= newChildP
)
261 Int32 childIdx
= findChild(childP
);
265 // do the ref early, to prevent destroys on
266 editMField(ChildrenFieldMask
, _mfChildren
);
268 _mfChildren
.replace(childIdx
, newChildP
);
277 Int32
Node::findChild(Node
* const childP
) const
281 for(index
= 0; index
< _mfChildren
.size(); index
++)
283 if( _mfChildren
[index
] == childP
)
287 if(index
< _mfChildren
.size())
297 void Node::subChild(Node
* const childP
)
299 Int32 childIdx
= findChild(childP
);
303 editMField(ChildrenFieldMask
, _mfChildren
);
305 // MFUnrecChildNodePtr::iterator childIt = _mfChildren.begin_nc();
307 // childIt += childIdx;
309 _mfChildren
.erase(childIdx
);
313 SWARNING
<< "Node(" << this << ")::subChild: " << childP
314 << " is not one of my children!" << std::endl
;
318 void Node::subChild(UInt32 childIndex
)
320 if(childIndex
< _mfChildren
.size())
322 editMField(ChildrenFieldMask
, _mfChildren
);
324 // MFUnrecChildNodePtr::iterator childIt = _mfChildren.begin_nc();
326 // childIt += childIndex;
328 _mfChildren
.erase(childIndex
);
332 void Node::clearChildren(void)
334 editMField(ChildrenFieldMask
, _mfChildren
);
339 SizeT
Node::getBinSize(ConstFieldMaskArg whichField
)
341 SizeT returnValue
= Inherited::getBinSize(whichField
);
343 if(FieldBits::NoField
!= (VolumeFieldMask
& whichField
))
345 returnValue
+= _sfVolume
.getBinSize();
348 if(FieldBits::NoField
!= (TravMaskFieldMask
& whichField
))
350 returnValue
+= _sfTravMask
.getBinSize();
353 if(FieldBits::NoField
!= (ParentFieldMask
& whichField
))
355 returnValue
+= _sfParent
.getBinSize();
358 if(FieldBits::NoField
!= (ChildrenFieldMask
& whichField
))
360 returnValue
+= _mfChildren
.getBinSize();
363 if(FieldBits::NoField
!= (CoreFieldMask
& whichField
))
365 returnValue
+= _sfCore
.getBinSize();
371 void Node::copyToBin(BinaryDataHandler
&pMem
,
372 ConstFieldMaskArg whichField
)
374 Inherited::copyToBin(pMem
, whichField
);
376 if(FieldBits::NoField
!= (VolumeFieldMask
& whichField
))
378 _sfVolume
.copyToBin(pMem
);
381 if(FieldBits::NoField
!= (TravMaskFieldMask
& whichField
))
383 _sfTravMask
.copyToBin(pMem
);
386 if(FieldBits::NoField
!= (ParentFieldMask
& whichField
))
388 _sfParent
.copyToBin(pMem
);
391 if(FieldBits::NoField
!= (ChildrenFieldMask
& whichField
))
393 _mfChildren
.copyToBin(pMem
);
396 if(FieldBits::NoField
!= (CoreFieldMask
& whichField
))
398 _sfCore
.copyToBin(pMem
);
402 void Node::copyFromBin(BinaryDataHandler
&pMem
,
403 ConstFieldMaskArg whichField
)
405 Inherited::copyFromBin(pMem
, whichField
);
407 if(FieldBits::NoField
!= (VolumeFieldMask
& whichField
))
409 _sfVolume
.copyFromBin(pMem
);
412 if(FieldBits::NoField
!= (TravMaskFieldMask
& whichField
))
414 _sfTravMask
.copyFromBin(pMem
);
417 if(FieldBits::NoField
!= (ParentFieldMask
& whichField
))
419 _sfParent
.copyFromBin(pMem
);
422 if(FieldBits::NoField
!= (ChildrenFieldMask
& whichField
))
424 _mfChildren
.copyFromBin(pMem
);
427 if(FieldBits::NoField
!= (CoreFieldMask
& whichField
))
429 _sfCore
.copyFromBin(pMem
);
433 /*-------------------------------------------------------------------------*/
434 /* Get Transformation */
436 Matrix
Node::getToWorld(void)
445 void Node::getToWorld(Matrix
&result
)
447 if(getParent() != NULL
)
449 getParent()->getToWorld(result
);
453 result
.setIdentity();
456 if(getCore() != NULL
)
457 getCore()->accumulateMatrix(result
);
460 /*-------------------------------------------------------------------------*/
463 void Node::getWorldVolume(BoxVolume
&result
)
467 if(getParent() != NULL
)
469 getParent()->getToWorld(m
);
478 result
= getVolume();
482 void Node::updateVolume(void)
484 // still valid or static, nothing to do
485 if(_sfVolume
.getValue().isValid () == true ||
486 _sfVolume
.getValue().isStatic() == true ||
487 getTravMask() == 0x0000 )
492 // be careful to not change the real volume. If two threads
493 // are updating the same aspect this will lead to chaos
495 BoxVolume vol
= _sfVolume
.getValue();
497 MFUnrecChildNodePtr::const_iterator cIt
=
498 this->getMFChildren()->begin();
499 MFUnrecChildNodePtr::const_iterator cEnd
=
500 this->getMFChildren()->end();
504 for(; cIt
!= cEnd
; ++cIt
)
506 if(*cIt
!= NULL
&& (*cIt
)->getTravMask())
508 (*cIt
)->updateVolume();
509 vol
.extendBy((*cIt
)->getVolume());
513 // test for null core. Shouldn't happen, but just in case...
514 if(getCore() != NULL
)
516 getCore()->adjustVolume(vol
);
519 // don't propagate the static flag from children
520 vol
.setStatic(false);
522 editSField(VolumeFieldMask
);
524 _sfVolume
.setValue(vol
);
527 /*-------------------------------------------------------------------------*/
536 Node::ParentFieldId
),
540 NodeCore::ParentsFieldId
),
541 _sfTravMask(TypeTraits
<UInt32
>::getMax())
548 Node::Node(const Node
&source
) :
555 Node::ParentFieldId
),
560 NodeCore::ParentsFieldId
),
562 _sfTravMask (source
._sfTravMask
)
564 ,_occlusionMask(source
._occlusionMask
)
568 /*-------------------------------------------------------------------------*/
575 bool Node::linkParent (FieldContainer
* const pParent
,
576 UInt16
const childFieldId
,
577 UInt16
const parentFieldId
)
579 if(parentFieldId
== ParentFieldId
)
581 Node
*pTypedParent
= dynamic_cast<Node
*>(pParent
);
583 if(pTypedParent
!= NULL
)
585 Node
*pOldParent
= _sfParent
.getValue ();
587 if(pOldParent
!= NULL
)
589 pOldParent
->unlinkChild(this, ChildrenFieldId
);
592 editSField(ParentFieldMask
);
594 _sfParent
.setValue(pTypedParent
, childFieldId
);
602 return Inherited::linkParent(pParent
, childFieldId
, parentFieldId
);
605 bool Node::unlinkParent(FieldContainer
* const pParent
,
606 UInt16
const parentFieldId
)
608 if(parentFieldId
== ParentFieldId
)
610 Node
*pTypedParent
= dynamic_cast<Node
*>(pParent
);
612 if(pTypedParent
!= NULL
)
614 if(_sfParent
.getValue() == pTypedParent
)
616 editSField(ParentFieldMask
);
618 _sfParent
.setValue(NULL
, 0xFFFF);
623 SWARNING
<< "Child ([" << this
624 << "] id [" << this->getId()
625 << "] type [" << this->getType().getCName()
626 << "] parentFieldId [" << parentFieldId
627 << "]) - Parent ([" << pParent
628 << "] id [" << pParent
->getId()
629 << "] type [" << pParent
->getType().getCName()
630 << "]): link inconsistent!"
637 return Inherited::unlinkParent(pParent
, parentFieldId
);
640 bool Node::unlinkChild (FieldContainer
* const pChild
,
641 UInt16
const childFieldId
)
643 if(childFieldId
== ChildrenFieldId
)
645 Node
*pTypedChild
= dynamic_cast<Node
*>(pChild
);
647 if(pTypedChild
!= NULL
)
649 Int32 iChildIdx
= _mfChildren
.findIndex(pTypedChild
);
653 editMField(ParentFieldMask
, _mfChildren
);
655 _mfChildren
.erase(iChildIdx
);
660 SWARNING
<< "Parent ([" << this
661 << "] id [" << this->getId()
662 << "] type [" << this->getType().getCName()
663 << "] childFieldId [" << childFieldId
664 << "]) - Child ([" << pChild
665 << "] id [" << pChild
->getId()
666 << "] type [" << pChild
->getType().getCName()
667 << "]): link inconsistent!"
676 if(childFieldId
== CoreFieldId
)
678 NodeCore
*pTypedChild
= dynamic_cast<NodeCore
*>(pChild
);
680 if(pTypedChild
!= NULL
)
682 if(_sfCore
.getValue() == pTypedChild
)
684 editSField(CoreFieldMask
);
686 _sfCore
.setValue(NULL
);
691 SWARNING
<< "Parent ([" << this
692 << "] id [" << this->getId()
693 << "] type [" << this->getType().getCName()
694 << "] childFieldId [" << childFieldId
695 << "]) - Child ([" << pChild
696 << "] id [" << pChild
->getId()
697 << "] type [" << pChild
->getType().getCName()
698 << "]): link inconsistent!"
707 return Inherited::unlinkChild(pChild
, childFieldId
);
710 void Node::invalidateVolume(void)
712 BoxVolume
&vol
= _sfVolume
.getValue();
714 if(vol
.isValid() == true && vol
.isStatic() == false)
716 editSField(VolumeFieldMask
);
720 if(getParent() != NULL
)
722 getParent()->invalidateVolume();
727 void Node::changed(ConstFieldMaskArg whichField
,
731 Inherited::changed(whichField
, origin
, details
);
733 if(whichField
& (CoreFieldMask
| ChildrenFieldMask
))
738 if(whichField
& TravMaskFieldMask
)
740 if(getParent() != NULL
)
742 getParent()->invalidateVolume();
751 void Node::dump( UInt32 uiIndent
,
752 const BitVector bvFlags
) const
756 indentLog(uiIndent
, PLOG
);
762 << _mfChildren
.size()
764 // << _attachmentMap.getValue().size()
766 << "Parent : " << std::hex
;
768 if(_sfParent
.getValue() != NULL
)
770 PLOG
<< _sfParent
.getValue()->getId() << " | ";
777 PLOG
<< this << std::dec
<< std::endl
;
779 indentLog(uiIndent
, PLOG
);
781 PLOG
<< "[" << std::endl
;
783 if(_sfCore
.getValue() != NULL
)
785 _sfCore
.getValue()->dump(uiIndent
+ 4, bvFlags
);
789 indentLog(uiIndent
+ 4, PLOG
);
790 PLOG
<< "Core : " << "NULL" << std::endl
;
793 Inherited::dump(uiIndent
+ 4, bvFlags
);
795 indentLog(uiIndent
, PLOG
);
796 PLOG
<< "]" << std::endl
;
798 indentLog(uiIndent
, PLOG
);
800 PLOG
<< "{" << std::endl
;
802 for(i
= 0; i
< _mfChildren
.size(); i
++)
804 _mfChildren
[i
]->dump(uiIndent
+ 4, bvFlags
);
809 indentLog(uiIndent
, PLOG
);
811 PLOG
<< "}" << std::endl
;
814 /*-------------------------------------------------------------------------*/
817 SFBoxVolume
*Node::editSFVolume(void)
819 editSField(VolumeFieldMask
);
824 const SFBoxVolume
*Node::getSFVolume(void) const
829 SFUInt32
*Node::editSFTravMask(void)
831 editSField(TravMaskFieldMask
);
836 const SFUInt32
*Node::getSFTravMask(void) const
841 const SFParentNodePtr
*Node::getSFParent(void) const
846 const SFUnrecChildNodeCorePtr
*Node::getSFCore(void) const
851 const MFUnrecChildNodePtr
*Node::getMFChildren(void) const
856 #ifdef OSG_MT_CPTR_ASPECT
857 FieldContainer
*Node::createAspectCopy(const FieldContainer
*pRefAspect
) const
859 Node
*returnValue
= NULL
;
861 newAspectCopy(returnValue
,
862 dynamic_cast<const Node
*>(pRefAspect
),
863 dynamic_cast<const Node
*>(this));
869 #ifdef OSG_MT_CPTR_ASPECT
870 void Node::execSyncV( FieldContainer
&oFrom
,
871 ConstFieldMaskArg whichField
,
872 AspectOffsetStore
&oOffsets
,
873 ConstFieldMaskArg syncMode
,
874 const UInt32 uiSyncInfo
)
876 this->execSync(static_cast<Node
*>(&oFrom
),
884 EditFieldHandlePtr
Node::editHandleVolume(void)
886 SFBoxVolume::EditHandlePtr
returnValue(
887 new SFBoxVolume::EditHandle(
889 this->getType().getFieldDesc(VolumeFieldId
),
892 editSField(VolumeFieldMask
);
897 GetFieldHandlePtr
Node::getHandleVolume(void) const
899 SFBoxVolume::GetHandlePtr
returnValue(
900 new SFBoxVolume::GetHandle(
902 this->getType().getFieldDesc(VolumeFieldId
),
903 const_cast<Node
*>(this)));
908 EditFieldHandlePtr
Node::editHandleTravMask(void)
910 SFUInt32::EditHandlePtr
returnValue(
911 new SFUInt32::EditHandle(
913 this->getType().getFieldDesc(TravMaskFieldId
),
916 editSField(TravMaskFieldMask
);
921 GetFieldHandlePtr
Node::getHandleTravMask(void) const
923 SFUInt32::GetHandlePtr
returnValue(
924 new SFUInt32::GetHandle(
926 this->getType().getFieldDesc(TravMaskFieldId
),
927 const_cast<Node
*>(this)));
932 GetFieldHandlePtr
Node::getHandleParent(void) const
934 SFParentNodePtr::GetHandlePtr
returnValue(
935 new SFParentNodePtr::GetHandle(
937 this->getType().getFieldDesc(ParentFieldId
),
938 const_cast<Node
*>(this)));
943 EditFieldHandlePtr
Node::editHandleCore(void)
945 SFUnrecChildNodeCorePtr::EditHandlePtr
returnValue(
946 new SFUnrecChildNodeCorePtr::EditHandle(
948 this->getType().getFieldDesc(CoreFieldId
),
951 typedef void (Node::*SetCoreF
)(NodeCore
* const);
953 SetCoreF fFunc
= &Node::setCore
;
955 returnValue
->setSetMethod(boost::bind(fFunc
, this, _1
));
957 editSField(CoreFieldMask
);
962 GetFieldHandlePtr
Node::getHandleCore(void) const
964 SFUnrecChildNodeCorePtr::GetHandlePtr
returnValue(
965 new SFUnrecChildNodeCorePtr::GetHandle(
967 this->getType().getFieldDesc(CoreFieldId
),
968 const_cast<Node
*>(this)));
973 EditFieldHandlePtr
Node::editHandleChildren(void)
975 MFUnrecChildNodePtr::EditHandlePtr
returnValue(
976 new MFUnrecChildNodePtr::EditHandle(
978 this->getType().getFieldDesc(ChildrenFieldId
),
981 typedef void (Node::*AddChildF
)(Node
* const);
983 AddChildF fFunc
= &Node::addChild
;
985 returnValue
->setAddMethod(boost::bind(fFunc
, this, _1
));
987 editMField(ChildrenFieldMask
, _mfChildren
);
992 GetFieldHandlePtr
Node::getHandleChildren(void) const
994 MFUnrecChildNodePtr::GetHandlePtr
returnValue(
995 new MFUnrecChildNodePtr::GetHandle(
997 this->getType().getFieldDesc(ChildrenFieldId
),
998 const_cast<Node
*>(this)));
1003 void Node::resolveLinks(void)
1005 Inherited::resolveLinks();
1007 editSField(CoreFieldMask
);
1008 _sfCore
.setValue(NULL
);
1010 editMField(ChildrenFieldMask
, _mfChildren
);
1011 _mfChildren
.clear();
1014 /*---------------------------------------------------------------------*/
1015 /*! \name Node cloning */
1018 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1019 especially NodeCores, are shared, only if a container's type name is in
1020 \a cloneTypeNames or if it belonfs to a group in \a cloneGroupNames it is
1021 cloned. If a container's type is in \a ignoreTypeNames or belongs to a
1022 group in \a ignoreGroupNames it is ignored altogether.
1024 \param[in] rootNode Root of the scene to clone.
1025 \param[in] cloneTypeNames List of type names that are cloned.
1026 \param[in] ignoreTypeNames List of type names that are ignored.
1027 \param[in] cloneGroupNames List of group names that are cloned.
1028 \param[in] ignoreGroupNames LIst of group names that are ignored.
1029 \return The root Node of the cloned scene.
1031 \ingroup GrpBaseFieldContainerNodes
1035 NodeTransitPtr
cloneTree(const OSG::Node
*rootNode
,
1036 const std::vector
<std::string
> &cloneTypeNames
,
1037 const std::vector
<std::string
> &ignoreTypeNames
,
1038 const std::vector
<std::string
> &cloneGroupNames
,
1039 const std::vector
<std::string
> &ignoreGroupNames
)
1041 std::vector
<const ReflexiveContainerType
*> cloneTypes
;
1042 std::vector
<const ReflexiveContainerType
*> ignoreTypes
;
1043 std::vector
<UInt16
> cloneGroupIds
;
1044 std::vector
<UInt16
> ignoreGroupIds
;
1046 appendTypesVector (cloneTypeNames
, cloneTypes
);
1047 appendTypesVector (ignoreTypeNames
, ignoreTypes
);
1048 appendGroupsVector(cloneGroupNames
, cloneGroupIds
);
1049 appendGroupsVector(ignoreGroupNames
, ignoreGroupIds
);
1051 return cloneTree(rootNode
, cloneTypes
, ignoreTypes
,
1052 cloneGroupIds
, ignoreGroupIds
);
1055 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1056 especially NodeCores, are shared, only if a container's group id is in
1057 \a cloneGroupIds it is cloned. If a container's group id is in
1058 \a ignoreGroupIds it is ignored altogether.
1060 \param[in] rootNode Root of the scene to clone.
1061 \param[in] cloneGroupIds List of group ids, whose members are cloned.
1062 \param[in] ignoreGroupIds List of group ids, whose members are ignored.
1063 \return The root Node of the cloned scene.
1065 \ingroup GrpBaseFieldContainerNodes
1069 NodeTransitPtr
cloneTree(const OSG::Node
*rootNode
,
1070 const std::vector
<OSG::UInt16
> &cloneGroupIds
,
1071 const std::vector
<OSG::UInt16
> &ignoreGroupIds
)
1073 std::vector
<const ReflexiveContainerType
*> cloneTypes
;
1074 std::vector
<const ReflexiveContainerType
*> ignoreTypes
;
1076 return cloneTree(rootNode
, cloneTypes
, ignoreTypes
,
1077 cloneGroupIds
, ignoreGroupIds
);
1080 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1081 especially NodeCores, are shared, only if a container's type name is in
1082 \a cloneTypesString it is cloned. If a container's type is in
1083 \a ignoreTypesString it is ignored altogether.
1085 \param[in] rootNode Root of the scene to clone.
1086 \param[in] cloneTypesString Comma separated string of type names that are
1087 cloned instead of shared.
1088 \param[in] ignoreTypesString Comma separated string of type names that are
1090 \return The root Node of the cloned scene.
1092 \ingroup GrpBaseFieldContainerNodes
1096 NodeTransitPtr
cloneTree(const OSG::Node
*rootNode
,
1097 const std::string
&cloneTypesString
,
1098 const std::string
&ignoreTypesString
)
1100 std::vector
<const ReflexiveContainerType
*> cloneTypes
;
1101 std::vector
<const ReflexiveContainerType
*> ignoreTypes
;
1102 std::vector
<UInt16
> cloneGroupIds
;
1103 std::vector
<UInt16
> ignoreGroupIds
;
1105 appendTypesString(cloneTypesString
, cloneTypes
);
1106 appendTypesString(ignoreTypesString
, ignoreTypes
);
1108 return cloneTree(rootNode
, cloneTypes
, ignoreTypes
,
1109 cloneGroupIds
, ignoreGroupIds
);
1112 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1113 especially NodeCores, are shared, only if a container's type is in
1114 \a cloneTypes of belongs to a group in \a cloneGroupIds it is cloned.
1115 If a container's type is in \a ignoreTypes or belongs to a group in
1116 \a ignoreGroupIds it is ignored altogether.
1118 \param[in] rootNode Root of the scene to clone.
1119 \param[in] cloneTypes List of types to clone instead of share.
1120 \param[in] ignoreTypes List of types to ignore.
1121 \param[in] cloneGroupIds List of group ids, whose members are cloned.
1122 \param[in] ignoreGroupIds List of group ids, whose members are ignored.
1123 \return The root Node of the cloned scene.
1125 \ingroup GrpBaseFieldContainerNodes
1129 NodeTransitPtr
cloneTree(
1130 const OSG::Node
*rootNode
,
1131 const std::vector
<const OSG::ReflexiveContainerType
*> &cloneTypes
,
1132 const std::vector
<const OSG::ReflexiveContainerType
*> &ignoreTypes
,
1133 const std::vector
<OSG::UInt16
> &cloneGroupIds
,
1134 const std::vector
<OSG::UInt16
> &ignoreGroupIds
)
1136 NodeUnrecPtr
rootClone(NULL
);
1138 if(rootNode
!= NULL
)
1140 NodeUnrecPtr childClone
;
1141 NodeCore
*core
= rootNode
->getCore();
1143 rootClone
= Node::create();
1144 rootClone
->setTravMask(rootNode
->getTravMask());
1146 cloneAttachments(rootNode
, rootClone
,
1147 cloneTypes
, ignoreTypes
,
1148 cloneGroupIds
, ignoreGroupIds
);
1152 NodeCoreUnrecPtr coreClone
= NULL
;
1153 const FieldContainerType
&coreType
= core
->getType();
1155 // test if core type should NOT be ignored
1156 if(!TypePredicates::typeInGroupIds(
1157 ignoreGroupIds
.begin(),
1158 ignoreGroupIds
.end(), coreType
) &&
1159 !TypePredicates::typeDerivedFrom(
1160 ignoreTypes
.begin(),
1161 ignoreTypes
.end(), coreType
) )
1163 // test if core should cloned
1164 if(TypePredicates::typeInGroupIds (
1165 cloneGroupIds
.begin(),
1166 cloneGroupIds
.end(), coreType
) ||
1167 TypePredicates::typeDerivedFrom(
1169 cloneTypes
.end(), coreType
) )
1173 dynamic_pointer_cast
<NodeCore
>(
1175 cloneTypes
, ignoreTypes
,
1176 cloneGroupIds
, ignoreGroupIds
));
1185 rootClone
->setCore(coreClone
);
1188 for(UInt32 i
= 0; i
< rootNode
->getNChildren(); ++i
)
1190 childClone
= cloneTree(rootNode
->getChild(i
),
1191 cloneTypes
, ignoreTypes
,
1192 cloneGroupIds
, ignoreGroupIds
);
1194 rootClone
->addChild(childClone
);
1198 return NodeTransitPtr(rootClone
);
1201 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1202 especially NodeCores, are cloned, only if a container's type name is in
1203 \a shareTypeNames or if it belonfs to a group in \a shareGroupNames it is
1204 shared. If a container's type is in \a ignoreTypeNames or belongs to a
1205 group in \a ignoreGroupNames it is ignored altogether.
1207 \param[in] rootNode Root of the scene to clone.
1208 \param[in] shareTypeNames List of type names that are shared.
1209 \param[in] ignoreTypeNames List of type names that are ignored.
1210 \param[in] shareGroupNames List of group names that are shared.
1211 \param[in] ignoreGroupNames LIst of group names that are ignored.
1212 \return The root Node of the cloned scene.
1214 \ingroup GrpBaseFieldContainerNodes
1218 NodeTransitPtr
deepCloneTree(const OSG::Node
*rootNode
,
1219 const std::vector
<std::string
> &shareTypeNames
,
1220 const std::vector
<std::string
> &ignoreTypeNames
,
1221 const std::vector
<std::string
> &shareGroupNames
,
1222 const std::vector
<std::string
> &ignoreGroupNames
)
1224 std::vector
<const ReflexiveContainerType
*> shareTypes
;
1225 std::vector
<const ReflexiveContainerType
*> ignoreTypes
;
1226 std::vector
<UInt16
> shareGroupIds
;
1227 std::vector
<UInt16
> ignoreGroupIds
;
1229 appendTypesVector (shareTypeNames
, shareTypes
);
1230 appendTypesVector (ignoreTypeNames
, ignoreTypes
);
1231 appendGroupsVector(shareGroupNames
, shareGroupIds
);
1232 appendGroupsVector(ignoreGroupNames
, ignoreGroupIds
);
1234 return deepCloneTree(rootNode
, shareTypes
, ignoreTypes
,
1235 shareGroupIds
, ignoreGroupIds
);
1238 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1239 especially NodeCores, are cloned, only if a container's group id is in
1240 \a shareGroupIds it is shared. If a container's group id is in
1241 \a ignoreGroupIds it is ignored altogether.
1243 \param[in] rootNode Root of the scene to clone.
1244 \param[in] shareGroupIds List of group ids, whose members are shared.
1245 \param[in] ignoreGroupIds List of group ids, whose members are ignored.
1246 \return The root Node of the cloned scene.
1248 \ingroup GrpBaseFieldContainerNodes
1252 NodeTransitPtr
deepCloneTree(const OSG::Node
*rootNode
,
1253 const std::vector
<OSG::UInt16
> &shareGroupIds
,
1254 const std::vector
<OSG::UInt16
> &ignoreGroupIds
)
1256 std::vector
<const ReflexiveContainerType
*> shareTypes
;
1257 std::vector
<const ReflexiveContainerType
*> ignoreTypes
;
1259 return deepCloneTree(rootNode
, shareTypes
, ignoreTypes
,
1260 shareGroupIds
, ignoreGroupIds
);
1263 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1264 especially NodeCores, are cloned, only if a container's type name is in
1265 \a shareTypesString it is shared. If a container's type is in
1266 \a ignoreTypesString it is ignored altogether.
1268 \param[in] rootNode Root of the scene to clone.
1269 \param[in] shareTypesString Comma separated string of type names that are
1270 shared instead of cloned.
1271 \param[in] ignoreTypesString Comma separated string of type names that are
1273 \return The root Node of the cloned scene.
1275 \ingroup GrpBaseFieldContainerNodes
1279 NodeTransitPtr
deepCloneTree(const Node
*rootNode
,
1280 const std::string
&shareTypesString
,
1281 const std::string
&ignoreTypesString
)
1283 std::vector
<const ReflexiveContainerType
*> shareTypes
;
1284 std::vector
<const ReflexiveContainerType
*> ignoreTypes
;
1285 std::vector
<UInt16
> shareGroupIds
;
1286 std::vector
<UInt16
> ignoreGroupIds
;
1288 appendTypesString(shareTypesString
, shareTypes
);
1289 appendTypesString(ignoreTypesString
, ignoreTypes
);
1291 return deepCloneTree(rootNode
, shareTypes
, ignoreTypes
,
1292 shareGroupIds
, ignoreGroupIds
);
1295 /*! Clones the scene starting at \a rootNode. By default FieldContainers,
1296 especially NodeCores, are cloned, only if a container's type is in
1297 \a shareTypes of belongs to a group in \a shareGroupIds it is shared.
1298 If a container's type is in \a ignoreTypes or belongs to a group in
1299 \a ignoreGroupIds it is ignored altogether.
1301 \param[in] rootNode Root of the scene to clone.
1302 \param[in] shareTypes List of types to share instead of clone.
1303 \param[in] ignoreTypes List of types to ignore.
1304 \param[in] shareGroupIds List of group ids, whose members are shared.
1305 \param[in] ignoreGroupIds List of group ids, whose members are ignored.
1306 \return The root Node of the cloned scene.
1308 \ingroup GrpBaseFieldContainerNodes
1312 NodeTransitPtr
deepCloneTree(
1313 const OSG::Node
*rootNode
,
1314 const std::vector
<const OSG::ReflexiveContainerType
*> &shareTypes
,
1315 const std::vector
<const OSG::ReflexiveContainerType
*> &ignoreTypes
,
1316 const std::vector
<OSG::UInt16
> &shareGroupIds
,
1317 const std::vector
<OSG::UInt16
> &ignoreGroupIds
)
1319 NodeUnrecPtr
rootClone(NULL
);
1321 if(rootNode
!= NULL
)
1323 NodeUnrecPtr childClone
;
1324 NodeCore
*core
= rootNode
->getCore();
1326 rootClone
= Node::create();
1327 rootClone
->setTravMask(rootNode
->getTravMask());
1329 deepCloneAttachments(rootNode
, rootClone
,
1330 shareTypes
, ignoreTypes
,
1331 shareGroupIds
, ignoreGroupIds
);
1335 NodeCoreUnrecPtr
coreClone(NULL
);
1336 const FieldContainerType
&coreType
= core
->getType();
1338 // test if core type should NOT be ignored
1339 if(!TypePredicates::typeInGroupIds (
1340 ignoreGroupIds
.begin(),
1341 ignoreGroupIds
.end(), coreType
) &&
1342 !TypePredicates::typeDerivedFrom(
1343 ignoreTypes
.begin(),
1344 ignoreTypes
.end(), coreType
) )
1346 // test if core should be shared
1347 if(TypePredicates::typeInGroupIds (
1348 shareGroupIds
.begin(),
1349 shareGroupIds
.end(), coreType
) ||
1350 TypePredicates::typeDerivedFrom(
1352 shareTypes
.end(), coreType
) )
1361 dynamic_pointer_cast
<NodeCore
>(
1363 shareTypes
, ignoreTypes
,
1364 shareGroupIds
, ignoreGroupIds
));
1368 rootClone
->setCore(coreClone
);
1371 for(UInt32 i
= 0; i
< rootNode
->getNChildren(); ++i
)
1373 childClone
= deepCloneTree(rootNode
->getChild(i
),
1374 shareTypes
, ignoreTypes
,
1375 shareGroupIds
, ignoreGroupIds
);
1377 rootClone
->addChild(childClone
);
1381 return NodeTransitPtr(rootClone
);
1385 /*---------------------------------------------------------------------*/