Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OSGNode.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *                     Copyright 2000-2002 by OpenSG Forum                   *
00006  *                                                                           *
00007  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00008  *                                                                           *
00009 \*---------------------------------------------------------------------------*/
00010 /*---------------------------------------------------------------------------*\
00011  *                                License                                    *
00012  *                                                                           *
00013  * This library is free software; you can redistribute it and/or modify it   *
00014  * under the terms of the GNU Library General Public License as published    *
00015  * by the Free Software Foundation, version 2.                               *
00016  *                                                                           *
00017  * This library is distributed in the hope that it will be useful, but       *
00018  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00020  * Library General Public License for more details.                          *
00021  *                                                                           *
00022  * You should have received a copy of the GNU Library General Public         *
00023  * License along with this library; if not, write to the Free Software       *
00024  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00025  *                                                                           *
00026 \*---------------------------------------------------------------------------*/
00027 /*---------------------------------------------------------------------------*\
00028  *                                Changes                                    *
00029  *                                                                           *
00030  *                                                                           *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035 \*---------------------------------------------------------------------------*/
00036 
00037 #ifdef OSG_DOC_FILES_IN_MODULE
00038 
00041 #endif
00042 
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 #include <ctype.h>
00046 
00047 #include <functional>
00048 #include <algorithm>
00049 
00050 #include "OSGConfig.h"
00051 #include "OSGFieldContainerPtr.h"
00052 #include "OSGFieldContainerType.h"
00053 #include "OSGNode.h"
00054 #include "OSGNodeCore.h"
00055 #include "OSGBinaryDataHandler.h"
00056 #include "OSGSFFieldContainerPtr.h"
00057 #include "OSGMFFieldContainerPtr.h"
00058 
00059 OSG_USING_NAMESPACE
00060 
00061 const BitVector Node::VolumeFieldMask      =
00062         (TypeTraits<BitVector>::One << Node::VolumeFieldId     );
00063 const BitVector Node::TravMaskFieldMask      = 
00064         (TypeTraits<BitVector>::One << Node::TravMaskFieldId   );
00065 const BitVector Node::ParentFieldMask      = 
00066         (TypeTraits<BitVector>::One << Node::ParentFieldId     );
00067 const BitVector Node::ChildrenFieldMask    = 
00068         (TypeTraits<BitVector>::One << Node::ChildrenFieldId   );
00069 const BitVector Node::CoreFieldMask        = 
00070         (TypeTraits<BitVector>::One << Node::CoreFieldId       );
00071 
00072 FieldDescription *Node::_desc[] =
00073 {
00074     new FieldDescription(SFDynamicVolume::getClassType(),
00075                          "volume",
00076                          OSG_FC_FIELD_IDM_DESC(VolumeField),
00077                          false,
00078                          (FieldAccessMethod) &Node::getSFVolume),
00079 
00080     // Yes, this is wrong, it should be an UInt32, but changing
00081     // it now will break all old .osb files, and this info is
00082     // nearly never necessary to be loaded from files.
00083     new FieldDescription(SFBool::getClassType(),
00084                          "travMask",
00085                          OSG_FC_FIELD_IDM_DESC(TravMaskField),
00086                          false,
00087                          (FieldAccessMethod) &Node::getSFTravMask),
00088 
00089     new FieldDescription(SFNodePtr::getClassType(),
00090                          "parent",
00091                          OSG_FC_FIELD_IDM_DESC(ParentField),
00092                          true,
00093                          (FieldAccessMethod) &Node::getSFParent),
00094 
00095     new FieldDescription(MFNodePtr::getClassType(),
00096                          "children",
00097                          OSG_FC_FIELD_IDM_DESC(ChildrenField),
00098                          false,
00099                          (FieldAccessMethod) &Node::getMFChildren),
00100 
00101     new FieldDescription(SFNodeCorePtr::getClassType(),
00102                          "core",
00103                          OSG_FC_FIELD_IDM_DESC(CoreField),
00104                          false,
00105                          (FieldAccessMethod) &Node::getSFCore)
00106 };
00107 
00108 FieldContainerType Node::_type(
00109     "Node",
00110     "AttachmentContainer",
00111     0,
00112     (PrototypeCreateF) &Node::createEmpty,
00113     0,
00114     _desc,
00115     sizeof(_desc));
00116 
00117 
00118 const NodePtr Node::NullNode(NullFC);
00119 
00120 OSG_FIELD_CONTAINER_DEF(Node, NodePtr)
00121 
00122 /*-------------------------------------------------------------------------*/
00123 /*                                Set                                      */
00124 
00125 void Node::setCore(const NodeCorePtr &core)
00126 {
00127     NodePtr thisP = getPtr();
00128 
00129     thisP.setParentFieldPos(CoreFieldId);
00130 
00131     addRefCP(core);
00132 
00133     if(_sfCore.getValue() != NullFC)
00134     {
00135         beginEditCP(_sfCore.getValue(), NodeCore::ParentsFieldMask);
00136         {
00137             _sfCore.getValue()->subParent(thisP);
00138         }
00139         endEditCP  (_sfCore.getValue(), NodeCore::ParentsFieldMask);
00140 
00141         subRefCP(_sfCore.getValue());
00142     }
00143 
00144     _sfCore.setValue(core);
00145 
00146     if(_sfCore.getValue() != NullFC)
00147     {
00148         beginEditCP(_sfCore.getValue(), NodeCore::ParentsFieldMask);
00149         {
00150             _sfCore.getValue()->addParent(thisP);
00151         }
00152         endEditCP  (_sfCore.getValue(), NodeCore::ParentsFieldMask);
00153     }
00154 
00155     // TODO Check if required (GV)
00156     invalidateVolume();
00157 }
00158 
00159 /*-------------------------------------------------------------------------*/
00160 /*                             Children                                    */
00161 
00162 void Node::addChild(const NodePtr &childP)
00163 {
00164     if(childP != NullFC)
00165     {
00166         // do the ref early, to prevent destroys on getParent(a)->addChild(a)
00167         addRefCP(childP);
00168 
00169         // already somebody else's child?
00170         if(childP->getParent() != NullFC)
00171         {
00172             beginEditCP(childP->getParent(), Node::ChildrenFieldMask);
00173             childP->getParent()->subChild(childP);
00174             endEditCP(childP->getParent(), Node::ChildrenFieldMask);
00175         }
00176 
00177         _mfChildren.push_back(childP);
00178 
00179         beginEditCP(childP, Node::ParentFieldMask);
00180         {
00181             childP->setParent(getPtr());
00182         }
00183         endEditCP  (childP, Node::ParentFieldMask);
00184 
00185         // TODO Check if required (GV)
00186 #ifndef OSG_GV_BETA
00187         invalidateVolume();
00188 #endif
00189     }
00190 }
00191 
00192 void Node::insertChild(UInt32 childIndex, const NodePtr &childP)
00193 {
00194     MFNodePtr::iterator childIt = _mfChildren.begin();
00195 
00196     if(childP != NullFC)
00197     {
00198         // do the ref early, to prevent destroys on getParent(a)->addChild(a)
00199         addRefCP(childP);
00200 
00201         // already somebody else's child?
00202         if(childP->getParent() != NullFC)
00203         {
00204             beginEditCP(childP->getParent(), Node::ChildrenFieldMask);
00205             childP->getParent()->subChild(childP);
00206             endEditCP(childP->getParent(), Node::ChildrenFieldMask);
00207         }
00208 
00209         childIt += childIndex;
00210 
00211         _mfChildren.insert(childIt, childP);
00212 
00213         beginEditCP(childP, Node::ParentFieldMask);
00214         {
00215             childP->setParent(getPtr());
00216         }
00217         endEditCP  (childP, Node::ParentFieldMask);
00218     }
00219 
00220     // TODO check if required (GV)
00221 #ifndef OSG_GV_BETA
00222     invalidateVolume();
00223 #endif
00224 }
00225 
00226 void Node::replaceChild(UInt32 childIndex, const NodePtr &childP)
00227 {
00228     if(childP != NullFC && childIndex < _mfChildren.size())
00229     {
00230         // do the ref early, to prevent destroys on getParent(a)->addChild(a)
00231         addRefCP(childP);
00232 
00233         // remove the current child
00234         beginEditCP(_mfChildren[childIndex], Node::ParentFieldMask);
00235         {
00236             _mfChildren[childIndex]->setParent(NullNode);
00237         }
00238         endEditCP  (_mfChildren[childIndex], Node::ParentFieldMask);
00239 
00240         subRefCP(_mfChildren[childIndex]);
00241 
00242         // already somebody else's child?
00243         if(childP->getParent() != NullNode)
00244         {
00245             beginEditCP(childP->getParent(), Node::ChildrenFieldMask);
00246             childP->getParent()->subChild(childP);
00247             endEditCP(childP->getParent(), Node::ChildrenFieldMask);
00248         }
00249 
00250         // set the new child
00251         _mfChildren[childIndex] = childP;
00252 
00253         beginEditCP(childP, Node::ParentFieldMask);
00254         {
00255             childP->setParent(getPtr());
00256         }
00257         endEditCP  (childP, Node::ParentFieldMask);
00258     }
00259 
00260     // TODO check if required (GV)
00261 #ifndef OSG_GV_BETA
00262     invalidateVolume();
00263 #endif
00264 }
00265 
00267 
00268 bool Node::replaceChildBy(const NodePtr &childP,
00269                           const NodePtr &newChildP)
00270 {
00271     MFNodePtr::iterator childIt = _mfChildren.find(childP);
00272 
00273     if(newChildP != NullFC)
00274     {
00275         if(childIt != _mfChildren.end())
00276         {
00277             // do the ref early, to prevent destroys on 
00278             // getParent(a)->addChild(a)
00279 
00280             addRefCP(newChildP);
00281 
00282             beginEditCP(childP, Node::ParentFieldMask);
00283             {
00284                 childP->setParent(NullNode);
00285             }
00286             endEditCP  (childP, Node::ParentFieldMask);
00287 
00288             subRefCP(childP);
00289 
00290             // already somebody else's child?
00291             if(newChildP->getParent() != NullFC)
00292             {
00293                 beginEditCP(newChildP->getParent(), Node::ChildrenFieldMask);
00294                 newChildP->getParent()->subChild(newChildP);
00295                 endEditCP(newChildP->getParent(), Node::ChildrenFieldMask);
00296             }
00297 
00298             (*childIt) = newChildP;
00299 
00300             beginEditCP(newChildP, Node::ParentFieldMask);
00301             {
00302                 newChildP->setParent(getPtr());
00303             }
00304             endEditCP  (newChildP, Node::ParentFieldMask);
00305 
00306             // TODO check if required (GV)
00307 #ifndef OSG_GV_BETA
00308             invalidateVolume();
00309 #endif
00310 
00311             return true;
00312         }
00313     }
00314 
00315     return false;
00316 }
00317 
00318 Int32 Node::findChild(const NodePtr &childP) const
00319 {
00320     UInt32 index;
00321 
00322     for(index = 0; index < _mfChildren.size(); index++)
00323     {
00324         if( _mfChildren[index] == childP)
00325             break;
00326     }
00327 
00328     if(index < _mfChildren.size())
00329         return index;
00330     else
00331         return -1;
00332 }
00333 
00334 void Node::subChild(const NodePtr &childP)
00335 {
00336     MFNodePtr::iterator childIt = _mfChildren.find(childP);
00337 
00338     if(childIt != _mfChildren.end())
00339     {
00340         beginEditCP(childP, Node::ParentFieldMask);
00341         {
00342             childP->setParent(NullNode);
00343         }
00344         endEditCP  (childP, Node::ParentFieldMask);
00345 
00346         subRefCP(childP);
00347 
00348         _mfChildren.erase(childIt);
00349     }
00350     else
00351     {
00352         SWARNING << "Node(" << this << ")::subChild: " << childP 
00353                  << " is not one of my children!" << std::endl;
00354     }
00355 
00356     // TODO check if required (GV)
00357 #ifndef OSG_GV_BETA
00358     invalidateVolume();
00359 #endif
00360 }
00361 
00362 void Node::subChild(UInt32 childIndex)
00363 {
00364     MFNodePtr::iterator childIt = _mfChildren.begin();
00365 
00366     childIt += childIndex;
00367 
00368     if(childIt != _mfChildren.end())
00369     {
00370         beginEditCP(*childIt, Node::ParentFieldMask);
00371         {
00372             (*childIt)->setParent(NullNode);
00373         }
00374         endEditCP  (*childIt, Node::ParentFieldMask);
00375 
00376         subRefCP(*childIt);
00377 
00378         _mfChildren.erase(childIt);
00379     }
00380 
00381     // TODO check if required (GV)
00382 #ifndef OSG_GV_BETA
00383     invalidateVolume();
00384 #endif
00385 }
00386 
00387 
00388 /*-------------------------------------------------------------------------*/
00389 /*                           Get Transformation                            */
00390 
00391 Matrix Node::getToWorld(void)
00392 {
00393     Matrix tmp;
00394 
00395     getToWorld(tmp);
00396 
00397     return tmp;
00398 }
00399 
00400 void Node::getToWorld(Matrix &result)
00401 {
00402     if(getParent() != NullFC)
00403     {
00404         getParent()->getToWorld(result);
00405     }
00406     else
00407     {
00408         result.setIdentity();
00409     }
00410 
00411     getCore()->accumulateMatrix(result);
00412 }
00413 
00414 /*-------------------------------------------------------------------------*/
00415 /*                           Volume                                        */
00416 
00417 void Node::getWorldVolume(DynamicVolume &result)
00418 {
00419     Matrix m;
00420 
00421     if(getParent() != NullFC)
00422     {
00423         getParent()->getToWorld(m);
00424     }
00425     else
00426     {
00427         m.setIdentity();
00428     }
00429 
00430     updateVolume();
00431 
00432     result = getVolume();
00433     result.transform(m);
00434 /*
00435 Pnt3f low,high;
00436 result.getBounds(low,high);     
00437 fprintf(stderr,"%p: node 0x%p gwv (%f %f %f  %f %f %f)\n", 
00438             Thread::getCurrent(), this,
00439             low[0], low[1], low[2], 
00440             high[0], high[1], high[2] );
00441 */
00442 }
00443 
00444 void Node::updateVolume(void)
00445 {
00446     if(_sfVolume.getValue().getInstance().isValid() == true)
00447         return;             // still valid, nothing to do
00448 
00449     // be careful to not change the real volume. If two threads
00450     // are updating the same aspect this will lead to chaos
00451     
00452     DynamicVolume vol = _sfVolume.getValue();
00453 
00454 //fprintf(stderr,"%p: node 0x%p update needed\n", Thread::getCurrent(), this);
00455 
00456     MFNodePtr::iterator it;
00457 
00458     vol.getInstance().setEmpty();
00459 
00460     if(getTravMask())
00461     {
00462         for(it = _mfChildren.begin(); it != _mfChildren.end(); ++it)
00463         {
00464             if((*it)->getTravMask())
00465             {
00466                 (*it)->updateVolume();
00467                 vol.getInstance().extendBy((*it)->getVolume());
00468             }
00469         }
00470 
00471         // test for null core. Shouldn't happen, but just in case...
00472         if(getCore() != NullFC)
00473             getCore()->adjustVolume(vol.getInstance());
00474     }
00475     
00476     NodePtr thisP = getPtr();
00477 
00478     beginEditCP(thisP, VolumeFieldMask);
00479    
00480     vol.instanceChanged();
00481     
00482     _sfVolume.setValue(vol);
00483     
00484     endEditCP(thisP, VolumeFieldMask);
00485 }
00486 
00487 void Node::invalidateVolume(void)
00488 {
00489     Volume &vol=_sfVolume.getValue().getInstance();
00490     
00491     if(vol.isValid() == true && vol.isStatic() == false)
00492     {
00493         NodePtr thisP = getPtr();
00494 
00495         beginEditCP(thisP, VolumeFieldMask);
00496 
00497         vol.setValid(false);
00498         _sfVolume.getValue().instanceChanged();
00499         
00500         endEditCP(thisP, VolumeFieldMask);
00501 
00502         if(getParent() != NullFC)
00503         {
00504             getParent()->invalidateVolume();
00505         }
00506     }
00507 }
00508 
00509 /*-------------------------------------------------------------------------*/
00510 /*                                Dump                                     */
00511 
00512 void Node::dump(      UInt32    uiIndent,
00513                 const BitVector bvFlags) const
00514 {
00515     UInt32 i;
00516 
00517     NodePtr thisP = getPtr();
00518 
00519     indentLog(uiIndent, PLOG);
00520 
00521     PLOG << "Node"
00522          << "("
00523          << thisP.getFieldContainerId()
00524          << ") : "
00525          << _mfChildren.size() 
00526          << " children | "
00527          << _attachmentMap.getValue().size() 
00528          << " attachments | "
00529          << "Parent : " << std::hex;
00530 
00531     if(_sfParent.getValue() != NullFC)
00532         PLOG << "0x" << &(*(_sfParent.getValue())) << " | ";
00533     else
00534         PLOG << "NULL | ";
00535 
00536     PLOG << "0x" << this << std::dec << std::endl;
00537 
00538     indentLog(uiIndent, PLOG);
00539 
00540     PLOG << "[" << std::endl;
00541 
00542     if(_sfCore.getValue() != NullFC)
00543     {
00544         _sfCore.getValue()->dump(uiIndent + 4, bvFlags);
00545     }
00546     else
00547     {
00548         indentLog(uiIndent + 4, PLOG);
00549         PLOG << "Core : " << "NULL" << std::endl;
00550     }
00551 
00552     Inherited::dump(uiIndent, bvFlags);
00553 
00554     indentLog(uiIndent, PLOG);
00555     PLOG << "]" << std::endl;
00556 
00557     indentLog(uiIndent, PLOG);
00558 
00559     PLOG << "{" << std::endl;
00560 
00561     for(i = 0; i < _mfChildren.size(); i++)
00562     {
00563         _mfChildren[i]->dump(uiIndent + 4, bvFlags);
00564         PLOG << std::endl;
00565     }
00566 
00567 
00568     indentLog(uiIndent, PLOG);
00569 
00570     PLOG << "}" << std::endl;
00571 
00572 /*
00573     for(i = 0; i < indent; i++)
00574     {
00575         cerr << " ";
00576     }
00577     cerr << "  Parent : ";
00578 
00579 
00580     for(i = 0; i < indent; i++)
00581     {
00582         cerr << " ";
00583     }
00584 
00585     for(i = 0; i < indent; i++)
00586         fprintf(stderr, " ");
00587 
00588     fprintf(stderr, "NAttachments : \n");
00589 
00590     map<UInt32, AttachmentPtr>::const_iterator fcI;
00591 
00592     fcI = _attachmentMap.getValue().begin();
00593 
00594     while(fcI != _attachmentMap.getValue().end())
00595     {
00596         (*fcI).second->dump(indent + 2);
00597         ++fcI;
00598     }
00599 
00600     for(i = 0; i < indent; i++)
00601     {
00602         cerr << " ";
00603     }
00604 
00605     cerr << "{" << std::endl;
00606 
00607 
00608     for(i = 0; i < indent; i++)
00609     {
00610         cerr << " ";
00611     }
00612 
00613     cerr << "}" << std::endl;
00614 */
00615 }
00616 
00617 /*-------------------------------------------------------------------------*/
00618 /*                            Constructors                                 */
00619 
00620 Node::Node(void) :
00621      Inherited  (),
00622     _sfVolume   (),
00623     _sfTravMask (TypeTraits<UInt32>::getMax()),
00624     _sfParent   (),
00625     _mfChildren (),
00626     _sfCore     ()
00627 {
00628 }
00629 
00630 Node::Node(const Node &source) :
00631      Inherited  (source),
00632     _sfVolume   (source._sfVolume),
00633     _sfTravMask (source._sfTravMask),
00634     _sfParent   (),
00635     _mfChildren (),
00636     _sfCore     ()
00637 {
00638 }
00639 
00640 /*-------------------------------------------------------------------------*/
00641 /*                             Destructor                                  */
00642 
00643 Node::~Node(void)
00644 {
00645     if(_sfCore.getValue() != NullFC)
00646     {
00647         NodePtr thisP = getPtr();
00648 
00649         beginEditCP(_sfCore.getValue(), NodeCore::ParentsFieldMask);
00650         {
00651             _sfCore.getValue()->subParent(thisP);
00652         }
00653         endEditCP  (_sfCore.getValue(), NodeCore::ParentsFieldMask);
00654 
00655         subRefCP(_sfCore.getValue());
00656     }
00657 
00658     MFNodePtr::iterator       vChildIt    = _mfChildren.begin();
00659     MFNodePtr::const_iterator endChildren = _mfChildren.end  ();
00660 
00661     while(vChildIt != endChildren)
00662     {
00663         beginEditCP(*vChildIt, Node::ParentFieldMask);
00664         {
00665             (*vChildIt)->setParent(NullNode);
00666         }
00667         endEditCP  (*vChildIt, Node::ParentFieldMask);
00668 
00669         subRefCP(*vChildIt);
00670 
00671         ++vChildIt;
00672     }
00673 }
00674 
00675 #if defined(OSG_FIXED_MFIELDSYNC)
00676 void Node::onDestroyAspect(UInt32 uiId, UInt32 uiAspect)
00677 {
00678     _mfChildren.terminateShare(uiAspect, this->getContainerSize());
00679 }
00680 #endif
00681 
00682 NodePtr OSG::cloneTree(const NodePtr &pRootNode)
00683 {
00684     NodePtr returnValue = NullFC;
00685 
00686     if(pRootNode != NullFC)
00687     {
00688         NodePtr pChildClone = NullFC;
00689 
00690         returnValue = Node::create();
00691 
00692         beginEditCP(returnValue);
00693         {
00694             returnValue->setTravMask(pRootNode->getTravMask());
00695             returnValue->setCore    (pRootNode->getCore());
00696             
00697             for(UInt32 i = 0; i < pRootNode->getNChildren(); i++)
00698             {
00699                 pChildClone = cloneTree(pRootNode->getChild(i));
00700                 
00701                 returnValue->addChild(pChildClone);
00702             }
00703         }
00704         endEditCP  (returnValue);
00705     }
00706 
00707     return returnValue;
00708 }
00709 
00710 // deep clone of a fieldcontainer.
00711 // we should move this into OSGFieldContainer.cpp?
00712 FieldContainerPtr OSG::deepClone(const FieldContainerPtr &src,
00713                                  const std::vector<std::string> &share)
00714 {
00715     if(src == NullFC)
00716         return NullFC;
00717     
00718     const FieldContainerType &type = src->getType();
00719 
00720     //FDEBUG(("deepClone: fieldcontainertype = %s\n", type.getCName()));
00721 
00722     FieldContainerPtr dst = FieldContainerFactory::the()->createFieldContainer(type.getName().str());
00723 
00724     //UInt32 fcount = type.getNumFieldDescs();
00725     // ignore dynamic fields.
00726     UInt32 fcount = osgMin(type.getNumFieldDescs(), dst->getType().getNumFieldDescs());
00727     
00728     
00729     for(UInt32 i=1;i <= fcount;++i)
00730     {
00731         const FieldDescription* fdesc = type.getFieldDescription(i);
00732     
00733         if(fdesc->isInternal())
00734             continue;
00735     
00736         BitVector mask = fdesc->getFieldMask();
00737 
00738         Field *src_field = src->getField(i);
00739         Field *dst_field = dst->getField(i);
00740     
00741         const FieldType &ftype = src_field->getType();
00742     
00743         std::string fieldType = ftype.getName().str();
00744   
00745         // attachements
00746         if(strcmp(fdesc->getCName(), "attachments") == 0)
00747         {
00748             SFAttachmentMap *amap = (SFAttachmentMap *) src_field;
00749             
00750             AttachmentMap::const_iterator   mapIt = amap->getValue().begin();
00751             AttachmentMap::const_iterator   mapEnd = amap->getValue().end();
00752 
00753             beginEditCP(dst, mask);
00754             for(; mapIt != mapEnd; ++mapIt)
00755             {
00756                 FieldContainerPtr fc = mapIt->second;
00757 
00758                 bool shareit = false;
00759                 for(UInt32 k=0;k<share.size();++k)
00760                 {
00761                     FieldContainerType *fct = FieldContainerFactory::the()
00762                                             ->findType(share[k].c_str());
00763                     if(fc != NullFC && fct != NULL &&
00764                        fc->getType().isDerivedFrom(*fct))
00765                     {
00766                         shareit = true;
00767                         break;
00768                     }
00769                 }
00770                 
00771                 if(!shareit)
00772                     fc = OSG::deepClone(fc, share);
00773                 
00774                 if(fc != NullFC)
00775                     AttachmentContainerPtr::dcast(dst)->addAttachment(AttachmentPtr::dcast(fc));
00776             }
00777             endEditCP(dst, mask);
00778             continue;
00779         }
00780         
00781         // field
00782         if(strstr(ftype.getCName(), "Ptr") == NULL)
00783         {
00784             //FDEBUG(("deepClone: fieldname = %s fieldType = %s\n", fdesc->getCName(), fieldType.c_str()));
00785             beginEditCP(dst, mask);
00786                 dst_field->setAbstrValue(*src_field);
00787             endEditCP(dst, mask);
00788         }
00789         else // field with pointer
00790         {
00791             if(src_field->getCardinality() == FieldType::SINGLE_FIELD)
00792             {
00793                 FieldContainerPtr fc = ((SFFieldContainerPtr *) src_field)->getValue();
00794                 
00795                 bool shareit = false;
00796                 for(UInt32 k=0;k<share.size();++k)
00797                 {
00798                     FieldContainerType *fct = FieldContainerFactory::the()
00799                                             ->findType(share[k].c_str());
00800                     if(fc != NullFC && fct != NULL &&
00801                        fc->getType().isDerivedFrom(*fct))
00802                     {
00803                         shareit = true;
00804                         break;
00805                     }
00806                 }
00807                 
00808                 if(!shareit)
00809                     fc = OSG::deepClone(fc, share);
00810                 
00811                 if(fc != NullFC)
00812                 {
00813                     // increment reference counter!
00814                     addRefCP(fc);
00815                     beginEditCP(dst);
00816                         ((SFFieldContainerPtr *) dst_field)->setValue(fc);
00817                     endEditCP(dst);
00818                 }
00819             }
00820             else if(src_field->getCardinality() == FieldType::MULTI_FIELD)
00821             {
00822                 beginEditCP(dst, mask);
00823                     for(UInt32 j=0;j < ((MFFieldContainerPtr*)src_field)->size();++j)
00824                     {
00825                         FieldContainerPtr fc = (*(((MFFieldContainerPtr *)src_field)))[j];
00826                         
00827                         bool shareit = false;
00828                         for(UInt32 k=0;k<share.size();++k)
00829                         {
00830                             FieldContainerType *fct = FieldContainerFactory::the()
00831                                             ->findType(share[k].c_str());
00832                             if(fc != NullFC && fct != NULL &&
00833                                fc->getType().isDerivedFrom(*fct))
00834                             {
00835                                 shareit = true;
00836                                 break;
00837                             }
00838                         }
00839                         
00840                         if(!shareit)
00841                             fc = OSG::deepClone(fc, share);
00842                         
00843                         if(fc != NullFC)
00844                         {
00845                             // increment reference counter!
00846                             addRefCP(fc);
00847                             ((MFFieldContainerPtr *) dst_field)->push_back(fc);
00848                         }
00849                     }
00850                 endEditCP(dst, mask);
00851             }
00852         }
00853     }
00854     return dst;
00855 }
00856 
00857 FieldContainerPtr OSG::deepClone(const FieldContainerPtr &src,
00858                                  const std::vector<UInt16> &shareGroupIds)
00859 {
00860     std::vector<std::string> share;
00861     share.reserve(shareGroupIds.size());
00862     for(UInt32 i=0;i<shareGroupIds.size();++i)
00863     {
00864         const char *name = FieldContainerFactory::the()->findGroupName(shareGroupIds[i]);
00865         if(name != NULL)
00866             share.push_back(name);
00867     }
00868     return OSG::deepClone(src, share);
00869 }
00870 
00871 // shareString is a comma separated FieldContainer type list
00872 // e.g. "Material, Geometry"
00873 FieldContainerPtr OSG::deepClone(const FieldContainerPtr &src,
00874                                  const std::string &shareString)
00875 {
00876     std::vector<std::string> share;
00877     
00878     // parse comma separated names.
00879     std::string::const_iterator nextComma;
00880     std::string::const_iterator curPos = shareString.begin();
00881     while(curPos < shareString.end())
00882     {
00883         nextComma = std::find(curPos, shareString.end(), ',');
00884         // strip leading spaces
00885         curPos = std::find_if(curPos, nextComma, std::not1(std::ptr_fun(isspace)));
00886         share.push_back(std::string(curPos, nextComma));
00887         curPos = ++nextComma;
00888     }
00889     
00890     return OSG::deepClone(src, share);
00891 }
00892 
00893 // deep clone of attachements.
00894 void OSG::deepCloneAttachments(const NodePtr &src, NodePtr &dst,
00895                                const std::vector<std::string> &share)
00896 {
00897     SFAttachmentMap *amap = (SFAttachmentMap *) src->getSFAttachments();
00898             
00899     AttachmentMap::const_iterator   mapIt = amap->getValue().begin();
00900     AttachmentMap::const_iterator   mapEnd = amap->getValue().end();
00901 
00902     beginEditCP(dst, Node::AttachmentsFieldMask);
00903     for(; mapIt != mapEnd; ++mapIt)
00904     {
00905         FieldContainerPtr fc = mapIt->second;
00906 
00907         bool shareit = false;
00908         for(UInt32 k=0;k<share.size();++k)
00909         {
00910             FieldContainerType *fct = FieldContainerFactory::the()
00911                                       ->findType(share[k].c_str());
00912             if(fc != NullFC && fct != NULL &&
00913                fc->getType().isDerivedFrom(*fct))
00914             {
00915                 shareit = true;
00916                 break;
00917             }
00918         }
00919         
00920         if(!shareit)
00921             fc = OSG::deepClone(fc, share);
00922         
00923         if(fc != NullFC)
00924             dst->addAttachment(AttachmentPtr::dcast(fc));
00925     }
00926     endEditCP(dst, Node::AttachmentsFieldMask);
00927 }
00928 
00929 void OSG::deepCloneAttachments(const NodePtr &src, NodePtr &dst,
00930                                const std::vector<UInt16> &shareGroupIds)
00931 {
00932     std::vector<std::string> share;
00933     share.reserve(shareGroupIds.size());
00934     for(UInt32 i=0;i<shareGroupIds.size();++i)
00935     {
00936         const char *name = FieldContainerFactory::the()
00937                            ->findGroupName(shareGroupIds[i]);
00938         if(name != NULL)
00939             share.push_back(name);
00940     }
00941     OSG::deepCloneAttachments(src, dst, share);
00942 }
00943 
00944 // shareString is a comma separated FieldContainer type list
00945 // e.g. "Material, Geometry"
00946 void OSG::deepCloneAttachments(const NodePtr &src, NodePtr &dst,
00947                                const std::string &shareString)
00948 {
00949     std::vector<std::string> share;
00950     
00951     // parse comma separated names.
00952     std::string::const_iterator nextComma;
00953     std::string::const_iterator curPos = shareString.begin();
00954     while(curPos < shareString.end())
00955     {
00956         nextComma = std::find(curPos, shareString.end(), ',');
00957         // strip leading spaces
00958         curPos = std::find_if(curPos, nextComma, std::not1(std::ptr_fun(isspace)));
00959         share.push_back(std::string(curPos, nextComma));
00960         curPos = ++nextComma;
00961     }
00962     
00963     OSG::deepCloneAttachments(src, dst, share);
00964 }
00965 
00966 // deep clone of nodes.
00967 NodePtr OSG::deepCloneTree(const NodePtr &src,
00968                            const std::vector<std::string> &share)
00969 {
00970     NodePtr dst = NullFC;
00971 
00972     if(src != NullFC)
00973     {
00974         dst = Node::create();
00975         deepCloneAttachments(src, dst, share);
00976         
00977         beginEditCP(dst);
00978         {
00979             dst->setActive(src->getActive());
00980             dst->setTravMask(src->getTravMask());
00981             dst->setCore(NodeCorePtr::dcast(OSG::deepClone(src->getCore(), share)));
00982             
00983             for(UInt32 i = 0; i < src->getNChildren(); i++)
00984                 dst->addChild(deepCloneTree(src->getChild(i), share));
00985         }
00986         endEditCP  (dst);
00987     }
00988 
00989     return dst;
00990 }
00991 
00992 NodePtr OSG::deepCloneTree(const NodePtr &src,
00993                            const std::vector<UInt16> &shareGroupIds)
00994 {
00995     std::vector<std::string> share;
00996     share.reserve(shareGroupIds.size());
00997     for(UInt32 i=0;i<shareGroupIds.size();++i)
00998     {
00999         const char *name = FieldContainerFactory::the()->findGroupName(shareGroupIds[i]);
01000         if(name != NULL)
01001             share.push_back(name);
01002     }
01003     return OSG::deepCloneTree(src, share);
01004 }
01005 
01006 // shareString is a comma separated FieldContainer type list
01007 // e.g. "Material, Geometry"
01008 NodePtr OSG::deepCloneTree(const NodePtr &src,
01009                            const std::string &shareString)
01010 {
01011     std::vector<std::string> share;
01012     
01013     // parse comma separated names.
01014     std::string::const_iterator nextComma;
01015     std::string::const_iterator curPos = shareString.begin();
01016     while(curPos < shareString.end())
01017     {
01018         nextComma = std::find(curPos, shareString.end(), ',');
01019         // strip leading spaces
01020         curPos = std::find_if(curPos, nextComma, std::not1(std::ptr_fun(isspace)));
01021         share.push_back(std::string(curPos, nextComma));
01022         curPos = ++nextComma;
01023     }
01024     
01025     return OSG::deepCloneTree(src, share);
01026 }
01027 
01028 
01029 /*-------------------------------------------------------------------------*/
01030 /*                              cvs id's                                   */
01031 
01032 #ifdef __sgi
01033 #pragma set woff 1174
01034 #endif
01035 
01036 #ifdef OSG_LINUX_ICC
01037 #pragma warning( disable : 177 )
01038 #endif
01039 
01040 namespace
01041 {
01042     static Char8 cvsid_cpp[] = "@(#)$Id: $";
01043     static Char8 cvsid_hpp[] = OSGNODE_HEADER_CVSID;
01044     static Char8 cvsid_inl[] = OSGNODE_INLINE_CVSID;
01045 }

Generated on Thu Aug 25 04:07:55 2005 for OpenSG by  doxygen 1.4.3