BsSceneObject.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. #pragma once
  2. #include "BsCorePrerequisites.h"
  3. #include "BsMatrix4.h"
  4. #include "BsVector3.h"
  5. #include "BsQuaternion.h"
  6. #include "BsRTTIType.h"
  7. #include "BsCoreSceneManager.h"
  8. #include "BsGameObjectManager.h"
  9. #include "BsGameObject.h"
  10. #include "BsComponent.h"
  11. namespace BansheeEngine
  12. {
  13. /**
  14. * @brief Possible modifiers that can be applied to a SceneObject
  15. */
  16. enum SceneObjectFlags
  17. {
  18. SOF_DontInstantiate = 0x01, /**< Object wont be in the main scene and its components won't receive updates. */
  19. SOF_DontSave = 0x02, /**< Object will be skipped when saving the scene hierarchy or a prefab. */
  20. SOF_Persistent = 0x04, /**< Object will remain in the scene even after scene clear, unless destroyed directly.
  21. This only works with top-level objects. */
  22. SOF_Internal = 0x08 /**< Provides a hint to external systems that his object is used by engine internals.
  23. For example, those systems might not want to display those objects together with the
  24. user created ones. */
  25. };
  26. /**
  27. * @brief SceneObject represents an object in the scene graph. It has a world position,
  28. * place in the hierarchy and optionally a number of attached components.
  29. */
  30. class BS_CORE_EXPORT SceneObject : public GameObject
  31. {
  32. /**
  33. * @brief Flags that signify which part of the SceneObject needs updating.
  34. */
  35. enum DirtyFlags
  36. {
  37. LocalTfrmDirty = 0x01,
  38. WorldTfrmDirty = 0x02
  39. };
  40. friend class CoreSceneManager;
  41. friend class Prefab;
  42. friend class PrefabDiff;
  43. friend class PrefabUtility;
  44. public:
  45. ~SceneObject();
  46. /**
  47. * @brief Creates a new SceneObject with the specified name. Object will be placed in the top
  48. * of the scene hierarchy.
  49. */
  50. static HSceneObject create(const String& name, UINT32 flags = 0);
  51. /**
  52. * @brief Destroys this object and any of its held components.
  53. *
  54. * @param [in] immediate If true, the object will be deallocated and become unusable
  55. * right away. Otherwise the deallocation will be delayed to the end of
  56. * frame (preferred method).
  57. */
  58. void destroy(bool immediate = false);
  59. /**
  60. * @copydoc GameObject::_setInstanceData
  61. */
  62. void _setInstanceData(GameObjectInstanceDataPtr& other) override;
  63. /**
  64. * @brief Returns a handle to this object.
  65. */
  66. HSceneObject getHandle() const { return mThisHandle; }
  67. /**
  68. * @brief Returns the UUID of the prefab this object is linked to, if any.
  69. *
  70. * @note Requires a search of all parents potentially.
  71. */
  72. String getPrefabLink() const;
  73. /**
  74. * @brief Breaks the link between this prefab instance and its prefab.
  75. */
  76. void breakPrefabLink();
  77. /**
  78. * @brief Checks if the scene object has a specific bit flag set.
  79. */
  80. bool hasFlag(UINT32 flag) const;
  81. private:
  82. SceneObject(const String& name, UINT32 flags);
  83. /**
  84. * @brief Creates a new SceneObject instance, registers it with the game object manager,
  85. * creates and returns a handle to the new object.
  86. *
  87. * @note When creating objects with DontInstantiate flag it is the callers responsibility
  88. * to manually destroy the object, otherwise it will leak.
  89. */
  90. static HSceneObject createInternal(const String& name, UINT32 flags = 0);
  91. /**
  92. * @brief Destroys this object and any of its held components.
  93. *
  94. * @param [in] immediate If true, the object will be deallocated and become unusable
  95. * right away. Otherwise the deallocation will be delayed to the end of
  96. * frame (preferred method).
  97. *
  98. * @note Unlike "destroy", does not remove the object from its parent.
  99. */
  100. void destroyInternal(bool immediate = false);
  101. /**
  102. * @brief Recursively enables the provided set of flags on
  103. * this object and all children.
  104. */
  105. void setFlags(UINT32 flags);
  106. /**
  107. * @brief Recursively disables the provided set of flags on
  108. * this object and all children.
  109. */
  110. void unsetFlags(UINT32 flags);
  111. /**
  112. * @brief Checks is the scene object instantiated and visible in the scene.
  113. */
  114. bool isInstantiated() const { return (mFlags & SOF_DontInstantiate) == 0; }
  115. /**
  116. * @brief Register the scene object with the scene and activate all of its components.
  117. */
  118. void instantiate();
  119. private:
  120. HSceneObject mThisHandle;
  121. String mPrefabLinkUUID;
  122. PrefabDiffPtr mPrefabDiff;
  123. UINT32 mPrefabHash;
  124. UINT32 mFlags;
  125. /************************************************************************/
  126. /* Transform */
  127. /************************************************************************/
  128. public:
  129. /**
  130. * @brief Sets the local position of the object.
  131. */
  132. void setPosition(const Vector3& position);
  133. /**
  134. * @brief Gets the local position of the object.
  135. */
  136. const Vector3& getPosition() const { return mPosition; }
  137. /**
  138. * @brief Sets the world position of the object.
  139. */
  140. void setWorldPosition(const Vector3& position);
  141. /**
  142. * @brief Gets the world position of the object.
  143. *
  144. * @note Performance warning: This might involve updating the transforms if the transform is dirty.
  145. */
  146. const Vector3& getWorldPosition() const;
  147. /**
  148. * @brief Sets the local rotation of the object.
  149. */
  150. void setRotation(const Quaternion& rotation);
  151. /**
  152. * @brief Gets the local rotation of the object.
  153. */
  154. const Quaternion& getRotation() const { return mRotation; }
  155. /**
  156. * @brief Sets the world rotation of the object.
  157. */
  158. void setWorldRotation(const Quaternion& rotation);
  159. /**
  160. * @brief Gets world rotation of the object.
  161. *
  162. * @note Performance warning: This might involve updating the transforms if the transform is dirty.
  163. */
  164. const Quaternion& getWorldRotation() const;
  165. /**
  166. * @brief Sets the local scale of the object.
  167. */
  168. void setScale(const Vector3& scale);
  169. /**
  170. * @brief Gets the local scale of the object.
  171. */
  172. const Vector3& getScale() const { return mScale; }
  173. /**
  174. * @brief Sets the world scale of the object.
  175. *
  176. * @note This will not work properly if this object or any of its parents
  177. * have non-affine transform matrices.
  178. */
  179. void setWorldScale(const Vector3& scale);
  180. /**
  181. * @brief Gets world scale of the object.
  182. *
  183. * @note Performance warning: This might involve updating the transforms if the transform is dirty.
  184. */
  185. const Vector3& getWorldScale() const;
  186. /**
  187. * @brief Orients the object so it is looking at the provided "location" (local space)
  188. * where "up" is used for determining the location of the objects Y axis.
  189. *
  190. */
  191. void lookAt(const Vector3& location, const Vector3& up = Vector3::UNIT_Y);
  192. /**
  193. * @brief Gets the objects world transform matrix.
  194. *
  195. * @note Performance warning: This might involve updating the transforms if the transform is dirty.
  196. */
  197. const Matrix4& getWorldTfrm() const;
  198. /**
  199. * @brief Gets the objects local transform matrix.
  200. */
  201. const Matrix4& getLocalTfrm() const;
  202. /**
  203. * @brief Moves the object's position by the vector offset provided along world axes.
  204. */
  205. void move(const Vector3& vec);
  206. /**
  207. * @brief Moves the object's position by the vector offset provided along it's own axes (relative to orientation).
  208. */
  209. void moveRelative(const Vector3& vec);
  210. /**
  211. * @brief Gets the Z (forward) axis of the object, in world space.
  212. *
  213. * @return Forward axis of the object.
  214. */
  215. Vector3 getForward() const { return getWorldRotation().rotate(-Vector3::UNIT_Z); }
  216. /**
  217. * @brief Gets the Y (up) axis of the object, in world space.
  218. *
  219. * @return Up axis of the object.
  220. */
  221. Vector3 getUp() const { return getWorldRotation().rotate(Vector3::UNIT_Y); }
  222. /**
  223. * @brief Gets the X (right) axis of the object, in world space.
  224. *
  225. * @return Right axis of the object.
  226. */
  227. Vector3 getRight() const { return getWorldRotation().rotate(Vector3::UNIT_X); }
  228. /**
  229. * @brief Rotates the game object so it's forward axis faces the provided
  230. * direction.
  231. *
  232. * @note Local forward axis is considered to be negative Z.
  233. *
  234. * @param forwardDir The forward direction to face, in world space.
  235. */
  236. void setForward(const Vector3& forwardDir);
  237. /**
  238. * @brief Rotate the object around an arbitrary axis.
  239. */
  240. void rotate(const Vector3& axis, const Radian& angle);
  241. /**
  242. * @brief Rotate the object around an arbitrary axis using a Quaternion.
  243. */
  244. void rotate(const Quaternion& q);
  245. /**
  246. * @brief Rotates around local Z axis.
  247. *
  248. * @param angle Angle to rotate by.
  249. */
  250. void roll(const Radian& angle);
  251. /**
  252. * @brief Rotates around Y axis.
  253. *
  254. * @param angle Angle to rotate by.
  255. */
  256. void yaw(const Radian& angle);
  257. /**
  258. * @brief Rotates around X axis
  259. *
  260. * @param angle Angle to rotate by.
  261. */
  262. void pitch(const Radian& angle);
  263. /**
  264. * @brief Forces any dirty transform matrices on this object to be updated.
  265. *
  266. * @note Normally this is done internally when retrieving a transform, but sometimes
  267. * it is useful to update transforms manually.
  268. */
  269. void updateTransformsIfDirty();
  270. /**
  271. * @brief Returns a hash value that changes whenever a scene objects
  272. * transform gets updated. It allows you to detect changes with
  273. * the local or world transforms without directly comparing their
  274. * values with some older state.
  275. */
  276. UINT32 getTransformHash() const { return mDirtyHash; }
  277. private:
  278. Vector3 mPosition;
  279. Quaternion mRotation;
  280. Vector3 mScale;
  281. mutable Vector3 mWorldPosition;
  282. mutable Quaternion mWorldRotation;
  283. mutable Vector3 mWorldScale;
  284. mutable Matrix4 mCachedLocalTfrm;
  285. mutable Matrix4 mCachedWorldTfrm;
  286. mutable UINT32 mDirtyFlags;
  287. mutable UINT32 mDirtyHash;
  288. /**
  289. * @brief Marks the transform as dirty so that we know to update
  290. * it when the transform is requested.
  291. */
  292. void markTfrmDirty() const;
  293. /**
  294. * @brief Updates the local transform. Normally just reconstructs the
  295. * transform matrix from the position/rotation/scale.
  296. */
  297. void updateLocalTfrm() const;
  298. /**
  299. * @brief Updates the world transform. Reconstructs the local transform
  300. * matrix and multiplies it with any parent transforms.
  301. *
  302. * @note If parent transforms are dirty they will be updated.
  303. */
  304. void updateWorldTfrm() const;
  305. /**
  306. * @brief Checks if cached local transform needs updating.
  307. */
  308. bool isCachedLocalTfrmUpToDate() const { return (mDirtyFlags & DirtyFlags::LocalTfrmDirty) == 0; }
  309. /**
  310. * @brief Checks if cached world transform needs updating.
  311. */
  312. bool isCachedWorldTfrmUpToDate() const { return (mDirtyFlags & DirtyFlags::WorldTfrmDirty) == 0; }
  313. /************************************************************************/
  314. /* Hierarchy */
  315. /************************************************************************/
  316. public:
  317. /**
  318. * @brief Changes the parent of this object. Also removes the object from the current parent,
  319. * and assigns it to the new parent.
  320. *
  321. * @param [in] parent New parent.
  322. */
  323. void setParent(const HSceneObject& parent);
  324. /**
  325. * @brief Gets the parent of this object.
  326. *
  327. * @return Parent object, or nullptr if this SceneObject is at root level.
  328. */
  329. HSceneObject getParent() const { return mParent; }
  330. /**
  331. * @brief Gets a child of this item.
  332. *
  333. * @param idx The zero based index of the child.
  334. *
  335. * @return SceneObject of the child.
  336. */
  337. HSceneObject getChild(UINT32 idx) const;
  338. /**
  339. * @brief Find the index of the specified child. Don't persist this value as
  340. * it may change whenever you add/remove children.
  341. *
  342. * @param child The child to look for.
  343. *
  344. * @return The zero-based index of the found child, or -1 if no match was found.
  345. */
  346. int indexOfChild(const HSceneObject& child) const;
  347. /**
  348. * @brief Gets the number of all child GameObjects.
  349. */
  350. UINT32 getNumChildren() const { return (UINT32)mChildren.size(); }
  351. /**
  352. * @brief Enables or disables this object. Disabled objects also implicitly disable
  353. * all their child objects. No components on the disabled object are updated.
  354. */
  355. void setActive(bool active);
  356. /**
  357. * @brief Returns whether or not an object is active.
  358. *
  359. * @param self If true, the method will only check if this particular object was activated
  360. * or deactivated directly via setActive. If false we we also check if any of
  361. * the objects parents are inactive.
  362. */
  363. bool getActive(bool self = false);
  364. /**
  365. * @brief Makes a deep copy of this object.
  366. */
  367. HSceneObject clone();
  368. private:
  369. HSceneObject mParent;
  370. Vector<HSceneObject> mChildren;
  371. bool mActiveSelf;
  372. bool mActiveHierarchy;
  373. /**
  374. * @brief Adds a child to the child array. This method doesn't check for null or duplicate values.
  375. *
  376. * @param [in] object New child.
  377. */
  378. void addChild(const HSceneObject& object);
  379. /**
  380. * @brief Removes the child from the object.
  381. *
  382. * @param [in] object Child to remove.
  383. *
  384. * @throws INTERNAL_ERROR If the provided child isn't a child of the current object.
  385. */
  386. void removeChild(const HSceneObject& object);
  387. /**
  388. * @brief Changes the object active in hierarchy state.
  389. */
  390. void setActiveHierarchy(bool active);
  391. /************************************************************************/
  392. /* Component */
  393. /************************************************************************/
  394. public:
  395. /**
  396. * @brief Constructs a new component of the specified type and adds it to
  397. * the internal component list.
  398. */
  399. template<class T, class... Args>
  400. GameObjectHandle<T> addComponent(Args &&... args)
  401. {
  402. static_assert((std::is_base_of<BansheeEngine::Component, T>::value),
  403. "Specified type is not a valid Component.");
  404. std::shared_ptr<T> gameObject(new (bs_alloc<T, PoolAlloc>()) T(mThisHandle,
  405. std::forward<Args>(args)...),
  406. &bs_delete<PoolAlloc, T>, StdAlloc<T, PoolAlloc>());
  407. GameObjectHandle<T> newComponent =
  408. GameObjectHandle<T>(GameObjectManager::instance().registerObject(gameObject));
  409. mComponents.push_back(newComponent);
  410. if (isInstantiated())
  411. newComponent->onInitialized();
  412. return newComponent;
  413. }
  414. /**
  415. * @brief Searches for a component with the specific type and returns the first one
  416. * it finds.
  417. *
  418. * @note Don't call this too often as it is relatively slow. It is more efficient
  419. * to call it once and store the result for further use.
  420. *
  421. * @tparam typename T Type of the component.
  422. *
  423. * @return Component if found, nullptr otherwise.
  424. */
  425. template <typename T>
  426. GameObjectHandle<T> getComponent()
  427. {
  428. static_assert((std::is_base_of<BansheeEngine::Component, T>::value),
  429. "Specified type is not a valid Component.");
  430. return static_object_cast<T>(getComponent(T::getRTTIStatic()->getRTTIId()));
  431. }
  432. /**
  433. * @brief Checks if the current object contains the specified component
  434. *
  435. * @note Don't call this too often as it is relatively slow.
  436. *
  437. * @tparam typename T Type of the component.
  438. *
  439. * @return True if component exists on the object.
  440. */
  441. template <typename T>
  442. bool hasComponent()
  443. {
  444. static_assert((std::is_base_of<BansheeEngine::Component, T>::value),
  445. "Specified type is not a valid Component.");
  446. for (auto iter = mComponents.begin(); iter != mComponents.end(); ++iter)
  447. {
  448. if ((*iter)->getRTTI()->getRTTIId() == T::getRTTIStatic()->getRTTIId())
  449. return true;
  450. }
  451. return false;
  452. }
  453. /**
  454. * @brief Searches for a component with the specified type id and returns the first one it
  455. * finds.
  456. *
  457. * @note Don't call this too often as it is relatively slow. It is more efficient to
  458. * call it once and store the result for further use.
  459. *
  460. * @param typeId Identifier for the type.
  461. *
  462. * @return Component if found, nullptr otherwise.
  463. */
  464. HComponent getComponent(UINT32 typeId) const;
  465. /**
  466. * @brief Removes the component from this object, and deallocates it.
  467. *
  468. * @param [in] component The component to destroy.
  469. * @param [in] immediate If true, the component will be deallocated and become unusable
  470. * right away. Otherwise the deallocation will be delayed to the end of
  471. * frame (preferred method).
  472. */
  473. void destroyComponent(const HComponent component, bool immediate = false);
  474. /**
  475. * @brief Removes the component from this object, and deallocates it.
  476. *
  477. * @param [in] component The component to destroy.
  478. * @param [in] immediate If true, the component will be deallocated and become unusable
  479. * right away. Otherwise the deallocation will be delayed to the end of
  480. * frame (preferred method).
  481. */
  482. void destroyComponent(Component* component, bool immediate = false);
  483. /**
  484. * @brief Returns all components on this object.
  485. */
  486. const Vector<HComponent>& getComponents() const { return mComponents; }
  487. private:
  488. /**
  489. * @brief Creates an empty component with the default constructor.
  490. */
  491. template <typename T>
  492. static std::shared_ptr<T> createEmptyComponent()
  493. {
  494. static_assert((std::is_base_of<BansheeEngine::Component, T>::value), "Specified type is not a valid Component.");
  495. std::shared_ptr<T> gameObject(new (bs_alloc<T, PoolAlloc>()) T(), &bs_delete<PoolAlloc, T>, StdAlloc<T, PoolAlloc>());
  496. GameObjectHandle<T>(GameObjectManager::instance().registerObject(gameObject));
  497. return gameObject;
  498. }
  499. /**
  500. * @brief Adds the component to the internal component array.
  501. */
  502. void addComponentInternal(const std::shared_ptr<Component> component);
  503. Vector<HComponent> mComponents;
  504. /************************************************************************/
  505. /* RTTI */
  506. /************************************************************************/
  507. public:
  508. friend class GameObjectRTTI;
  509. friend class SceneObjectRTTI;
  510. static RTTITypeBase* getRTTIStatic();
  511. virtual RTTITypeBase* getRTTI() const;
  512. };
  513. }