CmGameObjectHandle.h 3.1 KB

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