Browse Source

Some more work on gameobjects and components

Marko Pintera 13 years ago
parent
commit
78926122ab

+ 3 - 0
CamelotRenderer/CamelotRenderer.vcxproj

@@ -135,6 +135,7 @@
     <ClInclude Include="Include\CmWindowEventUtilities.h" />
     <ClInclude Include="Include\CmResourceST.h" />
     <ClInclude Include="Include\CmGameObject.h" />
+    <ClInclude Include="Include\CmComponent.h" />
     <ClInclude Include="Include\stdafx.h" />
     <ClInclude Include="Include\targetver.h" />
   </ItemGroup>
@@ -165,6 +166,7 @@
     <ClCompile Include="Source\CmRenderWindow.cpp" />
     <ClCompile Include="Source\CmResource.cpp" />
     <ClCompile Include="Source\CmResources.cpp" />
+    <ClCompile Include="Source\CmSceneManager.cpp" />
     <ClCompile Include="Source\CmTexture.cpp" />
     <ClCompile Include="Source\CmTextureManager.cpp" />
     <ClCompile Include="Source\CmTextureState.cpp" />
@@ -172,6 +174,7 @@
     <ClCompile Include="Source\CmViewport.cpp" />
     <ClCompile Include="Source\CmWindowEventUtilities.cpp" />
     <ClCompile Include="Source\CmGameObject.cpp" />
+    <ClCompile Include="Source\CmComponent.cpp" />
     <ClCompile Include="Source\stdafx.cpp" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+ 9 - 0
CamelotRenderer/CamelotRenderer.vcxproj.filters

@@ -193,6 +193,9 @@
     <ClInclude Include="Include\CmGameObject.h">
       <Filter>Header Files\Scene</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmComponent.h">
+      <Filter>Header Files\Scene</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CamelotRenderer.cpp">
@@ -297,5 +300,11 @@
     <ClCompile Include="Source\CmGameObject.cpp">
       <Filter>Source Files\Scene</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmComponent.cpp">
+      <Filter>Source Files\Scene</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmSceneManager.cpp">
+      <Filter>Header Files\Scene</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 25 - 0
CamelotRenderer/Include/CmComponent.h

@@ -0,0 +1,25 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+
+namespace CamelotEngine
+{
+	class Component
+	{
+	private:
+		friend class GameObject;
+
+		Component(GameObjectPtr parent);
+		virtual ~Component();
+
+		/**
+		 * @brief	Destroys the Component and makes it unusable, without actually deleting it.
+		 * 			
+		 *			This is an internal method that should only get called by GameObject.
+		 */
+		void destroy();
+
+		GameObjectPtr mParent;
+		bool mIsDestroyed;
+	};
+}

+ 39 - 6
CamelotRenderer/Include/CmGameObject.h

@@ -5,6 +5,8 @@
 #include "CmVector3.h"
 #include "CmQuaternion.h"
 
+#include "boost/static_assert.hpp"
+
 namespace CamelotEngine
 {
 	class CM_EXPORT GameObject
@@ -13,6 +15,11 @@ namespace CamelotEngine
 		GameObject(const String& name);
 		~GameObject();
 
+		void destroy();
+
+	private:
+		bool mIsDestroyed;
+
 		/************************************************************************/
 		/* 								Transform	                     		*/
 		/************************************************************************/
@@ -59,14 +66,14 @@ namespace CamelotEngine
 		 *
 		 * @param [in]	parent	New parent.
 		 */
-		void setParent(GameObject* parent);
+		void setParent(GameObjectPtr parent);
 
 		/**
 		 * @brief	Gets the parent of this object.
 		 *
 		 * @return	Parent object, or nullptr if this GameObject is at root level.
 		 */
-		GameObject* getParent() const { return mParent; }
+		GameObjectPtr getParent() const { return mParent; }
 
 		/**
 		 * @brief	Gets a child of this item.
@@ -77,7 +84,7 @@ namespace CamelotEngine
 		 * 			
 		 * @throws ERR_INVALIDPARAMS If the index is out of range.
 		 */
-		GameObject* getChild(unsigned int idx) const;
+		GameObjectPtr getChild(unsigned int idx) const;
 
 		/**
 		 * @brief	Find the index of the specified child. Don't persist this value as
@@ -87,7 +94,7 @@ namespace CamelotEngine
 		 *
 		 * @return	The zero-based index of the found child, or -1 if no match was found.
 		 */
-		int indexOfChild(const GameObject* child) const;
+		int indexOfChild(const GameObjectPtr child) const;
 
 		/**
 		 * @brief	Gets the number of all child GameObjects.
@@ -95,8 +102,8 @@ namespace CamelotEngine
 		int getNumChildren() const { return mChildren.size(); }
 
 	private:
-		GameObject* mParent;
-		vector<GameObject*>::type mChildren;
+		GameObjectPtr mParent;
+		vector<GameObjectPtr>::type mChildren;
 
 		/**
 		 * @brief	Adds a child to the child array. This method doesn't check for null or duplicate values.
@@ -113,5 +120,31 @@ namespace CamelotEngine
 		 * @throws INTERNAL_ERROR If the provided child isn't a child of the current object.
 		 */
 		void removeChild(GameObject* object);
+
+		/************************************************************************/
+		/* 								Component	                     		*/
+		/************************************************************************/
+	public:
+		template <typename T>
+		std::shared_ptr<T> addComponent()
+		{
+			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::Component, T>::value), 
+				"Specified type is not a valid Component.");
+
+			std::shared_ptr<T> newComponent = std::shared_ptr<T>(new T(this));
+			mComponents.push_back(newComponent);
+
+			return newComponent;
+		}
+
+		/**
+		 * @brief	Removes the component from this GameObject, and deallocates it.
+		 *
+		 * @param [in]	component	The component to destroy.
+		 */
+		void destroyComponent(ComponentPtr component);
+
+	private:
+		vector<ComponentPtr>::type mComponents;
 	};
 }

+ 6 - 0
CamelotRenderer/Include/CmPrerequisites.h

@@ -102,6 +102,9 @@ namespace CamelotEngine {
 	// Resources
 	class Resource;
 	class Resources;
+	// Scene
+	class GameObject;
+	class Component;
 }
 
 /* Shared pointer typedefs*/
@@ -112,6 +115,9 @@ namespace CamelotEngine
 	typedef std::shared_ptr<HardwarePixelBuffer> HardwarePixelBufferPtr;
 	typedef std::shared_ptr<Texture> TexturePtr;
 	typedef std::shared_ptr<Resource> ResourcePtr;
+
+	typedef std::shared_ptr<Component> ComponentPtr;
+	typedef std::shared_ptr<GameObject> GameObjectPtr;
 }
 
 #endif // __OgrePrerequisites_H__

+ 22 - 0
CamelotRenderer/Source/CmComponent.cpp

@@ -0,0 +1,22 @@
+#include "CmComponent.h"
+
+namespace CamelotEngine
+{
+	Component::Component(GameObjectPtr parent)
+		:mParent(parent), mIsDestroyed(false)
+	{
+
+	}
+
+	Component::~Component()
+	{
+		if(!mIsDestroyed)
+			destroy();
+	}
+
+	void Component::destroy()
+	{
+		mIsDestroyed = true;
+		mParent = nullptr;
+	}
+}

+ 51 - 12
CamelotRenderer/Source/CmGameObject.cpp

@@ -1,5 +1,7 @@
 #include "CmGameObject.h"
+#include "CmComponent.h"
 #include "CmException.h"
+#include "CmDebug.h"
 
 namespace CamelotEngine
 {
@@ -8,13 +10,31 @@ namespace CamelotEngine
 		mCachedLocalTfrm(Matrix4::IDENTITY), mIsCachedLocalTfrmUpToDate(false),
 		mCachedWorldTfrm(Matrix4::IDENTITY), mIsCachedWorldTfrmUpToDate(false),
 		mCustomWorldTfrm(Matrix4::IDENTITY), mIsCustomTfrmModeActive(false),
-		mParent(nullptr)
+		mParent(nullptr), mIsDestroyed(false)
 	{ }
 
 	GameObject::~GameObject()
 	{
+		if(!mIsDestroyed)
+			destroy();
+	}
+
+	void GameObject::destroy()
+	{
+		mIsDestroyed = true;
+
 		if(mParent != nullptr)
 			mParent->removeChild(this);
+
+		for(auto iter = mChildren.begin(); iter != mChildren.end(); ++iter)
+			(*iter)->destroy();
+
+		mChildren.clear();
+
+		for(auto iter = mComponents.begin(); iter != mComponents.end(); ++iter)
+			(*iter)->destroy();
+
+		mComponents.clear();
 	}
 
 	/************************************************************************/
@@ -49,7 +69,7 @@ namespace CamelotEngine
 
 	const Matrix4& GameObject::getLocalTfrm()
 	{
-		if(!mIsCachedLocalTfrmUpToDate) // TODO - Low priority - This unnecessarily updates world transform as well
+		if(!mIsCachedLocalTfrmUpToDate)
 			updateLocalTfrm();
 
 		return mCachedLocalTfrm;
@@ -91,7 +111,7 @@ namespace CamelotEngine
 	/* 								Hierarchy	                     		*/
 	/************************************************************************/
 
-	void GameObject::setParent(GameObject* parent)
+	void GameObject::setParent(GameObjectPtr parent)
 	{
 		if(parent == nullptr)
 		{
@@ -112,7 +132,7 @@ namespace CamelotEngine
 		}
 	}
 
-	GameObject* GameObject::getChild(unsigned int idx) const
+	GameObjectPtr GameObject::getChild(unsigned int idx) const
 	{
 		if(idx < 0 || idx >= mChildren.size())
 		{
@@ -123,7 +143,7 @@ namespace CamelotEngine
 		return mChildren[idx];
 	}
 
-	int GameObject::indexOfChild(const GameObject* child) const
+	int GameObject::indexOfChild(const GameObjectPtr child) const
 	{
 		for(int i = 0; i < (int)mChildren.size(); i++)
 		{
@@ -136,19 +156,38 @@ namespace CamelotEngine
 
 	void GameObject::addChild(GameObject* object)
 	{
-		mChildren.push_back(object);
+		//mChildren.push_back(object); // TODO - Not implemented. I'm not sure what's the best way to handle "this" ptr and smart ptrs
 	}
 
 	void GameObject::removeChild(GameObject* object)
 	{
-		auto result = find(mChildren.begin(), mChildren.end(), object);
+		//auto result = find(mChildren.begin(), mChildren.end(), object);
+
+		//if(result != mChildren.end())
+		//	mChildren.erase(result);
+		//else
+		//{
+		//	CM_EXCEPT(InternalErrorException, 
+		//		"Trying to remove a child but it's not a child of the transform.");
+		//}
+	}
 
-		if(result != mChildren.end())
-			mChildren.erase(result);
-		else
+	void GameObject::destroyComponent(ComponentPtr component)
+	{
+		if(component == nullptr)
 		{
-			CM_EXCEPT(InternalErrorException, 
-				"Trying to remove a child but it's not a child of the transform.");
+			LOGDBG("Trying to remove a null component");
+			return;
+		}
+
+		auto iter = std::find(mComponents.begin(), mComponents.end(), component);
+
+		if(iter != mComponents.end())
+		{
+			(*iter)->destroy();
+			mComponents.erase(iter);
 		}
+		else
+			LOGDBG("Trying to remove a component that doesn't exist on this GameObject.");
 	}
 }

+ 0 - 0
CamelotRenderer/Source/CmSceneManager.cpp