2
0

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