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

Bugfix: Fixed a problem that sometimes caused managed components or resources to have their managed instances garbage collected, before the assembly refresh process was complete

BearishSun 7 лет назад
Родитель
Сommit
98771da99e

+ 6 - 13
Source/MBansheeEngine/Input/VirtualInput.cs

@@ -36,15 +36,8 @@ namespace BansheeEngine
         /// </summary>
         /// </summary>
         public static InputConfiguration KeyConfig
         public static InputConfiguration KeyConfig
         {
         {
-            get
-            {
-                return Internal_GetKeyConfig();
-            }
-
-            set
-            {
-                Internal_SetKeyConfig(value);
-            }
+            get { return Internal_GetKeyConfig(); }
+            set { Internal_SetKeyConfig(value); }
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -53,10 +46,10 @@ namespace BansheeEngine
         /// </summary>
         /// </summary>
         /// <param name="button">Virtual button to check.</param>
         /// <param name="button">Virtual button to check.</param>
         /// <param name="deviceIdx">Optional device index in case multiple input devices are available.</param>
         /// <param name="deviceIdx">Optional device index in case multiple input devices are available.</param>
-		public static bool IsButtonDown(VirtualButton button, int deviceIdx = 0)
-	    {
+        public static bool IsButtonDown(VirtualButton button, int deviceIdx = 0)
+        {
             return Internal_IsButtonDown(ref button, deviceIdx);
             return Internal_IsButtonDown(ref button, deviceIdx);
-	    }
+        }
 
 
         /// <summary>
         /// <summary>
         /// Checks if the physical button combination corresponding to the specified virtual button is being released this
         /// Checks if the physical button combination corresponding to the specified virtual button is being released this
@@ -141,7 +134,7 @@ namespace BansheeEngine
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern float Internal_GetAxisValue(ref VirtualAxis button, int deviceIdx);
         private static extern float Internal_GetAxisValue(ref VirtualAxis button, int deviceIdx);
-	};
+    };
 
 
     /** @} */
     /** @} */
 }
 }

+ 22 - 36
Source/SBansheeEngine/BsManagedComponent.cpp

@@ -33,21 +33,21 @@ namespace bs
 
 
 	MonoObject* ManagedComponent::getManagedInstance() const
 	MonoObject* ManagedComponent::getManagedInstance() const
 	{
 	{
-		if(mGCHandle != 0)
-			return MonoUtil::getObjectFromGCHandle(mGCHandle);
+		if(mOwner)
+			return mOwner->getManagedInstance();
 
 
 		return nullptr;
 		return nullptr;
 	}
 	}
 
 
-	ComponentBackupData ManagedComponent::backup(bool clearExisting)
+	RawBackupData ManagedComponent::backup(bool clearExisting)
 	{
 	{
-		ComponentBackupData backupData;
+		RawBackupData backupData;
 
 
 		// If type is not missing read data from actual managed instance, instead just 
 		// If type is not missing read data from actual managed instance, instead just 
 		// return the data we backed up before the type was lost
 		// return the data we backed up before the type was lost
 		if (!mMissingType)
 		if (!mMissingType)
 		{
 		{
-			MonoObject* instance = MonoUtil::getObjectFromGCHandle(mGCHandle);
+			MonoObject* instance = mOwner->getManagedInstance();
 			SPtr<ManagedSerializableObject> serializableObject = ManagedSerializableObject::createFromExisting(instance);
 			SPtr<ManagedSerializableObject> serializableObject = ManagedSerializableObject::createFromExisting(instance);
 
 
 			// Serialize the object information and its fields. We cannot just serialize the entire object because
 			// Serialize the object information and its fields. We cannot just serialize the entire object because
@@ -80,12 +80,6 @@ namespace bs
 
 
 		if (clearExisting)
 		if (clearExisting)
 		{
 		{
-			if (mGCHandle != 0)
-			{
-				MonoUtil::freeGCHandle(mGCHandle);
-				mGCHandle = 0;
-			}
-
 			mManagedClass = nullptr;
 			mManagedClass = nullptr;
 			mRuntimeType = nullptr;
 			mRuntimeType = nullptr;
 			mOnCreatedThunk = nullptr;
 			mOnCreatedThunk = nullptr;
@@ -101,11 +95,12 @@ namespace bs
 		return backupData;
 		return backupData;
 	}
 	}
 
 
-	void ManagedComponent::restore(MonoObject* instance, const ComponentBackupData& data, bool missingType)
+	void ManagedComponent::restore(const RawBackupData& data, bool missingType)
 	{
 	{
-		initialize(instance);
+		initialize(mOwner);
 		mObjInfo = nullptr;
 		mObjInfo = nullptr;
 
 
+		MonoObject* instance = mOwner->getManagedInstance();
 		if (instance != nullptr && data.data != nullptr)
 		if (instance != nullptr && data.data != nullptr)
 		{
 		{
 			MemorySerializer ms;
 			MemorySerializer ms;
@@ -131,15 +126,15 @@ namespace bs
 		mRequiresReset = true;
 		mRequiresReset = true;
 	}
 	}
 
 
-	void ManagedComponent::initialize(MonoObject* instance)
+	void ManagedComponent::initialize(ScriptManagedComponent* owner)
 	{
 	{
+		mOwner = owner;
 		mFullTypeName = mNamespace + "." + mTypeName;
 		mFullTypeName = mNamespace + "." + mTypeName;
 		
 		
+		MonoObject* instance = owner->getManagedInstance();
 		mManagedClass = nullptr;
 		mManagedClass = nullptr;
 		if (instance != nullptr)
 		if (instance != nullptr)
 		{
 		{
-			mGCHandle = MonoUtil::newGCHandle(instance, false);
-
 			::MonoClass* monoClass = MonoUtil::getClass(instance);
 			::MonoClass* monoClass = MonoUtil::getClass(instance);
 			mRuntimeType = MonoUtil::getType(monoClass);
 			mRuntimeType = MonoUtil::getType(monoClass);
 
 
@@ -256,12 +251,10 @@ namespace bs
 
 
 	bool ManagedComponent::calculateBounds(Bounds& bounds)
 	bool ManagedComponent::calculateBounds(Bounds& bounds)
 	{
 	{
-		MonoObject* instance;
+		MonoObject* instance = nullptr;
 		
 		
-		if(mGCHandle != 0)
-			instance = MonoUtil::getObjectFromGCHandle(mGCHandle);
-		else
-			instance = nullptr;
+		if(mOwner)
+			instance = mOwner->getManagedInstance();
 
 
 		if (instance != nullptr && mCalculateBoundsMethod != nullptr)
 		if (instance != nullptr && mCalculateBoundsMethod != nullptr)
 		{
 		{
@@ -288,7 +281,7 @@ namespace bs
 	{
 	{
 		if (mOnUpdateThunk != nullptr)
 		if (mOnUpdateThunk != nullptr)
 		{
 		{
-			MonoObject* instance = MonoUtil::getObjectFromGCHandle(mGCHandle);
+			MonoObject* instance = mOwner->getManagedInstance();
 
 
 			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
 			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
 			// for some extra speed.
 			// for some extra speed.
@@ -300,7 +293,7 @@ namespace bs
 	{
 	{
 		if (mRequiresReset && mOnResetThunk != nullptr)
 		if (mRequiresReset && mOnResetThunk != nullptr)
 		{
 		{
-			MonoObject* instance = MonoUtil::getObjectFromGCHandle(mGCHandle);
+			MonoObject* instance = mOwner->getManagedInstance();
 
 
 			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
 			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
 			// for some extra speed.
 			// for some extra speed.
@@ -318,15 +311,11 @@ namespace bs
 		if (!ScriptAssemblyManager::instance().getSerializableObjectInfo(mNamespace, mTypeName, mObjInfo))
 		if (!ScriptAssemblyManager::instance().getSerializableObjectInfo(mNamespace, mTypeName, mObjInfo))
 		{
 		{
 			instance = ScriptAssemblyManager::instance().getMissingComponentClass()->createInstance(true);
 			instance = ScriptAssemblyManager::instance().getMissingComponentClass()->createInstance(true);
-
-			initialize(instance);
 			mMissingType = true;
 			mMissingType = true;
 		}
 		}
 		else
 		else
 		{
 		{
 			instance = mObjInfo->mMonoClass->createInstance();
 			instance = mObjInfo->mMonoClass->createInstance();
-
-			initialize(instance);
 			mMissingType = false;
 			mMissingType = false;
 		}
 		}
 
 
@@ -351,7 +340,7 @@ namespace bs
 
 
 	void ManagedComponent::onCreated()
 	void ManagedComponent::onCreated()
 	{
 	{
-		MonoObject* instance = MonoUtil::getObjectFromGCHandle(mGCHandle);
+		MonoObject* instance = mOwner->getManagedInstance();
 
 
 		if (mSerializedObjectData != nullptr && !mMissingType)
 		if (mSerializedObjectData != nullptr && !mMissingType)
 		{
 		{
@@ -373,7 +362,7 @@ namespace bs
 	{
 	{
 		if (mOnInitializedThunk != nullptr)
 		if (mOnInitializedThunk != nullptr)
 		{
 		{
-			MonoObject* instance = MonoUtil::getObjectFromGCHandle(mGCHandle);
+			MonoObject* instance = mOwner->getManagedInstance();
 
 
 			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
 			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
 			// for some extra speed.
 			// for some extra speed.
@@ -387,22 +376,19 @@ namespace bs
 	{
 	{
 		if (mOnDestroyThunk != nullptr)
 		if (mOnDestroyThunk != nullptr)
 		{
 		{
-			MonoObject* instance = MonoUtil::getObjectFromGCHandle(mGCHandle);
+			MonoObject* instance = mOwner->getManagedInstance();
 
 
 			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
 			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
 			// for some extra speed.
 			// for some extra speed.
 			MonoUtil::invokeThunk(mOnDestroyThunk, instance);
 			MonoUtil::invokeThunk(mOnDestroyThunk, instance);
 		}
 		}
-
-		MonoUtil::freeGCHandle(mGCHandle);
-		mGCHandle = 0;
 	}
 	}
 
 
 	void ManagedComponent::onEnabled()
 	void ManagedComponent::onEnabled()
 	{
 	{
 		if (mOnEnabledThunk != nullptr)
 		if (mOnEnabledThunk != nullptr)
 		{
 		{
-			MonoObject* instance = MonoUtil::getObjectFromGCHandle(mGCHandle);
+			MonoObject* instance = mOwner->getManagedInstance();
 
 
 			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
 			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
 			// for some extra speed.
 			// for some extra speed.
@@ -414,7 +400,7 @@ namespace bs
 	{
 	{
 		if (mOnDisabledThunk != nullptr)
 		if (mOnDisabledThunk != nullptr)
 		{
 		{
-			MonoObject* instance = MonoUtil::getObjectFromGCHandle(mGCHandle);
+			MonoObject* instance = mOwner->getManagedInstance();
 
 
 			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
 			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
 			// for some extra speed.
 			// for some extra speed.
@@ -426,7 +412,7 @@ namespace bs
 	{
 	{
 		if(mOnTransformChangedThunk != nullptr)
 		if(mOnTransformChangedThunk != nullptr)
 		{
 		{
-			MonoObject* instance = MonoUtil::getObjectFromGCHandle(mGCHandle);
+			MonoObject* instance = mOwner->getManagedInstance();
 
 
 			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
 			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
 			// for some extra speed.
 			// for some extra speed.

+ 10 - 17
Source/SBansheeEngine/BsManagedComponent.h

@@ -4,6 +4,7 @@
 
 
 #include "BsScriptEnginePrerequisites.h"
 #include "BsScriptEnginePrerequisites.h"
 #include "Scene/BsComponent.h"
 #include "Scene/BsComponent.h"
+#include "BsScriptObject.h"
 
 
 namespace bs
 namespace bs
 {
 {
@@ -11,8 +12,6 @@ namespace bs
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
-	struct ComponentBackupData;
-
 	/**
 	/**
 	 * Component that internally wraps a Mono component object that can be of user-defined type. Acts as interop
 	 * Component that internally wraps a Mono component object that can be of user-defined type. Acts as interop
 	 * layer between native Component and a Mono user defined component type since managed types cannot simply derive
 	 * layer between native Component and a Mono user defined component type since managed types cannot simply derive
@@ -49,31 +48,32 @@ namespace bs
 		 * @return						An object containing the serialized component. You can provide this to restore()
 		 * @return						An object containing the serialized component. You can provide this to restore()
 		 *								method to re-create the original component.
 		 *								method to re-create the original component.
 		 */
 		 */
-		ComponentBackupData backup(bool clearExisting = true);
+		RawBackupData backup(bool clearExisting = true);
 
 
 		/**
 		/**
 		 * Restores a component from previously serialized data.
 		 * Restores a component from previously serialized data.
 		 *
 		 *
-		 * @param[in]	instance	New instance of the managed component. Must be of the valid component type or of 
-		 *							BansheeEngine.MissingComponent type if the original type is missing.
 		 * @param[in]	data		Serialized managed component data that will be used for initializing the new managed
 		 * @param[in]	data		Serialized managed component data that will be used for initializing the new managed
 		 *							instance.
 		 *							instance.
 		 * @param[in]	missingType	Is the component's type missing (can happen after assembly reload). If true then the
 		 * @param[in]	missingType	Is the component's type missing (can happen after assembly reload). If true then the
 		 *							serialized data will be stored internally until later date when user perhaps restores
 		 *							serialized data will be stored internally until later date when user perhaps restores
 		 *							the type with another refresh. @p instance must be null if this is true.
 		 *							the type with another refresh. @p instance must be null if this is true.
 		 */
 		 */
-		void restore(MonoObject* instance, const ComponentBackupData& data, bool missingType);
+		void restore(const RawBackupData& data, bool missingType);
 
 
 		/**	Triggers the managed OnReset callback. */
 		/**	Triggers the managed OnReset callback. */
 		void triggerOnReset();
 		void triggerOnReset();
 
 
 	private:
 	private:
+		friend class ScriptManagedComponent;
+
 		/**
 		/**
 		 * Finalizes construction of the object. Must be called before use or when the managed component instance changes.
 		 * Finalizes construction of the object. Must be called before use or when the managed component instance changes.
 		 *
 		 *
-		 * @param[in]	object	Managed component instance.
+		 * @param[in]	owner		Script class that handles interop between the native and managed code for this
+		 *							component.
 		 */
 		 */
-		void initialize(MonoObject* object);
+		void initialize(ScriptManagedComponent* owner);
 
 
 		typedef void(BS_THUNKCALL *OnCreatedThunkDef) (MonoObject*, MonoException**);
 		typedef void(BS_THUNKCALL *OnCreatedThunkDef) (MonoObject*, MonoException**);
 		typedef void(BS_THUNKCALL *OnInitializedThunkDef) (MonoObject*, MonoException**);
 		typedef void(BS_THUNKCALL *OnInitializedThunkDef) (MonoObject*, MonoException**);
@@ -86,7 +86,7 @@ namespace bs
 
 
 		MonoClass* mManagedClass = nullptr;
 		MonoClass* mManagedClass = nullptr;
 		MonoReflectionType* mRuntimeType = nullptr;
 		MonoReflectionType* mRuntimeType = nullptr;
-		uint32_t mGCHandle = 0;
+		ScriptManagedComponent* mOwner = nullptr;
 
 
 		String mNamespace;
 		String mNamespace;
 		String mTypeName;
 		String mTypeName;
@@ -160,12 +160,5 @@ namespace bs
 		ManagedComponent(); // Serialization only
 		ManagedComponent(); // Serialization only
 	};
 	};
 
 
-	/**	Contains serialized component data buffer. */
-	struct ComponentBackupData
-	{
-		UINT8* data;
-		UINT32 size;
-	};
-
 	/** @} */
 	/** @} */
-}
+}

+ 10 - 26
Source/SBansheeEngine/BsManagedResource.cpp

@@ -18,11 +18,11 @@
 namespace bs
 namespace bs
 {
 {
 	ManagedResource::ManagedResource()
 	ManagedResource::ManagedResource()
-		:Resource(false), mGCHandle(0)
+		:Resource(false)
 	{ }
 	{ }
 
 
 	ManagedResource::ManagedResource(MonoObject* managedInstance)
 	ManagedResource::ManagedResource(MonoObject* managedInstance)
-		:Resource(false), mGCHandle(0)
+		:Resource(false)
 	{
 	{
 		SPtr<ManagedResourceMetaData> metaData = bs_shared_ptr_new<ManagedResourceMetaData>();
 		SPtr<ManagedResourceMetaData> metaData = bs_shared_ptr_new<ManagedResourceMetaData>();
 		mMetaData = metaData;
 		mMetaData = metaData;
@@ -39,15 +39,15 @@ namespace bs
 
 
 	MonoObject* ManagedResource::getManagedInstance() const
 	MonoObject* ManagedResource::getManagedInstance() const
 	{
 	{
-		if(mGCHandle != 0)
-			return MonoUtil::getObjectFromGCHandle(mGCHandle);
+		if(mOwner)
+			return mOwner->getManagedInstance();
 		
 		
 		return nullptr;
 		return nullptr;
 	}
 	}
 
 
-	ResourceBackupData ManagedResource::backup(bool clearExisting)
+	ResourceBackupData ManagedResource::backup()
 	{
 	{
-		MonoObject* instance = MonoUtil::getObjectFromGCHandle(mGCHandle);
+		MonoObject* instance = mOwner->getManagedInstance();
 		SPtr<ManagedSerializableObject> serializableObject = ManagedSerializableObject::createFromExisting(instance);
 		SPtr<ManagedSerializableObject> serializableObject = ManagedSerializableObject::createFromExisting(instance);
 
 
 		ResourceBackupData backupData;
 		ResourceBackupData backupData;
@@ -64,24 +64,14 @@ namespace bs
 			backupData.data = nullptr;
 			backupData.data = nullptr;
 		}
 		}
 
 
-		if (clearExisting)
-		{
-			if (mGCHandle != 0)
-			{
-				MonoUtil::freeGCHandle(mGCHandle);
-				mGCHandle = 0;
-			}
-		}
-
 		return backupData;
 		return backupData;
 	}
 	}
 
 
-	void ManagedResource::restore(MonoObject* instance, const ResourceBackupData& data)
+	void ManagedResource::restore(const ResourceBackupData& data)
 	{
 	{
+		MonoObject* instance = mOwner->getManagedInstance();
 		if (instance != nullptr)
 		if (instance != nullptr)
 		{
 		{
-			mGCHandle = MonoUtil::newGCHandle(instance, false);
-
 			if (data.data != nullptr)
 			if (data.data != nullptr)
 			{
 			{
 				MemorySerializer ms;
 				MemorySerializer ms;
@@ -124,10 +114,9 @@ namespace bs
 
 
 	void ManagedResource::setHandle(MonoObject* object, const HManagedResource& myHandle)
 	void ManagedResource::setHandle(MonoObject* object, const HManagedResource& myHandle)
 	{
 	{
-		mGCHandle = MonoUtil::newGCHandle(object, false);
 		mMyHandle = myHandle.getWeak();
 		mMyHandle = myHandle.getWeak();
 
 
-		ScriptResourceManager::instance().createManagedScriptResource(myHandle, object);
+		mOwner = ScriptResourceManager::instance().createManagedScriptResource(myHandle, object);
 		ManagedResourceManager::instance().registerManagedResource(mMyHandle);
 		ManagedResourceManager::instance().registerManagedResource(mMyHandle);
 	}
 	}
 
 
@@ -135,12 +124,7 @@ namespace bs
 	{
 	{
 		Resource::destroy();
 		Resource::destroy();
 
 
-		if (mGCHandle != 0)
-		{
-			MonoUtil::freeGCHandle(mGCHandle);
-			mGCHandle = 0;
-		}
-
+		mOwner->_notifyDestroyed();
 		ManagedResourceManager::instance().unregisterManagedResource(mMyHandle);
 		ManagedResourceManager::instance().unregisterManagedResource(mMyHandle);
 	}
 	}
 
 

+ 4 - 9
Source/SBansheeEngine/BsManagedResource.h

@@ -23,23 +23,18 @@ namespace bs
 		/**
 		/**
 		 * Serializes the internal managed resource.
 		 * Serializes the internal managed resource.
 		 *
 		 *
-		 * @param[in]	clearExisting	Should the managed resource handle be released. (Will trigger a finalizer if this is
-		 *								the last reference to it)
 		 * @return						An object containing the serialized resource. You can provide this to restore()
 		 * @return						An object containing the serialized resource. You can provide this to restore()
 		 *								method to re-create the original resource.
 		 *								method to re-create the original resource.
 		 */
 		 */
-		ResourceBackupData backup(bool clearExisting = true);
+		ResourceBackupData backup();
 
 
 		/**
 		/**
 		 * Restores a resource from previously serialized data.
 		 * Restores a resource from previously serialized data.
 		 *
 		 *
-		 * @param[in]	instance	New instance of the managed resource. Must be of the valid resource type this object was
-		 *							originally created from. Can be null if the type cannot be found (can happen after an
-		 *							assembly refresh).
 		 * @param[in]	data		Serialized managed resource data that will be used for initializing the new managed
 		 * @param[in]	data		Serialized managed resource data that will be used for initializing the new managed
 		 *							instance.
 		 *							instance.
 		 */
 		 */
-		void restore(MonoObject* instance, const ResourceBackupData& data);
+		void restore(const ResourceBackupData& data);
 
 
 		/**
 		/**
 		 * Creates a new managed resource wrapper from an actual managed resource object. Caller must ensure the provided
 		 * Creates a new managed resource wrapper from an actual managed resource object. Caller must ensure the provided
@@ -69,8 +64,8 @@ namespace bs
 		/** @copydoc Resource::destroy */
 		/** @copydoc Resource::destroy */
 		void destroy() override;
 		void destroy() override;
 
 
-		UINT32 mGCHandle;
 		WeakResourceHandle<ManagedResource> mMyHandle;
 		WeakResourceHandle<ManagedResource> mMyHandle;
+		ScriptManagedResource* mOwner = nullptr;
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -78,7 +73,7 @@ namespace bs
 	public:
 	public:
 		friend class ManagedResourceRTTI;
 		friend class ManagedResourceRTTI;
 		static RTTITypeBase* getRTTIStatic();
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
+		RTTITypeBase* getRTTI() const override;
 
 
 	protected:
 	protected:
 		ManagedResource(); // Serialization only
 		ManagedResource(); // Serialization only

+ 2 - 2
Source/SBansheeEngine/BsScriptGameObjectManager.cpp

@@ -76,8 +76,8 @@ namespace bs
 	ScriptManagedComponent* ScriptGameObjectManager::createManagedScriptComponent(MonoObject* existingInstance,
 	ScriptManagedComponent* ScriptGameObjectManager::createManagedScriptComponent(MonoObject* existingInstance,
 																				  const HManagedComponent& component)
 																				  const HManagedComponent& component)
 	{
 	{
-		ScriptManagedComponent* nativeInstance = new (bs_alloc<ScriptManagedComponent>()) ScriptManagedComponent(existingInstance);
-		nativeInstance->setNativeHandle(component);
+		ScriptManagedComponent* nativeInstance = new (bs_alloc<ScriptManagedComponent>()) 
+			ScriptManagedComponent(existingInstance, component);
 
 
 		UINT64 instanceId = component->getInstanceId();
 		UINT64 instanceId = component->getInstanceId();
 		mScriptComponents[instanceId] = nativeInstance;
 		mScriptComponents[instanceId] = nativeInstance;

+ 1 - 1
Source/SBansheeEngine/BsScriptObjectManager.cpp

@@ -105,4 +105,4 @@ namespace bs
 
 
 		mFinalizedObjects[readQueueIdx].clear();
 		mFinalizedObjects[readQueueIdx].clear();
 	}
 	}
-}
+}

+ 14 - 9
Source/SBansheeEngine/Wrappers/BsScriptManagedComponent.cpp

@@ -18,13 +18,15 @@
 
 
 namespace bs
 namespace bs
 {
 {
-	ScriptManagedComponent::ScriptManagedComponent(MonoObject* instance)
-		:ScriptObject(instance), mTypeMissing(false)
+	ScriptManagedComponent::ScriptManagedComponent(MonoObject* instance, const HManagedComponent& component)
+		:ScriptObject(instance), mComponent(component), mTypeMissing(false)
 	{
 	{
 		assert(instance != nullptr);
 		assert(instance != nullptr);
 
 
 		MonoUtil::getClassName(instance, mNamespace, mType);
 		MonoUtil::getClassName(instance, mNamespace, mType);
-		mGCHandle = MonoUtil::newWeakGCHandle(instance);
+		mGCHandle = MonoUtil::newGCHandle(instance, false);
+
+		component->initialize(this);
 	}
 	}
 
 
 	void ScriptManagedComponent::initRuntimeData()
 	void ScriptManagedComponent::initRuntimeData()
@@ -85,13 +87,13 @@ namespace bs
 			instance = currentObjInfo->mMonoClass->createInstance(construct);
 			instance = currentObjInfo->mMonoClass->createInstance(construct);
 		}
 		}
 
 
-		mGCHandle = MonoUtil::newWeakGCHandle(instance);
+		mGCHandle = MonoUtil::newGCHandle(instance, false);
 		return instance;
 		return instance;
 	}
 	}
 
 
 	void ScriptManagedComponent::_clearManagedInstance()
 	void ScriptManagedComponent::_clearManagedInstance()
 	{
 	{
-		mGCHandle = 0;
+		freeManagedInstance();
 	}
 	}
 
 
 	ScriptObjectBackup ScriptManagedComponent::beginRefresh()
 	ScriptObjectBackup ScriptManagedComponent::beginRefresh()
@@ -111,10 +113,8 @@ namespace bs
 	{
 	{
 		HManagedComponent managedComponent = static_object_cast<ManagedComponent>(mComponent);
 		HManagedComponent managedComponent = static_object_cast<ManagedComponent>(mComponent);
 
 
-		ComponentBackupData componentBackup = any_cast<ComponentBackupData>(backupData.data);
-
-		MonoObject* instance = MonoUtil::getObjectFromGCHandle(mGCHandle);
-		managedComponent->restore(instance, componentBackup, mTypeMissing);
+		RawBackupData componentBackup = any_cast<RawBackupData>(backupData.data);
+		managedComponent->restore(componentBackup, mTypeMissing);
 	}
 	}
 
 
 	void ScriptManagedComponent::_onManagedInstanceDeleted(bool assemblyRefresh)
 	void ScriptManagedComponent::_onManagedInstanceDeleted(bool assemblyRefresh)
@@ -127,4 +127,9 @@ namespace bs
 		if (!assemblyRefresh || mComponent.isDestroyed(true))
 		if (!assemblyRefresh || mComponent.isDestroyed(true))
 			ScriptGameObjectManager::instance().destroyScriptComponent(this);
 			ScriptGameObjectManager::instance().destroyScriptComponent(this);
 	}
 	}
+
+	void ScriptManagedComponent::_notifyDestroyed()
+	{
+		freeManagedInstance();
+	}
 }
 }

+ 5 - 1
Source/SBansheeEngine/Wrappers/BsScriptManagedComponent.h

@@ -29,8 +29,9 @@ namespace bs
 
 
 	private:
 	private:
 		friend class ScriptGameObjectManager;
 		friend class ScriptGameObjectManager;
+		friend class ManagedComponent;
 
 
-		ScriptManagedComponent(MonoObject* instance);
+		ScriptManagedComponent(MonoObject* instance, const HManagedComponent& component);
 		
 		
 		/** @copydoc ScriptObjectBase::beginRefresh */
 		/** @copydoc ScriptObjectBase::beginRefresh */
 		ScriptObjectBackup beginRefresh() override;
 		ScriptObjectBackup beginRefresh() override;
@@ -47,6 +48,9 @@ namespace bs
 		/** @copydoc ScriptObjectBase::_onManagedInstanceDeleted */
 		/** @copydoc ScriptObjectBase::_onManagedInstanceDeleted */
 		void _onManagedInstanceDeleted(bool assemblyRefresh) override;
 		void _onManagedInstanceDeleted(bool assemblyRefresh) override;
 
 
+		/** @copydoc ScriptComponentBase::_notifyDestroyed */
+		void _notifyDestroyed() override;
+
 		HManagedComponent mComponent;
 		HManagedComponent mComponent;
 		String mNamespace;
 		String mNamespace;
 		String mType;
 		String mType;

+ 10 - 5
Source/SBansheeEngine/Wrappers/BsScriptManagedResource.cpp

@@ -20,7 +20,7 @@ namespace bs
 		BS_ASSERT(instance != nullptr);
 		BS_ASSERT(instance != nullptr);
 
 
 		MonoUtil::getClassName(instance, mNamespace, mType);
 		MonoUtil::getClassName(instance, mNamespace, mType);
-		mGCHandle = MonoUtil::newWeakGCHandle(instance);
+		mGCHandle = MonoUtil::newGCHandle(instance, false);
 	}
 	}
 
 
 	void ScriptManagedResource::initRuntimeData()
 	void ScriptManagedResource::initRuntimeData()
@@ -42,20 +42,20 @@ namespace bs
 			return nullptr;
 			return nullptr;
 
 
 		MonoObject* instance = currentObjInfo->mMonoClass->createInstance(construct);
 		MonoObject* instance = currentObjInfo->mMonoClass->createInstance(construct);
-		mGCHandle = MonoUtil::newWeakGCHandle(instance);
+		mGCHandle = MonoUtil::newGCHandle(instance, false);
 
 
 		return instance;
 		return instance;
 	}
 	}
 
 
 	void ScriptManagedResource::_clearManagedInstance()
 	void ScriptManagedResource::_clearManagedInstance()
 	{
 	{
-		mGCHandle = 0;
+		freeManagedInstance();
 	}
 	}
 
 
 	ScriptObjectBackup ScriptManagedResource::beginRefresh()
 	ScriptObjectBackup ScriptManagedResource::beginRefresh()
 	{
 	{
 		ScriptObjectBackup backupData;
 		ScriptObjectBackup backupData;
-		backupData.data = mResource->backup(true);
+		backupData.data = mResource->backup();
 
 
 		return backupData;
 		return backupData;
 	}
 	}
@@ -65,7 +65,7 @@ namespace bs
 		MonoObject* instance = MonoUtil::getObjectFromGCHandle(mGCHandle);
 		MonoObject* instance = MonoUtil::getObjectFromGCHandle(mGCHandle);
 
 
 		ResourceBackupData resourceBackup = any_cast<ResourceBackupData>(backupData.data);
 		ResourceBackupData resourceBackup = any_cast<ResourceBackupData>(backupData.data);
-		mResource->restore(instance, resourceBackup);
+		mResource->restore(resourceBackup);
 
 
 		// If we could not find resource type after refresh, treat it as if it was destroyed
 		// If we could not find resource type after refresh, treat it as if it was destroyed
 		if (instance == nullptr)
 		if (instance == nullptr)
@@ -89,6 +89,11 @@ namespace bs
 		}
 		}
 	}
 	}
 
 
+	void ScriptManagedResource::_notifyDestroyed()
+	{
+		freeManagedInstance();
+	}
+
 	void ScriptManagedResource::setResource(const HResource& resource)
 	void ScriptManagedResource::setResource(const HResource& resource)
 	{
 	{
 		mResource = static_resource_cast<ManagedResource>(resource);
 		mResource = static_resource_cast<ManagedResource>(resource);

+ 4 - 0
Source/SBansheeEngine/Wrappers/BsScriptManagedResource.h

@@ -30,6 +30,7 @@ namespace bs
 		const HManagedResource& getHandle() const { return mResource; }
 		const HManagedResource& getHandle() const { return mResource; }
 	private:
 	private:
 		friend class ScriptResourceManager;
 		friend class ScriptResourceManager;
+		friend class ManagedResource;
 
 
 		/** @copydoc ScriptObjectBase::beginRefresh */
 		/** @copydoc ScriptObjectBase::beginRefresh */
 		ScriptObjectBackup beginRefresh() override;
 		ScriptObjectBackup beginRefresh() override;
@@ -46,6 +47,9 @@ namespace bs
 		/** @copydoc ScriptObjectBase::_onManagedInstanceDeleted */
 		/** @copydoc ScriptObjectBase::_onManagedInstanceDeleted */
 		void _onManagedInstanceDeleted(bool assemblyRefresh) override;
 		void _onManagedInstanceDeleted(bool assemblyRefresh) override;
 
 
+		/** Called by the owned managed resource when it is destroyed. */
+		void _notifyDestroyed();
+
 		HManagedResource mResource;
 		HManagedResource mResource;
 		String mNamespace;
 		String mNamespace;
 		String mType;
 		String mType;