00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
00058
00059 CModelEntry e;
00060 e.BaseModelId= idModelBase;
00061 e.ModelId= idModel;
00062 e.Creator= creator;
00063
00064
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
00081 RegObservers.erase(e);
00082 RegObservers.insert(e);
00083 }
00084
00085
00086
00087
00088
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
00135 set<IModel*>::iterator it;
00136 it= Models.begin();
00137 while( it!=Models.end())
00138 {
00139 deleteModel(*it);
00140 it= Models.begin();
00141 }
00142
00143 _ValidateModelList= NULL;
00144
00145
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;
00163 return NULL;
00164 }
00165 else
00166 {
00167 IModel *m= (*itModel).Creator();
00168 if(!m) return NULL;
00169
00170
00171 m->_OwnerMot= this;
00172
00173
00174 std::vector<CTravEntry>::const_iterator itTrav;
00175 for(itTrav= Traversals.begin(); itTrav!=Traversals.end(); itTrav++)
00176 {
00177
00178 IObs *obs= createObs((*itTrav).Trav, idModel);
00179 nlassert(obs);
00180
00181 obs->Model= m;
00182 obs->Trav= (*itTrav).Trav;
00183
00184 m->Observers.insert(IModel::CObsMap::value_type((*itTrav).TravId, obs));
00185
00186 if((*itTrav).Trav->getRoot())
00187 (*itTrav).Trav->link(NULL, m);
00188 }
00189
00190
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
00199 Models.insert(m);
00200
00201
00202 m->linkToValidateList();
00203
00204
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
00228 IModel *model= _ValidateModelList;
00229 IModel *next;
00230 while( model )
00231 {
00232
00233 next= model->_NextModelToValidate;
00234
00235
00236 model->validate();
00237
00238
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
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
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
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
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
00333
00334
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
00361
00362
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
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
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
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
00478 unlinkFromValidateList();
00479
00480
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
00513 if(TouchObs[IModel::Dirty])
00514 {
00515
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
00524 cleanTouch();
00525 }
00526 }
00527
00528
00529
00530 void IModel::linkToValidateList()
00531 {
00532 if(!_OwnerMot)
00533 return;
00534
00535
00536 if( ! (_PrecModelToValidate!=NULL || _OwnerMot->_ValidateModelList==this) )
00537 {
00538
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
00555 if( _PrecModelToValidate!=NULL || _OwnerMot->_ValidateModelList==this )
00556 {
00557
00558 if(_PrecModelToValidate)
00559 _PrecModelToValidate->_NextModelToValidate= _NextModelToValidate;
00560 else
00561 _OwnerMot->_ValidateModelList= _NextModelToValidate;
00562
00563
00564 if(_NextModelToValidate)
00565 _NextModelToValidate->_PrecModelToValidate= _PrecModelToValidate;
00566
00567
00568 _PrecModelToValidate= NULL;
00569 _NextModelToValidate= NULL;
00570 }
00571 }
00572
00573
00574
00575
00576
00577
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
00600 SonMap.clear();
00601 FatherMap.clear();
00602
00603
00604 for(it= FatherList.begin(); it!=FatherList.end(); it++)
00605 {
00606 IObs *father= (*it);
00607
00608 father->delChild(this);
00609 }
00610
00611
00612 for(it= SonList.begin(); it!=SonList.end(); it++)
00613 {
00614 IObs *son= (*it);
00615
00616 son->delParent(this);
00617 }
00618
00619
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
00638 ItObsMap it= SonMap.find(son);
00639 if(it==SonMap.end())
00640 {
00641
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
00652 ItObsMap it= SonMap.find(son);
00653 if(it!=SonMap.end())
00654 {
00655
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
00669 ItObsMap itMap;
00670 itMap= FatherMap.find(father);
00671 if(itMap!=FatherMap.end())
00672 return;
00673
00674
00675 for(ItObsList it= FatherList.begin(); it!=FatherList.end();it++)
00676 {
00677
00678 (*it)->delChild(this);
00679 }
00680 FatherMap.clear();
00681 FatherList.clear();
00682 }
00683
00684
00685 ItObsMap it= FatherMap.find(father);
00686 if(it==FatherMap.end())
00687 {
00688
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
00699 ItObsMap it= FatherMap.find(father);
00700 if(it!=FatherMap.end())
00701 {
00702
00703 FatherList.erase(it->second);
00704 FatherMap.erase(it);
00705 NumFathers--;
00706 }
00707 }
00708
00709
00710
00711 }