Entity.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "Log.h"
  25. #include "Scene.h"
  26. #include "StringUtils.h"
  27. #include "DebugNew.h"
  28. Entity::Entity(EntityID id, const std::string& name) :
  29. mID(id),
  30. mName(name),
  31. mNameHash(name),
  32. mNetFlags(NET_SYNCTOALL),
  33. mGroupFlags(0),
  34. mScene(0),
  35. mOwner(0),
  36. mNextComponentName(0x30),
  37. mNetUpdateDistance(0.0f),
  38. mPredictionTimer(0.0f)
  39. {
  40. }
  41. Entity::~Entity()
  42. {
  43. removeAllComponents();
  44. }
  45. void Entity::onEvent(EventListener* sender, StringHash eventType, VariantMap& eventData)
  46. {
  47. WeakPtr<Entity> self(this);
  48. // Special-case event handling: send to all components that are event listeners
  49. for (unsigned i = 0; i < mEventListeners.size(); ++i)
  50. {
  51. // Do not check if the component actually subscribes to the event, because its onEvent() does that check
  52. mEventListeners[i]->onEvent(sender, eventType, eventData);
  53. // Exit immediately if entity was removed as a response to the event
  54. if (self.isExpired())
  55. return;
  56. }
  57. }
  58. void Entity::save(Serializer& dest)
  59. {
  60. // Write identification and flags
  61. dest.writeUInt(mID);
  62. dest.writeString(mName);
  63. dest.writeUByte(mNetFlags);
  64. dest.writeFloat(mNetUpdateDistance);
  65. dest.writeUInt(mGroupFlags);
  66. // Write properties
  67. dest.writeVLE(mProperties.size());
  68. for (PropertyMap::const_iterator i = mProperties.begin(); i != mProperties.end(); ++i)
  69. {
  70. dest.writeShortStringHash(i->first);
  71. dest.writeVariant(i->second.mValue);
  72. dest.writeBool(i->second.mSync);
  73. }
  74. // Write components
  75. dest.writeVLE(mComponents.size());
  76. for (std::vector<SharedPtr<Component> >::iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  77. (*i)->save(dest);
  78. }
  79. void Entity::load(Deserializer& source, ResourceCache* cache)
  80. {
  81. // Load should only be called for new entities, but remove components just to be sure
  82. removeAllComponents();
  83. // Scene reads the identification, so do not read here
  84. mNetFlags = source.readUByte();
  85. mNetUpdateDistance = source.readFloat();
  86. mGroupFlags = source.readUInt();
  87. // Read properties
  88. mProperties.clear();
  89. unsigned numProperties = source.readVLE();
  90. for (unsigned i = 0; i < numProperties; ++i)
  91. {
  92. ShortStringHash key = source.readShortStringHash();
  93. Property newProperty;
  94. newProperty.mValue = source.readVariant();
  95. newProperty.mSync = source.readBool();
  96. mProperties[key] = newProperty;
  97. }
  98. // Create and read components
  99. unsigned numComponents = source.readVLE();
  100. for (unsigned i = 0; i < numComponents; ++i)
  101. {
  102. ShortStringHash type = source.readShortStringHash();
  103. std::string name = source.readString();
  104. Component* newComponent = createComponent(type, name);
  105. newComponent->load(source, cache);
  106. }
  107. }
  108. void Entity::saveXML(XMLElement& dest)
  109. {
  110. // Write identification and flags
  111. dest.setInt("id", mID);
  112. if (!mName.empty())
  113. dest.setString("name", mName);
  114. dest.setInt("netflags", mNetFlags);
  115. dest.setFloat("netdistance", mNetUpdateDistance);
  116. dest.setInt("groupflags", mGroupFlags);
  117. // Write properties
  118. for (PropertyMap::const_iterator i = mProperties.begin(); i != mProperties.end(); ++i)
  119. {
  120. XMLElement propertyElem = dest.createChildElement("property");
  121. // Use name if possible, or hash if reverse mapping is unavailable
  122. std::string name = shortHashToString(i->first);
  123. if (name.empty())
  124. propertyElem.setInt("hash", i->first.mData);
  125. else
  126. propertyElem.setString("name", name);
  127. propertyElem.setVariant(i->second.mValue);
  128. propertyElem.setBool("sync", i->second.mSync);
  129. }
  130. // Write components
  131. for (std::vector<SharedPtr<Component> >::iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  132. {
  133. XMLElement componentElem = dest.createChildElement("component");
  134. (*i)->saveXML(componentElem);
  135. }
  136. }
  137. void Entity::loadXML(const XMLElement& source, ResourceCache* cache)
  138. {
  139. // Load should only be called for new entities, but remove components just to be sure
  140. removeAllComponents();
  141. // Scene reads the identification, so do not read here
  142. mNetFlags = source.getInt("netflags");
  143. mNetUpdateDistance = source.getFloat("netdistance");
  144. mGroupFlags = source.getInt("groupflags");
  145. // Read properties
  146. mProperties.clear();
  147. XMLElement propertyElem = source.getChildElement("property");
  148. while (propertyElem)
  149. {
  150. ShortStringHash key;
  151. if (propertyElem.hasAttribute("hash"))
  152. key.mData = propertyElem.getInt("hash");
  153. else
  154. key = ShortStringHash(propertyElem.getString("name"));
  155. Property newProperty;
  156. newProperty.mValue = propertyElem.getVariant();
  157. newProperty.mSync = propertyElem.getBool("sync");
  158. mProperties[key] = newProperty;
  159. propertyElem = propertyElem.getNextElement("property");
  160. }
  161. // Create and read components
  162. XMLElement componentElem = source.getChildElement("component");
  163. while (componentElem)
  164. {
  165. std::string type = componentElem.getString("type");
  166. std::string name = componentElem.getString("name");
  167. Component* newComponent = createComponent(ShortStringHash(type), name);
  168. newComponent->loadXML(componentElem, cache);
  169. componentElem = componentElem.getNextElement("component");
  170. }
  171. }
  172. void Entity::postLoad(ResourceCache* cache)
  173. {
  174. // Perform post-load on all components (resolve entity & component references)
  175. for (std::vector<SharedPtr<Component> >::iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  176. (*i)->postLoad(cache);
  177. }
  178. bool Entity::writeNetUpdate(Serializer& dest, Serializer& destRevision, Deserializer& baseRevision, const NetUpdateInfo& info)
  179. {
  180. // Note: this function only builds a delta-update of entity properties, not components
  181. VariantMap baseProperties;
  182. if (baseRevision.getSize())
  183. {
  184. // We read the base properties as an ordinary variantmap, because only synced properties are stored,
  185. // and therefored storing the sync bool would be redundant
  186. baseProperties = baseRevision.readVariantMap();
  187. }
  188. unsigned syncedProperties = 0;
  189. std::set<ShortStringHash> changedProperties;
  190. for (PropertyMap::iterator i = mProperties.begin(); i != mProperties.end(); ++i)
  191. {
  192. if (i->second.mSync)
  193. {
  194. VariantMap::const_iterator j = baseProperties.find(i->first);
  195. if ((j == baseProperties.end()) || (i->second.mValue != j->second))
  196. changedProperties.insert(i->first);
  197. ++syncedProperties;
  198. }
  199. }
  200. // Write all synced properties to the dest.revision buffer, and delta to network stream
  201. destRevision.writeVLE(syncedProperties);
  202. dest.writeVLE(changedProperties.size());
  203. for (PropertyMap::iterator i = mProperties.begin(); i != mProperties.end(); ++i)
  204. {
  205. if (i->second.mSync)
  206. {
  207. destRevision.writeShortStringHash(i->first);
  208. destRevision.writeVariant(i->second.mValue);
  209. if (changedProperties.find(i->first) != changedProperties.end())
  210. {
  211. dest.writeShortStringHash(i->first);
  212. dest.writeVariant(i->second.mValue);
  213. }
  214. }
  215. }
  216. return changedProperties.size() > 0;
  217. }
  218. void Entity::postNetUpdate(ResourceCache* cache)
  219. {
  220. // Perform post-network update on all components (resolve entity & component references)
  221. // Note: does not track which components actually got updated. For most components this is a no-op
  222. for (std::vector<SharedPtr<Component> >::iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  223. {
  224. if ((*i)->isProxy())
  225. (*i)->postNetUpdate(cache);
  226. }
  227. }
  228. void Entity::interpolate(bool snapToEnd)
  229. {
  230. // Interpolate all proxy components
  231. for (std::vector<SharedPtr<Component> >::iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  232. {
  233. if ((*i)->isProxy())
  234. (*i)->interpolate(snapToEnd);
  235. }
  236. }
  237. void Entity::getComponentRefs(std::vector<ComponentRef>& dest)
  238. {
  239. dest.clear();
  240. for (std::vector<SharedPtr<Component> >::iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  241. (*i)->getComponentRefs(dest);
  242. }
  243. void Entity::getResourceRefs(std::vector<Resource*>& dest)
  244. {
  245. dest.clear();
  246. for (std::vector<SharedPtr<Component> >::iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  247. (*i)->getResourceRefs(dest);
  248. }
  249. void Entity::setName(const std::string& name)
  250. {
  251. mName = name;
  252. mNameHash = StringHash(name);
  253. }
  254. void Entity::setNetFlags(unsigned char flags)
  255. {
  256. // Respect the authority and proxy flags if they have been set already
  257. if (mNetFlags & NET_MODEFLAGS)
  258. mNetFlags = (mNetFlags & NET_MODEFLAGS) | (flags & ~NET_MODEFLAGS);
  259. else
  260. mNetFlags = flags;
  261. }
  262. void Entity::setGroupFlags(unsigned flags)
  263. {
  264. mGroupFlags = flags;
  265. }
  266. void Entity::setOwner(Connection* owner)
  267. {
  268. if (mID >= LOCAL_ENTITY)
  269. {
  270. LOGERROR("Owner can not be set for local entities");
  271. return;
  272. }
  273. mOwner = owner;
  274. }
  275. void Entity::setProperty(ShortStringHash key, const Variant& value)
  276. {
  277. mProperties[key].mValue = value;
  278. }
  279. void Entity::setProperty(ShortStringHash key, const Variant& value, bool sync)
  280. {
  281. mProperties[key].mValue = value;
  282. mProperties[key].mSync = sync;
  283. }
  284. void Entity::setPropertySync(ShortStringHash key, bool enable)
  285. {
  286. mProperties[key].mSync = enable;
  287. }
  288. void Entity::setProperties(const PropertyMap& properties)
  289. {
  290. mProperties = properties;
  291. }
  292. void Entity::setProperties(const VariantMap& properties, bool sync)
  293. {
  294. mProperties.clear();
  295. for (VariantMap::const_iterator i = properties.begin(); i != properties.end(); ++i)
  296. {
  297. Property newProperty;
  298. newProperty.mValue = i->second;
  299. newProperty.mSync = sync;
  300. mProperties[i->first] = newProperty;
  301. }
  302. }
  303. void Entity::setNetUpdateDistance(float distance)
  304. {
  305. mNetUpdateDistance = max(distance, 0.0f);
  306. }
  307. void Entity::setPredictionTimer(float time)
  308. {
  309. if (!isTransientPredicted())
  310. return;
  311. mPredictionTimer = time;
  312. }
  313. void Entity::setPredictionFrom(Entity* other)
  314. {
  315. if (!isTransientPredicted())
  316. return;
  317. // If the other entity is owner-predicted, set full prediction period. Otherwise propagate the higher timer value
  318. if (other->isOwnerPredicted())
  319. mPredictionTimer = mScene->getTransientPredictionTime();
  320. if (other->isTransientPredicted())
  321. mPredictionTimer = max(mPredictionTimer, other->getPredictionTimer());
  322. }
  323. void Entity::updatePredictionTimer(float timeStep)
  324. {
  325. // Decrement prediction timer if necessary
  326. if (mPredictionTimer > 0.0f)
  327. mPredictionTimer = max(mPredictionTimer - timeStep, 0.0f);
  328. }
  329. void Entity::removeProperty(ShortStringHash key)
  330. {
  331. PropertyMap::iterator i = mProperties.find(key);
  332. if (i != mProperties.end())
  333. mProperties.erase(i);
  334. }
  335. void Entity::removeAllProperties()
  336. {
  337. mProperties.clear();
  338. }
  339. void Entity::addComponent(Component* component)
  340. {
  341. if (!component)
  342. {
  343. LOGERROR("Null component for addComponent");
  344. return;
  345. }
  346. ShortStringHash combinedHash = component->getCombinedHash();
  347. for (std::vector<SharedPtr<Component> >::const_iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  348. {
  349. // Make sure component is not already added
  350. if (component == *i)
  351. {
  352. LOGWARNING("Component " + component->getTypeName() + " already added to entity " + mName);
  353. return;
  354. }
  355. // Check the same combined hash does not already exist (can not replicate or load/save parent references)
  356. if (combinedHash == (*i)->getCombinedHash())
  357. {
  358. // If types differ, it is a more insiduous hash collision
  359. if (component->getType() != (*i)->getType())
  360. {
  361. SAFE_EXCEPTION("Component hash collision between " + component->getTypeName() + " name " + component->getName() +
  362. " and " + (*i)->getTypeName() + " name " + (*i)->getName() + " in entity " + mName);
  363. }
  364. // The more common cause is adding several components with the same type and name
  365. else
  366. {
  367. LOGERROR("Component with type " + component->getTypeName() + " name " + component->getName() +
  368. "already exists in entity " + mName);
  369. }
  370. }
  371. }
  372. component->mEntity = this;
  373. mComponents.push_back(SharedPtr<Component>(component));
  374. updateEventListeners();
  375. }
  376. Component* Entity::createComponent(ShortStringHash type, const std::string& name)
  377. {
  378. if (!mScene)
  379. EXCEPTION("Entity not in scene, can not create components");
  380. SharedPtr<Component> newComponent = mScene->createComponent(type, name);
  381. addComponent(newComponent);
  382. return newComponent;
  383. }
  384. void Entity::removeComponent(Component* component)
  385. {
  386. if (!component)
  387. return;
  388. for (std::vector<SharedPtr<Component> >::iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  389. {
  390. if ((*i) == component)
  391. {
  392. removeComponent(i);
  393. return;
  394. }
  395. }
  396. LOGWARNING("Component " + component->getTypeName() + " not found in entity " + mName);
  397. }
  398. void Entity::removeComponent(ShortStringHash type, const std::string& name)
  399. {
  400. for (std::vector<SharedPtr<Component> >::iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  401. {
  402. if (((*i)->getType() == type) && ((name.empty()) || ((*i)->getName() == name)))
  403. {
  404. removeComponent(i);
  405. return;
  406. }
  407. }
  408. LOGWARNING("Component type " + toString(type) + " name " + name + " not found in entity " + mName);
  409. }
  410. void Entity::removeComponent(ShortStringHash type, StringHash nameHash)
  411. {
  412. for (std::vector<SharedPtr<Component> >::iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  413. {
  414. if (((*i)->getType() == type) && ((!nameHash) || ((*i)->getNameHash() == nameHash)))
  415. {
  416. removeComponent(i);
  417. return;
  418. }
  419. }
  420. LOGWARNING("Component type " + toString(type) + " name hash " + toString(nameHash) + " not found in entity " + mName);
  421. }
  422. void Entity::removeAllComponents()
  423. {
  424. while (mComponents.size())
  425. removeComponent(mComponents.end() - 1, true);
  426. mEventListeners.clear();
  427. }
  428. bool Entity::hasProperty(ShortStringHash key) const
  429. {
  430. PropertyMap::const_iterator i = mProperties.find(key);
  431. if (i == mProperties.end())
  432. return false;
  433. return i->second.mValue.getType() != VAR_NONE;
  434. }
  435. const Variant& Entity::getProperty(ShortStringHash key) const
  436. {
  437. static const Variant empty;
  438. PropertyMap::const_iterator i = mProperties.find(key);
  439. if (i == mProperties.end())
  440. return empty;
  441. else
  442. return i->second.mValue;
  443. }
  444. bool Entity::getPropertySync(ShortStringHash key) const
  445. {
  446. PropertyMap::const_iterator i = mProperties.find(key);
  447. if (i == mProperties.end())
  448. return false;
  449. else
  450. return i->second.mSync;
  451. }
  452. std::string Entity::getUniqueComponentName()
  453. {
  454. std::string ret;
  455. ret += mNextComponentName;
  456. ++mNextComponentName;
  457. // Use only 0-9, @-Z and a-z to be sure component survives XML serialization
  458. if (mNextComponentName == 0x3a)
  459. mNextComponentName = 0x40;
  460. if (mNextComponentName == 0x5b)
  461. mNextComponentName = 0x61;
  462. if (mNextComponentName == 0x7b)
  463. mNextComponentName = 0x30;
  464. return ret;
  465. }
  466. bool Entity::hasComponent(ShortStringHash type) const
  467. {
  468. for (std::vector<SharedPtr<Component> >::const_iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  469. {
  470. if ((*i)->getType() == type)
  471. return true;
  472. }
  473. return false;
  474. }
  475. bool Entity::hasComponent(ShortStringHash type, const std::string& name) const
  476. {
  477. for (std::vector<SharedPtr<Component> >::const_iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  478. {
  479. if (((*i)->getType() == type) && ((*i)->getName() == name))
  480. return true;
  481. }
  482. return false;
  483. }
  484. bool Entity::hasComponent(ShortStringHash type, StringHash nameHash) const
  485. {
  486. for (std::vector<SharedPtr<Component> >::const_iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  487. {
  488. if (((*i)->getType() == type) && ((*i)->getNameHash() == nameHash))
  489. return true;
  490. }
  491. return false;
  492. }
  493. bool Entity::hasComponent(unsigned short combinedHash) const
  494. {
  495. for (std::vector<SharedPtr<Component> >::const_iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  496. {
  497. if ((*i)->getCombinedHash().mData == combinedHash)
  498. return true;
  499. }
  500. return false;
  501. }
  502. Component* Entity::getComponent(ShortStringHash type) const
  503. {
  504. for (std::vector<SharedPtr<Component> >::const_iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  505. {
  506. if ((*i)->getType() == type)
  507. return *i;
  508. }
  509. return 0;
  510. }
  511. Component* Entity::getComponent(ShortStringHash type, const std::string& name) const
  512. {
  513. for (std::vector<SharedPtr<Component> >::const_iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  514. {
  515. if (((*i)->getType() == type) && ((*i)->getName() == name))
  516. return *i;
  517. }
  518. return 0;
  519. }
  520. Component* Entity::getComponent(ShortStringHash type, StringHash nameHash) const
  521. {
  522. for (std::vector<SharedPtr<Component> >::const_iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  523. {
  524. if (((*i)->getType() == type) && ((*i)->getNameHash() == nameHash))
  525. return *i;
  526. }
  527. return 0;
  528. }
  529. Component* Entity::getComponent(unsigned short combinedHash) const
  530. {
  531. for (std::vector<SharedPtr<Component> >::const_iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  532. {
  533. if ((*i)->getCombinedHash().mData == combinedHash)
  534. return *i;
  535. }
  536. return 0;
  537. }
  538. void Entity::getComponents(std::vector<Component*>& result, ShortStringHash type) const
  539. {
  540. result.clear();
  541. for (std::vector<SharedPtr<Component> >::const_iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  542. {
  543. if ((*i)->getType() == type)
  544. result.push_back(*i);
  545. }
  546. }
  547. bool Entity::isPlayback() const
  548. {
  549. if (!mScene)
  550. return false;
  551. return mScene->isPlayback();
  552. }
  553. bool Entity::checkSync(Connection* connection) const
  554. {
  555. if (mNetFlags & NET_SYNCTONONE)
  556. return false;
  557. if (mNetFlags & NET_SYNCTOOWNER)
  558. return mOwner == connection;
  559. return true;
  560. }
  561. bool Entity::checkPrediction(Connection* connection) const
  562. {
  563. if (isOwnerPredicted())
  564. {
  565. // On server need to check the actual owner. On client need only check if owner is non-null
  566. if (isAuthority())
  567. {
  568. if ((mOwner) && (mOwner == connection))
  569. return true;
  570. }
  571. else
  572. {
  573. if (mOwner)
  574. return true;
  575. }
  576. }
  577. if (isTransientPredicted())
  578. return mPredictionTimer > 0.0f;
  579. return false;
  580. }
  581. void Entity::removeComponent(std::vector<SharedPtr<Component> >::iterator i, bool removeAll)
  582. {
  583. (*i)->mEntity = 0;
  584. mComponents.erase(i);
  585. if (!removeAll)
  586. updateEventListeners();
  587. }
  588. void Entity::updateEventListeners()
  589. {
  590. mEventListeners.clear();
  591. for (std::vector<SharedPtr<Component> >::const_iterator i = mComponents.begin(); i != mComponents.end(); ++i)
  592. {
  593. EventListener* listener = dynamic_cast<EventListener*>(i->getPtr());
  594. if (listener)
  595. mEventListeners.push_back(listener);
  596. }
  597. }