BsGameObjectHandle.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #pragma once
  2. namespace BansheeEngine
  3. {
  4. class GameObjectManager;
  5. /**
  6. * @brief Internal data shared between GameObject handles.
  7. */
  8. struct BS_CORE_EXPORT GameObjectHandleData
  9. {
  10. GameObjectHandleData()
  11. :mPtr(nullptr), mInstanceId(0)
  12. { }
  13. GameObjectHandleData(const std::shared_ptr<GameObjectInstanceData>& ptr)
  14. {
  15. mPtr = ptr;
  16. if(ptr != nullptr)
  17. mInstanceId = ptr->object->getInstanceId();
  18. else
  19. mInstanceId = 0;
  20. }
  21. std::shared_ptr<GameObjectInstanceData> mPtr;
  22. UINT64 mInstanceId;
  23. };
  24. /**
  25. * @brief A handle that can point to various types of game objects.
  26. * It primarily keeps track if the object is still alive, so anything
  27. * still referencing it doesn't accidentally use it.
  28. *
  29. * @note This class exists because references between game objects should be quite loose.
  30. * For example one game object should be able to reference another one without the other
  31. * one knowing. But if that is the case I also need to handle the case when the other
  32. * object we're referencing has been deleted, and that is the main purpose of this class.
  33. *
  34. */
  35. class BS_CORE_EXPORT GameObjectHandleBase : public IReflectable
  36. {
  37. public:
  38. GameObjectHandleBase();
  39. /**
  40. * @brief Returns true if the object the handle is pointing to has been destroyed.
  41. *
  42. * @param checkQueued Game objects can be queued for destruction but no actually destroyed yet, and still accessible.
  43. * If this is false this method will return true only if the object is completely inaccessible (fully destroyed).
  44. * If this is true this method will return true if object is completely inaccessible or if it is just queued for destruction.
  45. */
  46. bool isDestroyed(bool checkQueued = false) const
  47. { return mData->mPtr == nullptr || mData->mPtr->object == nullptr || (checkQueued && mData->mPtr->object->_getIsDestroyed()); }
  48. /**
  49. * @brief Returns the instance ID of the object the handle is referencing.
  50. */
  51. UINT64 getInstanceId() const { return mData->mInstanceId; }
  52. /**
  53. * @brief Returns pointer to the referenced GameObject.
  54. *
  55. * @note Throws exception if the GameObject was destroyed.
  56. */
  57. GameObject* get() const
  58. {
  59. throwIfDestroyed();
  60. return mData->mPtr->object.get();
  61. }
  62. /**
  63. * @brief Returns a smart pointer to the referenced GameObject.
  64. *
  65. * @note Throws exception if the GameObject was destroyed.
  66. */
  67. std::shared_ptr<GameObject> getInternalPtr() const
  68. {
  69. throwIfDestroyed();
  70. return mData->mPtr->object;
  71. }
  72. /**
  73. * @brief Returns pointer to the referenced GameObject.
  74. *
  75. * @note Throws exception if the GameObject was destroyed.
  76. */
  77. GameObject* operator->() const { return get(); }
  78. /**
  79. * @brief Returns reference to the referenced GameObject.
  80. *
  81. * @note Throws exception if the GameObject was destroyed.
  82. */
  83. GameObject& operator*() const { return *get(); }
  84. /**
  85. * @brief Returns internal handle data.
  86. *
  87. * @note Internal method.
  88. */
  89. std::shared_ptr<GameObjectHandleData> _getHandleData() const { return mData; }
  90. /**
  91. * @brief Resolves a handle to a proper GameObject in case it was created uninitialized.
  92. *
  93. * @note Internal method.
  94. */
  95. void _resolve(const GameObjectHandleBase& object);
  96. /**
  97. * @brief Changes the GameObject instance the handle is pointing to.
  98. *
  99. * @note Internal method.
  100. */
  101. void _setHandleData(const GameObjectPtr& object);
  102. protected:
  103. friend class SceneObject;
  104. friend class SceneObjectRTTI;
  105. friend class GameObjectManager;
  106. GameObjectHandleBase(const std::shared_ptr<GameObject> ptr);
  107. GameObjectHandleBase(const std::shared_ptr<GameObjectHandleData>& data);
  108. GameObjectHandleBase(std::nullptr_t ptr);
  109. /**
  110. * @brief Throws an exception if the referenced GameObject has been destroyed.
  111. */
  112. inline void throwIfDestroyed() const;
  113. /**
  114. * @brief Invalidates the handle signifying the referenced object was destroyed.
  115. */
  116. void destroy()
  117. {
  118. // It's important not to clear mData->mPtr as some code might rely
  119. // on it. (e.g. for restoring lost handles)
  120. if (mData->mPtr != nullptr)
  121. mData->mPtr->object = nullptr;
  122. }
  123. std::shared_ptr<GameObjectHandleData> mData;
  124. /************************************************************************/
  125. /* RTTI */
  126. /************************************************************************/
  127. public:
  128. friend class GameObjectHandleRTTI;
  129. static RTTITypeBase* getRTTIStatic();
  130. virtual RTTITypeBase* getRTTI() const;
  131. };
  132. /**
  133. * @copydoc GameObjectHandleBase
  134. *
  135. * @note It is important this class contains no data since we often
  136. * value cast it to its base.
  137. */
  138. template <typename T>
  139. class GameObjectHandle : public GameObjectHandleBase
  140. {
  141. public:
  142. /**
  143. * @brief Constructs a new empty handle.
  144. */
  145. GameObjectHandle()
  146. :GameObjectHandleBase()
  147. {
  148. mData = bs_shared_ptr<GameObjectHandleData, PoolAlloc>();
  149. }
  150. /**
  151. * @brief Copy constructor from another handle of the same type.
  152. */
  153. template <typename T1>
  154. GameObjectHandle(const GameObjectHandle<T1>& ptr)
  155. :GameObjectHandleBase()
  156. {
  157. mData = ptr._getHandleData();
  158. }
  159. /**
  160. * @brief Copy constructor from another handle of the base type.
  161. */
  162. GameObjectHandle(const GameObjectHandleBase& ptr)
  163. :GameObjectHandleBase()
  164. {
  165. mData = ptr._getHandleData();
  166. }
  167. /**
  168. * @brief Invalidates the handle.
  169. */
  170. inline GameObjectHandle<T>& operator=(std::nullptr_t ptr)
  171. {
  172. mData = bs_shared_ptr<GameObjectHandleData, PoolAlloc>();
  173. return *this;
  174. }
  175. /**
  176. * @brief Casts a specific handle to the base handle.
  177. */
  178. inline operator GameObjectHandleBase()
  179. {
  180. GameObjectHandleBase base(mData);
  181. return base;
  182. }
  183. /**
  184. * @brief Returns a pointer to the referenced GameObject.
  185. *
  186. * @note Throws exception if the GameObject was destroyed.
  187. */
  188. T* get() const
  189. {
  190. throwIfDestroyed();
  191. return reinterpret_cast<T*>(mData->mPtr->object.get());
  192. }
  193. /**
  194. * @brief Returns a smart pointer to the referenced GameObject.
  195. *
  196. * @note Throws exception if the GameObject was destroyed.
  197. */
  198. std::shared_ptr<T> getInternalPtr() const
  199. {
  200. throwIfDestroyed();
  201. return std::static_pointer_cast<T>(mData->mPtr->object);
  202. }
  203. /**
  204. * @brief Returns pointer to the referenced GameObject.
  205. *
  206. * @note Throws exception if the GameObject was destroyed.
  207. */
  208. T* operator->() const { return get(); }
  209. /**
  210. * @brief Returns reference to the referenced GameObject.
  211. *
  212. * @note Throws exception if the GameObject was destroyed.
  213. */
  214. T& operator*() const { return *get(); }
  215. template<class _Ty>
  216. struct Bool_struct
  217. {
  218. int _Member;
  219. };
  220. /**
  221. * @brief Allows direct conversion of handle to bool.
  222. *
  223. * @note This is needed because we can't directly convert to bool
  224. * since then we can assign pointer to bool and that's weird.
  225. */
  226. operator int Bool_struct<T>::*() const
  227. {
  228. return (((mData->mPtr != nullptr) && (mData->mPtr->object != nullptr)) ? &Bool_struct<T>::_Member : 0);
  229. }
  230. private:
  231. friend class SceneObject;
  232. friend class SceneObjectRTTI;
  233. friend class GameObjectManager;
  234. /**
  235. * @brief Creates a GameObject handle from a smart pointer.
  236. */
  237. explicit GameObjectHandle(const std::shared_ptr<T> ptr)
  238. :GameObjectHandleBase(ptr)
  239. { }
  240. };
  241. /**
  242. * @brief Casts one GameObject handle type to another.
  243. */
  244. template<class _Ty1, class _Ty2>
  245. GameObjectHandle<_Ty1> static_object_cast(const GameObjectHandle<_Ty2>& other)
  246. {
  247. return GameObjectHandle<_Ty1>(other);
  248. }
  249. /**
  250. * @brief Compares if two handles point to the same GameObject.
  251. */
  252. template<class _Ty1, class _Ty2>
  253. bool operator==(const GameObjectHandle<_Ty1>& _Left, const GameObjectHandle<_Ty2>& _Right)
  254. {
  255. return (_Left == nullptr && _Right == nullptr) || (_Left != nullptr && _Right != nullptr && _Left.get() == _Right.get());
  256. }
  257. /**
  258. * @brief Compares if two handles point to different GameObjects.
  259. */
  260. template<class _Ty1, class _Ty2>
  261. bool operator!=(const GameObjectHandle<_Ty1>& _Left, const GameObjectHandle<_Ty2>& _Right)
  262. {
  263. return (!(_Left == _Right));
  264. }
  265. }