Pārlūkot izejas kodu

I'm experimenting, check in

Marko Pintera 11 gadi atpakaļ
vecāks
revīzija
3ba679cfbd

+ 44 - 0
GameObjectSerialization.txt

@@ -1,6 +1,50 @@
 TODO
  - Ability to break external references as a pre-processing step
 
+ ---------------------------------------
+
+ Serialization:
+ - Starts in ManagedComponent
+ - in onSerializationStarted
+   - I find managed class from RuntimeScriptObject
+   - I query all fields of the class, and its base classes
+   - I add the fields in multiple internal arrays separated by type (int, float, ComponentRef, etc.)
+     - Those arrays are assigned to mRTTIData
+   - Data from those arrays is retrieved using various set/get functions in the RTTI using normal RTTI functionality
+     - Returned field data contains type id, field id and value
+   - I will also store a list of ReflectablePtrs pointing to SerializableObjectInfo describing each used type
+     - I should probably ensure that SerializableObjectInfo RTTI does not include children when serializing to prevent including useless data
+   - What happens when I encounter a SerializableObject?
+     - Instantiate a new instance of SerializableObject class and return a reference to it
+	   - It will have SerializableObjectRTTI which will do the same job ScriptComponentRTTI (this class) does
+	   - They should probably derive from same base class
+ - in onSerializationEnded
+   - I clear mRTTIData
+ - in onDeserializationStarted
+   - I create an empty set of arrays in mRTTIData
+ - in onDeserializationEnded
+   - TODO - Pretty much the exact reverse of above?
+    - But make sure to gracefully handle non-existing types
+
+In RuntimeScriptObjects I need to ensure I return array types when GetSerializableObjectInfo is called
+ - Arrays with different ranks should count as different types?
+ - Also make sure to properly deal with generic parameters
+ScriptSerializableFieldInfoArray doesn't support multi-dimensional arrays (need to figure out how to look those up in Mono)
+Consider removing mNamespace/mTypename from SerializableFieldInfo and adding a special SerializableFieldInfo for SerializableObjects
+
+Dictionaries:
+ - WIll need special SerializableFieldInfo for KeyValuePair
+
+ ---------------------------------------
+
+ Testing:
+ Set up a test case - Initially disable field serialization
+ - In C# create SceneObject("ManagedSO")
+  - Add to it DbgComponent
+ - Call a dummy C++ method (in ScriptSceneObject for example)
+   - C++ method calls clone() on the scene object and creates a new "ManagedSOClone" object and parents it as a child of current SO
+   - C# then retrieves a child and checks if the component is there
+
  ---------------------------------------
  C# component serialization
 

+ 33 - 0
SBansheeEngine/Include/BsManagedSerializationData.h

@@ -0,0 +1,33 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "CmIReflectable.h"
+#include <mono/jit/jit.h>
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ManagedSerializationDataArray : public CM::IReflectable
+	{
+
+	};
+
+	class BS_SCR_BE_EXPORT ManagedSerializationData : public CM::IReflectable
+	{
+	public:
+		static ManagedSerializationDataPtr create(MonoObject* managedInstance);
+
+	protected:
+		ManagedSerializationData(const CM::String& ns, const CM::String& typeName);
+
+		CM::String mNamespace;
+		CM::String mTypename;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class ManagedSerializationDataRTTI;
+		static CM::RTTITypeBase* getRTTIStatic();
+		virtual CM::RTTITypeBase* getRTTI() const;
+	};
+}

+ 56 - 0
SBansheeEngine/Include/BsManagedSerializationDataRTTI.h

@@ -0,0 +1,56 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "CmRTTIType.h"
+#include "BsManagedSerializationData.h"
+#include "CmException.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ManagedSerializationDataRTTI : public CM::RTTIType<ManagedSerializationData, CM::IReflectable, ManagedSerializationDataRTTI>
+	{
+	private:
+		CM::String& getNamespace(ManagedSerializationData* obj)
+		{
+			return obj->mNamespace;
+		}
+
+		void setNamespace(ManagedSerializationData* obj, CM::String& val)
+		{
+			obj->mNamespace = val;
+		}
+
+		CM::String& getTypename(ManagedSerializationData* obj)
+		{
+			return obj->mTypename;
+		}
+
+		void setTypename(ManagedSerializationData* obj, CM::String& val)
+		{
+			obj->mTypename = val;
+		}
+
+	public:
+		ManagedSerializationDataRTTI()
+		{
+			addPlainField("mNamespace", 0, &ManagedSerializationDataRTTI::getNamespace, &ManagedSerializationDataRTTI::setNamespace);
+			addPlainField("mTypename", 1, &ManagedSerializationDataRTTI::getTypename, &ManagedSerializationDataRTTI::setTypename);
+		}
+
+		virtual const CM::String& getRTTIName()
+		{
+			static CM::String name = "ManagedSerializationData";
+			return name;
+		}
+
+		virtual CM::UINT32 getRTTIId()
+		{
+			return TID_ManagedSerializationData;
+		}
+
+		virtual std::shared_ptr<CM::IReflectable> newRTTIObject()
+		{
+			CM_EXCEPT(CM::InvalidStateException, "Cannot instantiate an abstract class.");
+		}
+	};
+}

+ 5 - 139
SBansheeEngine/Include/BsRuntimeScriptObjects.h

@@ -1,158 +1,24 @@
 #pragma once
 
 #include "BsScriptEnginePrerequisites.h"
+#include "BsScriptSerializableObjectInfo.h"
 #include "CmModule.h"
 #include <mono/jit/jit.h>
 
 namespace BansheeEngine
 {
-	enum class ScriptFieldType
-	{
-		Bool,
-		Char,
-		I8,
-		U8,
-		I16,
-		U16,
-		I32,
-		U32,
-		I64,
-		U64,
-		Float,
-		Double,
-		String,
-		SerializableObjectValue,
-		SerializableObjectRef,
-		TextureRef,
-		SpriteTextureRef,
-		SceneObjectRef,
-		ComponentRef,
-		Other
-	};
-
-	enum class ScriptFieldFlags
-	{
-		Serializable = 0x01,
-		Array = 0x02,
-		Inspectable = 0x04
-	};
-
-	struct BS_SCR_BE_EXPORT SerializableFieldInfo
-	{
-		SerializableFieldInfo();
-		~SerializableFieldInfo();
-
-		CM::String mName;
-		CM::String mTypeNamespace;
-		CM::String mTypeName;
-		CM::UINT32 mFieldId;
-
-		ScriptFieldType mType;
-		ScriptFieldFlags mFlags;
-
-		MonoField* mMonoField;
-
-		bool isArray();
-		bool isReferenceType();
-		bool isNull(MonoObject* obj);
-		void setNull(MonoObject* obj);
-
-		CM::UINT32 getNumArrayElements(MonoObject* obj);
-		void setNumArrayElements(MonoObject* obj, CM::UINT32 numElements, bool discardExisting = true);
-
-		void setU8(MonoObject* obj, CM::UINT8 val, CM::UINT32 arrayIdx = 0);
-		CM::UINT8 getU8(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setI8(MonoObject* obj, CM::INT8 val, CM::UINT32 arrayIdx = 0);
-		CM::INT8 getI8(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setU16(MonoObject* obj, CM::UINT16 val, CM::UINT32 arrayIdx = 0);
-		CM::UINT16 getU16(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setI16(MonoObject* obj, CM::INT16 val, CM::UINT32 arrayIdx = 0);
-		CM::INT16 getI16(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setU32(MonoObject* obj, CM::UINT32 val, CM::UINT32 arrayIdx = 0);
-		CM::UINT32 getU32(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setI32(MonoObject* obj, CM::INT32 val, CM::UINT32 arrayIdx = 0);
-		CM::INT32 getI32(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setU64(MonoObject* obj, CM::UINT64 val, CM::UINT32 arrayIdx = 0);
-		CM::UINT64 getU64(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setI64(MonoObject* obj, CM::INT64 val, CM::UINT32 arrayIdx = 0);
-		CM::INT64 getI64(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setBool(MonoObject* obj, bool val, CM::UINT32 arrayIdx = 0);
-		bool getBool(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setChar(MonoObject* obj, wchar_t val, CM::UINT32 arrayIdx = 0);
-		wchar_t getChar(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setFloat(MonoObject* obj, float val, CM::UINT32 arrayIdx = 0);
-		float getFloat(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setDouble(MonoObject* obj, double val, CM::UINT32 arrayIdx = 0);
-		double getDouble(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setString(MonoObject* obj, const CM::WString& val, CM::UINT32 arrayIdx = 0);
-		CM::WString getString(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setTexture(MonoObject* obj, const CM::HTexture& resource, CM::UINT32 arrayIdx = 0);
-		CM::HTexture getTexture(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setSpriteTexture(MonoObject* obj, const HSpriteTexture& resource, CM::UINT32 arrayIdx = 0);
-		HSpriteTexture getSpriteTexture(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setSceneObject(MonoObject* obj, const CM::HSceneObject& sceneObject, CM::UINT32 arrayIdx = 0);
-		CM::HSceneObject getSceneObject(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setComponent(MonoObject* obj, const CM::HComponent& component, CM::UINT32 arrayIdx = 0);
-		CM::HComponent getComponent(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-		void setSerializableObject(MonoObject* obj, const MonoObject* value, CM::UINT32 arrayIdx = 0);
-		MonoObject* getSerializableObject(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-
-	private:
-		void setValue(MonoObject* obj, void* val, CM::UINT32 arrayIdx = 0);
-		void* getValue(MonoObject* obj, CM::UINT32 arrayIdx = 0);
-	};
-
-	struct BS_SCR_BE_EXPORT SerializableObjectInfo
-	{
-		SerializableObjectInfo();
-		~SerializableObjectInfo();
-
-		CM::String mNamespace;
-		CM::String mTypeName;
-		CM::UINT32 mTypeId;
-
-		MonoClass* mMonoClass;
-
-		CM::UnorderedMap<CM::String, CM::UINT32>::type mFieldNameToId;
-		CM::UnorderedMap<CM::UINT32, SerializableFieldInfo*>::type mFields;
-
-		std::weak_ptr<SerializableObjectInfo> mBaseClass;
-		CM::Vector<std::weak_ptr<SerializableObjectInfo>>::type mDerivedClasses;
-	};
-
-	struct BS_SCR_BE_EXPORT SerializableAssemblyInfo
-	{
-		CM::UnorderedMap<CM::String, CM::UINT32>::type mTypeNameToId;
-		CM::UnorderedMap<CM::UINT32, std::shared_ptr<SerializableObjectInfo>>::type mObjectInfos;
-	};
-
 	class BS_SCR_BE_EXPORT RuntimeScriptObjects : public CM::Module<RuntimeScriptObjects>
 	{
 	public:
 		~RuntimeScriptObjects();
 
 		void refreshScriptObjects(const CM::String& assemblyName);
-		bool getSerializableObjectInfo(const CM::String& ns, const CM::String& typeName, std::shared_ptr<SerializableObjectInfo>& outInfo);
+		bool getSerializableObjectInfo(const CM::String& ns, const CM::String& typeName, std::shared_ptr<ScriptSerializableObjectInfo>& outInfo);
 		bool hasSerializableObjectInfo(const CM::String& ns, const CM::String& typeName);
+
+		bool isArray(const MonoClass* monoClass) const;
 	private:
-		CM::UnorderedMap<CM::String, std::shared_ptr<SerializableAssemblyInfo>>::type mAssemblyInfos;
+		CM::UnorderedMap<CM::String, std::shared_ptr<ScriptSerializableAssemblyInfo>>::type mAssemblyInfos;
 
 		void clearScriptObjects(const CM::String& assemblyName);
 	};

+ 20 - 1
SBansheeEngine/Include/BsScriptEnginePrerequisites.h

@@ -35,11 +35,30 @@ namespace BansheeEngine
 	class ScriptSceneObject;
 	class ScriptComponent;
 	class ManagedComponent;
+	class ManagedSerializationData;
+	class ScriptSerializableAssemblyInfo;
+	class ScriptSerializableObjectInfo;
+	class ScriptSerializableFieldInfo;
+	class ScriptSerializableFieldInfoPlain;
+	class ScriptSerializableFieldInfoArray;
 
 	enum TypeID_BansheeScript
 	{
-		TID_ManagedComponent = 50000
+		TID_ManagedComponent = 50000,
+		TID_ManagedSerializationData = 50001,
+		TID_SerializableAssemblyInfo = 50004,
+		TID_SerializableObjectInfo = 50005,
+		TID_SerializableFieldInfo = 50006,
+		TID_SerializableFieldInfoPlain = 50007,
+		TID_SerializableFieldInfoArray = 50008
 	};
 
 	static const char* BansheeEngineAssemblyName = "MBansheeEngine";
+
+	typedef std::shared_ptr<ManagedSerializationData> ManagedSerializationDataPtr;
+	typedef std::shared_ptr<ScriptSerializableAssemblyInfo> ScriptSerializableAssemblyInfoPtr;
+	typedef std::shared_ptr<ScriptSerializableObjectInfo> ScriptSerializableObjectInfoPtr;
+	typedef std::shared_ptr<ScriptSerializableFieldInfo> ScriptSerializableFieldInfoPtr;
+	typedef std::shared_ptr<ScriptSerializableFieldInfoPlain> ScriptSerializableFieldInfoPlainPtr;
+	typedef std::shared_ptr<ScriptSerializableFieldInfoArray> ScriptSerializableFieldInfoArrayPtr;
 }

+ 220 - 0
SBansheeEngine/Include/BsScriptSerializableObjectInfo.h

@@ -0,0 +1,220 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "CmIReflectable.h"
+#include <mono/jit/jit.h>
+
+namespace BansheeEngine
+{
+	enum class ScriptFieldType
+	{
+		Bool,
+		Char,
+		I8,
+		U8,
+		I16,
+		U16,
+		I32,
+		U32,
+		I64,
+		U64,
+		Float,
+		Double,
+		String,
+		SerializableObjectValue,
+		SerializableObjectRef,
+		TextureRef,
+		SpriteTextureRef,
+		SceneObjectRef,
+		ComponentRef,
+		Other
+	};
+
+	enum class ScriptFieldFlags
+	{
+		Serializable = 0x01,
+		Inspectable = 0x02
+	};
+
+	struct BS_SCR_BE_EXPORT ScriptSerializableFieldInfo : public CM::IReflectable
+	{
+		ScriptSerializableFieldInfo();
+		virtual ~ScriptSerializableFieldInfo() { }
+
+		CM::String mName;
+		CM::String mTypeNamespace;
+		CM::String mTypeName;
+		CM::UINT32 mFieldId;
+
+		ScriptFieldType mType;
+		ScriptFieldFlags mFlags;
+
+		MonoField* mMonoField;
+
+		virtual bool isArray() const = 0;
+		virtual bool isReferenceType() const = 0;
+
+		bool isNull(MonoObject* obj);
+		void setNull(MonoObject* obj);
+
+		virtual CM::UINT32 getNumArrayElements(MonoObject* obj, CM::UINT32 dimension) = 0;
+		virtual void setNumArrayElements(MonoObject* obj, CM::UINT32 numElements, CM::UINT32 dimension, bool discardExisting = true) = 0;
+
+		void setU8(MonoObject* obj, CM::UINT8 val, CM::UINT32 arrayIdx = 0);
+		CM::UINT8 getU8(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setI8(MonoObject* obj, CM::INT8 val, CM::UINT32 arrayIdx = 0);
+		CM::INT8 getI8(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setU16(MonoObject* obj, CM::UINT16 val, CM::UINT32 arrayIdx = 0);
+		CM::UINT16 getU16(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setI16(MonoObject* obj, CM::INT16 val, CM::UINT32 arrayIdx = 0);
+		CM::INT16 getI16(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setU32(MonoObject* obj, CM::UINT32 val, CM::UINT32 arrayIdx = 0);
+		CM::UINT32 getU32(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setI32(MonoObject* obj, CM::INT32 val, CM::UINT32 arrayIdx = 0);
+		CM::INT32 getI32(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setU64(MonoObject* obj, CM::UINT64 val, CM::UINT32 arrayIdx = 0);
+		CM::UINT64 getU64(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setI64(MonoObject* obj, CM::INT64 val, CM::UINT32 arrayIdx = 0);
+		CM::INT64 getI64(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setBool(MonoObject* obj, bool val, CM::UINT32 arrayIdx = 0);
+		bool getBool(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setChar(MonoObject* obj, wchar_t val, CM::UINT32 arrayIdx = 0);
+		wchar_t getChar(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setFloat(MonoObject* obj, float val, CM::UINT32 arrayIdx = 0);
+		float getFloat(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setDouble(MonoObject* obj, double val, CM::UINT32 arrayIdx = 0);
+		double getDouble(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setString(MonoObject* obj, const CM::WString& val, CM::UINT32 arrayIdx = 0);
+		CM::WString getString(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setTexture(MonoObject* obj, const CM::HTexture& resource, CM::UINT32 arrayIdx = 0);
+		CM::HTexture getTexture(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setSpriteTexture(MonoObject* obj, const HSpriteTexture& resource, CM::UINT32 arrayIdx = 0);
+		HSpriteTexture getSpriteTexture(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setSceneObject(MonoObject* obj, const CM::HSceneObject& sceneObject, CM::UINT32 arrayIdx = 0);
+		CM::HSceneObject getSceneObject(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setComponent(MonoObject* obj, const CM::HComponent& component, CM::UINT32 arrayIdx = 0);
+		CM::HComponent getComponent(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		void setSerializableObject(MonoObject* obj, const MonoObject* value, CM::UINT32 arrayIdx = 0);
+		MonoObject* getSerializableObject(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+	protected:
+		virtual void setValue(MonoObject* obj, void* val, CM::UINT32 arrayIdx = 0) = 0;
+		virtual void* getValue(MonoObject* obj, CM::UINT32 arrayIdx = 0) = 0;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class ScriptSerializableFieldInfoRTTI;
+		static CM::RTTITypeBase* getRTTIStatic();
+		virtual CM::RTTITypeBase* getRTTI() const;
+	};
+
+	struct BS_SCR_BE_EXPORT ScriptSerializableFieldInfoPlain : public ScriptSerializableFieldInfo
+	{
+	public:
+		virtual bool isArray() const { return false; }
+		virtual bool isReferenceType() const;
+
+		virtual CM::UINT32 getNumArrayElements(MonoObject* obj, CM::UINT32 dimension);
+		virtual void setNumArrayElements(MonoObject* obj, CM::UINT32 numElements, CM::UINT32 dimension, bool discardExisting = true);
+
+	protected:
+		virtual void setValue(MonoObject* obj, void* val, CM::UINT32 arrayIdx = 0);
+		virtual void* getValue(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class ScriptSerializableFieldInfoPlainRTTI;
+		static CM::RTTITypeBase* getRTTIStatic();
+		virtual CM::RTTITypeBase* getRTTI() const;
+	};
+
+	struct BS_SCR_BE_EXPORT ScriptSerializableFieldInfoArray : public ScriptSerializableFieldInfo
+	{
+	public:
+		ScriptSerializableFieldInfoArray();
+
+		CM::UINT8 mArrayDimensions;
+
+		virtual bool isArray() const { return true; }
+		virtual bool isReferenceType() const { return true; }
+
+		virtual CM::UINT32 getNumArrayElements(MonoObject* obj, CM::UINT32 dimension);
+		virtual void setNumArrayElements(MonoObject* obj, CM::UINT32 numElements, CM::UINT32 dimension, bool discardExisting = true);
+
+	protected:
+		virtual void setValue(MonoObject* obj, void* val, CM::UINT32 arrayIdx = 0);
+		virtual void* getValue(MonoObject* obj, CM::UINT32 arrayIdx = 0);
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class ScriptSerializableFieldInfoArrayRTTI;
+		static CM::RTTITypeBase* getRTTIStatic();
+		virtual CM::RTTITypeBase* getRTTI() const;
+	};
+
+	struct BS_SCR_BE_EXPORT ScriptSerializableObjectInfo : public CM::IReflectable
+	{
+		ScriptSerializableObjectInfo();
+
+		CM::String mNamespace;
+		CM::String mTypeName;
+		CM::UINT32 mTypeId;
+
+		MonoClass* mMonoClass;
+
+		CM::UnorderedMap<CM::String, CM::UINT32>::type mFieldNameToId;
+		CM::UnorderedMap<CM::UINT32, std::shared_ptr<ScriptSerializableFieldInfo>>::type mFields;
+
+		std::weak_ptr<ScriptSerializableObjectInfo> mBaseClass;
+		CM::Vector<std::weak_ptr<ScriptSerializableObjectInfo>>::type mDerivedClasses;
+
+		CM::String getFullTypeName() const { return mNamespace + "." + mTypeName; }
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class ScriptSerializableObjectInfoRTTI;
+		static CM::RTTITypeBase* getRTTIStatic();
+		virtual CM::RTTITypeBase* getRTTI() const;
+	};
+
+	struct BS_SCR_BE_EXPORT ScriptSerializableAssemblyInfo : public CM::IReflectable
+	{
+		CM::String mName;
+
+		CM::UnorderedMap<CM::String, CM::UINT32>::type mTypeNameToId;
+		CM::UnorderedMap<CM::UINT32, std::shared_ptr<ScriptSerializableObjectInfo>>::type mObjectInfos;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class ScriptSerializableAssemblyInfoRTTI;
+		static CM::RTTITypeBase* getRTTIStatic();
+		virtual CM::RTTITypeBase* getRTTI() const;
+	};
+}

+ 306 - 0
SBansheeEngine/Include/BsScriptSerializableObjectInfoRTTI.h

@@ -0,0 +1,306 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "CmRTTIType.h"
+#include "BsScriptSerializableObjectInfo.h"
+#include "CmException.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ScriptSerializableAssemblyInfoRTTI : public CM::RTTIType<ScriptSerializableAssemblyInfo, CM::IReflectable, ScriptSerializableAssemblyInfoRTTI>
+	{
+	private:
+		CM::String& getName(ScriptSerializableAssemblyInfo* obj)
+		{
+			return obj->mName;
+		}
+
+		void setName(ScriptSerializableAssemblyInfo* obj, CM::String& val)
+		{
+			obj->mName = val;
+		}
+
+		ScriptSerializableObjectInfoPtr getSerializableObjectInfo(ScriptSerializableAssemblyInfo* obj, CM::UINT32 idx) 
+		{ 
+			auto iter = obj->mObjectInfos.begin();
+			for(CM::UINT32 i = 0; i < idx; i++)
+				iter++;
+
+			return iter->second;
+		}
+
+		void setSerializableObjectInfo(ScriptSerializableAssemblyInfo* obj, UINT32 idx, ScriptSerializableObjectInfoPtr val) 
+		{ 
+			obj->mTypeNameToId[val->getFullTypeName()] = val->mTypeId;
+			obj->mObjectInfos[val->mTypeId] = val;
+		}
+		
+		UINT32 getSerializableObjectInfoArraySize(ScriptSerializableAssemblyInfo* obj) { return (UINT32)obj->mObjectInfos.size(); }
+		void setSerializableObjectInfoArraySize(ScriptSerializableAssemblyInfo* obj, UINT32 size) {  }
+
+	public:
+		ScriptSerializableAssemblyInfoRTTI()
+		{
+			addPlainField("mName", 0, &ScriptSerializableAssemblyInfoRTTI::getName, &ScriptSerializableAssemblyInfoRTTI::setName);
+			addReflectablePtrArrayField("mObjectInfos", 1, &ScriptSerializableAssemblyInfoRTTI::getSerializableObjectInfo, 
+				&ScriptSerializableAssemblyInfoRTTI::getSerializableObjectInfoArraySize, &ScriptSerializableAssemblyInfoRTTI::setSerializableObjectInfo, 
+				&ScriptSerializableAssemblyInfoRTTI::setSerializableObjectInfoArraySize);
+		}
+
+		virtual const CM::String& getRTTIName()
+		{
+			static CM::String name = "ScriptSerializableAssemblyInfo";
+			return name;
+		}
+
+		virtual CM::UINT32 getRTTIId()
+		{
+			return TID_SerializableAssemblyInfo;
+		}
+
+		virtual std::shared_ptr<CM::IReflectable> newRTTIObject()
+		{
+			return cm_shared_ptr<ScriptSerializableAssemblyInfo>();
+		}
+	};
+
+	class BS_SCR_BE_EXPORT ScriptSerializableObjectInfoRTTI : public CM::RTTIType<ScriptSerializableObjectInfo, CM::IReflectable, ScriptSerializableObjectInfoRTTI>
+	{
+	private:
+		CM::String& getNamespace(ScriptSerializableObjectInfo* obj)
+		{
+			return obj->mNamespace;
+		}
+
+		void setNamespace(ScriptSerializableObjectInfo* obj, CM::String& val)
+		{
+			obj->mNamespace = val;
+		}
+
+		CM::String& getTypename(ScriptSerializableObjectInfo* obj)
+		{
+			return obj->mTypeName;
+		}
+
+		void setTypename(ScriptSerializableObjectInfo* obj, CM::String& val)
+		{
+			obj->mTypeName = val;
+		}
+
+		CM::UINT32& getTypeId(ScriptSerializableObjectInfo* obj)
+		{
+			return obj->mTypeId;
+		}
+
+		void setTypeId(ScriptSerializableObjectInfo* obj, CM::UINT32& val)
+		{
+			obj->mTypeId = val;
+		}
+
+		ScriptSerializableObjectInfoPtr getBaseClass(ScriptSerializableObjectInfo* obj)
+		{
+			return obj->mBaseClass.lock();
+		}
+
+		void setBaseClass(ScriptSerializableObjectInfo* obj, ScriptSerializableObjectInfoPtr val)
+		{
+			obj->mBaseClass = val;
+		}
+
+		ScriptSerializableFieldInfoPtr getSerializableFieldInfo(ScriptSerializableObjectInfo* obj, CM::UINT32 idx) 
+		{ 
+			auto iter = obj->mFields.begin();
+			for(CM::UINT32 i = 0; i < idx; i++)
+				iter++;
+
+			return iter->second;
+		}
+
+		void setSerializableFieldInfo(ScriptSerializableObjectInfo* obj, UINT32 idx, ScriptSerializableFieldInfoPtr val) 
+		{ 
+			obj->mFieldNameToId[val->mName] = val->mFieldId;
+			obj->mFields[val->mFieldId] = val;
+		}
+
+		UINT32 getSerializableFieldInfoArraySize(ScriptSerializableObjectInfo* obj) { return (UINT32)obj->mFields.size(); }
+		void setSerializableFieldInfoArraySize(ScriptSerializableObjectInfo* obj, UINT32 size) {  }
+
+	public:
+		ScriptSerializableObjectInfoRTTI()
+		{
+			addPlainField("mNamespace", 0, &ScriptSerializableObjectInfoRTTI::getNamespace, &ScriptSerializableObjectInfoRTTI::setNamespace);
+			addPlainField("mTypename", 1, &ScriptSerializableObjectInfoRTTI::getTypename, &ScriptSerializableObjectInfoRTTI::setTypename);
+			addPlainField("mTypeId", 2, &ScriptSerializableObjectInfoRTTI::getTypeId, &ScriptSerializableObjectInfoRTTI::setTypeId);
+			addReflectablePtrField("mBaseClass", 3, &ScriptSerializableObjectInfoRTTI::getBaseClass, &ScriptSerializableObjectInfoRTTI::setBaseClass);
+
+			addReflectablePtrArrayField("mFields", 4, &ScriptSerializableObjectInfoRTTI::getSerializableFieldInfo, 
+				&ScriptSerializableObjectInfoRTTI::getSerializableFieldInfoArraySize, &ScriptSerializableObjectInfoRTTI::setSerializableFieldInfo, 
+				&ScriptSerializableObjectInfoRTTI::setSerializableFieldInfoArraySize);
+		}
+
+		virtual const CM::String& getRTTIName()
+		{
+			static CM::String name = "ScriptSerializableObjectInfo";
+			return name;
+		}
+
+		virtual CM::UINT32 getRTTIId()
+		{
+			return TID_SerializableObjectInfo;
+		}
+
+		virtual std::shared_ptr<CM::IReflectable> newRTTIObject()
+		{
+			return cm_shared_ptr<ScriptSerializableObjectInfo>();
+		}
+	};
+
+	class BS_SCR_BE_EXPORT ScriptSerializableFieldInfoRTTI : public CM::RTTIType<ScriptSerializableFieldInfo, CM::IReflectable, ScriptSerializableFieldInfoRTTI>
+	{
+	private:
+		CM::String& getTypeNamespace(ScriptSerializableFieldInfo* obj)
+		{
+			return obj->mTypeNamespace;
+		}
+
+		void setTypeNamespace(ScriptSerializableFieldInfo* obj, CM::String& val)
+		{
+			obj->mTypeNamespace = val;
+		}
+
+		CM::String& getTypeName(ScriptSerializableFieldInfo* obj)
+		{
+			return obj->mTypeName;
+		}
+
+		void setTypeName(ScriptSerializableFieldInfo* obj, CM::String& val)
+		{
+			obj->mTypeName = val;
+		}
+
+		CM::String& getName(ScriptSerializableFieldInfo* obj)
+		{
+			return obj->mName;
+		}
+
+		void setName(ScriptSerializableFieldInfo* obj, CM::String& val)
+		{
+			obj->mName = val;
+		}
+
+		CM::UINT32& getFieldId(ScriptSerializableFieldInfo* obj)
+		{
+			return obj->mFieldId;
+		}
+
+		void setFieldId(ScriptSerializableFieldInfo* obj, CM::UINT32& val)
+		{
+			obj->mFieldId = val;
+		}
+
+		CM::UINT32& getFlags(ScriptSerializableFieldInfo* obj)
+		{
+			CM::UINT32 flags = (CM::UINT32)obj->mFlags;
+
+			return flags;
+		}
+
+		void setFlags(ScriptSerializableFieldInfo* obj, CM::UINT32& val)
+		{
+			obj->mFlags = (ScriptFieldFlags)val;
+		}
+
+		CM::UINT32& getType(ScriptSerializableFieldInfo* obj)
+		{
+			CM::UINT32 flags = (CM::UINT32)obj->mType;
+
+			return flags;
+		}
+
+		void setType(ScriptSerializableFieldInfo* obj, CM::UINT32& val)
+		{
+			obj->mType = (ScriptFieldType)val;
+		}
+
+	public:
+		ScriptSerializableFieldInfoRTTI()
+		{
+			addPlainField("mName", 0, &ScriptSerializableFieldInfoRTTI::getName, &ScriptSerializableFieldInfoRTTI::setName);
+			addPlainField("mTypeNamespace", 1, &ScriptSerializableFieldInfoRTTI::getTypeNamespace, &ScriptSerializableFieldInfoRTTI::setTypeNamespace);
+			addPlainField("mTypeName", 2, &ScriptSerializableFieldInfoRTTI::getTypeName, &ScriptSerializableFieldInfoRTTI::setTypeName);
+			addPlainField("mFieldId", 3, &ScriptSerializableFieldInfoRTTI::getFieldId, &ScriptSerializableFieldInfoRTTI::setFieldId);
+			addPlainField("mFlags", 4, &ScriptSerializableFieldInfoRTTI::getFlags, &ScriptSerializableFieldInfoRTTI::setFlags);
+			addPlainField("mType", 5, &ScriptSerializableFieldInfoRTTI::getType, &ScriptSerializableFieldInfoRTTI::setType);
+		}
+
+		virtual const CM::String& getRTTIName()
+		{
+			static CM::String name = "ScriptSerializableFieldInfo";
+			return name;
+		}
+
+		virtual CM::UINT32 getRTTIId()
+		{
+			return TID_SerializableFieldInfo;
+		}
+
+		virtual std::shared_ptr<CM::IReflectable> newRTTIObject()
+		{
+			CM_EXCEPT(CM::InvalidStateException, "Cannot instantiate an abstract class.");
+		}
+	};
+
+	class BS_SCR_BE_EXPORT ScriptSerializableFieldInfoPlainRTTI : public CM::RTTIType<ScriptSerializableFieldInfoPlain, ScriptSerializableFieldInfo, ScriptSerializableFieldInfoPlainRTTI>
+	{
+	private:
+
+	public:
+		ScriptSerializableFieldInfoPlainRTTI()
+		{
+
+		}
+
+		virtual const CM::String& getRTTIName()
+		{
+			static CM::String name = "ScriptSerializableFieldInfoPlain";
+			return name;
+		}
+
+		virtual CM::UINT32 getRTTIId()
+		{
+			return TID_SerializableFieldInfoPlain;
+		}
+
+		virtual std::shared_ptr<CM::IReflectable> newRTTIObject()
+		{
+			return cm_shared_ptr<ScriptSerializableFieldInfoPlain>();
+		}
+	};
+
+	class BS_SCR_BE_EXPORT ScriptSerializableFieldInfoArrayRTTI : public CM::RTTIType<ScriptSerializableFieldInfoArray, ScriptSerializableFieldInfo, ScriptSerializableFieldInfoArrayRTTI>
+	{
+	private:
+
+	public:
+		ScriptSerializableFieldInfoArrayRTTI()
+		{
+
+		}
+
+		virtual const CM::String& getRTTIName()
+		{
+			static CM::String name = "ScriptSerializableFieldInfoArray";
+			return name;
+		}
+
+		virtual CM::UINT32 getRTTIId()
+		{
+			return TID_SerializableFieldInfoArray;
+		}
+
+		virtual std::shared_ptr<CM::IReflectable> newRTTIObject()
+		{
+			return cm_shared_ptr<ScriptSerializableFieldInfoArray>();
+		}
+	};
+}

+ 6 - 0
SBansheeEngine/SBansheeEngine.vcxproj

@@ -228,6 +228,8 @@
   <ItemGroup>
     <ClInclude Include="Include\BsManagedComponent.h" />
     <ClInclude Include="Include\BsManagedComponentRTTI.h" />
+    <ClInclude Include="Include\BsManagedSerializationData.h" />
+    <ClInclude Include="Include\BsManagedSerializationDataRTTI.h" />
     <ClInclude Include="Include\BsRuntimeScriptObjects.h" />
     <ClInclude Include="Include\BsScriptComponent.h" />
     <ClInclude Include="Include\BsScriptEnginePrerequisites.h" />
@@ -255,13 +257,16 @@
     <ClInclude Include="Include\BsScriptResource.h" />
     <ClInclude Include="Include\BsScriptResourceManager.h" />
     <ClInclude Include="Include\BsScriptSceneObject.h" />
+    <ClInclude Include="Include\BsScriptSerializableObjectInfoRTTI.h" />
     <ClInclude Include="Include\BsScriptSpriteTexture.h" />
     <ClInclude Include="Include\BsScriptStringTable.h" />
     <ClInclude Include="Include\BsScriptTexture2D.h" />
     <ClInclude Include="Include\BsScriptGUIContent.h" />
+    <ClInclude Include="Include\BsScriptSerializableObjectInfo.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsManagedComponent.cpp" />
+    <ClCompile Include="Source\BsManagedSerializationData.cpp" />
     <ClCompile Include="Source\BsRuntimeScriptObjects.cpp" />
     <ClCompile Include="Source\BsScriptComponent.cpp" />
     <ClCompile Include="Source\BsScriptEnginePlugin.cpp" />
@@ -285,6 +290,7 @@
     <ClCompile Include="Source\BsScriptGUIInputBox.cpp" />
     <ClCompile Include="Source\BsScriptResourceManager.cpp" />
     <ClCompile Include="Source\BsScriptSceneObject.cpp" />
+    <ClCompile Include="Source\BsScriptSerializableObjectInfo.cpp" />
     <ClCompile Include="Source\BsScriptSpriteTexture.cpp" />
     <ClCompile Include="Source\BsScriptStringTable.cpp" />
     <ClCompile Include="Source\BsScriptTexture2D.cpp" />

+ 18 - 0
SBansheeEngine/SBansheeEngine.vcxproj.filters

@@ -114,6 +114,18 @@
     <ClInclude Include="Include\BsScriptSceneObject.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsManagedSerializationData.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsManagedSerializationDataRTTI.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsScriptSerializableObjectInfo.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsScriptSerializableObjectInfoRTTI.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsScriptTexture2D.cpp">
@@ -200,5 +212,11 @@
     <ClCompile Include="Source\BsScriptSceneObject.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsManagedSerializationData.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsScriptSerializableObjectInfo.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 28 - 0
SBansheeEngine/Source/BsManagedSerializationData.cpp

@@ -0,0 +1,28 @@
+#include "BsManagedSerializationData.h"
+#include "BsManagedSerializationDataRTTI.h"
+
+using namespace CamelotFramework;
+
+namespace BansheeEngine
+{
+	ManagedSerializationDataPtr ManagedSerializationData::create(MonoObject* managedInstance)
+	{
+
+	}
+
+	ManagedSerializationData::ManagedSerializationData(const CM::String& ns, const CM::String& typeName)
+		:mNamespace(ns), mTypename(typeName)
+	{
+
+	}
+
+	RTTITypeBase* ManagedSerializationData::getRTTIStatic()
+	{
+		return ManagedSerializationDataRTTI::instance();
+	}
+
+	RTTITypeBase* ManagedSerializationData::getRTTI() const
+	{
+		return ManagedSerializationData::getRTTIStatic();
+	}
+}

+ 34 - 480
SBansheeEngine/Source/BsRuntimeScriptObjects.cpp

@@ -6,471 +6,11 @@
 #include "BsMonoClass.h"
 #include "BsMonoField.h"
 #include "BsMonoUtil.h"
-#include "BsScriptTexture2D.h"
-#include "BsScriptSpriteTexture.h"
-#include "BsScriptSceneObject.h"
-#include "BsScriptComponent.h"
 
 using namespace CamelotFramework;
 
 namespace BansheeEngine
 {
-	SerializableObjectInfo::SerializableObjectInfo()
-		:mMonoClass(nullptr), mTypeId(0)
-	{
-
-	}
-
-	SerializableObjectInfo::~SerializableObjectInfo()
-	{
-		for(auto& field : mFields)
-		{
-			cm_delete(field.second);
-		}
-	}
-
-	SerializableFieldInfo::SerializableFieldInfo()
-		:mMonoField(nullptr), mType(ScriptFieldType::Other), mFlags((ScriptFieldFlags)0), mFieldId(0)
-	{
-
-	}
-
-	SerializableFieldInfo::~SerializableFieldInfo()
-	{
-
-	}
-
-	bool SerializableFieldInfo::isArray()
-	{
-		return ((UINT32)mFlags & (UINT32)ScriptFieldFlags::Array) != 0;
-	}
-
-	bool SerializableFieldInfo::isReferenceType()
-	{
-		return (isArray() || mType == ScriptFieldType::TextureRef || mType == ScriptFieldType::SpriteTextureRef || 
-			mType == ScriptFieldType::SceneObjectRef || mType == ScriptFieldType::ComponentRef || mType == ScriptFieldType::SerializableObjectRef);
-	}
-
-	bool SerializableFieldInfo::isNull(MonoObject* obj)
-	{
-		assert(isReferenceType());
-
-		void* val = mMonoField->getValue(obj);
-
-		return val == nullptr;
-	}
-
-	void SerializableFieldInfo::setNull(MonoObject* obj)
-	{
-		assert(isReferenceType());
-
-		mMonoField->setValue(obj, nullptr);
-	}
-
-	UINT32 SerializableFieldInfo::getNumArrayElements(MonoObject* obj)
-	{
-		assert(((UINT32)mFlags & (UINT32)ScriptFieldFlags::Array) != 0);
-
-		MonoArray* array = reinterpret_cast<MonoArray*>(mMonoField->getValue(obj));
-		return (UINT32)mono_array_length(array);
-	}
-
-	void SerializableFieldInfo::setNumArrayElements(MonoObject* obj, UINT32 numElements, bool discardExisting)
-	{
-		assert(((UINT32)mFlags & (UINT32)ScriptFieldFlags::Array) != 0);
-
-		uint32_t lengths[1] = { numElements };
-
-		MonoArray* newArray = mono_array_new_full(MonoManager::instance().getDomain(), 
-			mMonoField->getType()->_getInternalClass(), (uintptr_t*)lengths, nullptr);
-
-		if(!discardExisting)
-		{
-			MonoArray* existingArray = reinterpret_cast<MonoArray*>(mMonoField->getValue(obj));
-			UINT32 existingArrayLength = (UINT32)mono_array_length(existingArray);
-
-			UINT32 elemsToCopy = std::min(existingArrayLength, numElements);
-			int32_t elemSize = mono_array_element_size(mMonoField->getType()->_getInternalClass());
-
-			for(UINT32 i = 0; i < elemsToCopy; i++)
-			{
-				void* existingValAddr = (void*)mono_array_addr_with_size(existingArray, elemSize, (uintptr_t)i);
-				void* newValAddr = (void*)mono_array_addr_with_size(newArray, elemSize, (uintptr_t)i);
-
-				memcpy(newValAddr, existingValAddr, elemSize);
-			}
-		}
-
-		mMonoField->setValue(obj, newArray);
-	}
-
-	void SerializableFieldInfo::setU8(MonoObject* obj, UINT8 val, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::U8);
-
-		setValue(obj, &val, arrayIdx);
-	}
-
-	UINT8 SerializableFieldInfo::getU8(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::U8);
-
-		return *(UINT8*)getValue(obj, arrayIdx);
-	}
-
-	void SerializableFieldInfo::setI8(MonoObject* obj, INT8 val, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::I8);
-
-		setValue(obj, &val, arrayIdx);
-	}
-
-	INT8 SerializableFieldInfo::getI8(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::I8);
-
-		return *(INT8*)getValue(obj, arrayIdx);
-	}
-
-	void SerializableFieldInfo::setU16(MonoObject* obj, UINT16 val, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::U16);
-
-		setValue(obj, &val, arrayIdx);
-	}
-
-	UINT16 SerializableFieldInfo::getU16(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::U16);
-
-		return *(UINT16*)getValue(obj, arrayIdx);
-	}
-
-	void SerializableFieldInfo::setI16(MonoObject* obj, INT16 val, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::I16);
-
-		setValue(obj, &val, arrayIdx);
-	}
-
-	INT16 SerializableFieldInfo::getI16(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::I16);
-
-		return *(INT16*)getValue(obj, arrayIdx);
-	}
-
-	void SerializableFieldInfo::setU32(MonoObject* obj, UINT32 val, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::U32);
-
-		setValue(obj, &val, arrayIdx);
-	}
-
-	UINT32 SerializableFieldInfo::getU32(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::U32);
-
-		return *(UINT32*)getValue(obj, arrayIdx);
-	}
-
-	void SerializableFieldInfo::setI32(MonoObject* obj, INT32 val, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::I32);
-
-		setValue(obj, &val, arrayIdx);
-	}
-
-	INT32 SerializableFieldInfo::getI32(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::I32);
-
-		return *(INT32*)getValue(obj, arrayIdx);
-	}
-
-	void SerializableFieldInfo::setU64(MonoObject* obj, UINT64 val, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::U64);
-
-		setValue(obj, &val, arrayIdx);
-	}
-
-	UINT64 SerializableFieldInfo::getU64(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::U64);
-
-		return *(UINT64*)getValue(obj, arrayIdx);
-	}
-
-	void SerializableFieldInfo::setI64(MonoObject* obj, INT64 val, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::I64);
-
-		setValue(obj, &val, arrayIdx);
-	}
-
-	INT64 SerializableFieldInfo::getI64(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::I64);
-
-		return *(INT64*)getValue(obj, arrayIdx);
-	}
-
-	void SerializableFieldInfo::setBool(MonoObject* obj, bool val, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::Bool);
-
-		setValue(obj, &val, arrayIdx);
-	}
-
-	bool SerializableFieldInfo::getBool(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::Bool);
-
-		return *(bool*)getValue(obj, arrayIdx);
-	}
-
-	void SerializableFieldInfo::setChar(MonoObject* obj, wchar_t val, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::Char);
-
-		setValue(obj, &val, arrayIdx);
-	}
-
-	wchar_t SerializableFieldInfo::getChar(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::Char);
-
-		return *(wchar_t*)getValue(obj, arrayIdx);
-	}
-
-	void SerializableFieldInfo::setFloat(MonoObject* obj, float val, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::Float);
-
-		setValue(obj, &val, arrayIdx);
-	}
-
-	float SerializableFieldInfo::getFloat(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::Float);
-
-		return *(float*)getValue(obj, arrayIdx);
-	}
-
-	void SerializableFieldInfo::setDouble(MonoObject* obj, double val, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::Double);
-
-		setValue(obj, &val, arrayIdx);
-	}
-
-	double SerializableFieldInfo::getDouble(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::Double);
-
-		return *(double*)getValue(obj, arrayIdx);
-	}
-
-	void SerializableFieldInfo::setString(MonoObject* obj, const WString& val, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::String);
-
-		MonoString* str = MonoUtil::wstringToMono(MonoManager::instance().getDomain(), val);
-		setValue(obj, str, arrayIdx);
-	}
-
-	WString SerializableFieldInfo::getString(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::String);
-
-		MonoString* str = (MonoString*)getValue(obj, arrayIdx);
-		if(str == nullptr)
-			return L"";
-
-		return MonoUtil::monoToWString(str);
-	}
-
-	void SerializableFieldInfo::setTexture(MonoObject* obj, const HTexture& resource, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::TextureRef);
-
-		if(resource == nullptr)
-		{
-			setValue(obj, nullptr, arrayIdx);
-		}
-		else
-		{
-			ScriptTexture2D* scriptResource = ScriptResourceManager::instance().getScriptTexture(resource);
-			if(scriptResource == nullptr)
-				scriptResource = ScriptResourceManager::instance().createScriptTexture(resource);
-
-			MonoObject* managedInstance = scriptResource->getManagedInstance();
-			setValue(obj, (void*)managedInstance, arrayIdx);
-		}
-	}
-
-	CM::HTexture SerializableFieldInfo::getTexture(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::TextureRef);
-
-		MonoObject* managedInstance = (MonoObject*)getValue(obj, arrayIdx);
-		if(managedInstance == nullptr)
-			return HTexture();
-
-		ScriptTexture2D* scriptResource = ScriptTexture2D::toNative(managedInstance);
-		return static_resource_cast<Texture>(scriptResource->getNativeHandle());
-	}
-
-	void SerializableFieldInfo::setSpriteTexture(MonoObject* obj, const HSpriteTexture& resource, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::SpriteTextureRef);
-
-		if(resource == nullptr)
-		{
-			setValue(obj, nullptr, arrayIdx);
-		}
-		else
-		{
-			ScriptSpriteTexture* scriptResource = ScriptResourceManager::instance().getScriptSpriteTexture(resource);
-			if(scriptResource == nullptr)
-				scriptResource = ScriptResourceManager::instance().createScriptSpriteTexture(resource);
-
-			MonoObject* managedInstance = scriptResource->getManagedInstance();
-			setValue(obj, (void*)managedInstance, arrayIdx);
-		}
-	}
-
-	HSpriteTexture SerializableFieldInfo::getSpriteTexture(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::SpriteTextureRef);
-
-		MonoObject* managedInstance = (MonoObject*)getValue(obj, arrayIdx);
-		if(managedInstance == nullptr)
-			return HTexture();
-
-		ScriptSpriteTexture* scriptResource = ScriptSpriteTexture::toNative(managedInstance);
-		return static_resource_cast<SpriteTexture>(scriptResource->getNativeHandle());
-	}
-
-	void SerializableFieldInfo::setSceneObject(MonoObject* obj, const HSceneObject& sceneObject, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::SceneObjectRef);
-
-		if(sceneObject == nullptr)
-		{
-			setValue(obj, nullptr, arrayIdx);
-		}
-		else
-		{
-			ScriptSceneObject* scriptSceneObject = ScriptGameObjectManager::instance().getScriptSceneObject(sceneObject);
-			if(scriptSceneObject == nullptr)
-				scriptSceneObject = ScriptGameObjectManager::instance().createScriptSceneObject(sceneObject);
-
-			MonoObject* managedInstance = scriptSceneObject->getManagedInstance();
-			setValue(obj, (void*)managedInstance, arrayIdx);
-		}
-	}
-
-	HSceneObject SerializableFieldInfo::getSceneObject(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::SceneObjectRef);
-
-		MonoObject* managedInstance = (MonoObject*)getValue(obj, arrayIdx);
-		if(managedInstance == nullptr)
-			return HSceneObject();
-
-		ScriptSceneObject* scriptSceneObject = ScriptSceneObject::toNative(managedInstance);
-		return static_object_cast<SceneObject>(scriptSceneObject->getNativeHandle());
-	}
-
-	void SerializableFieldInfo::setComponent(MonoObject* obj, const HComponent& component, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::ComponentRef);
-
-		if(component == nullptr)
-		{
-			setValue(obj, nullptr, arrayIdx);
-		}
-		else
-		{
-			ScriptComponent* scriptComponent = ScriptGameObjectManager::instance().getScriptComponent(component);
-			if(scriptComponent == nullptr)
-				scriptComponent = ScriptGameObjectManager::instance().createScriptComponent(component);
-
-			MonoObject* managedInstance = scriptComponent->getManagedInstance();
-			setValue(obj, (void*)managedInstance, arrayIdx);
-		}
-	}
-
-	HComponent SerializableFieldInfo::getComponent(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::ComponentRef);
-
-		MonoObject* managedInstance = (MonoObject*)getValue(obj, arrayIdx);
-		if(managedInstance == nullptr)
-			return HComponent();
-
-		ScriptComponent* scriptComponent = ScriptComponent::toNative(managedInstance);
-		return static_object_cast<Component>(scriptComponent->getNativeHandle());
-	}
-
-
-	void SerializableFieldInfo::setSerializableObject(MonoObject* obj, const MonoObject* value, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::SerializableObjectRef || mType == ScriptFieldType::SerializableObjectValue);
-
-		setValue(obj, (void*)value, arrayIdx);
-	}
-
-	MonoObject* SerializableFieldInfo::getSerializableObject(MonoObject* obj, UINT32 arrayIdx)
-	{
-		assert(mType == ScriptFieldType::SerializableObjectRef || mType == ScriptFieldType::SerializableObjectValue);
-
-		return (MonoObject*)getValue(obj, arrayIdx);
-	}
-
-	void SerializableFieldInfo::setValue(MonoObject* obj, void* val, CM::UINT32 arrayIdx)
-	{
-		if(isArray())
-		{
-			MonoArray* array = (MonoArray*)mMonoField->getValue(obj);
-			UINT32 elemSize = mono_array_element_size(mMonoField->getType()->_getInternalClass());
-
-			UINT32 numElems = (UINT32)mono_array_length(array);
-			assert(arrayIdx < numElems);
-
-			void* elemAddr = mono_array_addr_with_size(array, elemSize, arrayIdx);
-			memcpy(elemAddr, val, elemSize);
-		}
-		else
-		{
-			assert(arrayIdx == 0);
-
-			mMonoField->setValue(obj, val);
-		}
-	}
-
-	void* SerializableFieldInfo::getValue(MonoObject* obj, CM::UINT32 arrayIdx)
-	{
-		if(isArray())
-		{
-			MonoArray* array = (MonoArray*)mMonoField->getValue(obj);
-			UINT32 elemSize = mono_array_element_size(mMonoField->getType()->_getInternalClass());
-
-			UINT32 numElems = (UINT32)mono_array_length(array);
-			assert(arrayIdx < numElems);
-
-			return mono_array_addr_with_size(array, elemSize, arrayIdx);
-		}
-		else
-		{
-			assert(arrayIdx == 0);
-
-			return mMonoField->getValue(obj);
-		}
-	}
-
 	RuntimeScriptObjects::~RuntimeScriptObjects()
 	{
 
@@ -532,7 +72,9 @@ namespace BansheeEngine
 		if(curAssembly == nullptr)
 			return;
 
-		std::shared_ptr<SerializableAssemblyInfo> assemblyInfo = cm_shared_ptr<SerializableAssemblyInfo>();
+		std::shared_ptr<ScriptSerializableAssemblyInfo> assemblyInfo = cm_shared_ptr<ScriptSerializableAssemblyInfo>();
+		assemblyInfo->mName = assemblyName;
+
 		mAssemblyInfos[assemblyName] = assemblyInfo;
 
 		// Populate class data
@@ -541,15 +83,14 @@ namespace BansheeEngine
 		{
 			if((curClass->isSubClassOf(componentClass) || curClass->hasAttribute(serializableAttribute)) && curClass != componentClass)
 			{
-				std::shared_ptr<SerializableObjectInfo> objInfo = cm_shared_ptr<SerializableObjectInfo>();
+				std::shared_ptr<ScriptSerializableObjectInfo> objInfo = cm_shared_ptr<ScriptSerializableObjectInfo>();
 
 				objInfo->mTypeId = mUniqueTypeId++;
 				objInfo->mTypeName = curClass->getTypeName();
 				objInfo->mNamespace = curClass->getNamespace();
 				objInfo->mMonoClass = curClass;
 
-				String fullTypeName = objInfo->mNamespace + "." + objInfo->mTypeName;
-				assemblyInfo->mTypeNameToId[fullTypeName] = objInfo->mTypeId;
+				assemblyInfo->mTypeNameToId[objInfo->getFullTypeName()] = objInfo->mTypeId;
 				assemblyInfo->mObjectInfos[objInfo->mTypeId] = objInfo;
 			}
 		}
@@ -557,7 +98,7 @@ namespace BansheeEngine
 		// Populate field data
 		for(auto& curClassInfo : assemblyInfo->mObjectInfos)
 		{
-			std::shared_ptr<SerializableObjectInfo> objInfo = curClassInfo.second;
+			std::shared_ptr<ScriptSerializableObjectInfo> objInfo = curClassInfo.second;
 
 			String fullTypeName = objInfo->mNamespace + "." + objInfo->mTypeName;
 			assemblyInfo->mTypeNameToId[fullTypeName] = objInfo->mTypeId;
@@ -571,23 +112,21 @@ namespace BansheeEngine
 				if(field->isStatic())
 					continue;
 
-				SerializableFieldInfo* fieldInfo = cm_new<SerializableFieldInfo>();
-				fieldInfo->mFieldId = mUniqueFieldId++;
-				fieldInfo->mMonoField = field;
-				fieldInfo->mName = field->getName();
-
 				MonoClass* fieldType = field->getType();
-				fieldInfo->mTypeNamespace = fieldType->getNamespace();
-				fieldInfo->mTypeName = fieldType->getTypeName();
-
 				MonoClass* fieldElementClass = fieldType;
 				MonoType* monoType = mono_class_get_type(fieldType->_getInternalClass());
 				int monoPrimitiveType = mono_type_get_type(monoType);
 
-				// TODO - We don't support nested arrays or multi-dimensional arrays
+				std::shared_ptr<ScriptSerializableFieldInfo> fieldInfo = nullptr;
+
 				bool isSupportedType = true;
 				if(monoPrimitiveType == MONO_TYPE_ARRAY) 
 				{
+					std::shared_ptr<ScriptSerializableFieldInfoArray> arrayFieldInfo = cm_shared_ptr<ScriptSerializableFieldInfoArray>();
+					arrayFieldInfo->mArrayDimensions = (UINT32)mono_class_get_rank(fieldType->_getInternalClass());
+
+					fieldInfo = arrayFieldInfo;
+
 					::MonoClass* elementClass = mono_class_get_element_class(fieldType->_getInternalClass());
 					if(elementClass != nullptr)
 					{
@@ -600,10 +139,25 @@ namespace BansheeEngine
 
 						fieldElementClass = MonoManager::instance().findClass(elementNs, elementTypeName);
 					}
-
-					fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Array);
 				}
-				// TODO - Also check for List and get its generic primitive
+				else if(monoPrimitiveType == MONO_TYPE_CLASS)
+				{
+					// TODO - Check for List or Dictionary
+					
+					// If not List/Dictionary
+					fieldInfo = cm_shared_ptr<ScriptSerializableFieldInfoPlain>();
+				}
+				else
+				{
+					fieldInfo = cm_shared_ptr<ScriptSerializableFieldInfoPlain>();
+				}
+
+				fieldInfo->mFieldId = mUniqueFieldId++;
+				fieldInfo->mMonoField = field;
+				fieldInfo->mName = field->getName();
+
+				fieldInfo->mTypeNamespace = fieldType->getNamespace();
+				fieldInfo->mTypeName = fieldType->getTypeName();
 
 				//  Determine field type
 				switch(monoPrimitiveType) // TODO - If array I need to get underlying type
@@ -658,7 +212,7 @@ namespace BansheeEngine
 						fieldInfo->mType = ScriptFieldType::ComponentRef;
 					else
 					{
-						if(hasSerializableObjectInfo(fieldElementClass->getNamespace(), fieldElementClass->getTypeName()))
+						if(hasSerializableObjectInfo(fieldElementClass->getNamespace(), fieldElementClass->getTypeName())) // TODO - Ensure this checks for array types
 							fieldInfo->mType = ScriptFieldType::SerializableObjectRef;
 					}
 
@@ -699,7 +253,7 @@ namespace BansheeEngine
 			MonoClass* base = curClass.second->mMonoClass->getBaseClass();
 			while(base != nullptr)
 			{
-				std::shared_ptr<SerializableObjectInfo> baseObjInfo;
+				std::shared_ptr<ScriptSerializableObjectInfo> baseObjInfo;
 				if(getSerializableObjectInfo(base->getNamespace(), base->getTypeName(), baseObjInfo))
 				{
 					curClass.second->mBaseClass = baseObjInfo;
@@ -718,7 +272,7 @@ namespace BansheeEngine
 		mAssemblyInfos.erase(assemblyName);
 	}
 
-	bool RuntimeScriptObjects::getSerializableObjectInfo(const CM::String& ns, const CM::String& typeName, std::shared_ptr<SerializableObjectInfo>& outInfo)
+	bool RuntimeScriptObjects::getSerializableObjectInfo(const CM::String& ns, const CM::String& typeName, std::shared_ptr<ScriptSerializableObjectInfo>& outInfo)
 	{
 		String fullName = ns + "." + typeName;
 		for(auto& curAssembly : mAssemblyInfos)

+ 518 - 0
SBansheeEngine/Source/BsScriptSerializableObjectInfo.cpp

@@ -0,0 +1,518 @@
+#include "BsScriptSerializableObjectInfo.h"
+#include "BsScriptSerializableObjectInfoRTTI.h"
+#include "BsMonoUtil.h"
+#include "BsMonoField.h"
+#include "BsMonoClass.h"
+#include "BsMonoManager.h"
+#include "BsScriptResourceManager.h"
+#include "BsScriptGameObjectManager.h"
+#include "BsScriptTexture2D.h"
+#include "BsScriptSpriteTexture.h"
+#include "BsScriptComponent.h"
+#include "BsScriptSceneObject.h"
+
+using namespace CamelotFramework;
+
+namespace BansheeEngine
+{
+	RTTITypeBase* ScriptSerializableAssemblyInfo::getRTTIStatic()
+	{
+		return ScriptSerializableAssemblyInfoRTTI::instance();
+	}
+
+	RTTITypeBase* ScriptSerializableAssemblyInfo::getRTTI() const
+	{
+		return ScriptSerializableAssemblyInfo::getRTTIStatic();
+	}
+
+	ScriptSerializableObjectInfo::ScriptSerializableObjectInfo()
+		:mMonoClass(nullptr), mTypeId(0)
+	{
+
+	}
+
+	RTTITypeBase* ScriptSerializableObjectInfo::getRTTIStatic()
+	{
+		return ScriptSerializableObjectInfoRTTI::instance();
+	}
+
+	RTTITypeBase* ScriptSerializableObjectInfo::getRTTI() const
+	{
+		return ScriptSerializableObjectInfo::getRTTIStatic();
+	}
+
+	ScriptSerializableFieldInfo::ScriptSerializableFieldInfo()
+		:mMonoField(nullptr), mType(ScriptFieldType::Other), mFlags((ScriptFieldFlags)0), mFieldId(0), mArrayDimensions(0)
+	{
+
+	}
+
+	bool ScriptSerializableFieldInfo::isNull(MonoObject* obj)
+	{
+		assert(isReferenceType());
+
+		void* val = mMonoField->getValue(obj);
+
+		return val == nullptr;
+	}
+
+	void ScriptSerializableFieldInfo::setNull(MonoObject* obj)
+	{
+		assert(isReferenceType());
+
+		mMonoField->setValue(obj, nullptr);
+	}
+
+	void ScriptSerializableFieldInfo::setU8(MonoObject* obj, UINT8 val, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::U8);
+
+		setValue(obj, &val, arrayIdx);
+	}
+
+	UINT8 ScriptSerializableFieldInfo::getU8(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::U8);
+
+		return *(UINT8*)getValue(obj, arrayIdx);
+	}
+
+	void ScriptSerializableFieldInfo::setI8(MonoObject* obj, INT8 val, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::I8);
+
+		setValue(obj, &val, arrayIdx);
+	}
+
+	INT8 ScriptSerializableFieldInfo::getI8(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::I8);
+
+		return *(INT8*)getValue(obj, arrayIdx);
+	}
+
+	void ScriptSerializableFieldInfo::setU16(MonoObject* obj, UINT16 val, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::U16);
+
+		setValue(obj, &val, arrayIdx);
+	}
+
+	UINT16 ScriptSerializableFieldInfo::getU16(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::U16);
+
+		return *(UINT16*)getValue(obj, arrayIdx);
+	}
+
+	void ScriptSerializableFieldInfo::setI16(MonoObject* obj, INT16 val, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::I16);
+
+		setValue(obj, &val, arrayIdx);
+	}
+
+	INT16 ScriptSerializableFieldInfo::getI16(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::I16);
+
+		return *(INT16*)getValue(obj, arrayIdx);
+	}
+
+	void ScriptSerializableFieldInfo::setU32(MonoObject* obj, UINT32 val, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::U32);
+
+		setValue(obj, &val, arrayIdx);
+	}
+
+	UINT32 ScriptSerializableFieldInfo::getU32(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::U32);
+
+		return *(UINT32*)getValue(obj, arrayIdx);
+	}
+
+	void ScriptSerializableFieldInfo::setI32(MonoObject* obj, INT32 val, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::I32);
+
+		setValue(obj, &val, arrayIdx);
+	}
+
+	INT32 ScriptSerializableFieldInfo::getI32(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::I32);
+
+		return *(INT32*)getValue(obj, arrayIdx);
+	}
+
+	void ScriptSerializableFieldInfo::setU64(MonoObject* obj, UINT64 val, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::U64);
+
+		setValue(obj, &val, arrayIdx);
+	}
+
+	UINT64 ScriptSerializableFieldInfo::getU64(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::U64);
+
+		return *(UINT64*)getValue(obj, arrayIdx);
+	}
+
+	void ScriptSerializableFieldInfo::setI64(MonoObject* obj, INT64 val, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::I64);
+
+		setValue(obj, &val, arrayIdx);
+	}
+
+	INT64 ScriptSerializableFieldInfo::getI64(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::I64);
+
+		return *(INT64*)getValue(obj, arrayIdx);
+	}
+
+	void ScriptSerializableFieldInfo::setBool(MonoObject* obj, bool val, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::Bool);
+
+		setValue(obj, &val, arrayIdx);
+	}
+
+	bool ScriptSerializableFieldInfo::getBool(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::Bool);
+
+		return *(bool*)getValue(obj, arrayIdx);
+	}
+
+	void ScriptSerializableFieldInfo::setChar(MonoObject* obj, wchar_t val, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::Char);
+
+		setValue(obj, &val, arrayIdx);
+	}
+
+	wchar_t ScriptSerializableFieldInfo::getChar(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::Char);
+
+		return *(wchar_t*)getValue(obj, arrayIdx);
+	}
+
+	void ScriptSerializableFieldInfo::setFloat(MonoObject* obj, float val, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::Float);
+
+		setValue(obj, &val, arrayIdx);
+	}
+
+	float ScriptSerializableFieldInfo::getFloat(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::Float);
+
+		return *(float*)getValue(obj, arrayIdx);
+	}
+
+	void ScriptSerializableFieldInfo::setDouble(MonoObject* obj, double val, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::Double);
+
+		setValue(obj, &val, arrayIdx);
+	}
+
+	double ScriptSerializableFieldInfo::getDouble(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::Double);
+
+		return *(double*)getValue(obj, arrayIdx);
+	}
+
+	void ScriptSerializableFieldInfo::setString(MonoObject* obj, const WString& val, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::String);
+
+		MonoString* str = MonoUtil::wstringToMono(MonoManager::instance().getDomain(), val);
+		setValue(obj, str, arrayIdx);
+	}
+
+	WString ScriptSerializableFieldInfo::getString(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::String);
+
+		MonoString* str = (MonoString*)getValue(obj, arrayIdx);
+		if(str == nullptr)
+			return L"";
+
+		return MonoUtil::monoToWString(str);
+	}
+
+	void ScriptSerializableFieldInfo::setTexture(MonoObject* obj, const HTexture& resource, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::TextureRef);
+
+		if(resource == nullptr)
+		{
+			setValue(obj, nullptr, arrayIdx);
+		}
+		else
+		{
+			ScriptTexture2D* scriptResource = ScriptResourceManager::instance().getScriptTexture(resource);
+			if(scriptResource == nullptr)
+				scriptResource = ScriptResourceManager::instance().createScriptTexture(resource);
+
+			MonoObject* managedInstance = scriptResource->getManagedInstance();
+			setValue(obj, (void*)managedInstance, arrayIdx);
+		}
+	}
+
+	CM::HTexture ScriptSerializableFieldInfo::getTexture(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::TextureRef);
+
+		MonoObject* managedInstance = (MonoObject*)getValue(obj, arrayIdx);
+		if(managedInstance == nullptr)
+			return HTexture();
+
+		ScriptTexture2D* scriptResource = ScriptTexture2D::toNative(managedInstance);
+		return static_resource_cast<Texture>(scriptResource->getNativeHandle());
+	}
+
+	void ScriptSerializableFieldInfo::setSpriteTexture(MonoObject* obj, const HSpriteTexture& resource, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::SpriteTextureRef);
+
+		if(resource == nullptr)
+		{
+			setValue(obj, nullptr, arrayIdx);
+		}
+		else
+		{
+			ScriptSpriteTexture* scriptResource = ScriptResourceManager::instance().getScriptSpriteTexture(resource);
+			if(scriptResource == nullptr)
+				scriptResource = ScriptResourceManager::instance().createScriptSpriteTexture(resource);
+
+			MonoObject* managedInstance = scriptResource->getManagedInstance();
+			setValue(obj, (void*)managedInstance, arrayIdx);
+		}
+	}
+
+	HSpriteTexture ScriptSerializableFieldInfo::getSpriteTexture(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::SpriteTextureRef);
+
+		MonoObject* managedInstance = (MonoObject*)getValue(obj, arrayIdx);
+		if(managedInstance == nullptr)
+			return HTexture();
+
+		ScriptSpriteTexture* scriptResource = ScriptSpriteTexture::toNative(managedInstance);
+		return static_resource_cast<SpriteTexture>(scriptResource->getNativeHandle());
+	}
+
+	void ScriptSerializableFieldInfo::setSceneObject(MonoObject* obj, const HSceneObject& sceneObject, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::SceneObjectRef);
+
+		if(sceneObject == nullptr)
+		{
+			setValue(obj, nullptr, arrayIdx);
+		}
+		else
+		{
+			ScriptSceneObject* scriptSceneObject = ScriptGameObjectManager::instance().getScriptSceneObject(sceneObject);
+			if(scriptSceneObject == nullptr)
+				scriptSceneObject = ScriptGameObjectManager::instance().createScriptSceneObject(sceneObject);
+
+			MonoObject* managedInstance = scriptSceneObject->getManagedInstance();
+			setValue(obj, (void*)managedInstance, arrayIdx);
+		}
+	}
+
+	HSceneObject ScriptSerializableFieldInfo::getSceneObject(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::SceneObjectRef);
+
+		MonoObject* managedInstance = (MonoObject*)getValue(obj, arrayIdx);
+		if(managedInstance == nullptr)
+			return HSceneObject();
+
+		ScriptSceneObject* scriptSceneObject = ScriptSceneObject::toNative(managedInstance);
+		return static_object_cast<SceneObject>(scriptSceneObject->getNativeHandle());
+	}
+
+	void ScriptSerializableFieldInfo::setComponent(MonoObject* obj, const HComponent& component, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::ComponentRef);
+
+		if(component == nullptr)
+		{
+			setValue(obj, nullptr, arrayIdx);
+		}
+		else
+		{
+			ScriptComponent* scriptComponent = ScriptGameObjectManager::instance().getScriptComponent(component);
+			if(scriptComponent == nullptr)
+				scriptComponent = ScriptGameObjectManager::instance().createScriptComponent(component);
+
+			MonoObject* managedInstance = scriptComponent->getManagedInstance();
+			setValue(obj, (void*)managedInstance, arrayIdx);
+		}
+	}
+
+	HComponent ScriptSerializableFieldInfo::getComponent(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::ComponentRef);
+
+		MonoObject* managedInstance = (MonoObject*)getValue(obj, arrayIdx);
+		if(managedInstance == nullptr)
+			return HComponent();
+
+		ScriptComponent* scriptComponent = ScriptComponent::toNative(managedInstance);
+		return static_object_cast<Component>(scriptComponent->getNativeHandle());
+	}
+
+
+	void ScriptSerializableFieldInfo::setSerializableObject(MonoObject* obj, const MonoObject* value, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::SerializableObjectRef || mType == ScriptFieldType::SerializableObjectValue);
+
+		setValue(obj, (void*)value, arrayIdx);
+	}
+
+	MonoObject* ScriptSerializableFieldInfo::getSerializableObject(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::SerializableObjectRef || mType == ScriptFieldType::SerializableObjectValue);
+
+		return (MonoObject*)getValue(obj, arrayIdx);
+	}
+
+	RTTITypeBase* ScriptSerializableFieldInfo::getRTTIStatic()
+	{
+		return ScriptSerializableFieldInfoRTTI::instance();
+	}
+
+	RTTITypeBase* ScriptSerializableFieldInfo::getRTTI() const
+	{
+		return ScriptSerializableFieldInfo::getRTTIStatic();
+	}
+
+	bool ScriptSerializableFieldInfoPlain::isReferenceType() const
+	{
+		return (mType == ScriptFieldType::TextureRef || mType == ScriptFieldType::SpriteTextureRef || 
+			mType == ScriptFieldType::SceneObjectRef || mType == ScriptFieldType::ComponentRef || mType == ScriptFieldType::SerializableObjectRef);
+	}
+
+	CM::UINT32 ScriptSerializableFieldInfoPlain::getNumArrayElements(MonoObject* obj, CM::UINT32 dimension)
+	{
+		assert(false);
+
+		return 0;
+	}
+
+	void ScriptSerializableFieldInfoPlain::setNumArrayElements(MonoObject* obj, CM::UINT32 numElements, CM::UINT32 dimension, bool discardExisting)
+	{
+		assert(false);
+	}
+
+	void ScriptSerializableFieldInfoPlain::setValue(MonoObject* obj, void* val, CM::UINT32 arrayIdx)
+	{
+		assert(arrayIdx == 0);
+
+		mMonoField->setValue(obj, val);
+	}
+
+	void* ScriptSerializableFieldInfoPlain::getValue(MonoObject* obj, CM::UINT32 arrayIdx)
+	{
+		assert(arrayIdx == 0);
+
+		return mMonoField->getValue(obj);
+	}
+
+	RTTITypeBase* ScriptSerializableFieldInfoPlain::getRTTIStatic()
+	{
+		return ScriptSerializableFieldInfoPlainRTTI::instance();
+	}
+
+	RTTITypeBase* ScriptSerializableFieldInfoPlain::getRTTI() const
+	{
+		return ScriptSerializableFieldInfoPlain::getRTTIStatic();
+	}
+
+	ScriptSerializableFieldInfoArray::ScriptSerializableFieldInfoArray()
+		:mArrayDimensions(0)
+	{
+
+	}
+
+	CM::UINT32 ScriptSerializableFieldInfoArray::getNumArrayElements(MonoObject* obj, CM::UINT32 dimension)
+	{
+		if(dimension >= mArrayDimensions)
+			CM_EXCEPT(InvalidParametersException, "Invalid array dimension: " + toString(dimension) + ". Valid range is: [0, + " + toString(mArrayDimensions - 1) + "]");
+
+		MonoArray* array = reinterpret_cast<MonoArray*>(mMonoField->getValue(obj));
+		return (UINT32)mono_array_length(array);
+	}
+
+	void ScriptSerializableFieldInfoArray::setNumArrayElements(MonoObject* obj, CM::UINT32 numElements, CM::UINT32 dimension, bool discardExisting)
+	{
+		uint32_t lengths[1] = { numElements };
+
+		MonoArray* newArray = mono_array_new_full(MonoManager::instance().getDomain(), 
+			mMonoField->getType()->_getInternalClass(), (uintptr_t*)lengths, nullptr);
+
+		if(!discardExisting)
+		{
+			MonoArray* existingArray = reinterpret_cast<MonoArray*>(mMonoField->getValue(obj));
+			UINT32 existingArrayLength = (UINT32)mono_array_length(existingArray);
+
+			UINT32 elemsToCopy = std::min(existingArrayLength, numElements);
+			int32_t elemSize = mono_array_element_size(mMonoField->getType()->_getInternalClass());
+
+			for(UINT32 i = 0; i < elemsToCopy; i++)
+			{
+				void* existingValAddr = (void*)mono_array_addr_with_size(existingArray, elemSize, (uintptr_t)i);
+				void* newValAddr = (void*)mono_array_addr_with_size(newArray, elemSize, (uintptr_t)i);
+
+				memcpy(newValAddr, existingValAddr, elemSize);
+			}
+		}
+
+		mMonoField->setValue(obj, newArray);
+	}
+
+	void ScriptSerializableFieldInfoArray::setValue( MonoObject* obj, void* val, CM::UINT32 arrayIdx)
+	{
+		MonoArray* array = (MonoArray*)mMonoField->getValue(obj);
+		UINT32 elemSize = mono_array_element_size(mMonoField->getType()->_getInternalClass());
+
+		UINT32 numElems = (UINT32)mono_array_length(array);
+		assert(arrayIdx < numElems);
+
+		void* elemAddr = mono_array_addr_with_size(array, elemSize, arrayIdx);
+		memcpy(elemAddr, val, elemSize);
+	}
+
+	void* ScriptSerializableFieldInfoArray::getValue( MonoObject* obj, CM::UINT32 arrayIdx)
+	{
+		MonoArray* array = (MonoArray*)mMonoField->getValue(obj);
+		UINT32 elemSize = mono_array_element_size(mMonoField->getType()->_getInternalClass());
+
+		UINT32 numElems = (UINT32)mono_array_length(array);
+		assert(arrayIdx < numElems);
+
+		return mono_array_addr_with_size(array, elemSize, arrayIdx);
+	}
+
+	RTTITypeBase* ScriptSerializableFieldInfoArray::getRTTIStatic()
+	{
+		return ScriptSerializableFieldInfoArrayRTTI::instance();
+	}
+
+	RTTITypeBase* ScriptSerializableFieldInfoArray::getRTTI() const
+	{
+		return ScriptSerializableFieldInfoArray::getRTTIStatic();
+	}
+}