2
0

BsGameObjectHandle.h 8.2 KB

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