Преглед изворни кода

Fixed a bunch of issues with destroying of GameObjects (WIP)

Marko Pintera пре 13 година
родитељ
комит
7eadcafc4d

+ 4 - 4
CamelotClient/CamelotClient.cpp

@@ -64,7 +64,7 @@ int CALLBACK WinMain(
 	GameObjectHandle<DebugCamera> debugCamera = cameraGO->addComponent<DebugCamera>();
 
 	HGameObject testModelGO = GameObject::create("TestMesh");
-	HRenderable testRenderable = testModelGO->addComponent<Renderable>();
+	//HRenderable testRenderable = testModelGO->addComponent<Renderable>();
 
 	HGameObject testTextGO = GameObject::create("TestText");
 	GameObjectHandle<TestTextSprite> textSprite = testTextGO->addComponent<TestTextSprite>();
@@ -85,7 +85,7 @@ int CALLBACK WinMain(
 		font = Importer::instance().import("C:\\arial.ttf", fontImportOptions);
 	}
 
-	textSprite->setText(camera, "TESTfAV", font, 12);
+	//textSprite->setText(camera, "TESTfAV", font, 12);
 
 #if defined DX9
 	///////////////// HLSL 9 SHADERS //////////////////////////
@@ -269,8 +269,8 @@ int CALLBACK WinMain(
 
 	//_ASSERT(_CrtCheckMemory());
 
-	testRenderable->setMesh(dbgMeshRef);
-	testRenderable->setMaterial(testMaterial);
+	//testRenderable->setMesh(dbgMeshRef);
+	//testRenderable->setMaterial(testMaterial);
 
 	//// Set the new state for the flag
 	//_CrtSetDbgFlag( tmpFlag );

+ 1 - 1
CamelotClient/CmTestTextSprite.cpp

@@ -27,7 +27,7 @@ namespace CamelotEngine
 	{
 		mSkin = CM_NEW(GUISkin, GUIAlloc) GUISkin();
 
-		OverlayManager::instance().attachOverlay(camera.getInternalPtr(), this);		
+		OverlayManager::instance().attachOverlay(camera.get(), this);		
 
 		GUIElementStyle labelStyle;
 		labelStyle.font = font;

+ 3 - 0
CamelotCore/CamelotCore.vcxproj

@@ -177,6 +177,8 @@
   </ItemDefinitionGroup>
   <ItemGroup>
     <ClInclude Include="Include\CmGameObjectHandle.h" />
+    <ClInclude Include="Include\CmGameObjectREAL.h" />
+    <ClInclude Include="Include\CmGameObjectRTTI.h" />
     <ClInclude Include="Include\CmMemAllocCategories.h" />
     <ClInclude Include="Include\CmOverlay.h" />
     <ClInclude Include="Include\CmApplication.h" />
@@ -305,6 +307,7 @@
     <ClCompile Include="Include\CmMaterialManager.cpp" />
     <ClCompile Include="Source\CamelotRenderer.cpp" />
     <ClCompile Include="Source\CmGameObjectHandle.cpp" />
+    <ClCompile Include="Source\CmGameObjectREAL.cpp" />
     <ClCompile Include="Source\CmOverlay.cpp" />
     <ClCompile Include="Source\CmApplication.cpp" />
     <ClCompile Include="Source\CmBlendState.cpp" />

+ 9 - 0
CamelotCore/CamelotCore.vcxproj.filters

@@ -471,6 +471,12 @@
     <ClInclude Include="Include\CmGameObjectHandle.h">
       <Filter>Header Files\Scene</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmGameObjectREAL.h">
+      <Filter>Header Files\Scene</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmGameObjectRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CamelotRenderer.cpp">
@@ -731,5 +737,8 @@
     <ClCompile Include="Source\CmGameObjectHandle.cpp">
       <Filter>Source Files\Scene</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmGameObjectREAL.cpp">
+      <Filter>Source Files\Scene</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 2 - 10
CamelotCore/Include/CmComponent.h

@@ -1,11 +1,11 @@
 #pragma once
 
 #include "CmPrerequisites.h"
-#include "CmIReflectable.h"
+#include "CmGameObjectREAL.h"
 
 namespace CamelotEngine
 {
-	class CM_EXPORT Component : public IReflectable
+	class CM_EXPORT Component : public GameObjectREAL
 	{
 	public:
 		/**
@@ -29,15 +29,7 @@ namespace CamelotEngine
 
 		Component(const HGameObject& parent);
 
-		/**
-		 * @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();
-
 		HGameObject mParent;
-		bool mIsDestroyed;
 
 		/************************************************************************/
 		/* 								RTTI		                     		*/

+ 1 - 1
CamelotCore/Include/CmGUIWidget.h

@@ -10,7 +10,7 @@ namespace CamelotEngine
 	public:
 		virtual ~GUIWidget();
 
-		virtual void render(const CameraPtr& camera, DeferredRenderContextPtr& renderContext) const;
+		virtual void render(const Camera* camera, DeferredRenderContextPtr& renderContext) const;
 	protected:
 		friend class GameObject;
 

+ 10 - 1
CamelotCore/Include/CmGameObject.h

@@ -6,12 +6,13 @@
 #include "CmQuaternion.h"
 #include "CmRTTIType.h"
 #include "CmSceneManager.h"
+#include "CmGameObjectREAL.h"
 
 #include "boost/static_assert.hpp"
 
 namespace CamelotEngine
 {
-	class CM_EXPORT GameObject
+	class CM_EXPORT GameObject : public GameObjectREAL
 	{
 		friend class SceneManager;
 	public:
@@ -270,5 +271,13 @@ namespace CamelotEngine
 
 	private:
 		vector<HComponent>::type mComponents;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class GameObjectRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const;
 	};
 }

+ 12 - 20
CamelotCore/Include/CmGameObjectHandle.h

@@ -1,5 +1,7 @@
 #pragma once
 
+#include "CmGameObjectREAL.h"
+
 namespace CamelotEngine
 {
 	struct CM_EXPORT GameObjectHandleData
@@ -7,11 +9,11 @@ namespace CamelotEngine
 		GameObjectHandleData()
 		{ }
 
-		GameObjectHandleData(void* ptr)
+		GameObjectHandleData(GameObjectREAL* ptr)
 			:mPtr(ptr)
 		{ }
 
-		std::shared_ptr<void> mPtr;
+		std::shared_ptr<GameObjectREAL> mPtr;
 	};
 
 	/**
@@ -63,14 +65,6 @@ namespace CamelotEngine
 			mData = ptr.getHandleData();
 		}
 
-		/**
-		 * @brief	Creates a new handle. Internal use only. Don't call this manually.
-		 */
-		static GameObjectHandle<T> _create(T* ptr)
-		{
-			return GameObjectHandle<T>(ptr);
-		}
-
 		T* get() const 
 		{ 
 			throwIfDestroyed();
@@ -80,13 +74,6 @@ 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
 		{
@@ -101,15 +88,20 @@ namespace CamelotEngine
 		}
 
 	private:
-		friend T;
+		friend GameObject;
 
 		explicit GameObjectHandle(T* ptr)
 			:GameObjectHandleBase()
 		{
-			mData = std::shared_ptr<GameObjectHandleData>(new GameObjectHandleData(ptr));
+			mData = std::shared_ptr<GameObjectHandleData>(new GameObjectHandleData((GameObjectREAL*)ptr));
+		}
+
+		static GameObjectHandle<T> _create(T* ptr)
+		{
+			return GameObjectHandle<T>(ptr);
 		}
 
-		void releaseHeldObject()
+		void destroy()
 		{
 			mData->mPtr = nullptr;
 		}

+ 14 - 0
CamelotCore/Include/CmGameObjectREAL.h

@@ -0,0 +1,14 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+#include "CmIReflectable.h"
+
+namespace CamelotEngine
+{
+	class CM_EXPORT GameObjectREAL : public IReflectable
+	{
+	public:
+		virtual ~GameObjectREAL() 
+		{ }
+	};
+}

+ 35 - 0
CamelotCore/Include/CmGameObjectRTTI.h

@@ -0,0 +1,35 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+#include "CmRTTIType.h"
+#include "CmGameObject.h"
+
+namespace CamelotEngine
+{
+	class CM_EXPORT GameObjectRTTI : public RTTIType<GameObject, IReflectable, GameObjectRTTI>
+	{
+	private:
+
+	public:
+		GameObjectRTTI()
+		{
+
+		}
+
+		virtual const String& getRTTIName()
+		{
+			static String name = "GameObject";
+			return name;
+		}
+
+		virtual UINT32 getRTTIId()
+		{
+			return TID_GameObject;
+		}
+
+		virtual std::shared_ptr<IReflectable> newRTTIObject()
+		{
+			CM_EXCEPT(NotImplementedException, "This RTTI class is unfinished.");
+		}
+	};
+}

+ 1 - 1
CamelotCore/Include/CmOverlay.h

@@ -16,7 +16,7 @@ namespace CamelotEngine
 	public:
 		virtual ~Overlay();
 
-		virtual void render(const CameraPtr& camera, DeferredRenderContextPtr& renderContext) const = 0;
+		virtual void render(const Camera* camera, DeferredRenderContextPtr& renderContext) const = 0;
 
 	protected:
 		friend class GameObject;

+ 3 - 3
CamelotCore/Include/CmOverlayManager.h

@@ -16,10 +16,10 @@ namespace CamelotEngine
 	class CM_EXPORT OverlayManager : public Module<OverlayManager>
 	{
 	public:
-		void render(const CameraPtr& camera, DeferredRenderContextPtr& renderContext) const;
+		void render(const Camera* camera, DeferredRenderContextPtr& renderContext) const;
 
-		void attachOverlay(const CameraPtr& camera, const Overlay* overlay);
-		void detachOverlay(const CameraPtr& camera, const Overlay* overlay);
+		void attachOverlay(const Camera* camera, const Overlay* overlay);
+		void detachOverlay(const Camera* camera, const Overlay* overlay);
 		void detachOverlayFromAll(const Overlay* overlay);
 	private:
 		unordered_map<const Camera*, unordered_set<const Overlay*>::type>::type mOverlaysPerCamera;

+ 3 - 1
CamelotCore/Include/CmPrerequisites.h

@@ -151,6 +151,7 @@ namespace CamelotEngine {
 	struct FontData;
 	class TextSprite;
 	class SpriteTexture;
+	class GameObjectREAL;
 	// Asset import
 	class SpecificImporter;
 	class Importer;
@@ -290,7 +291,8 @@ namespace CamelotEngine
 		TID_STDMAP = 1055,
 		TID_FontImportOptions = 1056,
 		TID_FontData = 1057,
-		TID_IndexElementData = 1058
+		TID_IndexElementData = 1058,
+		TID_GameObject = 1059
 	};
 
 	/**

+ 9 - 9
CamelotCore/Source/CmApplication.cpp

@@ -83,15 +83,15 @@ namespace CamelotEngine
 		MaterialManager::startUp(CM_NEW(MaterialManager, GenAlloc) MaterialManager());
 		FontManager::startUp(CM_NEW(FontManager, GenAlloc) FontManager());
 
+		OverlayManager::startUp(CM_NEW(OverlayManager, GenAlloc) OverlayManager());
+		GUIMaterialManager::startUp(CM_NEW(GUIMaterialManager, GenAlloc) GUIMaterialManager());
+		GUIManager::startUp(CM_NEW(GUIManager, GenAlloc) GUIManager());
+
 		Importer::startUp(CM_NEW(Importer, GenAlloc) Importer());
 		loadPlugin("CamelotFreeImgImporter"); // TODO - Load this automatically somehow
 		loadPlugin("CamelotFBXImporter"); // TODO - Load this automatically somehow
 		loadPlugin("CamelotFontImporter"); // TODO - Load this automatically somehow
 
-		OverlayManager::startUp(CM_NEW(OverlayManager, GenAlloc) OverlayManager());
-		GUIMaterialManager::startUp(CM_NEW(GUIMaterialManager, GenAlloc) GUIMaterialManager());
-		GUIManager::startUp(CM_NEW(GUIManager, GenAlloc) GUIManager());
-
 		loadPlugin("CamelotOISInput"); // TODO - Load this automatically somehow
 	}
 
@@ -156,24 +156,24 @@ namespace CamelotEngine
 	{
 		mPrimaryRenderWindow = nullptr;
 
-		GUIManager::shutDown();
-		GUIMaterialManager::shutDown();
-		OverlayManager::shutDown();
-
 		Importer::shutDown();
 		FontManager::shutDown();
 		MaterialManager::shutDown();
 		MeshManager::shutDown();
 
 		SceneManager::shutDown();
+		GUIManager::shutDown();
+		GUIMaterialManager::shutDown();
+		OverlayManager::shutDown();
+
 		RendererManager::shutDown();
 		RenderSystem::shutDown();
 
 		HighLevelGpuProgramManager::shutDown();
 		Resources::shutDown();
 		CoreGpuObjectManager::shutDown(); // Must shut down before DynLibManager to ensure all objects are destroyed before unloading their libraries
-		DynLibManager::shutDown();
 		Input::shutDown();
+		DynLibManager::shutDown();
 		Time::shutDown();
 	}
 

+ 1 - 7
CamelotCore/Source/CmComponent.cpp

@@ -4,20 +4,14 @@
 namespace CamelotEngine
 {
 	Component::Component(const HGameObject& parent)
-		:mParent(parent), mIsDestroyed(false)
+		:mParent(parent)
 	{
 
 	}
 
 	Component::~Component()
 	{
-		if(!mIsDestroyed)
-			destroy();
-	}
 
-	void Component::destroy()
-	{
-		mIsDestroyed = true;
 	}
 
 	RTTITypeBase* Component::getRTTIStatic()

+ 1 - 1
CamelotCore/Source/CmGUIWidget.cpp

@@ -153,7 +153,7 @@ namespace CamelotEngine
 		}
 	}
 
-	void GUIWidget::render(const CameraPtr& camera, DeferredRenderContextPtr& renderContext) const
+	void GUIWidget::render(const Camera* camera, DeferredRenderContextPtr& renderContext) const
 	{
 		// Mesh is re-created every frame. There might be a better approach that only recreates it upon change,
 		// but for now it seems like too much hassle for something like GUI that is pretty dynamic anyway.

+ 16 - 3
CamelotCore/Source/CmGameObject.cpp

@@ -3,6 +3,7 @@
 #include "CmSceneManager.h"
 #include "CmException.h"
 #include "CmDebug.h"
+#include "CmGameObjectRTTI.h"
 
 namespace CamelotEngine
 {
@@ -61,11 +62,13 @@ namespace CamelotEngine
 		mChildren.clear();
 
 		for(auto iter = mComponents.begin(); iter != mComponents.end(); ++iter)
-			(*iter)->destroy();
+		{
+			(*iter).destroy();
+		}
 
 		mComponents.clear();
 
-		mThisHandle.releaseHeldObject();
+		mThisHandle.destroy();
 	}
 
 	/************************************************************************/
@@ -362,7 +365,7 @@ namespace CamelotEngine
 
 		if(iter != mComponents.end())
 		{
-			(*iter)->destroy();
+			(*iter).destroy();
 			mComponents.erase(iter);
 
 			gSceneManager().notifyComponentRemoved((*iter));
@@ -370,4 +373,14 @@ namespace CamelotEngine
 		else
 			LOGDBG("Trying to remove a component that doesn't exist on this GameObject.");
 	}
+
+	RTTITypeBase* GameObject::getRTTIStatic()
+	{
+		return GameObjectRTTI::instance();
+	}
+
+	RTTITypeBase* GameObject::getRTTI() const
+	{
+		return GameObject::getRTTIStatic();
+	}
 }

+ 1 - 0
CamelotCore/Source/CmGameObjectREAL.cpp

@@ -0,0 +1 @@
+#include "CmGameObjectREAL.h"

+ 6 - 6
CamelotCore/Source/CmOverlayManager.cpp

@@ -4,9 +4,9 @@
 
 namespace CamelotEngine
 {
-	void OverlayManager::render(const CameraPtr& camera, DeferredRenderContextPtr& renderContext) const
+	void OverlayManager::render(const Camera* camera, DeferredRenderContextPtr& renderContext) const
 	{
-		auto overlays = mOverlaysPerCamera.find(camera.get());
+		auto overlays = mOverlaysPerCamera.find(camera);
 
 		if(overlays == mOverlaysPerCamera.end())
 			return;
@@ -17,14 +17,14 @@ namespace CamelotEngine
 		}
 	}
 
-	void OverlayManager::attachOverlay(const CameraPtr& camera, const Overlay* overlay)
+	void OverlayManager::attachOverlay(const Camera* camera, const Overlay* overlay)
 	{
-		mOverlaysPerCamera[camera.get()].insert(overlay);
+		mOverlaysPerCamera[camera].insert(overlay);
 	}
 
-	void OverlayManager::detachOverlay(const CameraPtr& camera, const Overlay* overlay)
+	void OverlayManager::detachOverlay(const Camera* camera, const Overlay* overlay)
 	{
-		mOverlaysPerCamera[camera.get()].erase(overlay);
+		mOverlaysPerCamera[camera].erase(overlay);
 	}
 
 	void OverlayManager::detachOverlayFromAll(const Overlay* overlay)

+ 1 - 1
CamelotForwardRenderer/Source/CmForwardRenderer.cpp

@@ -96,7 +96,7 @@ namespace CamelotEngine
 		}
 
 		// Render overlays for this camera
-		OverlayManager::instance().render(camera.getInternalPtr(), renderContext);
+		OverlayManager::instance().render(camera.get(), renderContext);
 
 		renderContext->endFrame();
 

+ 3 - 2
CamelotOISInput/Source/CmOISPlugin.cpp

@@ -16,7 +16,8 @@ namespace CamelotEngine
 		// TODO - Window handles in Windows are 64 bits when compiled as x64, but OIS only accepts a 32bit value. Is this okay?
 		UINT32 windowId = (UINT32)gApplication().getAppWindowId();
 
-		InputHandlerOIS* inputHandler = CM_NEW(InputHandlerOIS, GenAlloc) InputHandlerOIS(windowId);
-		gInput().registerInputHandler(InputHandlerPtr(inputHandler, &MemAllocDeleter<InputHandlerOIS, GenAlloc>::deleter));
+		InputHandlerPtr inputHandler = InputHandlerPtr(CM_NEW(InputHandlerOIS, GenAlloc) InputHandlerOIS(windowId), &MemAllocDeleter<InputHandlerOIS, GenAlloc>::deleter);
+
+		gInput().registerInputHandler(inputHandler);
 	}
 }

+ 2 - 0
CamelotUtility/Include/CmIReflectable.h

@@ -11,6 +11,8 @@ namespace CamelotEngine
 	class CM_UTILITY_EXPORT IReflectable
 	{
 	public:
+		virtual ~IReflectable() {}
+
 		/**
 		 * @brief	Returns an interface you can use to access class Run Time Type Information.
 		 *

+ 25 - 0
TODO.txt

@@ -21,6 +21,27 @@ Figure out how to store texture references in a font?
 
 Move Debug to CamelotCore and add SetFillMode
 
+
+
+
+
+Rename GameObject -> SceneObject
+Rename GameObjectREAL -> GameObject
+
+IReflectable doesn't have a virtual destructor. When I add it the program crashes
+
+GameObjectREAL is IReflectable but doesn't have RTTI
+ - COmponentRTTI doesn't account its new parent is GameObjectREAL so change that
+
+Make GameObjectHandle hold a normal pointer instead of a shared one
+ - By its definition its guaranteed to have only one reference so there's no need for shared ptr
+
+getVisibleRederables iterates over all gameobjects and calls getType, which will return empty handle if none is found, which is expensive
+
+
+
+
+
 Add TextUtil class
  - Ability to calculate a size of a line (will need this if I want to add "..." to text that doesn't fit)
  - Maybe even move line and word classes to it
@@ -234,6 +255,10 @@ Low priority TODO:
     - I might need to add an exception thrown if user tries to use them
   - Structs aren't supported in GLSL for introspection reasons
  - Go through pixel formats and removed unused ones: L8, L16, A4L4, and many others
+ - Having shared_ptrs used in RenderSystem and CommandQueue can cause potential performance problems. Dozends of thousands of shared
+    pointers may be getting queued in command queue per frame, in a slightly more complex scene, which will most certainly cause performance problems
+    due to thread safety and atomics used by shared_ptr. However I still need some guarantee that objects queued in RenderSystem won't be destroyed
+	by the sim. thread.
 
 Optional TODO:
  - Need better handling for shader techniques. Some Materials are able to run on all renderers yet I can only specify one. This is problematic