瀏覽代碼

Added clone method to SerializedProperty (untested)
Added range to int fields

Marko Pintera 11 年之前
父節點
當前提交
5796d726b7
共有 27 個文件被更改,包括 633 次插入94 次删除
  1. 33 33
      BansheeCore/Include/BsCoreThread.h
  2. 3 0
      BansheeEditor/Include/BsGUIIntField.h
  3. 10 1
      BansheeEditor/Source/BsGUIIntField.cpp
  4. 6 3
      Inspector.txt
  5. 8 0
      MBansheeEditor/GUI/GUIIntField.cs
  6. 147 5
      MBansheeEditor/Inspector/InspectableArray.cs
  7. 33 0
      MBansheeEngine/SerializableProperty.cs
  8. 1 0
      SBansheeEditor/Include/BsScriptGUIIntField.h
  9. 8 0
      SBansheeEditor/Source/BsScriptGUIIntField.cpp
  10. 1 1
      SBansheeEngine/Include/BsManagedComponentRTTI.h
  11. 1 1
      SBansheeEngine/Include/BsManagedResourceRTTI.h
  12. 4 2
      SBansheeEngine/Include/BsManagedSerializableArray.h
  13. 1 1
      SBansheeEngine/Include/BsManagedSerializableArrayRTTI.h
  14. 3 1
      SBansheeEngine/Include/BsManagedSerializableDictionary.h
  15. 20 0
      SBansheeEngine/Include/BsManagedSerializableField.h
  16. 3 1
      SBansheeEngine/Include/BsManagedSerializableList.h
  17. 3 1
      SBansheeEngine/Include/BsManagedSerializableObject.h
  18. 1 1
      SBansheeEngine/Include/BsManagedSerializableObjectInfo.h
  19. 2 2
      SBansheeEngine/Include/BsManagedSerializableObjectInfoRTTI.h
  20. 1 1
      SBansheeEngine/Include/BsScriptEnginePrerequisites.h
  21. 5 0
      SBansheeEngine/Include/BsScriptSerializableProperty.h
  22. 32 18
      SBansheeEngine/Source/BsManagedSerializableArray.cpp
  23. 22 4
      SBansheeEngine/Source/BsManagedSerializableDictionary.cpp
  24. 193 4
      SBansheeEngine/Source/BsManagedSerializableField.cpp
  25. 23 9
      SBansheeEngine/Source/BsManagedSerializableList.cpp
  26. 30 5
      SBansheeEngine/Source/BsManagedSerializableObject.cpp
  27. 39 0
      SBansheeEngine/Source/BsScriptSerializableProperty.cpp

+ 33 - 33
BansheeCore/Include/BsCoreThread.h

@@ -37,30 +37,30 @@ public:
 	BS_CORE_EXPORT ~CoreThread();
 	BS_CORE_EXPORT ~CoreThread();
 
 
 	/**
 	/**
-		* @brief	Returns the id of the core thread. 
-		*/
+	 * @brief	Returns the id of the core thread. 
+	 */
 	BS_CORE_EXPORT BS_THREAD_ID_TYPE getCoreThreadId() { return mCoreThreadId; }
 	BS_CORE_EXPORT BS_THREAD_ID_TYPE getCoreThreadId() { return mCoreThreadId; }
 
 
 	/**
 	/**
-		* @brief	Creates or retrieves an accessor that you can use for executing commands on the core thread from 
-		* 			a non-core thread. The accessor will be bound to the thread you call this method on.
-		* 			
-		* @note		Accessors contain their own command queue and their commands will only start to get executed once that queue is submitted
-		* 			to the core thread via "submitAccessors" method.
-		*/
+	 * @brief	Creates or retrieves an accessor that you can use for executing commands on the core thread from 
+	 * 			a non-core thread. The accessor will be bound to the thread you call this method on.
+	 * 			
+	 * @note		Accessors contain their own command queue and their commands will only start to get executed once that queue is submitted
+	 * 			to the core thread via "submitAccessors" method.
+	 */
 	BS_CORE_EXPORT CoreAccessorPtr getAccessor();
 	BS_CORE_EXPORT CoreAccessorPtr getAccessor();
 
 
 	/**
 	/**
-	* @brief	Retrieves an accessor that you can use for executing commands on the core thread from
-	* 			a non-core thread. There is only one synchronized accessor and you may access it from any thread you wish.
-	* 			Note however that it is much more efficient to retrieve a separate non-synchronized accessor using
-	* 			"getAccessor" for each thread you will be using it on.
-	* 			
-	* @note		Accessors contain their own command queue and their commands will only start to get executed once that queue is submitted
-	* 			to the core thread via "submitAccessors" method.
-	* 			
-	*			Synced accessor commands are sent after all non-synced accessor commands are sent.
-	*/
+	 * @brief	Retrieves an accessor that you can use for executing commands on the core thread from
+	 * 			a non-core thread. There is only one synchronized accessor and you may access it from any thread you wish.
+	 * 			Note however that it is much more efficient to retrieve a separate non-synchronized accessor using
+	 * 			"getAccessor" for each thread you will be using it on.
+	 * 			
+	 * @note		Accessors contain their own command queue and their commands will only start to get executed once that queue is submitted
+	 * 			to the core thread via "submitAccessors" method.
+	 * 			
+	 *			Synced accessor commands are sent after all non-synced accessor commands are sent.
+	 */
 	BS_CORE_EXPORT SyncedCoreAccessor& getSyncedAccessor();
 	BS_CORE_EXPORT SyncedCoreAccessor& getSyncedAccessor();
 
 
 	/**
 	/**
@@ -69,24 +69,24 @@ public:
 	BS_CORE_EXPORT void submitAccessors(bool blockUntilComplete = false);
 	BS_CORE_EXPORT void submitAccessors(bool blockUntilComplete = false);
 
 
 	/**
 	/**
-		* @brief	Queues a new command that will be added to the global command queue. You are allowed to call this from any thread,
-		* 			however be aware that it involves possibly slow synchronization primitives, so limit your usage.
-		* 			
-		* @param	blockUntilComplete If true the thread will be blocked until the command executes. Be aware that there may be many commands queued before it
-		* 							   and they all need to be executed in order before the current command is reached, which might take a long time.
-		* 	
-		* @see		CommandQueue::queueReturn
-		*/
+	 * @brief	Queues a new command that will be added to the global command queue. You are allowed to call this from any thread,
+	 * 			however be aware that it involves possibly slow synchronization primitives, so limit your usage.
+	 * 			
+	 * @param	blockUntilComplete If true the thread will be blocked until the command executes. Be aware that there may be many commands queued before it
+	 * 							   and they all need to be executed in order before the current command is reached, which might take a long time.
+	 * 	
+	 * @see		CommandQueue::queueReturn
+	 */
 	BS_CORE_EXPORT AsyncOp queueReturnCommand(std::function<void(AsyncOp&)> commandCallback, bool blockUntilComplete = false);
 	BS_CORE_EXPORT AsyncOp queueReturnCommand(std::function<void(AsyncOp&)> commandCallback, bool blockUntilComplete = false);
 
 
 	/**
 	/**
-	* @brief	Queues a new command that will be added to the global command queue.You are allowed to call this from any thread,
-		* 			however be aware that it involves possibly slow synchronization primitives, so limit your usage.
-		* 	
-		* @param	blockUntilComplete If true the thread will be blocked until the command executes. Be aware that there may be many commands queued before it
-		* 							   and they all need to be executed in order before the current command is reached, which might take a long time.
-		* @see		CommandQueue::queue
-		*/
+	 * @brief	Queues a new command that will be added to the global command queue.You are allowed to call this from any thread,
+	 * 			however be aware that it involves possibly slow synchronization primitives, so limit your usage.
+	 * 	
+	 * @param	blockUntilComplete If true the thread will be blocked until the command executes. Be aware that there may be many commands queued before it
+	 * 							   and they all need to be executed in order before the current command is reached, which might take a long time.
+	 * @see		CommandQueue::queue
+	 */
 	BS_CORE_EXPORT void queueCommand(std::function<void()> commandCallback, bool blockUntilComplete = false);
 	BS_CORE_EXPORT void queueCommand(std::function<void()> commandCallback, bool blockUntilComplete = false);
 
 
 	/**
 	/**

+ 3 - 0
BansheeEditor/Include/BsGUIIntField.h

@@ -16,6 +16,7 @@ namespace BansheeEngine
 
 
 		INT32 getValue() const { return mValue; }
 		INT32 getValue() const { return mValue; }
 		void setValue(INT32 value);
 		void setValue(INT32 value);
+		void setRange(INT32 min, INT32 max);
 
 
 		bool hasInputFocus() const { return mHasInputFocus; }
 		bool hasInputFocus() const { return mHasInputFocus; }
 
 
@@ -40,6 +41,8 @@ namespace BansheeEngine
 		GUIInputBox* mInputBox;
 		GUIInputBox* mInputBox;
 		INT32 mValue;
 		INT32 mValue;
 		INT32 mLastDragPos;
 		INT32 mLastDragPos;
+		INT32 mMinValue;
+		INT32 mMaxValue;
 		bool mIsDragging;
 		bool mIsDragging;
 		bool mIsDragCursorSet;
 		bool mIsDragCursorSet;
 		bool mHasInputFocus;
 		bool mHasInputFocus;

+ 10 - 1
BansheeEditor/Source/BsGUIIntField.cpp

@@ -23,7 +23,8 @@ namespace BansheeEngine
 	GUIIntField::GUIIntField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
 	GUIIntField::GUIIntField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
 		const String& style, const GUILayoutOptions& layoutOptions, bool withLabel)
 		const String& style, const GUILayoutOptions& layoutOptions, bool withLabel)
 		:TGUIField(dummy, labelContent, labelWidth, style, layoutOptions, withLabel), mInputBox(nullptr), mIsDragging(false),
 		:TGUIField(dummy, labelContent, labelWidth, style, layoutOptions, withLabel), mInputBox(nullptr), mIsDragging(false),
-		mLastDragPos(0), mIsDragCursorSet(false), mHasInputFocus(false)
+		mLastDragPos(0), mIsDragCursorSet(false), mHasInputFocus(false), mMinValue(std::numeric_limits<INT32>::lowest()), 
+		mMaxValue(std::numeric_limits<INT32>::max())
 	{
 	{
 		mInputBox = GUIInputBox::create(false, GUIOptions(GUIOption::flexibleWidth()), getSubStyleName(getInputStyleType()));
 		mInputBox = GUIInputBox::create(false, GUIOptions(GUIOption::flexibleWidth()), getSubStyleName(getInputStyleType()));
 		mInputBox->setFilter(&GUIIntField::intFilter);
 		mInputBox->setFilter(&GUIIntField::intFilter);
@@ -149,10 +150,18 @@ namespace BansheeEngine
 
 
 	void GUIIntField::setValue(INT32 value)
 	void GUIIntField::setValue(INT32 value)
 	{
 	{
+		value = Math::clamp(value, mMinValue, mMaxValue);
+
 		mValue = value;
 		mValue = value;
 		mInputBox->setText(toWString(value));
 		mInputBox->setText(toWString(value));
 	}
 	}
 
 
+	void GUIIntField::setRange(INT32 min, INT32 max)
+	{
+		mMinValue = min;
+		mMaxValue = max;
+	}
+
 	void GUIIntField::updateClippedBounds()
 	void GUIIntField::updateClippedBounds()
 	{
 	{
 		Vector2I offset = _getOffset();
 		Vector2I offset = _getOffset();

+ 6 - 3
Inspector.txt

@@ -18,10 +18,10 @@ ARRAY TODO:
  - Add Delete/Clone/MoveUp/MoveDown buttons
  - Add Delete/Clone/MoveUp/MoveDown buttons
  - Ensure that case when array is null is handled properly. Will likely need a [Create] button
  - Ensure that case when array is null is handled properly. Will likely need a [Create] button
  - Need a GUIFoldout that doesn't have BG and is just a single button.
  - Need a GUIFoldout that doesn't have BG and is just a single button.
+ - Add IntField that has min/max limits so it cannot go below 0 for array size
 
 
-Inspectable Refresh/Refactor TODO:
-Parent layout element destruction should be automatic
-Child Inspectable element destruction should also probably be automatic
+Need code for cloning an array element (or pretty much any element)
+Hook up array buttons
 
 
 TODO:
 TODO:
  - Hook up int field set/get callbacks
  - Hook up int field set/get callbacks
@@ -88,6 +88,9 @@ KEEP IN MIND:
 
 
 ----------------------------------------------
 ----------------------------------------------
 
 
+Various trivial fixes:
+ - Add icons to array clone/delete/up/down buttons
+
 LATER:
 LATER:
  - Add support for list, dictionary and multi-rank array types
  - Add support for list, dictionary and multi-rank array types
  - Add tabbing between fields
  - Add tabbing between fields

+ 8 - 0
MBansheeEditor/GUI/GUIIntField.cs

@@ -39,6 +39,11 @@ namespace BansheeEditor
             return value;
             return value;
         }
         }
 
 
+        public void SetRange(int min, int max)
+        {
+            Internal_SetRange(mCachedPtr, min, max);
+        }
+
         private void DoOnChanged(int newValue)
         private void DoOnChanged(int newValue)
         {
         {
             if (OnChanged != null)
             if (OnChanged != null)
@@ -57,5 +62,8 @@ namespace BansheeEditor
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_HasInputFocus(IntPtr nativeInstance, out bool value);
         private static extern void Internal_HasInputFocus(IntPtr nativeInstance, out bool value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetRange(IntPtr nativeInstance, int min, int max);
     }
     }
 }
 }

+ 147 - 5
MBansheeEditor/Inspector/InspectableArray.cs

@@ -9,14 +9,56 @@ namespace BansheeEditor
 {
 {
     public class InspectableArray : InspectableObjectBase
     public class InspectableArray : InspectableObjectBase
     {
     {
+        private class EntryRow
+        {
+            public GUILayoutX rowLayout;
+            public GUILayoutY contentLayout;
+            public GUIButton cloneBtn;
+            public GUIButton deleteBtn;
+            public GUIButton moveUpBtn;
+            public GUIButton moveDownBtn;
+
+            public EntryRow(GUILayout parentLayout)
+            {
+                rowLayout = parentLayout.AddLayoutX();
+                contentLayout = rowLayout.AddLayoutY();
+                cloneBtn = new GUIButton("C");
+                deleteBtn = new GUIButton("X");
+                moveUpBtn = new GUIButton("Up");
+                moveDownBtn = new GUIButton("Down");
+
+                rowLayout.AddElement(cloneBtn);
+                rowLayout.AddElement(deleteBtn);
+                rowLayout.AddElement(moveUpBtn);
+                rowLayout.AddElement(moveDownBtn);
+            }
+
+            public void Destroy()
+            {
+                rowLayout.Destroy();
+                contentLayout.Destroy();
+                cloneBtn.Destroy();
+                deleteBtn.Destroy();
+                moveUpBtn.Destroy();
+                moveDownBtn.Destroy();
+            }
+        }
+
         private const int IndentAmount = 15;
         private const int IndentAmount = 15;
 
 
         private object oldPropertyValue; // TODO - This will unnecessarily hold references to the object
         private object oldPropertyValue; // TODO - This will unnecessarily hold references to the object
         private int numArrayElements;
         private int numArrayElements;
 
 
         private GUILabel guiLabel;
         private GUILabel guiLabel;
+        private GUIIntField guiSizeField;
+        private GUIButton guiResizeBtn;
+
+        private GUILayout guiTitleLayout;
         private GUILayout guiChildLayout;
         private GUILayout guiChildLayout;
         private GUILayoutY guiContentLayout;
         private GUILayoutY guiContentLayout;
+
+        private List<EntryRow> rows = new List<EntryRow>();
+
         private bool isInitialized;
         private bool isInitialized;
 
 
         public InspectableArray(string title, InspectableFieldLayout layout, SerializableProperty property)
         public InspectableArray(string title, InspectableFieldLayout layout, SerializableProperty property)
@@ -31,7 +73,15 @@ namespace BansheeEditor
                 return;
                 return;
 
 
             guiLabel = new GUILabel(title); // TODO - Add foldout and hook up its callbacks
             guiLabel = new GUILabel(title); // TODO - Add foldout and hook up its callbacks
-            layout.AddElement(layoutIndex, guiLabel);
+            guiSizeField = new GUIIntField();
+            guiSizeField.SetRange(0, int.MaxValue);
+            guiResizeBtn = new GUIButton("Resize");
+            guiResizeBtn.OnClick += OnResizeButtonClicked;
+
+            guiTitleLayout = layout.AddLayoutX(layoutIndex);
+            guiTitleLayout.AddElement(guiLabel);
+            guiTitleLayout.AddElement(guiSizeField);
+            guiTitleLayout.AddElement(guiResizeBtn);
 
 
             guiChildLayout = layout.AddLayoutX(layoutIndex);
             guiChildLayout = layout.AddLayoutX(layoutIndex);
 
 
@@ -68,17 +118,109 @@ namespace BansheeEditor
             if (!isInitialized)
             if (!isInitialized)
                 Initialize(layoutIndex);
                 Initialize(layoutIndex);
 
 
+            foreach (var row in rows)
+                row.Destroy();
+
+            rows.Clear();
+
             SerializableArray array = property.GetArray();
             SerializableArray array = property.GetArray();
 
 
-            int childLayoutIndex = 0;
             numArrayElements = array.GetLength();
             numArrayElements = array.GetLength();
             for (int i = 0; i < numArrayElements; i++)
             for (int i = 0; i < numArrayElements; i++)
             {
             {
-                InspectableObjectBase childObj = CreateDefaultInspectable(i + ".", new InspectableFieldLayout(guiContentLayout), array.GetProperty(i));
+                EntryRow newRow = new EntryRow(guiContentLayout);
+                rows.Add(newRow);
+
+                InspectableObjectBase childObj = CreateDefaultInspectable(i + ".", new InspectableFieldLayout(newRow.contentLayout), array.GetProperty(i));
                 AddChild(childObj);
                 AddChild(childObj);
 
 
-                childObj.Refresh(childLayoutIndex);
-                childLayoutIndex += childObj.GetNumLayoutElements();
+                childObj.Refresh(0);
+            }
+        }
+
+        private void OnResizeButtonClicked()
+        {
+            int size = guiSizeField.Value; // TODO - Support multi-rank arrays
+
+            Array newArray = property.CreateArrayInstance(new int[] {size});
+            SerializableArray array = property.GetArray();
+
+            int maxSize = MathEx.Min(size, array.GetLength());
+
+            for (int i = 0; i < maxSize; i++)
+                newArray.SetValue(array.GetProperty(i).GetValue<object>(), i);
+
+            property.SetValue(newArray);
+        }
+
+        private void OnDeleteButtonClicked(int index)
+        {
+            SerializableArray array = property.GetArray();
+
+            int size = MathEx.Max(0, array.GetLength() - 1);
+            Array newArray = property.CreateArrayInstance(new int[] { size });
+
+            int destIdx = 0;
+            for (int i = 0; i < array.GetLength(); i++)
+            {
+                if (i == index)
+                    continue;
+
+                newArray.SetValue(array.GetProperty(i).GetValue<object>(), destIdx);
+                destIdx++;
+            }
+
+            property.SetValue(newArray);
+        }
+
+        private void OnCloneButtonClicked(int index)
+        {
+            SerializableArray array = property.GetArray();
+
+            int size = array.GetLength() + 1;
+            Array newArray = property.CreateArrayInstance(new int[] { size });
+
+            object clonedEntry = null;
+            for (int i = 0; i < array.GetLength(); i++)
+            {
+                object value = array.GetProperty(i).GetValue<object>();
+
+                newArray.SetValue(value, i);
+
+                if (i == index)
+                {
+                    // TODO - Clone
+                }
+            }
+
+            newArray.SetValue(clonedEntry, size - 1);
+
+            property.SetValue(newArray);
+        }
+
+        private void OnMoveUpButtonClicked(int index)
+        {
+            SerializableArray array = property.GetArray();
+
+            if ((index - 1) >= 0)
+            {
+                object previousEntry = array.GetProperty(index - 1).GetValue<object>();
+
+                array.GetProperty(index - 1).SetValue(array.GetProperty(index).GetValue<object>());
+                array.GetProperty(index).SetValue(previousEntry);
+            }
+        }
+
+        private void OnMoveDownButtonClicked(int index)
+        {
+            SerializableArray array = property.GetArray();
+
+            if ((index + 1) < array.GetLength())
+            {
+                object nextEntry = array.GetProperty(index + 1).GetValue<object>();
+
+                array.GetProperty(index + 1).SetValue(array.GetProperty(index).GetValue<object>());
+                array.GetProperty(index).SetValue(nextEntry);
             }
             }
         }
         }
     }
     }

+ 33 - 0
MBansheeEngine/SerializableProperty.cs

@@ -59,6 +59,14 @@ namespace BansheeEngine
             return (T)getter();
             return (T)getter();
         }
         }
 
 
+        public T GetValueCopy<T>()
+        {
+            if (!typeof(T).IsAssignableFrom(internalType))
+                throw new Exception("Attempted to retrieve a serializable value using an invalid type. Provided type: " + typeof(T) + ". Needed type: " + internalType);
+
+            return (T)Internal_CloneManagedInstance(mCachedPtr, getter());
+        }
+
         public void SetValue<T>(T value)
         public void SetValue<T>(T value)
         {
         {
             if (!typeof(T).IsAssignableFrom(internalType))
             if (!typeof(T).IsAssignableFrom(internalType))
@@ -83,12 +91,37 @@ namespace BansheeEngine
             return Internal_CreateArray(mCachedPtr, GetValue<Array>());
             return Internal_CreateArray(mCachedPtr, GetValue<Array>());
         }
         }
 
 
+        public T CreateObjectInstance<T>()
+        {
+            if (type != FieldType.Object)
+                throw new Exception("Attempting to retrieve object information from a field that doesn't contain an object.");
+
+            return (T) Internal_CreateMangedObjectInstance(mCachedPtr);
+        }
+
+        public Array CreateArrayInstance(int[] lengths)
+        {
+            if (type != FieldType.Array)
+                throw new Exception("Attempting to retrieve array information from a field that doesn't contain an array.");
+
+            return Internal_CreateManagedArrayInstance(mCachedPtr, lengths);
+        }
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern SerializableObject Internal_CreateObject(IntPtr nativeInstance, object instance);
         private static extern SerializableObject Internal_CreateObject(IntPtr nativeInstance, object instance);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern SerializableArray Internal_CreateArray(IntPtr nativeInstance, Array instance);
         private static extern SerializableArray Internal_CreateArray(IntPtr nativeInstance, Array instance);
 
 
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern object Internal_CreateMangedObjectInstance(IntPtr nativeInstance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern Array Internal_CreateManagedArrayInstance(IntPtr nativeInstance, int[] lengths);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern object Internal_CloneManagedInstance(IntPtr nativeInstance, object original);
+
         public static FieldType DetermineFieldType(Type internalType)
         public static FieldType DetermineFieldType(Type internalType)
         {
         {
             if (!internalType.IsArray)
             if (!internalType.IsArray)

+ 1 - 0
SBansheeEditor/Include/BsScriptGUIIntField.h

@@ -17,6 +17,7 @@ namespace BansheeEngine
 		static void internal_getValue(ScriptGUIIntField* nativeInstance, INT32* output);
 		static void internal_getValue(ScriptGUIIntField* nativeInstance, INT32* output);
 		static void internal_setValue(ScriptGUIIntField* nativeInstance, INT32 value);
 		static void internal_setValue(ScriptGUIIntField* nativeInstance, INT32 value);
 		static void internal_hasInputFocus(ScriptGUIIntField* nativeInstance, bool* output);
 		static void internal_hasInputFocus(ScriptGUIIntField* nativeInstance, bool* output);
+		static void internal_setRange(ScriptGUIIntField* nativeInstance, INT32 min, INT32 max);
 
 
 		static void onChanged(MonoObject* instance, INT32 newValue);
 		static void onChanged(MonoObject* instance, INT32 newValue);
 
 

+ 8 - 0
SBansheeEditor/Source/BsScriptGUIIntField.cpp

@@ -34,6 +34,7 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_GetValue", &ScriptGUIIntField::internal_getValue);
 		metaData.scriptClass->addInternalCall("Internal_GetValue", &ScriptGUIIntField::internal_getValue);
 		metaData.scriptClass->addInternalCall("Internal_SetValue", &ScriptGUIIntField::internal_setValue);
 		metaData.scriptClass->addInternalCall("Internal_SetValue", &ScriptGUIIntField::internal_setValue);
 		metaData.scriptClass->addInternalCall("Internal_HasInputFocus", &ScriptGUIIntField::internal_hasInputFocus);
 		metaData.scriptClass->addInternalCall("Internal_HasInputFocus", &ScriptGUIIntField::internal_hasInputFocus);
+		metaData.scriptClass->addInternalCall("Internal_SetRange", &ScriptGUIIntField::internal_setRange);
 
 
 		onChangedThunk = (OnChangedThunkDef)metaData.scriptClass->getMethod("DoOnChanged", 1).getThunk();
 		onChangedThunk = (OnChangedThunkDef)metaData.scriptClass->getMethod("DoOnChanged", 1).getThunk();
 	}
 	}
@@ -86,6 +87,13 @@ namespace BansheeEngine
 		*output = intField->hasInputFocus();
 		*output = intField->hasInputFocus();
 	}
 	}
 
 
+	void ScriptGUIIntField::internal_setRange(ScriptGUIIntField* nativeInstance, INT32 min, INT32 max)
+	{
+		GUIIntField* intField = static_cast<GUIIntField*>(nativeInstance->getGUIElement());
+
+		intField->setRange(min, max);
+	}
+
 	void ScriptGUIIntField::onChanged(MonoObject* instance, INT32 newValue)
 	void ScriptGUIIntField::onChanged(MonoObject* instance, INT32 newValue)
 	{
 	{
 		MonoException* exception = nullptr;
 		MonoException* exception = nullptr;

+ 1 - 1
SBansheeEngine/Include/BsManagedComponentRTTI.h

@@ -55,7 +55,7 @@ namespace BansheeEngine
 		{
 		{
 			ManagedComponent* mc = static_cast<ManagedComponent*>(obj);
 			ManagedComponent* mc = static_cast<ManagedComponent*>(obj);
 
 
-			mc->mRTTIData = ManagedSerializableObject::create(mc->getManagedInstance());
+			mc->mRTTIData = ManagedSerializableObject::createFromExisting(mc->getManagedInstance());
 		}
 		}
 
 
 		virtual void onDeserializationStarted(IReflectable* obj)
 		virtual void onDeserializationStarted(IReflectable* obj)

+ 1 - 1
SBansheeEngine/Include/BsManagedResourceRTTI.h

@@ -32,7 +32,7 @@ namespace BansheeEngine
 		{
 		{
 			ManagedResource* mc = static_cast<ManagedResource*>(obj);
 			ManagedResource* mc = static_cast<ManagedResource*>(obj);
 
 
-			mc->mRTTIData = ManagedSerializableObject::create(mc->getManagedInstance());
+			mc->mRTTIData = ManagedSerializableObject::createFromExisting(mc->getManagedInstance());
 		}
 		}
 
 
 		virtual void onDeserializationEnded(IReflectable* obj)
 		virtual void onDeserializationEnded(IReflectable* obj)

+ 4 - 2
SBansheeEngine/Include/BsManagedSerializableArray.h

@@ -17,7 +17,9 @@ namespace BansheeEngine
 
 
 		MonoObject* getManagedInstance() const { return mManagedInstance; }
 		MonoObject* getManagedInstance() const { return mManagedInstance; }
 
 
-		static ManagedSerializableArrayPtr create(MonoObject* managedInstance, const ManagedSerializableTypeInfoArrayPtr& typeInfo);
+		static ManagedSerializableArrayPtr createFromExisting(MonoObject* managedInstance, const ManagedSerializableTypeInfoArrayPtr& typeInfo);
+		static ManagedSerializableArrayPtr createFromNew(const ManagedSerializableTypeInfoArrayPtr& typeInfo, const Vector<UINT32>& sizes);
+		static MonoObject* createManagedInstance(const ManagedSerializableTypeInfoArrayPtr& typeInfo, const Vector<UINT32>& sizes);
 
 
 	protected:
 	protected:
 		MonoObject* mManagedInstance;
 		MonoObject* mManagedInstance;
@@ -53,7 +55,7 @@ namespace BansheeEngine
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
 		/************************************************************************/
 		
 		
-		static ManagedSerializableArrayPtr createEmpty();
+		static ManagedSerializableArrayPtr createFromNew();
 
 
 	public:
 	public:
 		friend class ManagedSerializableArrayRTTI;
 		friend class ManagedSerializableArrayRTTI;

+ 1 - 1
SBansheeEngine/Include/BsManagedSerializableArrayRTTI.h

@@ -115,7 +115,7 @@ namespace BansheeEngine
 
 
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		{
 		{
-			return ManagedSerializableArray::createEmpty();
+			return ManagedSerializableArray::createFromNew();
 		}
 		}
 	};
 	};
 }
 }

+ 3 - 1
SBansheeEngine/Include/BsManagedSerializableDictionary.h

@@ -33,7 +33,9 @@ namespace BansheeEngine
 
 
 		MonoObject* getManagedInstance() const { return mManagedInstance; }
 		MonoObject* getManagedInstance() const { return mManagedInstance; }
 
 
-		static ManagedSerializableDictionaryPtr create(MonoObject* managedInstance, const ManagedSerializableTypeInfoDictionaryPtr& typeInfo);
+		static ManagedSerializableDictionaryPtr createFromExisting(MonoObject* managedInstance, const ManagedSerializableTypeInfoDictionaryPtr& typeInfo);
+		static ManagedSerializableDictionaryPtr createFromNew(const ManagedSerializableTypeInfoDictionaryPtr& typeInfo);
+		static MonoObject* createManagedInstance(const ManagedSerializableTypeInfoDictionaryPtr& typeInfo);
 
 
 	protected:
 	protected:
 		MonoObject* mManagedInstance;
 		MonoObject* mManagedInstance;

+ 20 - 0
SBansheeEngine/Include/BsManagedSerializableField.h

@@ -29,6 +29,7 @@ namespace BansheeEngine
 	public:
 	public:
 		static ManagedSerializableFieldDataPtr create(const ManagedSerializableTypeInfoPtr& typeInfo, MonoObject* value);
 		static ManagedSerializableFieldDataPtr create(const ManagedSerializableTypeInfoPtr& typeInfo, MonoObject* value);
 		virtual void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) = 0;
 		virtual void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) = 0;
+		virtual MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) = 0;
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -64,6 +65,7 @@ namespace BansheeEngine
 		bool value;
 		bool value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -81,6 +83,7 @@ namespace BansheeEngine
 		wchar_t value;
 		wchar_t value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -98,6 +101,7 @@ namespace BansheeEngine
 		INT8 value;
 		INT8 value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -115,6 +119,7 @@ namespace BansheeEngine
 		UINT8 value;
 		UINT8 value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -132,6 +137,7 @@ namespace BansheeEngine
 		INT16 value;
 		INT16 value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -149,6 +155,7 @@ namespace BansheeEngine
 		UINT16 value;
 		UINT16 value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -166,6 +173,7 @@ namespace BansheeEngine
 		INT32 value;
 		INT32 value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -183,6 +191,7 @@ namespace BansheeEngine
 		UINT32 value;
 		UINT32 value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -200,6 +209,7 @@ namespace BansheeEngine
 		INT64 value;
 		INT64 value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -217,6 +227,7 @@ namespace BansheeEngine
 		UINT64 value;
 		UINT64 value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -234,6 +245,7 @@ namespace BansheeEngine
 		float value;
 		float value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -252,6 +264,7 @@ namespace BansheeEngine
 		double value;
 		double value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -269,6 +282,7 @@ namespace BansheeEngine
 		WString value;
 		WString value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -286,6 +300,7 @@ namespace BansheeEngine
 		HResource value;
 		HResource value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -303,6 +318,7 @@ namespace BansheeEngine
 		HGameObject value;
 		HGameObject value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -320,6 +336,7 @@ namespace BansheeEngine
 		ManagedSerializableObjectPtr value;
 		ManagedSerializableObjectPtr value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -337,6 +354,7 @@ namespace BansheeEngine
 		ManagedSerializableArrayPtr value;
 		ManagedSerializableArrayPtr value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -354,6 +372,7 @@ namespace BansheeEngine
 		ManagedSerializableListPtr value;
 		ManagedSerializableListPtr value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -371,6 +390,7 @@ namespace BansheeEngine
 		ManagedSerializableDictionaryPtr value;
 		ManagedSerializableDictionaryPtr value;
 
 
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo);
+		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/

+ 3 - 1
SBansheeEngine/Include/BsManagedSerializableList.h

@@ -17,7 +17,9 @@ namespace BansheeEngine
 
 
 		MonoObject* getManagedInstance() const { return mManagedInstance; }
 		MonoObject* getManagedInstance() const { return mManagedInstance; }
 
 
-		static ManagedSerializableListPtr create(MonoObject* managedInstance, const ManagedSerializableTypeInfoListPtr& typeInfo);
+		static ManagedSerializableListPtr createFromExisting(MonoObject* managedInstance, const ManagedSerializableTypeInfoListPtr& typeInfo);
+		static ManagedSerializableListPtr createFromNew(const ManagedSerializableTypeInfoListPtr& typeInfo, UINT32 size);
+		static MonoObject* createManagedInstance(const ManagedSerializableTypeInfoListPtr& typeInfo, UINT32 size);
 
 
 	protected:
 	protected:
 		MonoObject* mManagedInstance;
 		MonoObject* mManagedInstance;

+ 3 - 1
SBansheeEngine/Include/BsManagedSerializableObject.h

@@ -18,7 +18,9 @@ namespace BansheeEngine
 		MonoObject* getManagedInstance() const { return mManagedInstance; }
 		MonoObject* getManagedInstance() const { return mManagedInstance; }
 		ManagedSerializableObjectInfoPtr getObjectInfo() const { return mObjInfo; }
 		ManagedSerializableObjectInfoPtr getObjectInfo() const { return mObjInfo; }
 
 
-		static ManagedSerializableObjectPtr create(MonoObject* managedInstance);
+		static ManagedSerializableObjectPtr createFromExisting(MonoObject* managedInstance);
+		static ManagedSerializableObjectPtr createFromNew(const ManagedSerializableTypeInfoObjectPtr& type);
+		static MonoObject* createManagedInstance(const ManagedSerializableTypeInfoObjectPtr& type);
 
 
 	protected:
 	protected:
 		ManagedSerializableObjectInfoPtr mObjInfo;
 		ManagedSerializableObjectInfoPtr mObjInfo;

+ 1 - 1
SBansheeEngine/Include/BsManagedSerializableObjectInfo.h

@@ -181,7 +181,7 @@ namespace BansheeEngine
 	public:
 	public:
 		ManagedSerializableObjectInfo();
 		ManagedSerializableObjectInfo();
 
 
-		ScriptSerializableTypeInfoObjectPtr mTypeInfo;
+		ManagedSerializableTypeInfoObjectPtr mTypeInfo;
 		UINT32 mTypeId;
 		UINT32 mTypeId;
 
 
 		MonoClass* mMonoClass;
 		MonoClass* mMonoClass;

+ 2 - 2
SBansheeEngine/Include/BsManagedSerializableObjectInfoRTTI.h

@@ -67,12 +67,12 @@ namespace BansheeEngine
 	class BS_SCR_BE_EXPORT ManagedSerializableObjectInfoRTTI : public RTTIType<ManagedSerializableObjectInfo, IReflectable, ManagedSerializableObjectInfoRTTI>
 	class BS_SCR_BE_EXPORT ManagedSerializableObjectInfoRTTI : public RTTIType<ManagedSerializableObjectInfo, IReflectable, ManagedSerializableObjectInfoRTTI>
 	{
 	{
 	private:
 	private:
-		ScriptSerializableTypeInfoObjectPtr getTypeInfo(ManagedSerializableObjectInfo* obj)
+		ManagedSerializableTypeInfoObjectPtr getTypeInfo(ManagedSerializableObjectInfo* obj)
 		{
 		{
 			return obj->mTypeInfo;
 			return obj->mTypeInfo;
 		}
 		}
 
 
-		void setTypeInfo(ManagedSerializableObjectInfo* obj, ScriptSerializableTypeInfoObjectPtr val)
+		void setTypeInfo(ManagedSerializableObjectInfo* obj, ManagedSerializableTypeInfoObjectPtr val)
 		{
 		{
 			obj->mTypeInfo = val;
 			obj->mTypeInfo = val;
 		}
 		}

+ 1 - 1
SBansheeEngine/Include/BsScriptEnginePrerequisites.h

@@ -106,7 +106,7 @@ namespace BansheeEngine
 	typedef std::shared_ptr<ManagedSerializableFieldKey> ManagedSerializableFieldKeyPtr;
 	typedef std::shared_ptr<ManagedSerializableFieldKey> ManagedSerializableFieldKeyPtr;
 	typedef std::shared_ptr<ManagedSerializableFieldDataEntry> ManagedSerializableFieldDataEntryPtr;
 	typedef std::shared_ptr<ManagedSerializableFieldDataEntry> ManagedSerializableFieldDataEntryPtr;
 	typedef std::shared_ptr<ManagedSerializableTypeInfo> ManagedSerializableTypeInfoPtr;
 	typedef std::shared_ptr<ManagedSerializableTypeInfo> ManagedSerializableTypeInfoPtr;
-	typedef std::shared_ptr<ManagedSerializableTypeInfoObject> ScriptSerializableTypeInfoObjectPtr;
+	typedef std::shared_ptr<ManagedSerializableTypeInfoObject> ManagedSerializableTypeInfoObjectPtr;
 	typedef std::shared_ptr<ManagedSerializableObject> ManagedSerializableObjectPtr;
 	typedef std::shared_ptr<ManagedSerializableObject> ManagedSerializableObjectPtr;
 	typedef std::shared_ptr<ManagedSerializableArray> ManagedSerializableArrayPtr;
 	typedef std::shared_ptr<ManagedSerializableArray> ManagedSerializableArrayPtr;
 	typedef std::shared_ptr<ManagedSerializableList> ManagedSerializableListPtr;
 	typedef std::shared_ptr<ManagedSerializableList> ManagedSerializableListPtr;

+ 5 - 0
SBansheeEngine/Include/BsScriptSerializableProperty.h

@@ -18,6 +18,11 @@ namespace BansheeEngine
 		static MonoObject* internal_createObject(ScriptSerializableProperty* nativeInstance, MonoObject* object);
 		static MonoObject* internal_createObject(ScriptSerializableProperty* nativeInstance, MonoObject* object);
 		static MonoObject* internal_createArray(ScriptSerializableProperty* nativeInstance, MonoObject* object);
 		static MonoObject* internal_createArray(ScriptSerializableProperty* nativeInstance, MonoObject* object);
 
 
+		static MonoObject* internal_createManagedObjectInstance(ScriptSerializableProperty* nativeInstance);
+		static MonoObject* internal_createManagedArrayInstance(ScriptSerializableProperty* nativeInstance, MonoArray* sizes);
+
+		static MonoObject* internal_cloneManagedInstance(ScriptSerializableProperty* nativeInstance, MonoObject* original);
+
 		ScriptSerializableProperty(MonoObject* instance, const ManagedSerializableTypeInfoPtr& typeInfo);
 		ScriptSerializableProperty(MonoObject* instance, const ManagedSerializableTypeInfoPtr& typeInfo);
 
 
 		ManagedSerializableTypeInfoPtr mTypeInfo;
 		ManagedSerializableTypeInfoPtr mTypeInfo;

+ 32 - 18
SBansheeEngine/Source/BsManagedSerializableArray.cpp

@@ -27,7 +27,7 @@ namespace BansheeEngine
 			mNumElements[i] = getLength(i);
 			mNumElements[i] = getLength(i);
 	}
 	}
 
 
-	ManagedSerializableArrayPtr ManagedSerializableArray::create(MonoObject* managedInstance, const ManagedSerializableTypeInfoArrayPtr& typeInfo)
+	ManagedSerializableArrayPtr ManagedSerializableArray::createFromExisting(MonoObject* managedInstance, const ManagedSerializableTypeInfoArrayPtr& typeInfo)
 	{
 	{
 		if(managedInstance == nullptr)
 		if(managedInstance == nullptr)
 			return nullptr;
 			return nullptr;
@@ -38,11 +38,38 @@ namespace BansheeEngine
 		return bs_shared_ptr<ManagedSerializableArray>(ConstructPrivately(), typeInfo, managedInstance);
 		return bs_shared_ptr<ManagedSerializableArray>(ConstructPrivately(), typeInfo, managedInstance);
 	}
 	}
 
 
-	ManagedSerializableArrayPtr ManagedSerializableArray::createEmpty()
+	ManagedSerializableArrayPtr ManagedSerializableArray::createFromNew(const ManagedSerializableTypeInfoArrayPtr& typeInfo, const Vector<UINT32>& sizes)
+	{
+		return bs_shared_ptr<ManagedSerializableArray>(ConstructPrivately(), typeInfo, createManagedInstance(typeInfo, sizes));
+	}
+
+	ManagedSerializableArrayPtr ManagedSerializableArray::createFromNew()
 	{
 	{
 		return bs_shared_ptr<ManagedSerializableArray>(ConstructPrivately());
 		return bs_shared_ptr<ManagedSerializableArray>(ConstructPrivately());
 	}
 	}
 
 
+	MonoObject* ManagedSerializableArray::createManagedInstance(const ManagedSerializableTypeInfoArrayPtr& typeInfo, const Vector<UINT32>& sizes)
+	{
+		if (!typeInfo->isTypeLoaded())
+			return nullptr;
+
+		MonoClass* arrayClass = RuntimeScriptObjects::instance().getSystemArrayClass();
+
+		MonoMethod* createInstance = arrayClass->getMethodExact("CreateInstance", "Type,int[]");
+		MonoArray* lengthArray = mono_array_new(MonoManager::instance().getDomain(), mono_get_int32_class(), (UINT32)sizes.size());
+
+		for (UINT32 i = 0; i < (UINT32)sizes.size(); i++)
+		{
+			void* elemAddr = mono_array_addr_with_size(lengthArray, sizeof(int), i);
+			memcpy(elemAddr, &sizes[i], sizeof(int));
+		}
+
+		void* params[2] = {
+			mono_type_get_object(MonoManager::instance().getDomain(), mono_class_get_type(typeInfo->getMonoClass())), lengthArray };
+
+		return createInstance->invoke(nullptr, params);
+	}
+
 	void ManagedSerializableArray::serializeManagedInstance()
 	void ManagedSerializableArray::serializeManagedInstance()
 	{
 	{
 		UINT32 totalNumElements = 1;
 		UINT32 totalNumElements = 1;
@@ -60,24 +87,11 @@ namespace BansheeEngine
 
 
 	void ManagedSerializableArray::deserializeManagedInstance()
 	void ManagedSerializableArray::deserializeManagedInstance()
 	{
 	{
-		if(!mArrayTypeInfo->isTypeLoaded())
-			return;
+		mManagedInstance = createManagedInstance(mArrayTypeInfo, mNumElements);
 
 
-		MonoClass* arrayClass = RuntimeScriptObjects::instance().getSystemArrayClass();
-
-		MonoMethod* createInstance = arrayClass->getMethodExact("CreateInstance", "Type,int[]");
-		MonoArray* lengthArray = mono_array_new(MonoManager::instance().getDomain(), mono_get_int32_class(), (UINT32)mNumElements.size());
-
-		for(UINT32 i = 0; i < (UINT32)mNumElements.size(); i++)
-		{
-			void* elemAddr = mono_array_addr_with_size(lengthArray, sizeof(int), i);
-			memcpy(elemAddr, &mNumElements[i], sizeof(int));
-		}
-
-		void* params[2] = { 
-			mono_type_get_object(MonoManager::instance().getDomain(), mono_class_get_type(mArrayTypeInfo->getMonoClass())), lengthArray };
+		if (mManagedInstance == nullptr)
+			return;
 
 
-		mManagedInstance = createInstance->invoke(nullptr, params);
 		initMonoObjects();
 		initMonoObjects();
 
 
 		UINT32 idx = 0;
 		UINT32 idx = 0;

+ 22 - 4
SBansheeEngine/Source/BsManagedSerializableDictionary.cpp

@@ -52,7 +52,7 @@ namespace BansheeEngine
 
 
 	}
 	}
 
 
-	ManagedSerializableDictionaryPtr ManagedSerializableDictionary::create(MonoObject* managedInstance, const ManagedSerializableTypeInfoDictionaryPtr& typeInfo)
+	ManagedSerializableDictionaryPtr ManagedSerializableDictionary::createFromExisting(MonoObject* managedInstance, const ManagedSerializableTypeInfoDictionaryPtr& typeInfo)
 	{
 	{
 		if(managedInstance == nullptr)
 		if(managedInstance == nullptr)
 			return nullptr;
 			return nullptr;
@@ -68,6 +68,24 @@ namespace BansheeEngine
 		return bs_shared_ptr<ManagedSerializableDictionary>(ConstructPrivately(), typeInfo, managedInstance);
 		return bs_shared_ptr<ManagedSerializableDictionary>(ConstructPrivately(), typeInfo, managedInstance);
 	}
 	}
 
 
+	ManagedSerializableDictionaryPtr ManagedSerializableDictionary::createFromNew(const ManagedSerializableTypeInfoDictionaryPtr& typeInfo)
+	{
+		return bs_shared_ptr<ManagedSerializableDictionary>(ConstructPrivately(), typeInfo, createManagedInstance(typeInfo));
+	}
+
+	MonoObject* ManagedSerializableDictionary::createManagedInstance(const ManagedSerializableTypeInfoDictionaryPtr& typeInfo)
+	{
+		if (!typeInfo->isTypeLoaded())
+			return nullptr;
+
+		::MonoClass* dictionaryMonoClass = typeInfo->getMonoClass();
+		MonoClass* dictionaryClass = MonoManager::instance().findClass(dictionaryMonoClass);
+		if (dictionaryClass == nullptr)
+			return nullptr;
+
+		return dictionaryClass->createInstance();
+	}
+
 	ManagedSerializableDictionaryPtr ManagedSerializableDictionary::createEmpty()
 	ManagedSerializableDictionaryPtr ManagedSerializableDictionary::createEmpty()
 	{
 	{
 		return bs_shared_ptr<ManagedSerializableDictionary>(ConstructPrivately());
 		return bs_shared_ptr<ManagedSerializableDictionary>(ConstructPrivately());
@@ -95,17 +113,17 @@ namespace BansheeEngine
 
 
 	void ManagedSerializableDictionary::deserializeManagedInstance()
 	void ManagedSerializableDictionary::deserializeManagedInstance()
 	{
 	{
-		if(!mDictionaryTypeInfo->isTypeLoaded())
+		mManagedInstance = createManagedInstance(mDictionaryTypeInfo);
+		if (mManagedInstance == nullptr)
 			return;
 			return;
 
 
 		::MonoClass* dictionaryMonoClass = mDictionaryTypeInfo->getMonoClass();
 		::MonoClass* dictionaryMonoClass = mDictionaryTypeInfo->getMonoClass();
 		MonoClass* dictionaryClass = MonoManager::instance().findClass(dictionaryMonoClass);
 		MonoClass* dictionaryClass = MonoManager::instance().findClass(dictionaryMonoClass);
-		if(dictionaryClass == nullptr)
+		if (dictionaryClass == nullptr)
 			return;
 			return;
 
 
 		initMonoObjects(dictionaryClass);
 		initMonoObjects(dictionaryClass);
 
 
-		mManagedInstance = dictionaryClass->createInstance();
 		assert(mKeyEntries.size() == mValueEntries.size());
 		assert(mKeyEntries.size() == mValueEntries.size());
 
 
 		for(UINT32 i = 0; i < (UINT32)mKeyEntries.size(); i++)
 		for(UINT32 i = 0; i < (UINT32)mKeyEntries.size(); i++)

+ 193 - 4
SBansheeEngine/Source/BsManagedSerializableField.cpp

@@ -203,7 +203,7 @@ namespace BansheeEngine
 			auto fieldData = bs_shared_ptr<ManagedSerializableFieldDataObject>();
 			auto fieldData = bs_shared_ptr<ManagedSerializableFieldDataObject>();
 			if(value != nullptr)
 			if(value != nullptr)
 			{
 			{
-				fieldData->value = ManagedSerializableObject::create(value);
+				fieldData->value = ManagedSerializableObject::createFromExisting(value);
 			}
 			}
 
 
 			return fieldData;
 			return fieldData;
@@ -213,7 +213,7 @@ namespace BansheeEngine
 			auto fieldData = bs_shared_ptr<ManagedSerializableFieldDataArray>();
 			auto fieldData = bs_shared_ptr<ManagedSerializableFieldDataArray>();
 			if(value != nullptr)
 			if(value != nullptr)
 			{
 			{
-				fieldData->value = ManagedSerializableArray::create(value, std::static_pointer_cast<ManagedSerializableTypeInfoArray>(typeInfo));
+				fieldData->value = ManagedSerializableArray::createFromExisting(value, std::static_pointer_cast<ManagedSerializableTypeInfoArray>(typeInfo));
 			}
 			}
 
 
 			return fieldData;
 			return fieldData;
@@ -223,7 +223,7 @@ namespace BansheeEngine
 			auto fieldData = bs_shared_ptr<ManagedSerializableFieldDataList>();
 			auto fieldData = bs_shared_ptr<ManagedSerializableFieldDataList>();
 			if(value != nullptr)
 			if(value != nullptr)
 			{
 			{
-				fieldData->value = ManagedSerializableList::create(value, std::static_pointer_cast<ManagedSerializableTypeInfoList>(typeInfo));
+				fieldData->value = ManagedSerializableList::createFromExisting(value, std::static_pointer_cast<ManagedSerializableTypeInfoList>(typeInfo));
 			}
 			}
 
 
 			return fieldData;
 			return fieldData;
@@ -233,7 +233,7 @@ namespace BansheeEngine
 			auto fieldData = bs_shared_ptr<ManagedSerializableFieldDataDictionary>();
 			auto fieldData = bs_shared_ptr<ManagedSerializableFieldDataDictionary>();
 			if(value != nullptr)
 			if(value != nullptr)
 			{
 			{
-				fieldData->value = ManagedSerializableDictionary::create(value, std::static_pointer_cast<ManagedSerializableTypeInfoDictionary>(typeInfo));
+				fieldData->value = ManagedSerializableDictionary::createFromExisting(value, std::static_pointer_cast<ManagedSerializableTypeInfoDictionary>(typeInfo));
 			}
 			}
 
 
 			return fieldData;
 			return fieldData;
@@ -557,6 +557,195 @@ namespace BansheeEngine
 		BS_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
 		BS_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
 	}
 	}
 
 
+	MonoObject* ManagedSerializableFieldDataBool::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		if (typeInfo->getTypeId() == TID_SerializableTypeInfoPrimitive)
+		{
+			auto primitiveTypeInfo = std::static_pointer_cast<ManagedSerializableTypeInfoPrimitive>(typeInfo);
+			if (primitiveTypeInfo->mType == ScriptPrimitiveType::Bool)
+				return mono_value_box(MonoManager::instance().getDomain(), mono_get_boolean_class(), &value);
+		}
+
+		BS_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
+	}
+
+	MonoObject* ManagedSerializableFieldDataChar::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		if (typeInfo->getTypeId() == TID_SerializableTypeInfoPrimitive)
+		{
+			auto primitiveTypeInfo = std::static_pointer_cast<ManagedSerializableTypeInfoPrimitive>(typeInfo);
+			if (primitiveTypeInfo->mType == ScriptPrimitiveType::Char)
+				return mono_value_box(MonoManager::instance().getDomain(), mono_get_char_class(), &value);
+		}
+
+		BS_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
+	}
+
+	MonoObject* ManagedSerializableFieldDataI8::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		if (typeInfo->getTypeId() == TID_SerializableTypeInfoPrimitive)
+		{
+			auto primitiveTypeInfo = std::static_pointer_cast<ManagedSerializableTypeInfoPrimitive>(typeInfo);
+			if (primitiveTypeInfo->mType == ScriptPrimitiveType::I8)
+				return mono_value_box(MonoManager::instance().getDomain(), mono_get_sbyte_class(), &value);
+		}
+
+		BS_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
+	}
+
+	MonoObject* ManagedSerializableFieldDataU8::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		if (typeInfo->getTypeId() == TID_SerializableTypeInfoPrimitive)
+		{
+			auto primitiveTypeInfo = std::static_pointer_cast<ManagedSerializableTypeInfoPrimitive>(typeInfo);
+			if (primitiveTypeInfo->mType == ScriptPrimitiveType::U8)
+				return mono_value_box(MonoManager::instance().getDomain(), mono_get_byte_class(), &value);
+		}
+
+		BS_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
+	}
+
+	MonoObject* ManagedSerializableFieldDataI16::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		if (typeInfo->getTypeId() == TID_SerializableTypeInfoPrimitive)
+		{
+			auto primitiveTypeInfo = std::static_pointer_cast<ManagedSerializableTypeInfoPrimitive>(typeInfo);
+			if (primitiveTypeInfo->mType == ScriptPrimitiveType::I16)
+				return mono_value_box(MonoManager::instance().getDomain(), mono_get_int16_class(), &value);
+		}
+
+		BS_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
+	}
+
+	MonoObject* ManagedSerializableFieldDataU16::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		if (typeInfo->getTypeId() == TID_SerializableTypeInfoPrimitive)
+		{
+			auto primitiveTypeInfo = std::static_pointer_cast<ManagedSerializableTypeInfoPrimitive>(typeInfo);
+			if (primitiveTypeInfo->mType == ScriptPrimitiveType::U16)
+				return mono_value_box(MonoManager::instance().getDomain(), mono_get_uint16_class(), &value);
+		}
+
+		BS_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
+	}
+
+	MonoObject* ManagedSerializableFieldDataI32::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		if (typeInfo->getTypeId() == TID_SerializableTypeInfoPrimitive)
+		{
+			auto primitiveTypeInfo = std::static_pointer_cast<ManagedSerializableTypeInfoPrimitive>(typeInfo);
+			if (primitiveTypeInfo->mType == ScriptPrimitiveType::I32)
+				return mono_value_box(MonoManager::instance().getDomain(), mono_get_int32_class(), &value);
+		}
+
+		BS_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
+	}
+
+	MonoObject* ManagedSerializableFieldDataU32::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		if (typeInfo->getTypeId() == TID_SerializableTypeInfoPrimitive)
+		{
+			auto primitiveTypeInfo = std::static_pointer_cast<ManagedSerializableTypeInfoPrimitive>(typeInfo);
+			if (primitiveTypeInfo->mType == ScriptPrimitiveType::U32)
+				return mono_value_box(MonoManager::instance().getDomain(), mono_get_uint32_class(), &value);
+		}
+
+		BS_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
+	}
+
+	MonoObject* ManagedSerializableFieldDataI64::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		if (typeInfo->getTypeId() == TID_SerializableTypeInfoPrimitive)
+		{
+			auto primitiveTypeInfo = std::static_pointer_cast<ManagedSerializableTypeInfoPrimitive>(typeInfo);
+			if (primitiveTypeInfo->mType == ScriptPrimitiveType::I64)
+				return mono_value_box(MonoManager::instance().getDomain(), mono_get_int64_class(), &value);
+		}
+
+		BS_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
+	}
+
+	MonoObject* ManagedSerializableFieldDataU64::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		if (typeInfo->getTypeId() == TID_SerializableTypeInfoPrimitive)
+		{
+			auto primitiveTypeInfo = std::static_pointer_cast<ManagedSerializableTypeInfoPrimitive>(typeInfo);
+			if (primitiveTypeInfo->mType == ScriptPrimitiveType::U64)
+				return mono_value_box(MonoManager::instance().getDomain(), mono_get_uint64_class(), &value);
+		}
+
+		BS_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
+	}
+
+	MonoObject* ManagedSerializableFieldDataFloat::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		if (typeInfo->getTypeId() == TID_SerializableTypeInfoPrimitive)
+		{
+			auto primitiveTypeInfo = std::static_pointer_cast<ManagedSerializableTypeInfoPrimitive>(typeInfo);
+			if (primitiveTypeInfo->mType == ScriptPrimitiveType::Float)
+				return mono_value_box(MonoManager::instance().getDomain(), mono_get_single_class(), &value);
+		}
+
+		BS_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
+	}
+
+	MonoObject* ManagedSerializableFieldDataDouble::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		if (typeInfo->getTypeId() == TID_SerializableTypeInfoPrimitive)
+		{
+			auto primitiveTypeInfo = std::static_pointer_cast<ManagedSerializableTypeInfoPrimitive>(typeInfo);
+			if (primitiveTypeInfo->mType == ScriptPrimitiveType::Double)
+				return mono_value_box(MonoManager::instance().getDomain(), mono_get_double_class(), &value);
+		}
+
+		BS_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
+	}
+
+	MonoObject* ManagedSerializableFieldDataString::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		return (MonoObject*)getValue(typeInfo);
+	}
+
+	MonoObject* ManagedSerializableFieldDataResourceRef::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		return (MonoObject*)getValue(typeInfo);
+	}
+
+	MonoObject* ManagedSerializableFieldDataGameObjectRef::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		return (MonoObject*)getValue(typeInfo);
+	}
+
+	MonoObject* ManagedSerializableFieldDataObject::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		if (typeInfo->getTypeId() == TID_SerializableTypeInfoObject)
+		{
+			auto objectTypeInfo = std::static_pointer_cast<ManagedSerializableTypeInfoObject>(typeInfo);
+
+			if (value != nullptr)
+				return value->getManagedInstance();
+
+			return nullptr;
+		}
+
+		BS_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
+	}
+
+	MonoObject* ManagedSerializableFieldDataArray::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		return (MonoObject*)getValue(typeInfo);
+	}
+
+	MonoObject* ManagedSerializableFieldDataList::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		return (MonoObject*)getValue(typeInfo);
+	}
+
+	MonoObject* ManagedSerializableFieldDataDictionary::getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo)
+	{
+		return (MonoObject*)getValue(typeInfo);
+	}
+
 	RTTITypeBase* ManagedSerializableFieldKey::getRTTIStatic()
 	RTTITypeBase* ManagedSerializableFieldKey::getRTTIStatic()
 	{
 	{
 		return ManagedSerializableFieldKeyRTTI::instance();
 		return ManagedSerializableFieldKeyRTTI::instance();

+ 23 - 9
SBansheeEngine/Source/BsManagedSerializableList.cpp

@@ -28,7 +28,7 @@ namespace BansheeEngine
 		mNumElements = getLength();
 		mNumElements = getLength();
 	}
 	}
 
 
-	ManagedSerializableListPtr ManagedSerializableList::create(MonoObject* managedInstance, const ManagedSerializableTypeInfoListPtr& typeInfo)
+	ManagedSerializableListPtr ManagedSerializableList::createFromExisting(MonoObject* managedInstance, const ManagedSerializableTypeInfoListPtr& typeInfo)
 	{
 	{
 		if(managedInstance == nullptr)
 		if(managedInstance == nullptr)
 			return nullptr;
 			return nullptr;
@@ -44,6 +44,25 @@ namespace BansheeEngine
 		return bs_shared_ptr<ManagedSerializableList>(ConstructPrivately(), typeInfo, managedInstance);
 		return bs_shared_ptr<ManagedSerializableList>(ConstructPrivately(), typeInfo, managedInstance);
 	}
 	}
 
 
+	ManagedSerializableListPtr ManagedSerializableList::createFromNew(const ManagedSerializableTypeInfoListPtr& typeInfo, UINT32 size)
+	{
+		return bs_shared_ptr<ManagedSerializableList>(ConstructPrivately(), typeInfo, createManagedInstance(typeInfo, size));
+	}
+
+	MonoObject* ManagedSerializableList::createManagedInstance(const ManagedSerializableTypeInfoListPtr& typeInfo, UINT32 size)
+	{
+		if (!typeInfo->isTypeLoaded())
+			return nullptr;
+
+		::MonoClass* listMonoClass = typeInfo->getMonoClass();
+		MonoClass* listClass = MonoManager::instance().findClass(listMonoClass);
+		if (listClass == nullptr)
+			return nullptr;
+
+		void* params[1] = { &size };
+		return listClass->createInstance("int", params);
+	}
+
 	ManagedSerializableListPtr ManagedSerializableList::createEmpty()
 	ManagedSerializableListPtr ManagedSerializableList::createEmpty()
 	{
 	{
 		return bs_shared_ptr<ManagedSerializableList>(ConstructPrivately());
 		return bs_shared_ptr<ManagedSerializableList>(ConstructPrivately());
@@ -60,19 +79,14 @@ namespace BansheeEngine
 
 
 	void ManagedSerializableList::deserializeManagedInstance()
 	void ManagedSerializableList::deserializeManagedInstance()
 	{
 	{
-		if(!mListTypeInfo->isTypeLoaded())
-			return;
+		mManagedInstance = createManagedInstance(mListTypeInfo, mNumElements);
 
 
-		::MonoClass* listMonoClass = mListTypeInfo->getMonoClass();
-		MonoClass* listClass = MonoManager::instance().findClass(listMonoClass);
-		if(listClass == nullptr)
+		if (mManagedInstance == nullptr)
 			return;
 			return;
 
 
+		MonoClass* listClass = MonoManager::instance().findClass(mListTypeInfo->getMonoClass());
 		initMonoObjects(listClass);
 		initMonoObjects(listClass);
 
 
-		void* params[1] = { &mNumElements };
-		mManagedInstance = listClass->createInstance("int", params);
-
 		for(auto& arrayEntry : mListEntries)
 		for(auto& arrayEntry : mListEntries)
 		{
 		{
 			addFieldData(arrayEntry);
 			addFieldData(arrayEntry);

+ 30 - 5
SBansheeEngine/Source/BsManagedSerializableObject.cpp

@@ -19,7 +19,7 @@ namespace BansheeEngine
 
 
 	}
 	}
 
 
-	ManagedSerializableObjectPtr ManagedSerializableObject::create(MonoObject* managedInstance)
+	ManagedSerializableObjectPtr ManagedSerializableObject::createFromExisting(MonoObject* managedInstance)
 	{
 	{
 		if(managedInstance == nullptr)
 		if(managedInstance == nullptr)
 			return nullptr;
 			return nullptr;
@@ -35,6 +35,31 @@ namespace BansheeEngine
 		return bs_shared_ptr<ManagedSerializableObject>(ConstructPrivately(), objInfo, managedInstance);
 		return bs_shared_ptr<ManagedSerializableObject>(ConstructPrivately(), objInfo, managedInstance);
 	}
 	}
 
 
+	ManagedSerializableObjectPtr ManagedSerializableObject::createFromNew(const ManagedSerializableTypeInfoObjectPtr& type)
+	{
+		ManagedSerializableObjectInfoPtr currentObjInfo = nullptr;
+
+		// See if this type even still exists
+		if (!RuntimeScriptObjects::instance().getSerializableObjectInfo(type->mTypeNamespace, type->mTypeName, currentObjInfo))
+			return nullptr;
+
+		return bs_shared_ptr<ManagedSerializableObject>(ConstructPrivately(), currentObjInfo, createManagedInstance(type));
+	}
+
+	MonoObject* ManagedSerializableObject::createManagedInstance(const ManagedSerializableTypeInfoObjectPtr& type)
+	{
+		ManagedSerializableObjectInfoPtr currentObjInfo = nullptr;
+
+		// See if this type even still exists
+		if (!RuntimeScriptObjects::instance().getSerializableObjectInfo(type->mTypeNamespace, type->mTypeName, currentObjInfo))
+			return nullptr;
+
+		if (type->mValueType)
+			return currentObjInfo->mMonoClass->createInstance(false);
+		else
+			return currentObjInfo->mMonoClass->createInstance();
+	}
+
 	ManagedSerializableObjectPtr ManagedSerializableObject::createEmpty()
 	ManagedSerializableObjectPtr ManagedSerializableObject::createEmpty()
 	{
 	{
 		return bs_shared_ptr<ManagedSerializableObject>(ConstructPrivately());
 		return bs_shared_ptr<ManagedSerializableObject>(ConstructPrivately());
@@ -85,10 +110,10 @@ namespace BansheeEngine
 		if(!RuntimeScriptObjects::instance().getSerializableObjectInfo(storedObjInfo->mTypeInfo->mTypeNamespace, storedObjInfo->mTypeInfo->mTypeName, currentObjInfo))
 		if(!RuntimeScriptObjects::instance().getSerializableObjectInfo(storedObjInfo->mTypeInfo->mTypeNamespace, storedObjInfo->mTypeInfo->mTypeName, currentObjInfo))
 			return;
 			return;
 
 
-		if(storedObjInfo->mTypeInfo->mValueType)
-			mManagedInstance = currentObjInfo->mMonoClass->createInstance(false);
-		else
-			mManagedInstance = currentObjInfo->mMonoClass->createInstance();
+		mManagedInstance = createManagedInstance(storedObjInfo->mTypeInfo);
+
+		if (mManagedInstance == nullptr)
+			return;
 
 
 		auto findFieldInfoFromKey = [&] (UINT16 typeId, UINT16 fieldId, ManagedSerializableObjectInfoPtr objInfo, 
 		auto findFieldInfoFromKey = [&] (UINT16 typeId, UINT16 fieldId, ManagedSerializableObjectInfoPtr objInfo, 
 			ManagedSerializableFieldInfoPtr& outFieldInfo, ManagedSerializableObjectInfoPtr &outObjInfo) -> bool
 			ManagedSerializableFieldInfoPtr& outFieldInfo, ManagedSerializableObjectInfoPtr &outObjInfo) -> bool

+ 39 - 0
SBansheeEngine/Source/BsScriptSerializableProperty.cpp

@@ -7,6 +7,10 @@
 #include "BsManagedSerializableObjectInfo.h"
 #include "BsManagedSerializableObjectInfo.h"
 #include "BsScriptSerializableObject.h"
 #include "BsScriptSerializableObject.h"
 #include "BsScriptSerializableArray.h"
 #include "BsScriptSerializableArray.h"
+#include "BsManagedSerializableObject.h"
+#include "BsManagedSerializableArray.h"
+#include "BsManagedSerializableField.h"
+#include "BsMemorySerializer.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -20,6 +24,9 @@ namespace BansheeEngine
 	{
 	{
 		metaData.scriptClass->addInternalCall("Internal_CreateObject", &ScriptSerializableProperty::internal_createObject);
 		metaData.scriptClass->addInternalCall("Internal_CreateObject", &ScriptSerializableProperty::internal_createObject);
 		metaData.scriptClass->addInternalCall("Internal_CreateArray", &ScriptSerializableProperty::internal_createArray);
 		metaData.scriptClass->addInternalCall("Internal_CreateArray", &ScriptSerializableProperty::internal_createArray);
+		metaData.scriptClass->addInternalCall("Internal_CreateManagedObjectInstance", &ScriptSerializableProperty::internal_createManagedObjectInstance);
+		metaData.scriptClass->addInternalCall("Internal_CreateManagedArrayInstance", &ScriptSerializableProperty::internal_createManagedArrayInstance);
+		metaData.scriptClass->addInternalCall("Internal_CloneManagedInstance", &ScriptSerializableProperty::internal_cloneManagedInstance);
 	}
 	}
 
 
 	ScriptSerializableProperty* ScriptSerializableProperty::create(const ManagedSerializableTypeInfoPtr& typeInfo)
 	ScriptSerializableProperty* ScriptSerializableProperty::create(const ManagedSerializableTypeInfoPtr& typeInfo)
@@ -45,4 +52,36 @@ namespace BansheeEngine
 
 
 		return newObject->getManagedInstance();
 		return newObject->getManagedInstance();
 	}
 	}
+
+	MonoObject* ScriptSerializableProperty::internal_createManagedObjectInstance(ScriptSerializableProperty* nativeInstance)
+	{
+		ManagedSerializableTypeInfoObjectPtr objectTypeInfo = std::static_pointer_cast<ManagedSerializableTypeInfoObject>(nativeInstance->mTypeInfo);
+		return ManagedSerializableObject::createManagedInstance(objectTypeInfo);
+	}
+
+	MonoObject* ScriptSerializableProperty::internal_createManagedArrayInstance(ScriptSerializableProperty* nativeInstance, MonoArray* sizes)
+	{
+		Vector<UINT32> nativeSizes;
+		UINT32 arrayLen = (UINT32)mono_array_length(sizes);
+		for (UINT32 i = 0; i < arrayLen; i++)
+			nativeSizes.push_back(mono_array_get(sizes, UINT32, i));
+
+		ManagedSerializableTypeInfoArrayPtr arrayTypeInfo = std::static_pointer_cast<ManagedSerializableTypeInfoArray>(nativeInstance->mTypeInfo);
+		return ManagedSerializableArray::createManagedInstance(arrayTypeInfo, nativeSizes);
+	}
+
+	MonoObject* ScriptSerializableProperty::internal_cloneManagedInstance(ScriptSerializableProperty* nativeInstance, MonoObject* original)
+	{
+		ManagedSerializableFieldDataPtr data = ManagedSerializableFieldData::create(nativeInstance->mTypeInfo, original);
+
+		MemorySerializer ms;
+
+		// Note: This code unnecessarily encodes to binary and decodes from it. I could have added a specialized clone method that does it directly,
+		// but didn't feel the extra code was justified.
+		UINT32 size = 0;
+		UINT8* encodedData = ms.encode(data.get(), size);
+		ManagedSerializableFieldDataPtr clonedData = std::static_pointer_cast<ManagedSerializableFieldData>(ms.decode(encodedData, size));
+
+		return clonedData->getValueBoxed(nativeInstance->mTypeInfo);
+	}
 }
 }