BsGameObjectHandle.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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. /** @cond INTERNAL */
  87. /** Returns internal handle data. */
  88. std::shared_ptr<GameObjectHandleData> _getHandleData() const { return mData; }
  89. /** Resolves a handle to a proper GameObject in case it was created uninitialized. */
  90. void _resolve(const GameObjectHandleBase& object);
  91. /** Changes the GameObject instance the handle is pointing to. */
  92. void _setHandleData(const GameObjectPtr& object);
  93. /** @endcond */
  94. protected:
  95. friend class GameObjectManager;
  96. template<class _Ty1, class _Ty2>
  97. friend bool operator==(const GameObjectHandle<_Ty1>& _Left, const GameObjectHandle<_Ty2>& _Right);
  98. GameObjectHandleBase(const std::shared_ptr<GameObject> ptr);
  99. GameObjectHandleBase(const std::shared_ptr<GameObjectHandleData>& data);
  100. GameObjectHandleBase(std::nullptr_t ptr);
  101. /** Throws an exception if the referenced GameObject has been destroyed. */
  102. inline void throwIfDestroyed() const;
  103. /** Invalidates the handle signifying the referenced object was destroyed. */
  104. void destroy()
  105. {
  106. // It's important not to clear mData->mPtr as some code might rely
  107. // on it. (e.g. for restoring lost handles)
  108. if (mData->mPtr != nullptr)
  109. mData->mPtr->object = nullptr;
  110. }
  111. std::shared_ptr<GameObjectHandleData> mData;
  112. /************************************************************************/
  113. /* RTTI */
  114. /************************************************************************/
  115. public:
  116. friend class GameObjectHandleRTTI;
  117. static RTTITypeBase* getRTTIStatic();
  118. virtual RTTITypeBase* getRTTI() const override;
  119. };
  120. /** @} */
  121. /** @addtogroup Scene
  122. * @{
  123. */
  124. /**
  125. * @copydoc GameObjectHandleBase
  126. *
  127. * @note It is important this class contains no data since we often value cast it to its base.
  128. */
  129. template <typename T>
  130. class GameObjectHandle : public GameObjectHandleBase
  131. {
  132. public:
  133. /** Constructs a new empty handle. */
  134. GameObjectHandle()
  135. :GameObjectHandleBase()
  136. {
  137. mData = bs_shared_ptr_new<GameObjectHandleData>();
  138. }
  139. /** Copy constructor from another handle of the same type. */
  140. template <typename T1>
  141. GameObjectHandle(const GameObjectHandle<T1>& ptr)
  142. :GameObjectHandleBase()
  143. {
  144. mData = ptr._getHandleData();
  145. }
  146. /** Copy constructor from another handle of the base type. */
  147. GameObjectHandle(const GameObjectHandleBase& ptr)
  148. :GameObjectHandleBase()
  149. {
  150. mData = ptr._getHandleData();
  151. }
  152. /** Invalidates the handle. */
  153. GameObjectHandle<T>& operator=(std::nullptr_t ptr)
  154. {
  155. mData = bs_shared_ptr_new<GameObjectHandleData>();
  156. return *this;
  157. }
  158. /** Casts a specific handle to the base handle. */
  159. operator GameObjectHandleBase()
  160. {
  161. GameObjectHandleBase base(mData);
  162. return base;
  163. }
  164. /**
  165. * Returns a pointer to the referenced GameObject.
  166. *
  167. * @note Throws exception if the GameObject was destroyed.
  168. */
  169. T* get() const
  170. {
  171. throwIfDestroyed();
  172. return reinterpret_cast<T*>(mData->mPtr->object.get());
  173. }
  174. /**
  175. * Returns a smart pointer to the referenced GameObject.
  176. *
  177. * @note Throws exception if the GameObject was destroyed.
  178. */
  179. std::shared_ptr<T> getInternalPtr() const
  180. {
  181. throwIfDestroyed();
  182. return std::static_pointer_cast<T>(mData->mPtr->object);
  183. }
  184. /**
  185. * Returns pointer to the referenced GameObject.
  186. *
  187. * @note Throws exception if the GameObject was destroyed.
  188. */
  189. T* operator->() const { return get(); }
  190. /**
  191. * Returns reference to the referenced GameObject.
  192. *
  193. * @note Throws exception if the GameObject was destroyed.
  194. */
  195. T& operator*() const { return *get(); }
  196. /** @cond INTERNAL */
  197. template<class _Ty>
  198. struct Bool_struct
  199. {
  200. int _Member;
  201. };
  202. /**
  203. * Allows direct conversion of handle to bool.
  204. *
  205. * @note
  206. * This is needed because we can't directly convert to bool since then we can assign pointer to bool and that's
  207. * weird.
  208. */
  209. operator int Bool_struct<T>::*() const
  210. {
  211. return (((mData->mPtr != nullptr) && (mData->mPtr->object != nullptr)) ? &Bool_struct<T>::_Member : 0);
  212. }
  213. /** @endcond */
  214. };
  215. /** Casts one GameObject handle type to another. */
  216. template<class _Ty1, class _Ty2>
  217. GameObjectHandle<_Ty1> static_object_cast(const GameObjectHandle<_Ty2>& other)
  218. {
  219. return GameObjectHandle<_Ty1>(other);
  220. }
  221. /** @cond INTERNAL */
  222. /** Compares if two handles point to the same GameObject. */
  223. template<class _Ty1, class _Ty2>
  224. bool operator==(const GameObjectHandle<_Ty1>& _Left, const GameObjectHandle<_Ty2>& _Right)
  225. {
  226. return (_Left.mData == nullptr && _Right.mData == nullptr) ||
  227. (_Left.mData != nullptr && _Right.mData != nullptr && _Left.getInstanceId() == _Right.getInstanceId());
  228. }
  229. /** Compares if two handles point to different GameObject%s. */
  230. template<class _Ty1, class _Ty2>
  231. bool operator!=(const GameObjectHandle<_Ty1>& _Left, const GameObjectHandle<_Ty2>& _Right)
  232. {
  233. return (!(_Left == _Right));
  234. }
  235. /** @endcond */
  236. /** @} */
  237. }