| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
- //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
- #pragma once
- namespace BansheeEngine
- {
- /** @addtogroup Implementation
- * @{
- */
- class GameObjectManager;
- template <typename T>
- class GameObjectHandle;
- /** @cond INTERNAL */
- /** Contains instance data that is held by all GameObject handles. */
- struct GameObjectInstanceData
- {
- GameObjectInstanceData()
- :mInstanceId(0), object(nullptr)
- { }
- std::shared_ptr<GameObject> object;
- UINT64 mInstanceId;
- };
- typedef std::shared_ptr<GameObjectInstanceData> GameObjectInstanceDataPtr;
- /** Internal data shared between GameObject handles. */
- struct BS_CORE_EXPORT GameObjectHandleData
- {
- GameObjectHandleData()
- :mPtr(nullptr)
- { }
- GameObjectHandleData(const std::shared_ptr<GameObjectInstanceData>& ptr)
- {
- mPtr = ptr;
- }
- std::shared_ptr<GameObjectInstanceData> mPtr;
- };
- /** @endcond */
- /**
- * A handle that can point to various types of game objects. It primarily keeps track if the object is still alive,
- * so anything still referencing it doesn't accidentally use it.
- *
- * @note
- * This class exists because references between game objects should be quite loose. For example one game object should
- * be able to reference another one without the other one knowing. But if that is the case I also need to handle the
- * case when the other object we're referencing has been deleted, and that is the main purpose of this class.
- */
- class BS_CORE_EXPORT GameObjectHandleBase : public IReflectable
- {
- public:
- GameObjectHandleBase();
- /**
- * Returns true if the object the handle is pointing to has been destroyed.
- *
- * @param[in] checkQueued Game objects can be queued for destruction but not actually destroyed yet, and still
- * accessible. If this is false this method will return true only if the object is
- * completely inaccessible (fully destroyed). If this is true this method will return true
- * if object is completely inaccessible or if it is just queued for destruction.
- */
- bool isDestroyed(bool checkQueued = false) const;
- /** Returns the instance ID of the object the handle is referencing. */
- UINT64 getInstanceId() const { return mData->mPtr != nullptr ? mData->mPtr->mInstanceId : 0; }
- /**
- * Returns pointer to the referenced GameObject.
- *
- * @note Throws exception if the GameObject was destroyed.
- */
- GameObject* get() const
- {
- throwIfDestroyed();
- return mData->mPtr->object.get();
- }
- /**
- * Returns a smart pointer to the referenced GameObject.
- *
- * @note Throws exception if the GameObject was destroyed.
- */
- std::shared_ptr<GameObject> getInternalPtr() const
- {
- throwIfDestroyed();
- return mData->mPtr->object;
- }
- /**
- * Returns pointer to the referenced GameObject.
- *
- * @note Throws exception if the GameObject was destroyed.
- */
- GameObject* operator->() const { return get(); }
- /**
- * Returns reference to the referenced GameObject.
- *
- * @note Throws exception if the GameObject was destroyed.
- */
- GameObject& operator*() const { return *get(); }
- public: // ***** INTERNAL ******
- /** @cond INTERNAL */
- /** Returns internal handle data. */
- std::shared_ptr<GameObjectHandleData> _getHandleData() const { return mData; }
- /** Resolves a handle to a proper GameObject in case it was created uninitialized. */
- void _resolve(const GameObjectHandleBase& object);
- /** Changes the GameObject instance the handle is pointing to. */
- void _setHandleData(const GameObjectPtr& object);
- /** @endcond */
- protected:
- friend class GameObjectManager;
- template<class _Ty1, class _Ty2>
- friend bool operator==(const GameObjectHandle<_Ty1>& _Left, const GameObjectHandle<_Ty2>& _Right);
- GameObjectHandleBase(const std::shared_ptr<GameObject> ptr);
- GameObjectHandleBase(const std::shared_ptr<GameObjectHandleData>& data);
- GameObjectHandleBase(std::nullptr_t ptr);
- /** Throws an exception if the referenced GameObject has been destroyed. */
- inline void throwIfDestroyed() const;
-
- /** Invalidates the handle signifying the referenced object was destroyed. */
- void destroy()
- {
- // It's important not to clear mData->mPtr as some code might rely
- // on it. (e.g. for restoring lost handles)
- if (mData->mPtr != nullptr)
- mData->mPtr->object = nullptr;
- }
- std::shared_ptr<GameObjectHandleData> mData;
- /************************************************************************/
- /* RTTI */
- /************************************************************************/
- public:
- friend class GameObjectHandleRTTI;
- static RTTITypeBase* getRTTIStatic();
- virtual RTTITypeBase* getRTTI() const override;
- };
- /** @} */
- /** @addtogroup Scene
- * @{
- */
- /**
- * @copydoc GameObjectHandleBase
- *
- * @note It is important this class contains no data since we often value cast it to its base.
- */
- template <typename T>
- class GameObjectHandle : public GameObjectHandleBase
- {
- public:
- /** Constructs a new empty handle. */
- GameObjectHandle()
- :GameObjectHandleBase()
- {
- mData = bs_shared_ptr_new<GameObjectHandleData>();
- }
- /** Copy constructor from another handle of the same type. */
- template <typename T1>
- GameObjectHandle(const GameObjectHandle<T1>& ptr)
- :GameObjectHandleBase()
- {
- mData = ptr._getHandleData();
- }
- /** Copy constructor from another handle of the base type. */
- GameObjectHandle(const GameObjectHandleBase& ptr)
- :GameObjectHandleBase()
- {
- mData = ptr._getHandleData();
- }
- /** Invalidates the handle. */
- GameObjectHandle<T>& operator=(std::nullptr_t ptr)
- {
- mData = bs_shared_ptr_new<GameObjectHandleData>();
- return *this;
- }
- /** Casts a specific handle to the base handle. */
- operator GameObjectHandleBase()
- {
- GameObjectHandleBase base(mData);
- return base;
- }
- /**
- * Returns a pointer to the referenced GameObject.
- *
- * @note Throws exception if the GameObject was destroyed.
- */
- T* get() const
- {
- throwIfDestroyed();
- return reinterpret_cast<T*>(mData->mPtr->object.get());
- }
- /**
- * Returns a smart pointer to the referenced GameObject.
- *
- * @note Throws exception if the GameObject was destroyed.
- */
- std::shared_ptr<T> getInternalPtr() const
- {
- throwIfDestroyed();
- return std::static_pointer_cast<T>(mData->mPtr->object);
- }
- /**
- * Returns pointer to the referenced GameObject.
- *
- * @note Throws exception if the GameObject was destroyed.
- */
- T* operator->() const { return get(); }
- /**
- * Returns reference to the referenced GameObject.
- *
- * @note Throws exception if the GameObject was destroyed.
- */
- T& operator*() const { return *get(); }
- public: // ***** INTERNAL ******
- /** @cond INTERNAL */
- template<class _Ty>
- struct Bool_struct
- {
- int _Member;
- };
- /**
- * Allows direct conversion of handle to bool.
- *
- * @note
- * This is needed because we can't directly convert to bool since then we can assign pointer to bool and that's
- * weird.
- */
- operator int Bool_struct<T>::*() const
- {
- return (((mData->mPtr != nullptr) && (mData->mPtr->object != nullptr)) ? &Bool_struct<T>::_Member : 0);
- }
- /** @endcond */
- };
- /** Casts one GameObject handle type to another. */
- template<class _Ty1, class _Ty2>
- GameObjectHandle<_Ty1> static_object_cast(const GameObjectHandle<_Ty2>& other)
- {
- return GameObjectHandle<_Ty1>(other);
- }
- /** @cond INTERNAL */
- /** Compares if two handles point to the same GameObject. */
- template<class _Ty1, class _Ty2>
- bool operator==(const GameObjectHandle<_Ty1>& _Left, const GameObjectHandle<_Ty2>& _Right)
- {
- return (_Left.mData == nullptr && _Right.mData == nullptr) ||
- (_Left.mData != nullptr && _Right.mData != nullptr && _Left.getInstanceId() == _Right.getInstanceId());
- }
- /** Compares if two handles point to different GameObject%s. */
- template<class _Ty1, class _Ty2>
- bool operator!=(const GameObjectHandle<_Ty1>& _Left, const GameObjectHandle<_Ty2>& _Right)
- {
- return (!(_Left == _Right));
- }
- /** @endcond */
- /** @} */
- }
|