2
0

CmGameObjectHandle.h 3.5 KB

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