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

Assembly refresh (WIP - Does not run)

Marko Pintera 11 лет назад
Родитель
Сommit
3aa329733b
76 измененных файлов с 1899 добавлено и 1025 удалено
  1. 5 0
      BansheeEditor/Include/BsEditorWidgetManager.h
  2. 3 0
      BansheeEditor/Include/BsGizmoManager.h
  3. 5 0
      BansheeEditor/Source/BsEditorWidgetManager.cpp
  4. 6 5
      BansheeMono/Include/BsMonoAssembly.h
  5. 25 2
      BansheeMono/Include/BsMonoManager.h
  6. 12 8
      BansheeMono/Source/BsMonoAssembly.cpp
  7. 86 36
      BansheeMono/Source/BsMonoManager.cpp
  8. 1 1
      MBansheeEditor/EditorWindow.cs
  9. 28 7
      MBansheeEditor/Scene/Gizmos.cs
  10. 1 1
      MBansheeEditor/Scene/SceneCamera.cs
  11. 3 0
      MBansheeEditor/Scene/SceneWindow.cs
  12. 52 14
      MBansheeEngine/Camera.cs
  13. 4 0
      SBansheeEditor/Include/BsEditorScriptManager.h
  14. 23 7
      SBansheeEditor/Include/BsScriptEditorWindow.h
  15. 4 9
      SBansheeEditor/Include/BsScriptGizmoManager.h
  16. 2 0
      SBansheeEditor/Include/BsScriptGizmos.h
  17. 4 8
      SBansheeEditor/Include/BsScriptHandleManager.h
  18. 23 10
      SBansheeEditor/Source/BsEditorScriptManager.cpp
  19. 2 2
      SBansheeEditor/Source/BsGUIGameObjectField.cpp
  20. 3 3
      SBansheeEditor/Source/BsGUIResourceField.cpp
  21. 139 32
      SBansheeEditor/Source/BsScriptEditorWindow.cpp
  22. 32 79
      SBansheeEditor/Source/BsScriptGizmoManager.cpp
  23. 12 0
      SBansheeEditor/Source/BsScriptGizmos.cpp
  24. 44 74
      SBansheeEditor/Source/BsScriptHandleManager.cpp
  25. 22 1
      SBansheeEngine/Include/BsManagedComponent.h
  26. 1 7
      SBansheeEngine/Include/BsManagedComponentRTTI.h
  27. 17 0
      SBansheeEngine/Include/BsManagedResource.h
  28. 1 1
      SBansheeEngine/Include/BsManagedSerializableArrayRTTI.h
  29. 1 1
      SBansheeEngine/Include/BsManagedSerializableDictionaryRTTI.h
  30. 1 1
      SBansheeEngine/Include/BsManagedSerializableListRTTI.h
  31. 7 2
      SBansheeEngine/Include/BsManagedSerializableObject.h
  32. 23 0
      SBansheeEngine/Include/BsManagedSerializableObjectData.h
  33. 56 0
      SBansheeEngine/Include/BsManagedSerializableObjectDataRTTI.h
  34. 1 1
      SBansheeEngine/Include/BsManagedSerializableObjectRTTI.h
  35. 58 57
      SBansheeEngine/Include/BsScriptAssemblyManager.h
  36. 6 0
      SBansheeEngine/Include/BsScriptComponent.h
  37. 5 2
      SBansheeEngine/Include/BsScriptEnginePrerequisites.h
  38. 8 4
      SBansheeEngine/Include/BsScriptGameObject.h
  39. 13 2
      SBansheeEngine/Include/BsScriptGameObjectManager.h
  40. 5 0
      SBansheeEngine/Include/BsScriptManagedResource.h
  41. 49 1
      SBansheeEngine/Include/BsScriptObject.h
  42. 22 0
      SBansheeEngine/Include/BsScriptObjectManager.h
  43. 7 4
      SBansheeEngine/Include/BsScriptResource.h
  44. 0 3
      SBansheeEngine/Include/BsScriptResourceManager.h
  45. 7 2
      SBansheeEngine/SBansheeEngine.vcxproj
  46. 21 6
      SBansheeEngine/SBansheeEngine.vcxproj.filters
  47. 107 11
      SBansheeEngine/Source/BsManagedComponent.cpp
  48. 70 0
      SBansheeEngine/Source/BsManagedResource.cpp
  49. 4 4
      SBansheeEngine/Source/BsManagedSerializableArray.cpp
  50. 2 2
      SBansheeEngine/Source/BsManagedSerializableDictionary.cpp
  51. 2 2
      SBansheeEngine/Source/BsManagedSerializableList.cpp
  52. 55 27
      SBansheeEngine/Source/BsManagedSerializableObject.cpp
  53. 15 0
      SBansheeEngine/Source/BsManagedSerializableObjectData.cpp
  54. 10 10
      SBansheeEngine/Source/BsManagedSerializableObjectInfo.cpp
  55. 481 470
      SBansheeEngine/Source/BsScriptAssemblyManager.cpp
  56. 41 2
      SBansheeEngine/Source/BsScriptComponent.cpp
  57. 7 4
      SBansheeEngine/Source/BsScriptEnginePlugin.cpp
  58. 3 1
      SBansheeEngine/Source/BsScriptFont.cpp
  59. 22 0
      SBansheeEngine/Source/BsScriptGameObject.cpp
  60. 40 14
      SBansheeEngine/Source/BsScriptGameObjectManager.cpp
  61. 49 8
      SBansheeEngine/Source/BsScriptManagedResource.cpp
  62. 25 1
      SBansheeEngine/Source/BsScriptObject.cpp
  63. 1 0
      SBansheeEngine/Source/BsScriptObjectImpl.cpp
  64. 49 0
      SBansheeEngine/Source/BsScriptObjectManager.cpp
  65. 22 0
      SBansheeEngine/Source/BsScriptResource.cpp
  66. 11 22
      SBansheeEngine/Source/BsScriptResourceManager.cpp
  67. 3 1
      SBansheeEngine/Source/BsScriptSceneObject.cpp
  68. 1 1
      SBansheeEngine/Source/BsScriptSerializableArray.cpp
  69. 1 1
      SBansheeEngine/Source/BsScriptSerializableDictionary.cpp
  70. 1 1
      SBansheeEngine/Source/BsScriptSerializableList.cpp
  71. 2 2
      SBansheeEngine/Source/BsScriptSerializableObject.cpp
  72. 3 1
      SBansheeEngine/Source/BsScriptSpriteTexture.cpp
  73. 3 1
      SBansheeEngine/Source/BsScriptTexture2D.cpp
  74. 3 1
      SBansheeEngine/Source/BsScriptTexture3D.cpp
  75. 3 1
      SBansheeEngine/Source/BsScriptTextureCube.cpp
  76. 13 44
      TODO.txt

+ 5 - 0
BansheeEditor/Include/BsEditorWidgetManager.h

@@ -26,6 +26,11 @@ namespace BansheeEngine
 		 */
 		void registerWidget(const String& name, std::function<EditorWidgetBase*(EditorWidgetContainer&)> createCallback);
 
+		/**
+		 * @brief	Unregisters a widget so it may no longer be opened using this manager.
+		 */
+		void unregisterWidget(const String& name);
+
 		/**
 		 * @brief	Creates a widget with the given name. If widget is already created it returns the existing instance.
 		 * 			Widget is opened in a new window.

+ 3 - 0
BansheeEditor/Include/BsGizmoManager.h

@@ -24,6 +24,9 @@ namespace BansheeEngine
 		void setTransform(const Matrix4& transform);
 		void setPickable(bool pickable) { mPickable = pickable; }
 
+		Color getColor() const { return mColor; }
+		Matrix4 getTransform() const { return mTransform; }
+
 		void drawCube(const Vector3& position, const Vector3& extents);
 		void drawSphere(const Vector3& position, float radius);
 		void drawWireCube(const Vector3& position, const Vector3& extents);

+ 5 - 0
BansheeEditor/Source/BsEditorWidgetManager.cpp

@@ -55,6 +55,11 @@ namespace BansheeEngine
 		mCreateCallbacks[name] = createCallback;
 	}
 
+	void EditorWidgetManager::unregisterWidget(const String& name)
+	{
+		mCreateCallbacks.erase(name);
+	}
+
 	EditorWidgetBase* EditorWidgetManager::open(const String& name)
 	{
 		auto iterFind = mActiveWidgets.find(name);

+ 6 - 5
BansheeMono/Include/BsMonoAssembly.h

@@ -69,20 +69,20 @@ namespace BansheeEngine
 	private:
 		friend class MonoManager;
 
-		MonoAssembly();
+		MonoAssembly(const String& path, const String& name);
 
 		/**
-		 * @brief	Loads an assembly from the specified path.
+		 * @brief	Loads an assembly into the specified domain.
 		 */
-		void load(MonoDomain* domain, const String& path, const String& name);
+		void load(MonoDomain* domain);
 
 		/**
-		 * @brief	Loads an assembly from an internal mono image.
+		 * @brief	Initializes an assembly from an internal mono image.
 		 *
 		 * @note	Normally used for assemblies that were already loaded by the managed runtime
 		 *			as dependencies.
 		 */
-		void loadFromImage(MonoImage* image, const String& name);
+		void loadFromImage(MonoImage* image);
 
 		/**
 		 * @brief	Unloads the assembly and all the types associated with it.
@@ -99,6 +99,7 @@ namespace BansheeEngine
 		bool isGenericClass(const String& name) const;
 
 		String mName;
+		String mPath;
 		MonoImage* mMonoImage;
 		::MonoAssembly* mMonoAssembly;
 		bool mIsLoaded;

+ 25 - 2
BansheeMono/Include/BsMonoManager.h

@@ -73,15 +73,35 @@ namespace BansheeEngine
 		 */
 		MonoAssembly* getAssembly(const String& name) const;
 
+		/**
+		 * @brief	Unloads the active domain all script assemblies are loaded in
+		 *			and destroys any managed objects associated with it.
+		 */
+		void unloadScriptDomain();
+
+		/**
+		 * @brief	Loads a new script domain. If another domain already exists it will be unloaded. This will also
+		 *			restore any previously loaded assemblies.
+		 */
+		void loadScriptDomain();
+
 		/**
 		 * @brief	Registers a new script type. This should be done before any assembly loading is done.
 		 *			Upon assembly load these script types will be initialized with necessary information about their
 		 *			managed counterparts.
 		 */
 		static void registerScriptType(ScriptMeta* metaData);
+
+		/**
+		 * @brief	Triggered right after a domain was reloaded. This signals the outside world that they should
+		 *			update any kept Mono references as the old ones will no longer be valid.
+		 */
+		Event<void()> onDomainReload;
 	private:
-		static const String MONO_LIB_DIR;
-		static const String MONO_ETC_DIR;
+		/**
+		 * @brief	Initializes a previous loaded assembly.
+		 */
+		void initializeAssembly(MonoAssembly& assembly);
 
 		/**
 		 * @brief	Returns a list of all types that will be initializes with their assembly gets loaded.
@@ -92,6 +112,9 @@ namespace BansheeEngine
 			return mTypesToInitialize;
 		}
 
+		static const String MONO_LIB_DIR;
+		static const String MONO_ETC_DIR;
+
 		UnorderedMap<String, MonoAssembly*> mAssemblies;
 		MonoDomain* mScriptDomain;
 		MonoDomain* mRootDomain;

+ 12 - 8
BansheeMono/Source/BsMonoAssembly.cpp

@@ -33,8 +33,9 @@ namespace BansheeEngine
 
 	}
 
-	MonoAssembly::MonoAssembly()
-		:mIsLoaded(false), mMonoImage(nullptr), mMonoAssembly(nullptr), mIsDependency(false), mHaveCachedClassList(false)
+	MonoAssembly::MonoAssembly(const String& path, const String& name)
+		:mIsLoaded(false), mMonoImage(nullptr), mMonoAssembly(nullptr), mIsDependency(false), mHaveCachedClassList(false),
+		mPath(path), mName(name)
 	{
 
 	}
@@ -44,15 +45,17 @@ namespace BansheeEngine
 		unload();
 	}
 
-	void MonoAssembly::load(MonoDomain* domain, const String& path, const String& name)
+	void MonoAssembly::load(MonoDomain* domain)
 	{
-		::MonoAssembly* monoAssembly = mono_domain_assembly_open(domain, path.c_str());
+		if (mIsLoaded)
+			unload();
+
+		::MonoAssembly* monoAssembly = mono_domain_assembly_open(domain, mPath.c_str());
 		if(monoAssembly == nullptr)
 		{
-			BS_EXCEPT(InvalidParametersException, "Cannot load Mono assembly: " + path);
+			BS_EXCEPT(InvalidParametersException, "Cannot load Mono assembly: " + mPath);
 		}
 
-		mName = name;
 		mMonoAssembly = monoAssembly;
 		mMonoImage = mono_assembly_get_image(mMonoAssembly);
 		if(mMonoImage == nullptr)
@@ -66,7 +69,7 @@ namespace BansheeEngine
 		mIsDependency = false;
 	}
 
-	void MonoAssembly::loadFromImage(MonoImage* image, const String& name)
+	void MonoAssembly::loadFromImage(MonoImage* image)
 	{
 		::MonoAssembly* monoAssembly = mono_image_get_assembly(image);
 		if(monoAssembly == nullptr)
@@ -74,7 +77,6 @@ namespace BansheeEngine
 			BS_EXCEPT(InvalidParametersException, "Cannot get assembly from image.");
 		}
 
-		mName = name;
 		mMonoAssembly = monoAssembly;
 		mMonoImage = image;
 
@@ -92,6 +94,7 @@ namespace BansheeEngine
 
 		mClasses.clear();
 		mClassesByRaw.clear();
+		mCachedClassList.clear();
 
 		if(mMonoImage != nullptr && !mIsDependency)
 		{
@@ -101,6 +104,7 @@ namespace BansheeEngine
 		}
 
 		mIsLoaded = false;
+		mIsDependency = false;
 		mMonoAssembly = nullptr;
 		mHaveCachedClassList = false;
 	}

+ 86 - 36
BansheeMono/Source/BsMonoManager.cpp

@@ -41,19 +41,7 @@ namespace BansheeEngine
 
 		mAssemblies.clear();
 
-		if (mScriptDomain != nullptr)
-		{
-			mono_domain_set(mono_get_root_domain(), false);
-			mono_domain_finalize(mScriptDomain, 2000);
-			
-			MonoObject* exception = nullptr;
-			mono_domain_try_unload(mScriptDomain, &exception);
-
-			if (exception != nullptr)
-				MonoUtil::throwIfException(exception);
-
-			mScriptDomain = nullptr;
-		}
+		unloadScriptDomain();
 
 		if (mRootDomain != nullptr)
 		{
@@ -84,23 +72,39 @@ namespace BansheeEngine
 		}
 		else
 		{
-			assembly = new (bs_alloc<MonoAssembly>()) MonoAssembly();
+			assembly = new (bs_alloc<MonoAssembly>()) MonoAssembly(path, name);
 			mAssemblies[name] = assembly;
 		}
 		
-		if(!assembly->mIsLoaded)
+		initializeAssembly(*assembly);
+
+		return *assembly;
+	}
+
+	void MonoManager::unloadAssembly(MonoAssembly& assembly)
+	{
+		::MonoAssembly* monoAssembly = assembly.mMonoAssembly;
+		assembly.unload();
+
+		if(monoAssembly)
+			mono_assembly_close(monoAssembly);
+	}
+
+	void MonoManager::initializeAssembly(MonoAssembly& assembly)
+	{
+		if (!assembly.mIsLoaded)
 		{
-			assembly->load(mScriptDomain, path, name);
+			assembly.load(mScriptDomain);
 
 			// Fully initialize all types that use this assembly
-			Vector<ScriptMeta*>& mTypeMetas = getTypesToInitialize()[name];
-			for(auto& meta : mTypeMetas)
+			Vector<ScriptMeta*>& mTypeMetas = getTypesToInitialize()[assembly.mName];
+			for (auto& meta : mTypeMetas)
 			{
-				meta->scriptClass = assembly->getClass(meta->ns, meta->name);
-				if(meta->scriptClass == nullptr)
+				meta->scriptClass = assembly.getClass(meta->ns, meta->name);
+				if (meta->scriptClass == nullptr)
 					BS_EXCEPT(InvalidParametersException, "Unable to find class of type: \"" + meta->ns + "::" + meta->name + "\"");
 
-				if(meta->scriptClass->hasField("mCachedPtr"))
+				if (meta->scriptClass->hasField("mCachedPtr"))
 					meta->thisPtrField = meta->scriptClass->getField("mCachedPtr");
 				else
 					meta->thisPtrField = nullptr;
@@ -109,26 +113,23 @@ namespace BansheeEngine
 			}
 		}
 
-		if(!mIsCoreLoaded)
+		if (!mIsCoreLoaded)
 		{
 			mIsCoreLoaded = true;
 
-			MonoAssembly* corlib = new (bs_alloc<MonoAssembly>()) MonoAssembly();
-			mAssemblies["corlib"] = corlib;
-
-			corlib->loadFromImage(mono_get_corlib(), "corlib");		
-		}
+			MonoAssembly* corlib = nullptr;
 
-		return *assembly;
-	}
-
-	void MonoManager::unloadAssembly(MonoAssembly& assembly)
-	{
-		::MonoAssembly* monoAssembly = assembly.mMonoAssembly;
-		assembly.unload();
+			auto iterFind = mAssemblies.find("corlib");
+			if (iterFind == mAssemblies.end())
+			{
+				corlib = new (bs_alloc<MonoAssembly>()) MonoAssembly("corlib", "corlib");
+				mAssemblies["corlib"] = corlib;
+			}
+			else
+				corlib = iterFind->second;
 
-		if(monoAssembly)
-			mono_assembly_close(monoAssembly);
+			corlib->loadFromImage(mono_get_corlib());
+		}
 	}
 
 	MonoAssembly* MonoManager::getAssembly(const String& name) const
@@ -222,4 +223,53 @@ namespace BansheeEngine
 
 		return typeNameStr;
 	}
+
+	void MonoManager::unloadScriptDomain()
+	{
+		if (mScriptDomain != nullptr)
+		{
+			mono_domain_set(mono_get_root_domain(), false);
+			mono_domain_finalize(mScriptDomain, 2000);
+
+			MonoObject* exception = nullptr;
+			mono_domain_try_unload(mScriptDomain, &exception);
+
+			if (exception != nullptr)
+				MonoUtil::throwIfException(exception);
+
+			mono_gc_collect(mono_gc_max_generation());
+
+			mScriptDomain = nullptr;
+		}
+
+		for (auto& assemblyEntry : mAssemblies)
+			assemblyEntry.second->unload();
+
+		mIsCoreLoaded = true;
+	}
+
+	void MonoManager::loadScriptDomain()
+	{
+		if (mScriptDomain != nullptr)
+			unloadScriptDomain();
+
+		if (mScriptDomain == nullptr)
+		{
+			mScriptDomain = mono_domain_create_appdomain("ScriptDomain", nullptr);
+			mono_domain_set(mScriptDomain, false);
+
+			if (mScriptDomain == nullptr)
+			{
+				BS_EXCEPT(InternalErrorException, "Cannot create script app domain.");
+			}
+		}
+
+		if (mScriptDomain != nullptr)
+		{
+			for (auto& assemblyEntry : mAssemblies)
+				initializeAssembly(*assemblyEntry.second);
+		}
+
+		onDomainReload();
+	}
 }

+ 1 - 1
MBansheeEditor/EditorWindow.cs

@@ -31,7 +31,7 @@ namespace BansheeEditor
             return screenPos;
         }
 
-        protected EditorWindow()
+        private void OnInitializeInternal()
         {
             GUI = CreatePanel(0, 0, Width, Height);
         }

+ 28 - 7
MBansheeEditor/Scene/Gizmos.cs

@@ -5,19 +5,34 @@ namespace BansheeEditor
 {
     public class Gizmos
     {
-        private static Color _color;
-        private static Matrix4 _transform;
-
         public static Color color
         {
-            get { return _color; }
-            set { _color = value; Internal_SetColor(_color); }
+            get
+            {
+                Color value;
+                Internal_GetColor(out value); 
+                return value; 
+            }
+
+            set
+            {
+                Internal_SetColor(value);
+            }
         }
 
         public static Matrix4 transform
         {
-            get { return _transform; }
-            set { _transform = value; Internal_SetTransform(_transform); }
+            get
+            {
+                Matrix4 value;
+                Internal_GetTransform(out value);
+                return value; 
+            }
+
+            set
+            {
+                Internal_SetTransform(value);
+            }
         }
 
         public static void DrawCube(Vector3 position, Vector3 extents)
@@ -58,9 +73,15 @@ namespace BansheeEditor
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_SetColor(Color color);
 
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetColor(out Color color);
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_SetTransform(Matrix4 transform);
 
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetTransform(out Matrix4 transform);
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_DrawCube(Vector3 position, Vector3 extents);
 

+ 1 - 1
MBansheeEditor/Scene/SceneCamera.cs

@@ -38,7 +38,7 @@ namespace BansheeEditor
         private Radian pitch;
         private bool lastButtonState;
 
-        public SceneCamera()
+        private void OnReset()
         {
             moveForwardBtn = new VirtualButton(MoveForwardBinding);
             moveLeftBtn = new VirtualButton(MoveLeftBinding);

+ 3 - 0
MBansheeEditor/Scene/SceneWindow.cs

@@ -22,6 +22,9 @@ namespace BansheeEditor
         }
 
         internal SceneWindow()
+        { }
+
+        private void OnInitialize()
         {
             UpdateRenderTexture(Width, Height);
         }

+ 52 - 14
MBansheeEngine/Camera.cs

@@ -10,6 +10,9 @@ namespace BansheeEngine
     {
         private CameraHandler handler;
 
+        [SerializeField]
+        private SerializableData serializableData;
+
         internal CameraHandler Handler
         {
             get { return handler; }
@@ -18,43 +21,43 @@ namespace BansheeEngine
         public float aspectRatio
         {
             get { return handler.aspectRatio; }
-            set { handler.aspectRatio = value; }
+            set { handler.aspectRatio = value; serializableData.aspectRatio = value; }
         }
 
         public float nearClipPlane
         {
             get { return handler.nearClipPlane; }
-            set { handler.nearClipPlane = value; }
+            set { handler.nearClipPlane = value; serializableData.nearClipPlane = value; }
         }
 
         public float farClipPlane
         {
             get { return handler.farClipPlane; }
-            set { handler.farClipPlane = value; }
+            set { handler.farClipPlane = value; serializableData.farClipPlane = value; }
         }
 
         public Degree fieldOfView
         {
             get { return handler.fieldOfView; }
-            set { handler.fieldOfView = value; }
+            set { handler.fieldOfView = value; serializableData.fieldOfView = value; }
         }
 
         public Rect2 viewportRect
         {
             get { return handler.viewportRect; }
-            set { handler.viewportRect = value; }
+            set { handler.viewportRect = value; serializableData.viewportRect = value; }
         }
 
         public ProjectionType projectionType
         {
             get { return handler.projectionType; }
-            set { handler.projectionType = value; }
+            set { handler.projectionType = value; serializableData.projectionType = value; }
         }
 
         public float orthoHeight
         {
             get { return handler.orthoHeight; }
-            set { handler.orthoHeight = value; }
+            set { handler.orthoHeight = value; serializableData.orthoHeight = value; }
         }
 
         public float orthoWidth
@@ -65,37 +68,37 @@ namespace BansheeEngine
         public Color clearColor
         {
             get { return handler.clearColor; }
-            set { handler.clearColor = value; }
+            set { handler.clearColor = value; serializableData.clearColor = value; }
         }
 
         public float clearDepth
         {
             get { return handler.clearDepth; }
-            set { handler.clearDepth = value; }
+            set { handler.clearDepth = value; serializableData.clearDepth = value; }
         }
 
         public UInt16 clearStencil
         {
             get { return handler.clearStencil; }
-            set { handler.clearStencil = value; }
+            set { handler.clearStencil = value; serializableData.clearStencil = value; }
         }
 
         public ClearFlags clearFlags
         {
             get { return handler.clearFlags; }
-            set { handler.clearFlags = value; }
+            set { handler.clearFlags = value; serializableData.clearFlags = value; }
         }
 
         public int priority
         {
             get { return handler.priority; }
-            set { handler.priority = value; }
+            set { handler.priority = value; serializableData.priority = value; }
         }
 
         public UInt64 layers
         {
             get { return handler.layers; }
-            set { handler.layers = value; }
+            set { handler.layers = value; serializableData.layers = value; }
         }
 
         public Matrix4 projMatrix
@@ -154,9 +157,26 @@ namespace BansheeEngine
         public Vector3 ProjectPoint(Vector3 value) { return handler.ProjectPoint(value); }
         public Vector3 UnprojectPoint(Vector3 value) { return handler.UnprojectPoint(value); }
 
-        private void OnInitialize()
+        private void OnReset()
         {
             handler = new CameraHandler(sceneObject);
+
+            // Restore saved values after reset
+            handler.aspectRatio = serializableData.aspectRatio;
+            handler.nearClipPlane = serializableData.nearClipPlane;
+            handler.farClipPlane = serializableData.farClipPlane;
+            handler.fieldOfView = serializableData.fieldOfView;
+            handler.viewportRect = serializableData.viewportRect;
+            handler.projectionType = serializableData.projectionType;
+            handler.orthoHeight = serializableData.orthoHeight;
+            handler.clearColor = serializableData.clearColor;
+            handler.clearDepth = serializableData.clearDepth;
+            handler.clearStencil = serializableData.clearStencil;
+            handler.clearFlags = serializableData.clearFlags;
+            handler.priority = serializableData.priority;
+            handler.layers = serializableData.layers;
+
+            // TODO - Make RenderTexture a resource so I can save/restore it?
         }
 
         private void Update()
@@ -168,5 +188,23 @@ namespace BansheeEngine
         {
             handler.OnDestroy();
         }
+
+        [SerializeObject]
+        private struct SerializableData
+        {
+            public float aspectRatio;
+            public float nearClipPlane;
+            public float farClipPlane;
+            public Degree fieldOfView;
+            public Rect2 viewportRect;
+            public ProjectionType projectionType;
+            public float orthoHeight;
+            public Color clearColor;
+            public float clearDepth;
+            public UInt16 clearStencil;
+            public ClearFlags clearFlags;
+            public int priority;
+            public UInt64 layers;
+        }
     }
 }

+ 4 - 0
SBansheeEditor/Include/BsEditorScriptManager.h

@@ -14,6 +14,8 @@ namespace BansheeEngine
 		void update();
 
 	private:
+		void loadMonoTypes();
+
 		static const float EDITOR_UPDATE_RATE;
 
 		MonoAssembly* mEditorAssembly;
@@ -21,5 +23,7 @@ namespace BansheeEngine
 
 		MonoClass* mProgramEdClass;
 		MonoMethod* mUpdateMethod;
+
+		HEvent mOnDomainLoadConn;
 	};
 }

+ 23 - 7
SBansheeEditor/Include/BsScriptEditorWindow.h

@@ -9,7 +9,7 @@ namespace BansheeEngine
 {
 	class ScriptEditorWidget;
 
-	class BS_SCR_BED_EXPORT ScriptEditorWindow : public ScriptObject<ScriptEditorWindow>
+	class BS_SCR_BED_EXPORT ScriptEditorWindow : public ScriptObject<ScriptEditorWindow, PersistentScriptObjectBase>
 	{
 		struct EditorWindowHandle
 		{
@@ -21,13 +21,14 @@ namespace BansheeEngine
 
 		~ScriptEditorWindow();
 
-		EditorWidgetBase* getEditorWidget() const { return mEditorWidget; }
+		EditorWidgetBase* getEditorWidget() const;
 
 		static void registerManagedEditorWindows();
+		static void clearRegisteredEditorWindow();
 	private:
 		friend class ScriptEditorWidget;
 
-		ScriptEditorWindow(MonoObject* instance, const String& windowName, const String& displayName, EditorWidgetBase* editorWidget);
+		ScriptEditorWindow(ScriptEditorWidget* editorWidget);
 
 		static MonoObject* internal_createOrGetInstance(MonoString* ns, MonoString* typeName);
 
@@ -45,14 +46,18 @@ namespace BansheeEngine
 		void onFocusChanged(bool inFocus);
 
 		void _onManagedInstanceDeleted();
+		ScriptObjectBackup beginRefresh();
+		void endRefresh(const ScriptObjectBackup& backupData);
+		MonoObject* _createManagedInstance(bool construct);
 
 		String mName;
-		EditorWidgetBase* mEditorWidget;
+		ScriptEditorWidget* mEditorWidget;
 		Vector<ScriptGUIPanel*> mPanels;
 		HEvent mOnWidgetMovedConn;
 		HEvent mOnWidgetResizedConn;
 		HEvent mOnParentChangedConn;
 		HEvent mOnFocusChangedConn;
+		bool mRefreshInProgress;
 
 		static MonoMethod* onResizedMethod;
 		static MonoMethod* onFocusChangedMethod;
@@ -62,6 +67,7 @@ namespace BansheeEngine
 		static void unregisterScriptEditorWindow(const String& windowTypeName);
 
 		static UnorderedMap<String, EditorWindowHandle> OpenScriptEditorWindows;
+		static Vector<String> AvailableWindowTypes;
 
 		static EditorWidgetBase* openEditorWidgetCallback(String ns, String type, EditorWidgetContainer& parentContainer);
 	};
@@ -69,18 +75,28 @@ namespace BansheeEngine
 	class BS_SCR_BED_EXPORT ScriptEditorWidget : public EditorWidgetBase
 	{
 	public:
-		ScriptEditorWidget(const String& windowTypeName, const HString& displayName, 
-			EditorWidgetContainer& parentContainer, MonoClass* monoClass, MonoObject* managedInstance);
+		ScriptEditorWidget(const String& ns, const String& type, EditorWidgetContainer& parentContainer);
 		~ScriptEditorWidget();
 
+		bool createManagedInstance();
 		void update();
+		void reloadMonoTypes(MonoClass* windowClass);
+		void triggerOnInitialize();
+
+		MonoObject* getManagedInstance() const { return mManagedInstance; }
 
 	private:
+		typedef void(__stdcall *OnInitializeThunkDef) (MonoObject*, MonoException**);
 		typedef void(__stdcall *UpdateThunkDef) (MonoObject*, MonoException**);
 
-		String mWindowTypeName;
+		String mNamespace;
+		String mTypename;
+
+		OnInitializeThunkDef mOnInitializeThunk;
+		OnInitializeThunkDef mOnInitializeInternalThunk;
 		UpdateThunkDef mUpdateThunk;
 		MonoObject* mManagedInstance;
+
 		ScriptEditorWindow* mScriptParent;
 	};
 }

+ 4 - 9
SBansheeEditor/Include/BsScriptGizmoManager.h

@@ -17,31 +17,26 @@ namespace BansheeEngine
 	{
 		struct GizmoData
 		{
-			UINT32 assemblyId;
 			MonoClass* componentType;
 			MonoMethod* drawGizmosMethod;
 			UINT32 flags;
 		};
 
 	public:
-		ScriptGizmoManager(RuntimeScriptObjects& scriptObjectManager);
+		ScriptGizmoManager(ScriptAssemblyManager& scriptObjectManager);
 		~ScriptGizmoManager();
 
 		void update();
 
 	private:
-		void reloadAssemblyMethods(MonoAssembly* assembly);
+		void reloadAssemblyData();
 		bool isValidDrawGizmoMethod(MonoMethod* method, MonoClass*& componentType, UINT32& drawGizmoFlags);
 
-		RuntimeScriptObjects& mScriptObjectManager;
-		HEvent mAssemblyRefreshedConn;
+		ScriptAssemblyManager& mScriptObjectManager;
+		HEvent mDomainLoadedConn;
 
 		MonoClass* mDrawGizmoAttribute;
 		MonoField* mFlagsField;
-		Map<String, UINT32> mAssemblyNameToId;
 		Map<String, GizmoData> mGizmoDrawers;
-		UINT32 mNextAssemblyId;
-
-		Vector<MonoAssembly*> mDelayedLoad;
 	};
 }

+ 2 - 0
SBansheeEditor/Include/BsScriptGizmos.h

@@ -16,7 +16,9 @@ namespace BansheeEngine
 
 	private:
 		static void internal_SetColor(Color color);
+		static void internal_GetColor(Color* color);
 		static void internal_SetTransform(Matrix4 transform);
+		static void internal_GetTransform(Matrix4* transform);
 		static void internal_DrawCube(Vector3 position, Vector3 extents);
 		static void internal_DrawSphere(Vector3 position, float radius);
 		static void internal_DrawWireCube(Vector3 position, Vector3 extents);

+ 4 - 8
SBansheeEditor/Include/BsScriptHandleManager.h

@@ -10,7 +10,6 @@ namespace BansheeEngine
 	{
 		struct CustomHandleData
 		{
-			UINT32 assemblyId;
 			MonoClass* handleType;
 			MonoClass* componentType;
 			MonoMethod* ctor;
@@ -29,7 +28,7 @@ namespace BansheeEngine
 		};
 
 	public:
-		ScriptHandleManager(RuntimeScriptObjects& scriptObjectManager);
+		ScriptHandleManager(ScriptAssemblyManager& scriptObjectManager);
 		~ScriptHandleManager();
 
 	protected:
@@ -37,7 +36,7 @@ namespace BansheeEngine
 		void triggerHandles();
 		void queueDrawCommands();
 
-		void reloadAssembly(MonoAssembly* assembly);
+		void reloadAssemblyData();
 		bool isValidHandleType(MonoClass* type, MonoClass*& componentType, MonoMethod*& ctor);
 
 		void callPreInput(MonoObject* instance);
@@ -45,14 +44,11 @@ namespace BansheeEngine
 		void callDraw(MonoObject* instance);
 		void callDestroy(MonoObject* instance);
 
-		RuntimeScriptObjects& mScriptObjectManager;
-		HEvent mAssemblyRefreshedConn;
+		ScriptAssemblyManager& mScriptObjectManager;
+		HEvent mDomainLoadConn;
 
-		Map<String, UINT32> mAssemblyNameToId;
 		Map<String, CustomHandleData> mHandles;
 
-		UINT32 mNextAssemblyId = 0;
-
 		ActiveCustomHandles mActiveHandleData;
 
 		MonoObject* mDefaultHandleManager = nullptr;

+ 23 - 10
SBansheeEditor/Source/BsEditorScriptManager.cpp

@@ -4,7 +4,7 @@
 #include "BsMonoAssembly.h"
 #include "BsMonoClass.h"
 #include "BsMonoMethod.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsScriptGizmoManager.h"
 #include "BsScriptHandleManager.h"
 #include "BsScriptHandleSliderManager.h"
@@ -18,24 +18,21 @@ namespace BansheeEngine
 	EditorScriptManager::EditorScriptManager()
 		:mEditorAssembly(nullptr), mProgramEdClass(nullptr), mUpdateMethod(nullptr)
 	{
-		const String ENGINE_ASSEMBLY_PATH = "..\\..\\Assemblies\\MBansheeEditor.dll";
-		const String ENGINE_ASSEMBLY_NAME = BansheeEditorAssemblyName;
 		const String ASSEMBLY_ENTRY_POINT = "Program::Start";
 
-		mEditorAssembly = &MonoManager::instance().loadAssembly(ENGINE_ASSEMBLY_PATH, ENGINE_ASSEMBLY_NAME);
 		ScriptEditorWindow::registerManagedEditorWindows();
 
-		RuntimeScriptObjects::instance().refreshScriptObjects(BansheeEditorAssemblyName);
+		ScriptAssemblyManager::instance().loadAssemblyInfo(BansheeEditorAssemblyName);
 
 		ScriptHandleSliderManager::startUp();
-		ScriptGizmoManager::startUp(RuntimeScriptObjects::instance());
-		HandleManager::startUp<ScriptHandleManager>(RuntimeScriptObjects::instance());
+		ScriptGizmoManager::startUp(ScriptAssemblyManager::instance());
+		HandleManager::startUp<ScriptHandleManager>(ScriptAssemblyManager::instance());
 
-		mProgramEdClass = mEditorAssembly->getClass("BansheeEditor", "Program");
-		mUpdateMethod = mProgramEdClass->getMethod("EditorUpdate");
+		mOnDomainLoadConn = MonoManager::instance().onDomainReload.connect(std::bind(&EditorScriptManager::loadMonoTypes, this));
+		loadMonoTypes();
 
 		mEditorAssembly->invoke(ASSEMBLY_ENTRY_POINT);
-		
+
 		// Initial update
 		mLastUpdateTime = gTime().getTime();
 		mUpdateMethod->invoke(nullptr, nullptr);
@@ -43,6 +40,8 @@ namespace BansheeEngine
 
 	EditorScriptManager::~EditorScriptManager()
 	{
+		mOnDomainLoadConn.disconnect();
+
 		ScriptHandleSliderManager::shutDown();
 		HandleManager::shutDown();
 		ScriptGizmoManager::shutDown();
@@ -63,4 +62,18 @@ namespace BansheeEngine
 
 		ScriptGizmoManager::instance().update();
 	}
+
+	void EditorScriptManager::loadMonoTypes()
+	{
+		const String ENGINE_ASSEMBLY_PATH = "..\\..\\Assemblies\\MBansheeEditor.dll";
+		const String ENGINE_ASSEMBLY_NAME = BansheeEditorAssemblyName;
+		
+		mEditorAssembly = &MonoManager::instance().loadAssembly(ENGINE_ASSEMBLY_PATH, ENGINE_ASSEMBLY_NAME);
+
+		mProgramEdClass = mEditorAssembly->getClass("BansheeEditor", "Program");
+		mUpdateMethod = mProgramEdClass->getMethod("EditorUpdate");
+
+		ScriptEditorWindow::clearRegisteredEditorWindow();
+		ScriptEditorWindow::registerManagedEditorWindows();
+	}
 }

+ 2 - 2
SBansheeEditor/Source/BsGUIGameObjectField.cpp

@@ -10,7 +10,7 @@
 #include "BsGUISceneTreeView.h"
 #include "BsGUIWidget.h"
 #include "BsGameObjectManager.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsMonoClass.h"
 #include "BsSceneObject.h"
 #include "BsManagedComponent.h"
@@ -202,7 +202,7 @@ namespace BansheeEngine
 		if (draggedSceneObjects->numObjects <= 0)
 			return;
 
-		MonoClass* sceneObjectClass = RuntimeScriptObjects::instance().getSceneObjectClass();
+		MonoClass* sceneObjectClass = ScriptAssemblyManager::instance().getSceneObjectClass();
 
 		if (mType == sceneObjectClass->getFullName()) // A scene object
 		{

+ 3 - 3
SBansheeEditor/Source/BsGUIResourceField.cpp

@@ -10,7 +10,7 @@
 #include "BsGUIResourceTreeView.h"
 #include "BsGUIWidget.h"
 #include "BsGameObjectManager.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsMonoClass.h"
 #include "BsMonoManager.h"
 #include "BsResources.h"
@@ -224,7 +224,7 @@ namespace BansheeEngine
 			{
 			case TID_Texture:
 			{
-				if (RuntimeScriptObjects::instance().getTextureClass()->isSubClassOf(acceptedClass))
+				if (ScriptAssemblyManager::instance().getTextureClass()->isSubClassOf(acceptedClass))
 				{
 					setUUID(uuid);
 					found = true;
@@ -233,7 +233,7 @@ namespace BansheeEngine
 				break;
 			case TID_SpriteTexture:
 			{
-				if (RuntimeScriptObjects::instance().getSpriteTextureClass()->isSubClassOf(acceptedClass))
+				if (ScriptAssemblyManager::instance().getSpriteTextureClass()->isSubClassOf(acceptedClass))
 				{
 					setUUID(uuid);
 					found = true;

+ 139 - 32
SBansheeEditor/Source/BsScriptEditorWindow.cpp

@@ -16,11 +16,12 @@ using namespace std::placeholders;
 namespace BansheeEngine
 {
 	UnorderedMap<String, ScriptEditorWindow::EditorWindowHandle> ScriptEditorWindow::OpenScriptEditorWindows;
+	Vector<String> ScriptEditorWindow::AvailableWindowTypes;
 	MonoMethod* ScriptEditorWindow::onResizedMethod = nullptr;
 	MonoMethod* ScriptEditorWindow::onFocusChangedMethod = nullptr;
 
-	ScriptEditorWindow::ScriptEditorWindow(MonoObject* instance, const String& windowName, const String& displayName, EditorWidgetBase* editorWidget)
-		:ScriptObject(instance), mName(windowName), mEditorWidget(editorWidget)
+	ScriptEditorWindow::ScriptEditorWindow(ScriptEditorWidget* editorWidget)
+		:ScriptObject(editorWidget->getManagedInstance()), mName(editorWidget->getName()), mEditorWidget(editorWidget), mRefreshInProgress(false)
 	{
 		mOnWidgetMovedConn = editorWidget->onMoved.connect(std::bind(&ScriptEditorWindow::onWidgetMoved, this, _1, _2));
 		mOnWidgetResizedConn = editorWidget->onResized.connect(std::bind(&ScriptEditorWindow::onWidgetResized, this, _1, _2));
@@ -70,11 +71,66 @@ namespace BansheeEngine
 		return nullptr;
 	}
 
+	EditorWidgetBase* ScriptEditorWindow::getEditorWidget() const 
+	{ 
+		return mEditorWidget; 
+	}
+
 	void ScriptEditorWindow::_onManagedInstanceDeleted()
 	{
-		unregisterScriptEditorWindow(mName);
+		if (!mRefreshInProgress)
+		{
+			unregisterScriptEditorWindow(mName);
+
+			ScriptObject::_onManagedInstanceDeleted();
+		}
+		else
+			mManagedInstance = nullptr;
+	}
+
+	ScriptObjectBackup ScriptEditorWindow::beginRefresh()
+	{
+		mRefreshInProgress = true;
+
+		auto iterFind = OpenScriptEditorWindows.find(mName);
+		if (iterFind != OpenScriptEditorWindows.end())
+		{
+			mono_gchandle_free(iterFind->second.gcHandle);
+			iterFind->second.gcHandle = 0;
+		}
+
+		return PersistentScriptObjectBase::beginRefresh();
+	}
+
+	void ScriptEditorWindow::endRefresh(const ScriptObjectBackup& backupData)
+	{
+		mRefreshInProgress = false;
+
+		mManagedInstance = mEditorWidget->getManagedInstance();
+		if (mManagedInstance != nullptr)
+		{
+			auto iterFind = OpenScriptEditorWindows.find(mName);
+			if (iterFind != OpenScriptEditorWindows.end())
+			{
+				iterFind->second.gcHandle = mono_gchandle_new(mManagedInstance, false);
+			}
+
+			mEditorWidget->triggerOnInitialize();
+		}
+		else
+		{
+			// We couldn't restore managed instance because window class cannot be found
+			_onManagedInstanceDeleted();
+		}
+
+		PersistentScriptObjectBase::endRefresh(backupData);
+	}
+
+	MonoObject* ScriptEditorWindow::_createManagedInstance(bool construct)
+	{
+		mEditorWidget->createManagedInstance();
 
-		ScriptObject::_onManagedInstanceDeleted();
+		return mEditorWidget->getManagedInstance();
 	}
 
 	bool ScriptEditorWindow::internal_hasFocus(ScriptEditorWindow* thisPtr)
@@ -167,36 +223,31 @@ namespace BansheeEngine
 					const String& className = curClass->getFullName();
 					EditorWidgetManager::instance().registerWidget(className, 
 						std::bind(&ScriptEditorWindow::openEditorWidgetCallback, curClass->getNamespace(), curClass->getTypeName(), std::placeholders::_1));
+					AvailableWindowTypes.push_back(className);
 				}
 			}
 		}
 	}
 
-	EditorWidgetBase* ScriptEditorWindow::openEditorWidgetCallback(String ns, String type, EditorWidgetContainer& parentContainer)
+	void ScriptEditorWindow::clearRegisteredEditorWindow()
 	{
-		MonoAssembly* assembly = MonoManager::instance().getAssembly(BansheeEditorAssemblyName);
-
-		if(assembly == nullptr)
-			return nullptr;
-
-		MonoClass* editorWindowClass = assembly->getClass(ns, type);
-
-		if(editorWindowClass == nullptr)
-			return nullptr;
-
-		MonoObject* editorWindowInstance = editorWindowClass->createInstance(false);
-		if(editorWindowInstance == nullptr)
-			return nullptr;
+		for (auto& windowType : AvailableWindowTypes)
+		{
+			EditorWidgetManager::instance().unregisterWidget(windowType);
+		}
 
-		String windowFullTypeName = MonoManager::instance().getFullTypeName(editorWindowInstance);
-		String displayName = MonoManager::instance().getTypeName(editorWindowInstance);
+		AvailableWindowTypes.clear();
+	}
 
-		ScriptEditorWidget* editorWidget = bs_new<ScriptEditorWidget>(windowFullTypeName, HString(toWString(displayName)), parentContainer, editorWindowClass, editorWindowInstance);
-		ScriptEditorWindow* nativeInstance = new (bs_alloc<ScriptEditorWindow>()) ScriptEditorWindow(editorWindowInstance, windowFullTypeName, displayName, editorWidget);
+	EditorWidgetBase* ScriptEditorWindow::openEditorWidgetCallback(String ns, String type, EditorWidgetContainer& parentContainer)
+	{
+		ScriptEditorWidget* editorWidget = bs_new<ScriptEditorWidget>(ns, type, parentContainer);
+		ScriptEditorWindow* nativeInstance = new (bs_alloc<ScriptEditorWindow>()) ScriptEditorWindow(editorWidget);
 
 		ScriptEditorWindow::registerScriptEditorWindow(nativeInstance);
 
-		mono_runtime_object_init(editorWindowInstance); // Construct it
+		mono_runtime_object_init(editorWidget->getManagedInstance()); // Construct it
+		editorWidget->triggerOnInitialize();
 
 		return editorWidget;
 	}
@@ -229,20 +280,58 @@ namespace BansheeEngine
 		}
 	}
 
-	ScriptEditorWidget::ScriptEditorWidget(const String& windowTypeName, const HString& displayName, 
-		EditorWidgetContainer& parentContainer, MonoClass* monoClass, MonoObject* managedInstance)
-		:EditorWidgetBase(displayName, windowTypeName, parentContainer), 
-		mWindowTypeName(windowTypeName), mUpdateThunk(nullptr), mManagedInstance(managedInstance)
+	ScriptEditorWidget::ScriptEditorWidget(const String& ns, const String& type, EditorWidgetContainer& parentContainer)
+		:EditorWidgetBase(HString(toWString(type)), ns + "." + type, parentContainer), mNamespace(ns), mTypename(type),
+		mUpdateThunk(nullptr), mManagedInstance(nullptr)
 	{
-		MonoMethod* updateMethod = monoClass->getMethod("EditorUpdate", 0);
-
-		if (updateMethod != nullptr)
-			mUpdateThunk = (UpdateThunkDef)updateMethod->getThunk();
+		createManagedInstance();
 	}
 
 	ScriptEditorWidget::~ScriptEditorWidget()
 	{
-		ScriptEditorWindow::unregisterScriptEditorWindow(mWindowTypeName);
+		ScriptEditorWindow::unregisterScriptEditorWindow(getName());
+	}
+
+	bool ScriptEditorWidget::createManagedInstance()
+	{
+		MonoAssembly* assembly = MonoManager::instance().getAssembly(BansheeEditorAssemblyName);
+
+		if (assembly != nullptr)
+		{
+			MonoClass* editorWindowClass = assembly->getClass(mNamespace, mTypename);
+
+			if (editorWindowClass != nullptr)
+			{
+				mManagedInstance = editorWindowClass->createInstance(false);
+
+				reloadMonoTypes(editorWindowClass);
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	void ScriptEditorWidget::triggerOnInitialize()
+	{
+		if (mOnInitializeInternalThunk != nullptr && mManagedInstance != nullptr)
+		{
+			MonoException* exception = nullptr;
+			mOnInitializeInternalThunk(mManagedInstance, &exception);
+
+			MonoUtil::throwIfException(exception);
+		}
+
+		if (mOnInitializeThunk != nullptr && mManagedInstance != nullptr)
+		{
+			MonoException* exception = nullptr;
+
+			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
+			// for some extra speed.
+			mOnInitializeThunk(mManagedInstance, &exception);
+
+			MonoUtil::throwIfException(exception);
+		}
 	}
 
 	void ScriptEditorWidget::update()
@@ -258,4 +347,22 @@ namespace BansheeEngine
 			MonoUtil::throwIfException(exception);
 		}
 	}
+
+	void ScriptEditorWidget::reloadMonoTypes(MonoClass* windowClass)
+	{
+		MonoMethod* updateMethod = windowClass->getMethod("EditorUpdate", 0);
+
+		if (updateMethod != nullptr)
+			mUpdateThunk = (UpdateThunkDef)updateMethod->getThunk();
+
+		MonoMethod* onInitializeMethod = windowClass->getMethod("OnInitialize", 0);
+
+		if (onInitializeMethod != nullptr)
+			mOnInitializeThunk = (OnInitializeThunkDef)onInitializeMethod->getThunk();
+
+		MonoMethod* onInitializeInternalMethod = windowClass->getMethod("OnInitializeInternal", 0);
+
+		if (onInitializeInternalMethod != nullptr)
+			mOnInitializeInternalThunk = (OnInitializeThunkDef)onInitializeInternalMethod->getThunk();
+	}
 }

+ 32 - 79
SBansheeEditor/Source/BsScriptGizmoManager.cpp

@@ -1,5 +1,5 @@
 #include "BsScriptGizmoManager.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsMonoAssembly.h"
 #include "BsMonoClass.h"
 #include "BsMonoMethod.h"
@@ -11,33 +11,22 @@
 #include "BsManagedComponent.h"
 #include "BsGizmoManager.h"
 #include "BsSelection.h"
+#include "BsMonoManager.h"
 
 using namespace std::placeholders;
 
 namespace BansheeEngine
 {
-	ScriptGizmoManager::ScriptGizmoManager(RuntimeScriptObjects& scriptObjectManager)
-		:mScriptObjectManager(scriptObjectManager), mDrawGizmoAttribute(nullptr), mNextAssemblyId(0), mFlagsField(nullptr)
+	ScriptGizmoManager::ScriptGizmoManager(ScriptAssemblyManager& scriptObjectManager)
+		:mScriptObjectManager(scriptObjectManager), mDrawGizmoAttribute(nullptr), mFlagsField(nullptr)
 	{
-		mAssemblyRefreshedConn = mScriptObjectManager.onAssemblyRefreshed.connect(std::bind(&ScriptGizmoManager::reloadAssemblyMethods, this, _1));
-
-		Vector<String> initializedAssemblyNames = mScriptObjectManager.getInitializedAssemblies();
-		for (auto& assemblyName : initializedAssemblyNames)
-		{
-			MonoAssembly* assembly = MonoManager::instance().getAssembly(assemblyName);
-			if (assembly != nullptr)
-				reloadAssemblyMethods(assembly);
-		}
+		mDomainLoadedConn = MonoManager::instance().onDomainReload.connect(std::bind(&ScriptGizmoManager::reloadAssemblyData, this));
+		reloadAssemblyData();
 	}
 
 	ScriptGizmoManager::~ScriptGizmoManager()
 	{
-		mAssemblyRefreshedConn.disconnect();
-	}
-
-	bool dummyIsSelected(const HSceneObject& so)
-	{
-		return false; // TODO - Replace with a call to Selection class once I have it
+		mDomainLoadedConn.disconnect();
 	}
 
 	void ScriptGizmoManager::update()
@@ -113,75 +102,39 @@ namespace BansheeEngine
 		}
 	}
 
-	void ScriptGizmoManager::reloadAssemblyMethods(MonoAssembly* assembly)
+	void ScriptGizmoManager::reloadAssemblyData()
 	{
-		String assemblyName = assembly->getName();
-
-		// If editor assembly, reload DrawGizmo attribute
-		if (assemblyName == BansheeEditorAssemblyName) 
-		{
-			mDrawGizmoAttribute = assembly->getClass("BansheeEditor", "DrawGizmo");
-			if (mDrawGizmoAttribute == nullptr)
-				BS_EXCEPT(InvalidStateException, "Cannot find DrawGizmo managed class.");
-
-			mFlagsField = mDrawGizmoAttribute->getField("flags");
-
-			// Load delayed assemblies first
-			for (auto iter = mDelayedLoad.rbegin(); iter != mDelayedLoad.rend(); ++iter)
-				reloadAssemblyMethods(*iter);
-
-			mDelayedLoad.clear();
-		}
-		else
-		{
-			// If we haven't loaded editor assembly yet, wait until we do before continuing
-			if (mDrawGizmoAttribute == nullptr)
-			{
-				mDelayedLoad.push_back(assembly);
-				return;
-			}
-		}
+		// Reload DrawGizmo attribute from editor assembly
+		MonoAssembly* editorAssembly = MonoManager::instance().getAssembly(BansheeEditorAssemblyName);
+		mDrawGizmoAttribute = editorAssembly->getClass("BansheeEditor", "DrawGizmo");
+		if (mDrawGizmoAttribute == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find DrawGizmo managed class.");
 
-		// If we had this assembly previously loaded, clear all of its methods
-		UINT32 assemblyId = 0;
-		auto iterFind = mAssemblyNameToId.find(assemblyName);
-		if (iterFind != mAssemblyNameToId.end())
-		{
-			assemblyId = iterFind->second;
-
-			Map<String, GizmoData> newGizmoDrawers;
-			for (auto& gizmoMethod : mGizmoDrawers)
-			{
-				if (gizmoMethod.second.assemblyId != assemblyId)
-					newGizmoDrawers[gizmoMethod.first] = gizmoMethod.second;
-			}
+		mFlagsField = mDrawGizmoAttribute->getField("flags");
 
-			mGizmoDrawers.swap(newGizmoDrawers);
-		}
-		else
+		Vector<String> scriptAssemblyNames = mScriptObjectManager.getScriptAssemblies();
+		for (auto& assemblyName : scriptAssemblyNames)
 		{
-			assemblyId = mNextAssemblyId++;
-			mAssemblyNameToId[assemblyName] = assemblyId;
-		}
+			MonoAssembly* assembly = MonoManager::instance().getAssembly(assemblyName);
 
-		// Find new gizmo drawer methods
-		const Vector<MonoClass*>& allClasses = assembly->getAllClasses();
-		for (auto curClass : allClasses)
-		{
-			const Vector<MonoMethod*>& methods = curClass->getAllMethods();
-			for (auto& curMethod : methods)
+			// Find new gizmo drawer methods
+			const Vector<MonoClass*>& allClasses = assembly->getAllClasses();
+			for (auto curClass : allClasses)
 			{
-				UINT32 drawGizmoFlags = 0;
-				MonoClass* componentType = nullptr;
-				if (isValidDrawGizmoMethod(curMethod, componentType, drawGizmoFlags))
+				const Vector<MonoMethod*>& methods = curClass->getAllMethods();
+				for (auto& curMethod : methods)
 				{
-					String fullComponentName = componentType->getFullName();
-					GizmoData& newGizmoData = mGizmoDrawers[fullComponentName];
+					UINT32 drawGizmoFlags = 0;
+					MonoClass* componentType = nullptr;
+					if (isValidDrawGizmoMethod(curMethod, componentType, drawGizmoFlags))
+					{
+						String fullComponentName = componentType->getFullName();
+						GizmoData& newGizmoData = mGizmoDrawers[fullComponentName];
 
-					newGizmoData.assemblyId = assemblyId;
-					newGizmoData.componentType = componentType;
-					newGizmoData.drawGizmosMethod = curMethod;
-					newGizmoData.flags = drawGizmoFlags;
+						newGizmoData.componentType = componentType;
+						newGizmoData.drawGizmosMethod = curMethod;
+						newGizmoData.flags = drawGizmoFlags;
+					}
 				}
 			}
 		}

+ 12 - 0
SBansheeEditor/Source/BsScriptGizmos.cpp

@@ -10,7 +10,9 @@ namespace BansheeEngine
 	void ScriptGizmos::initRuntimeData()
 	{
 		metaData.scriptClass->addInternalCall("Internal_SetColor", &ScriptGizmos::internal_SetColor);
+		metaData.scriptClass->addInternalCall("Internal_GetColor", &ScriptGizmos::internal_GetColor);
 		metaData.scriptClass->addInternalCall("Internal_SetTransform", &ScriptGizmos::internal_SetTransform);
+		metaData.scriptClass->addInternalCall("Internal_GetTransform", &ScriptGizmos::internal_GetTransform);
 		metaData.scriptClass->addInternalCall("Internal_DrawCube", &ScriptGizmos::internal_DrawCube);
 		metaData.scriptClass->addInternalCall("Internal_DrawSphere", &ScriptGizmos::internal_DrawSphere);
 		metaData.scriptClass->addInternalCall("Internal_DrawWireCube", &ScriptGizmos::internal_DrawWireCube);
@@ -25,11 +27,21 @@ namespace BansheeEngine
 		GizmoManager::instance().setColor(color);
 	}
 
+	void ScriptGizmos::internal_GetColor(Color* color)
+	{
+		*color = GizmoManager::instance().getColor();
+	}
+
 	void ScriptGizmos::internal_SetTransform(Matrix4 transform)
 	{
 		GizmoManager::instance().setTransform(transform);
 	}
 
+	void ScriptGizmos::internal_GetTransform(Matrix4* transform)
+	{
+		*transform = GizmoManager::instance().getTransform();
+	}
+
 	void ScriptGizmos::internal_DrawCube(Vector3 position, Vector3 extents)
 	{
 		GizmoManager::instance().drawCube(position, extents);

+ 44 - 74
SBansheeEditor/Source/BsScriptHandleManager.cpp

@@ -1,5 +1,5 @@
 #include "BsScriptHandleManager.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsMonoManager.h"
 #include "BsMonoAssembly.h"
 #include "BsMonoClass.h"
@@ -14,18 +14,11 @@ using namespace std::placeholders;
 
 namespace BansheeEngine
 {
-	ScriptHandleManager::ScriptHandleManager(RuntimeScriptObjects& scriptObjectManager)
+	ScriptHandleManager::ScriptHandleManager(ScriptAssemblyManager& scriptObjectManager)
 		:mScriptObjectManager(scriptObjectManager)
 	{
-		mAssemblyRefreshedConn = mScriptObjectManager.onAssemblyRefreshed.connect(std::bind(&ScriptHandleManager::reloadAssembly, this, _1));
-
-		Vector<String> initializedAssemblyNames = mScriptObjectManager.getInitializedAssemblies();
-		for (auto& assemblyName : initializedAssemblyNames)
-		{
-			MonoAssembly* assembly = MonoManager::instance().getAssembly(assemblyName);
-			if (assembly != nullptr)
-				reloadAssembly(assembly);
-		}
+		mDomainLoadConn = MonoManager::instance().onDomainReload.connect(std::bind(&ScriptHandleManager::reloadAssemblyData, this));
+		reloadAssemblyData();
 	}
 
 	ScriptHandleManager::~ScriptHandleManager()
@@ -42,7 +35,7 @@ namespace BansheeEngine
 			mono_gchandle_free(mDefaultHandleManagerGCHandle);
 		}
 
-		mAssemblyRefreshedConn.disconnect();
+		mDomainLoadConn.disconnect();
 	}
 
 	void ScriptHandleManager::refreshHandles()
@@ -131,83 +124,60 @@ namespace BansheeEngine
 		}
 	}
 
-	void ScriptHandleManager::reloadAssembly(MonoAssembly* assembly)
+	void ScriptHandleManager::reloadAssemblyData()
 	{
-		String assemblyName = assembly->getName();
+		// Reload types from editor assembly
+		MonoAssembly* editorAssembly = MonoManager::instance().getAssembly(BansheeEditorAssemblyName);
+		mCustomHandleAttribute = editorAssembly->getClass("BansheeEditor", "CustomHandle");
+		if (mCustomHandleAttribute == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find CustomHandle managed class.");
 
-		// If editor assembly, reload needed types
-		if (assemblyName == BansheeEditorAssemblyName)
-		{
-			mCustomHandleAttribute = assembly->getClass("BansheeEditor", "CustomHandle");
-			if (mCustomHandleAttribute == nullptr)
-				BS_EXCEPT(InvalidStateException, "Cannot find CustomHandle managed class.");
+		mHandleBaseClass = editorAssembly->getClass("BansheeEditor", "Handle");
+		if (mHandleBaseClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find Handle managed class.");
 
-			mHandleBaseClass = assembly->getClass("BansheeEditor", "Handle");
-			if (mHandleBaseClass == nullptr)
-				BS_EXCEPT(InvalidStateException, "Cannot find Handle managed class.");
+		mDefaultHandleManagerClass = editorAssembly->getClass("BansheeEditor", "DefaultHandleManager");
+		if (mDefaultHandleManagerClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find DefaultHandleManager managed class.");
 
-			mDefaultHandleManagerClass = assembly->getClass("BansheeEditor", "DefaultHandleManager");
-			if (mDefaultHandleManagerClass == nullptr)
-				BS_EXCEPT(InvalidStateException, "Cannot find DefaultHandleManager managed class.");
+		mTypeField = mCustomHandleAttribute->getField("type");
 
-			mTypeField = mCustomHandleAttribute->getField("type");
+		mPreInputMethod = mHandleBaseClass->getMethod("PreInput", 0);
+		mPostInputMethod = mHandleBaseClass->getMethod("PostInput", 0);
+		mDrawMethod = mHandleBaseClass->getMethod("Draw", 0);
+		mDestroyThunk = (DestroyThunkDef)mHandleBaseClass->getMethod("Destroy", 0)->getThunk();
 
-			mPreInputMethod = mHandleBaseClass->getMethod("PreInput", 0);
-			mPostInputMethod = mHandleBaseClass->getMethod("PostInput", 0);
-			mDrawMethod = mHandleBaseClass->getMethod("Draw", 0);
-			mDestroyThunk = (DestroyThunkDef)mHandleBaseClass->getMethod("Destroy", 0)->getThunk();
+		mDefaultHandleManager = nullptr; // Freed on assembly unload, so not valid anymore
+		mDefaultHandleManagerGCHandle = 0;
 
-			mDefaultHandleManager = nullptr; // Freed on assembly unload, so not valid anymore
-			mDefaultHandleManagerGCHandle = 0;
-		}
-		else
+		Vector<String> scriptAssemblyNames = mScriptObjectManager.getScriptAssemblies();
+		for (auto& assemblyName : scriptAssemblyNames)
 		{
-			// If we haven't loaded editor assembly yet, do nothing, caller must ensure to load assemblies in order
-			if (mCustomHandleAttribute == nullptr)
-				return;
-		}
-
-		// If we had this assembly previously loaded, clear all of its types
-		UINT32 assemblyId = 0;
-		auto iterFind = mAssemblyNameToId.find(assemblyName);
-		if (iterFind != mAssemblyNameToId.end())
-		{
-			assemblyId = iterFind->second;
+			MonoAssembly* assembly = MonoManager::instance().getAssembly(assemblyName);
 
-			Map<String, CustomHandleData> newHandles;
-			for (auto& handleData : mHandles)
+			// Find new custom handle types
+			const Vector<MonoClass*>& allClasses = assembly->getAllClasses();
+			for (auto curClass : allClasses)
 			{
-				if (handleData.second.assemblyId != assemblyId)
-					newHandles[handleData.first] = handleData.second;
-			}
+				MonoClass* componentType = nullptr;
+				MonoMethod* ctor = nullptr;
 
-			mHandles.swap(newHandles);
-		}
-		else
-		{
-			assemblyId = mNextAssemblyId++;
-			mAssemblyNameToId[assemblyName] = assemblyId;
-		}
-
-		// Find new custom handle types
-		const Vector<MonoClass*>& allClasses = assembly->getAllClasses();
-		for (auto curClass : allClasses)
-		{
-			MonoClass* componentType = nullptr;
-			MonoMethod* ctor = nullptr;
-
-			if (isValidHandleType(curClass, componentType, ctor))
-			{
-				String fullComponentName = componentType->getFullName();
+				if (isValidHandleType(curClass, componentType, ctor))
+				{
+					String fullComponentName = componentType->getFullName();
 
-				CustomHandleData& newHandleData = mHandles[fullComponentName];
+					CustomHandleData& newHandleData = mHandles[fullComponentName];
 
-				newHandleData.assemblyId = assemblyId;
-				newHandleData.componentType = componentType;
-				newHandleData.handleType = curClass;
-				newHandleData.ctor = ctor;
+					newHandleData.componentType = componentType;
+					newHandleData.handleType = curClass;
+					newHandleData.ctor = ctor;
+				}
 			}
 		}
+
+		// Clear selection data
+		mActiveHandleData.selectedObject = HSceneObject();
+		mActiveHandleData.handles.clear();
 	}
 
 	bool ScriptHandleManager::isValidHandleType(MonoClass* type, MonoClass*& componentType, MonoMethod*& ctor)

+ 22 - 1
SBansheeEngine/Include/BsManagedComponent.h

@@ -6,6 +6,8 @@
 
 namespace BansheeEngine
 {
+	struct ComponentBackupData;
+
 	class BS_SCR_BE_EXPORT ManagedComponent : public Component
 	{
 	public:
@@ -18,10 +20,16 @@ namespace BansheeEngine
 		const String& getManagedTypeName() const { return mTypeName; }
 		const String& getManagedFullTypeName() const { return mFullTypeName; }
 
+		ComponentBackupData backup(bool clearExisting = true);
+		void restore(MonoObject* instance, const ComponentBackupData& data);
+
+		void triggerOnReset();
+
 	private:
 		typedef void(__stdcall *OnInitializedThunkDef) (MonoObject*, MonoException**);
 		typedef void(__stdcall *UpdateThunkDef) (MonoObject*, MonoException**);
 		typedef void(__stdcall *OnDestroyedThunkDef) (MonoObject*, MonoException**);
+		typedef void(__stdcall *OnResetThunkDef) (MonoObject*, MonoException**);
 
 		MonoObject* mManagedInstance;
 		MonoReflectionType* mRuntimeType;
@@ -33,6 +41,7 @@ namespace BansheeEngine
 
 		OnInitializedThunkDef mOnInitializedThunk;
 		UpdateThunkDef mUpdateThunk;
+		OnResetThunkDef mOnResetThunk;
 		OnDestroyedThunkDef mOnDestroyThunk;
 
 		/************************************************************************/
@@ -46,7 +55,7 @@ namespace BansheeEngine
 		/** Standard constructor.
         */
 		ManagedComponent(const HSceneObject& parent, MonoReflectionType* runtimeType);
-		void initialize(MonoObject* object, MonoReflectionType* runtimeType, MonoClass* monoClass);
+		void initialize(MonoObject* object);
 
 		void onInitialized();
 		void onDestroyed();
@@ -65,4 +74,16 @@ namespace BansheeEngine
 	protected:
 		ManagedComponent(); // Serialization only
 	};
+
+	struct ComponentBackupData
+	{
+		struct DataBlock
+		{
+			UINT8* data;
+			UINT32 size;
+		};
+
+		DataBlock mTypeInfo;
+		DataBlock mObjectData;
+	};
 }

+ 1 - 7
SBansheeEngine/Include/BsManagedComponentRTTI.h

@@ -70,15 +70,9 @@ namespace BansheeEngine
 		static void finalizeDeserialization(ManagedComponent* mc)
 		{
 			ManagedSerializableObjectPtr serializableObject = any_cast<ManagedSerializableObjectPtr>(mc->mRTTIData);
-
-			::MonoClass* monoClass = mono_object_get_class(serializableObject->getManagedInstance());
-			MonoType* monoType = mono_class_get_type(monoClass);
-			MonoReflectionType* runtimeType = mono_type_get_object(MonoManager::instance().getDomain(), monoType);
-
-			MonoClass* managedClass = MonoManager::instance().findClass(monoClass);
 			MonoObject* managedInstance = serializableObject->getManagedInstance();
 
-			mc->initialize(managedInstance, runtimeType, managedClass);
+			mc->initialize(managedInstance);
 			mc->mRTTIData = nullptr;
 		}
 

+ 17 - 0
SBansheeEngine/Include/BsManagedResource.h

@@ -7,6 +7,8 @@
 
 namespace BansheeEngine
 {
+	struct ResourceBackupData;
+
 	class BS_SCR_BE_EXPORT ManagedResource : public Resource
 	{
 	public:
@@ -14,6 +16,9 @@ namespace BansheeEngine
 
 		MonoObject* getManagedInstance() const { return mManagedInstance; }
 
+		ResourceBackupData backup(bool clearExisting = true);
+		void restore(MonoObject* instance, const ResourceBackupData& data);
+
 		static HManagedResource create(MonoObject* managedResource);
 		static ManagedResourcePtr createEmpty();
 
@@ -38,4 +43,16 @@ namespace BansheeEngine
 	protected:
 		ManagedResource(); // Serialization only
 	};
+
+	struct ResourceBackupData
+	{
+		struct DataBlock
+		{
+			UINT8* data;
+			UINT32 size;
+		};
+
+		DataBlock mTypeInfo;
+		DataBlock mObjectData;
+	};
 }

+ 1 - 1
SBansheeEngine/Include/BsManagedSerializableArrayRTTI.h

@@ -4,7 +4,7 @@
 #include "BsRTTIType.h"
 #include "BsGameObjectManager.h"
 #include "BsManagedSerializableArray.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsMonoManager.h"
 #include "BsMonoClass.h"
 

+ 1 - 1
SBansheeEngine/Include/BsManagedSerializableDictionaryRTTI.h

@@ -4,7 +4,7 @@
 #include "BsRTTIType.h"
 #include "BsGameObjectManager.h"
 #include "BsManagedSerializableDictionary.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsMonoManager.h"
 #include "BsMonoClass.h"
 

+ 1 - 1
SBansheeEngine/Include/BsManagedSerializableListRTTI.h

@@ -4,7 +4,7 @@
 #include "BsRTTIType.h"
 #include "BsGameObjectManager.h"
 #include "BsManagedSerializableList.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsMonoManager.h"
 #include "BsMonoClass.h"
 

+ 7 - 2
SBansheeEngine/Include/BsManagedSerializableObject.h

@@ -18,6 +18,12 @@ namespace BansheeEngine
 		MonoObject* getManagedInstance() const { return mManagedInstance; }
 		ManagedSerializableObjectInfoPtr getObjectInfo() const { return mObjInfo; }
 
+		void setFieldData(const ManagedSerializableFieldInfoPtr& fieldInfo, const ManagedSerializableFieldDataPtr& val);
+		ManagedSerializableFieldDataPtr getFieldData(const ManagedSerializableFieldInfoPtr& fieldInfo) const;
+
+		void setObjectData(const ManagedSerializableObjectDataPtr& objectData, const ManagedSerializableObjectInfoPtr& originalEntriesType);
+		ManagedSerializableObjectDataPtr getObjectData() const;
+
 		static ManagedSerializableObjectPtr createFromExisting(MonoObject* managedInstance);
 		static ManagedSerializableObjectPtr createFromNew(const ManagedSerializableTypeInfoObjectPtr& type);
 		static MonoObject* createManagedInstance(const ManagedSerializableTypeInfoObjectPtr& type);
@@ -31,8 +37,7 @@ namespace BansheeEngine
 		 */
 		void deserializeManagedInstance(const Vector<ManagedSerializableFieldDataEntryPtr>& data);
 
-		void setFieldData(const ManagedSerializableFieldInfoPtr& fieldInfo, const ManagedSerializableFieldDataPtr& val);
-		ManagedSerializableFieldDataPtr getFieldData(const ManagedSerializableFieldInfoPtr& fieldInfo);
+		void setFieldEntries(const Vector<ManagedSerializableFieldDataEntryPtr>& data, const ManagedSerializableObjectInfoPtr& originalEntriesType);
 
 		/************************************************************************/
 		/* 								RTTI		                     		*/

+ 23 - 0
SBansheeEngine/Include/BsManagedSerializableObjectData.h

@@ -0,0 +1,23 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "BsIReflectable.h"
+#include <mono/jit/jit.h>
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ManagedSerializableObjectData : public IReflectable
+	{
+	public:
+		Vector<ManagedSerializableFieldDataEntryPtr> mFieldData;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+
+	public:
+		friend class ManagedSerializableObjectDataRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const;
+	};
+}

+ 56 - 0
SBansheeEngine/Include/BsManagedSerializableObjectDataRTTI.h

@@ -0,0 +1,56 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "BsRTTIType.h"
+#include "BsManagedSerializableObjectData.h"
+#include "BsManagedSerializableField.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ManagedSerializableObjectDataRTTI : public RTTIType <ManagedSerializableObjectData, IReflectable, ManagedSerializableObjectDataRTTI>
+	{
+	private:
+		ManagedSerializableFieldDataEntryPtr getFieldEntry(ManagedSerializableObjectData* obj, UINT32 arrayIdx)
+		{
+			return obj->mFieldData[arrayIdx];
+		}
+
+		void setFieldsEntry(ManagedSerializableObjectData* obj, UINT32 arrayIdx, ManagedSerializableFieldDataEntryPtr val)
+		{
+			obj->mFieldData[arrayIdx] = val;
+		}
+
+		UINT32 getNumFieldEntries(ManagedSerializableObjectData* obj)
+		{
+			return (UINT32)obj->mFieldData.size();
+		}
+
+		void setNumFieldEntries(ManagedSerializableObjectData* obj, UINT32 numEntries)
+		{
+			obj->mFieldData = Vector<ManagedSerializableFieldDataEntryPtr>(numEntries);
+		}
+
+	public:
+		ManagedSerializableObjectDataRTTI()
+		{
+			addReflectablePtrArrayField("mFieldEntries", 0, &ManagedSerializableObjectDataRTTI::getFieldEntry, &ManagedSerializableObjectDataRTTI::getNumFieldEntries,
+				&ManagedSerializableObjectDataRTTI::setFieldsEntry, &ManagedSerializableObjectDataRTTI::setNumFieldEntries);
+		}
+
+		virtual const String& getRTTIName()
+		{
+			static String name = "ScriptSerializableObjectData";
+			return name;
+		}
+
+		virtual UINT32 getRTTIId()
+		{
+			return TID_ScriptSerializableObjectData;
+		}
+
+		virtual std::shared_ptr<IReflectable> newRTTIObject()
+		{
+			return bs_shared_ptr<ManagedSerializableObjectData>();;
+		}
+	};
+}

+ 1 - 1
SBansheeEngine/Include/BsManagedSerializableObjectRTTI.h

@@ -2,7 +2,7 @@
 
 #include "BsScriptEnginePrerequisites.h"
 #include "BsRTTIType.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsManagedSerializableObject.h"
 #include "BsManagedSerializableField.h"
 #include "BsGameObjectManager.h"

+ 58 - 57
SBansheeEngine/Include/BsRuntimeScriptObjects.h → SBansheeEngine/Include/BsScriptAssemblyManager.h

@@ -1,58 +1,59 @@
-#pragma once
-
-#include "BsScriptEnginePrerequisites.h"
-#include "BsManagedSerializableObjectInfo.h"
-#include "BsModule.h"
-#include <mono/jit/jit.h>
-
-namespace BansheeEngine
-{
-	class BS_SCR_BE_EXPORT RuntimeScriptObjects : public Module<RuntimeScriptObjects>
-	{
-	public:
-		RuntimeScriptObjects();
-		~RuntimeScriptObjects();
-
-		void refreshScriptObjects(const String& assemblyName);
-		bool getSerializableObjectInfo(const String& ns, const String& typeName, std::shared_ptr<ManagedSerializableObjectInfo>& outInfo);
-		bool hasSerializableObjectInfo(const String& ns, const String& typeName);
-
-		Vector<String> getInitializedAssemblies() const;
-
-		MonoClass* getSystemArrayClass() const { return mSystemArrayClass; }
-		MonoClass* getSystemGenericListClass() const { return mSystemGenericListClass; }
-		MonoClass* getSystemGenericDictionaryClass() const { return mSystemGenericDictionaryClass; }
-		MonoClass* getComponentClass() const { return mComponentClass; }
-		MonoClass* getSceneObjectClass() const { return mSceneObjectClass; }
-		MonoClass* getManagedResourceClass() const { return mManagedResourceClass; }
-		MonoClass* getTextureClass() const { return mTextureClass; }
-		MonoClass* getSpriteTextureClass() const { return mSpriteTextureClass; }
-
-		ManagedSerializableTypeInfoPtr determineType(MonoClass* monoClass);
-
-		Event<void(MonoAssembly*)> onAssemblyRefreshed;
-	private:
-		UnorderedMap<String, std::shared_ptr<ManagedSerializableAssemblyInfo>> mAssemblyInfos;
-		bool mBaseTypesInitialized;
-
-		MonoClass* mSystemArrayClass;
-		MonoClass* mSystemGenericListClass;
-		MonoClass* mSystemGenericDictionaryClass;
-
-		MonoClass* mComponentClass;
-		MonoClass* mSceneObjectClass;
-
-		MonoClass* mTextureClass;
-		MonoClass* mSpriteTextureClass;
-		MonoClass* mManagedResourceClass;
-
-		MonoClass* mSerializeObjectAttribute;
-		MonoClass* mDontSerializeFieldAttribute;
-		MonoClass* mSerializeFieldAttribute;
-		MonoClass* mHideInInspectorAttribute;
-
-		void clearScriptObjects(const String& assemblyName);
-
-		void initializeBaseTypes();
-	};
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "BsManagedSerializableObjectInfo.h"
+#include "BsModule.h"
+#include <mono/jit/jit.h>
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ScriptAssemblyManager : public Module<ScriptAssemblyManager>
+	{
+	public:
+		ScriptAssemblyManager();
+		~ScriptAssemblyManager();
+
+		void loadAssemblyInfo(const String& assemblyName);
+		void refreshAssemblyInfo();
+		bool getSerializableObjectInfo(const String& ns, const String& typeName, std::shared_ptr<ManagedSerializableObjectInfo>& outInfo);
+		bool hasSerializableObjectInfo(const String& ns, const String& typeName);
+
+		Vector<String> getScriptAssemblies() const;
+
+		MonoClass* getSystemArrayClass() const { return mSystemArrayClass; }
+		MonoClass* getSystemGenericListClass() const { return mSystemGenericListClass; }
+		MonoClass* getSystemGenericDictionaryClass() const { return mSystemGenericDictionaryClass; }
+		MonoClass* getComponentClass() const { return mComponentClass; }
+		MonoClass* getSceneObjectClass() const { return mSceneObjectClass; }
+		MonoClass* getManagedResourceClass() const { return mManagedResourceClass; }
+		MonoClass* getTextureClass() const { return mTextureClass; }
+		MonoClass* getSpriteTextureClass() const { return mSpriteTextureClass; }
+		MonoClass* getFontClass() const { return mFontClass; }
+
+		ManagedSerializableTypeInfoPtr determineType(MonoClass* monoClass);
+	private:
+		UnorderedMap<String, std::shared_ptr<ManagedSerializableAssemblyInfo>> mAssemblyInfos;
+		bool mBaseTypesInitialized;
+
+		MonoClass* mSystemArrayClass;
+		MonoClass* mSystemGenericListClass;
+		MonoClass* mSystemGenericDictionaryClass;
+
+		MonoClass* mComponentClass;
+		MonoClass* mSceneObjectClass;
+
+		MonoClass* mTextureClass;
+		MonoClass* mSpriteTextureClass;
+		MonoClass* mManagedResourceClass;
+		MonoClass* mFontClass;
+
+		MonoClass* mSerializeObjectAttribute;
+		MonoClass* mDontSerializeFieldAttribute;
+		MonoClass* mSerializeFieldAttribute;
+		MonoClass* mHideInInspectorAttribute;
+
+		void clearScriptObjects();
+
+		void initializeBaseTypes();
+	};
 }

+ 6 - 0
SBansheeEngine/Include/BsScriptComponent.h

@@ -32,8 +32,14 @@ namespace BansheeEngine
 		ScriptComponent(MonoObject* instance);
 		~ScriptComponent() {}
 
+		virtual ScriptObjectBackup beginRefresh();
+		virtual void endRefresh(const ScriptObjectBackup& backupData);
+		virtual MonoObject* _createManagedInstance(bool construct);
+
 		void _onManagedInstanceDeleted();
 
 		GameObjectHandle<ManagedComponent> mManagedComponent;
+		String mNamespace;
+		String mType;
 	};
 }

+ 5 - 2
SBansheeEngine/Include/BsScriptEnginePrerequisites.h

@@ -58,9 +58,10 @@ namespace BansheeEngine
 	class ManagedSerializableAssemblyInfo;
 	class ManagedSerializableObjectInfo;
 	class ManagedSerializableFieldInfo;
+	class ManagedSerializableObjectData;
 	class ManagedResource;
 	class ManagedResourceMetaData;
-	class RuntimeScriptObjects;
+	class ScriptAssemblyManager;
 
 	typedef GameObjectHandle<ManagedComponent> HManagedComponent;
 	typedef ResourceHandle<ManagedResource> HManagedResource;
@@ -104,7 +105,8 @@ namespace BansheeEngine
 		TID_ScriptSerializableList = 50035,
 		TID_ScriptSerializableDictionary = 50036,
 		TID_ManagedResource = 50037,
-		TID_ManagedResourceMetaData = 50038
+		TID_ManagedResourceMetaData = 50038,
+		TID_ScriptSerializableObjectData = 50039
 	};
 
 	static const char* BansheeEngineAssemblyName = "MBansheeEngine";
@@ -124,6 +126,7 @@ namespace BansheeEngine
 	typedef std::shared_ptr<ManagedSerializableTypeInfoArray> ManagedSerializableTypeInfoArrayPtr;
 	typedef std::shared_ptr<ManagedSerializableTypeInfoList> ManagedSerializableTypeInfoListPtr;
 	typedef std::shared_ptr<ManagedSerializableTypeInfoDictionary> ManagedSerializableTypeInfoDictionaryPtr;
+	typedef std::shared_ptr<ManagedSerializableObjectData> ManagedSerializableObjectDataPtr;
 	typedef std::shared_ptr<ManagedResource> ManagedResourcePtr;
 	typedef std::shared_ptr<ManagedResourceMetaData> ManagedResourceMetaDataPtr;
 }

+ 8 - 4
SBansheeEngine/Include/BsScriptGameObject.h

@@ -5,16 +5,20 @@
 
 namespace BansheeEngine
 {
-	class BS_SCR_BE_EXPORT ScriptGameObjectBase : public ScriptObjectBase
+	class BS_SCR_BE_EXPORT ScriptGameObjectBase : public PersistentScriptObjectBase
 	{
 	public:
-		ScriptGameObjectBase(MonoObject* instance)
-			:ScriptObjectBase(instance)
-		{ }
+		ScriptGameObjectBase(MonoObject* instance);
 		virtual ~ScriptGameObjectBase() { }
 
 		virtual HGameObject getNativeHandle() const = 0;
 		virtual void setNativeHandle(const HGameObject& gameObject) = 0;
+
+		virtual ScriptObjectBackup beginRefresh();
+		virtual void endRefresh(const ScriptObjectBackup& backupData);
+
+	protected:
+		bool mRefreshInProgress;
 	};
 
 	class BS_SCR_BE_EXPORT ScriptGameObject : public ScriptObject<ScriptGameObject, ScriptGameObjectBase>

+ 13 - 2
SBansheeEngine/Include/BsScriptGameObjectManager.h

@@ -8,8 +8,18 @@ namespace BansheeEngine
 {
 	class BS_SCR_BE_EXPORT ScriptGameObjectManager : public Module<ScriptGameObjectManager>
 	{
+		struct ScriptGameObjectEntry
+		{
+			ScriptGameObjectEntry();
+			ScriptGameObjectEntry(ScriptGameObjectBase* instance, bool isComponent);
+
+			ScriptGameObjectBase* instance;
+			bool isComponent;
+		};
+
 	public:
 		ScriptGameObjectManager();
+		~ScriptGameObjectManager();
 
 		void registerScriptComponent(ScriptComponent* nativeInstance, const GameObjectHandle<ManagedComponent>& component);
 		ScriptSceneObject* createScriptSceneObject(const HSceneObject& sceneObject);
@@ -22,8 +32,9 @@ namespace BansheeEngine
 		void destroyScriptGameObject(ScriptGameObjectBase* gameObject);
 
 	private:
-		UnorderedMap<UINT64, ScriptGameObjectBase*> mScriptGameObjects;
+		void sendComponentResetEvents();
 
-		MonoClass* mSceneObjectClass;
+		UnorderedMap<UINT64, ScriptGameObjectEntry> mScriptGameObjects;
+		HEvent mOnAssemblyReloadDoneConn;
 	};
 }

+ 5 - 0
SBansheeEngine/Include/BsScriptManagedResource.h

@@ -22,8 +22,13 @@ namespace BansheeEngine
 
 		static void internal_createInstance(MonoObject* instance);
 
+		virtual ScriptObjectBackup beginRefresh();
+		virtual void endRefresh(const ScriptObjectBackup& backupData);
+		virtual MonoObject* _createManagedInstance(bool construct);
 		void _onManagedInstanceDeleted();
 
 		HManagedResource mResource;
+		String mNamespace;
+		String mType;
 	};
 }

+ 49 - 1
SBansheeEngine/Include/BsScriptObject.h

@@ -5,10 +5,13 @@
 #include "BsException.h"
 #include "BsMonoManager.h"
 #include "BsMonoField.h"
+#include "BsMonoClass.h"
 #include <mono/jit/jit.h>
 
 namespace BansheeEngine
 {
+	struct ScriptObjectBackup;
+
 	template <class Type, class Base>
 	struct InitScriptObjectOnStart
 	{
@@ -29,14 +32,28 @@ namespace BansheeEngine
 
 		MonoObject* getManagedInstance() const { return mManagedInstance; }
 		virtual void* getNativeRaw() const { return nullptr; }
+		virtual bool isPersistent() const { return false; }
 
+		virtual void _clearManagedInstance() { }
+		virtual void _restoreManagedInstance() { }
 		virtual void _onManagedInstanceDeleted();
 
+		virtual ScriptObjectBackup beginRefresh();
+		virtual void endRefresh(const ScriptObjectBackup& data);
+
 	protected:
-		
 		MonoObject* mManagedInstance;
 	};
 
+	class BS_SCR_BE_EXPORT PersistentScriptObjectBase : public ScriptObjectBase
+	{
+	public:
+		PersistentScriptObjectBase(MonoObject* instance);
+		virtual ~PersistentScriptObjectBase();
+
+		virtual bool isPersistent() const { return true; }
+	};
+
 	/**
 	 * @brief	 Base class for objects that can be extended using Mono scripting
 	 */
@@ -50,6 +67,7 @@ namespace BansheeEngine
 			// Compiler will only generate code for stuff that is directly used, including static data members,
 			// so we fool it here like we're using the class directly. Otherwise compiler won't generate the code for the member
 			// and our type won't get initialized on start (Actual behavior is a bit more random)
+			// TODO - Use volatile instead?
 			initOnStart.makeSureIAmInstantiated();
 
 			Type* param = (Type*)(Base*)this; // Needed due to multiple inheritance. Safe since Type must point to an class derived from this one.
@@ -61,6 +79,31 @@ namespace BansheeEngine
 		virtual ~ScriptObject() 
 		{ }
 
+		void _clearManagedInstance()
+		{
+			if (metaData.thisPtrField != nullptr && mManagedInstance != nullptr)
+				metaData.thisPtrField->setValue(mManagedInstance, nullptr);
+
+			mManagedInstance = nullptr;
+		}
+
+		void _restoreManagedInstance()
+		{
+			// Do not construct as constructor usually calls initialization code we don't need when restoring.
+			// Managed type needs to account for that on a per-type basis.
+			mManagedInstance = _createManagedInstance(false);
+
+			Type* param = (Type*)(Base*)this; // Needed due to multiple inheritance. Safe since Type must point to an class derived from this one.
+
+			if (metaData.thisPtrField != nullptr && mManagedInstance != nullptr)
+				metaData.thisPtrField->setValue(mManagedInstance, &param);
+		}
+
+		virtual MonoObject* _createManagedInstance(bool construct)
+		{
+			return metaData.scriptClass->createInstance(construct);
+		}
+
 		static Type* toNative(MonoObject* managedInstance)
 		{
 			Type* nativeInstance = nullptr;
@@ -105,6 +148,11 @@ namespace BansheeEngine
 	template <typename Type, typename Base>
 	ScriptMeta ScriptObject<Type, Base>::metaData;
 
+	struct ScriptObjectBackup
+	{
+		Any data;
+	};
+
 #define SCRIPT_OBJ(assembly, namespace, name)		\
 	static String getAssemblyName() { return assembly; }	\
 	static String getNamespace() { return namespace; }		\

+ 22 - 0
SBansheeEngine/Include/BsScriptObjectManager.h

@@ -0,0 +1,22 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "BsModule.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ScriptObjectManager : public Module <ScriptObjectManager>
+	{
+	public:
+		ScriptObjectManager();
+
+		void registerScriptObject(ScriptObjectBase* instance);
+		void unregisterScriptObject(ScriptObjectBase* instance);
+
+		void refreshAssemblies();
+
+		Event<void()> onRefreshComplete;
+	private:
+		Set<ScriptObjectBase*> mScriptObjects;
+	};
+}

+ 7 - 4
SBansheeEngine/Include/BsScriptResource.h

@@ -5,19 +5,22 @@
 
 namespace BansheeEngine
 {
-	class BS_SCR_BE_EXPORT ScriptResourceBase : public ScriptObjectBase
+	class BS_SCR_BE_EXPORT ScriptResourceBase : public PersistentScriptObjectBase
 	{
 	public:
 		virtual HResource getNativeHandle() const = 0;
 		virtual void setNativeHandle(const HResource& resource) = 0;
 
+		virtual ScriptObjectBackup beginRefresh();
+		virtual void endRefresh(const ScriptObjectBackup& backupData);
+
 	protected:
 		friend class ScriptResourceManager;
 
-		ScriptResourceBase(MonoObject* instance)
-			:ScriptObjectBase(instance)
-		{ }
+		ScriptResourceBase(MonoObject* instance);
 		virtual ~ScriptResourceBase() {}
+
+		bool mRefreshInProgress;
 	};
 
 	class BS_SCR_BE_EXPORT ScriptResource : public ScriptObject<ScriptResource, ScriptResourceBase>

+ 0 - 3
SBansheeEngine/Include/BsScriptResourceManager.h

@@ -106,9 +106,6 @@ namespace BansheeEngine
 
 	private:
 		UnorderedMap<String, ScriptResourceBase*> mScriptResources;
-		MonoClass* mTextureClass;
-		MonoClass* mSpriteTextureClass;
-		MonoClass* mFontClass;
 
 		void throwExceptionIfInvalidOrDuplicate(const String& uuid) const;
 	};

+ 7 - 2
SBansheeEngine/SBansheeEngine.vcxproj

@@ -248,7 +248,9 @@
     <ClInclude Include="Include\BsManagedSerializableList.h" />
     <ClInclude Include="Include\BsManagedSerializableListRTTI.h" />
     <ClInclude Include="Include\BsManagedSerializableObject.h" />
-    <ClInclude Include="Include\BsRuntimeScriptObjects.h" />
+    <ClInclude Include="Include\BsManagedSerializableObjectData.h" />
+    <ClInclude Include="Include\BsManagedSerializableObjectDataRTTI.h" />
+    <ClInclude Include="Include\BsScriptAssemblyManager.h" />
     <ClInclude Include="Include\BsScriptAsyncOp.h" />
     <ClInclude Include="Include\BsScriptCameraHandler.h" />
     <ClInclude Include="Include\BsScriptColor.h" />
@@ -319,7 +321,8 @@
     <ClCompile Include="Source\BsManagedResource.cpp" />
     <ClCompile Include="Source\BsManagedResourceManager.cpp" />
     <ClCompile Include="Source\BsManagedResourceMetaData.cpp" />
-    <ClCompile Include="Source\BsRuntimeScriptObjects.cpp" />
+    <ClCompile Include="Source\BsManagedSerializableObjectData.cpp" />
+    <ClCompile Include="Source\BsScriptAssemblyManager.cpp" />
     <ClCompile Include="Source\BsScriptAsyncOp.cpp" />
     <ClCompile Include="Source\BsScriptCameraHandler.cpp" />
     <ClCompile Include="Source\BsScriptColor.cpp" />
@@ -327,6 +330,7 @@
     <ClCompile Include="Source\BsScriptCursor.cpp" />
     <ClCompile Include="Source\BsScriptDebug.cpp" />
     <ClCompile Include="Source\BsScriptEnginePlugin.cpp" />
+    <ClCompile Include="Source\BsScriptGameObject.cpp" />
     <ClCompile Include="Source\BsScriptGameObjectManager.cpp" />
     <ClCompile Include="Source\BsScriptGUIButton.cpp" />
     <ClCompile Include="Source\BsScriptGUIElement.cpp" />
@@ -359,6 +363,7 @@
     <ClCompile Include="Source\BsScriptRenderTarget.cpp" />
     <ClCompile Include="Source\BsScriptRenderTexture.cpp" />
     <ClCompile Include="Source\BsScriptRenderTexture2D.cpp" />
+    <ClCompile Include="Source\BsScriptResource.cpp" />
     <ClCompile Include="Source\BsScriptResourceManager.cpp" />
     <ClCompile Include="Source\BsScriptSceneObject.cpp" />
     <ClCompile Include="Source\BsManagedSerializableArray.cpp" />

+ 21 - 6
SBansheeEngine/SBansheeEngine.vcxproj.filters

@@ -126,9 +126,6 @@
     <ClInclude Include="Include\BsScriptGUIPanel.h">
       <Filter>Header Files\GUI</Filter>
     </ClInclude>
-    <ClInclude Include="Include\BsRuntimeScriptObjects.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
     <ClInclude Include="Include\BsManagedSerializableArrayRTTI.h">
       <Filter>Header Files\Serialization\RTTI</Filter>
     </ClInclude>
@@ -276,6 +273,15 @@
     <ClInclude Include="Include\BsScriptObjectManager.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsScriptAssemblyManager.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsManagedSerializableObjectData.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsManagedSerializableObjectDataRTTI.h">
+      <Filter>Header Files\Serialization\RTTI</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsScriptTexture2D.cpp">
@@ -359,9 +365,6 @@
     <ClCompile Include="Source\BsScriptGUIPanel.cpp">
       <Filter>Source Files\GUI</Filter>
     </ClCompile>
-    <ClCompile Include="Source\BsRuntimeScriptObjects.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
     <ClCompile Include="Source\BsManagedSerializableArray.cpp">
       <Filter>Source Files\Serialization</Filter>
     </ClCompile>
@@ -485,5 +488,17 @@
     <ClCompile Include="Source\BsScriptObjectManager.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsScriptResource.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsScriptGameObject.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsScriptAssemblyManager.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsManagedSerializableObjectData.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 107 - 11
SBansheeEngine/Source/BsManagedComponent.cpp

@@ -4,17 +4,22 @@
 #include "BsMonoClass.h"
 #include "BsMonoUtil.h"
 #include "BsMonoMethod.h"
+#include "BsMemorySerializer.h"
+#include "BsManagedSerializableField.h"
+#include "BsManagedSerializableObject.h"
+#include "BsManagedSerializableObjectInfo.h"
+#include "BsManagedSerializableObjectData.h"
 #include "BsDebug.h"
 
 namespace BansheeEngine
 {
 	ManagedComponent::ManagedComponent()
-		:mUpdateThunk(nullptr), mOnDestroyThunk(nullptr), mOnInitializedThunk(nullptr)
+		:mUpdateThunk(nullptr), mOnDestroyThunk(nullptr), mOnInitializedThunk(nullptr), mOnResetThunk(nullptr)
 	{ }
 
 	ManagedComponent::ManagedComponent(const HSceneObject& parent, MonoReflectionType* runtimeType)
 		: Component(parent), mManagedInstance(nullptr), mRuntimeType(runtimeType), mUpdateThunk(nullptr), 
-		mOnDestroyThunk(nullptr), mOnInitializedThunk(nullptr)
+		mOnDestroyThunk(nullptr), mOnInitializedThunk(nullptr), mOnResetThunk(nullptr)
 	{
 		MonoType* monoType = mono_reflection_type_get_type(mRuntimeType);
 		::MonoClass* monoClass = mono_type_get_class(monoType);
@@ -31,7 +36,7 @@ namespace BansheeEngine
 
 		setName(mTypeName);
 
-		initialize(managedClass->createInstance(), runtimeType, managedClass);
+		initialize(managedClass->createInstance());
 	}
 
 	ManagedComponent::~ManagedComponent()
@@ -43,25 +48,100 @@ namespace BansheeEngine
 		}
 	}
 
-	void ManagedComponent::initialize(MonoObject* object, MonoReflectionType* runtimeType, MonoClass* monoClass)
+	ComponentBackupData ManagedComponent::backup(bool clearExisting)
 	{
-		mFullTypeName = mNamespace + "." + mTypeName;
+		ManagedSerializableObjectPtr serializableObject = ManagedSerializableObject::createFromExisting(mManagedInstance);
+
+		// Serialize the object information and its fields. We cannot just serialize the entire object because
+		// the managed instance had to be created in a previous step. So we handle creation of the top level object manually.
+		ComponentBackupData backupData;
+		if (serializableObject != nullptr)
+		{
+			ManagedSerializableObjectInfoPtr objectInfo = serializableObject->getObjectInfo();
+			ManagedSerializableObjectDataPtr objectData = serializableObject->getObjectData();
+
+			MemorySerializer ms;
+
+			backupData.mTypeInfo.size = 0;
+			backupData.mTypeInfo.data = ms.encode(objectInfo.get(), backupData.mTypeInfo.size);
+
+			backupData.mObjectData.size = 0;
+			backupData.mObjectData.data = ms.encode(objectData.get(), backupData.mObjectData.size);
+		}
+		else
+		{
+			backupData.mTypeInfo.size = 0;
+			backupData.mTypeInfo.data = nullptr;
+
+			backupData.mObjectData.size = 0;
+			backupData.mObjectData.data = nullptr;
+		}
 
+		if (clearExisting)
+		{
+			if (mManagedInstance != nullptr)
+			{
+				mManagedInstance = nullptr;
+				mono_gchandle_free(mManagedHandle);
+				mManagedHandle = 0;
+			}
+
+			mRuntimeType = nullptr;
+			mOnInitializedThunk = nullptr;
+			mUpdateThunk = nullptr;
+			mOnDestroyThunk = nullptr;
+		}
+
+		return backupData;
+	}
+
+	void ManagedComponent::restore(MonoObject* instance, const ComponentBackupData& data)
+	{
+		initialize(instance);
+
+		if (instance != nullptr && data.mTypeInfo.data != nullptr && data.mObjectData.data != nullptr)
+		{
+			MemorySerializer ms;
+			ManagedSerializableObjectInfoPtr objectInfo = std::static_pointer_cast<ManagedSerializableObjectInfo>(ms.decode(data.mTypeInfo.data, data.mTypeInfo.size));
+			ManagedSerializableObjectDataPtr objectData = std::static_pointer_cast<ManagedSerializableObjectData>(ms.decode(data.mObjectData.data, data.mObjectData.size));
+
+			ManagedSerializableObjectPtr serializableObject = ManagedSerializableObject::createFromExisting(instance);
+			serializableObject->setObjectData(objectData, objectInfo);
+		}
+	}
+
+	void ManagedComponent::initialize(MonoObject* object)
+	{
+		mFullTypeName = mNamespace + "." + mTypeName;
 		mManagedInstance = object;
-		mRuntimeType = runtimeType;
-		mManagedHandle = mono_gchandle_new(mManagedInstance, false);
+		
+		MonoClass* managedClass = nullptr;
+		if (mManagedInstance != nullptr)
+		{
+			mManagedHandle = mono_gchandle_new(mManagedInstance, false);
 
-		if (monoClass != nullptr)
+			::MonoClass* monoClass = mono_object_get_class(object);
+			MonoType* monoType = mono_class_get_type(monoClass);
+			mRuntimeType = mono_type_get_object(MonoManager::instance().getDomain(), monoType);
+
+			managedClass = MonoManager::instance().findClass(monoClass);
+		}
+
+		if (managedClass != nullptr)
 		{
-			MonoMethod* onInitializedMethod = monoClass->getMethod("OnInitialize", 0);
+			MonoMethod* onInitializedMethod = managedClass->getMethod("OnInitialize", 0);
 			if (onInitializedMethod != nullptr)
 				mOnInitializedThunk = (OnInitializedThunkDef)onInitializedMethod->getThunk();
 
-			MonoMethod* updateMethod = monoClass->getMethod("Update", 0);
+			MonoMethod* updateMethod = managedClass->getMethod("Update", 0);
 			if (updateMethod != nullptr)
 				mUpdateThunk = (UpdateThunkDef)updateMethod->getThunk();
 
-			MonoMethod* onDestroyMethod = monoClass->getMethod("OnDestroy", 0);
+			MonoMethod* onResetMethod = managedClass->getMethod("OnReset", 0);
+			if (onResetMethod != nullptr)
+				mOnResetThunk = (OnResetThunkDef)onResetMethod->getThunk();
+
+			MonoMethod* onDestroyMethod = managedClass->getMethod("OnDestroy", 0);
 			if (onDestroyMethod != nullptr)
 				mOnDestroyThunk = (OnDestroyedThunkDef)onDestroyMethod->getThunk();
 		}
@@ -81,6 +161,20 @@ namespace BansheeEngine
 		}
 	}
 
+	void ManagedComponent::triggerOnReset()
+	{
+		if (mOnResetThunk != nullptr && mManagedInstance != nullptr)
+		{
+			MonoException* exception = nullptr;
+
+			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
+			// for some extra speed.
+			mOnResetThunk(mManagedInstance, &exception);
+
+			MonoUtil::throwIfException(exception);
+		}
+	}
+
 	void ManagedComponent::onInitialized()
 	{
 		assert(mManagedInstance != nullptr);
@@ -115,6 +209,8 @@ namespace BansheeEngine
 
 			MonoUtil::throwIfException(exception);
 		}
+
+		triggerOnReset();
 	}
 
 	void ManagedComponent::onDestroyed()

+ 70 - 0
SBansheeEngine/Source/BsManagedResource.cpp

@@ -5,6 +5,11 @@
 #include "BsMonoClass.h"
 #include "BsResources.h"
 #include "BsManagedResourceManager.h"
+#include "BsManagedSerializableField.h"
+#include "BsManagedSerializableObject.h"
+#include "BsManagedSerializableObjectInfo.h"
+#include "BsManagedSerializableObjectData.h"
+#include "BsMemorySerializer.h"
 #include "BsDebug.h"
 
 namespace BansheeEngine
@@ -32,6 +37,71 @@ namespace BansheeEngine
 		}
 	}
 
+	ResourceBackupData ManagedResource::backup(bool clearExisting)
+	{
+		ManagedSerializableObjectPtr serializableObject = ManagedSerializableObject::createFromExisting(mManagedInstance);
+
+		ResourceBackupData backupData;
+		if (serializableObject != nullptr)
+		{
+			ManagedSerializableObjectInfoPtr objectInfo = serializableObject->getObjectInfo();
+			ManagedSerializableObjectDataPtr objectData = serializableObject->getObjectData();
+
+			MemorySerializer ms;
+
+			backupData.mTypeInfo.size = 0;
+			backupData.mTypeInfo.data = ms.encode(objectInfo.get(), backupData.mTypeInfo.size);
+
+			backupData.mObjectData.size = 0;
+			backupData.mObjectData.data = ms.encode(objectData.get(), backupData.mObjectData.size);
+		}
+		else
+		{
+			backupData.mTypeInfo.size = 0;
+			backupData.mTypeInfo.data = nullptr;
+
+			backupData.mObjectData.size = 0;
+			backupData.mObjectData.data = nullptr;
+		}
+
+		if (clearExisting)
+		{
+			if (mManagedInstance != nullptr)
+			{
+				mManagedInstance = nullptr;
+				mono_gchandle_free(mManagedHandle);
+				mManagedHandle = 0;
+			}
+		}
+
+		return backupData;
+	}
+
+	void ManagedResource::restore(MonoObject* instance, const ResourceBackupData& data)
+	{
+		mManagedInstance = instance;
+
+		if (mManagedInstance != nullptr)
+		{
+			mManagedHandle = mono_gchandle_new(mManagedInstance, false);
+
+			if (data.mTypeInfo.data != nullptr && data.mObjectData.data != nullptr)
+			{
+				MemorySerializer ms;
+				ManagedSerializableObjectInfoPtr objectInfo = std::static_pointer_cast<ManagedSerializableObjectInfo>(ms.decode(data.mTypeInfo.data, data.mTypeInfo.size));
+				ManagedSerializableObjectDataPtr objectData = std::static_pointer_cast<ManagedSerializableObjectData>(ms.decode(data.mObjectData.data, data.mObjectData.size));
+
+				ManagedSerializableObjectPtr serializableObject = ManagedSerializableObject::createFromExisting(instance);
+				serializableObject->setObjectData(objectData, objectInfo);
+			}
+		}
+		else
+		{
+			// Could not restore resource
+			ManagedResourceManager::instance().unregisterManagedResource(mMyHandle);
+		}
+	}
+
 	HManagedResource ManagedResource::create(MonoObject* managedResource)
 	{
 		ManagedResourcePtr newRes = bs_core_ptr<ManagedResource, GenAlloc>(new (bs_alloc<ManagedResource>()) ManagedResource(managedResource));

+ 4 - 4
SBansheeEngine/Source/BsManagedSerializableArray.cpp

@@ -1,7 +1,7 @@
 #include "BsManagedSerializableArray.h"
 #include "BsManagedSerializableArrayRTTI.h"
 #include "BsMonoManager.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsManagedSerializableField.h"
 #include "BsMonoClass.h"
 #include "BsMonoMethod.h"
@@ -32,7 +32,7 @@ namespace BansheeEngine
 		if(managedInstance == nullptr)
 			return nullptr;
 
-		if(!RuntimeScriptObjects::instance().getSystemArrayClass()->isInstanceOfType(managedInstance))
+		if(!ScriptAssemblyManager::instance().getSystemArrayClass()->isInstanceOfType(managedInstance))
 			return nullptr;
 
 		return bs_shared_ptr<ManagedSerializableArray>(ConstructPrivately(), typeInfo, managedInstance);
@@ -53,7 +53,7 @@ namespace BansheeEngine
 		if (!typeInfo->isTypeLoaded())
 			return nullptr;
 
-		MonoClass* arrayClass = RuntimeScriptObjects::instance().getSystemArrayClass();
+		MonoClass* arrayClass = ScriptAssemblyManager::instance().getSystemArrayClass();
 
 		MonoMethod* createInstance = arrayClass->getMethodExact("CreateInstance", "Type,int[]");
 		MonoArray* lengthArray = mono_array_new(MonoManager::instance().getDomain(), mono_get_int32_class(), (UINT32)sizes.size());
@@ -161,7 +161,7 @@ namespace BansheeEngine
 
 	UINT32 ManagedSerializableArray::getLength(UINT32 dimension) const
 	{
-		MonoClass* systemArray = RuntimeScriptObjects::instance().getSystemArrayClass();
+		MonoClass* systemArray = ScriptAssemblyManager::instance().getSystemArrayClass();
 		MonoMethod* getLength = systemArray->getMethod("GetLength", 1);
 
 		void* params[1] = { &dimension };

+ 2 - 2
SBansheeEngine/Source/BsManagedSerializableDictionary.cpp

@@ -1,7 +1,7 @@
 #include "BsManagedSerializableDictionary.h"
 #include "BsManagedSerializableDictionaryRTTI.h"
 #include "BsMonoManager.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsManagedSerializableField.h"
 #include "BsMonoClass.h"
 #include "BsMonoMethod.h"
@@ -62,7 +62,7 @@ namespace BansheeEngine
 		String elementTypeName = mono_class_get_name(monoClass);
 		String fullName = elementNs + "." + elementTypeName;
 
-		if(RuntimeScriptObjects::instance().getSystemGenericDictionaryClass()->getFullName() != fullName)
+		if(ScriptAssemblyManager::instance().getSystemGenericDictionaryClass()->getFullName() != fullName)
 			return nullptr;
 
 		return bs_shared_ptr<ManagedSerializableDictionary>(ConstructPrivately(), typeInfo, managedInstance);

+ 2 - 2
SBansheeEngine/Source/BsManagedSerializableList.cpp

@@ -1,7 +1,7 @@
 #include "BsManagedSerializableList.h"
 #include "BsManagedSerializableListRTTI.h"
 #include "BsMonoManager.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsManagedSerializableField.h"
 #include "BsMonoClass.h"
 #include "BsMonoMethod.h"
@@ -38,7 +38,7 @@ namespace BansheeEngine
 		String elementTypeName = mono_class_get_name(monoClass);
 		String fullName = elementNs + "." + elementTypeName;
 
-		if(RuntimeScriptObjects::instance().getSystemGenericListClass()->getFullName() != fullName)
+		if(ScriptAssemblyManager::instance().getSystemGenericListClass()->getFullName() != fullName)
 			return nullptr;
 
 		return bs_shared_ptr<ManagedSerializableList>(ConstructPrivately(), typeInfo, managedInstance);

+ 55 - 27
SBansheeEngine/Source/BsManagedSerializableObject.cpp

@@ -2,7 +2,8 @@
 #include "BsManagedSerializableObjectRTTI.h"
 #include "BsManagedSerializableObjectInfo.h"
 #include "BsManagedSerializableField.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
+#include "BsManagedSerializableObjectData.h"
 #include "BsMonoField.h"
 
 namespace BansheeEngine
@@ -29,7 +30,7 @@ namespace BansheeEngine
 		String elementTypeName = mono_class_get_name(monoClass);
 
 		ManagedSerializableObjectInfoPtr objInfo;
-		if(!RuntimeScriptObjects::instance().getSerializableObjectInfo(elementNs, elementTypeName, objInfo))
+		if(!ScriptAssemblyManager::instance().getSerializableObjectInfo(elementNs, elementTypeName, objInfo))
 			return nullptr;
 
 		return bs_shared_ptr<ManagedSerializableObject>(ConstructPrivately(), objInfo, managedInstance);
@@ -40,7 +41,7 @@ namespace BansheeEngine
 		ManagedSerializableObjectInfoPtr currentObjInfo = nullptr;
 
 		// See if this type even still exists
-		if (!RuntimeScriptObjects::instance().getSerializableObjectInfo(type->mTypeNamespace, type->mTypeName, currentObjInfo))
+		if (!ScriptAssemblyManager::instance().getSerializableObjectInfo(type->mTypeNamespace, type->mTypeName, currentObjInfo))
 			return nullptr;
 
 		return bs_shared_ptr<ManagedSerializableObject>(ConstructPrivately(), currentObjInfo, createManagedInstance(type));
@@ -51,7 +52,7 @@ namespace BansheeEngine
 		ManagedSerializableObjectInfoPtr currentObjInfo = nullptr;
 
 		// See if this type even still exists
-		if (!RuntimeScriptObjects::instance().getSerializableObjectInfo(type->mTypeNamespace, type->mTypeName, currentObjInfo))
+		if (!ScriptAssemblyManager::instance().getSerializableObjectInfo(type->mTypeNamespace, type->mTypeName, currentObjInfo))
 			return nullptr;
 
 		if (type->mValueType)
@@ -67,27 +68,25 @@ namespace BansheeEngine
 
 	void ManagedSerializableObject::deserializeManagedInstance(const Vector<ManagedSerializableFieldDataEntryPtr>& entries)
 	{
-		ManagedSerializableObjectInfoPtr storedObjInfo = mObjInfo;
-		ManagedSerializableObjectInfoPtr currentObjInfo = nullptr;
-
-		// See if this type even still exists
-		if(!RuntimeScriptObjects::instance().getSerializableObjectInfo(storedObjInfo->mTypeInfo->mTypeNamespace, storedObjInfo->mTypeInfo->mTypeName, currentObjInfo))
-			return;
-
-		mManagedInstance = createManagedInstance(storedObjInfo->mTypeInfo);
+		mManagedInstance = createManagedInstance(mObjInfo->mTypeInfo);
 
 		if (mManagedInstance == nullptr)
 			return;
 
-		auto findFieldInfoFromKey = [&] (UINT16 typeId, UINT16 fieldId, ManagedSerializableObjectInfoPtr objInfo, 
+		setFieldEntries(entries, mObjInfo);
+	}
+
+	void ManagedSerializableObject::setFieldEntries(const Vector<ManagedSerializableFieldDataEntryPtr>& entries, const ManagedSerializableObjectInfoPtr& originalEntriesType)
+	{
+		auto findFieldInfoFromKey = [&](UINT16 typeId, UINT16 fieldId, ManagedSerializableObjectInfoPtr objInfo,
 			ManagedSerializableFieldInfoPtr& outFieldInfo, ManagedSerializableObjectInfoPtr &outObjInfo) -> bool
 		{
-			while(objInfo != nullptr)
+			while (objInfo != nullptr)
 			{
-				if(objInfo->mTypeId == typeId)
+				if (objInfo->mTypeId == typeId)
 				{
 					auto iterFind = objInfo->mFields.find(fieldId);
-					if(iterFind != objInfo->mFields.end())
+					if (iterFind != objInfo->mFields.end())
 					{
 						outFieldInfo = iterFind->second;
 						outObjInfo = objInfo;
@@ -104,23 +103,23 @@ namespace BansheeEngine
 			return false;
 		};
 
-		auto findTypeNameMatchingFieldInfo = [&] (const ManagedSerializableFieldInfoPtr& fieldInfo, const ManagedSerializableObjectInfoPtr& fieldObjInfo, 
+		auto findTypeNameMatchingFieldInfo = [&](const ManagedSerializableFieldInfoPtr& fieldInfo, const ManagedSerializableObjectInfoPtr& fieldObjInfo,
 			ManagedSerializableObjectInfoPtr objInfo) -> ManagedSerializableFieldInfoPtr
 		{
-			while(objInfo != nullptr)
+			while (objInfo != nullptr)
 			{
-				if(objInfo->mTypeInfo->matches(fieldObjInfo->mTypeInfo))
+				if (objInfo->mTypeInfo->matches(fieldObjInfo->mTypeInfo))
 				{
 					auto iterFind = objInfo->mFieldNameToId.find(fieldInfo->mName);
-					if(iterFind != objInfo->mFieldNameToId.end())
+					if (iterFind != objInfo->mFieldNameToId.end())
 					{
 						auto iterFind2 = objInfo->mFields.find(iterFind->second);
-						if(iterFind2 != objInfo->mFields.end())
+						if (iterFind2 != objInfo->mFields.end())
 						{
 							ManagedSerializableFieldInfoPtr foundField = iterFind2->second;
-							if(foundField->isSerializable())
+							if (foundField->isSerializable())
 							{
-								if(fieldInfo->mTypeInfo->matches(foundField->mTypeInfo))
+								if (fieldInfo->mTypeInfo->matches(foundField->mTypeInfo))
 									return foundField;
 							}
 						}
@@ -135,17 +134,23 @@ namespace BansheeEngine
 			return nullptr;
 		};
 
+		ManagedSerializableObjectInfoPtr currentObjInfo = nullptr;
+
+		// See if this type even still exists
+		if (!ScriptAssemblyManager::instance().getSerializableObjectInfo(originalEntriesType->mTypeInfo->mTypeNamespace, originalEntriesType->mTypeInfo->mTypeName, currentObjInfo))
+			return;
+
 		// Scan all fields and ensure the fields still exist
-		for(auto& fieldEntry : entries)
+		for (auto& fieldEntry : entries)
 		{
 			ManagedSerializableFieldInfoPtr storedFieldEntry;
 			ManagedSerializableObjectInfoPtr storedFieldObjEntry;
 
-			if(!findFieldInfoFromKey(fieldEntry->mKey->mTypeId, fieldEntry->mKey->mFieldId, storedObjInfo, storedFieldEntry, storedFieldObjEntry))
+			if (!findFieldInfoFromKey(fieldEntry->mKey->mTypeId, fieldEntry->mKey->mFieldId, originalEntriesType, storedFieldEntry, storedFieldObjEntry))
 				continue;
 
 			ManagedSerializableFieldInfoPtr matchingFieldInfo = findTypeNameMatchingFieldInfo(storedFieldEntry, storedFieldObjEntry, currentObjInfo);
-			if(matchingFieldInfo != nullptr)
+			if (matchingFieldInfo != nullptr)
 				setFieldData(matchingFieldInfo, fieldEntry->mValue);
 		}
 	}
@@ -155,13 +160,36 @@ namespace BansheeEngine
 		fieldInfo->mMonoField->setValue(mManagedInstance, val->getValue(fieldInfo->mTypeInfo));
 	}
 
-	ManagedSerializableFieldDataPtr ManagedSerializableObject::getFieldData(const ManagedSerializableFieldInfoPtr& fieldInfo)
+	ManagedSerializableFieldDataPtr ManagedSerializableObject::getFieldData(const ManagedSerializableFieldInfoPtr& fieldInfo) const
 	{
 		MonoObject* fieldValue = fieldInfo->mMonoField->getValueBoxed(mManagedInstance);
 
 		return ManagedSerializableFieldData::create(fieldInfo->mTypeInfo, fieldValue);		
 	}
 
+	void ManagedSerializableObject::setObjectData(const ManagedSerializableObjectDataPtr& objectData, const ManagedSerializableObjectInfoPtr& originalEntriesType)
+	{
+		setFieldEntries(objectData->mFieldData, originalEntriesType);
+	}
+
+	ManagedSerializableObjectDataPtr ManagedSerializableObject::getObjectData() const
+	{
+		ManagedSerializableObjectDataPtr objectData = bs_shared_ptr<ManagedSerializableObjectData>();
+		objectData->mFieldData = Vector<ManagedSerializableFieldDataEntryPtr>(mObjInfo->mCachedAllFields.size());
+
+		UINT32 i = 0;
+		for (auto& field : mObjInfo->mCachedAllFields)
+		{
+			ManagedSerializableFieldKeyPtr fieldKey = ManagedSerializableFieldKey::create(field.parentTypeId, field.info->mFieldId);
+			ManagedSerializableFieldDataPtr fieldData = getFieldData(field.info);
+
+			objectData->mFieldData[i] = ManagedSerializableFieldDataEntry::create(fieldKey, fieldData);
+			i++;
+		}
+
+		return objectData;
+	}
+
 	RTTITypeBase* ManagedSerializableObject::getRTTIStatic()
 	{
 		return ManagedSerializableObjectRTTI::instance();

+ 15 - 0
SBansheeEngine/Source/BsManagedSerializableObjectData.cpp

@@ -0,0 +1,15 @@
+#include "BsManagedSerializableObjectData.h"
+#include "BsManagedSerializableObjectDataRTTI.h"
+
+namespace BansheeEngine
+{
+	RTTITypeBase* ManagedSerializableObjectData::getRTTIStatic()
+	{
+		return ManagedSerializableObjectDataRTTI::instance();
+	}
+
+	RTTITypeBase* ManagedSerializableObjectData::getRTTI() const
+	{
+		return ManagedSerializableObjectData::getRTTIStatic();
+	}
+}

+ 10 - 10
SBansheeEngine/Source/BsManagedSerializableObjectInfo.cpp

@@ -11,7 +11,7 @@
 #include "BsScriptComponent.h"
 #include "BsScriptSceneObject.h"
 #include "BsManagedSerializableObjectInfo.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 
 namespace BansheeEngine
 {
@@ -130,15 +130,15 @@ namespace BansheeEngine
 		case ScriptPrimitiveType::String:
 			return mono_get_string_class();
 		case ScriptPrimitiveType::TextureRef:
-			return RuntimeScriptObjects::instance().getTextureClass()->_getInternalClass();
+			return ScriptAssemblyManager::instance().getTextureClass()->_getInternalClass();
 		case ScriptPrimitiveType::SpriteTextureRef:
-			return RuntimeScriptObjects::instance().getSpriteTextureClass()->_getInternalClass();
+			return ScriptAssemblyManager::instance().getSpriteTextureClass()->_getInternalClass();
 		case ScriptPrimitiveType::ManagedResourceRef:
-			return RuntimeScriptObjects::instance().getManagedResourceClass()->_getInternalClass();
+			return ScriptAssemblyManager::instance().getManagedResourceClass()->_getInternalClass();
 		case ScriptPrimitiveType::SceneObjectRef:
-			return RuntimeScriptObjects::instance().getSceneObjectClass()->_getInternalClass();
+			return ScriptAssemblyManager::instance().getSceneObjectClass()->_getInternalClass();
 		case ScriptPrimitiveType::ComponentRef:
-			return RuntimeScriptObjects::instance().getComponentClass()->_getInternalClass();
+			return ScriptAssemblyManager::instance().getComponentClass()->_getInternalClass();
 		}
 
 		return nullptr;
@@ -166,13 +166,13 @@ namespace BansheeEngine
 
 	bool ManagedSerializableTypeInfoObject::isTypeLoaded() const
 	{
-		return RuntimeScriptObjects::instance().hasSerializableObjectInfo(mTypeNamespace, mTypeName);
+		return ScriptAssemblyManager::instance().hasSerializableObjectInfo(mTypeNamespace, mTypeName);
 	}
 
 	::MonoClass* ManagedSerializableTypeInfoObject::getMonoClass() const
 	{
 		ManagedSerializableObjectInfoPtr objInfo;
-		if(!RuntimeScriptObjects::instance().getSerializableObjectInfo(mTypeNamespace, mTypeName, objInfo))
+		if(!ScriptAssemblyManager::instance().getSerializableObjectInfo(mTypeNamespace, mTypeName, objInfo))
 			return nullptr;
 
 		return objInfo->mMonoClass->_getInternalClass();
@@ -243,7 +243,7 @@ namespace BansheeEngine
 		if(elementClass == nullptr)
 			return nullptr;
 
-		MonoClass* genericListClass = RuntimeScriptObjects::instance().getSystemGenericListClass();
+		MonoClass* genericListClass = ScriptAssemblyManager::instance().getSystemGenericListClass();
 		MonoType* genParams[1] = { mono_class_get_type(elementClass) };
 
 		return mono_class_bind_generic_parameters(genericListClass->_getInternalClass(), 1, genParams, false);
@@ -281,7 +281,7 @@ namespace BansheeEngine
 		if(keyClass == nullptr || valueClass == nullptr)
 			return nullptr;
 
-		MonoClass* genericDictionaryClass = RuntimeScriptObjects::instance().getSystemGenericDictionaryClass();
+		MonoClass* genericDictionaryClass = ScriptAssemblyManager::instance().getSystemGenericDictionaryClass();
 		MonoType* genParams[2] = { mono_class_get_type(keyClass), mono_class_get_type(valueClass) };
 
 		return mono_class_bind_generic_parameters(genericDictionaryClass->_getInternalClass(), 2, genParams, false);

+ 481 - 470
SBansheeEngine/Source/BsRuntimeScriptObjects.cpp → SBansheeEngine/Source/BsScriptAssemblyManager.cpp

@@ -1,471 +1,482 @@
-#include "BsRuntimeScriptObjects.h"
-#include "BsScriptResourceManager.h"
-#include "BsScriptGameObjectManager.h"
-#include "BsManagedSerializableObjectInfo.h"
-#include "BsMonoManager.h"
-#include "BsMonoAssembly.h"
-#include "BsMonoClass.h"
-#include "BsMonoField.h"
-#include "BsMonoMethod.h"
-#include "BsMonoProperty.h"
-#include "BsMonoUtil.h"
-#include "BsRTTIType.h"
-
-namespace BansheeEngine
-{
-	RuntimeScriptObjects::RuntimeScriptObjects()
-		:mBaseTypesInitialized(false), mSerializeObjectAttribute(nullptr), mDontSerializeFieldAttribute(nullptr), 
-		mComponentClass(nullptr), mSceneObjectClass(nullptr), mTextureClass(nullptr), mSpriteTextureClass(nullptr),
-		mSerializeFieldAttribute(nullptr), mHideInInspectorAttribute(nullptr), mSystemArrayClass(nullptr), mSystemGenericListClass(nullptr),
-		mSystemGenericDictionaryClass(nullptr), mManagedResourceClass(nullptr)
-	{
-
-	}
-
-	RuntimeScriptObjects::~RuntimeScriptObjects()
-	{
-
-	}
-
-	Vector<String> RuntimeScriptObjects::getInitializedAssemblies() const
-	{
-		Vector<String> initializedAssemblies;
-		for (auto& assemblyPair : mAssemblyInfos)
-			initializedAssemblies.push_back(assemblyPair.first);
-
-		return initializedAssemblies;
-	}
-
-	void RuntimeScriptObjects::refreshScriptObjects(const String& assemblyName)
-	{
-		clearScriptObjects(assemblyName);
-
-		if(!mBaseTypesInitialized)
-			initializeBaseTypes();
-
-		// Process all classes and fields
-		UINT32 mUniqueTypeId = 1;
-
-		MonoAssembly* curAssembly = MonoManager::instance().getAssembly(assemblyName);
-		if(curAssembly == nullptr)
-			return;
-
-		std::shared_ptr<ManagedSerializableAssemblyInfo> assemblyInfo = bs_shared_ptr<ManagedSerializableAssemblyInfo>();
-		assemblyInfo->mName = assemblyName;
-
-		mAssemblyInfos[assemblyName] = assemblyInfo;
-
-		// Populate class data
-		const Vector<MonoClass*>& allClasses = curAssembly->getAllClasses();
-		for(auto& curClass : allClasses)
-		{
-			if((curClass->isSubClassOf(mComponentClass) || curClass->isSubClassOf(mManagedResourceClass) || 
-				curClass->hasAttribute(mSerializeObjectAttribute)) && curClass != mComponentClass && curClass != mManagedResourceClass)
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoObject> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoObject>();
-				typeInfo->mTypeNamespace = curClass->getNamespace();
-				typeInfo->mTypeName = curClass->getTypeName();
-
-				MonoType* monoType = mono_class_get_type(curClass->_getInternalClass());
-				int monoPrimitiveType = mono_type_get_type(monoType);
-
-				if(monoPrimitiveType == MONO_TYPE_VALUETYPE)
-					typeInfo->mValueType = true;
-				else
-					typeInfo->mValueType = false;
-
-				std::shared_ptr<ManagedSerializableObjectInfo> objInfo = bs_shared_ptr<ManagedSerializableObjectInfo>();
-
-				objInfo->mTypeId = mUniqueTypeId++;
-
-				objInfo->mTypeInfo = typeInfo;
-				objInfo->mMonoClass = curClass;
-
-				assemblyInfo->mTypeNameToId[objInfo->getFullTypeName()] = objInfo->mTypeId;
-				assemblyInfo->mObjectInfos[objInfo->mTypeId] = objInfo;
-			}
-		}
-
-		// Populate field data
-		for(auto& curClassInfo : assemblyInfo->mObjectInfos)
-		{
-			std::shared_ptr<ManagedSerializableObjectInfo> objInfo = curClassInfo.second;
-
-			UINT32 mUniqueFieldId = 1;
-			const Vector<MonoField*>& fields = objInfo->mMonoClass->getAllFields();
-
-			for(auto& field : fields)
-			{
-				if(field->isStatic())
-					continue;
-
-				ManagedSerializableTypeInfoPtr typeInfo = determineType(field->getType());
-				if (typeInfo == nullptr)
-					continue;
-
-				std::shared_ptr<ManagedSerializableFieldInfo> fieldInfo = bs_shared_ptr<ManagedSerializableFieldInfo>();
-				fieldInfo->mFieldId = mUniqueFieldId++;
-				fieldInfo->mName = field->getName();
-				fieldInfo->mMonoField = field;
-				fieldInfo->mTypeInfo = typeInfo;
-				
-				MonoFieldVisibility visibility = field->getVisibility();
-				if (visibility == MonoFieldVisibility::Public)
-				{
-					if (!field->hasAttribute(mDontSerializeFieldAttribute))
-						fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Serializable);
-
-					if (!field->hasAttribute(mHideInInspectorAttribute))
-						fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Inspectable);
-				}
-				else
-				{
-					if (field->hasAttribute(mSerializeFieldAttribute))
-						fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Serializable);
-				}
-
-				objInfo->mFieldNameToId[fieldInfo->mName] = fieldInfo->mFieldId;
-				objInfo->mFields[fieldInfo->mFieldId] = fieldInfo;
-			}
-		}
-
-		// Form parent/child connections
-		for(auto& curClass : assemblyInfo->mObjectInfos)
-		{
-			MonoClass* base = curClass.second->mMonoClass->getBaseClass();
-			while(base != nullptr)
-			{
-				std::shared_ptr<ManagedSerializableObjectInfo> baseObjInfo;
-				if(getSerializableObjectInfo(base->getNamespace(), base->getTypeName(), baseObjInfo))
-				{
-					curClass.second->mBaseClass = baseObjInfo;
-					baseObjInfo->mDerivedClasses.push_back(curClass.second);
-
-					break;
-				}
-
-				base = base->getBaseClass();
-			}
-		}
-
-		// Finish object info initialization
-		for (auto& curClassInfo : assemblyInfo->mObjectInfos)
-		{
-			std::shared_ptr<ManagedSerializableObjectInfo> objInfo = curClassInfo.second;
-			objInfo->initialize();
-		}
-
-		onAssemblyRefreshed(curAssembly);
-	}
-
-	ManagedSerializableTypeInfoPtr RuntimeScriptObjects::determineType(MonoClass* monoClass)
-	{
-		if(!mBaseTypesInitialized)
-			BS_EXCEPT(InvalidStateException, "Calling determineType without previously initializing base types.");
-
-		MonoType* monoType = mono_class_get_type(monoClass->_getInternalClass());
-		int monoPrimitiveType = mono_type_get_type(monoType);
-
-		//  Determine field type
-		switch(monoPrimitiveType)
-		{
-		case MONO_TYPE_BOOLEAN:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::Bool;
-				return typeInfo;
-			}
-		case MONO_TYPE_CHAR:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::Char;
-				return typeInfo;
-			}
-		case MONO_TYPE_I1:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::I8;
-				return typeInfo;
-			}
-		case MONO_TYPE_U1:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::U8;
-				return typeInfo;
-			}
-		case MONO_TYPE_I2:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::I16;
-				return typeInfo;
-			}
-		case MONO_TYPE_U2:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::U16;
-				return typeInfo;
-			}
-		case MONO_TYPE_I4:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::I32;
-				return typeInfo;
-			}
-		case MONO_TYPE_U4:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::U32;
-				return typeInfo;
-			}
-		case MONO_TYPE_I8:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::I64;
-				return typeInfo;
-			}
-		case MONO_TYPE_U8:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::U64;
-				return typeInfo;
-			}
-		case MONO_TYPE_STRING:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::String;
-				return typeInfo;
-			}
-		case MONO_TYPE_R4:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::Float;
-				return typeInfo;
-			}
-		case MONO_TYPE_R8:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::Double;
-				return typeInfo;
-			}
-		case MONO_TYPE_CLASS:
-			if(monoClass->isSubClassOf(mTextureClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::TextureRef;
-				return typeInfo;
-			}
-			else if(monoClass->isSubClassOf(mSpriteTextureClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::SpriteTextureRef;
-				return typeInfo;
-			}
-			else if (monoClass->isSubClassOf(mManagedResourceClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::ManagedResourceRef;
-				return typeInfo;
-			}
-			else if(monoClass->isSubClassOf(mSceneObjectClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::SceneObjectRef;
-				return typeInfo;
-			}
-			else if(monoClass->isSubClassOf(mComponentClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::ComponentRef;
-				return typeInfo;
-			}
-			else
-			{
-				std::shared_ptr<ManagedSerializableObjectInfo> objInfo;
-				if (getSerializableObjectInfo(monoClass->getNamespace(), monoClass->getTypeName(), objInfo))
-					return objInfo->mTypeInfo;
-			}
-
-			break;
-		case MONO_TYPE_VALUETYPE:
-			{
-				std::shared_ptr<ManagedSerializableObjectInfo> objInfo;
-				if (getSerializableObjectInfo(monoClass->getNamespace(), monoClass->getTypeName(), objInfo))
-					return objInfo->mTypeInfo;
-			}
-
-			break;
-		case MONO_TYPE_GENERICINST:
-			if(monoClass->getFullName() == mSystemGenericListClass->getFullName()) // Full name is part of CIL spec, so it is just fine to compare like this
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoList> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoList>();
-
-				MonoProperty& itemProperty = monoClass->getProperty("Item");
-				MonoClass* itemClass = itemProperty.getReturnType();
-
-				if(itemClass != nullptr)
-					typeInfo->mElementType = determineType(itemClass);
-
-				return typeInfo;
-			}
-			else if(monoClass->getFullName() == mSystemGenericDictionaryClass->getFullName())
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoDictionary> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoDictionary>();
-
-				MonoMethod* getEnumerator = monoClass->getMethod("GetEnumerator");
-				MonoClass* enumClass = getEnumerator->getReturnType();
-
-				MonoProperty& currentProp = enumClass->getProperty("Current");
-				MonoClass* keyValuePair = currentProp.getReturnType();
-
-				MonoProperty& keyProperty = keyValuePair->getProperty("Key");
-				MonoProperty& valueProperty = keyValuePair->getProperty("Value");
-
-				MonoClass* keyClass = keyProperty.getReturnType();
-				if(keyClass != nullptr)
-					typeInfo->mKeyType = determineType(keyClass);
-
-				MonoClass* valueClass = valueProperty.getReturnType();
-				if(valueClass != nullptr)
-					typeInfo->mValueType = determineType(valueClass);
-
-				return typeInfo;
-			}
-			break;
-		case MONO_TYPE_SZARRAY:
-		case MONO_TYPE_ARRAY:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoArray> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoArray>();
-
-				::MonoClass* elementClass = mono_class_get_element_class(monoClass->_getInternalClass());
-				if(elementClass != nullptr)
-				{
-					MonoClass* monoElementClass = MonoManager::instance().findClass(elementClass);
-					if(monoElementClass != nullptr)
-						typeInfo->mElementType = determineType(monoElementClass);
-				}
-
-				typeInfo->mRank = (UINT32)mono_class_get_rank(monoClass->_getInternalClass());
-
-				return typeInfo;
-			}
-		}
-
-		return nullptr;
-	}
-
-	void RuntimeScriptObjects::clearScriptObjects(const String& assemblyName)
-	{
-		mAssemblyInfos.erase(assemblyName);
-
-		mBaseTypesInitialized = false;
-
-		mSystemArrayClass = nullptr;
-		mSystemGenericListClass = nullptr;
-		mSystemGenericDictionaryClass = nullptr;
-
-		mSerializeObjectAttribute = nullptr;
-		mDontSerializeFieldAttribute = nullptr;
-
-		mComponentClass = nullptr;
-		mSceneObjectClass = nullptr;
-
-		mManagedResourceClass = nullptr;
-		mTextureClass = nullptr;
-		mSpriteTextureClass = nullptr;
-
-		mSerializeFieldAttribute = nullptr;
-		mHideInInspectorAttribute = nullptr;
-	}
-
-	void RuntimeScriptObjects::initializeBaseTypes()
-	{
-		// Get necessary classes for detecting needed class & field information
-		MonoAssembly* corlib = MonoManager::instance().getAssembly("corlib");
-		if(corlib == nullptr)
-			BS_EXCEPT(InvalidStateException, "corlib assembly is not loaded.");
-
-		MonoAssembly* bansheeEngineAssembly = MonoManager::instance().getAssembly(BansheeEngineAssemblyName);
-		if(bansheeEngineAssembly == nullptr)
-			BS_EXCEPT(InvalidStateException, String(BansheeEngineAssemblyName) +  " assembly is not loaded.");
-
-		mSystemArrayClass = corlib->getClass("System", "Array");
-		if(mSystemArrayClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find System.Array managed class.");
-
-		mSystemGenericListClass = corlib->getClass("System.Collections.Generic", "List`1");
-		if(mSystemGenericListClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find List<T> managed class.");
-
-		mSystemGenericDictionaryClass = corlib->getClass("System.Collections.Generic", "Dictionary`2");
-		if(mSystemGenericDictionaryClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find Dictionary<TKey, TValue> managed class.");
-
-		mSerializeObjectAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "SerializeObject");
-		if(mSerializeObjectAttribute == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find SerializableObject managed class.");
-
-		mDontSerializeFieldAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "DontSerializeField");
-		if(mDontSerializeFieldAttribute == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find DontSerializeField managed class.");
-
-		mComponentClass = bansheeEngineAssembly->getClass("BansheeEngine", "Component");
-		if(mComponentClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find Component managed class.");
-
-		mSceneObjectClass = bansheeEngineAssembly->getClass("BansheeEngine", "SceneObject");
-		if(mSceneObjectClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find SceneObject managed class.");
-
-		mManagedResourceClass = bansheeEngineAssembly->getClass("BansheeEngine", "ManagedResource");
-		if (mManagedResourceClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find ManagedResource managed class.");
-
-		mTextureClass = bansheeEngineAssembly->getClass("BansheeEngine", "Texture2D");
-		if(mTextureClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find Texture2D managed class.");
-
-		mSpriteTextureClass = bansheeEngineAssembly->getClass("BansheeEngine", "SpriteTexture");
-		if(mSpriteTextureClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find SpriteTexture managed class.");
-
-		mSerializeFieldAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "SerializeField");
-		if(mSerializeFieldAttribute == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find SerializeField managed class.");
-
-		mHideInInspectorAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "HideInInspector");
-		if(mHideInInspectorAttribute == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find HideInInspector managed class.");
-
-		mBaseTypesInitialized = true;
-	}
-
-	bool RuntimeScriptObjects::getSerializableObjectInfo(const String& ns, const String& typeName, std::shared_ptr<ManagedSerializableObjectInfo>& outInfo)
-	{
-		String fullName = ns + "." + typeName;
-		for(auto& curAssembly : mAssemblyInfos)
-		{
-			auto iterFind = curAssembly.second->mTypeNameToId.find(fullName);
-			if(iterFind != curAssembly.second->mTypeNameToId.end())
-			{
-				outInfo = curAssembly.second->mObjectInfos[iterFind->second];
-
-				return true;
-			}
-		}
-
-		return false;
-	}
-
-	bool RuntimeScriptObjects::hasSerializableObjectInfo(const String& ns, const String& typeName)
-	{
-		String fullName = ns + "." + typeName;
-		for(auto& curAssembly : mAssemblyInfos)
-		{
-			auto iterFind = curAssembly.second->mTypeNameToId.find(fullName);
-			if(iterFind != curAssembly.second->mTypeNameToId.end())
-				return true;
-		}
-
-		return false;
-	}
+#include "BsScriptAssemblyManager.h"
+#include "BsScriptResourceManager.h"
+#include "BsScriptGameObjectManager.h"
+#include "BsManagedSerializableObjectInfo.h"
+#include "BsMonoManager.h"
+#include "BsMonoAssembly.h"
+#include "BsMonoClass.h"
+#include "BsMonoField.h"
+#include "BsMonoMethod.h"
+#include "BsMonoProperty.h"
+#include "BsMonoUtil.h"
+#include "BsRTTIType.h"
+
+namespace BansheeEngine
+{
+	ScriptAssemblyManager::ScriptAssemblyManager()
+		:mBaseTypesInitialized(false), mSerializeObjectAttribute(nullptr), mDontSerializeFieldAttribute(nullptr), 
+		mComponentClass(nullptr), mSceneObjectClass(nullptr), mTextureClass(nullptr), mSpriteTextureClass(nullptr),
+		mSerializeFieldAttribute(nullptr), mHideInInspectorAttribute(nullptr), mSystemArrayClass(nullptr), mSystemGenericListClass(nullptr),
+		mSystemGenericDictionaryClass(nullptr), mManagedResourceClass(nullptr), mFontClass(nullptr)
+	{
+
+	}
+
+	ScriptAssemblyManager::~ScriptAssemblyManager()
+	{
+
+	}
+
+	Vector<String> ScriptAssemblyManager::getScriptAssemblies() const
+	{
+		Vector<String> initializedAssemblies;
+		for (auto& assemblyPair : mAssemblyInfos)
+			initializedAssemblies.push_back(assemblyPair.first);
+
+		return initializedAssemblies;
+	}
+
+	void ScriptAssemblyManager::loadAssemblyInfo(const String& assemblyName)
+	{
+		if(!mBaseTypesInitialized)
+			initializeBaseTypes();
+
+		// Process all classes and fields
+		UINT32 mUniqueTypeId = 1;
+
+		MonoAssembly* curAssembly = MonoManager::instance().getAssembly(assemblyName);
+		if(curAssembly == nullptr)
+			return;
+
+		std::shared_ptr<ManagedSerializableAssemblyInfo> assemblyInfo = bs_shared_ptr<ManagedSerializableAssemblyInfo>();
+		assemblyInfo->mName = assemblyName;
+
+		mAssemblyInfos[assemblyName] = assemblyInfo;
+
+		// Populate class data
+		const Vector<MonoClass*>& allClasses = curAssembly->getAllClasses();
+		for(auto& curClass : allClasses)
+		{
+			if((curClass->isSubClassOf(mComponentClass) || curClass->isSubClassOf(mManagedResourceClass) || 
+				curClass->hasAttribute(mSerializeObjectAttribute)) && curClass != mComponentClass && curClass != mManagedResourceClass)
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoObject> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoObject>();
+				typeInfo->mTypeNamespace = curClass->getNamespace();
+				typeInfo->mTypeName = curClass->getTypeName();
+
+				MonoType* monoType = mono_class_get_type(curClass->_getInternalClass());
+				int monoPrimitiveType = mono_type_get_type(monoType);
+
+				if(monoPrimitiveType == MONO_TYPE_VALUETYPE)
+					typeInfo->mValueType = true;
+				else
+					typeInfo->mValueType = false;
+
+				std::shared_ptr<ManagedSerializableObjectInfo> objInfo = bs_shared_ptr<ManagedSerializableObjectInfo>();
+
+				objInfo->mTypeId = mUniqueTypeId++;
+
+				objInfo->mTypeInfo = typeInfo;
+				objInfo->mMonoClass = curClass;
+
+				assemblyInfo->mTypeNameToId[objInfo->getFullTypeName()] = objInfo->mTypeId;
+				assemblyInfo->mObjectInfos[objInfo->mTypeId] = objInfo;
+			}
+		}
+
+		// Populate field data
+		for(auto& curClassInfo : assemblyInfo->mObjectInfos)
+		{
+			std::shared_ptr<ManagedSerializableObjectInfo> objInfo = curClassInfo.second;
+
+			UINT32 mUniqueFieldId = 1;
+			const Vector<MonoField*>& fields = objInfo->mMonoClass->getAllFields();
+
+			for(auto& field : fields)
+			{
+				if(field->isStatic())
+					continue;
+
+				ManagedSerializableTypeInfoPtr typeInfo = determineType(field->getType());
+				if (typeInfo == nullptr)
+					continue;
+
+				std::shared_ptr<ManagedSerializableFieldInfo> fieldInfo = bs_shared_ptr<ManagedSerializableFieldInfo>();
+				fieldInfo->mFieldId = mUniqueFieldId++;
+				fieldInfo->mName = field->getName();
+				fieldInfo->mMonoField = field;
+				fieldInfo->mTypeInfo = typeInfo;
+				
+				MonoFieldVisibility visibility = field->getVisibility();
+				if (visibility == MonoFieldVisibility::Public)
+				{
+					if (!field->hasAttribute(mDontSerializeFieldAttribute))
+						fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Serializable);
+
+					if (!field->hasAttribute(mHideInInspectorAttribute))
+						fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Inspectable);
+				}
+				else
+				{
+					if (field->hasAttribute(mSerializeFieldAttribute))
+						fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Serializable);
+				}
+
+				objInfo->mFieldNameToId[fieldInfo->mName] = fieldInfo->mFieldId;
+				objInfo->mFields[fieldInfo->mFieldId] = fieldInfo;
+			}
+		}
+
+		// Form parent/child connections
+		for(auto& curClass : assemblyInfo->mObjectInfos)
+		{
+			MonoClass* base = curClass.second->mMonoClass->getBaseClass();
+			while(base != nullptr)
+			{
+				std::shared_ptr<ManagedSerializableObjectInfo> baseObjInfo;
+				if(getSerializableObjectInfo(base->getNamespace(), base->getTypeName(), baseObjInfo))
+				{
+					curClass.second->mBaseClass = baseObjInfo;
+					baseObjInfo->mDerivedClasses.push_back(curClass.second);
+
+					break;
+				}
+
+				base = base->getBaseClass();
+			}
+		}
+
+		// Finish object info initialization
+		for (auto& curClassInfo : assemblyInfo->mObjectInfos)
+		{
+			std::shared_ptr<ManagedSerializableObjectInfo> objInfo = curClassInfo.second;
+			objInfo->initialize();
+		}
+	}
+
+	void ScriptAssemblyManager::refreshAssemblyInfo()
+	{
+		for (auto& assemblyInfoEntry : mAssemblyInfos)
+			assemblyInfoEntry.second = nullptr;
+
+		clearScriptObjects();
+		for (auto& assemblyInfoEntry : mAssemblyInfos)
+		{
+			loadAssemblyInfo(assemblyInfoEntry.first);
+		}
+	}
+
+	ManagedSerializableTypeInfoPtr ScriptAssemblyManager::determineType(MonoClass* monoClass)
+	{
+		if(!mBaseTypesInitialized)
+			BS_EXCEPT(InvalidStateException, "Calling determineType without previously initializing base types.");
+
+		MonoType* monoType = mono_class_get_type(monoClass->_getInternalClass());
+		int monoPrimitiveType = mono_type_get_type(monoType);
+		
+		//  Determine field type
+		switch(monoPrimitiveType)
+		{
+		case MONO_TYPE_BOOLEAN:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::Bool;
+				return typeInfo;
+			}
+		case MONO_TYPE_CHAR:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::Char;
+				return typeInfo;
+			}
+		case MONO_TYPE_I1:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::I8;
+				return typeInfo;
+			}
+		case MONO_TYPE_U1:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::U8;
+				return typeInfo;
+			}
+		case MONO_TYPE_I2:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::I16;
+				return typeInfo;
+			}
+		case MONO_TYPE_U2:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::U16;
+				return typeInfo;
+			}
+		case MONO_TYPE_I4:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::I32;
+				return typeInfo;
+			}
+		case MONO_TYPE_U4:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::U32;
+				return typeInfo;
+			}
+		case MONO_TYPE_I8:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::I64;
+				return typeInfo;
+			}
+		case MONO_TYPE_U8:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::U64;
+				return typeInfo;
+			}
+		case MONO_TYPE_STRING:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::String;
+				return typeInfo;
+			}
+		case MONO_TYPE_R4:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::Float;
+				return typeInfo;
+			}
+		case MONO_TYPE_R8:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::Double;
+				return typeInfo;
+			}
+		case MONO_TYPE_CLASS:
+			if(monoClass->isSubClassOf(mTextureClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::TextureRef;
+				return typeInfo;
+			}
+			else if(monoClass->isSubClassOf(mSpriteTextureClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::SpriteTextureRef;
+				return typeInfo;
+			}
+			else if (monoClass->isSubClassOf(mManagedResourceClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::ManagedResourceRef;
+				return typeInfo;
+			}
+			else if(monoClass->isSubClassOf(mSceneObjectClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::SceneObjectRef;
+				return typeInfo;
+			}
+			else if(monoClass->isSubClassOf(mComponentClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::ComponentRef;
+				return typeInfo;
+			}
+			else
+			{
+				std::shared_ptr<ManagedSerializableObjectInfo> objInfo;
+				if (getSerializableObjectInfo(monoClass->getNamespace(), monoClass->getTypeName(), objInfo))
+					return objInfo->mTypeInfo;
+			}
+
+			break;
+		case MONO_TYPE_VALUETYPE:
+			{
+				std::shared_ptr<ManagedSerializableObjectInfo> objInfo;
+				if (getSerializableObjectInfo(monoClass->getNamespace(), monoClass->getTypeName(), objInfo))
+					return objInfo->mTypeInfo;
+			}
+
+			break;
+		case MONO_TYPE_GENERICINST:
+			if(monoClass->getFullName() == mSystemGenericListClass->getFullName()) // Full name is part of CIL spec, so it is just fine to compare like this
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoList> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoList>();
+
+				MonoProperty& itemProperty = monoClass->getProperty("Item");
+				MonoClass* itemClass = itemProperty.getReturnType();
+
+				if(itemClass != nullptr)
+					typeInfo->mElementType = determineType(itemClass);
+
+				return typeInfo;
+			}
+			else if(monoClass->getFullName() == mSystemGenericDictionaryClass->getFullName())
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoDictionary> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoDictionary>();
+
+				MonoMethod* getEnumerator = monoClass->getMethod("GetEnumerator");
+				MonoClass* enumClass = getEnumerator->getReturnType();
+
+				MonoProperty& currentProp = enumClass->getProperty("Current");
+				MonoClass* keyValuePair = currentProp.getReturnType();
+
+				MonoProperty& keyProperty = keyValuePair->getProperty("Key");
+				MonoProperty& valueProperty = keyValuePair->getProperty("Value");
+
+				MonoClass* keyClass = keyProperty.getReturnType();
+				if(keyClass != nullptr)
+					typeInfo->mKeyType = determineType(keyClass);
+
+				MonoClass* valueClass = valueProperty.getReturnType();
+				if(valueClass != nullptr)
+					typeInfo->mValueType = determineType(valueClass);
+
+				return typeInfo;
+			}
+			break;
+		case MONO_TYPE_SZARRAY:
+		case MONO_TYPE_ARRAY:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoArray> typeInfo = bs_shared_ptr<ManagedSerializableTypeInfoArray>();
+
+				::MonoClass* elementClass = mono_class_get_element_class(monoClass->_getInternalClass());
+				if(elementClass != nullptr)
+				{
+					MonoClass* monoElementClass = MonoManager::instance().findClass(elementClass);
+					if(monoElementClass != nullptr)
+						typeInfo->mElementType = determineType(monoElementClass);
+				}
+
+				typeInfo->mRank = (UINT32)mono_class_get_rank(monoClass->_getInternalClass());
+
+				return typeInfo;
+			}
+		}
+
+		return nullptr;
+	}
+
+	void ScriptAssemblyManager::clearScriptObjects()
+	{
+		mBaseTypesInitialized = false;
+
+		mSystemArrayClass = nullptr;
+		mSystemGenericListClass = nullptr;
+		mSystemGenericDictionaryClass = nullptr;
+
+		mSerializeObjectAttribute = nullptr;
+		mDontSerializeFieldAttribute = nullptr;
+
+		mComponentClass = nullptr;
+		mSceneObjectClass = nullptr;
+
+		mManagedResourceClass = nullptr;
+		mTextureClass = nullptr;
+		mSpriteTextureClass = nullptr;
+		mFontClass = nullptr;
+
+		mSerializeFieldAttribute = nullptr;
+		mHideInInspectorAttribute = nullptr;
+	}
+
+	void ScriptAssemblyManager::initializeBaseTypes()
+	{
+		// Get necessary classes for detecting needed class & field information
+		MonoAssembly* corlib = MonoManager::instance().getAssembly("corlib");
+		if(corlib == nullptr)
+			BS_EXCEPT(InvalidStateException, "corlib assembly is not loaded.");
+
+		MonoAssembly* bansheeEngineAssembly = MonoManager::instance().getAssembly(BansheeEngineAssemblyName);
+		if(bansheeEngineAssembly == nullptr)
+			BS_EXCEPT(InvalidStateException, String(BansheeEngineAssemblyName) +  " assembly is not loaded.");
+
+		mSystemArrayClass = corlib->getClass("System", "Array");
+		if(mSystemArrayClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find System.Array managed class.");
+
+		mSystemGenericListClass = corlib->getClass("System.Collections.Generic", "List`1");
+		if(mSystemGenericListClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find List<T> managed class.");
+
+		mSystemGenericDictionaryClass = corlib->getClass("System.Collections.Generic", "Dictionary`2");
+		if(mSystemGenericDictionaryClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find Dictionary<TKey, TValue> managed class.");
+
+		mSerializeObjectAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "SerializeObject");
+		if(mSerializeObjectAttribute == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find SerializableObject managed class.");
+
+		mDontSerializeFieldAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "DontSerializeField");
+		if(mDontSerializeFieldAttribute == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find DontSerializeField managed class.");
+
+		mComponentClass = bansheeEngineAssembly->getClass("BansheeEngine", "Component");
+		if(mComponentClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find Component managed class.");
+
+		mSceneObjectClass = bansheeEngineAssembly->getClass("BansheeEngine", "SceneObject");
+		if(mSceneObjectClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find SceneObject managed class.");
+
+		mManagedResourceClass = bansheeEngineAssembly->getClass("BansheeEngine", "ManagedResource");
+		if (mManagedResourceClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find ManagedResource managed class.");
+
+		mTextureClass = bansheeEngineAssembly->getClass("BansheeEngine", "Texture2D");
+		if(mTextureClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find Texture2D managed class.");
+
+		mSpriteTextureClass = bansheeEngineAssembly->getClass("BansheeEngine", "SpriteTexture");
+		if(mSpriteTextureClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find SpriteTexture managed class.");
+
+		mFontClass = bansheeEngineAssembly->getClass("BansheeEngine", "Font");
+		if (mFontClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find Font managed class.");
+
+		mSerializeFieldAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "SerializeField");
+		if(mSerializeFieldAttribute == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find SerializeField managed class.");
+
+		mHideInInspectorAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "HideInInspector");
+		if(mHideInInspectorAttribute == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find HideInInspector managed class.");
+
+		mBaseTypesInitialized = true;
+	}
+
+	bool ScriptAssemblyManager::getSerializableObjectInfo(const String& ns, const String& typeName, std::shared_ptr<ManagedSerializableObjectInfo>& outInfo)
+	{
+		String fullName = ns + "." + typeName;
+		for(auto& curAssembly : mAssemblyInfos)
+		{
+			auto iterFind = curAssembly.second->mTypeNameToId.find(fullName);
+			if(iterFind != curAssembly.second->mTypeNameToId.end())
+			{
+				outInfo = curAssembly.second->mObjectInfos[iterFind->second];
+
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	bool ScriptAssemblyManager::hasSerializableObjectInfo(const String& ns, const String& typeName)
+	{
+		String fullName = ns + "." + typeName;
+		for(auto& curAssembly : mAssemblyInfos)
+		{
+			auto iterFind = curAssembly.second->mTypeNameToId.find(fullName);
+			if(iterFind != curAssembly.second->mTypeNameToId.end())
+				return true;
+		}
+
+		return false;
+	}
 }

+ 41 - 2
SBansheeEngine/Source/BsScriptComponent.cpp

@@ -1,5 +1,7 @@
 #include "BsScriptComponent.h"
 #include "BsScriptGameObjectManager.h"
+#include "BsScriptObjectManager.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsScriptMeta.h"
 #include "BsMonoField.h"
 #include "BsMonoClass.h"
@@ -14,7 +16,13 @@ namespace BansheeEngine
 {
 	ScriptComponent::ScriptComponent(MonoObject* instance)
 		:ScriptObject(instance)
-	{ }
+	{ 
+		assert(instance != nullptr);
+
+		::MonoClass* monoClass = mono_object_get_class(instance);
+		mNamespace = mono_class_get_namespace(monoClass);
+		mType = mono_class_get_name(monoClass);
+	}
 
 	void ScriptComponent::initRuntimeData()
 	{
@@ -175,10 +183,41 @@ namespace BansheeEngine
 		return false;
 	}
 
+	MonoObject* ScriptComponent::_createManagedInstance(bool construct)
+	{
+		ManagedSerializableObjectInfoPtr currentObjInfo = nullptr;
+
+		// See if this type even still exists
+		if (!ScriptAssemblyManager::instance().getSerializableObjectInfo(mNamespace, mType, currentObjInfo))
+			return nullptr;
+
+		return currentObjInfo->mMonoClass->createInstance(construct);
+	}
+
+	ScriptObjectBackup ScriptComponent::beginRefresh()
+	{
+		ScriptGameObjectBase::beginRefresh();
+
+		ScriptObjectBackup backupData;
+		backupData.data = mManagedComponent->backup(true);
+
+		return backupData;
+	}
+
+	void ScriptComponent::endRefresh(const ScriptObjectBackup& backupData)
+	{
+		ComponentBackupData componentBackup = any_cast<ComponentBackupData>(backupData.data);
+		mManagedComponent->restore(mManagedInstance, componentBackup);
+
+		ScriptGameObjectBase::endRefresh(backupData);
+	}
+
 	void ScriptComponent::_onManagedInstanceDeleted()
 	{
 		mManagedInstance = nullptr;
-		ScriptGameObjectManager::instance().destroyScriptGameObject(this);
+
+		if (!mRefreshInProgress)
+			ScriptGameObjectManager::instance().destroyScriptGameObject(this);
 	}
 
 	void ScriptComponent::setNativeHandle(const HGameObject& gameObject)

+ 7 - 4
SBansheeEngine/Source/BsScriptEnginePlugin.cpp

@@ -1,13 +1,14 @@
 #include "BsScriptEnginePrerequisites.h"
 #include "BsMonoManager.h"
 #include "BsMonoAssembly.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsScriptResourceManager.h"
 #include "BsScriptGameObjectManager.h"
 #include "BsManagedResourceManager.h"
 #include "BsScriptManager.h"
 #include "BsScriptInput.h"
 #include "BsScriptVirtualInput.h"
+#include "BsScriptObjectManager.h"
 
 // DEBUG ONLY
 #include "BsScriptSceneObject.h"
@@ -43,14 +44,15 @@ namespace BansheeEngine
 		// DEBUG ONLY
 		mono_add_internal_call("BansheeEngine.Program::UnitTest1_GameObjectClone", &unitTest1_GameObjectClone);
 
+		ScriptObjectManager::startUp();
 		ManagedResourceManager::startUp();
-		RuntimeScriptObjects::startUp();
+		ScriptAssemblyManager::startUp();
 		ScriptResourceManager::startUp();
 		ScriptGameObjectManager::startUp();
 		ScriptInput::startUp();
 		ScriptVirtualInput::startUp();
 
-		RuntimeScriptObjects::instance().refreshScriptObjects(BansheeEngineAssemblyName);
+		ScriptAssemblyManager::instance().loadAssemblyInfo(BansheeEngineAssemblyName);
 
 		bansheeEngineAssembly.invoke(ASSEMBLY_ENTRY_POINT);
 
@@ -65,6 +67,7 @@ namespace BansheeEngine
 		ScriptManager::instance().destroy();
 		ScriptGameObjectManager::shutDown();
 		ScriptResourceManager::shutDown();
-		RuntimeScriptObjects::shutDown();
+		ScriptAssemblyManager::shutDown();
+		ScriptObjectManager::shutDown();
 	}
 }

+ 3 - 1
SBansheeEngine/Source/BsScriptFont.cpp

@@ -22,7 +22,9 @@ namespace BansheeEngine
 	void ScriptFont::_onManagedInstanceDeleted()
 	{
 		mManagedInstance = nullptr;
-		ScriptResourceManager::instance().destroyScriptResource(this);
+
+		if (!mRefreshInProgress)
+			ScriptResourceManager::instance().destroyScriptResource(this);
 	}
 
 	void ScriptFont::setNativeHandle(const HResource& resource)

+ 22 - 0
SBansheeEngine/Source/BsScriptGameObject.cpp

@@ -0,0 +1,22 @@
+#include "BsScriptGameObject.h"
+
+namespace BansheeEngine
+{
+	ScriptGameObjectBase::ScriptGameObjectBase(MonoObject* instance)
+		:PersistentScriptObjectBase(instance), mRefreshInProgress(false)
+	{ }
+
+	ScriptObjectBackup ScriptGameObjectBase::beginRefresh()
+	{
+		mRefreshInProgress = true;
+
+		return PersistentScriptObjectBase::beginRefresh();
+	}
+
+	void ScriptGameObjectBase::endRefresh(const ScriptObjectBackup& backupData)
+	{
+		mRefreshInProgress = false;
+
+		PersistentScriptObjectBase::endRefresh(backupData);
+	}
+}

+ 40 - 14
SBansheeEngine/Source/BsScriptGameObjectManager.cpp

@@ -9,20 +9,29 @@
 #include "BsMonoManager.h"
 #include "BsMonoAssembly.h"
 #include "BsMonoClass.h"
+#include "BsScriptAssemblyManager.h"
+#include "BsScriptObjectManager.h"
 
 namespace BansheeEngine
 {
+	ScriptGameObjectManager::ScriptGameObjectEntry::ScriptGameObjectEntry()
+		:instance(nullptr), isComponent(false)
+	{ }
+
+	ScriptGameObjectManager::ScriptGameObjectEntry::ScriptGameObjectEntry(ScriptGameObjectBase* instance, bool isComponent)
+		:instance(instance), isComponent(isComponent)
+	{ }
+
 	ScriptGameObjectManager::ScriptGameObjectManager()
-		:mSceneObjectClass(nullptr)
 	{
-		MonoAssembly* assembly = MonoManager::instance().getAssembly(BansheeEngineAssemblyName);
-		if(assembly == nullptr)
-			BS_EXCEPT(InternalErrorException, "Cannot find \"" + String(BansheeEngineAssemblyName) + "\" assembly.");
-
-		mSceneObjectClass = assembly->getClass("BansheeEngine", "SceneObject");
+		// Calls OnReset on all components after assembly reload happens
+		mOnAssemblyReloadDoneConn = ScriptObjectManager::instance().onRefreshComplete.connect(
+			std::bind(&ScriptGameObjectManager::sendComponentResetEvents, this));
+	}
 
-		if(mSceneObjectClass == nullptr)
-			BS_EXCEPT(InternalErrorException, "Cannot find managed SceneObject class.");
+	ScriptGameObjectManager::~ScriptGameObjectManager()
+	{
+		mOnAssemblyReloadDoneConn.disconnect();
 	}
 
 	void ScriptGameObjectManager::registerScriptComponent(ScriptComponent* nativeInstance, const GameObjectHandle<ManagedComponent>& component)
@@ -32,12 +41,13 @@ namespace BansheeEngine
 			BS_EXCEPT(InvalidStateException, "Script component for this Component already exists.");
 
 		nativeInstance->setManagedComponent(component);
-		mScriptGameObjects[component->getInstanceId()] = nativeInstance;
+		mScriptGameObjects[component->getInstanceId()] = ScriptGameObjectEntry(nativeInstance, true);
 	}
 
 	ScriptSceneObject* ScriptGameObjectManager::createScriptSceneObject(const HSceneObject& sceneObject)
 	{
-		MonoObject* instance = mSceneObjectClass->createInstance();
+		MonoClass* sceneObjectClass = ScriptAssemblyManager::instance().getSceneObjectClass();
+		MonoObject* instance = sceneObjectClass->createInstance();
 
 		return createScriptSceneObject(instance, sceneObject);
 	}
@@ -49,7 +59,7 @@ namespace BansheeEngine
 			BS_EXCEPT(InvalidStateException, "Script SceneObject for this SceneObject already exists.");
 
 		ScriptSceneObject* nativeInstance = new (bs_alloc<ScriptSceneObject>()) ScriptSceneObject(existingInstance, sceneObject);
-		mScriptGameObjects[sceneObject.getInstanceId()] = nativeInstance;
+		mScriptGameObjects[sceneObject.getInstanceId()] = ScriptGameObjectEntry(nativeInstance, false);
 
 		return nativeInstance;
 	}
@@ -58,7 +68,7 @@ namespace BansheeEngine
 	{
 		auto findIter = mScriptGameObjects.find(component.getInstanceId());
 		if(findIter != mScriptGameObjects.end())
-			return static_cast<ScriptComponent*>(findIter->second);
+			return static_cast<ScriptComponent*>(findIter->second.instance);
 
 		return nullptr;
 	}
@@ -67,7 +77,7 @@ namespace BansheeEngine
 	{
 		auto findIter = mScriptGameObjects.find(sceneObject.getInstanceId());
 		if(findIter != mScriptGameObjects.end())
-			return static_cast<ScriptSceneObject*>(findIter->second);
+			return static_cast<ScriptSceneObject*>(findIter->second.instance);
 
 		return nullptr;
 	}
@@ -76,7 +86,7 @@ namespace BansheeEngine
 	{
 		auto findIter = mScriptGameObjects.find(instanceId);
 		if (findIter != mScriptGameObjects.end())
-			return static_cast<ScriptSceneObject*>(findIter->second);
+			return static_cast<ScriptSceneObject*>(findIter->second.instance);
 
 		return nullptr;
 	}
@@ -88,4 +98,20 @@ namespace BansheeEngine
 
 		bs_delete(gameObject);
 	}
+
+	void ScriptGameObjectManager::sendComponentResetEvents()
+	{
+		for (auto& scriptObjectEntry : mScriptGameObjects)
+		{
+			const ScriptGameObjectEntry& entry = scriptObjectEntry.second;
+
+			if (!entry.isComponent)
+				continue;
+
+			ScriptComponent* scriptComponent = static_cast<ScriptComponent*>(entry.instance);
+			HManagedComponent component = scriptComponent->getNativeHandle();
+
+			component->triggerOnReset();
+		}
+	}
 }

+ 49 - 8
SBansheeEngine/Source/BsScriptManagedResource.cpp

@@ -1,5 +1,6 @@
 #include "BsScriptManagedResource.h"
 #include "BsScriptResourceManager.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsScriptMeta.h"
 #include "BsMonoField.h"
 #include "BsMonoClass.h"
@@ -13,7 +14,11 @@ namespace BansheeEngine
 	ScriptManagedResource::ScriptManagedResource(MonoObject* instance, const HManagedResource& resource)
 		:ScriptObject(instance), mResource(resource)
 	{
+		assert(instance != nullptr);
 
+		::MonoClass* monoClass = mono_object_get_class(instance);
+		mNamespace = mono_class_get_namespace(monoClass);
+		mType = mono_class_get_name(monoClass);
 	}
 
 	void ScriptManagedResource::initRuntimeData()
@@ -28,18 +33,54 @@ namespace BansheeEngine
 		ScriptResourceManager::instance().createManagedResource(instance, resource);
 	}
 
+	MonoObject* ScriptManagedResource::_createManagedInstance(bool construct)
+	{
+		ManagedSerializableObjectInfoPtr currentObjInfo = nullptr;
+
+		// See if this type even still exists
+		if (!ScriptAssemblyManager::instance().getSerializableObjectInfo(mNamespace, mType, currentObjInfo))
+			return nullptr;
+
+		return currentObjInfo->mMonoClass->createInstance(construct);
+	}
+
+	ScriptObjectBackup ScriptManagedResource::beginRefresh()
+	{
+		ScriptResourceBase::beginRefresh();
+
+		ScriptObjectBackup backupData;
+		backupData.data = mResource->backup(true);
+
+		return backupData;
+	}
+
+	void ScriptManagedResource::endRefresh(const ScriptObjectBackup& backupData)
+	{
+		ResourceBackupData resourceBackup = any_cast<ResourceBackupData>(backupData.data);
+		mResource->restore(mManagedInstance, resourceBackup);
+
+		// If we could not find resource type after refresh, treat it as if it was destroyed
+		if (mManagedInstance == nullptr)
+			_onManagedInstanceDeleted();
+
+		ScriptResourceBase::endRefresh(backupData);
+	}
+
 	void ScriptManagedResource::_onManagedInstanceDeleted()
 	{
 		mManagedInstance = nullptr;
 		
-		// The only way this method should be reachable is when Resource::unload is called, which means the resource
-		// has had to been already freed. Even if all managed instances are released ManagedResource itself holds the last
-		// instance which is only freed on unload().
-		// Note: During domain unload this could get called even if not all instances are released, but ManagedResourceManager
-		// should make sure all instances are unloaded before that happens.
-		assert(mResource == nullptr || !mResource.isLoaded()); 
-		
-		ScriptResourceManager::instance().destroyScriptResource(this);
+		if (!mRefreshInProgress)
+		{
+			// The only way this method should be reachable is when Resource::unload is called, which means the resource
+			// has had to been already freed. Even if all managed instances are released ManagedResource itself holds the last
+			// instance which is only freed on unload().
+			// Note: During domain unload this could get called even if not all instances are released, but ManagedResourceManager
+			// should make sure all instances are unloaded before that happens.
+			assert(mResource == nullptr || !mResource.isLoaded());
+
+			ScriptResourceManager::instance().destroyScriptResource(this);
+		}
 	}
 
 	void ScriptManagedResource::setNativeHandle(const HResource& resource)

+ 25 - 1
SBansheeEngine/Source/BsScriptObject.cpp

@@ -1,4 +1,5 @@
 #include "BsScriptObject.h"
+#include "BsScriptObjectManager.h"
 #include "BsMonoManager.h"
 #include "BsMonoField.h"
 
@@ -7,13 +8,25 @@ namespace BansheeEngine
 	ScriptObjectBase::ScriptObjectBase(MonoObject* instance)
 		:mManagedInstance(instance)
 	{	
-
+		ScriptObjectManager::instance().registerScriptObject(this);
 	}
 
 	ScriptObjectBase::~ScriptObjectBase() 
 	{
 		if(mManagedInstance != nullptr)
 			BS_EXCEPT(InvalidStateException, "Script object is being destroyed without its instance previously being released.");
+
+		ScriptObjectManager::instance().unregisterScriptObject(this);
+	}
+
+	ScriptObjectBackup ScriptObjectBase::beginRefresh() 
+	{ 
+		return ScriptObjectBackup(); 
+	}
+
+	void ScriptObjectBase::endRefresh(const ScriptObjectBackup& data) 
+	{ 
+
 	}
 
 	void ScriptObjectBase::_onManagedInstanceDeleted()
@@ -21,4 +34,15 @@ namespace BansheeEngine
 		mManagedInstance = nullptr;
 		bs_delete(this);
 	}
+
+	PersistentScriptObjectBase::PersistentScriptObjectBase(MonoObject* instance)
+		:ScriptObjectBase(instance)
+	{
+
+	}
+
+	PersistentScriptObjectBase::~PersistentScriptObjectBase()
+	{
+
+	}
 }

+ 1 - 0
SBansheeEngine/Source/BsScriptObjectImpl.cpp

@@ -2,6 +2,7 @@
 #include "BsMonoManager.h"
 #include "BsMonoClass.h"
 #include "BsMonoUtil.h"
+#include "BsScriptObjectManager.h"
 
 namespace BansheeEngine
 {

+ 49 - 0
SBansheeEngine/Source/BsScriptObjectManager.cpp

@@ -0,0 +1,49 @@
+#include "BsScriptObjectManager.h"
+#include "BsScriptObject.h"
+#include "BsMonoManager.h"
+#include "BsScriptAssemblyManager.h"
+
+namespace BansheeEngine
+{
+	ScriptObjectManager::ScriptObjectManager()
+	{
+
+	}
+
+	void ScriptObjectManager::registerScriptObject(ScriptObjectBase* instance)
+	{
+		mScriptObjects.insert(instance);
+	}
+
+	void ScriptObjectManager::unregisterScriptObject(ScriptObjectBase* instance)
+	{
+		mScriptObjects.erase(instance);
+	}
+
+	void ScriptObjectManager::refreshAssemblies()
+	{
+		Map<ScriptObjectBase*, ScriptObjectBackup> backupData;
+
+		for (auto& scriptObject : mScriptObjects)
+			backupData[scriptObject] = scriptObject->beginRefresh();
+
+		MonoManager::instance().unloadScriptDomain();
+
+		for (auto& scriptObject : mScriptObjects)
+			assert(scriptObject->isPersistent() && "Non-persistent ScriptObject alive after domain unload.");
+
+		for (auto& scriptObject : mScriptObjects)
+			scriptObject->_clearManagedInstance();
+
+		MonoManager::instance().loadScriptDomain();
+		ScriptAssemblyManager::instance().refreshAssemblyInfo();
+
+		for (auto& scriptObject : mScriptObjects)
+			scriptObject->_restoreManagedInstance();
+
+		for (auto& scriptObject : mScriptObjects)
+			scriptObject->endRefresh(backupData[scriptObject]);
+
+		onRefreshComplete();
+	}
+}

+ 22 - 0
SBansheeEngine/Source/BsScriptResource.cpp

@@ -0,0 +1,22 @@
+#include "BsScriptResource.h"
+
+namespace BansheeEngine
+{
+	ScriptResourceBase::ScriptResourceBase(MonoObject* instance)
+		:PersistentScriptObjectBase(instance), mRefreshInProgress(false)
+	{ }
+
+	ScriptObjectBackup ScriptResourceBase::beginRefresh()
+	{
+		mRefreshInProgress = true;
+
+		return PersistentScriptObjectBase::beginRefresh();
+	}
+
+	void ScriptResourceBase::endRefresh(const ScriptObjectBackup& backupData)
+	{
+		mRefreshInProgress = false;
+
+		PersistentScriptObjectBase::endRefresh(backupData);
+	}
+}

+ 11 - 22
SBansheeEngine/Source/BsScriptResourceManager.cpp

@@ -8,47 +8,34 @@
 #include "BsScriptSpriteTexture.h"
 #include "BsScriptFont.h"
 #include "BsScriptManagedResource.h"
+#include "BsScriptAssemblyManager.h"
 
 namespace BansheeEngine
 {
 	ScriptResourceManager::ScriptResourceManager()
-		:mTextureClass(nullptr), mSpriteTextureClass(nullptr)
 	{
-		MonoAssembly* assembly = MonoManager::instance().getAssembly(BansheeEngineAssemblyName);
-		if(assembly == nullptr)
-			BS_EXCEPT(InternalErrorException, "Cannot find \"" + String(BansheeEngineAssemblyName) + "\" assembly.");
-
-		mTextureClass = assembly->getClass("BansheeEngine", "Texture2D");
-		mSpriteTextureClass = assembly->getClass("BansheeEngine", "SpriteTexture");
-		mFontClass = assembly->getClass("BansheeEngine", "Font");
-
-		if(mTextureClass == nullptr)
-			BS_EXCEPT(InternalErrorException, "Cannot find managed Texture2D class.");
-
-		if(mSpriteTextureClass == nullptr)
-			BS_EXCEPT(InternalErrorException, "Cannot find managed SpriteTexture class.");
-
-		if (mFontClass == nullptr)
-			BS_EXCEPT(InternalErrorException, "Cannot find managed Font class.");
 	}
 
 	ScriptTexture2D* ScriptResourceManager::createScriptTexture2D(const HTexture& resourceHandle)
 	{
-		MonoObject* monoInstance = mTextureClass->createInstance();
+		MonoClass* textureClass = ScriptAssemblyManager::instance().getTextureClass();
+		MonoObject* monoInstance = textureClass->createInstance();
 
 		return createScriptTexture2D(monoInstance, resourceHandle);
 	}
 
 	ScriptTexture3D* ScriptResourceManager::createScriptTexture3D(const HTexture& resourceHandle)
 	{
-		MonoObject* monoInstance = mTextureClass->createInstance();
+		MonoClass* textureClass = ScriptAssemblyManager::instance().getTextureClass();
+		MonoObject* monoInstance = textureClass->createInstance();
 
 		return createScriptTexture3D(monoInstance, resourceHandle);
 	}
 
 	ScriptTextureCube* ScriptResourceManager::createScriptTextureCube(const HTexture& resourceHandle)
 	{
-		MonoObject* monoInstance = mTextureClass->createInstance();
+		MonoClass* textureClass = ScriptAssemblyManager::instance().getTextureClass();
+		MonoObject* monoInstance = textureClass->createInstance();
 
 		return createScriptTextureCube(monoInstance, resourceHandle);
 	}
@@ -94,7 +81,8 @@ namespace BansheeEngine
 
 	ScriptSpriteTexture* ScriptResourceManager::createScriptSpriteTexture(const HSpriteTexture& resourceHandle)
 	{
-		MonoObject* monoInstance = mSpriteTextureClass->createInstance();
+		MonoClass* spriteTextureClass = ScriptAssemblyManager::instance().getSpriteTextureClass();
+		MonoObject* monoInstance = spriteTextureClass->createInstance();
 
 		return createScriptSpriteTexture(monoInstance, resourceHandle);
 	}
@@ -114,7 +102,8 @@ namespace BansheeEngine
 
 	ScriptFont* ScriptResourceManager::createScriptFont(const HFont& resourceHandle)
 	{
-		MonoObject* monoInstance = mFontClass->createInstance();
+		MonoClass* fontClass = ScriptAssemblyManager::instance().getFontClass();
+		MonoObject* monoInstance = fontClass->createInstance();
 
 		return createScriptFont(monoInstance, resourceHandle);
 	}

+ 3 - 1
SBansheeEngine/Source/BsScriptSceneObject.cpp

@@ -299,7 +299,9 @@ namespace BansheeEngine
 	void ScriptSceneObject::_onManagedInstanceDeleted()
 	{
 		mManagedInstance = nullptr;
-		ScriptGameObjectManager::instance().destroyScriptGameObject(this);
+
+		if (!mRefreshInProgress)
+			ScriptGameObjectManager::instance().destroyScriptGameObject(this);
 	}
 
 	void ScriptSceneObject::setNativeHandle(const HGameObject& gameObject)

+ 1 - 1
SBansheeEngine/Source/BsScriptSerializableArray.cpp

@@ -3,7 +3,7 @@
 #include "BsMonoField.h"
 #include "BsMonoClass.h"
 #include "BsMonoManager.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsManagedSerializableObjectInfo.h"
 #include "BsScriptSerializableProperty.h"
 

+ 1 - 1
SBansheeEngine/Source/BsScriptSerializableDictionary.cpp

@@ -3,7 +3,7 @@
 #include "BsMonoField.h"
 #include "BsMonoClass.h"
 #include "BsMonoManager.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsManagedSerializableObjectInfo.h"
 #include "BsScriptSerializableProperty.h"
 

+ 1 - 1
SBansheeEngine/Source/BsScriptSerializableList.cpp

@@ -3,7 +3,7 @@
 #include "BsMonoField.h"
 #include "BsMonoClass.h"
 #include "BsMonoManager.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsManagedSerializableObjectInfo.h"
 #include "BsScriptSerializableProperty.h"
 

+ 2 - 2
SBansheeEngine/Source/BsScriptSerializableObject.cpp

@@ -1,6 +1,6 @@
 #include "BsScriptSerializableObject.h"
 #include "BsScriptSerializableField.h"
-#include "BsRuntimeScriptObjects.h"
+#include "BsScriptAssemblyManager.h"
 #include "BsScriptMeta.h"
 #include "BsMonoField.h"
 #include "BsMonoClass.h"
@@ -44,7 +44,7 @@ namespace BansheeEngine
 		String elementTypeName = mono_class_get_name(monoClass);
 
 		ManagedSerializableObjectInfoPtr objInfo;
-		RuntimeScriptObjects::instance().getSerializableObjectInfo(elementNs, elementTypeName, objInfo);
+		ScriptAssemblyManager::instance().getSerializableObjectInfo(elementNs, elementTypeName, objInfo);
 
 		createInternal(instance, objInfo);
 	}

+ 3 - 1
SBansheeEngine/Source/BsScriptSpriteTexture.cpp

@@ -39,7 +39,9 @@ namespace BansheeEngine
 	void ScriptSpriteTexture::_onManagedInstanceDeleted()
 	{
 		mManagedInstance = nullptr;
-		ScriptResourceManager::instance().destroyScriptResource(this);
+
+		if (!mRefreshInProgress)
+			ScriptResourceManager::instance().destroyScriptResource(this);
 	}
 
 	void ScriptSpriteTexture::setNativeHandle(const HResource& resource) 

+ 3 - 1
SBansheeEngine/Source/BsScriptTexture2D.cpp

@@ -87,7 +87,9 @@ namespace BansheeEngine
 	void ScriptTexture2D::_onManagedInstanceDeleted()
 	{
 		mManagedInstance = nullptr;
-		ScriptResourceManager::instance().destroyScriptResource(this);
+
+		if (!mRefreshInProgress)
+			ScriptResourceManager::instance().destroyScriptResource(this);
 	}
 
 	void ScriptTexture2D::setNativeHandle(const HResource& resource) 

+ 3 - 1
SBansheeEngine/Source/BsScriptTexture3D.cpp

@@ -87,7 +87,9 @@ namespace BansheeEngine
 	void ScriptTexture3D::_onManagedInstanceDeleted()
 	{
 		mManagedInstance = nullptr;
-		ScriptResourceManager::instance().destroyScriptResource(this);
+
+		if (!mRefreshInProgress)
+			ScriptResourceManager::instance().destroyScriptResource(this);
 	}
 
 	void ScriptTexture3D::setNativeHandle(const HResource& resource)

+ 3 - 1
SBansheeEngine/Source/BsScriptTextureCube.cpp

@@ -86,7 +86,9 @@ namespace BansheeEngine
 	void ScriptTextureCube::_onManagedInstanceDeleted()
 	{
 		mManagedInstance = nullptr;
-		ScriptResourceManager::instance().destroyScriptResource(this);
+
+		if (!mRefreshInProgress)
+			ScriptResourceManager::instance().destroyScriptResource(this);
 	}
 
 	void ScriptTextureCube::setNativeHandle(const HResource& resource)

+ 13 - 44
TODO.txt

@@ -1,14 +1,15 @@
 --------- ALL LONG TERM TASKS / FIXES BELONG TO GOOGLE DOCS: ImplementationTODO OR PossibleImprovements ----------
 
-See GDrive/Resources doc for resources refactor
+<<<<<Assembly refresh>>>>>
 
-I can get mono errors by checking g_print calls in goutput.c
- - Calling thunks incorrectly can cause those weird errors with no real callstack
+When serializing Camera I cannot save the reference to RenderTexture. Make it a Resource?
+Enum serialization probably doesn't work. I'll need to fix that before serializing Camera as it will try to serialize multiple enums
+ - Try using mono_type_get_underlying_type(monoType); to detect actual type of the enum (or possibly mono_class_enum_basetype)
+ - Make sure I don't just store enum as int as-is, as that might cause problems when deserializing if enum underlying type changed (e.g. it used to be int64 but is now int32)
 
-Crash on GLTextureBuffer::download on shutdown (OpenGL error invalid enum)
-Create a stack allocatable custom vector implementation and make getResourceDependencies and getCoreDependencies use it
+When component type cannot be found upon refresh it will still remain on SceneObject, invisible. Make sure it is not saved as such, or make it visible and removable.
 
-Multi-resource saving:
+<<<<Multi-resource saving>>>>:
  - Modify Font so it doesn't contain a texture, but instead keeps a handle to it
  - Register it in its meta file
  - When saving such a resource with dependencies save the contained files to a sub-directory with the same name as top level resource
@@ -18,7 +19,12 @@ Multi-resource saving:
 Other:
 Window resize end callback
 Add cutoff plane when rendering discs for rotation handle.
-What happens when I close widgets from C++ code (e.g. due to layout reload or change)? Will C# still try to access them?
+
+I can get mono errors by checking g_print calls in goutput.c
+ - Calling thunks incorrectly can cause those weird errors with no real callstack
+
+Crash on GLTextureBuffer::download on shutdown (OpenGL error invalid enum)
+Create a stack allocatable custom vector implementation and make getResourceDependencies and getCoreDependencies use it
 
 C# SceneView:
 Test new Scene window and fix every issue
@@ -26,43 +32,6 @@ Add ProjectWindow and HierarchyWindow to C#
  - Make TreeViews a C# element?
 Set up a default layout and save it
 
------------------
-Resource refresh:
- - Add ScriptObject::beginRefresh, ScriptObject::endRefresh
-   - Each ScriptObject can internally store data needed for refresh (e.g. serialized instance and similar)
-   - beginRefresh needs to at least clear mCachedPtr (and ensure when managed objects get destroyed that ScriptObjects stay as is)
-   - endRefresh needs to at least restore mCachedPtr
-   - Depending on ScriptObject other functionality might be needed
- - After refresh check if type still exists, and if it doesn't delete the ScriptObject (or throw an assert if that wasn't supposed to happen)
- - Add MonoManager::refreshDomain. This releases current domain (and all assemblies in it), and allocates a new one
- - Add CoreApplication::refreshManagedAssemblies
-    - Calls ScriptObject::beginRefresh, MonoManager::refreshDomain and ScriptObject::endRefresh
-    - Will also need to call RuntimeScriptManager and some other types that rely on Mono types
-
-When restoring manage instance don't call the constructor. Currently some constructors call native methods that set up ScriptObjects, which is not what I want to do.
- - Unity does call the constructor so if it turns out to be necesary go on a case by case basis and change their constructors so they do not call into native code. (Or if they have to, to check if the object isn't already initialized)
-
-Find all references to: MonoObject, MonoClass, MonoField, MonoProperty, MonoMethod, MonoAssembly, function thunks and ensure those are properly released and re-constructed during refresh.
- - Make a list and figure out possible issues. Then modify them before starting the refactor.
-
-Find all C# versions of ScriptObject and see if they store any data. If they do that data might need to be serialized and deserialized during refresh.
- - Make a list and figure out possible issues.
-
-Types that I need to ensure stay valid after refresh:
- - Any Component, Resource and GUI object
- - EditorWindow
-
-Types I can probably ignore:
- - SerializableProperty and related types
-   - They can't be serialized by anything. So technically after refresh we're forced to create new ones anyway.
- - HandleSlider
-   - Also can't be serialized.
-
-I need to ensure to call all start-up methods after refresh.
- - e.g. Component onInitialize and whatever is called for EditorWindow or inspectors
-
------------------
-
 Need a way to drag and drop items from Scene tree view to Scene view
 
 AFTER I have scene widget in C#: