CmSceneObject.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. #pragma once
  2. #include "CmPrerequisites.h"
  3. #include "CmMatrix4.h"
  4. #include "CmVector3.h"
  5. #include "CmQuaternion.h"
  6. #include "CmRTTIType.h"
  7. #include "CmSceneManager.h"
  8. #include "CmGameObjectManager.h"
  9. #include "CmGameObject.h"
  10. #include "boost/static_assert.hpp"
  11. namespace CamelotFramework
  12. {
  13. class CM_EXPORT SceneObject : public GameObject
  14. {
  15. friend class SceneManager;
  16. public:
  17. ~SceneObject();
  18. static HSceneObject create(const String& name);
  19. void destroy();
  20. UINT32 getId() const { return mId; }
  21. const String& getName() const { return mName; }
  22. void setName(const String& name) { mName = name; }
  23. private:
  24. HSceneObject mThisHandle;
  25. SceneObject(const String& name, UINT32 id);
  26. static HSceneObject createInternal(const String& name);
  27. void destroyInternal();
  28. /************************************************************************/
  29. /* Transform */
  30. /************************************************************************/
  31. public:
  32. void setPosition(const Vector3& position);
  33. const Vector3& getPosition() const { return mPosition; }
  34. const Vector3& getWorldPosition() const;
  35. void setRotation(const Quaternion& rotation);
  36. const Quaternion& getRotation() const { return mRotation; }
  37. const Quaternion& getWorldRotation() const;
  38. void setScale(const Vector3& scale);
  39. const Vector3& getScale() const { return mScale; }
  40. const Vector3& getWorldScale() const;
  41. void lookAt(const Vector3& location, const Vector3& up = Vector3::UNIT_Y);
  42. const Matrix4& getWorldTfrm() const;
  43. const Matrix4& getLocalTfrm() const;
  44. /** Moves the object's position by the vector offset provided along world axes.
  45. */
  46. void move(const Vector3& vec);
  47. /** Moves the object's position by the vector offset provided along it's own axes (relative to orientation).
  48. */
  49. void moveRelative(const Vector3& vec);
  50. /**
  51. * @brief Gets the Z (forward) axis of the object, in world space.
  52. *
  53. * @return Forward axis of the object.
  54. */
  55. Vector3 getForward() const { return getWorldRotation().rotate(-Vector3::UNIT_Z); }
  56. /**
  57. * @brief Gets the Y (up) axis of the object, in world space.
  58. *
  59. * @return Up axis of the object.
  60. */
  61. Vector3 getUp() const { return getWorldRotation().rotate(Vector3::UNIT_Y); }
  62. /**
  63. * @brief Gets the X (right) axis of the object, in world space.
  64. *
  65. * @return Right axis of the object.
  66. */
  67. Vector3 getRight() const { return getWorldRotation().rotate(Vector3::UNIT_X); }
  68. /**
  69. * @brief Rotates the game object so it's forward axis faces the provided
  70. * direction.
  71. *
  72. * @note Local forward axis is considered to be negative Z.
  73. *
  74. * @param forwardDir The forward direction to face, in world space.
  75. */
  76. void setForward(const Vector3& forwardDir);
  77. /** Rotate the object around an arbitrary axis.
  78. */
  79. void rotate(const Vector3& axis, const Radian& angle);
  80. /** Rotate the object around an arbitrary axis using a Quaternion.
  81. */
  82. void rotate(const Quaternion& q);
  83. /**
  84. * @brief Rotates around local Z axis.
  85. *
  86. * @param angle Angle to rotate by.
  87. */
  88. void roll(const Radian& angle);
  89. /**
  90. * @brief Rotates around Y axis.
  91. *
  92. * @param angle Angle to rotate by.
  93. */
  94. void yaw(const Radian& angle);
  95. /**
  96. * @brief Rotates around X axis
  97. *
  98. * @param angle Angle to rotate by.
  99. */
  100. void pitch(const Radian& angle);
  101. private:
  102. static UINT32 NextFreeId;
  103. String mName;
  104. UINT32 mId;
  105. Vector3 mPosition;
  106. Quaternion mRotation;
  107. Vector3 mScale;
  108. mutable Vector3 mWorldPosition;
  109. mutable Quaternion mWorldRotation;
  110. mutable Vector3 mWorldScale;
  111. mutable Matrix4 mCachedLocalTfrm;
  112. mutable bool mIsCachedLocalTfrmUpToDate;
  113. mutable Matrix4 mCachedWorldTfrm;
  114. mutable bool mIsCachedWorldTfrmUpToDate;
  115. Matrix4 mCustomWorldTfrm; // TODO
  116. bool mIsCustomTfrmModeActive; // TODO
  117. void markTfrmDirty() const;
  118. void updateLocalTfrm() const;
  119. void updateWorldTfrm() const;
  120. /************************************************************************/
  121. /* Hierarchy */
  122. /************************************************************************/
  123. public:
  124. /**
  125. * @brief Changes the parent of this object. Also removes the object from the current parent,
  126. * and assigns it to the new parent.
  127. *
  128. * @param [in] parent New parent.
  129. */
  130. void setParent(const HSceneObject& parent);
  131. /**
  132. * @brief Gets the parent of this object.
  133. *
  134. * @return Parent object, or nullptr if this SceneObject is at root level.
  135. */
  136. HSceneObject getParent() const { return mParent; }
  137. /**
  138. * @brief Gets a child of this item.
  139. *
  140. * @param idx The zero based index of the child.
  141. *
  142. * @return SceneObject of the child.
  143. *
  144. * @throws ERR_INVALIDPARAMS If the index is out of range.
  145. */
  146. HSceneObject getChild(unsigned int idx) const;
  147. /**
  148. * @brief Find the index of the specified child. Don't persist this value as
  149. * it may change whenever you add/remove children.
  150. *
  151. * @param child The child to look for.
  152. *
  153. * @return The zero-based index of the found child, or -1 if no match was found.
  154. */
  155. int indexOfChild(const HSceneObject& child) const;
  156. /**
  157. * @brief Gets the number of all child GameObjects.
  158. */
  159. UINT32 getNumChildren() const { return (UINT32)mChildren.size(); }
  160. /**
  161. * @brief Makes a deep copy of this object.
  162. */
  163. HSceneObject clone();
  164. private:
  165. HSceneObject mParent;
  166. Vector<HSceneObject>::type mChildren;
  167. /**
  168. * @brief Adds a child to the child array. This method doesn't check for null or duplicate values.
  169. *
  170. * @param [in] object New child.
  171. */
  172. void addChild(const HSceneObject& object);
  173. /**
  174. * @brief Removes the child from the object.
  175. *
  176. * @param [in] object Child to remove.
  177. *
  178. * @throws INTERNAL_ERROR If the provided child isn't a child of the current object.
  179. */
  180. void removeChild(const HSceneObject& object);
  181. /************************************************************************/
  182. /* Component */
  183. /************************************************************************/
  184. public:
  185. template <typename T>
  186. GameObjectHandle<T> addComponent()
  187. {
  188. BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotFramework::Component, T>::value), "Specified type is not a valid Component.");
  189. std::shared_ptr<T> gameObject(new (cm_alloc<T, PoolAlloc>()) T(mThisHandle), &cm_delete<PoolAlloc, T>, StdAlloc<PoolAlloc>());
  190. GameObjectHandle<T> newComponent = GameObjectHandle<T>(GameObjectManager::instance().registerObject(gameObject));
  191. mComponents.push_back(newComponent);
  192. gSceneManager().notifyComponentAdded(newComponent);
  193. return newComponent;
  194. }
  195. // addComponent that accepts an arbitrary number of parameters > 0
  196. #define MAKE_ADD_COMPONENT(z, n, unused) \
  197. template<class Type BOOST_PP_ENUM_TRAILING_PARAMS(n, class T)> \
  198. GameObjectHandle<Type> addComponent(BOOST_PP_ENUM_BINARY_PARAMS(n, T, &&t) ) \
  199. { \
  200. BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotFramework::Component, Type>::value), \
  201. "Specified type is not a valid Component."); \
  202. \
  203. std::shared_ptr<Type> gameObject(new (cm_alloc<Type, PoolAlloc>()) Type(mThisHandle, \
  204. std::forward<T0>(t0) BOOST_PP_REPEAT_FROM_TO(1, n, FORWARD_T, ~)), \
  205. &cm_delete<PoolAlloc, Type>, StdAlloc<PoolAlloc>()); \
  206. \
  207. GameObjectHandle<Type> newComponent = \
  208. GameObjectHandle<Type>(GameObjectManager::instance().registerObject(gameObject)); \
  209. \
  210. mComponents.push_back(newComponent); \
  211. \
  212. gSceneManager().notifyComponentAdded(newComponent); \
  213. \
  214. return newComponent; \
  215. }
  216. #define FORWARD_T(z, i, unused) \
  217. , std::forward<BOOST_PP_CAT(T, i)>(BOOST_PP_CAT(t, i))
  218. BOOST_PP_REPEAT_FROM_TO(1, 15, MAKE_ADD_COMPONENT, ~)
  219. #undef FORWARD_T
  220. #undef MAKE_ADD_COMPONENT
  221. /**
  222. * @brief Searches for a component with the specific type and returns the first one
  223. * it finds.
  224. *
  225. * @note Don't call this too often as it is relatively slow. It is more efficient
  226. * to call it once and store the result for further use.
  227. *
  228. * @tparam typename T Type of the component.
  229. *
  230. * @return Component if found, nullptr otherwise.
  231. */
  232. template <typename T>
  233. GameObjectHandle<T> getComponent()
  234. {
  235. BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotFramework::Component, T>::value),
  236. "Specified type is not a valid Component.");
  237. return static_object_cast<T>(getComponent(T::getRTTIStatic()->getRTTIId()));
  238. }
  239. /**
  240. * @brief Checks if the current object contains the specified component
  241. *
  242. * @note Don't call this too often as it is relatively slow.
  243. *
  244. * @tparam typename T Type of the component.
  245. *
  246. * @return True if component exists on the object.
  247. */
  248. template <typename T>
  249. bool hasComponent()
  250. {
  251. BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotFramework::Component, T>::value),
  252. "Specified type is not a valid Component.");
  253. return hasComponent(T::getRTTIStatic()->getRTTIId());
  254. }
  255. /**
  256. * @brief Searches for a component with the specified type id and returns the first one it
  257. * finds.
  258. *
  259. * @note Don't call this too often as it is relatively slow. It is more efficient to
  260. * call it once and store the result for further use.
  261. *
  262. * @param typeId Identifier for the type.
  263. *
  264. * @return Component if found, nullptr otherwise.
  265. */
  266. HComponent getComponent(UINT32 typeId) const;
  267. /**
  268. * @brief Removes the component from this SceneObject, and deallocates it.
  269. *
  270. * @param [in] component The component to destroy.
  271. */
  272. void destroyComponent(const HComponent& component);
  273. /**
  274. * @brief Removes the component from this SceneObject, and deallocates it.
  275. *
  276. * @param [in] component The component to destroy.
  277. */
  278. void destroyComponent(Component* component);
  279. /**
  280. * @brief Returns all components on this SceneObject.
  281. */
  282. Vector<HComponent>::type& getComponents() { return mComponents; }
  283. private:
  284. template <typename T>
  285. static std::shared_ptr<T> createEmptyComponent()
  286. {
  287. BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotFramework::Component, T>::value), "Specified type is not a valid Component.");
  288. std::shared_ptr<T> gameObject(new (cm_alloc<T, PoolAlloc>()) T(), &cm_delete<PoolAlloc, T>, StdAlloc<PoolAlloc>());
  289. GameObjectHandle<T>(GameObjectManager::instance().registerObject(gameObject));
  290. return gameObject;
  291. }
  292. void addComponentInternal(const std::shared_ptr<Component> component);
  293. Vector<HComponent>::type mComponents;
  294. /************************************************************************/
  295. /* RTTI */
  296. /************************************************************************/
  297. public:
  298. friend class GameObjectRTTI;
  299. friend class SceneObjectRTTI;
  300. static RTTITypeBase* getRTTIStatic();
  301. virtual RTTITypeBase* getRTTI() const;
  302. };
  303. }