Răsfoiți Sursa

Bugfix: Crash on shutdown when camera in scene

BearishSun 8 ani în urmă
părinte
comite
c57de7effa

+ 12 - 16
Source/BansheeCore/Components/BsCCamera.cpp

@@ -14,19 +14,15 @@ namespace bs
 		setName("Camera");
 	}
 
-	CCamera::CCamera(const HSceneObject& parent, SPtr<RenderTarget> target, float left, float top, float width, float height)
-		: Component(parent), mTarget(target), mLeft(left), mTop(top), mWidth(width), mHeight(height)
+	CCamera::CCamera(const HSceneObject& parent)
+		: Component(parent)
 	{
-		if(mTarget == nullptr)
-			mTarget = CoreApplication::instance().getPrimaryWindow();
-
 		setFlag(ComponentFlag::AlwaysRun, true);
 		setName("Camera");
 	}
 
 	CCamera::~CCamera()
 	{
-		mInternal->destroy();
 	}
 
 	ConvexVolume CCamera::getWorldFrustum() const
@@ -57,29 +53,29 @@ namespace bs
 		gSceneManager()._notifyMainCameraStateChanged(mInternal);
 	}
 
-	void CCamera::update() 
-	{
-
-	}
-
-	void CCamera::onInitialized()
+	void CCamera::_instantiate()
 	{
 		// If mInternal already exists this means this object was deserialized,
 		// so all we need to do is initialize it.
 		if (mInternal != nullptr)
 			mInternal->initialize();
 		else
-		{
-			mInternal = Camera::create(mTarget, mLeft, mTop, mWidth, mHeight);
-			mTarget = nullptr;
-		}
+			mInternal = Camera::create();
+
+		SPtr<RenderTarget> mainRT = CoreApplication::instance().getPrimaryWindow();
+		mInternal->getViewport()->setTarget(mainRT);
+	}
 
+	void CCamera::onInitialized()
+	{
 		gSceneManager()._bindActor(mInternal, SO());
 	}
 
 	void CCamera::onDestroyed()
 	{
 		gSceneManager()._unbindActor(mInternal);
+
+		mInternal->destroy();
 	}
 
 	RTTITypeBase* CCamera::getRTTIStatic()

+ 4 - 14
Source/BansheeCore/Components/BsCCamera.h

@@ -20,9 +20,7 @@ namespace bs
 	class BS_CORE_EXPORT BS_SCRIPT_EXPORT(m:Rendering,n:Camera) CCamera : public Component
 	{
 	public:
-		CCamera(const HSceneObject& parent, SPtr<RenderTarget> target = nullptr,
-			float left = 0.0f, float top = 0.0f, float width = 1.0f, float height = 1.0f);
-
+		CCamera(const HSceneObject& parent);
 		virtual ~CCamera();
 
 		/** @copydoc Camera::getViewport */
@@ -256,29 +254,21 @@ namespace bs
 
 		mutable SPtr<Camera> mInternal;
 
-		// Only valid during construction
-		SPtr<RenderTarget> mTarget;
-		float mLeft = 0.0f;
-		float mTop = 0.0f;
-		float mWidth = 1.0f;
-		float mHeight = 1.0f;
-
 		/************************************************************************/
 		/* 						COMPONENT OVERRIDES                      		*/
 		/************************************************************************/
 	protected:
 		friend class SceneObject;
 
+		/** @copydoc Component::_instantiate */
+		void _instantiate() override;
+
 		/** @copydoc Component::onInitialized */
 		void onInitialized() override;
 
 		/** @copydoc Component::onDestroyed */
 		void onDestroyed() override;
 
-	public:
-		/** @copydoc Component::update */
-		void update() override;
-
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/

+ 10 - 6
Source/BansheeCore/Components/BsCLight.cpp

@@ -22,10 +22,7 @@ namespace bs
 	}
 
 	CLight::~CLight()
-	{
-		if(mInternal != nullptr)
-			mInternal->destroy();
-	}
+	{ }
 
 	Sphere CLight::getBounds() const
 	{
@@ -42,8 +39,14 @@ namespace bs
 			mInternal->initialize();
 		else
 		{
-			mInternal = Light::create(mType, mColor, mIntensity,
-				mRange, mCastsShadows, mSpotAngle, mSpotFalloffAngle);
+			mInternal = Light::create(
+				mType,
+				mColor,
+				mIntensity,
+				mRange,
+				mCastsShadows,
+				mSpotAngle,
+				mSpotFalloffAngle);
 		}
 
 		gSceneManager()._bindActor(mInternal, sceneObject());
@@ -52,6 +55,7 @@ namespace bs
 	void CLight::onDestroyed()
 	{
 		gSceneManager()._unbindActor(mInternal);
+		mInternal->destroy();
 	}
 	
 	RTTITypeBase* CLight::getRTTIStatic()

+ 1 - 0
Source/BansheeCore/Components/BsCRenderable.cpp

@@ -103,6 +103,7 @@ namespace bs
 			mAnimation->_unregisterRenderable();
 
 		gSceneManager()._unbindActor(mInternal);
+		mInternal->destroy();
 	}
 
 	RTTITypeBase* CRenderable::getRTTIStatic()

+ 5 - 3
Source/BansheeCore/CoreThread/BsCoreObject.cpp

@@ -10,10 +10,10 @@ using namespace std::placeholders;
 namespace bs
 {
 	CoreObject::CoreObject(bool initializeOnCoreThread)
-		:mFlags(0), mCoreDirtyFlags(0), mInternalID(0)
+		: mFlags(initializeOnCoreThread ? CGO_INIT_ON_CORE_THREAD : 0)
+		, mCoreDirtyFlags(0)
+		, mInternalID(CoreObjectManager::instance().generateId())
 	{
-		mInternalID = CoreObjectManager::instance().registerObject(this);
-		mFlags = initializeOnCoreThread ? mFlags | CGO_INIT_ON_CORE_THREAD : mFlags;
 	}
 
 	CoreObject::~CoreObject() 
@@ -52,6 +52,7 @@ namespace bs
 
 	void CoreObject::initialize()
 	{
+		CoreObjectManager::instance().registerObject(this);
 		mCoreSpecific = createCore();
 
 		if (mCoreSpecific != nullptr)
@@ -76,6 +77,7 @@ namespace bs
 			}
 		}
 
+		mFlags |= CGO_INITIALIZED;
 		markDependenciesDirty();
 	}
 

+ 5 - 1
Source/BansheeCore/CoreThread/BsCoreObject.h

@@ -30,7 +30,8 @@ namespace bs
 		enum Flags
 		{
 			CGO_DESTROYED = 0x01, /**< Object has been destroyed and shouldn't be used. */
-			CGO_INIT_ON_CORE_THREAD = 0x02 /**< Object requires initialization on core thread. */
+			CGO_INIT_ON_CORE_THREAD = 0x02, /**< Object requires initialization on core thread. */
+			CGO_INITIALIZED = 0x04 /**< Object's initialize() method has been called. */
 		};
 
 	public:
@@ -53,6 +54,9 @@ namespace bs
 		 */
 		virtual void initialize();
 
+		/** Returns true if the object has been initialized. Non-initialized object should not be used. */
+		bool isInitialized() const { return (mFlags & CGO_INITIALIZED) != 0; }
+
 		/** Returns true if the object has been destroyed. Destroyed object should not be used. */
 		bool isDestroyed() const { return (mFlags & CGO_DESTROYED) != 0; }
 

+ 10 - 6
Source/BansheeCore/CoreThread/BsCoreObjectManager.cpp

@@ -32,18 +32,22 @@ namespace bs
 #endif
 	}
 
-	UINT64 CoreObjectManager::registerObject(CoreObject* object)
+	UINT64 CoreObjectManager::generateId()
 	{
-		assert(object != nullptr);
-
 		Lock lock(mObjectsMutex);
 
-		mObjects[mNextAvailableID] = object;
-		mDirtyObjects[mNextAvailableID] = { object, -1 };
-
 		return mNextAvailableID++;
 	}
 
+	void CoreObjectManager::registerObject(CoreObject* object)
+	{
+		Lock lock(mObjectsMutex);
+
+		UINT64 objId = object->getInternalID();
+		mObjects[objId] = object;
+		mDirtyObjects[objId] = { object, -1 };
+	}
+
 	void CoreObjectManager::unregisterObject(CoreObject* object)
 	{
 		assert(object != nullptr);

+ 4 - 1
Source/BansheeCore/CoreThread/BsCoreObjectManager.h

@@ -63,8 +63,11 @@ namespace bs
 		CoreObjectManager();
 		~CoreObjectManager();
 
+		/** Generates a new unique ID for a core object. */
+		UINT64 generateId();
+
 		/** Registers a new CoreObject notifying the manager the object	is created. */
-		UINT64 registerObject(CoreObject* object);
+		void registerObject(CoreObject* object);
 
 		/** Unregisters a CoreObject notifying the manager the object is destroyed. */
 		void unregisterObject(CoreObject* object);

+ 8 - 10
Source/BansheeCore/Renderer/BsCamera.cpp

@@ -671,23 +671,18 @@ namespace bs
 		return Vector3(0.0f, 0.0f, 0.0f);
 	}
 
-	Camera::Camera(SPtr<RenderTarget> target, float left, float top, float width, float height)
+	Camera::Camera()
 		:mMain(false)
-	{
-		if (target != nullptr)
-			target->blockUntilCoreInitialized();
-
-		mViewport = Viewport::create(target, left, top, width, height);
-	}
+	{ }
 
 	SPtr<ct::Camera> Camera::getCore() const
 	{
 		return std::static_pointer_cast<ct::Camera>(mCoreSpecific);
 	}
 
-	SPtr<Camera> Camera::create(SPtr<RenderTarget> target, float left, float top, float width, float height)
+	SPtr<Camera> Camera::create()
 	{
-		Camera* handler = new (bs_alloc<Camera>()) Camera(target, left, top, width, height);
+		Camera* handler = new (bs_alloc<Camera>()) Camera();
 		SPtr<Camera> handlerPtr = bs_core_ptr<Camera>(handler);
 		handlerPtr->_setThisPtr(handlerPtr);
 		handlerPtr->initialize();
@@ -715,6 +710,8 @@ namespace bs
 
 	void Camera::initialize()
 	{
+		mViewport = Viewport::create(nullptr);
+
 		CoreObject::initialize();
 
 		gSceneManager()._registerCamera(std::static_pointer_cast<Camera>(getThisPtr()));
@@ -722,7 +719,8 @@ namespace bs
 
 	void Camera::destroy()
 	{
-		gSceneManager()._unregisterCamera(std::static_pointer_cast<Camera>(getThisPtr()));
+		if(isInitialized())
+			gSceneManager()._unregisterCamera(std::static_pointer_cast<Camera>(getThisPtr()));
 
 		CoreObject::destroy();
 	}

+ 2 - 4
Source/BansheeCore/Renderer/BsCamera.h

@@ -466,8 +466,7 @@ namespace bs
 		SPtr<ct::Camera> getCore() const;
 
 		/**	Creates a new camera that renders to the specified portion of the provided render target. */
-		static SPtr<Camera> create(SPtr<RenderTarget> target = nullptr,
-			float left = 0.0f, float top = 0.0f, float width = 1.0f, float height = 1.0f);
+		static SPtr<Camera> create();
 
 		/** 
 		 * @name Internal
@@ -482,8 +481,7 @@ namespace bs
 
 		/** @} */
 	protected:
-		Camera(SPtr<RenderTarget> target = nullptr,
-			float left = 0.0f, float top = 0.0f, float width = 1.0f, float height = 1.0f);
+		Camera();
 
 		/** @copydoc CameraBase */
 		Rect2I getViewportRect() const override;

+ 3 - 0
Source/BansheeCore/Scene/BsPrefab.cpp

@@ -72,6 +72,9 @@ namespace bs
 		}
 
 		// Clone the hierarchy for internal storage
+		if (mRoot != nullptr)
+			mRoot->destroy(true);
+
 		mRoot = sceneObject->clone(false);
 		mRoot->mParent = nullptr;
 		mRoot->mLinkId = -1;

+ 2 - 1
Source/BansheeEditor/EditorWindow/BsEditorWindowBase.cpp

@@ -85,7 +85,8 @@ namespace bs
 		mRenderWindow = renderWindow;
 		mSceneObject = SceneObject::create("EditorWindow", SOF_Internal | SOF_Persistent | SOF_DontSave);
 
-		mCamera = mSceneObject->addComponent<CCamera>(renderWindow, 0.0f, 0.0f, 1.0f, 1.0f);
+		mCamera = mSceneObject->addComponent<CCamera>();
+		mCamera->getViewport()->setTarget(renderWindow);
 		mCamera->setNearClipDistance(5);
 		mCamera->setAspectRatio(1.0f);
 		mCamera->setLayers(0);

+ 4 - 2
Source/Examples/ExampleGettingStarted/Main.cpp

@@ -313,7 +313,8 @@ namespace bs
 
 		// Add a Camera component that will output whatever it sees into that window 
 		// (You could also use a render texture or another window you created).
-		sceneCamera = sceneCameraSO->addComponent<CCamera>(window);
+		sceneCamera = sceneCameraSO->addComponent<CCamera>();
+		sceneCamera->getViewport()->setTarget(window);
 
 		// Set up camera component properties
 
@@ -388,7 +389,8 @@ namespace bs
 		SPtr<RenderWindow> window = gApplication().getPrimaryWindow();
 
 		// First we want another camera that is responsible for rendering GUI
-		HCamera guiCamera = guiSO->addComponent<CCamera>(window);
+		HCamera guiCamera = guiSO->addComponent<CCamera>();
+		sceneCamera->getViewport()->setTarget(window);
 
 		// Notify the renderer that the camera will only be used for overlays (e.g. GUI) so it can optimize its usage
 		SPtr<RenderSettings> settings = guiCamera->getRenderSettings();

+ 2 - 1
Source/Examples/ExamplePhysicallyBasedShading/Main.cpp

@@ -317,7 +317,8 @@ namespace bs
 
 		// Add a Camera component that will output whatever it sees into that window 
 		// (You could also use a render texture or another window you created).
-		sceneCamera = sceneCameraSO->addComponent<CCamera>(window);
+		sceneCamera = sceneCameraSO->addComponent<CCamera>();
+		sceneCamera->getViewport()->setTarget(window);
 
 		// Set up camera component properties