Просмотр исходного кода

Game objects now use a shared_ptr instead of a raw pointer

Marko Pintera 12 лет назад
Родитель
Сommit
b63db1970e

+ 23 - 22
CamelotCore/Include/CmGameObjectHandle.h

@@ -5,19 +5,15 @@ namespace CamelotFramework
 	struct CM_EXPORT GameObjectHandleData
 	{
 		GameObjectHandleData()
-			:mPtr(nullptr), mDeleter(nullptr)
+			:mPtr(nullptr)
 		{ }
 
-		GameObjectHandleData(GameObject* ptr, void(*deleter)(GameObject*))
+		GameObjectHandleData(const std::shared_ptr<GameObject>& ptr)
 		{
 			mPtr = ptr;
-			mDeleter = deleter;
 		}
 
-		typedef void(*HandleDeleter)(GameObject*);
-
-		GameObject* mPtr;
-		HandleDeleter mDeleter;
+		std::shared_ptr<GameObject> mPtr;
 	};
 
 	/**
@@ -50,7 +46,14 @@ namespace CamelotFramework
 		{ 
 			throwIfDestroyed();
 
-			return mData->mPtr; 
+			return mData->mPtr.get(); 
+		}
+
+		std::shared_ptr<GameObject> getInternalPtr() const
+		{
+			throwIfDestroyed();
+
+			return mData->mPtr;
 		}
 
 		GameObject* operator->() const { return get(); }
@@ -65,17 +68,7 @@ namespace CamelotFramework
 		
 		void destroy()
 		{
-			if(mData->mPtr != nullptr)
-			{
-				GameObject* toDelete = mData->mPtr;
-				mData->mPtr = nullptr; // Need to set this to null before deleting, otherwise destructor thinks object isn't destroyed
-				// and we end up here again
-
-				if(mData->mDeleter != nullptr)
-					mData->mDeleter(toDelete);
-				else
-					delete toDelete;
-			}
+			mData->mPtr = nullptr;
 		}
 
 		std::shared_ptr<GameObjectHandleData> mData;
@@ -119,8 +112,16 @@ namespace CamelotFramework
 		{ 
 			throwIfDestroyed();
 
-			return reinterpret_cast<T*>(mData->mPtr); 
+			return reinterpret_cast<T*>(mData->mPtr.get()); 
 		}
+
+		std::shared_ptr<T> getInternalPtr() const
+		{
+			throwIfDestroyed();
+
+			return std::static_pointer_cast<T>(mData->mPtr);
+		}
+
 		T* operator->() const { return get(); }
 		T& operator*() const { return *get(); }
 
@@ -140,10 +141,10 @@ namespace CamelotFramework
 	private:
 		friend SceneObject;
 
-		explicit GameObjectHandle(T* ptr, void(*deleter)(GameObject*) = nullptr)
+		explicit GameObjectHandle(const std::shared_ptr<T> ptr)
 			:GameObjectHandleBase()
 		{
-			mData = cm_shared_ptr<GameObjectHandleData, PoolAlloc>((GameObject*)ptr, deleter);
+			mData = cm_shared_ptr<GameObjectHandleData, PoolAlloc>(std::static_pointer_cast<GameObject>(ptr));
 		}
 	};
 

+ 3 - 1
CamelotCore/Include/CmGameObjectRTTI.h

@@ -9,11 +9,13 @@ namespace CamelotFramework
 	class CM_EXPORT GameObjectRTTI : public RTTIType<GameObject, IReflectable, GameObjectRTTI>
 	{
 	private:
+		UINT64& getInstanceID(GameObject* obj) { return obj->mInstanceId; }
+		void setInstanceID(GameObject* obj, UINT64& instanceId) { obj->mInstanceId = instanceId; }
 
 	public:
 		GameObjectRTTI()
 		{
-
+			addPlainField("mInstanceID", 0, &GameObjectRTTI::getInstanceID, &GameObjectRTTI::setInstanceID);
 		}
 
 		virtual const String& getRTTIName()

+ 6 - 4
CamelotCore/Include/CmSceneObject.h

@@ -16,6 +16,8 @@ namespace CamelotFramework
 	{
 		friend class SceneManager;
 	public:
+		~SceneObject();
+
 		static HSceneObject create(const String& name);
 		void destroy();
 
@@ -28,7 +30,6 @@ namespace CamelotFramework
 		HSceneObject mThisHandle;
 
 		SceneObject(const String& name, UINT32 id);
-		~SceneObject();
 
 		static HSceneObject createInternal(const String& name);
 		void destroyInternal();
@@ -224,7 +225,7 @@ namespace CamelotFramework
 			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotFramework::Component, T>::value), "Specified type is not a valid Component.");
 
 			GameObjectHandle<T> newComponent = GameObjectHandle<T>(
-				new (cm_alloc<T, PoolAlloc>()) T(mThisHandle), &cm_delete<PoolAlloc, GameObject>);
+				std::shared_ptr<T>(new (cm_alloc<T, PoolAlloc>()) T(mThisHandle), &cm_delete<PoolAlloc, T>, StdAlloc<PoolAlloc>()));
 			mComponents.push_back(newComponent);
 
 			gSceneManager().notifyComponentAdded(newComponent);
@@ -241,8 +242,9 @@ namespace CamelotFramework
 				"Specified type is not a valid Component.");										\
 																									\
 			GameObjectHandle<Type> newComponent = GameObjectHandle<Type>(							\
-				new (cm_alloc<Type, PoolAlloc>()) Type(mThisHandle, std::forward<T0>(t0) BOOST_PP_REPEAT_FROM_TO(1, n, FORWARD_T, ~)),	\
-				&cm_delete<PoolAlloc, GameObject>);													\
+				std::shared_ptr<Type>(new (cm_alloc<Type, PoolAlloc>()) Type(mThisHandle,			\
+				std::forward<T0>(t0) BOOST_PP_REPEAT_FROM_TO(1, n, FORWARD_T, ~)),					\
+				&cm_delete<PoolAlloc, Type>, StdAlloc<PoolAlloc>()));								\
 																									\
 			mComponents.push_back(newComponent);													\
 																									\

+ 5 - 4
CamelotCore/Source/CmSceneObject.cpp

@@ -37,9 +37,10 @@ namespace CamelotFramework
 
 	HSceneObject SceneObject::createInternal(const String& name)
 	{
-		HSceneObject sceneObject = GameObjectHandle<SceneObject>(
-			new (cm_alloc<SceneObject, PoolAlloc>()) SceneObject(name, NextFreeId++),
-			&cm_delete<PoolAlloc, GameObject>);
+		std::shared_ptr<SceneObject> sceneObjectPtr = std::shared_ptr<SceneObject>(new (cm_alloc<SceneObject, PoolAlloc>()) SceneObject(name, NextFreeId++), 
+			&cm_delete<PoolAlloc, SceneObject>, StdAlloc<PoolAlloc>());
+
+		HSceneObject sceneObject = GameObjectHandle<SceneObject>(sceneObjectPtr);
 		sceneObject->mThisHandle = sceneObject;
 
 		return sceneObject;
@@ -378,7 +379,7 @@ namespace CamelotFramework
 	void SceneObject::destroyComponent(Component* component)
 	{
 		auto iterFind = std::find_if(mComponents.begin(), mComponents.end(), 
-			[component](const HComponent& x) { return x.getHandleData()->mPtr == component; });
+			[component](const HComponent& x) { return x.getHandleData()->mPtr.get() == component; });
 
 		if(iterFind == mComponents.end())
 		{