# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

mot.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "std3d.h"
00027 
00028 #include "3d/mot.h"
00029 #include "nel/misc/debug.h"
00030 #include "nel/misc/stream.h"
00031 #include <algorithm>
00032 #include <list>
00033 using namespace std;
00034 using namespace NLMISC;
00035 
00036 
00037 namespace       NL3D
00038 {
00039 
00040 
00041 // ***************************************************************************
00042 // ***************************************************************************
00043 // CMOT static.
00044 // ***************************************************************************
00045 // ***************************************************************************
00046 
00047 
00048 // ***************************************************************************
00049 set<CMOT::CModelEntry>          CMOT::RegModels;
00050 set<CMOT::CObsEntry>            CMOT::RegObservers;
00051 
00052 // ***************************************************************************
00053 void    CMOT::registerModel(const CClassId &idModel, const CClassId &idModelBase, IModel* (*creator)())
00054 {
00055         nlassert(idModel!=CClassId::Null);
00056         nlassert(creator);
00057         // idModelBase may be Null...
00058 
00059         CModelEntry             e;
00060         e.BaseModelId= idModelBase;
00061         e.ModelId= idModel;
00062         e.Creator= creator;
00063 
00064         // Insert/replace e.
00065         RegModels.erase(e);
00066         RegModels.insert(e);
00067 }
00068 // ***************************************************************************
00069 void    CMOT::registerObs(const CClassId &idTrav, const CClassId &idModel, IObs* (*creator)())
00070 {
00071         nlassert(idTrav!=CClassId::Null);
00072         nlassert(idModel!=CClassId::Null);
00073         nlassert(creator);
00074 
00075         CObsEntry               e;
00076         e.ModelId= idModel;
00077         e.TravId= idTrav;
00078         e.Creator= creator;
00079 
00080         // Insert/replace e.
00081         RegObservers.erase(e);
00082         RegObservers.insert(e);
00083 }
00084 
00085 
00086 // ***************************************************************************
00087 // ***************************************************************************
00088 // CMOT.
00089 // ***************************************************************************
00090 // ***************************************************************************
00091 
00092 
00093 // ***************************************************************************
00094 CMOT::CMOT()
00095 {
00096         _ValidateModelList= NULL;
00097 }
00098 // ***************************************************************************
00099 CMOT::~CMOT()
00100 {
00101         release();
00102 }
00103 
00104 // ***************************************************************************
00105 void    CMOT::addTrav(ITrav *v)
00106 {
00107         nlassert(v);
00108         CClassId        idTrav= v->getClassId();
00109         nlassert(idTrav!=CClassId::Null);       
00110 
00111         CTravEntry      e;
00112         e.TravId= idTrav;
00113         e.Trav= v;
00114 
00115         Traversals.push_back(e);
00116         v->addedToMOT(this);
00117 }
00118 // ***************************************************************************
00119 ITrav   *CMOT::getTrav(const CClassId &idTrav) const 
00120 {
00121         std::vector<CTravEntry>::const_iterator it;
00122 
00123         for(it= Traversals.begin(); it!= Traversals.end(); it++)
00124         {
00125                 if(idTrav== (*it).TravId)
00126                         return (*it).Trav;
00127         }
00128 
00129         return NULL;
00130 }
00131 // ***************************************************************************
00132 void    CMOT::release()
00133 {
00134         // First, release all the models.
00135         set<IModel*>::iterator  it;
00136         it= Models.begin();
00137         while( it!=Models.end())
00138         {
00139                 deleteModel(*it);
00140                 it= Models.begin();
00141         }
00142         // No models at all.
00143         _ValidateModelList= NULL;
00144 
00145         // Then release the traversals ptrs.
00146         Traversals.clear();
00147 }
00148 
00149 
00150 // ***************************************************************************
00151 IModel  *CMOT::createModel(const CClassId &idModel)
00152 {
00153         nlassert(idModel!=CClassId::Null);
00154 
00155         CModelEntry     e;
00156         e.ModelId= idModel;
00157         set<CModelEntry>::iterator      itModel;
00158         itModel= RegModels.find(e);
00159 
00160         if(itModel==RegModels.end())
00161         {
00162                 nlstop;                 // Warning, CScene::registerBasics () has not been called !
00163                 return NULL;
00164         }
00165         else
00166         {
00167                 IModel  *m= (*itModel).Creator();
00168                 if(!m)  return NULL;
00169 
00170                 // Set the owner for the model.
00171                 m->_OwnerMot= this;
00172 
00173                 // create observer for each trav.
00174                 std::vector<CTravEntry>::const_iterator itTrav;
00175                 for(itTrav= Traversals.begin(); itTrav!=Traversals.end(); itTrav++)
00176                 {
00177                         // Create observer.
00178                         IObs    *obs= createObs((*itTrav).Trav, idModel);
00179                         nlassert(obs);
00180                         // Init model.
00181                         obs->Model= m;
00182                         obs->Trav= (*itTrav).Trav;
00183                         // Attach it to Model.
00184                         m->Observers.insert(IModel::CObsMap::value_type((*itTrav).TravId, obs));
00185                         // Attach them to traversal's root.
00186                         if((*itTrav).Trav->getRoot())
00187                                 (*itTrav).Trav->link(NULL, m);
00188                 }
00189 
00190                 // After m finished, init the observers.
00191                 IModel::CObsMap::const_iterator itObs;
00192                 for(itObs= m->Observers.begin(); itObs!=m->Observers.end(); itObs++)
00193                 {
00194                         IObs    *o= (*itObs).second;
00195                         o->init();
00196                 }
00197 
00198                 // Insert the model into the set.
00199                 Models.insert(m);
00200 
00201                 // By default the model is validate() in CMOT::validateModels().
00202                 m->linkToValidateList();
00203 
00204                 // Once the model is correclty created, finish init him.
00205                 m->initModel();
00206 
00207                 return m;
00208         }
00209 }
00210 // ***************************************************************************
00211 void    CMOT::deleteModel(IModel *model)
00212 {
00213         if(model==NULL)
00214                 return;
00215         set<IModel*>::iterator  it= Models.find(model);
00216         if(it!=Models.end())
00217         {
00218                 delete *it;
00219                 Models.erase(it);
00220         }
00221 }
00222 
00223 
00224 // ***************************************************************************
00225 void    CMOT::validateModels()
00226 {
00227         // check all the models which must be checked.
00228         IModel  *model= _ValidateModelList;
00229         IModel  *next;
00230         while( model )
00231         {
00232                 // next to validate. get next now, because model->validate() may remove model from the list.
00233                 next= model->_NextModelToValidate;
00234 
00235                 // chek / validate the model.
00236                 model->validate();
00237 
00238                 // next.
00239                 model= next;
00240         }
00241 }
00242 
00243 
00244 // ***************************************************************************
00245 IObs    *CMOT::createObs(const ITrav *trav, const CClassId &idModel) const
00246 {
00247         nlassert(trav);
00248         CClassId idTrav= trav->getClassId();
00249         nlassert(idTrav!=CClassId::Null);
00250 
00251         if(idModel==CClassId::Null)
00252         {
00253                 // Use trav to create default observer.
00254                 return trav->createDefaultObs();
00255         }
00256 
00257         CObsEntry       e;
00258         e.TravId= idTrav;
00259         e.ModelId= idModel;
00260         std::set<CObsEntry>::iterator   it;
00261         it= RegObservers.find(e);
00262 
00263         if(it==RegObservers.end())
00264         {
00265                 // Try the father of the model.
00266                 CModelEntry     e;
00267                 e.ModelId= idModel;
00268                 set<CModelEntry>::iterator      it;
00269                 it= RegModels.find(e);
00270 
00271                 nlassert(it!=RegModels.end());
00272 
00273                 return createObs(trav, (*it).BaseModelId);
00274         }
00275         else
00276         {
00277                 // Register with the specified observer.
00278                 return (*it).Creator();
00279         }
00280 }
00281 
00282 
00283 // ***************************************************************************
00284 IObs    *CMOT::getModelObs(IModel *m, const NLMISC::CClassId &idTrav) const
00285 {
00286         if(!m)
00287                 return NULL;
00288         return m->getObs(idTrav);
00289 }
00290 
00291 
00292 // ***************************************************************************
00293 // ***************************************************************************
00294 // ITrav.
00295 // ***************************************************************************
00296 // ***************************************************************************
00297 
00298 
00299 // ***************************************************************************
00300 void    ITrav::setRoot(IModel   *root)
00301 {
00302         if(root)
00303                 Root= root->getObs(getClassId());
00304         else
00305                 Root= NULL;
00306 }
00307 // ***************************************************************************
00308 IModel  *ITrav::getRoot() const
00309 {
00310         if(Root)
00311                 return Root->Model;
00312         else
00313                 return NULL;
00314 }
00315 
00316 // ***************************************************************************
00317 void    ITrav::link(IModel *m1, IModel *m2) const
00318 {
00319         IObs    *o1,*o2;
00320 
00321         nlassert(m2);
00322         CClassId        travId= getClassId();
00323 
00324         if(m1)
00325         {
00326                 o1= m1->getObs(travId);
00327                 nlassert(o1);
00328         }
00329         else
00330         {
00331                 o1= Root;
00332                 // If his one is NULL, return.
00333                 // NB: this may not be an error. eg: in CScene::release(), when all models are deleted, 
00334                 // a ~CSkeletonModel() call link() to Root, but Root model may have been deleted first!!!
00335                 if(!o1)
00336                         return;
00337         }
00338         o2= m2->getObs(travId);
00339         nlassert(o1);
00340         nlassert(o2);
00341         o2->addParent(o1);
00342         o1->addChild(o2);
00343 }
00344 // ***************************************************************************
00345 void    ITrav::unlink(IModel *m1, IModel *m2) const
00346 {
00347         IObs    *o1,*o2;
00348 
00349         nlassert(m2);
00350         CClassId        travId= getClassId();
00351 
00352         if(m1)
00353         {
00354                 o1= m1->getObs(travId);
00355                 nlassert(o1);
00356         }
00357         else
00358         {
00359                 o1= Root;
00360                 // If his one is NULL, return.
00361                 // NB: this may not be an error. eg: in CScene::release(), when all models are deleted, 
00362                 // a ~CSkeletonModel() call link() to Root, but Root model may have been deleted first!!!
00363                 if(!o1)
00364                         return;
00365         }
00366         o2= m2->getObs(travId);
00367         nlassert(o1);
00368         nlassert(o2);
00369         o2->delParent(o1);
00370         o1->delChild(o2);
00371 }
00372 
00373 // ***************************************************************************
00374 void    ITrav::moveChildren(IModel *parentFrom, IModel *parentTo) const
00375 {
00376         // Make a local list of children (since link() modify the list).
00377         list<IModel     *>      children;
00378         for(IModel      *c= getFirstChild(parentFrom); c!=NULL; c= getNextChild(parentFrom))
00379                 children.push_back(c);
00380 
00381         for(list<IModel *>::iterator it= children.begin(); it!= children.end();it++)
00382         {
00383                 unlink(parentFrom, *it);
00384                 link(parentTo, *it);
00385         }
00386 }
00387 // ***************************************************************************
00388 void    ITrav::copyChildren(IModel *parentFrom, IModel *parentTo) const
00389 {
00390         // Make a local list of children (since link() modify the list).
00391         list<IModel     *>      children;
00392         for(IModel      *c= getFirstChild(parentFrom); c!=NULL; c= getNextChild(parentFrom))
00393                 children.push_back(c);
00394 
00395         for(list<IModel *>::iterator it= children.begin(); it!= children.end();it++)
00396         {
00397                 link(parentTo, *it);
00398         }
00399 }
00400 
00401 
00402 // ***************************************************************************
00403 sint ITrav::getNumChildren (IModel *m) const
00404 {
00405         IObs *o = m->getObs(getClassId());
00406         return o->getNumChildren();
00407 }
00408 // ***************************************************************************
00409 IModel* ITrav::getFirstChild (IModel *m) const
00410 {
00411         IObs *o = m->getObs(getClassId());
00412         IObs *child = o->getFirstChild();
00413         if (child != NULL)
00414                 return child->Model;
00415         return NULL;
00416 }
00417 // ***************************************************************************
00418 IModel* ITrav::getNextChild (IModel *m) const
00419 {
00420         IObs *o = m->getObs(getClassId());
00421         IObs *child = o->getNextChild();
00422         if (child != NULL)
00423                 return child->Model;
00424         return NULL;
00425 }
00426 
00427 // ***************************************************************************
00428 sint ITrav::getNumParents (IModel *m) const
00429 {
00430         IObs *o = m->getObs(getClassId());
00431         return o->getNumParents();
00432 }
00433 // ***************************************************************************
00434 IModel* ITrav::getFirstParent (IModel *m) const
00435 {
00436         IObs *o = m->getObs(getClassId());
00437         IObs *father = o->getFirstParent();
00438         if (father != NULL)
00439                 return father->Model;
00440         return NULL;
00441 
00442 }
00443 // ***************************************************************************
00444 IModel* ITrav::getNextParent (IModel *m) const
00445 {
00446         IObs *o = m->getObs(getClassId());
00447         IObs *father = o->getNextParent();
00448         if (father != NULL)
00449                 return father->Model;
00450         return NULL;
00451 }
00452 
00453 
00454 
00455 
00456 // ***************************************************************************
00457 // ***************************************************************************
00458 // IModel.
00459 // ***************************************************************************
00460 // ***************************************************************************
00461 
00462 
00463 // ***************************************************************************
00464 IModel::IModel()
00465 {
00466         TouchObs.resize(Last);
00467         LastClassId= 0;
00468         LastObs= NULL;
00469 
00470         _OwnerMot= NULL;
00471         _PrecModelToValidate= NULL;
00472         _NextModelToValidate= NULL;
00473 }
00474 // ***************************************************************************
00475 IModel::~IModel()
00476 {
00477         // ensure the model is no more linked to the validateList.
00478         unlinkFromValidateList();
00479 
00480         // delte observers.
00481         CObsMap::iterator       it;
00482         for(it=Observers.begin();it!=Observers.end();it++)
00483         {
00484                 delete (*it).second;
00485                 (*it).second=NULL;
00486         }
00487 }
00488 // ***************************************************************************
00489 IObs    *IModel::getObs(const CClassId &idTrav) const 
00490 {
00491         CObsMap::const_iterator it;
00492 
00493         if(idTrav==LastClassId)
00494                 return LastObs;
00495 
00496         LastClassId= idTrav;
00497         it= Observers.find(idTrav);
00498         if(it==Observers.end())
00499                 LastObs= NULL;
00500         else
00501                 LastObs= (*it).second;
00502 
00503         return LastObs;
00504 }
00505 
00506 
00507 // ***************************************************************************
00508 void    IModel::validate()
00509 {
00510         update();
00511 
00512         // If the model is newer than observers.
00513         if(TouchObs[IModel::Dirty])
00514         {
00515                 // update all model's observers.
00516                 IModel::CObsMap::iterator       it;
00517                 for(it= Observers.begin(); it!= Observers.end(); it++)
00518                 {
00519                         IObs    *o= (*it).second;
00520                         o->update();
00521                 }
00522 
00523                 // Must clear all dirty falgs.
00524                 cleanTouch();
00525         }
00526 }
00527 
00528 
00529 // ***************************************************************************
00530 void    IModel::linkToValidateList()
00531 {
00532         if(!_OwnerMot)
00533                 return;
00534 
00535         // If the model is not already inserted.
00536         if( ! (_PrecModelToValidate!=NULL  ||  _OwnerMot->_ValidateModelList==this) )
00537         {
00538                 // insert it.
00539                 _NextModelToValidate= _OwnerMot->_ValidateModelList;
00540                 _PrecModelToValidate= NULL;
00541                 if(_NextModelToValidate)
00542                         _NextModelToValidate->_PrecModelToValidate= this;
00543                 _OwnerMot->_ValidateModelList= this;
00544         }
00545 }
00546 
00547 
00548 // ***************************************************************************
00549 void    IModel::unlinkFromValidateList()
00550 {
00551         if(!_OwnerMot)
00552                 return;
00553 
00554         // If the model is inserted.
00555         if( _PrecModelToValidate!=NULL  ||  _OwnerMot->_ValidateModelList==this )
00556         {
00557                 // update prec.
00558                 if(_PrecModelToValidate)
00559                         _PrecModelToValidate->_NextModelToValidate= _NextModelToValidate;
00560                 else
00561                         _OwnerMot->_ValidateModelList= _NextModelToValidate;
00562 
00563                 // update next.
00564                 if(_NextModelToValidate)
00565                         _NextModelToValidate->_PrecModelToValidate= _PrecModelToValidate;
00566 
00567                 // End.
00568                 _PrecModelToValidate= NULL;
00569                 _NextModelToValidate= NULL;
00570         }
00571 }
00572 
00573 
00574 
00575 // ***************************************************************************
00576 // ***************************************************************************
00577 // IObs.
00578 // ***************************************************************************
00579 // ***************************************************************************
00580 
00581 
00582 
00583 // ***************************************************************************
00584 IObs::IObs()
00585 {
00586         Model= NULL;
00587         Trav= NULL;
00588 
00589         NumFathers= 0;
00590         NumSons= 0;
00591         CurSonIt= SonList.end();
00592         CurFatherIt= FatherList.end();
00593 }
00594 // ***************************************************************************
00595 IObs::~IObs()
00596 {
00597         ItObsList       it;
00598 
00599         // delete map of Its.
00600         SonMap.clear();
00601         FatherMap.clear();
00602 
00603         // Delete link from fathers.
00604         for(it= FatherList.begin(); it!=FatherList.end(); it++)
00605         {
00606                 IObs    *father= (*it);
00607                 // Must use delChild() since don't know what father is.
00608                 father->delChild(this);
00609         }
00610 
00611         // Delete link from sons.
00612         for(it= SonList.begin(); it!=SonList.end(); it++)
00613         {
00614                 IObs    *son= (*it);
00615                 // Must use delParent() since don't know what son is.
00616                 son->delParent(this);
00617         }
00618 
00619         // And so delete lists.
00620         SonList.clear();
00621         FatherList.clear();
00622         NumFathers= 0;
00623         NumSons= 0;
00624 }
00625 // ***************************************************************************
00626 IObs    *IObs::getObs(const CClassId &idTrav) const
00627 {
00628         return Model->getObs(idTrav);
00629 }
00630 
00631 
00632 // ***************************************************************************
00633 void    IObs::addChild(IObs *son)
00634 {
00635         nlassert(son);
00636 
00637         // insert (if not exist).
00638         ItObsMap        it= SonMap.find(son);
00639         if(it==SonMap.end())
00640         {
00641                 // insert in the map and in the list.
00642                 SonMap[son]= SonList.insert(SonList.end(), son);
00643                 NumSons++;
00644         }
00645 }
00646 // ***************************************************************************
00647 void    IObs::delChild(IObs *son)
00648 {
00649         nlassert(son);
00650 
00651         // Just erase (if possible).
00652         ItObsMap        it= SonMap.find(son);
00653         if(it!=SonMap.end())
00654         {
00655                 // erase from list, then from mapt
00656                 SonList.erase(it->second);
00657                 SonMap.erase(it);
00658                 NumSons--;
00659         }
00660 }
00661 // ***************************************************************************
00662 void    IObs::addParent(IObs *father)
00663 {
00664         nlassert(father);
00665 
00666         if(isTreeNode())
00667         {
00668                 // Must test if father is already linked.
00669                 ItObsMap        itMap;
00670                 itMap= FatherMap.find(father);
00671                 if(itMap!=FatherMap.end())
00672                         return;         // father is already a parent of this.
00673 
00674                 // Tree node, so delete fathers, and fathers links to me.
00675                 for(ItObsList it= FatherList.begin(); it!=FatherList.end();it++)
00676                 {
00677                         // Must use delChild() since don't know what father is.
00678                         (*it)->delChild(this);
00679                 }
00680                 FatherMap.clear();
00681                 FatherList.clear();
00682         }
00683 
00684         // insert (if not exist).
00685         ItObsMap        it= FatherMap.find(father);
00686         if(it==FatherMap.end())
00687         {
00688                 // insert in the map and in the list.
00689                 FatherMap[father]= FatherList.insert(FatherList.end(), father);
00690                 NumFathers++;
00691         }
00692 }
00693 // ***************************************************************************
00694 void    IObs::delParent(IObs *father)
00695 {
00696         nlassert(father);
00697 
00698         // Just erase (if possible).
00699         ItObsMap        it= FatherMap.find(father);
00700         if(it!=FatherMap.end())
00701         {
00702                 // erase from list, then from mapt
00703                 FatherList.erase(it->second);
00704                 FatherMap.erase(it);
00705                 NumFathers--;
00706         }
00707 }
00708 
00709 
00710 
00711 }