Browse Source

Many fixes to get assembly refresh working
Nested managed types are now properly enumerated
Extended MonoUtil with a more robust way of retrieving class type name and namespace

Marko Pintera 11 years ago
parent
commit
6bbe6114ce
29 changed files with 245 additions and 124 deletions
  1. 7 0
      BansheeMono/Include/BsMonoAssembly.h
  2. 0 26
      BansheeMono/Include/BsMonoManager.h
  3. 49 0
      BansheeMono/Include/BsMonoUtil.h
  4. 63 6
      BansheeMono/Source/BsMonoAssembly.cpp
  5. 5 3
      BansheeMono/Source/BsMonoClass.cpp
  6. 2 53
      BansheeMono/Source/BsMonoManager.cpp
  7. 2 0
      BansheeUtility/Source/BsMemorySerializer.cpp
  8. 29 0
      MBansheeEditor/DebugWindow.cs
  9. 2 0
      MBansheeEditor/EditorApplication.cs
  10. 1 0
      MBansheeEditor/MBansheeEditor.csproj
  11. 3 0
      SBansheeEditor/Include/BsEditorScriptManager.h
  12. 19 2
      SBansheeEditor/Source/BsEditorScriptManager.cpp
  13. 4 2
      SBansheeEditor/Source/BsScriptGUIGameObjectField.cpp
  14. 3 2
      SBansheeEditor/Source/BsScriptGUIResourceField.cpp
  15. 2 2
      SBansheeEditor/Source/BsScriptGizmoManager.cpp
  16. 2 1
      SBansheeEditor/Source/BsScriptHandleManager.cpp
  17. 6 0
      SBansheeEngine/Include/BsScriptObjectManager.h
  18. 4 2
      SBansheeEngine/Source/BsManagedComponent.cpp
  19. 4 4
      SBansheeEngine/Source/BsManagedResource.cpp
  20. 5 3
      SBansheeEngine/Source/BsManagedSerializableDictionary.cpp
  21. 5 3
      SBansheeEngine/Source/BsManagedSerializableList.cpp
  22. 4 3
      SBansheeEngine/Source/BsManagedSerializableObject.cpp
  23. 3 0
      SBansheeEngine/Source/BsScriptAssemblyManager.cpp
  24. 3 4
      SBansheeEngine/Source/BsScriptComponent.cpp
  25. 2 2
      SBansheeEngine/Source/BsScriptInputConfiguration.cpp
  26. 2 3
      SBansheeEngine/Source/BsScriptManagedResource.cpp
  27. 2 0
      SBansheeEngine/Source/BsScriptObjectManager.cpp
  28. 5 2
      SBansheeEngine/Source/BsScriptSerializableObject.cpp
  29. 7 1
      TODO.txt

+ 7 - 0
BansheeMono/Include/BsMonoAssembly.h

@@ -71,6 +71,13 @@ namespace BansheeEngine
 
 
 		MonoAssembly(const String& path, const String& name);
 		MonoAssembly(const String& path, const String& name);
 
 
+		/**
+	     * @brief	Attempts to find a managed class with the specified namespace and name
+		 *			in this assembly. Registers a new class using the provided raw class if
+		 *			one cannot be found. Returns null provided raw class is null.
+	     */
+		MonoClass* getClass(const String& namespaceName, const String& name, ::MonoClass* rawMonoClass) const;
+
 		/**
 		/**
 		 * @brief	Loads an assembly into the specified domain.
 		 * @brief	Loads an assembly into the specified domain.
 		 */
 		 */

+ 0 - 26
BansheeMono/Include/BsMonoManager.h

@@ -41,27 +41,6 @@ namespace BansheeEngine
 		 */
 		 */
 		MonoClass* findClass(::MonoClass* rawMonoClass);
 		MonoClass* findClass(::MonoClass* rawMonoClass);
 
 
-		/**
-		 * @brief	Returns the type name of the provided object, with namespace.
-		 *
-		 * @param 	obj	If non-null, the object to get the type name of.
-		 */
-		String getFullTypeName(MonoObject* obj);
-
-		/**
-		 * @brief	Returns the namespace of the provided object.
-		 *
-		 * @param 	obj	If non-null, the object to get the namespace of.
-		 */
-		String getNamespace(MonoObject* obj);
-
-		/**
-		 * @brief	Returns the type name of the provided object, without namespace.
-		 *
-		 * @param 	obj	If non-null, the object to get the type name of.
-		 */
-		String getTypeName(MonoObject* obj);
-
 		/**
 		/**
 		 * @brief	Returns the current Mono domains.
 		 * @brief	Returns the current Mono domains.
 		 */
 		 */
@@ -92,11 +71,6 @@ namespace BansheeEngine
 		 */
 		 */
 		static void registerScriptType(ScriptMeta* metaData);
 		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:
 	private:
 		/**
 		/**
 		 * @brief	Initializes a previous loaded assembly.
 		 * @brief	Initializes a previous loaded assembly.

+ 49 - 0
BansheeMono/Include/BsMonoUtil.h

@@ -67,6 +67,55 @@ namespace BansheeEngine
 			return wstringToMono(domain, toWString(str));
 			return wstringToMono(domain, toWString(str));
 		}
 		}
 
 
+		/**
+		 * @brief	Outputs name and namespace for the type of the specified object.
+		 */
+		static void getClassName(MonoObject* obj, String& ns, String& typeName)
+		{
+			if (obj == nullptr)
+				return;
+
+			::MonoClass* monoClass = mono_object_get_class(obj);
+			getClassName(monoClass, ns, typeName);
+		}
+
+		/**
+		 * @brief	Outputs name and namespace for the specified type.
+		 */
+		static void getClassName(::MonoClass* monoClass, String& ns, String& typeName)
+		{
+			::MonoClass* nestingClass = mono_class_get_nesting_type(monoClass);
+
+			if (nestingClass == nullptr)
+			{
+				ns = mono_class_get_namespace(monoClass);
+				typeName = mono_class_get_name(monoClass);
+
+				return;
+			}
+			else
+			{
+				typeName = String("+") + mono_class_get_name(monoClass);
+
+				do 
+				{
+					::MonoClass* nextNestingClass = mono_class_get_nesting_type(nestingClass);
+					if (nextNestingClass != nullptr)
+					{
+						typeName = String("+") + mono_class_get_name(nestingClass) + typeName;
+						nestingClass = nextNestingClass;
+					}
+					else
+					{
+						ns = mono_class_get_namespace(nestingClass);
+						typeName = mono_class_get_name(nestingClass) + typeName;
+
+						break;
+					}
+				} while (true);
+			}
+		}
+
 		/**
 		/**
 		 * @copydoc	throwIfException
 		 * @copydoc	throwIfException
 		 */
 		 */

+ 63 - 6
BansheeMono/Source/BsMonoAssembly.cpp

@@ -162,8 +162,9 @@ namespace BansheeEngine
 		if(iterFind != mClassesByRaw.end())
 		if(iterFind != mClassesByRaw.end())
 			return iterFind->second;
 			return iterFind->second;
 
 
-		String ns = mono_class_get_namespace(rawMonoClass);
-		String typeName = mono_class_get_name(rawMonoClass);
+		String ns;
+		String typeName;
+		MonoUtil::getClassName(rawMonoClass, ns, typeName);
 
 
 		MonoClass* newClass = new (bs_alloc<MonoClass>()) MonoClass(ns, typeName, rawMonoClass, this);
 		MonoClass* newClass = new (bs_alloc<MonoClass>()) MonoClass(ns, typeName, rawMonoClass, this);
 		
 		
@@ -178,12 +179,39 @@ namespace BansheeEngine
 		return newClass;
 		return newClass;
 	}
 	}
 
 
+	MonoClass* MonoAssembly::getClass(const String& ns, const String& typeName, ::MonoClass* rawMonoClass) const
+	{
+		if (!mIsLoaded)
+			BS_EXCEPT(InvalidStateException, "Trying to use an unloaded assembly.");
+
+		if (rawMonoClass == nullptr)
+			return nullptr;
+
+		auto iterFind = mClassesByRaw.find(rawMonoClass);
+
+		if (iterFind != mClassesByRaw.end())
+			return iterFind->second;
+
+		MonoClass* newClass = new (bs_alloc<MonoClass>()) MonoClass(ns, typeName, rawMonoClass, this);
+
+		mClassesByRaw[rawMonoClass] = newClass;
+
+		if (!isGenericClass(typeName)) // No point in referencing generic types by name as all instances share it
+		{
+			MonoAssembly::ClassId classId(ns, typeName);
+			mClasses[classId] = newClass;
+		}
+
+		return newClass;
+	}
+
 	const Vector<MonoClass*>& MonoAssembly::getAllClasses() const
 	const Vector<MonoClass*>& MonoAssembly::getAllClasses() const
 	{
 	{
 		if(mHaveCachedClassList)
 		if(mHaveCachedClassList)
 			return mCachedClassList;
 			return mCachedClassList;
-
+		
 		mCachedClassList.clear();
 		mCachedClassList.clear();
+		Stack<MonoClass*> todo;
 
 
 		int numRows = mono_image_get_table_rows (mMonoImage, MONO_TABLE_TYPEDEF);
 		int numRows = mono_image_get_table_rows (mMonoImage, MONO_TABLE_TYPEDEF);
 
 
@@ -191,13 +219,42 @@ namespace BansheeEngine
 		{
 		{
 			::MonoClass* monoClass = mono_class_get (mMonoImage, (i + 1) | MONO_TOKEN_TYPE_DEF);
 			::MonoClass* monoClass = mono_class_get (mMonoImage, (i + 1) | MONO_TOKEN_TYPE_DEF);
 
 
-			String ns = mono_class_get_namespace(monoClass);
-			String type = mono_class_get_name(monoClass);
+			String ns;
+			String type;
+			MonoUtil::getClassName(monoClass, ns, type);
 
 
 			MonoClass* curClass = getClass(ns, type);
 			MonoClass* curClass = getClass(ns, type);
 
 
-			if(curClass != nullptr)
+			if (curClass != nullptr)
+			{
+				// Get nested types if it has any
+				todo.push(curClass);
+				while (!todo.empty())
+				{
+					MonoClass* curNestedClass = todo.top();
+					todo.pop();
+
+					void* iter = nullptr;
+					do
+					{
+						::MonoClass* rawNestedClass = rawNestedClass = mono_class_get_nested_types(curNestedClass->_getInternalClass(), &iter);
+						if (rawNestedClass == nullptr)
+							break;
+
+						String nestedType = curNestedClass->getTypeName() + "+" + mono_class_get_name(rawNestedClass);
+
+						MonoClass* nestedClass = getClass(ns, nestedType, rawNestedClass);
+						if (nestedClass != nullptr)
+						{
+							mCachedClassList.push_back(nestedClass);
+							todo.push(nestedClass);
+						}
+
+					} while (true);					
+				}
+
 				mCachedClassList.push_back(curClass);
 				mCachedClassList.push_back(curClass);
+			}
 		}
 		}
 
 
 		mHaveCachedClassList = true;
 		mHaveCachedClassList = true;

+ 5 - 3
BansheeMono/Source/BsMonoClass.cpp

@@ -6,6 +6,7 @@
 #include "BsMonoManager.h"
 #include "BsMonoManager.h"
 #include "BsUtil.h"
 #include "BsUtil.h"
 #include "BsException.h"
 #include "BsException.h"
+#include "BsMonoUtil.h"
 #include <mono/metadata/debug-helpers.h>
 #include <mono/metadata/debug-helpers.h>
 #include "BsDebug.h"
 #include "BsDebug.h"
 
 
@@ -280,10 +281,11 @@ namespace BansheeEngine
 		if(monoBase == nullptr)
 		if(monoBase == nullptr)
 			return nullptr;
 			return nullptr;
 
 
-		String ns = mono_class_get_namespace(monoBase);
-		String typeName = mono_class_get_name(monoBase);
+		String ns;
+		String type;
+		MonoUtil::getClassName(monoBase, ns, type);
 
 
-		return MonoManager::instance().findClass(ns, typeName);
+		return MonoManager::instance().findClass(ns, type);
 	}
 	}
 
 
 	bool MonoClass::isInstanceOfType(MonoObject* object) const
 	bool MonoClass::isInstanceOfType(MonoObject* object) const

+ 2 - 53
BansheeMono/Source/BsMonoManager.cpp

@@ -174,56 +174,6 @@ namespace BansheeEngine
 		return nullptr;
 		return nullptr;
 	}
 	}
 
 
-	String MonoManager::getFullTypeName(MonoObject* obj)
-	{
-		if(obj == nullptr)
-			BS_EXCEPT(InvalidParametersException, "Object cannot be null.");
-
-		::MonoClass* monoClass = mono_object_get_class(obj);
-
-		const char* nameSpaceChars = mono_class_get_namespace(monoClass);
-		String namespaceStr;
-		if(nameSpaceChars != nullptr)
-			namespaceStr = nameSpaceChars;
-
-		const char* typeNameChars = mono_class_get_name(monoClass);
-		String typeNameStr;
-		if(typeNameChars != nullptr)
-			typeNameStr = typeNameChars;
-
-		return namespaceStr + "." + typeNameStr;
-	}
-
-	String MonoManager::getNamespace(MonoObject* obj)
-	{
-		if(obj == nullptr)
-			BS_EXCEPT(InvalidParametersException, "Object cannot be null.");
-
-		::MonoClass* monoClass = mono_object_get_class(obj);
-
-		const char* nameSpaceChars = mono_class_get_namespace(monoClass);
-		String namespaceStr;
-		if(nameSpaceChars != nullptr)
-			namespaceStr = nameSpaceChars;
-
-		return namespaceStr;
-	}
-
-	String MonoManager::getTypeName(MonoObject* obj)
-	{
-		if(obj == nullptr)
-			BS_EXCEPT(InvalidParametersException, "Object cannot be null.");
-
-		::MonoClass* monoClass = mono_object_get_class(obj);
-
-		const char* typeNameChars = mono_class_get_name(monoClass);
-		String typeNameStr;
-		if(typeNameChars != nullptr)
-			typeNameStr = typeNameChars;
-
-		return typeNameStr;
-	}
-
 	void MonoManager::unloadScriptDomain()
 	void MonoManager::unloadScriptDomain()
 	{
 	{
 		if (mScriptDomain != nullptr)
 		if (mScriptDomain != nullptr)
@@ -245,7 +195,8 @@ namespace BansheeEngine
 		for (auto& assemblyEntry : mAssemblies)
 		for (auto& assemblyEntry : mAssemblies)
 			assemblyEntry.second->unload();
 			assemblyEntry.second->unload();
 
 
-		mIsCoreLoaded = true;
+		mAssemblies.erase("corlib");
+		mIsCoreLoaded = false;
 	}
 	}
 
 
 	void MonoManager::loadScriptDomain()
 	void MonoManager::loadScriptDomain()
@@ -269,7 +220,5 @@ namespace BansheeEngine
 			for (auto& assemblyEntry : mAssemblies)
 			for (auto& assemblyEntry : mAssemblies)
 				initializeAssembly(*assemblyEntry.second);
 				initializeAssembly(*assemblyEntry.second);
 		}
 		}
-
-		onDomainReload();
 	}
 	}
 }
 }

+ 2 - 0
BansheeUtility/Source/BsMemorySerializer.cpp

@@ -49,6 +49,8 @@ namespace BansheeEngine
 			bs_free(iter->buffer);
 			bs_free(iter->buffer);
 		}
 		}
 
 
+		mBufferPieces.clear();
+
 		return resultBuffer;
 		return resultBuffer;
 	}
 	}
 
 

+ 29 - 0
MBansheeEditor/DebugWindow.cs

@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    internal class DebugWindow : EditorWindow
+    {
+        private void OnInitialize()
+        {
+            GUIButton refreshAssembly = new GUIButton("Refresh assembly");
+            refreshAssembly.OnClick += RefreshAssembly_OnClick;
+
+            GUI.layout.AddElement(refreshAssembly);
+        }
+
+        void RefreshAssembly_OnClick()
+        {
+            Internal_RefreshAssembly();
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern void Internal_RefreshAssembly();
+    }
+}

+ 2 - 0
MBansheeEditor/EditorApplication.cs

@@ -57,6 +57,7 @@ namespace BansheeEditor
 
 
         private InspectorWindow inspector;
         private InspectorWindow inspector;
         private SceneWindow scene;
         private SceneWindow scene;
+        private DebugWindow debug;
 
 
         // DEBUG ONLY
         // DEBUG ONLY
         Debug_Component1 dbgComponent;
         Debug_Component1 dbgComponent;
@@ -85,6 +86,7 @@ namespace BansheeEditor
             // Open windows
             // Open windows
             inspector = EditorWindow.OpenWindow<InspectorWindow>();
             inspector = EditorWindow.OpenWindow<InspectorWindow>();
             scene = EditorWindow.OpenWindow<SceneWindow>();
             scene = EditorWindow.OpenWindow<SceneWindow>();
+            debug = EditorWindow.OpenWindow<DebugWindow>();
 
 
             // DEBUG ONLY
             // DEBUG ONLY
 
 

+ 1 - 0
MBansheeEditor/MBansheeEditor.csproj

@@ -45,6 +45,7 @@
     <Compile Include="DbgGizmoComponent.cs" />
     <Compile Include="DbgGizmoComponent.cs" />
     <Compile Include="DbgResource.cs" />
     <Compile Include="DbgResource.cs" />
     <Compile Include="DebugCameraHandle.cs" />
     <Compile Include="DebugCameraHandle.cs" />
+    <Compile Include="DebugWindow.cs" />
     <Compile Include="Debug_Component1.cs" />
     <Compile Include="Debug_Component1.cs" />
     <Compile Include="Debug_Component2.cs" />
     <Compile Include="Debug_Component2.cs" />
     <Compile Include="EditorApplication.cs" />
     <Compile Include="EditorApplication.cs" />

+ 3 - 0
SBansheeEditor/Include/BsEditorScriptManager.h

@@ -15,6 +15,7 @@ namespace BansheeEngine
 
 
 	private:
 	private:
 		void loadMonoTypes();
 		void loadMonoTypes();
+		static void debug_refreshAssembly();
 
 
 		static const float EDITOR_UPDATE_RATE;
 		static const float EDITOR_UPDATE_RATE;
 
 
@@ -25,5 +26,7 @@ namespace BansheeEngine
 		MonoMethod* mUpdateMethod;
 		MonoMethod* mUpdateMethod;
 
 
 		HEvent mOnDomainLoadConn;
 		HEvent mOnDomainLoadConn;
+
+		static bool mDebugRefresh;
 	};
 	};
 }
 }

+ 19 - 2
SBansheeEditor/Source/BsEditorScriptManager.cpp

@@ -1,6 +1,6 @@
 #include "BsEditorScriptManager.h"
 #include "BsEditorScriptManager.h"
 #include "BsScriptEditorWindow.h"
 #include "BsScriptEditorWindow.h"
-#include "BsMonoManager.h"
+#include "BsScriptObjectManager.h"
 #include "BsMonoAssembly.h"
 #include "BsMonoAssembly.h"
 #include "BsMonoClass.h"
 #include "BsMonoClass.h"
 #include "BsMonoMethod.h"
 #include "BsMonoMethod.h"
@@ -14,6 +14,7 @@
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	const float EditorScriptManager::EDITOR_UPDATE_RATE = 1.0f/60.0f; // Seconds
 	const float EditorScriptManager::EDITOR_UPDATE_RATE = 1.0f/60.0f; // Seconds
+	bool EditorScriptManager::mDebugRefresh = false;
 
 
 	EditorScriptManager::EditorScriptManager()
 	EditorScriptManager::EditorScriptManager()
 		:mEditorAssembly(nullptr), mProgramEdClass(nullptr), mUpdateMethod(nullptr)
 		:mEditorAssembly(nullptr), mProgramEdClass(nullptr), mUpdateMethod(nullptr)
@@ -27,7 +28,8 @@ namespace BansheeEngine
 		ScriptGizmoManager::startUp(ScriptAssemblyManager::instance());
 		ScriptGizmoManager::startUp(ScriptAssemblyManager::instance());
 		HandleManager::startUp<ScriptHandleManager>(ScriptAssemblyManager::instance());
 		HandleManager::startUp<ScriptHandleManager>(ScriptAssemblyManager::instance());
 
 
-		mOnDomainLoadConn = MonoManager::instance().onDomainReload.connect(std::bind(&EditorScriptManager::loadMonoTypes, this));
+		
+		mOnDomainLoadConn = ScriptObjectManager::instance().onRefreshDomainLoaded.connect(std::bind(&EditorScriptManager::loadMonoTypes, this));
 		
 		
 		mEditorAssembly->invoke(ASSEMBLY_ENTRY_POINT);
 		mEditorAssembly->invoke(ASSEMBLY_ENTRY_POINT);
 
 
@@ -58,9 +60,20 @@ namespace BansheeEngine
 			mLastUpdateTime += numUpdates * EDITOR_UPDATE_RATE;
 			mLastUpdateTime += numUpdates * EDITOR_UPDATE_RATE;
 		}
 		}
 
 
+		if (mDebugRefresh)
+		{
+			ScriptObjectManager::instance().refreshAssemblies();
+			mDebugRefresh = false;
+		}
+
 		ScriptGizmoManager::instance().update();
 		ScriptGizmoManager::instance().update();
 	}
 	}
 
 
+	void EditorScriptManager::debug_refreshAssembly()
+	{
+		mDebugRefresh = true;
+	}
+
 	void EditorScriptManager::loadMonoTypes()
 	void EditorScriptManager::loadMonoTypes()
 	{
 	{
 		const String ENGINE_ASSEMBLY_PATH = "..\\..\\Assemblies\\MBansheeEditor.dll";
 		const String ENGINE_ASSEMBLY_PATH = "..\\..\\Assemblies\\MBansheeEditor.dll";
@@ -73,5 +86,9 @@ namespace BansheeEngine
 
 
 		ScriptEditorWindow::clearRegisteredEditorWindow();
 		ScriptEditorWindow::clearRegisteredEditorWindow();
 		ScriptEditorWindow::registerManagedEditorWindows();
 		ScriptEditorWindow::registerManagedEditorWindows();
+
+		// DEBUG ONLY
+		MonoClass* debugWindowClass = mEditorAssembly->getClass("BansheeEditor", "DebugWindow");
+		debugWindowClass->addInternalCall("Internal_RefreshAssembly", &EditorScriptManager::debug_refreshAssembly);
 	}
 	}
 }
 }

+ 4 - 2
SBansheeEditor/Source/BsScriptGUIGameObjectField.cpp

@@ -17,6 +17,7 @@
 #include "BsScriptGUIContent.h"
 #include "BsScriptGUIContent.h"
 #include "BsScriptGameObject.h"
 #include "BsScriptGameObject.h"
 #include "BsScriptGameObjectManager.h"
 #include "BsScriptGameObjectManager.h"
+#include "BsMonoUtil.h"
 
 
 using namespace std::placeholders;
 using namespace std::placeholders;
 
 
@@ -53,8 +54,9 @@ namespace BansheeEngine
 		MonoType* monoType = mono_reflection_type_get_type(type);
 		MonoType* monoType = mono_reflection_type_get_type(type);
 		::MonoClass* monoClass = mono_type_get_class(monoType);
 		::MonoClass* monoClass = mono_type_get_class(monoType);
 
 
-		String typeNamespace = mono_class_get_namespace(monoClass);
-		String typeName = mono_class_get_name(monoClass);
+		String typeNamespace;
+		String typeName;
+		MonoUtil::getClassName(monoClass, typeNamespace, typeName);
 
 
 		GUIGameObjectField* guiGameObjectField = nullptr;
 		GUIGameObjectField* guiGameObjectField = nullptr;
 		if (withTitle)
 		if (withTitle)

+ 3 - 2
SBansheeEditor/Source/BsScriptGUIResourceField.cpp

@@ -53,8 +53,9 @@ namespace BansheeEngine
 		MonoType* monoType = mono_reflection_type_get_type(type);
 		MonoType* monoType = mono_reflection_type_get_type(type);
 		::MonoClass* monoClass = mono_type_get_class(monoType);
 		::MonoClass* monoClass = mono_type_get_class(monoType);
 
 
-		String typeNamespace = mono_class_get_namespace(monoClass);
-		String typeName = mono_class_get_name(monoClass);
+		String typeNamespace;
+		String typeName;
+		MonoUtil::getClassName(monoClass, typeNamespace, typeName);
 
 
 		GUIResourceField* guiResourceField = nullptr;
 		GUIResourceField* guiResourceField = nullptr;
 		if (withTitle)
 		if (withTitle)

+ 2 - 2
SBansheeEditor/Source/BsScriptGizmoManager.cpp

@@ -11,7 +11,7 @@
 #include "BsManagedComponent.h"
 #include "BsManagedComponent.h"
 #include "BsGizmoManager.h"
 #include "BsGizmoManager.h"
 #include "BsSelection.h"
 #include "BsSelection.h"
-#include "BsMonoManager.h"
+#include "BsScriptObjectManager.h"
 
 
 using namespace std::placeholders;
 using namespace std::placeholders;
 
 
@@ -20,7 +20,7 @@ namespace BansheeEngine
 	ScriptGizmoManager::ScriptGizmoManager(ScriptAssemblyManager& scriptObjectManager)
 	ScriptGizmoManager::ScriptGizmoManager(ScriptAssemblyManager& scriptObjectManager)
 		:mScriptObjectManager(scriptObjectManager), mDrawGizmoAttribute(nullptr), mFlagsField(nullptr)
 		:mScriptObjectManager(scriptObjectManager), mDrawGizmoAttribute(nullptr), mFlagsField(nullptr)
 	{
 	{
-		mDomainLoadedConn = MonoManager::instance().onDomainReload.connect(std::bind(&ScriptGizmoManager::reloadAssemblyData, this));
+		mDomainLoadedConn = ScriptObjectManager::instance().onRefreshDomainLoaded.connect(std::bind(&ScriptGizmoManager::reloadAssemblyData, this));
 		reloadAssemblyData();
 		reloadAssemblyData();
 	}
 	}
 
 

+ 2 - 1
SBansheeEditor/Source/BsScriptHandleManager.cpp

@@ -9,6 +9,7 @@
 #include "BsSelection.h"
 #include "BsSelection.h"
 #include "BsSceneObject.h"
 #include "BsSceneObject.h"
 #include "BsManagedComponent.h"
 #include "BsManagedComponent.h"
+#include "BsScriptObjectManager.h"
 
 
 using namespace std::placeholders;
 using namespace std::placeholders;
 
 
@@ -17,7 +18,7 @@ namespace BansheeEngine
 	ScriptHandleManager::ScriptHandleManager(ScriptAssemblyManager& scriptObjectManager)
 	ScriptHandleManager::ScriptHandleManager(ScriptAssemblyManager& scriptObjectManager)
 		:mScriptObjectManager(scriptObjectManager)
 		:mScriptObjectManager(scriptObjectManager)
 	{
 	{
-		mDomainLoadConn = MonoManager::instance().onDomainReload.connect(std::bind(&ScriptHandleManager::reloadAssemblyData, this));
+		mDomainLoadConn = ScriptObjectManager::instance().onRefreshDomainLoaded.connect(std::bind(&ScriptHandleManager::reloadAssemblyData, this));
 		reloadAssemblyData();
 		reloadAssemblyData();
 	}
 	}
 
 

+ 6 - 0
SBansheeEngine/Include/BsScriptObjectManager.h

@@ -15,6 +15,12 @@ namespace BansheeEngine
 
 
 		void refreshAssemblies();
 		void refreshAssemblies();
 
 
+		/**
+		 * @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()> onRefreshDomainLoaded;
+
 		Event<void()> onRefreshComplete;
 		Event<void()> onRefreshComplete;
 	private:
 	private:
 		Set<ScriptObjectBase*> mScriptObjects;
 		Set<ScriptObjectBase*> mScriptObjects;

+ 4 - 2
SBansheeEngine/Source/BsManagedComponent.cpp

@@ -25,8 +25,7 @@ namespace BansheeEngine
 		MonoType* monoType = mono_reflection_type_get_type(mRuntimeType);
 		MonoType* monoType = mono_reflection_type_get_type(mRuntimeType);
 		::MonoClass* monoClass = mono_type_get_class(monoType);
 		::MonoClass* monoClass = mono_type_get_class(monoType);
 
 
-		mNamespace = mono_class_get_namespace(monoClass);
-		mTypeName = mono_class_get_name(monoClass);
+		MonoUtil::getClassName(monoClass, mNamespace, mTypeName);
 
 
 		MonoClass* managedClass = MonoManager::instance().findClass(mNamespace, mTypeName);
 		MonoClass* managedClass = MonoManager::instance().findClass(mNamespace, mTypeName);
 		if(managedClass == nullptr)
 		if(managedClass == nullptr)
@@ -129,7 +128,10 @@ namespace BansheeEngine
 		{
 		{
 			MemorySerializer ms;
 			MemorySerializer ms;
 			ManagedSerializableObjectInfoPtr objectInfo = std::static_pointer_cast<ManagedSerializableObjectInfo>(ms.decode(data.mTypeInfo.data, data.mTypeInfo.size));
 			ManagedSerializableObjectInfoPtr objectInfo = std::static_pointer_cast<ManagedSerializableObjectInfo>(ms.decode(data.mTypeInfo.data, data.mTypeInfo.size));
+
+			GameObjectManager::instance().startDeserialization();
 			ManagedSerializableObjectDataPtr objectData = std::static_pointer_cast<ManagedSerializableObjectData>(ms.decode(data.mObjectData.data, data.mObjectData.size));
 			ManagedSerializableObjectDataPtr objectData = std::static_pointer_cast<ManagedSerializableObjectData>(ms.decode(data.mObjectData.data, data.mObjectData.size));
+			GameObjectManager::instance().endDeserialization();
 
 
 			if (!missingType)
 			if (!missingType)
 			{
 			{

+ 4 - 4
SBansheeEngine/Source/BsManagedResource.cpp

@@ -10,6 +10,7 @@
 #include "BsManagedSerializableObjectInfo.h"
 #include "BsManagedSerializableObjectInfo.h"
 #include "BsManagedSerializableObjectData.h"
 #include "BsManagedSerializableObjectData.h"
 #include "BsMemorySerializer.h"
 #include "BsMemorySerializer.h"
+#include "BsMonoUtil.h"
 #include "BsDebug.h"
 #include "BsDebug.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
@@ -24,10 +25,9 @@ namespace BansheeEngine
 		ManagedResourceMetaDataPtr metaData = bs_shared_ptr<ManagedResourceMetaData>();
 		ManagedResourceMetaDataPtr metaData = bs_shared_ptr<ManagedResourceMetaData>();
 		mMetaData = metaData;
 		mMetaData = metaData;
 
 
-		::MonoClass* monoClass = mono_object_get_class(managedInstance);
-
-		metaData->typeNamespace = mono_class_get_namespace(monoClass);
-		metaData->typeName = mono_class_get_name(monoClass);
+		String elementNs;
+		String elementTypeName;
+		MonoUtil::getClassName(managedInstance, metaData->typeNamespace, metaData->typeName);
 
 
 		MonoClass* managedClass = MonoManager::instance().findClass(metaData->typeNamespace, metaData->typeName);
 		MonoClass* managedClass = MonoManager::instance().findClass(metaData->typeNamespace, metaData->typeName);
 		if (managedClass == nullptr)
 		if (managedClass == nullptr)

+ 5 - 3
SBansheeEngine/Source/BsManagedSerializableDictionary.cpp

@@ -6,6 +6,7 @@
 #include "BsMonoClass.h"
 #include "BsMonoClass.h"
 #include "BsMonoMethod.h"
 #include "BsMonoMethod.h"
 #include "BsMonoProperty.h"
 #include "BsMonoProperty.h"
+#include "BsMonoUtil.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -57,9 +58,10 @@ namespace BansheeEngine
 		if(managedInstance == nullptr)
 		if(managedInstance == nullptr)
 			return nullptr;
 			return nullptr;
 
 
-		::MonoClass* monoClass = mono_object_get_class(managedInstance);
-		String elementNs = mono_class_get_namespace(monoClass);
-		String elementTypeName = mono_class_get_name(monoClass);
+		String elementNs;
+		String elementTypeName;
+		MonoUtil::getClassName(managedInstance, elementNs, elementTypeName);
+
 		String fullName = elementNs + "." + elementTypeName;
 		String fullName = elementNs + "." + elementTypeName;
 
 
 		if(ScriptAssemblyManager::instance().getSystemGenericDictionaryClass()->getFullName() != fullName)
 		if(ScriptAssemblyManager::instance().getSystemGenericDictionaryClass()->getFullName() != fullName)

+ 5 - 3
SBansheeEngine/Source/BsManagedSerializableList.cpp

@@ -6,6 +6,7 @@
 #include "BsMonoClass.h"
 #include "BsMonoClass.h"
 #include "BsMonoMethod.h"
 #include "BsMonoMethod.h"
 #include "BsMonoProperty.h"
 #include "BsMonoProperty.h"
+#include "BsMonoUtil.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -33,9 +34,10 @@ namespace BansheeEngine
 		if(managedInstance == nullptr)
 		if(managedInstance == nullptr)
 			return nullptr;
 			return nullptr;
 
 
-		::MonoClass* monoClass = mono_object_get_class(managedInstance);
-		String elementNs = mono_class_get_namespace(monoClass);
-		String elementTypeName = mono_class_get_name(monoClass);
+		String elementNs;
+		String elementTypeName;
+		MonoUtil::getClassName(managedInstance, elementNs, elementTypeName);
+
 		String fullName = elementNs + "." + elementTypeName;
 		String fullName = elementNs + "." + elementTypeName;
 
 
 		if(ScriptAssemblyManager::instance().getSystemGenericListClass()->getFullName() != fullName)
 		if(ScriptAssemblyManager::instance().getSystemGenericListClass()->getFullName() != fullName)

+ 4 - 3
SBansheeEngine/Source/BsManagedSerializableObject.cpp

@@ -5,6 +5,7 @@
 #include "BsScriptAssemblyManager.h"
 #include "BsScriptAssemblyManager.h"
 #include "BsManagedSerializableObjectData.h"
 #include "BsManagedSerializableObjectData.h"
 #include "BsMonoField.h"
 #include "BsMonoField.h"
+#include "BsMonoUtil.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -25,9 +26,9 @@ namespace BansheeEngine
 		if(managedInstance == nullptr)
 		if(managedInstance == nullptr)
 			return nullptr;
 			return nullptr;
 
 
-		::MonoClass* monoClass = mono_object_get_class(managedInstance);
-		String elementNs = mono_class_get_namespace(monoClass);
-		String elementTypeName = mono_class_get_name(monoClass);
+		String elementNs;
+		String elementTypeName;
+		MonoUtil::getClassName(managedInstance, elementNs, elementTypeName);
 
 
 		ManagedSerializableObjectInfoPtr objInfo;
 		ManagedSerializableObjectInfoPtr objInfo;
 		if(!ScriptAssemblyManager::instance().getSerializableObjectInfo(elementNs, elementTypeName, objInfo))
 		if(!ScriptAssemblyManager::instance().getSerializableObjectInfo(elementNs, elementTypeName, objInfo))

+ 3 - 0
SBansheeEngine/Source/BsScriptAssemblyManager.cpp

@@ -468,6 +468,9 @@ namespace BansheeEngine
 		String fullName = ns + "." + typeName;
 		String fullName = ns + "." + typeName;
 		for(auto& curAssembly : mAssemblyInfos)
 		for(auto& curAssembly : mAssemblyInfos)
 		{
 		{
+			if (curAssembly.second == nullptr)
+				continue;
+
 			auto iterFind = curAssembly.second->mTypeNameToId.find(fullName);
 			auto iterFind = curAssembly.second->mTypeNameToId.find(fullName);
 			if(iterFind != curAssembly.second->mTypeNameToId.end())
 			if(iterFind != curAssembly.second->mTypeNameToId.end())
 			{
 			{

+ 3 - 4
SBansheeEngine/Source/BsScriptComponent.cpp

@@ -11,6 +11,7 @@
 #include "BsScriptSceneObject.h"
 #include "BsScriptSceneObject.h"
 #include "BsManagedComponent.h"
 #include "BsManagedComponent.h"
 #include "BsSceneObject.h"
 #include "BsSceneObject.h"
+#include "BsMonoUtil.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -19,9 +20,7 @@ namespace BansheeEngine
 	{ 
 	{ 
 		assert(instance != nullptr);
 		assert(instance != nullptr);
 
 
-		::MonoClass* monoClass = mono_object_get_class(instance);
-		mNamespace = mono_class_get_namespace(monoClass);
-		mType = mono_class_get_name(monoClass);
+		MonoUtil::getClassName(instance, mNamespace, mType);
 	}
 	}
 
 
 	void ScriptComponent::initRuntimeData()
 	void ScriptComponent::initRuntimeData()
@@ -196,7 +195,7 @@ namespace BansheeEngine
 	{
 	{
 		ComponentBackupData componentBackup = any_cast<ComponentBackupData>(backupData.data);
 		ComponentBackupData componentBackup = any_cast<ComponentBackupData>(backupData.data);
 		mManagedComponent->restore(mManagedInstance, componentBackup, mTypeMissing);
 		mManagedComponent->restore(mManagedInstance, componentBackup, mTypeMissing);
-
+		
 		ScriptGameObjectBase::endRefresh(backupData);
 		ScriptGameObjectBase::endRefresh(backupData);
 	}
 	}
 
 

+ 2 - 2
SBansheeEngine/Source/BsScriptInputConfiguration.cpp

@@ -101,10 +101,10 @@ namespace BansheeEngine
 
 
 	void ScriptInputConfiguration::_onManagedInstanceDeleted()
 	void ScriptInputConfiguration::_onManagedInstanceDeleted()
 	{
 	{
-		mManagedInstance = nullptr;
-
 		UINT64 configId = (UINT64)mInputConfig.get();
 		UINT64 configId = (UINT64)mInputConfig.get();
 		ScriptInputConfigurations.erase(configId);
 		ScriptInputConfigurations.erase(configId);
+
+		ScriptObject::_onManagedInstanceDeleted();
 	}
 	}
 
 
 	ScriptVirtualAxis::ScriptVirtualAxis(MonoObject* instance)
 	ScriptVirtualAxis::ScriptVirtualAxis(MonoObject* instance)

+ 2 - 3
SBansheeEngine/Source/BsScriptManagedResource.cpp

@@ -8,6 +8,7 @@
 #include "BsManagedResource.h"
 #include "BsManagedResource.h"
 #include "BsResources.h"
 #include "BsResources.h"
 #include "BsException.h"
 #include "BsException.h"
+#include "BsMonoUtil.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -16,9 +17,7 @@ namespace BansheeEngine
 	{
 	{
 		assert(instance != nullptr);
 		assert(instance != nullptr);
 
 
-		::MonoClass* monoClass = mono_object_get_class(instance);
-		mNamespace = mono_class_get_namespace(monoClass);
-		mType = mono_class_get_name(monoClass);
+		MonoUtil::getClassName(instance, mNamespace, mType);
 	}
 	}
 
 
 	void ScriptManagedResource::initRuntimeData()
 	void ScriptManagedResource::initRuntimeData()

+ 2 - 0
SBansheeEngine/Source/BsScriptObjectManager.cpp

@@ -38,6 +38,8 @@ namespace BansheeEngine
 		MonoManager::instance().loadScriptDomain();
 		MonoManager::instance().loadScriptDomain();
 		ScriptAssemblyManager::instance().refreshAssemblyInfo();
 		ScriptAssemblyManager::instance().refreshAssemblyInfo();
 
 
+		onRefreshDomainLoaded();
+
 		for (auto& scriptObject : mScriptObjects)
 		for (auto& scriptObject : mScriptObjects)
 			scriptObject->_restoreManagedInstance();
 			scriptObject->_restoreManagedInstance();
 
 

+ 5 - 2
SBansheeEngine/Source/BsScriptSerializableObject.cpp

@@ -5,6 +5,7 @@
 #include "BsMonoField.h"
 #include "BsMonoField.h"
 #include "BsMonoClass.h"
 #include "BsMonoClass.h"
 #include "BsMonoManager.h"
 #include "BsMonoManager.h"
+#include "BsMonoUtil.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -40,8 +41,10 @@ namespace BansheeEngine
 	{
 	{
 		MonoType* internalType = mono_reflection_type_get_type(type);
 		MonoType* internalType = mono_reflection_type_get_type(type);
 		::MonoClass* monoClass = mono_type_get_class(internalType);
 		::MonoClass* monoClass = mono_type_get_class(internalType);
-		String elementNs = mono_class_get_namespace(monoClass);
-		String elementTypeName = mono_class_get_name(monoClass);
+
+		String elementNs;
+		String elementTypeName;
+		MonoUtil::getClassName(monoClass, elementNs, elementTypeName);
 
 
 		ManagedSerializableObjectInfoPtr objInfo;
 		ManagedSerializableObjectInfoPtr objInfo;
 		ScriptAssemblyManager::instance().getSerializableObjectInfo(elementNs, elementTypeName, objInfo);
 		ScriptAssemblyManager::instance().getSerializableObjectInfo(elementNs, elementTypeName, objInfo);

+ 7 - 1
TODO.txt

@@ -3,7 +3,13 @@
 <<<<<Assembly refresh>>>>>
 <<<<<Assembly refresh>>>>>
 
 
 When serializing Camera I cannot save the reference to RenderTexture. Make it a Resource?
 When serializing Camera I cannot save the reference to RenderTexture. Make it a Resource?
-Add a "Assembly Refresh" button so I can actually test it
+Possibly set up automatic refresh in debug mode after initialization? As an ad-hoc unit test
+
+Occasional crash happens in ScriptObjectManager::refreshAssemblies when backupData.data ends up being null (not all the time though)
+
+addComponent gets called during end refresh
+ - This seems to add another Camera to the scene
+ - While the old one contines to exist as well
 
 
 <<<<Multi-resource saving>>>>:
 <<<<Multi-resource saving>>>>:
  - Modify Font so it doesn't contain a texture, but instead keeps a handle to it
  - Modify Font so it doesn't contain a texture, but instead keeps a handle to it