BsSceneObject.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Scene/BsSceneObject.h"
  4. #include "Scene/BsComponent.h"
  5. #include "Scene/BsSceneManager.h"
  6. #include "Error/BsException.h"
  7. #include "Debug/BsDebug.h"
  8. #include "RTTI/BsSceneObjectRTTI.h"
  9. #include "Serialization/BsMemorySerializer.h"
  10. #include "Scene/BsGameObjectManager.h"
  11. #include "Scene/BsPrefabUtility.h"
  12. #include "Math/BsMatrix3.h"
  13. #include "BsCoreApplication.h"
  14. namespace bs
  15. {
  16. SceneObject::SceneObject(const String& name, UINT32 flags)
  17. : GameObject(), mPrefabHash(0), mFlags(flags), mCachedLocalTfrm(Matrix4::IDENTITY)
  18. , mCachedWorldTfrm(Matrix4::IDENTITY), mDirtyFlags(0xFFFFFFFF), mDirtyHash(0), mActiveSelf(true)
  19. , mActiveHierarchy(true), mMobility(ObjectMobility::Movable)
  20. {
  21. setName(name);
  22. }
  23. SceneObject::~SceneObject()
  24. {
  25. if(!mThisHandle.isDestroyed())
  26. {
  27. LOGWRN("Object is being deleted without being destroyed first? " + mName);
  28. destroyInternal(mThisHandle, true);
  29. }
  30. }
  31. HSceneObject SceneObject::create(const String& name, UINT32 flags)
  32. {
  33. HSceneObject newObject = createInternal(name, flags);
  34. if (newObject->isInstantiated())
  35. gSceneManager().registerNewSO(newObject);
  36. return newObject;
  37. }
  38. HSceneObject SceneObject::createInternal(const String& name, UINT32 flags)
  39. {
  40. SPtr<SceneObject> sceneObjectPtr = SPtr<SceneObject>(new (bs_alloc<SceneObject>()) SceneObject(name, flags),
  41. &bs_delete<SceneObject>, StdAlloc<SceneObject>());
  42. HSceneObject sceneObject = GameObjectManager::instance().registerObject(sceneObjectPtr);
  43. sceneObject->mThisHandle = sceneObject;
  44. return sceneObject;
  45. }
  46. HSceneObject SceneObject::createInternal(const SPtr<SceneObject>& soPtr, UINT64 originalId)
  47. {
  48. HSceneObject sceneObject = GameObjectManager::instance().registerObject(soPtr, originalId);
  49. sceneObject->mThisHandle = sceneObject;
  50. return sceneObject;
  51. }
  52. void SceneObject::destroy(bool immediate)
  53. {
  54. // Parent is our owner, so when his reference to us is removed, delete might be called.
  55. // So make sure this is the last thing we do.
  56. if(mParent != nullptr)
  57. {
  58. if(!mParent.isDestroyed())
  59. mParent->removeChild(mThisHandle);
  60. mParent = nullptr;
  61. }
  62. destroyInternal(mThisHandle, immediate);
  63. }
  64. void SceneObject::destroyInternal(GameObjectHandleBase& handle, bool immediate)
  65. {
  66. if (immediate)
  67. {
  68. for (auto iter = mChildren.begin(); iter != mChildren.end(); ++iter)
  69. (*iter)->destroyInternal(*iter, true);
  70. mChildren.clear();
  71. // It's important to remove the elements from the array as soon as they're destroyed, as OnDestroy callbacks
  72. // for components might query the SO's components, and we want to only return live ones
  73. while (!mComponents.empty())
  74. {
  75. HComponent component = mComponents.back();
  76. component->_setIsDestroyed();
  77. if (isInstantiated())
  78. gSceneManager()._notifyComponentDestroyed(component);
  79. component->destroyInternal(component, true);
  80. mComponents.erase(mComponents.end() - 1);
  81. }
  82. GameObjectManager::instance().unregisterObject(handle);
  83. }
  84. else
  85. GameObjectManager::instance().queueForDestroy(handle);
  86. }
  87. void SceneObject::_setInstanceData(GameObjectInstanceDataPtr& other)
  88. {
  89. GameObject::_setInstanceData(other);
  90. // Instance data changed, so make sure to refresh the handles to reflect that
  91. SPtr<SceneObject> thisPtr = mThisHandle.getInternalPtr();
  92. mThisHandle._setHandleData(thisPtr);
  93. }
  94. UUID SceneObject::getPrefabLink(bool onlyDirect) const
  95. {
  96. const SceneObject* curObj = this;
  97. while (curObj != nullptr)
  98. {
  99. if (!curObj->mPrefabLinkUUID.empty())
  100. return curObj->mPrefabLinkUUID;
  101. if (curObj->mParent != nullptr && !onlyDirect)
  102. curObj = curObj->mParent.get();
  103. else
  104. curObj = nullptr;
  105. }
  106. return UUID::EMPTY;
  107. }
  108. HSceneObject SceneObject::getPrefabParent() const
  109. {
  110. HSceneObject curObj = mThisHandle;
  111. while (curObj != nullptr)
  112. {
  113. if (!curObj->mPrefabLinkUUID.empty())
  114. return curObj;
  115. if (curObj->mParent != nullptr)
  116. curObj = curObj->mParent;
  117. else
  118. curObj = nullptr;
  119. }
  120. return curObj;
  121. }
  122. void SceneObject::breakPrefabLink()
  123. {
  124. SceneObject* rootObj = this;
  125. while (rootObj != nullptr)
  126. {
  127. if (!rootObj->mPrefabLinkUUID.empty())
  128. break;
  129. if (rootObj->mParent != nullptr)
  130. rootObj = rootObj->mParent.get();
  131. else
  132. rootObj = nullptr;
  133. }
  134. if (rootObj != nullptr)
  135. {
  136. rootObj->mPrefabLinkUUID = UUID::EMPTY;
  137. rootObj->mPrefabDiff = nullptr;
  138. PrefabUtility::clearPrefabIds(rootObj->getHandle(), true, false);
  139. }
  140. }
  141. bool SceneObject::hasFlag(UINT32 flag) const
  142. {
  143. return (mFlags & flag) != 0;
  144. }
  145. void SceneObject::_setFlags(UINT32 flags)
  146. {
  147. mFlags |= flags;
  148. for (auto& child : mChildren)
  149. child->_setFlags(flags);
  150. }
  151. void SceneObject::_unsetFlags(UINT32 flags)
  152. {
  153. mFlags &= ~flags;
  154. for (auto& child : mChildren)
  155. child->_unsetFlags(flags);
  156. }
  157. void SceneObject::_instantiate(bool prefabOnly)
  158. {
  159. std::function<void(SceneObject*)> instantiateRecursive = [&](SceneObject* obj)
  160. {
  161. obj->mFlags &= ~SOF_DontInstantiate;
  162. if (obj->mParent == nullptr)
  163. gSceneManager().registerNewSO(obj->mThisHandle);
  164. for (auto& component : obj->mComponents)
  165. component->_instantiate();
  166. for (auto& child : obj->mChildren)
  167. {
  168. if(!prefabOnly || child->mPrefabLinkUUID.empty())
  169. instantiateRecursive(child.get());
  170. }
  171. };
  172. std::function<void(SceneObject*)> triggerEventsRecursive = [&](SceneObject* obj)
  173. {
  174. for (auto& component : obj->mComponents)
  175. gSceneManager()._notifyComponentCreated(component, obj->getActive());
  176. for (auto& child : obj->mChildren)
  177. {
  178. if (!prefabOnly || child->mPrefabLinkUUID.empty())
  179. triggerEventsRecursive(child.get());
  180. }
  181. };
  182. instantiateRecursive(this);
  183. triggerEventsRecursive(this);
  184. }
  185. /************************************************************************/
  186. /* Transform */
  187. /************************************************************************/
  188. void SceneObject::setPosition(const Vector3& position)
  189. {
  190. if (mMobility == ObjectMobility::Movable)
  191. {
  192. mLocalTfrm.setPosition(position);
  193. notifyTransformChanged(TCF_Transform);
  194. }
  195. }
  196. void SceneObject::setRotation(const Quaternion& rotation)
  197. {
  198. if (mMobility == ObjectMobility::Movable)
  199. {
  200. mLocalTfrm.setRotation(rotation);
  201. notifyTransformChanged(TCF_Transform);
  202. }
  203. }
  204. void SceneObject::setScale(const Vector3& scale)
  205. {
  206. if (mMobility == ObjectMobility::Movable)
  207. {
  208. mLocalTfrm.setScale(scale);
  209. notifyTransformChanged(TCF_Transform);
  210. }
  211. }
  212. void SceneObject::setWorldPosition(const Vector3& position)
  213. {
  214. if(mMobility != ObjectMobility::Movable)
  215. return;
  216. if (mParent != nullptr)
  217. mLocalTfrm.setWorldPosition(position, mParent->getTransform());
  218. else
  219. mLocalTfrm.setPosition(position);
  220. notifyTransformChanged(TCF_Transform);
  221. }
  222. void SceneObject::setWorldRotation(const Quaternion& rotation)
  223. {
  224. if (mMobility != ObjectMobility::Movable)
  225. return;
  226. if (mParent != nullptr)
  227. mLocalTfrm.setWorldRotation(rotation, mParent->getTransform());
  228. else
  229. mLocalTfrm.setRotation(rotation);
  230. notifyTransformChanged(TCF_Transform);
  231. }
  232. void SceneObject::setWorldScale(const Vector3& scale)
  233. {
  234. if (mMobility != ObjectMobility::Movable)
  235. return;
  236. if (mParent != nullptr)
  237. mLocalTfrm.setWorldScale(scale, mParent->getTransform());
  238. else
  239. mLocalTfrm.setScale(scale);
  240. notifyTransformChanged(TCF_Transform);
  241. }
  242. const Transform& SceneObject::getTransform() const
  243. {
  244. if (!isCachedWorldTfrmUpToDate())
  245. updateWorldTfrm();
  246. return mWorldTfrm;
  247. }
  248. void SceneObject::lookAt(const Vector3& location, const Vector3& up)
  249. {
  250. const Transform& worldTfrm = getTransform();
  251. Vector3 forward = location - worldTfrm.getPosition();
  252. Quaternion rotation = worldTfrm.getRotation();
  253. rotation.lookRotation(forward, up);
  254. setWorldRotation(rotation);
  255. }
  256. const Matrix4& SceneObject::getWorldMatrix() const
  257. {
  258. if (!isCachedWorldTfrmUpToDate())
  259. updateWorldTfrm();
  260. return mCachedWorldTfrm;
  261. }
  262. Matrix4 SceneObject::getInvWorldMatrix() const
  263. {
  264. if (!isCachedWorldTfrmUpToDate())
  265. updateWorldTfrm();
  266. Matrix4 worldToLocal = mWorldTfrm.getInvMatrix();
  267. return worldToLocal;
  268. }
  269. const Matrix4& SceneObject::getLocalMatrix() const
  270. {
  271. if (!isCachedLocalTfrmUpToDate())
  272. updateLocalTfrm();
  273. return mCachedLocalTfrm;
  274. }
  275. void SceneObject::move(const Vector3& vec)
  276. {
  277. if (mMobility == ObjectMobility::Movable)
  278. {
  279. mLocalTfrm.move(vec);
  280. notifyTransformChanged(TCF_Transform);
  281. }
  282. }
  283. void SceneObject::moveRelative(const Vector3& vec)
  284. {
  285. if (mMobility == ObjectMobility::Movable)
  286. {
  287. mLocalTfrm.moveRelative(vec);
  288. notifyTransformChanged(TCF_Transform);
  289. }
  290. }
  291. void SceneObject::rotate(const Vector3& axis, const Radian& angle)
  292. {
  293. if (mMobility == ObjectMobility::Movable)
  294. {
  295. mLocalTfrm.rotate(axis, angle);
  296. notifyTransformChanged(TCF_Transform);
  297. }
  298. }
  299. void SceneObject::rotate(const Quaternion& q)
  300. {
  301. if (mMobility == ObjectMobility::Movable)
  302. {
  303. mLocalTfrm.rotate(q);
  304. notifyTransformChanged(TCF_Transform);
  305. }
  306. }
  307. void SceneObject::roll(const Radian& angle)
  308. {
  309. if (mMobility == ObjectMobility::Movable)
  310. {
  311. mLocalTfrm.roll(angle);
  312. notifyTransformChanged(TCF_Transform);
  313. }
  314. }
  315. void SceneObject::yaw(const Radian& angle)
  316. {
  317. if (mMobility == ObjectMobility::Movable)
  318. {
  319. mLocalTfrm.yaw(angle);
  320. notifyTransformChanged(TCF_Transform);
  321. }
  322. }
  323. void SceneObject::pitch(const Radian& angle)
  324. {
  325. if (mMobility == ObjectMobility::Movable)
  326. {
  327. mLocalTfrm.pitch(angle);
  328. notifyTransformChanged(TCF_Transform);
  329. }
  330. }
  331. void SceneObject::setForward(const Vector3& forwardDir)
  332. {
  333. const Transform& worldTfrm = getTransform();
  334. Quaternion currentRotation = worldTfrm.getRotation();
  335. currentRotation.lookRotation(forwardDir);
  336. setWorldRotation(currentRotation);
  337. }
  338. void SceneObject::updateTransformsIfDirty()
  339. {
  340. if (!isCachedLocalTfrmUpToDate())
  341. updateLocalTfrm();
  342. if (!isCachedWorldTfrmUpToDate())
  343. updateWorldTfrm();
  344. }
  345. void SceneObject::notifyTransformChanged(TransformChangedFlags flags) const
  346. {
  347. // If object is immovable, don't send transform changed events nor mark the transform dirty
  348. TransformChangedFlags componentFlags = flags;
  349. if (mMobility != ObjectMobility::Movable)
  350. componentFlags = (TransformChangedFlags)(componentFlags & ~TCF_Transform);
  351. else
  352. {
  353. mDirtyFlags |= DirtyFlags::LocalTfrmDirty | DirtyFlags::WorldTfrmDirty;
  354. mDirtyHash++;
  355. }
  356. // Only send component flags if we haven't removed them all
  357. if (componentFlags != 0)
  358. {
  359. for (auto& entry : mComponents)
  360. {
  361. if (entry->supportsNotify(flags))
  362. {
  363. bool alwaysRun = entry->hasFlag(ComponentFlag::AlwaysRun);
  364. if (alwaysRun || gSceneManager().isRunning())
  365. entry->onTransformChanged(componentFlags);
  366. }
  367. }
  368. }
  369. // Mobility flag is only relevant for this scene object
  370. flags = (TransformChangedFlags)(flags & ~TCF_Mobility);
  371. if (flags != 0)
  372. {
  373. for (auto& entry : mChildren)
  374. entry->notifyTransformChanged(flags);
  375. }
  376. }
  377. void SceneObject::updateWorldTfrm() const
  378. {
  379. mWorldTfrm = mLocalTfrm;
  380. // Don't allow movement from parent when not movable
  381. if (mParent != nullptr && mMobility == ObjectMobility::Movable)
  382. {
  383. mWorldTfrm.makeWorld(mParent->getTransform());
  384. mCachedWorldTfrm = mWorldTfrm.getMatrix();
  385. }
  386. else
  387. {
  388. mCachedWorldTfrm = getLocalMatrix();
  389. }
  390. mDirtyFlags &= ~DirtyFlags::WorldTfrmDirty;
  391. }
  392. void SceneObject::updateLocalTfrm() const
  393. {
  394. mCachedLocalTfrm = mLocalTfrm.getMatrix();
  395. mDirtyFlags &= ~DirtyFlags::LocalTfrmDirty;
  396. }
  397. /************************************************************************/
  398. /* Hierarchy */
  399. /************************************************************************/
  400. void SceneObject::setParent(const HSceneObject& parent, bool keepWorldTransform)
  401. {
  402. if (parent.isDestroyed())
  403. return;
  404. #if BS_EDITOR_BUILD
  405. UUID originalPrefab = getPrefabLink();
  406. #endif
  407. if (mMobility != ObjectMobility::Movable)
  408. keepWorldTransform = true;
  409. _setParent(parent, keepWorldTransform);
  410. #if BS_EDITOR_BUILD
  411. if (gCoreApplication().isEditor())
  412. {
  413. UUID newPrefab = getPrefabLink();
  414. if (originalPrefab != newPrefab)
  415. PrefabUtility::clearPrefabIds(mThisHandle);
  416. }
  417. #endif
  418. }
  419. void SceneObject::_setParent(const HSceneObject& parent, bool keepWorldTransform)
  420. {
  421. if (mThisHandle == parent)
  422. return;
  423. if (mParent == nullptr || mParent != parent)
  424. {
  425. Transform worldTfrm;
  426. // Make sure the object keeps its world coordinates
  427. if (keepWorldTransform)
  428. worldTfrm = getTransform();
  429. if (mParent != nullptr)
  430. mParent->removeChild(mThisHandle);
  431. if (parent != nullptr)
  432. parent->addChild(mThisHandle);
  433. mParent = parent;
  434. if (keepWorldTransform)
  435. {
  436. mLocalTfrm = worldTfrm;
  437. if (mParent != nullptr)
  438. mLocalTfrm.makeLocal(mParent->getTransform());
  439. }
  440. notifyTransformChanged((TransformChangedFlags)(TCF_Parent | TCF_Transform));
  441. }
  442. }
  443. HSceneObject SceneObject::getChild(UINT32 idx) const
  444. {
  445. if(idx >= mChildren.size())
  446. {
  447. BS_EXCEPT(InternalErrorException, "Child index out of range.");
  448. }
  449. return mChildren[idx];
  450. }
  451. int SceneObject::indexOfChild(const HSceneObject& child) const
  452. {
  453. for(int i = 0; i < (int)mChildren.size(); i++)
  454. {
  455. if(mChildren[i] == child)
  456. return i;
  457. }
  458. return -1;
  459. }
  460. void SceneObject::addChild(const HSceneObject& object)
  461. {
  462. mChildren.push_back(object);
  463. object->_setFlags(mFlags);
  464. }
  465. void SceneObject::removeChild(const HSceneObject& object)
  466. {
  467. auto result = find(mChildren.begin(), mChildren.end(), object);
  468. if(result != mChildren.end())
  469. mChildren.erase(result);
  470. else
  471. {
  472. BS_EXCEPT(InternalErrorException,
  473. "Trying to remove a child but it's not a child of the transform.");
  474. }
  475. }
  476. HSceneObject SceneObject::findPath(const String& path) const
  477. {
  478. if (path.empty())
  479. return HSceneObject();
  480. String trimmedPath = path;
  481. StringUtil::trim(trimmedPath, "/");
  482. Vector<String> entries = StringUtil::split(trimmedPath, "/");
  483. // Find scene object referenced by the path
  484. HSceneObject so = getHandle();
  485. UINT32 pathIdx = 0;
  486. for (; pathIdx < (UINT32)entries.size(); pathIdx++)
  487. {
  488. String entry = entries[pathIdx];
  489. if (entry.empty())
  490. continue;
  491. // This character signifies not-a-scene-object. This is allowed to support
  492. // paths used by the scripting system (which can point to properties of
  493. // components on scene objects).
  494. if (entry[0] != '!')
  495. break;
  496. String childName = entry.substr(1, entry.size() - 1);
  497. so = so->findChild(childName);
  498. if (so == nullptr)
  499. break;
  500. }
  501. return so;
  502. }
  503. HSceneObject SceneObject::findChild(const String& name, bool recursive)
  504. {
  505. for (auto& child : mChildren)
  506. {
  507. if (child->getName() == name)
  508. return child;
  509. }
  510. if (recursive)
  511. {
  512. for (auto& child : mChildren)
  513. {
  514. HSceneObject foundObject = child->findChild(name, true);
  515. if (foundObject != nullptr)
  516. return foundObject;
  517. }
  518. }
  519. return HSceneObject();
  520. }
  521. Vector<HSceneObject> SceneObject::findChildren(const String& name, bool recursive)
  522. {
  523. std::function<void(const HSceneObject&, Vector<HSceneObject>&)> findChildrenInternal =
  524. [&](const HSceneObject& so, Vector<HSceneObject>& output)
  525. {
  526. for (auto& child : so->mChildren)
  527. {
  528. if (child->getName() == name)
  529. output.push_back(child);
  530. }
  531. if (recursive)
  532. {
  533. for (auto& child : so->mChildren)
  534. findChildrenInternal(child, output);
  535. }
  536. };
  537. Vector<HSceneObject> output;
  538. findChildrenInternal(mThisHandle, output);
  539. return output;
  540. }
  541. void SceneObject::setActive(bool active)
  542. {
  543. mActiveSelf = active;
  544. setActiveHierarchy(active);
  545. }
  546. void SceneObject::setActiveHierarchy(bool active, bool triggerEvents)
  547. {
  548. bool activeHierarchy = active && mActiveSelf;
  549. if (mActiveHierarchy != activeHierarchy)
  550. {
  551. mActiveHierarchy = activeHierarchy;
  552. if (triggerEvents)
  553. {
  554. if (activeHierarchy)
  555. {
  556. for (auto& component : mComponents)
  557. gSceneManager()._notifyComponentActivated(component, triggerEvents);
  558. }
  559. else
  560. {
  561. for (auto& component : mComponents)
  562. gSceneManager()._notifyComponentDeactivated(component, triggerEvents);
  563. }
  564. }
  565. }
  566. for (auto child : mChildren)
  567. {
  568. child->setActiveHierarchy(mActiveHierarchy, triggerEvents);
  569. }
  570. }
  571. bool SceneObject::getActive(bool self) const
  572. {
  573. if (self)
  574. return mActiveSelf;
  575. else
  576. return mActiveHierarchy;
  577. }
  578. void SceneObject::setMobility(ObjectMobility mobility)
  579. {
  580. if(mMobility != mobility)
  581. {
  582. mMobility = mobility;
  583. // If mobility changed to movable, update both the mobility flag and transform, otherwise just mobility
  584. if (mMobility == ObjectMobility::Movable)
  585. notifyTransformChanged((TransformChangedFlags)(TCF_Transform | TCF_Mobility));
  586. else
  587. notifyTransformChanged(TCF_Mobility);
  588. }
  589. }
  590. HSceneObject SceneObject::clone(bool instantiate)
  591. {
  592. bool isInstantiated = !hasFlag(SOF_DontInstantiate);
  593. if (!instantiate)
  594. _setFlags(SOF_DontInstantiate);
  595. else
  596. _unsetFlags(SOF_DontInstantiate);
  597. UINT32 bufferSize = 0;
  598. MemorySerializer serializer;
  599. UINT8* buffer = serializer.encode(this, bufferSize, (void*(*)(UINT32))&bs_alloc);
  600. GameObjectManager::instance().setDeserializationMode(GODM_UseNewIds | GODM_RestoreExternal);
  601. SPtr<SceneObject> cloneObj = std::static_pointer_cast<SceneObject>(serializer.decode(buffer, bufferSize));
  602. bs_free(buffer);
  603. if(isInstantiated)
  604. _unsetFlags(SOF_DontInstantiate);
  605. else
  606. _setFlags(SOF_DontInstantiate);
  607. return cloneObj->mThisHandle;
  608. }
  609. HComponent SceneObject::getComponent(RTTITypeBase* type) const
  610. {
  611. for(auto& entry : mComponents)
  612. {
  613. if(entry->getRTTI()->isDerivedFrom(type))
  614. return entry;
  615. }
  616. return HComponent();
  617. }
  618. void SceneObject::destroyComponent(const HComponent component, bool immediate)
  619. {
  620. if(component == nullptr)
  621. {
  622. LOGDBG("Trying to remove a null component");
  623. return;
  624. }
  625. auto iter = std::find(mComponents.begin(), mComponents.end(), component);
  626. if(iter != mComponents.end())
  627. {
  628. (*iter)->_setIsDestroyed();
  629. if (isInstantiated())
  630. gSceneManager()._notifyComponentDestroyed(*iter);
  631. (*iter)->destroyInternal(*iter, immediate);
  632. mComponents.erase(iter);
  633. }
  634. else
  635. LOGDBG("Trying to remove a component that doesn't exist on this SceneObject.");
  636. }
  637. void SceneObject::destroyComponent(Component* component, bool immediate)
  638. {
  639. auto iterFind = std::find_if(mComponents.begin(), mComponents.end(),
  640. [component](const HComponent& x)
  641. {
  642. if(x.isDestroyed())
  643. return false;
  644. return x._getHandleData()->mPtr->object.get() == component; }
  645. );
  646. if(iterFind != mComponents.end())
  647. {
  648. destroyComponent(*iterFind, immediate);
  649. }
  650. }
  651. HComponent SceneObject::addComponent(UINT32 typeId)
  652. {
  653. SPtr<IReflectable> newObj = rtti_create(typeId);
  654. if(!rtti_is_subclass<Component>(newObj.get()))
  655. {
  656. LOGERR("Specified type is not a valid Component.");
  657. return HComponent();
  658. }
  659. SPtr<Component> componentPtr = std::static_pointer_cast<Component>(newObj);
  660. HComponent newComponent = GameObjectManager::instance().registerObject(componentPtr);
  661. newComponent->mParent = mThisHandle;
  662. addAndInitializeComponent(newComponent);
  663. return newComponent;
  664. }
  665. void SceneObject::addComponentInternal(const SPtr<Component> component)
  666. {
  667. GameObjectHandle<Component> newComponent = GameObjectManager::instance().getObject(component->getInstanceId());
  668. newComponent->mParent = mThisHandle;
  669. newComponent->mThisHandle = newComponent;
  670. mComponents.push_back(newComponent);
  671. }
  672. void SceneObject::addAndInitializeComponent(const HComponent& component)
  673. {
  674. component->mThisHandle = component;
  675. mComponents.push_back(component);
  676. if (isInstantiated())
  677. {
  678. component->_instantiate();
  679. gSceneManager()._notifyComponentCreated(component, getActive());
  680. }
  681. }
  682. void SceneObject::addAndInitializeComponent(const SPtr<Component> component)
  683. {
  684. GameObjectHandle<Component> newComponent = GameObjectManager::instance().getObject(component->getInstanceId());
  685. newComponent->mParent = mThisHandle;
  686. addAndInitializeComponent(newComponent);
  687. }
  688. RTTITypeBase* SceneObject::getRTTIStatic()
  689. {
  690. return SceneObjectRTTI::instance();
  691. }
  692. RTTITypeBase* SceneObject::getRTTI() const
  693. {
  694. return SceneObject::getRTTIStatic();
  695. }
  696. }