CmGameObjectHandle.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #pragma once
  2. namespace CamelotFramework
  3. {
  4. struct CM_EXPORT GameObjectHandleData
  5. {
  6. GameObjectHandleData()
  7. :mPtr(nullptr)
  8. { }
  9. GameObjectHandleData(const std::shared_ptr<GameObject>& ptr)
  10. {
  11. mPtr = ptr;
  12. }
  13. std::shared_ptr<GameObject> mPtr;
  14. };
  15. /**
  16. * @brief A handle that can point to various types of game objects.
  17. * It primarily keeps track if the object is still alive, so anything
  18. * still referencing it doesn't accidentally use it.
  19. *
  20. * @note This class exists because I want the references between game objects be quite loose.
  21. * For example one game object should be able to reference another one without the other
  22. * one knowing. But if that is the case I also need to handle the case when the other
  23. * object we're referencing has been deleted, and that is the main purpose of this class.
  24. *
  25. */
  26. class CM_EXPORT GameObjectHandleBase
  27. {
  28. public:
  29. GameObjectHandleBase(const std::shared_ptr<GameObjectHandleData> data);
  30. /**
  31. * @brief Checks if the object has been destroyed
  32. */
  33. bool isDestroyed() const { return mData->mPtr == nullptr; }
  34. /**
  35. * @brief Internal method only. Not meant to be called directly.
  36. */
  37. std::shared_ptr<GameObjectHandleData> getHandleData() const { return mData; }
  38. GameObject* get() const
  39. {
  40. throwIfDestroyed();
  41. return mData->mPtr.get();
  42. }
  43. std::shared_ptr<GameObject> getInternalPtr() const
  44. {
  45. throwIfDestroyed();
  46. return mData->mPtr;
  47. }
  48. GameObject* operator->() const { return get(); }
  49. GameObject& operator*() const { return *get(); }
  50. protected:
  51. friend SceneObject;
  52. GameObjectHandleBase();
  53. inline void throwIfDestroyed() const;
  54. void destroy()
  55. {
  56. mData->mPtr = nullptr;
  57. }
  58. std::shared_ptr<GameObjectHandleData> mData;
  59. };
  60. // NOTE: It is important this class contains no data since we often value
  61. // cast it to its base
  62. template <typename T>
  63. class GameObjectHandle : public GameObjectHandleBase
  64. {
  65. public:
  66. GameObjectHandle()
  67. :GameObjectHandleBase()
  68. {
  69. mData = cm_shared_ptr<GameObjectHandleData, PoolAlloc>();
  70. }
  71. template <typename T1>
  72. GameObjectHandle(const GameObjectHandle<T1>& ptr)
  73. :GameObjectHandleBase()
  74. {
  75. mData = ptr.getHandleData();
  76. }
  77. inline GameObjectHandle<T>& operator=(std::nullptr_t ptr)
  78. {
  79. mData = cm_shared_ptr<GameObjectHandleData, PoolAlloc>();
  80. mData->mPtr = nullptr;
  81. return *this;
  82. }
  83. inline operator GameObjectHandleBase()
  84. {
  85. GameObjectHandleBase base(mData);
  86. return base;
  87. }
  88. T* get() const
  89. {
  90. throwIfDestroyed();
  91. return reinterpret_cast<T*>(mData->mPtr.get());
  92. }
  93. std::shared_ptr<T> getInternalPtr() const
  94. {
  95. throwIfDestroyed();
  96. return std::static_pointer_cast<T>(mData->mPtr);
  97. }
  98. T* operator->() const { return get(); }
  99. T& operator*() const { return *get(); }
  100. template<class _Ty>
  101. struct CM_Bool_struct
  102. {
  103. int _Member;
  104. };
  105. // Conversion to bool
  106. // (Why not just directly convert to bool? Because then we can assign pointer to bool and that's weird)
  107. operator int CM_Bool_struct<T>::*() const
  108. {
  109. return (((mData->mPtr != nullptr)) ? &CM_Bool_struct<T>::_Member : 0);
  110. }
  111. private:
  112. friend SceneObject;
  113. explicit GameObjectHandle(const std::shared_ptr<T> ptr)
  114. :GameObjectHandleBase()
  115. {
  116. mData = cm_shared_ptr<GameObjectHandleData, PoolAlloc>(std::static_pointer_cast<GameObject>(ptr));
  117. }
  118. };
  119. template<class _Ty1, class _Ty2>
  120. GameObjectHandle<_Ty1> static_object_cast(const GameObjectHandle<_Ty2>& other)
  121. {
  122. return GameObjectHandle<_Ty1>(other);
  123. }
  124. template<class _Ty1, class _Ty2>
  125. bool operator==(const GameObjectHandle<_Ty1>& _Left, const GameObjectHandle<_Ty2>& _Right)
  126. {
  127. return (_Left.get() == _Right.get());
  128. }
  129. template<class _Ty1, class _Ty2>
  130. bool operator!=(const GameObjectHandle<_Ty1>& _Left, const GameObjectHandle<_Ty2>& _Right)
  131. {
  132. return (!(_Left == _Right));
  133. }
  134. }