Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/world_entities/world_entity.cc @ 8735

Last change on this file since 8735 was 8724, checked in by bensch, 18 years ago

merged the bsp-model-stuff back here

File size: 21.2 KB
Line 
1
2
3/*
4   orxonox - the future of 3D-vertical-scrollers
5
6   Copyright (C) 2004 orx
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2, or (at your option)
11   any later version.
12
13   ### File Specific:
14   main-programmer: Patrick Boenzli
15   co-programmer: Christian Meyer
16*/
17#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY
18
19#include "world_entity.h"
20#include "shell_command.h"
21
22#include "model.h"
23#include "md2/md2Model.h"
24#include "md3/md3_model.h"
25
26#include "aabb_tree_node.h"
27
28#include "util/loading/resource_manager.h"
29#include "util/loading/load_param.h"
30#include "vector.h"
31#include "obb_tree.h"
32
33#include "glgui_bar.h"
34
35#include "state.h"
36#include "camera.h"
37
38#include "collision_handle.h"
39#include "collision_event.h"
40
41#include <stdarg.h>
42
43
44using namespace std;
45
46SHELL_COMMAND(model, WorldEntity, loadModel)
47->describe("sets the Model of the WorldEntity")
48->defaultValues("models/ships/fighter.obj", 1.0f);
49
50SHELL_COMMAND(debugEntity, WorldEntity, debugWE);
51
52/**
53 *  Loads the WordEntity-specific Part of any derived Class
54 *
55 * @param root: Normally NULL, as the Derived Entities define a loadParams Function themeselves,
56 *              that can calls WorldEntities loadParams for itself.
57 */
58WorldEntity::WorldEntity()
59    : Synchronizeable()
60{
61  this->setClassID(CL_WORLD_ENTITY, "WorldEntity");
62
63  this->obbTree = NULL;
64  this->aabbNode = NULL;
65  this->healthWidget = NULL;
66  this->healthMax = 1.0f;
67  this->health = 1.0f;
68  this->damage = 0.0f; // no damage dealt by a default entity
69  this->scaling = 1.0f;
70
71  /* OSOLETE */
72  this->bVisible = true;
73  this->bCollide = true;
74
75  this->objectListNumber = OM_INIT;
76  this->objectListIterator = NULL;
77
78  // reset all collision handles to NULL == unsubscribed state
79  for(int i = 0; i < CREngine::CR_NUMBER; ++i)
80    this->collisionHandles[i] = NULL;
81  this->bReactive = false;
82
83  // registering default reactions:
84//   this->subscribeReaction(CREngine::CR_OBJECT_DAMAGE, CL_WORLD_ENTITY);
85
86  this->toList(OM_NULL);
87
88  modelFileName_handle = registerVarId( new SynchronizeableString( &modelFileName, &modelFileName, "modelFileName" ) );
89  scaling_handle = registerVarId( new SynchronizeableFloat( &scaling, &scaling, "scaling" ) );
90}
91
92/**
93 *  standard destructor
94*/
95WorldEntity::~WorldEntity ()
96{
97  State::getObjectManager()->toList(this, OM_INIT);
98
99  // Delete the model (unregister it with the ResourceManager)
100  for (unsigned int i = 0; i < this->models.size(); i++)
101    this->setModel(NULL, i);
102
103  // Delete the obbTree
104  if( this->obbTree != NULL)
105    delete this->obbTree;
106
107  if (this->healthWidget != NULL)
108    delete this->healthWidget;
109
110  this->unsubscribeReaction();
111}
112
113/**
114 * loads the WorldEntity Specific Parameters.
115 * @param root: the XML-Element to load the Data From
116 */
117void WorldEntity::loadParams(const TiXmlElement* root)
118{
119  // Do the PNode loading stuff
120  PNode::loadParams(root);
121
122  LoadParam(root, "md2texture", this, WorldEntity, loadMD2Texture)
123  .describe("the fileName of the texture, that should be loaded onto this world-entity. (must be relative to the data-dir)")
124  .defaultValues("");
125
126  // Model Loading
127  LoadParam(root, "model", this, WorldEntity, loadModel)
128  .describe("the fileName of the model, that should be loaded onto this world-entity. (must be relative to the data-dir)")
129  .defaultValues("", 1.0f, 0);
130
131  LoadParam(root, "maxHealth", this, WorldEntity, setHealthMax)
132  .describe("The Maximum health that can be loaded onto this entity")
133  .defaultValues(1.0f);
134
135  LoadParam(root, "health", this, WorldEntity, setHealth)
136  .describe("The Health the WorldEntity has at this moment")
137  .defaultValues(1.0f);
138}
139
140
141/**
142 * loads a Model onto a WorldEntity
143 * @param fileName the name of the model to load
144 * @param scaling the Scaling of the model
145 *
146 * FIXME
147 * @todo: separate the obb tree generation from the model
148 */
149void WorldEntity::loadModel(const std::string& fileName, float scaling, unsigned int modelNumber, unsigned int obbTreeDepth)
150{
151  this->modelLODName = fileName;
152  this->scaling = scaling;
153
154  std::string name = fileName;
155
156  if (  name.find( ResourceManager::getInstance()->getDataDir() ) == 0 )
157  {
158    name.erase(ResourceManager::getInstance()->getDataDir().size());
159  }
160
161  this->modelFileName = name;
162
163  if (!fileName.empty())
164  {
165    // search for the special character # in the LoadParam
166    if (fileName.find('#') != std::string::npos)
167    {
168      PRINTF(4)("Found # in %s... searching for LOD's\n", fileName.c_str());
169      std::string lodFile = fileName;
170      unsigned int offset = lodFile.find('#');
171      for (unsigned int i = 0; i < 3; i++)
172      {
173        lodFile[offset] = 48+(int)i;
174        if (ResourceManager::isInDataDir(lodFile))
175          this->loadModel(lodFile, scaling, i);
176      }
177      return;
178    }
179    if (this->scaling <= 0.0)
180    {
181      PRINTF(1)("YOU GAVE ME A CRAPY SCALE resetting to 1.0\n");
182      this->scaling = 1.0;
183    }
184    if(fileName.find(".obj") != std::string::npos)
185    {
186      PRINTF(4)("fetching OBJ file: %s\n", fileName.c_str());
187      BaseObject* loadedModel = ResourceManager::getInstance()->load(fileName, OBJ, RP_CAMPAIGN, this->scaling);
188      if (loadedModel != NULL)
189        this->setModel(dynamic_cast<Model*>(loadedModel), modelNumber);
190      else
191        PRINTF(1)("OBJ-File %s not found.\n", fileName.c_str());
192
193      if( modelNumber == 0)
194        this->buildObbTree(obbTreeDepth);
195    }
196    else if(fileName.find(".md2") != std::string::npos)
197    {
198      PRINTF(4)("fetching MD2 file: %s\n", fileName.c_str());
199      Model* m = new MD2Model(fileName, this->md2TextureFileName, this->scaling);
200      //this->setModel((Model*)ResourceManager::getInstance()->load(fileName, MD2, RP_CAMPAIGN), 0);
201      this->setModel(m, 0);
202
203      if( m != NULL)
204        this->buildObbTree(obbTreeDepth);
205    }
206    else /*if(fileName.find(".md3") != std::string::npos)*/
207    {
208      PRINTF(4)("fetching MD3 file: %s\n", fileName.c_str());
209      Model* m = new md3::MD3Model(fileName, this->scaling);
210      this->setModel(m, 0);
211
212//       if( m != NULL)
213//         this->buildObbTree(obbTreeDepth);
214    }
215  }
216  else
217  {
218    this->setModel(NULL);
219  }
220}
221
222/**
223 * sets a specific Model for the Object.
224 * @param model The Model to set
225 * @param modelNumber the n'th model in the List to get.
226 */
227void WorldEntity::setModel(Model* model, unsigned int modelNumber)
228{
229  if (this->models.size() <= modelNumber)
230    this->models.resize(modelNumber+1, NULL);
231
232  if (this->models[modelNumber] != NULL)
233  {
234    Resource* resource = ResourceManager::getInstance()->locateResourceByPointer(dynamic_cast<BaseObject*>(this->models[modelNumber]));
235    if (resource != NULL)
236      ResourceManager::getInstance()->unload(resource, RP_LEVEL);
237    else
238    {
239      PRINTF(4)("Forcing model deletion\n");
240      delete this->models[modelNumber];
241    }
242  }
243
244  this->models[modelNumber] = model;
245}
246
247
248/**
249 * builds the obb-tree
250 * @param depth the depth to calculate
251 */
252bool WorldEntity::buildObbTree(int depth)
253{
254  if (this->obbTree)
255    delete this->obbTree;
256
257  if (this->models[0] != NULL)
258    this->obbTree = new OBBTree(depth, models[0]->getModelInfo(), this);
259  else
260  {
261    PRINTF(1)("could not create obb-tree, because no model was loaded yet\n");
262    this->obbTree = NULL;
263    return false;
264  }
265
266
267  // create the axis aligned bounding box
268  if( this->aabbNode != NULL)
269  {
270    delete this->aabbNode;
271    this->aabbNode = NULL;
272  }
273
274  if( this->models[0] != NULL) {
275    this->aabbNode = new AABBTreeNode();
276    this->aabbNode->spawnBVTree(this->models[0]);
277  }
278  return true;
279}
280
281
282/**
283 * subscribes this world entity to a collision reaction
284 *  @param type the type of reaction to subscribe to
285 *  @param target1 a filter target (classID)
286 */
287void WorldEntity::subscribeReaction(CREngine::CRType type, long target1)
288{
289  this->subscribeReaction(type);
290
291  // add the target filter
292  this->collisionHandles[type]->addTarget(target1);
293}
294
295
296/**
297 * subscribes this world entity to a collision reaction
298 *  @param type the type of reaction to subscribe to
299 *  @param target1 a filter target (classID)
300 */
301void WorldEntity::subscribeReaction(CREngine::CRType type, long target1, long target2)
302{
303  this->subscribeReaction(type);
304
305  // add the target filter
306  this->collisionHandles[type]->addTarget(target1);
307  this->collisionHandles[type]->addTarget(target2);
308}
309
310
311/**
312 * subscribes this world entity to a collision reaction
313 *  @param type the type of reaction to subscribe to
314 *  @param target1 a filter target (classID)
315 */
316void WorldEntity::subscribeReaction(CREngine::CRType type, long target1, long target2, long target3)
317{
318  this->subscribeReaction(type);
319
320  // add the target filter
321  this->collisionHandles[type]->addTarget(target1);
322  this->collisionHandles[type]->addTarget(target2);
323  this->collisionHandles[type]->addTarget(target3);
324}
325
326
327/**
328 * subscribes this world entity to a collision reaction
329 *  @param type the type of reaction to subscribe to
330 *  @param target1 a filter target (classID)
331 */
332void WorldEntity::subscribeReaction(CREngine::CRType type, long target1, long target2, long target3, long target4)
333{
334  this->subscribeReaction(type);
335
336  // add the target filter
337  this->collisionHandles[type]->addTarget(target1);
338  this->collisionHandles[type]->addTarget(target2);
339  this->collisionHandles[type]->addTarget(target3);
340  this->collisionHandles[type]->addTarget(target4);
341}
342
343
344/**
345 * subscribes this world entity to a collision reaction
346 *  @param type the type of reaction to subscribe to
347 *  @param nrOfTargets number of target filters
348 *  @param ... the targets as classIDs
349 */
350void WorldEntity::subscribeReaction(CREngine::CRType type)
351{
352  if( this->collisionHandles[type] != NULL)  {
353    PRINTF(2)("Registering for a CollisionReaction already subscribed to! Skipping\n");
354    return;
355  }
356
357  this->collisionHandles[type] = CREngine::getInstance()->subscribeReaction(this, type);
358
359  // now there is at least one collision reaction subscribed
360  this->bReactive = true;
361}
362
363
364/**
365 * unsubscribes a specific reaction from the worldentity
366 *  @param type the reaction to unsubscribe
367 */
368void WorldEntity::unsubscribeReaction(CREngine::CRType type)
369{
370  if( this->collisionHandles[type] == NULL)
371    return;
372
373  CREngine::getInstance()->unsubscribeReaction(this->collisionHandles[type]);
374  this->collisionHandles[type] = NULL;
375
376  // check if there is still any handler registered
377  for(int i = 0; i < CREngine::CR_NUMBER; ++i)
378  {
379    if( this->collisionHandles[i] != NULL)
380    {
381      this->bReactive = true;
382      return;
383    }
384  }
385  this->bReactive = false;
386}
387
388
389/**
390 * unsubscribes all collision reactions
391 */
392void WorldEntity::unsubscribeReaction()
393{
394  for( int i = 0; i < CREngine::CR_NUMBER; i++)
395    this->unsubscribeReaction((CREngine::CRType)i);
396
397  // there are no reactions subscribed from now on
398  this->bReactive = false;
399}
400
401
402/**
403 * registers a new collision event to this world entity
404 *  @param entityA entity of the collision
405 *  @param entityB entity of the collision
406 *  @param bvA colliding bounding volume of entityA
407 *  @param bvB colliding bounding volume of entityA
408 */
409bool WorldEntity::registerCollision(WorldEntity* entityA, WorldEntity* entityB, BoundingVolume* bvA, BoundingVolume* bvB)
410{
411  // is there any handler listening?
412  if( !this->bReactive)
413    return false;
414
415  // get a collision event
416  CollisionEvent* c = CREngine::getInstance()->popCollisionEventObject();
417  assert(c != NULL); // if this should fail: we got not enough precached CollisionEvents: alter value in cr_defs.h
418  c->collide(entityA, entityB, bvA, bvB);
419
420  for( int i = 0; i < CREngine::CR_NUMBER; ++i)
421    if( this->collisionHandles[i] != NULL)
422      this->collisionHandles[i]->registerCollisionEvent(c);
423  return true;
424}
425
426
427/**
428 * registers a new collision event to this woeld entity
429 *  @param entity the entity that collides
430 *  @param plane it stands on
431 *  @param position it collides on the plane
432 */
433bool WorldEntity::registerCollision(WorldEntity* entity, WorldEntity* groundEntity, Vector normal, Vector position)
434{
435  // is there any handler listening?
436  if( !this->bReactive)
437    return false;
438
439  // get a collision event
440  CollisionEvent* c = CREngine::getInstance()->popCollisionEventObject();
441  assert(c != NULL); // if this should fail: we got not enough precached CollisionEvents: alter value in cr_defs.h
442  c->collide(entity, groundEntity, normal, position);
443
444  for( int i = 0; i < CREngine::CR_NUMBER; ++i)
445    if( this->collisionHandles[i] != NULL)
446      this->collisionHandles[i]->registerCollisionEvent(c);
447  return true;
448}
449
450
451/**
452 * @brief moves this entity to the List OM_List
453 * @param list the list to set this Entity to.
454 *
455 * this is the same as a call to State::getObjectManager()->toList(entity , list);
456 * directly, but with an easier interface.
457 *
458 * @todo inline this (peut etre)
459 */
460void WorldEntity::toList(OM_LIST list)
461{
462  State::getObjectManager()->toList(this, list);
463}
464
465void WorldEntity::toReflectionList()
466{
467  State::getObjectManager()->toReflectionList( this );
468}
469
470void removeFromReflectionList()
471{
472/// TODO
473///  State::getObject
474}
475
476/**
477 * sets the character attributes of a worldentity
478 * @param character attributes
479 *
480 * these attributes don't have to be set, only use them, if you need them
481*/
482//void WorldEntity::setCharacterAttributes(CharacterAttributes* charAttr)
483//{}
484
485
486/**
487 *  this function is called, when two entities collide
488 * @param entity: the world entity with whom it collides
489 *
490 * Implement behaviour like damage application or other miscellaneous collision stuff in this function
491 */
492void WorldEntity::collidesWith(WorldEntity* entity, const Vector& location)
493{
494  /**
495   * THIS IS A DEFAULT COLLISION-Effect.
496   * IF YOU WANT TO CREATE A SPECIFIC COLLISION ON EACH OBJECT
497   * USE::
498   * if (entity->isA(CL_WHAT_YOU_ARE_LOOKING_FOR)) { printf "dothings"; };
499   *
500   * You can always define a default Action.... don't be affraid just test it :)
501   */
502  //  PRINTF(3)("collision %s vs %s @ (%f,%f,%f)\n", this->getClassName(), entity->getClassName(), location.x, location.y, location.z);
503}
504
505
506/**
507 *  this function is called, when two entities collide
508 * @param entity: the world entity with whom it collides
509 *
510 * Implement behaviour like damage application or other miscellaneous collision stuff in this function
511 */
512void WorldEntity::collidesWithGround(const Vector& location)
513{
514  PRINTF(0)("BSP_GROUND: %s collides \n", this->getClassName() );
515}
516
517void WorldEntity::collidesWithGround(const Vector& feet, const Vector& ray_1, const Vector& ray_2)
518{
519
520  // PRINTF(0)("BSP_GROUND: Player collides \n", this->getClassName() );
521
522  Vector v = this->getAbsDirX();
523  v.x *= 10.1;
524  v.y *= 10.1;
525  v.z *= 10.1;
526  Vector u = Vector(0.0,-20.0,0.0);
527
528
529  if(!(this->getAbsCoor().x == ray_2.x && this->getAbsCoor().y == ray_2.y && this->getAbsCoor().z == ray_2.z) )
530  {
531
532  this->setAbsCoor(ray_2 - v);
533
534  }
535    else
536  {
537    if(ray_1.x == this->getAbsCoor().x + v.x && ray_1.y == this->getAbsCoor().y + v.y + 0.1 && ray_1.z ==this->getAbsCoor().z + v.z)
538    {
539      this->setAbsCoor(feet -u );
540    }
541
542    this->setAbsCoor(ray_2 - v);
543
544  }
545
546
547}
548
549/**
550 *  this is called immediately after the Entity has been constructed, initialized and then Spawned into the World
551 *
552 */
553void WorldEntity::postSpawn ()
554{}
555
556
557/**
558 *  this method is called by the world if the WorldEntity leaves the game
559 */
560void WorldEntity::leaveWorld ()
561{}
562
563
564/**
565 * resets the WorldEntity to its initial values. eg. used for multiplayer games: respawning
566 */
567void WorldEntity::reset()
568{}
569
570/**
571 *  this method is called every frame
572 * @param time: the time in seconds that has passed since the last tick
573 *
574 * Handle all stuff that should update with time inside this method (movement, animation, etc.)
575*/
576void WorldEntity::tick(float time)
577{}
578
579
580/**
581 *  the entity is drawn onto the screen with this function
582 *
583 * This is a central function of an entity: call it to let the entity painted to the screen.
584 * Just override this function with whatever you want to be drawn.
585*/
586void WorldEntity::draw() const
587{
588  //PRINTF(0)("(%s::%s)\n", this->getClassName(), this->getName());
589  //  assert(!unlikely(this->models.empty()));
590  {
591    glMatrixMode(GL_MODELVIEW);
592    glPushMatrix();
593
594    /* translate */
595    glTranslatef (this->getAbsCoor ().x,
596                  this->getAbsCoor ().y,
597                  this->getAbsCoor ().z);
598    Vector tmpRot = this->getAbsDir().getSpacialAxis();
599    glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
600
601
602    // This Draws the LOD's
603    float cameraDistance = State::getCamera()->distance(this);
604    if (cameraDistance > 30 && this->models.size() >= 3 && this->models[2] != NULL)
605    {
606      this->models[2]->draw();
607    }
608    else if (cameraDistance > 10 && this->models.size() >= 2 && this->models[1] != NULL)
609    {
610      this->models[1]->draw();
611    }
612    else if (this->models.size() >= 1 && this->models[0] != NULL)
613    {
614      this->models[0]->draw();
615    }
616
617    if( this->aabbNode != NULL)
618      this->aabbNode->drawBV(0, DRAW_BV_POLYGON, Vector(1, 0.6, 0.2), true);
619
620    glPopMatrix();
621  }
622}
623
624/**
625 * @param health the Health to add.
626 * @returns the health left (this->healthMax - health+this->health)
627 */
628float WorldEntity::increaseHealth(float health)
629{
630  this->health += health;
631  if (this->health > this->healthMax)
632  {
633    float retHealth = this->healthMax - this->health;
634    this->health = this->healthMax;
635    this->updateHealthWidget();
636    return retHealth;
637  }
638  this->updateHealthWidget();
639  return 0.0;
640}
641
642/**
643 * @param health the Health to be removed
644 * @returns 0.0 or the rest, that was not substracted (bellow 0.0)
645 */
646float WorldEntity::decreaseHealth(float health)
647{
648  this->health -= health;
649
650  if (this->health < 0)
651  {
652    float retHealth = -this->health;
653    this->health = 0.0f;
654    this->updateHealthWidget();
655    return retHealth;
656  }
657  this->updateHealthWidget();
658  return 0.0;
659
660}
661
662/**
663 * @param maxHealth the maximal health that can be loaded onto the entity.
664 */
665void WorldEntity::setHealthMax(float healthMax)
666{
667  this->healthMax = healthMax;
668  if (this->health > this->healthMax)
669  {
670    PRINTF(3)("new maxHealth is bigger as the old health. Did you really intend to do this for (%s::%s)\n", this->getClassName(), this->getName());
671    this->health = this->healthMax;
672  }
673  this->updateHealthWidget();
674}
675
676/**
677 * @brief creates the HealthWidget
678 *
679 * since not all entities need an HealthWidget, it is only created on request.
680 */
681void WorldEntity::createHealthWidget()
682{
683  if (this->healthWidget == NULL)
684  {
685    this->healthWidget = new OrxGui::GLGuiBar();
686    this->healthWidget->setSize2D(30,400);
687    this->healthWidget->setAbsCoor2D(10,100);
688
689    this->updateHealthWidget();
690  }
691  else
692    PRINTF(3)("Allready created the HealthWidget for %s::%s\n", this->getClassName(), this->getName());
693}
694
695void WorldEntity::increaseHealthMax(float increaseHealth)
696{
697  this->healthMax += increaseHealth;
698  this->updateHealthWidget();
699}
700
701
702OrxGui::GLGuiWidget* WorldEntity::getHealthWidget()
703{
704  this->createHealthWidget();
705  return this->healthWidget;
706}
707
708/**
709 * @param visibility shows or hides the health-bar
710 * (creates the widget if needed)
711 */
712void WorldEntity::setHealthWidgetVisibilit(bool visibility)
713{
714  if (visibility)
715  {
716    if (this->healthWidget != NULL)
717      this->healthWidget->show();
718    else
719    {
720      this->createHealthWidget();
721      this->updateHealthWidget();
722      this->healthWidget->show();
723    }
724  }
725  else if (this->healthWidget != NULL)
726    this->healthWidget->hide();
727}
728
729
730/**
731 * hit the world entity with
732 *  @param damage damage to be dealt
733 */
734void WorldEntity::hit(float damage)
735{
736  this->decreaseHealth(damage);
737
738  if( this->getHealth() > 0)
739  {
740    // any small explosion animaitions
741  }
742  else
743  {
744    this->destroy();
745
746//     if( State::getGameRules() != NULL)
747//       State::getGameRules()->registerKill(Kill(NULL, this));
748  }
749}
750
751
752/**
753 * @brief updates the HealthWidget
754 */
755void WorldEntity::updateHealthWidget()
756{
757  if (this->healthWidget != NULL)
758  {
759    this->healthWidget->setMaximum(this->healthMax);
760    this->healthWidget->setValue(this->health);
761  }
762}
763
764
765/**
766 * DEBUG-DRAW OF THE BV-Tree.
767 * @param depth What depth to draw
768 * @param drawMode the mode to draw this entity under
769 */
770void WorldEntity::drawBVTree(int depth, int drawMode) const
771{
772  glMatrixMode(GL_MODELVIEW);
773  glPushMatrix();
774  /* translate */
775  glTranslatef (this->getAbsCoor ().x,
776                this->getAbsCoor ().y,
777                this->getAbsCoor ().z);
778  /* rotate */
779  Vector tmpRot = this->getAbsDir().getSpacialAxis();
780  glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
781
782
783  if (this->obbTree)
784    this->obbTree->drawBV(depth, drawMode);
785
786
787  glPopMatrix();
788}
789
790
791/**
792 * Debug the WorldEntity
793 */
794void WorldEntity::debugEntity() const
795{
796  PRINT(0)("WorldEntity %s::%s  (DEBUG)\n", this->getClassName(), this->getName());
797  this->debugNode();
798  PRINT(0)("List: %s ; ModelCount %d - ", ObjectManager::OMListToString(this->objectListNumber) , this->models.size());
799  for (unsigned int i = 0; i < this->models.size(); i++)
800  {
801    if (models[i] != NULL)
802      PRINT(0)(" : %d:%s", i, this->models[i]->getName());
803  }
804  PRINT(0)("\n");
805
806}
807
808
809/**
810 * handler for changes on registred vars
811 * @param id id's which changed
812 */
813void WorldEntity::varChangeHandler( std::list< int > & id )
814{
815  if ( std::find( id.begin(), id.end(), modelFileName_handle ) != id.end() ||
816       std::find( id.begin(), id.end(), scaling_handle ) != id.end()
817     )
818  {
819    loadModel( modelFileName, scaling );
820  }
821
822  PNode::varChangeHandler( id );
823}
824
Note: See TracBrowser for help on using the repository browser.