Ver código fonte

GameObjects now use handles

Marko Pintera 12 anos atrás
pai
commit
b75ee7ad4a

+ 3 - 5
CamelotClient/CamelotClient.cpp

@@ -52,7 +52,7 @@ int CALLBACK WinMain(
 	RenderSystem* renderSystem = RenderSystem::instancePtr();
 	RenderWindowPtr renderWindow = gApplication().getPrimaryRenderWindow();
 
-	GameObjectPtr cameraGO = GameObject::create("MainCamera");
+	HGameObject cameraGO = GameObject::create("MainCamera");
 	CameraPtr camera = cameraGO->addComponent<Camera>();
 
 	camera->init(renderWindow, 0.0f, 0.0f, 1.0f, 1.0f, 0);
@@ -63,10 +63,10 @@ int CALLBACK WinMain(
 
 	std::shared_ptr<DebugCamera> debugCamera = cameraGO->addComponent<DebugCamera>();
 
-	GameObjectPtr testModelGO = GameObject::create("TestMesh");
+	HGameObject testModelGO = GameObject::create("TestMesh");
 	RenderablePtr testRenderable = testModelGO->addComponent<Renderable>();
 
-	GameObjectPtr testTextGO = GameObject::create("TestText");
+	HGameObject testTextGO = GameObject::create("TestText");
 	std::shared_ptr<TestTextSprite> textSprite = testTextGO->addComponent<TestTextSprite>();
 
 	HFont font;
@@ -298,11 +298,9 @@ int CALLBACK WinMain(
 	vertProgRef.reset();
 
 	testModelGO->destroy();
-	testModelGO = nullptr;
 	testRenderable = nullptr;
 
 	cameraGO->destroy();
-	cameraGO = nullptr;
 	camera = nullptr;
 	debugCamera = nullptr;
 

+ 1 - 1
CamelotClient/CmDebugCamera.cpp

@@ -15,7 +15,7 @@ namespace CamelotEngine
 	const float DebugCamera::FAST_MODE_MULTIPLIER = 2.0f;
 	const float DebugCamera::ROTATION_SPEED = 0.5f; // Degrees/pixel
 
-	DebugCamera::DebugCamera(GameObjectPtr parent)
+	DebugCamera::DebugCamera(const HGameObject& parent)
 		:Component(parent), mGoingForward(false), mGoingBack(false), mGoingLeft(false), mGoingRight(false), 
 		mFastMove(false), mCameraRotating(false), mPitch(0.0f), mYaw(0.0f)
 	{

+ 1 - 1
CamelotClient/CmDebugCamera.h

@@ -44,7 +44,7 @@ namespace CamelotEngine
 
 		/** Standard constructor.
         */
-		DebugCamera(GameObjectPtr parent);
+		DebugCamera(const HGameObject& parent);
 
 	public:
 		virtual void update();

+ 1 - 1
CamelotClient/CmTestTextSprite.cpp

@@ -12,7 +12,7 @@
 
 namespace CamelotEngine
 {
-	TestTextSprite::TestTextSprite(GameObjectPtr parent)
+	TestTextSprite::TestTextSprite(const HGameObject& parent)
 		:GUIWidget(parent), mSkin(nullptr)
 	{
 	}

+ 1 - 1
CamelotClient/CmTestTextSprite.h

@@ -8,7 +8,7 @@ namespace CamelotEngine
 	private:
 		friend class GameObject;
 
-		TestTextSprite(GameObjectPtr parent);
+		TestTextSprite(const HGameObject& parent);
 
 		GUISkin* mSkin;
 	public:

+ 1 - 1
CamelotCore/Include/CmCamera.h

@@ -527,7 +527,7 @@ namespace CamelotEngine {
 
 		/** Standard constructor.
         */
-		Camera(GameObjectPtr parent);
+		Camera(const HGameObject& parent);
 
 	public:
 		virtual void update() {}

+ 4 - 4
CamelotCore/Include/CmComponent.h

@@ -11,12 +11,12 @@ namespace CamelotEngine
 		/**
 		 * @brief	Returns the GameObject this Component is assigned to.
 		 */
-		GameObjectPtr gameObject() const { return mParent.lock(); }
+		HGameObject gameObject() const { return mParent; }
 
 		/**
 		 * @brief	Same as gameObject(), just a shorter name.
 		 */
-		GameObjectPtr GO() const { return gameObject(); }
+		HGameObject GO() const { return gameObject(); }
 
 		/**
 		 * @brief	Called once per frame on all components.
@@ -27,7 +27,7 @@ namespace CamelotEngine
 	protected:
 		friend class GameObject;
 
-		Component(GameObjectPtr parent);
+		Component(const HGameObject& parent);
 
 		/**
 		 * @brief	Destroys the Component and makes it unusable, without actually deleting it.
@@ -36,7 +36,7 @@ namespace CamelotEngine
 		 */
 		void destroy();
 
-		std::weak_ptr<GameObject> mParent;
+		HGameObject mParent;
 		bool mIsDestroyed;
 
 		/************************************************************************/

+ 1 - 1
CamelotCore/Include/CmGUIWidget.h

@@ -14,7 +14,7 @@ namespace CamelotEngine
 	protected:
 		friend class GameObject;
 
-		GUIWidget(GameObjectPtr parent);
+		GUIWidget(const HGameObject& parent);
 
 		GUILabel* addLabel(const String& text);
 

+ 15 - 16
CamelotCore/Include/CmGameObject.h

@@ -15,18 +15,17 @@ namespace CamelotEngine
 	{
 		friend class SceneManager;
 	public:
-		static GameObjectPtr create(const String& name);
-		~GameObject();
-
+		static HGameObject create(const String& name);
 		void destroy();
-		bool isDestroyed() { return mIsDestroyed; }
 
 	private:
+		HGameObject mThisHandle;
+
 		GameObject(const String& name);
-		static GameObjectPtr createInternal(const String& name);
+		~GameObject();
 
-		std::weak_ptr<GameObject> mThis;
-		bool mIsDestroyed;
+		static HGameObject createInternal(const String& name);
+		void destroyInternal();
 
 		/************************************************************************/
 		/* 								Transform	                     		*/
@@ -151,14 +150,14 @@ namespace CamelotEngine
 		 *
 		 * @param [in]	parent	New parent.
 		 */
-		void setParent(GameObjectPtr parent);
+		void setParent(const HGameObject& parent);
 
 		/**
 		 * @brief	Gets the parent of this object.
 		 *
 		 * @return	Parent object, or nullptr if this GameObject is at root level.
 		 */
-		GameObjectPtr getParent() const { return mParent.lock(); }
+		HGameObject getParent() const { return mParent; }
 
 		/**
 		 * @brief	Gets a child of this item.
@@ -169,7 +168,7 @@ namespace CamelotEngine
 		 * 			
 		 * @throws ERR_INVALIDPARAMS If the index is out of range.
 		 */
-		GameObjectPtr getChild(unsigned int idx) const;
+		HGameObject getChild(unsigned int idx) const;
 
 		/**
 		 * @brief	Find the index of the specified child. Don't persist this value as
@@ -179,7 +178,7 @@ namespace CamelotEngine
 		 *
 		 * @return	The zero-based index of the found child, or -1 if no match was found.
 		 */
-		int indexOfChild(const GameObjectPtr child) const;
+		int indexOfChild(const HGameObject& child) const;
 
 		/**
 		 * @brief	Gets the number of all child GameObjects.
@@ -187,15 +186,15 @@ namespace CamelotEngine
 		UINT32 getNumChildren() const { return (UINT32)mChildren.size(); }
 
 	private:
-		std::weak_ptr<GameObject> mParent;
-		vector<GameObjectPtr>::type mChildren;
+		HGameObject mParent;
+		vector<HGameObject>::type mChildren;
 
 		/**
 		 * @brief	Adds a child to the child array. This method doesn't check for null or duplicate values.
 		 *
 		 * @param [in]	object	New child.
 		 */
-		void addChild(GameObjectPtr object);
+		void addChild(const HGameObject& object);
 		
 		/**
 		 * @brief	Removes the child from the object. 
@@ -204,7 +203,7 @@ namespace CamelotEngine
 		 * 					
 		 * @throws INTERNAL_ERROR If the provided child isn't a child of the current object.
 		 */
-		void removeChild(GameObjectPtr object);
+		void removeChild(const HGameObject& object);
 
 		/************************************************************************/
 		/* 								Component	                     		*/
@@ -216,7 +215,7 @@ namespace CamelotEngine
 			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::Component, T>::value), 
 				"Specified type is not a valid Component.");
 
-			std::shared_ptr<T> newComponent(new T(mThis.lock()));
+			std::shared_ptr<T> newComponent(new T(mThisHandle));
 			mComponents.push_back(newComponent);
 
 			gSceneManager().notifyComponentAdded(newComponent);

+ 17 - 5
CamelotCore/Include/CmGameObjectHandle.h

@@ -35,7 +35,6 @@ namespace CamelotEngine
 
 	protected:
 		GameObjectHandleBase();
-		GameObjectHandleBase(const std::shared_ptr<GameObjectHandleData>& data);
 
 		inline void throwIfDestroyed() const;
 		std::shared_ptr<GameObjectHandleData> getHandleData() const { return mData; }
@@ -49,12 +48,16 @@ namespace CamelotEngine
 	public:
 		GameObjectHandle()
 			:GameObjectHandleBase()
-		{	}
+		{	
+			mData = std::shared_ptr<GameObjectHandleData>(new GameObjectHandleData());
+		}
 
 		template <typename T1>
 		GameObjectHandle(const GameObjectHandle<T1>& ptr)
 			:GameObjectHandleBase(ptr.getHandleData())
-		{ 	}
+		{ 	
+			mData = ptr.getHandleData();
+		}
 
 		T* get() const 
 		{ 
@@ -65,6 +68,13 @@ namespace CamelotEngine
 		T* operator->() const { return get(); }
 		T& operator*() const { return *get(); }
 
+		std::shared_ptr<T> getInternalPtr() const
+		{ 
+			throwIfDestroyed();
+
+			return std::static_pointer_cast<T>(mData->mPtr); 
+		}
+
 		template<class _Ty>
 		struct CM_Bool_struct
 		{
@@ -82,8 +92,10 @@ namespace CamelotEngine
 		friend T;
 
 		explicit GameObjectHandle(T* ptr)
-			:GameObjectHandleBase(std::shared_ptr<GameObjectHandleData>(new GameObjectHandleData(ptr));)
-		{ }
+			:GameObjectHandleBase()
+		{
+			mData = std::shared_ptr<GameObjectHandleData>(new GameObjectHandleData(ptr));
+		}
 
 		void releaseHeldObject()
 		{

+ 1 - 1
CamelotCore/Include/CmOverlay.h

@@ -21,6 +21,6 @@ namespace CamelotEngine
 	protected:
 		friend class GameObject;
 
-		Overlay(GameObjectPtr parent);
+		Overlay(const HGameObject& parent);
 	};
 }

+ 5 - 0
CamelotCore/Include/CmPrerequisites.h

@@ -327,6 +327,7 @@ namespace CamelotEngine
 
 namespace CamelotEngine
 {
+	// Resource handles
 	typedef ResourceHandle<Resource> HResource;
 	typedef ResourceHandle<Texture> HTexture;
 	typedef ResourceHandle<Mesh> HMesh;
@@ -339,6 +340,10 @@ namespace CamelotEngine
 	typedef ResourceHandle<BlendState> HBlendState;
 	typedef ResourceHandle<GpuProgInclude> HGpuProgInclude;
 	typedef ResourceHandle<Font> HFont;
+
+	// Game object handles
+	typedef GameObjectHandle<GameObject> HGameObject;
+	typedef GameObjectHandle<Component> HComponent;
 }
 
 #endif

+ 1 - 1
CamelotCore/Include/CmRenderable.h

@@ -26,7 +26,7 @@ namespace CamelotEngine
 
 		/** Standard constructor.
         */
-		Renderable(GameObjectPtr parent);
+		Renderable(const HGameObject& parent);
 
 	public:
 		virtual void update() {}

+ 3 - 3
CamelotCore/Include/CmSceneManager.h

@@ -17,7 +17,7 @@ namespace CamelotEngine
 		SceneManager();
 		virtual ~SceneManager();
 
-		GameObjectPtr getRootNode() const { return mRootNode; }
+		HGameObject getRootNode() const { return mRootNode; }
 
 		virtual void update();
 
@@ -30,7 +30,7 @@ namespace CamelotEngine
 
 	private:
 		friend class GameObject;
-		GameObjectPtr mRootNode;
+		HGameObject mRootNode;
 
 		/**
 		 * @brief	Register a new node in the scene manager, on the top-most level of the hierarchy.
@@ -40,7 +40,7 @@ namespace CamelotEngine
 		 *
 		 * @param [in]	node	Node you wish to add. It's your responsibility not to add duplicate or null nodes. This method won't check.
 		 */
-		void registerNewGO(GameObjectPtr node);
+		void registerNewGO(const HGameObject& node);
 
 		void notifyComponentAdded(ComponentPtr component);
 		void notifyComponentRemoved(ComponentPtr component);

+ 1 - 1
CamelotCore/Source/CmCamera.cpp

@@ -44,7 +44,7 @@ namespace CamelotEngine {
 	const float Camera::INFINITE_FAR_PLANE_ADJUST = 0.00001f;
 
     //-----------------------------------------------------------------------
-	Camera::Camera(GameObjectPtr parent)
+	Camera::Camera(const HGameObject& parent)
         : Component(parent),
 		mProjType(PT_PERSPECTIVE), 
 		mFOVy(Radian(Math::PI/4.0f)), 

+ 1 - 1
CamelotCore/Source/CmComponent.cpp

@@ -3,7 +3,7 @@
 
 namespace CamelotEngine
 {
-	Component::Component(GameObjectPtr parent)
+	Component::Component(const HGameObject& parent)
 		:mParent(parent), mIsDestroyed(false)
 	{
 

+ 1 - 1
CamelotCore/Source/CmGUIWidget.cpp

@@ -11,7 +11,7 @@ namespace CamelotEngine
 {
 	GUISkin GUIWidget::DefaultSkin;
 
-	GUIWidget::GUIWidget(GameObjectPtr parent)
+	GUIWidget::GUIWidget(const HGameObject& parent)
 		:Overlay(parent), mSkin(nullptr)
 	{
 		GUIManager::instance().registerWidget(this);

+ 42 - 39
CamelotCore/Source/CmGameObject.cpp

@@ -11,39 +11,52 @@ namespace CamelotEngine
 		mWorldPosition(Vector3::ZERO), mWorldRotation(Quaternion::IDENTITY), mWorldScale(Vector3::UNIT_SCALE),
 		mCachedLocalTfrm(Matrix4::IDENTITY), mIsCachedLocalTfrmUpToDate(false),
 		mCachedWorldTfrm(Matrix4::IDENTITY), mIsCachedWorldTfrmUpToDate(false),
-		mCustomWorldTfrm(Matrix4::IDENTITY), mIsCustomTfrmModeActive(false),
-		mIsDestroyed(false)
+		mCustomWorldTfrm(Matrix4::IDENTITY), mIsCustomTfrmModeActive(false)
 	{ }
 
 	GameObject::~GameObject()
 	{
-		if(!mIsDestroyed)
-			destroy();
+		if(!mThisHandle.isDestroyed())
+		{
+			LOGWRN("Object is being deleted without being destroyed first?");
+			destroyInternal();
+		}
 	}
 
-	GameObjectPtr GameObject::create(const String& name)
+	HGameObject GameObject::create(const String& name)
 	{
-		GameObjectPtr newObject = createInternal(name);
+		HGameObject newObject = createInternal(name);
 
 		gSceneManager().registerNewGO(newObject);
 
 		return newObject;
 	}
 
-	GameObjectPtr GameObject::createInternal(const String& name)
+	HGameObject GameObject::createInternal(const String& name)
 	{
-		GameObjectPtr newObject = GameObjectPtr(new GameObject(name));
-		newObject->mThis = newObject;
+		HGameObject gameObject = HGameObject(new GameObject(name));
+		gameObject->mThisHandle = gameObject;
 
-		return newObject;
+		return gameObject;
 	}
 
 	void GameObject::destroy()
 	{
-		mIsDestroyed = true;
+		// Parent is our owner, so when his reference to us is removed, delete might be called.
+		// So make sure this is the last thing we do.
+		if(mParent != nullptr)
+		{
+			if(!mParent.isDestroyed())
+				mParent->removeChild(mThisHandle);
+		}
+
+		destroyInternal();
+	}
 
+	void GameObject::destroyInternal()
+	{
 		for(auto iter = mChildren.begin(); iter != mChildren.end(); ++iter)
-			(*iter)->destroy();
+			(*iter)->destroyInternal();
 
 		mChildren.clear();
 
@@ -52,15 +65,7 @@ namespace CamelotEngine
 
 		mComponents.clear();
 
-		// Parent is our owner, so when his reference to us is removed, delete might be called.
-		// So make sure this is the last thing we do.
-		if(!mParent.expired())
-		{
-			GameObjectPtr parentPtr = mParent.lock();
-
-			if(!parentPtr->isDestroyed())
-				parentPtr->removeChild(mThis.lock());
-		}
+		mThisHandle.releaseHeldObject();
 	}
 
 	/************************************************************************/
@@ -230,18 +235,16 @@ namespace CamelotEngine
 
 	void GameObject::updateWorldTfrm() const
 	{
-		if(!mParent.expired())
+		if(mParent != nullptr)
 		{
-			GameObjectPtr tempParentPtr = mParent.lock();
-
-			mCachedWorldTfrm = getLocalTfrm() * tempParentPtr->getWorldTfrm();
+			mCachedWorldTfrm = getLocalTfrm() * mParent->getWorldTfrm();
 
 			// Update orientation
-			const Quaternion& parentOrientation = tempParentPtr->getWorldRotation();
+			const Quaternion& parentOrientation = mParent->getWorldRotation();
 			mWorldRotation = parentOrientation * mRotation;
 
 			// Update scale
-			const Vector3& parentScale = tempParentPtr->getWorldScale();
+			const Vector3& parentScale = mParent->getWorldScale();
 			// Scale own position by parent scale, NB just combine
 			// as equivalent axes, no shearing
 			mWorldScale = parentScale * mScale;
@@ -250,7 +253,7 @@ namespace CamelotEngine
 			mWorldPosition = parentOrientation * (parentScale * mPosition);
 
 			// Add altered position vector to parents
-			mWorldPosition += tempParentPtr->getWorldPosition();
+			mWorldPosition += mParent->getWorldPosition();
 		}
 		else
 		{
@@ -275,28 +278,28 @@ namespace CamelotEngine
 	/* 								Hierarchy	                     		*/
 	/************************************************************************/
 
-	void GameObject::setParent(GameObjectPtr parent)
+	void GameObject::setParent(const HGameObject& parent)
 	{
-		if(parent == nullptr || parent->isDestroyed())
+		if(parent.isDestroyed())
 		{
 			CM_EXCEPT(InternalErrorException, 
-				"Parent is not allowed to be NULL or destroyed.");
+				"Trying to assign a GameObject parent that is destroyed.");
 		}
 
-		if(mParent.expired() || mParent.lock() != parent)
+		if(mParent == nullptr || mParent != parent)
 		{
-			if(!mParent.expired())
-				mParent.lock()->removeChild(mThis.lock());
+			if(mParent != nullptr)
+				mParent->removeChild(mThisHandle);
 
 			if(parent != nullptr)
-				parent->addChild(mThis.lock());
+				parent->addChild(mThisHandle);
 
 			mParent = parent;
 			markTfrmDirty();
 		}
 	}
 
-	GameObjectPtr GameObject::getChild(unsigned int idx) const
+	HGameObject GameObject::getChild(unsigned int idx) const
 	{
 		if(idx < 0 || idx >= mChildren.size())
 		{
@@ -307,7 +310,7 @@ namespace CamelotEngine
 		return mChildren[idx];
 	}
 
-	int GameObject::indexOfChild(const GameObjectPtr child) const
+	int GameObject::indexOfChild(const HGameObject& child) const
 	{
 		for(int i = 0; i < (int)mChildren.size(); i++)
 		{
@@ -318,12 +321,12 @@ namespace CamelotEngine
 		return -1;
 	}
 
-	void GameObject::addChild(GameObjectPtr object)
+	void GameObject::addChild(const HGameObject& object)
 	{
 		mChildren.push_back(object); 
 	}
 
-	void GameObject::removeChild(GameObjectPtr object)
+	void GameObject::removeChild(const HGameObject& object)
 	{
 		auto result = find(mChildren.begin(), mChildren.end(), object);
 

+ 0 - 5
CamelotCore/Source/CmGameObjectHandle.cpp

@@ -5,11 +5,6 @@
 namespace CamelotEngine
 {
 	GameObjectHandleBase::GameObjectHandleBase()
-		:mData(new GameObjectHandleData())
-	{ }
-
-	GameObjectHandleBase::GameObjectHandleBase(const std::shared_ptr<GameObjectHandleData>& data)
-		:mData(data)
 	{ }
 
 	void GameObjectHandleBase::throwIfDestroyed() const

+ 1 - 1
CamelotCore/Source/CmOverlay.cpp

@@ -3,7 +3,7 @@
 
 namespace CamelotEngine
 {
-	Overlay::Overlay(GameObjectPtr parent)
+	Overlay::Overlay(const HGameObject& parent)
 		:Component(parent)
 	{
 

+ 1 - 1
CamelotCore/Source/CmRenderable.cpp

@@ -3,7 +3,7 @@
 
 namespace CamelotEngine
 {
-	Renderable::Renderable(GameObjectPtr parent)
+	Renderable::Renderable(const HGameObject& parent)
 		:Component(parent)
 	{ }
 

+ 5 - 5
CamelotCore/Source/CmSceneManager.cpp

@@ -19,12 +19,12 @@ namespace CamelotEngine
 
 	void SceneManager::update()
 	{
-		stack<GameObjectPtr>::type todo;
+		stack<HGameObject>::type todo;
 		todo.push(mRootNode);
 
 		while(!todo.empty())
 		{
-			GameObjectPtr currentGO = todo.top();
+			HGameObject currentGO = todo.top();
 			todo.pop();
 			                  
 			vector<ComponentPtr>::type components = currentGO->getComponents();
@@ -45,12 +45,12 @@ namespace CamelotEngine
 
 		vector<RenderablePtr>::type renderables;
 
-		stack<GameObjectPtr>::type todo;
+		stack<HGameObject>::type todo;
 		todo.push(mRootNode);
 
 		while(!todo.empty())
 		{
-			GameObjectPtr currentGO = todo.top();
+			HGameObject currentGO = todo.top();
 			todo.pop();
 
 			RenderablePtr curRenderable = currentGO->getComponent<Renderable>();
@@ -64,7 +64,7 @@ namespace CamelotEngine
 		return renderables;
 	}
 
-	void SceneManager::registerNewGO(GameObjectPtr node) 
+	void SceneManager::registerNewGO(const HGameObject& node) 
 	{ 
 		if(mRootNode) // If root node is null, then this new node is the root node
 			node->setParent(mRootNode);