Browse Source

C# object serialization WIP

Marko Pintera 11 năm trước cách đây
mục cha
commit
be6adc683d
40 tập tin đã thay đổi với 915 bổ sung220 xóa
  1. 11 25
      GameObjectSerialization.txt
  2. 1 1
      MBansheeEngine/Component.cs
  3. 6 0
      MBansheeEngine/GameObject.cs
  4. 1 0
      MBansheeEngine/MBansheeEngine.csproj
  5. 7 1
      MBansheeEngine/SpriteTexture.cs
  6. 6 0
      MBansheeEngine/Texture2D.cs
  7. 0 1
      SBansheeEditor/Source/BsScriptEditorGUI.cpp
  8. 0 1
      SBansheeEditor/Source/BsScriptEditorWindow.cpp
  9. 56 35
      SBansheeEngine/Include/BsRuntimeScriptObjects.h
  10. 3 0
      SBansheeEngine/Include/BsScriptEnginePrerequisites.h
  11. 33 0
      SBansheeEngine/Include/BsScriptGameObjectManager.h
  12. 0 8
      SBansheeEngine/Include/BsScriptObject.h
  13. 6 0
      SBansheeEngine/Include/BsScriptResource.h
  14. 62 0
      SBansheeEngine/Include/BsScriptResourceManager.h
  15. 3 0
      SBansheeEngine/Include/BsScriptSpriteTexture.h
  16. 3 0
      SBansheeEngine/Include/BsScriptTexture2D.h
  17. 4 0
      SBansheeEngine/SBansheeEngine.vcxproj
  18. 12 0
      SBansheeEngine/SBansheeEngine.vcxproj.filters
  19. 564 119
      SBansheeEngine/Source/BsRuntimeScriptObjects.cpp
  20. 0 1
      SBansheeEngine/Source/BsScriptComponent.cpp
  21. 0 1
      SBansheeEngine/Source/BsScriptFont.cpp
  22. 0 1
      SBansheeEngine/Source/BsScriptGUIArea.cpp
  23. 0 1
      SBansheeEngine/Source/BsScriptGUIButton.cpp
  24. 0 1
      SBansheeEngine/Source/BsScriptGUIElementStateStyle.cpp
  25. 0 1
      SBansheeEngine/Source/BsScriptGUIElementStyle.cpp
  26. 0 1
      SBansheeEngine/Source/BsScriptGUIFixedSpace.cpp
  27. 0 1
      SBansheeEngine/Source/BsScriptGUIFlexibleSpace.cpp
  28. 0 1
      SBansheeEngine/Source/BsScriptGUIInputBox.cpp
  29. 0 1
      SBansheeEngine/Source/BsScriptGUILabel.cpp
  30. 0 1
      SBansheeEngine/Source/BsScriptGUILayout.cpp
  31. 0 1
      SBansheeEngine/Source/BsScriptGUIListBox.cpp
  32. 0 1
      SBansheeEngine/Source/BsScriptGUIScrollArea.cpp
  33. 0 1
      SBansheeEngine/Source/BsScriptGUITexture.cpp
  34. 0 1
      SBansheeEngine/Source/BsScriptGUIToggle.cpp
  35. 0 1
      SBansheeEngine/Source/BsScriptGUIToggleGroup.cpp
  36. 6 0
      SBansheeEngine/Source/BsScriptGameObjectManager.cpp
  37. 0 1
      SBansheeEngine/Source/BsScriptHString.cpp
  38. 125 0
      SBansheeEngine/Source/BsScriptResourceManager.cpp
  39. 3 6
      SBansheeEngine/Source/BsScriptSpriteTexture.cpp
  40. 3 6
      SBansheeEngine/Source/BsScriptTexture2D.cpp

+ 11 - 25
GameObjectSerialization.txt

@@ -4,24 +4,16 @@ TODO
  ---------------------------------------
  ---------------------------------------
  C# component serialization
  C# component serialization
 
 
- RuntimeScriptObjects
- - enumerateSerializable()
-   - Goes through all (non-C++) Components and non-Component classes marked with [Serializable]
-    - Using C++ it finds all fields in those classes. Fields and their references are stored in C++ classes.
-	  - Need to enumerate value type fields, or fields holding other [Serializable] structures, references to other Components, SceneObjects or Resources
-        - Plus arrays, and possibly C# List
-        - Considers attributes
-            - [Serialized] - Forces field to be serialized (If valid type)
-            - [NotSerialized] - Forced field not to be serialized
-            - By default all public members are serialized and private ones are not
-	  - Something like SerializableComponentInfo (per-component), SerializableObjectInfo(per-non-component), SerializablePlainField,
-	    SerializableArrayField, SerializableResourceField, SerializableGameObjectField, SerializableObjectField, etc.
- - Internally it holds a Map with name -> Serializable*Info mapping for every supported type
-   - User can query if type is supported or not, and retrieve the serialization info if needed
-   - Using the serialization info user can retrieve actual values from an instance easily
-   - Serializable*Info classes contain findField method that accepts a name and a type
-     - This is used for deserialization
- - Using Serializable*Info you can create a brand new instance of a Component or a [Serializable] non-component
+ TODO:
+  - Add support for generic Lists, and potentially dictionaries
+   - Be careful with current field array support, lists should probably be handled completely differently and shouldn't share that code
+ - Implement set/get methods for strings/resourceRefs/gameObjectRefs/serializableObjects
+ - Make SerializableObjectInfo IReflectable and create its RTTI
+ - In BsScriptEnginePlugin.cpp I create RuntimeScriptObjects class but never destroy it, for debug purposes. Remember to remove that.
+ - Need a class that will keep track of all instances of ScriptResource and ScriptGameObject
+   - Need to update existing createInstance methods
+ - Need a way to create SerializableObject - likely createInstance() method in SerializableObjectField
+
 
 
 ScriptComponent
 ScriptComponent
  - C++ half of the C# component
  - C++ half of the C# component
@@ -44,6 +36,7 @@ ScriptComponentRTTI
     - Returns FieldId -> HGameObject
     - Returns FieldId -> HGameObject
   - GetResourceFields
   - GetResourceFields
     - Returns FieldID -> HResource
     - Returns FieldID -> HResource
+ - Make sure to scan all base classes as well
  - When serializing all those arrays are prepared in OnSerializatioStarted
  - When serializing all those arrays are prepared in OnSerializatioStarted
  - When deserializing they are send to the object in OnDeserializationEnded
  - When deserializing they are send to the object in OnDeserializationEnded
    - However existance for the fields is first checked by getting new copy of SerializableComponentInfo and seeing
    - However existance for the fields is first checked by getting new copy of SerializableComponentInfo and seeing
@@ -77,13 +70,6 @@ TODO - Possibly flesh out and example with Resources or Gameobject references a
 	     so hopefully this will only matter when enumerating all components which shouldn't be during performance
 	     so hopefully this will only matter when enumerating all components which shouldn't be during performance
 		 critical moments.
 		 critical moments.
 
 
-Inspector
- - RuntimeScriptObjects::enumerateInspectable creates a list of all inspectable classes (Components and others marked with [Serializable]
-  - Returns a hierarchy very similar to Serializable*Info and their children (Likely re-use the same hierarchy but with different flags?)
-  - This information is then used to generate needed fields
-
- - Importer inspectors are special and custom-built and shouldn't be considered here
-
 TODO - When reloading scripts how to handle restoring references?
 TODO - When reloading scripts how to handle restoring references?
 TODO - When I destroy a Component, how will I refresh the inspector to let it know that something has changed
 TODO - When I destroy a Component, how will I refresh the inspector to let it know that something has changed
   - Can happen from C# and C++
   - Can happen from C# and C++

+ 1 - 1
MBansheeEngine/Component.cs

@@ -3,7 +3,7 @@ using System.Runtime.CompilerServices;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-    public class Component : ScriptObject
+    public class Component : GameObject
     {
     {
         public Component()
         public Component()
         {
         {

+ 6 - 0
MBansheeEngine/GameObject.cs

@@ -0,0 +1,6 @@
+namespace BansheeEngine
+{
+    public class GameObject : ScriptObject
+    {
+    }
+}

+ 1 - 0
MBansheeEngine/MBansheeEngine.csproj

@@ -47,6 +47,7 @@
     <Compile Include="Component.cs" />
     <Compile Include="Component.cs" />
     <Compile Include="DbgComponent.cs" />
     <Compile Include="DbgComponent.cs" />
     <Compile Include="Font.cs" />
     <Compile Include="Font.cs" />
+    <Compile Include="GameObject.cs" />
     <Compile Include="GUI\GUI.cs" />
     <Compile Include="GUI\GUI.cs" />
     <Compile Include="GUI\GUIArea.cs" />
     <Compile Include="GUI\GUIArea.cs" />
     <Compile Include="GUI\GUIBase.cs" />
     <Compile Include="GUI\GUIBase.cs" />

+ 7 - 1
MBansheeEngine/SpriteTexture.cs

@@ -4,7 +4,13 @@ namespace BansheeEngine
 {
 {
     public sealed class SpriteTexture : Resource // TODO - Dummy class
     public sealed class SpriteTexture : Resource // TODO - Dummy class
     {
     {
-        public SpriteTexture()
+        // For internal use by the runtime
+        private SpriteTexture()
+        {
+            
+        }
+
+        public SpriteTexture(int dummyParam)
         {
         {
             Internal_CreateInstance(this);
             Internal_CreateInstance(this);
         }
         }

+ 6 - 0
MBansheeEngine/Texture2D.cs

@@ -5,6 +5,12 @@ namespace BansheeEngine
 {
 {
     public sealed class Texture2D : Resource
     public sealed class Texture2D : Resource
     {
     {
+        // For internal use by the runtime
+        private Texture2D()
+        {
+
+        }
+
         public Texture2D(TextureFormat format, int width, int height, bool hasMipmaps = false, bool gammaCorrection = false)
         public Texture2D(TextureFormat format, int width, int height, bool hasMipmaps = false, bool gammaCorrection = false)
         {
         {
             Internal_CreateInstance(this, format, width, height, hasMipmaps, gammaCorrection);
             Internal_CreateInstance(this, format, width, height, hasMipmaps, gammaCorrection);

+ 0 - 1
SBansheeEditor/Source/BsScriptEditorGUI.cpp

@@ -46,7 +46,6 @@ namespace BansheeEditor
 
 
 	void ScriptEditorGUI::internal_destroyInstance(ScriptEditorGUI* nativeInstance)
 	void ScriptEditorGUI::internal_destroyInstance(ScriptEditorGUI* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 
 

+ 0 - 1
SBansheeEditor/Source/BsScriptEditorWindow.cpp

@@ -69,7 +69,6 @@ namespace BansheeEditor
 		assert(iterFind == OpenScriptEditorWindows.end());
 		assert(iterFind == OpenScriptEditorWindows.end());
 #endif
 #endif
 
 
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 
 

+ 56 - 35
SBansheeEngine/Include/BsRuntimeScriptObjects.h

@@ -2,6 +2,7 @@
 
 
 #include "BsScriptEnginePrerequisites.h"
 #include "BsScriptEnginePrerequisites.h"
 #include "CmModule.h"
 #include "CmModule.h"
+#include <mono/jit/jit.h>
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -20,9 +21,12 @@ namespace BansheeEngine
 		Float,
 		Float,
 		Double,
 		Double,
 		String,
 		String,
-		SerializableObject,
-		ResourceRef,
-		GameObjectRef,
+		SerializableObjectValue,
+		SerializableObjectRef,
+		TextureRef,
+		SpriteTextureRef,
+		SceneObjectRef,
+		ComponentRef,
 		Other
 		Other
 	};
 	};
 
 
@@ -48,55 +52,71 @@ namespace BansheeEngine
 
 
 		MonoField* mMonoField;
 		MonoField* mMonoField;
 
 
-		CM::UINT32 getNumArrayElement(MonoObject* obj);
-		void setNumArrayElements(MonoObject* obj, CM::UINT32 numElements);
+		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);
 		void setU8(MonoObject* obj, CM::UINT8 val, CM::UINT32 arrayIdx = 0);
-		CM::UINT8 getU8(MonoObject* obj,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 setI8(MonoObject* obj,CM::INT8 val, CM::UINT32 arrayIdx = 0);
-		CM::INT8 getI8(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 setU16(MonoObject* obj,CM::UINT16 val, CM::UINT32 arrayIdx = 0);
-		CM::UINT16 getU16(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 setI16(MonoObject* obj,CM::INT16 val, CM::UINT32 arrayIdx = 0);
-		CM::INT16 getI16(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 setU32(MonoObject* obj,CM::UINT32 val, CM::UINT32 arrayIdx = 0);
-		CM::UINT32 getU32(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 setI32(MonoObject* obj,CM::INT32 val, CM::UINT32 arrayIdx = 0);
-		CM::INT32 getI32(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 setU64(MonoObject* obj,CM::UINT64 val, CM::UINT32 arrayIdx = 0);
-		CM::UINT64 getU64(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 setI64(MonoObject* obj,CM::INT64 val, CM::UINT32 arrayIdx = 0);
-		CM::INT64 getI64(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 setBool(MonoObject* obj,bool val, CM::UINT32 arrayIdx = 0);
-		bool getBool(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 setChar(MonoObject* obj,wchar_t val, CM::UINT32 arrayIdx = 0);
-		wchar_t getChar(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 setFloat(MonoObject* obj,float val, CM::UINT32 arrayIdx = 0);
-		float getFloat(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 setDouble(MonoObject* obj,double val, CM::UINT32 arrayIdx = 0);
-		double getDouble(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 setString(MonoObject* obj,const CM::WString& val, CM::UINT32 arrayIdx = 0);
-		CM::WString getString(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 setResource(MonoObject* obj,const CM::HResource& resource, CM::UINT32 arrayIdx = 0);
-		CM::HResource getResource(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 setGameObject(MonoObject* obj,const CM::HGameObject& gameObject, CM::UINT32 arrayIdx = 0);
-		CM::HGameObject getGameObject(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);
 
 
-		// TODO - Set/Get for SerializableObject
+		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
 	struct BS_SCR_BE_EXPORT SerializableObjectInfo
@@ -130,6 +150,7 @@ namespace BansheeEngine
 
 
 		void refreshScriptObjects(const CM::String& assemblyName);
 		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<SerializableObjectInfo>& outInfo);
+		bool hasSerializableObjectInfo(const CM::String& ns, const CM::String& typeName);
 	private:
 	private:
 		CM::UnorderedMap<CM::String, std::shared_ptr<SerializableAssemblyInfo>>::type mAssemblyInfos;
 		CM::UnorderedMap<CM::String, std::shared_ptr<SerializableAssemblyInfo>>::type mAssemblyInfos;
 
 

+ 3 - 0
SBansheeEngine/Include/BsScriptEnginePrerequisites.h

@@ -20,6 +20,8 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+	class ScriptResourceManager;
+	class ScriptResource;
 	class ScriptFont;
 	class ScriptFont;
 	class ScriptSpriteTexture;
 	class ScriptSpriteTexture;
 	class ScriptTexture2D;
 	class ScriptTexture2D;
@@ -29,6 +31,7 @@ namespace BansheeEngine
 	class ScriptGUIArea;
 	class ScriptGUIArea;
 	class ScriptGUILayout;
 	class ScriptGUILayout;
 	class ScriptGUILabel;
 	class ScriptGUILabel;
+	class ScriptGameObject;
 	class ScriptComponent;
 	class ScriptComponent;
 	class ManagedComponent;
 	class ManagedComponent;
 
 

+ 33 - 0
SBansheeEngine/Include/BsScriptGameObjectManager.h

@@ -0,0 +1,33 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "CmModule.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ScriptGameObjectManager : public CM::Module<ScriptGameObjectManager>
+	{
+	public:
+		// TODO - Add create methods
+
+		/**
+		 * @note Returns nullptr if script SceneObject doesn't exist.
+		 */
+		//ScriptSceneObject* getScriptSceneObject(CM::UINT64 id);
+
+		/**
+		 * @note Returns nullptr if script Component doesn't exist.
+		 */
+		//ScriptComponent* getScriptComponent(CM::UINT64 id);
+
+		/**
+		 * @note Returns nullptr if script GameObject doesn't exist.
+		 */
+		//ScriptGameObject* getScriptGameObject(CM::UINT64 id);
+
+		//void destroyScriptGameObject(ScriptGameObject* gameObject);
+
+	private:
+		CM::UnorderedMap<CM::UINT64, ScriptGameObject*>::type mScriptResources;
+	};
+}

+ 0 - 8
SBansheeEngine/Include/BsScriptObject.h

@@ -63,14 +63,6 @@ namespace BansheeEngine
 			mManagedInstance = instance;
 			mManagedInstance = instance;
 		}
 		}
 
 
-		void destroyInstance()
-		{
-			if(mManagedInstance == nullptr)
-				return;
-
-			mManagedInstance = nullptr;
-		}
-
 		template <class Type2>
 		template <class Type2>
 		static void throwIfInstancesDontMatch(ScriptObject<Type2>* lhs, void* rhs)
 		static void throwIfInstancesDontMatch(ScriptObject<Type2>* lhs, void* rhs)
 		{
 		{

+ 6 - 0
SBansheeEngine/Include/BsScriptResource.h

@@ -9,5 +9,11 @@ namespace BansheeEngine
 	public:
 	public:
 		virtual CM::HResource getNativeHandle() const = 0;
 		virtual CM::HResource getNativeHandle() const = 0;
 		virtual void setNativeHandle(const CM::HResource& resource) = 0;
 		virtual void setNativeHandle(const CM::HResource& resource) = 0;
+
+	protected:
+		friend class ScriptResourceManager;
+
+		ScriptResource() {}
+		virtual ~ScriptResource() {}
 	};
 	};
 }
 }

+ 62 - 0
SBansheeEngine/Include/BsScriptResourceManager.h

@@ -0,0 +1,62 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "CmModule.h"
+#include <mono/jit/jit.h>
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ScriptResourceManager : public CM::Module<ScriptResourceManager>
+	{
+	public:
+		ScriptResourceManager();
+
+		/**
+		 * @note Throws an exception if resource for the handle already exists.
+		 * 		 Creates a new managed instance of the object.
+		 */
+		ScriptTexture2D* createScriptTexture(const CM::HTexture& resourceHandle);
+
+		/**
+		 * @note Throws an exception if resource for the handle already exists.
+		 * 		 Initializes the ScriptResource with an existing managed instance.
+		 */
+		ScriptTexture2D* createScriptTexture(MonoObject* existingInstance, const CM::HTexture& resourceHandle);
+
+		/**
+		 * @note Throws an exception if resource for the handle already exists.
+		 * 		 Creates a new managed instance of the object.
+		 */
+		ScriptSpriteTexture* createScriptSpriteTexture(const HSpriteTexture& resourceHandle);
+
+		/**
+		 * @note Throws an exception if resource for the handle already exists.
+		 * 		 Initializes the ScriptResource with an existing managed instance.
+		 */
+		ScriptSpriteTexture* createScriptSpriteTexture(MonoObject* existingInstance, const HSpriteTexture& resourceHandle);
+
+		/**
+		 * @note Returns nullptr if script resource doesn't exist.
+		 */
+		ScriptTexture2D* getScriptTexture(const CM::HTexture& resourceHandle);
+
+		/**
+		 * @note Returns nullptr if script resource doesn't exist.
+		 */
+		ScriptSpriteTexture* getScriptSpriteTexture(const HSpriteTexture& resourceHandle);
+
+		/**
+		 * @note Returns nullptr if script resource doesn't exist.
+		 */
+		ScriptResource* getScriptResource(const CM::HResource& resourceHandle);
+
+		void destroyScriptResource(ScriptResource* resource);
+
+	private:
+		CM::UnorderedMap<CM::String, ScriptResource*>::type mScriptResources;
+		MonoClass* mTextureClass;
+		MonoClass* mSpriteTextureClass;
+
+		void throwExceptionIfInvalidOrDuplicate(const CM::String& uuid) const;
+	};
+}

+ 3 - 0
SBansheeEngine/Include/BsScriptSpriteTexture.h

@@ -17,12 +17,15 @@ namespace BansheeEngine
 		void setNativeHandle(const CM::HResource& resource);
 		void setNativeHandle(const CM::HResource& resource);
 
 
 	private:
 	private:
+		friend class ScriptResourceManager;
+
 		static void internal_createInstance(MonoObject* instance);
 		static void internal_createInstance(MonoObject* instance);
 		static void internal_destroyInstance(ScriptSpriteTexture* nativeInstance);
 		static void internal_destroyInstance(ScriptSpriteTexture* nativeInstance);
 
 
 		static void initRuntimeData();
 		static void initRuntimeData();
 
 
 		ScriptSpriteTexture(const HSpriteTexture& texture);
 		ScriptSpriteTexture(const HSpriteTexture& texture);
+		~ScriptSpriteTexture() {}
 
 
 		HSpriteTexture mTexture;
 		HSpriteTexture mTexture;
 	};
 	};

+ 3 - 0
SBansheeEngine/Include/BsScriptTexture2D.h

@@ -17,12 +17,15 @@ namespace BansheeEngine
 		CM::HResource getNativeHandle() const { return mTexture; }
 		CM::HResource getNativeHandle() const { return mTexture; }
 		void setNativeHandle(const CM::HResource& resource);
 		void setNativeHandle(const CM::HResource& resource);
 	private:
 	private:
+		friend class ScriptResourceManager;
+
 		static void internal_createInstance(MonoObject* instance, CM::UINT32 format, CM::UINT32 width, CM::UINT32 height, bool hasMipmaps, bool gammaCorrection);
 		static void internal_createInstance(MonoObject* instance, CM::UINT32 format, CM::UINT32 width, CM::UINT32 height, bool hasMipmaps, bool gammaCorrection);
 		static void internal_destroyInstance(ScriptTexture2D* nativeInstance);
 		static void internal_destroyInstance(ScriptTexture2D* nativeInstance);
 
 
 		static void initRuntimeData();
 		static void initRuntimeData();
 
 
 		ScriptTexture2D(const CM::HTexture& texture);
 		ScriptTexture2D(const CM::HTexture& texture);
+		~ScriptTexture2D() {}
 
 
 		CM::HTexture mTexture;
 		CM::HTexture mTexture;
 	};
 	};

+ 4 - 0
SBansheeEngine/SBansheeEngine.vcxproj

@@ -232,6 +232,7 @@
     <ClInclude Include="Include\BsScriptComponent.h" />
     <ClInclude Include="Include\BsScriptComponent.h" />
     <ClInclude Include="Include\BsScriptEnginePrerequisites.h" />
     <ClInclude Include="Include\BsScriptEnginePrerequisites.h" />
     <ClInclude Include="Include\BsScriptGameObject.h" />
     <ClInclude Include="Include\BsScriptGameObject.h" />
+    <ClInclude Include="Include\BsScriptGameObjectManager.h" />
     <ClInclude Include="Include\BsScriptGUIButton.h" />
     <ClInclude Include="Include\BsScriptGUIButton.h" />
     <ClInclude Include="Include\BsScriptGUIFixedSpace.h" />
     <ClInclude Include="Include\BsScriptGUIFixedSpace.h" />
     <ClInclude Include="Include\BsScriptGUIFlexibleSpace.h" />
     <ClInclude Include="Include\BsScriptGUIFlexibleSpace.h" />
@@ -252,6 +253,7 @@
     <ClInclude Include="Include\BsScriptMacros.h" />
     <ClInclude Include="Include\BsScriptMacros.h" />
     <ClInclude Include="Include\BsScriptObject.h" />
     <ClInclude Include="Include\BsScriptObject.h" />
     <ClInclude Include="Include\BsScriptResource.h" />
     <ClInclude Include="Include\BsScriptResource.h" />
+    <ClInclude Include="Include\BsScriptResourceManager.h" />
     <ClInclude Include="Include\BsScriptSpriteTexture.h" />
     <ClInclude Include="Include\BsScriptSpriteTexture.h" />
     <ClInclude Include="Include\BsScriptStringTable.h" />
     <ClInclude Include="Include\BsScriptStringTable.h" />
     <ClInclude Include="Include\BsScriptTexture2D.h" />
     <ClInclude Include="Include\BsScriptTexture2D.h" />
@@ -262,6 +264,7 @@
     <ClCompile Include="Source\BsRuntimeScriptObjects.cpp" />
     <ClCompile Include="Source\BsRuntimeScriptObjects.cpp" />
     <ClCompile Include="Source\BsScriptComponent.cpp" />
     <ClCompile Include="Source\BsScriptComponent.cpp" />
     <ClCompile Include="Source\BsScriptEnginePlugin.cpp" />
     <ClCompile Include="Source\BsScriptEnginePlugin.cpp" />
+    <ClCompile Include="Source\BsScriptGameObjectManager.cpp" />
     <ClCompile Include="Source\BsScriptGUIButton.cpp" />
     <ClCompile Include="Source\BsScriptGUIButton.cpp" />
     <ClCompile Include="Source\BsScriptGUIFixedSpace.cpp" />
     <ClCompile Include="Source\BsScriptGUIFixedSpace.cpp" />
     <ClCompile Include="Source\BsScriptGUIFlexibleSpace.cpp" />
     <ClCompile Include="Source\BsScriptGUIFlexibleSpace.cpp" />
@@ -279,6 +282,7 @@
     <ClCompile Include="Source\BsScriptGUIToggleGroup.cpp" />
     <ClCompile Include="Source\BsScriptGUIToggleGroup.cpp" />
     <ClCompile Include="Source\BsScriptHString.cpp" />
     <ClCompile Include="Source\BsScriptHString.cpp" />
     <ClCompile Include="Source\BsScriptGUIInputBox.cpp" />
     <ClCompile Include="Source\BsScriptGUIInputBox.cpp" />
+    <ClCompile Include="Source\BsScriptResourceManager.cpp" />
     <ClCompile Include="Source\BsScriptSpriteTexture.cpp" />
     <ClCompile Include="Source\BsScriptSpriteTexture.cpp" />
     <ClCompile Include="Source\BsScriptStringTable.cpp" />
     <ClCompile Include="Source\BsScriptStringTable.cpp" />
     <ClCompile Include="Source\BsScriptTexture2D.cpp" />
     <ClCompile Include="Source\BsScriptTexture2D.cpp" />

+ 12 - 0
SBansheeEngine/SBansheeEngine.vcxproj.filters

@@ -105,6 +105,12 @@
     <ClInclude Include="Include\BsScriptGameObject.h">
     <ClInclude Include="Include\BsScriptGameObject.h">
       <Filter>Header Files</Filter>
       <Filter>Header Files</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\BsScriptResourceManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsScriptGameObjectManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsScriptTexture2D.cpp">
     <ClCompile Include="Source\BsScriptTexture2D.cpp">
@@ -182,5 +188,11 @@
     <ClCompile Include="Source\BsScriptComponent.cpp">
     <ClCompile Include="Source\BsScriptComponent.cpp">
       <Filter>Source Files</Filter>
       <Filter>Source Files</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\BsScriptResourceManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsScriptGameObjectManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 564 - 119
SBansheeEngine/Source/BsRuntimeScriptObjects.cpp

@@ -1,8 +1,13 @@
 #include "BsRuntimeScriptObjects.h"
 #include "BsRuntimeScriptObjects.h"
+#include "BsScriptResourceManager.h"
+#include "BsScriptGameObjectManager.h"
 #include "BsMonoManager.h"
 #include "BsMonoManager.h"
 #include "BsMonoAssembly.h"
 #include "BsMonoAssembly.h"
 #include "BsMonoClass.h"
 #include "BsMonoClass.h"
 #include "BsMonoField.h"
 #include "BsMonoField.h"
+#include "BsMonoUtil.h"
+#include "BsScriptTexture2D.h"
+#include "BsScriptSpriteTexture.h"
 
 
 using namespace CamelotFramework;
 using namespace CamelotFramework;
 
 
@@ -33,6 +38,405 @@ namespace BansheeEngine
 
 
 	}
 	}
 
 
+	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)
+	{
+		if(resource == nullptr)
+		{
+			setValue(obj, nullptr, arrayIdx);
+		}
+		else
+		{
+			assert(mType == ScriptFieldType::SpriteTextureRef);
+
+			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);
+
+		// TODO
+	}
+
+	HSceneObject SerializableFieldInfo::getSceneObject(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::SceneObjectRef);
+
+		// TODO
+		return HSceneObject();
+	}
+
+	void SerializableFieldInfo::setComponent(MonoObject* obj, const HComponent& component, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::ComponentRef);
+
+		// TODO
+	}
+
+	HComponent SerializableFieldInfo::getComponent(MonoObject* obj, UINT32 arrayIdx)
+	{
+		assert(mType == ScriptFieldType::ComponentRef);
+
+		// TODO
+		return HComponent();
+	}
+
+
+	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()
 	RuntimeScriptObjects::~RuntimeScriptObjects()
 	{
 	{
 
 
@@ -59,10 +463,26 @@ namespace BansheeEngine
 		if(nonSerializedAttribute == nullptr)
 		if(nonSerializedAttribute == nullptr)
 			CM_EXCEPT(InvalidStateException, "Cannot find NonSerializedAttribute managed class.");
 			CM_EXCEPT(InvalidStateException, "Cannot find NonSerializedAttribute managed class.");
 
 
+		MonoClass* genericListClass = mscorlib->getClass("System", "List`1");
+		if(genericListClass == nullptr)
+			CM_EXCEPT(InvalidStateException, "Cannot find List<T> managed class.");
+
 		MonoClass* componentClass = bansheeEngineAssembly->getClass("BansheeEngine", "Component");
 		MonoClass* componentClass = bansheeEngineAssembly->getClass("BansheeEngine", "Component");
 		if(componentClass == nullptr)
 		if(componentClass == nullptr)
 			CM_EXCEPT(InvalidStateException, "Cannot find Component managed class.");
 			CM_EXCEPT(InvalidStateException, "Cannot find Component managed class.");
 
 
+		MonoClass* sceneObjectClass = bansheeEngineAssembly->getClass("BansheeEngine", "SceneObject");
+		if(sceneObjectClass == nullptr)
+			CM_EXCEPT(InvalidStateException, "Cannot find SceneObject managed class.");
+
+		MonoClass* textureClass = bansheeEngineAssembly->getClass("BansheeEngine", "Texture2D");
+		if(textureClass == nullptr)
+			CM_EXCEPT(InvalidStateException, "Cannot find Texture2D managed class.");
+
+		MonoClass* spriteTextureClass = bansheeEngineAssembly->getClass("BansheeEngine", "SpriteTexture");
+		if(spriteTextureClass == nullptr)
+			CM_EXCEPT(InvalidStateException, "Cannot find SpriteTexture managed class.");
+
 		MonoClass* serializeFieldAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "SerializeField");
 		MonoClass* serializeFieldAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "SerializeField");
 		if(serializeFieldAttribute == nullptr)
 		if(serializeFieldAttribute == nullptr)
 			CM_EXCEPT(InvalidStateException, "Cannot find SerializeField managed class.");
 			CM_EXCEPT(InvalidStateException, "Cannot find SerializeField managed class.");
@@ -70,7 +490,7 @@ namespace BansheeEngine
 		MonoClass* hideInInspectorAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "HideInInspector");
 		MonoClass* hideInInspectorAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "HideInInspector");
 		if(hideInInspectorAttribute == nullptr)
 		if(hideInInspectorAttribute == nullptr)
 			CM_EXCEPT(InvalidStateException, "Cannot find HideInInspector managed class.");
 			CM_EXCEPT(InvalidStateException, "Cannot find HideInInspector managed class.");
-
+		
 		// Process all classes and fields
 		// Process all classes and fields
 		CM::UINT32 mUniqueTypeId = 1;
 		CM::UINT32 mUniqueTypeId = 1;
 
 
@@ -81,8 +501,8 @@ namespace BansheeEngine
 		std::shared_ptr<SerializableAssemblyInfo> assemblyInfo = cm_shared_ptr<SerializableAssemblyInfo>();
 		std::shared_ptr<SerializableAssemblyInfo> assemblyInfo = cm_shared_ptr<SerializableAssemblyInfo>();
 		mAssemblyInfos[assemblyName] = assemblyInfo;
 		mAssemblyInfos[assemblyName] = assemblyInfo;
 
 
+		// Populate class data
 		const Vector<MonoClass*>::type& allClasses = curAssembly->getAllClasses();
 		const Vector<MonoClass*>::type& allClasses = curAssembly->getAllClasses();
-
 		for(auto& curClass : allClasses)
 		for(auto& curClass : allClasses)
 		{
 		{
 			if((curClass->isSubClassOf(componentClass) || curClass->hasAttribute(serializableAttribute)) && curClass != componentClass)
 			if((curClass->isSubClassOf(componentClass) || curClass->hasAttribute(serializableAttribute)) && curClass != componentClass)
@@ -94,122 +514,148 @@ namespace BansheeEngine
 				objInfo->mNamespace = curClass->getNamespace();
 				objInfo->mNamespace = curClass->getNamespace();
 				objInfo->mMonoClass = curClass;
 				objInfo->mMonoClass = curClass;
 
 
-				::MonoClass* baseClass = mono_class_get_parent(curClass->_getInternalClass());
-				if(baseClass != nullptr)
-				{
-					String dbgName = mono_class_get_name(baseClass);
-				}
-
 				String fullTypeName = objInfo->mNamespace + "." + objInfo->mTypeName;
 				String fullTypeName = objInfo->mNamespace + "." + objInfo->mTypeName;
 				assemblyInfo->mTypeNameToId[fullTypeName] = objInfo->mTypeId;
 				assemblyInfo->mTypeNameToId[fullTypeName] = objInfo->mTypeId;
 				assemblyInfo->mObjectInfos[objInfo->mTypeId] = objInfo;
 				assemblyInfo->mObjectInfos[objInfo->mTypeId] = objInfo;
+			}
+		}
+
+		// Populate field data
+		for(auto& curClassInfo : assemblyInfo->mObjectInfos)
+		{
+			std::shared_ptr<SerializableObjectInfo> objInfo = curClassInfo.second;
 
 
-				CM::UINT32 mUniqueFieldId = 1;
-				const CM::Vector<MonoField*>::type& fields = curClass->getAllFields();
+			String fullTypeName = objInfo->mNamespace + "." + objInfo->mTypeName;
+			assemblyInfo->mTypeNameToId[fullTypeName] = objInfo->mTypeId;
+			assemblyInfo->mObjectInfos[objInfo->mTypeId] = objInfo;
 
 
-				for(auto& field : fields)
+			CM::UINT32 mUniqueFieldId = 1;
+			const CM::Vector<MonoField*>::type& fields = objInfo->mMonoClass->getAllFields();
+
+			for(auto& field : fields)
+			{
+				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
+				bool isSupportedType = true;
+				if(monoPrimitiveType == MONO_TYPE_ARRAY) 
 				{
 				{
-					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();
-					
-					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
-					bool isSupportedType = true;
-					if(monoPrimitiveType == MONO_TYPE_ARRAY) 
+					::MonoClass* elementClass = mono_class_get_element_class(fieldType->_getInternalClass());
+					if(elementClass != nullptr)
+					{
+						monoType = mono_class_get_type(elementClass);
+						monoPrimitiveType = mono_type_get_type(monoType);
+
+						::MonoClass* elementClass = mono_type_get_class(monoType);
+						String elementNs = mono_class_get_namespace(elementClass);
+						String elementTypeName = mono_class_get_name(elementClass);
+
+						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
+
+				//  Determine field type
+				switch(monoPrimitiveType) // TODO - If array I need to get underlying type
+				{
+				case MONO_TYPE_BOOLEAN:
+					fieldInfo->mType = ScriptFieldType::Bool;
+					break;
+				case MONO_TYPE_CHAR:
+					fieldInfo->mType = ScriptFieldType::Char;
+					break;
+				case MONO_TYPE_I1:
+					fieldInfo->mType = ScriptFieldType::I8;
+					break;
+				case MONO_TYPE_U1:
+					fieldInfo->mType = ScriptFieldType::U8;
+					break;
+				case MONO_TYPE_I2:
+					fieldInfo->mType = ScriptFieldType::I16;
+					break;
+				case MONO_TYPE_U2:
+					fieldInfo->mType = ScriptFieldType::U16;
+					break;
+				case MONO_TYPE_I4:
+					fieldInfo->mType = ScriptFieldType::I32;
+					break;
+				case MONO_TYPE_U4:
+					fieldInfo->mType = ScriptFieldType::U32;
+					break;
+				case MONO_TYPE_I8:
+					fieldInfo->mType = ScriptFieldType::U64;
+					break;
+				case MONO_TYPE_U8:
+					fieldInfo->mType = ScriptFieldType::U64;
+					break;
+				case MONO_TYPE_STRING:
+					fieldInfo->mType = ScriptFieldType::String;
+					break;
+				case MONO_TYPE_R4:
+					fieldInfo->mType = ScriptFieldType::Float;
+					break;
+				case MONO_TYPE_R8:
+					fieldInfo->mType = ScriptFieldType::Double;
+					break;
+				case MONO_TYPE_CLASS:
+					if(fieldElementClass->isSubClassOf(textureClass))
+						fieldInfo->mType = ScriptFieldType::TextureRef;
+					else if(fieldElementClass->isSubClassOf(spriteTextureClass))
+						fieldInfo->mType = ScriptFieldType::SpriteTextureRef;
+					else if(fieldElementClass->isSubClassOf(sceneObjectClass))
+						fieldInfo->mType = ScriptFieldType::SceneObjectRef;
+					else if(fieldElementClass->isSubClassOf(componentClass))
+						fieldInfo->mType = ScriptFieldType::ComponentRef;
+					else
 					{
 					{
-						::MonoClass* elementClass = mono_class_get_element_class(fieldType->_getInternalClass());
-						if(elementClass != nullptr)
-						{
-							monoType = mono_class_get_type(elementClass);
-							monoPrimitiveType = mono_type_get_type(monoType);
-						}
-
-						fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Array);
+						if(hasSerializableObjectInfo(fieldElementClass->getNamespace(), fieldElementClass->getTypeName()))
+							fieldInfo->mType = ScriptFieldType::SerializableObjectRef;
 					}
 					}
-					// TODO - Also check for List and get its generic primitive
 
 
-					//  Determine field type
-					switch(monoPrimitiveType) // TODO - If array I need to get underlying type
+					break;
+				case MONO_TYPE_VALUETYPE:
+					if(hasSerializableObjectInfo(fieldElementClass->getNamespace(), fieldElementClass->getTypeName()))
+						fieldInfo->mType = ScriptFieldType::SerializableObjectValue;
+
+					break;
+				}
+
+				if(fieldInfo->mType != ScriptFieldType::Other)
+				{
+					MonoFieldVisibility visibility = field->getVisibility();
+					if(visibility == MonoFieldVisibility::Public)
 					{
 					{
-					case MONO_TYPE_BOOLEAN:
-						fieldInfo->mType = ScriptFieldType::Bool;
-						break;
-					case MONO_TYPE_CHAR:
-						fieldInfo->mType = ScriptFieldType::Char;
-						break;
-					case MONO_TYPE_I1:
-						fieldInfo->mType = ScriptFieldType::I8;
-						break;
-					case MONO_TYPE_U1:
-						fieldInfo->mType = ScriptFieldType::U8;
-						break;
-					case MONO_TYPE_I2:
-						fieldInfo->mType = ScriptFieldType::I16;
-						break;
-					case MONO_TYPE_U2:
-						fieldInfo->mType = ScriptFieldType::U16;
-						break;
-					case MONO_TYPE_I4:
-						fieldInfo->mType = ScriptFieldType::I32;
-						break;
-					case MONO_TYPE_U4:
-						fieldInfo->mType = ScriptFieldType::U32;
-						break;
-					case MONO_TYPE_I8:
-						fieldInfo->mType = ScriptFieldType::U64;
-						break;
-					case MONO_TYPE_U8:
-						fieldInfo->mType = ScriptFieldType::U64;
-						break;
-					case MONO_TYPE_STRING:
-						fieldInfo->mType = ScriptFieldType::String;
-						break;
-					case MONO_TYPE_R4:
-						fieldInfo->mType = ScriptFieldType::Float;
-						break;
-					case MONO_TYPE_R8:
-						fieldInfo->mType = ScriptFieldType::Double;
-						break;
-					case MONO_TYPE_CLASS:
-						// TODO - Check for Resource or GameObject ref, or SerializableObject
-						break;
-					case MONO_TYPE_VALUETYPE:
-						// TODO - Check for SerializableObject
-						break;
+						if(!field->hasAttribute(nonSerializedAttribute))
+							fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Serializable);
+
+						if(!field->hasAttribute(hideInInspectorAttribute))
+							fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Inspectable);
 					}
 					}
-					
-					if(fieldInfo->mType != ScriptFieldType::Other)
+					else
 					{
 					{
-						MonoFieldVisibility visibility = field->getVisibility();
-						if(visibility == MonoFieldVisibility::Public)
-						{
-							if(!field->hasAttribute(nonSerializedAttribute))
-								fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Serializable);
-
-							if(!field->hasAttribute(hideInInspectorAttribute))
-								fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Inspectable);
-						}
-						else
-						{
-							if(field->hasAttribute(serializeFieldAttribute))
-								fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Serializable);
-						}
+						if(field->hasAttribute(serializeFieldAttribute))
+							fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Serializable);
 					}
 					}
-
-					objInfo->mFieldNameToId[fieldInfo->mName] = fieldInfo->mFieldId;
-					objInfo->mFields[fieldInfo->mFieldId] = fieldInfo;
 				}
 				}
+
+				objInfo->mFieldNameToId[fieldInfo->mName] = fieldInfo->mFieldId;
+				objInfo->mFields[fieldInfo->mFieldId] = fieldInfo;
 			}
 			}
 		}
 		}
 
 
@@ -231,20 +677,6 @@ namespace BansheeEngine
 				base = base->getBaseClass();
 				base = base->getBaseClass();
 			}
 			}
 		}
 		}
-	
-		// TODO - How to handle arrays and/or Lists (or collections in general?)
-
-		// TODO - In BsScriptEnginePlugin.cpp I create RuntimeScriptObjects class but never destroy it, for debug purposes. Remember to remove that.
-
-		// TODO - Figure our field type (primitive, gameobject ref, etc.) - Should I do this here or while serializing? Probably here.
-		//    - Add easy way to modify those fields (depending on their type) - Maybe make them virtual
-		//  Detect field type:
-		//   - Primitive - straightforward just check for primitive types
-		//   - GameObjectHandle - check if object is SceneObject or derives from Component
-		//   - SerializableObject - check if object is SerializableObject
-		//   - ResourceHandle - derives from Resource
-
-		// TOOD - Make SerializableObjectInfo IReflectable and create its RTTI
 	}
 	}
 
 
 	void RuntimeScriptObjects::clearScriptObjects(const CM::String& assemblyName)
 	void RuntimeScriptObjects::clearScriptObjects(const CM::String& assemblyName)
@@ -260,7 +692,7 @@ namespace BansheeEngine
 			auto iterFind = curAssembly.second->mTypeNameToId.find(fullName);
 			auto iterFind = curAssembly.second->mTypeNameToId.find(fullName);
 			if(iterFind != curAssembly.second->mTypeNameToId.end())
 			if(iterFind != curAssembly.second->mTypeNameToId.end())
 			{
 			{
-				outInfo = curAssembly.second->mObjectInfos[iterFind->first];
+				outInfo = curAssembly.second->mObjectInfos[iterFind->second];
 
 
 				return true;
 				return true;
 			}
 			}
@@ -268,4 +700,17 @@ namespace BansheeEngine
 
 
 		return false;
 		return false;
 	}
 	}
+
+	bool RuntimeScriptObjects::hasSerializableObjectInfo(const CM::String& ns, const CM::String& typeName)
+	{
+		String fullName = ns + "." + typeName;
+		for(auto& curAssembly : mAssemblyInfos)
+		{
+			auto iterFind = curAssembly.second->mTypeNameToId.find(fullName);
+			if(iterFind != curAssembly.second->mTypeNameToId.end())
+				return true;
+		}
+
+		return false;
+	}
 }
 }

+ 0 - 1
SBansheeEngine/Source/BsScriptComponent.cpp

@@ -40,7 +40,6 @@ namespace BansheeEngine
 
 
 	void ScriptComponent::internal_destroyInstance(ScriptComponent* nativeInstance)
 	void ScriptComponent::internal_destroyInstance(ScriptComponent* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 
 

+ 0 - 1
SBansheeEngine/Source/BsScriptFont.cpp

@@ -42,7 +42,6 @@ namespace BansheeEngine
 
 
 	void ScriptFont::internal_destroyInstance(ScriptFont* nativeInstance)
 	void ScriptFont::internal_destroyInstance(ScriptFont* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 }
 }

+ 0 - 1
SBansheeEngine/Source/BsScriptGUIArea.cpp

@@ -91,7 +91,6 @@ namespace BansheeEngine
 
 
 	void ScriptGUIArea::internal_destroyInstance(ScriptGUIArea* nativeInstance)
 	void ScriptGUIArea::internal_destroyInstance(ScriptGUIArea* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 
 

+ 0 - 1
SBansheeEngine/Source/BsScriptGUIButton.cpp

@@ -83,7 +83,6 @@ namespace BansheeEngine
 
 
 	void ScriptGUIButton::internal_destroyInstance(ScriptGUIButton* nativeInstance)
 	void ScriptGUIButton::internal_destroyInstance(ScriptGUIButton* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 
 

+ 0 - 1
SBansheeEngine/Source/BsScriptGUIElementStateStyle.cpp

@@ -63,7 +63,6 @@ namespace BansheeEngine
 
 
 	void ScriptGUIElementStateStyle::internal_destroyInstance(ScriptGUIElementStateStyle* nativeInstance)
 	void ScriptGUIElementStateStyle::internal_destroyInstance(ScriptGUIElementStateStyle* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 }
 }

+ 0 - 1
SBansheeEngine/Source/BsScriptGUIElementStyle.cpp

@@ -65,7 +65,6 @@ namespace BansheeEngine
 
 
 	void ScriptGUIElementStyle::internal_destroyInstance(ScriptGUIElementStyle* nativeInstance)
 	void ScriptGUIElementStyle::internal_destroyInstance(ScriptGUIElementStyle* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 }
 }

+ 0 - 1
SBansheeEngine/Source/BsScriptGUIFixedSpace.cpp

@@ -50,7 +50,6 @@ namespace BansheeEngine
 
 
 	void ScriptGUIFixedSpace::internal_destroyInstance(ScriptGUIFixedSpace* nativeInstance)
 	void ScriptGUIFixedSpace::internal_destroyInstance(ScriptGUIFixedSpace* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 
 

+ 0 - 1
SBansheeEngine/Source/BsScriptGUIFlexibleSpace.cpp

@@ -50,7 +50,6 @@ namespace BansheeEngine
 
 
 	void ScriptGUIFlexibleSpace::internal_destroyInstance(ScriptGUIFlexibleSpace* nativeInstance)
 	void ScriptGUIFlexibleSpace::internal_destroyInstance(ScriptGUIFlexibleSpace* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 
 

+ 0 - 1
SBansheeEngine/Source/BsScriptGUIInputBox.cpp

@@ -70,7 +70,6 @@ namespace BansheeEngine
 
 
 	void ScriptGUIInputBox::internal_destroyInstance(ScriptGUIInputBox* nativeInstance)
 	void ScriptGUIInputBox::internal_destroyInstance(ScriptGUIInputBox* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 
 

+ 0 - 1
SBansheeEngine/Source/BsScriptGUILabel.cpp

@@ -68,7 +68,6 @@ namespace BansheeEngine
 
 
 	void ScriptGUILabel::internal_destroyInstance(ScriptGUILabel* nativeInstance)
 	void ScriptGUILabel::internal_destroyInstance(ScriptGUILabel* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 
 

+ 0 - 1
SBansheeEngine/Source/BsScriptGUILayout.cpp

@@ -91,7 +91,6 @@ namespace BansheeEngine
 
 
 	void ScriptGUILayout::internal_destroyInstance(ScriptGUILayout* nativeInstance)
 	void ScriptGUILayout::internal_destroyInstance(ScriptGUILayout* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 
 

+ 0 - 1
SBansheeEngine/Source/BsScriptGUIListBox.cpp

@@ -89,7 +89,6 @@ namespace BansheeEngine
 
 
 	void ScriptGUIListBox::internal_destroyInstance(ScriptGUIListBox* nativeInstance)
 	void ScriptGUIListBox::internal_destroyInstance(ScriptGUIListBox* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 
 

+ 0 - 1
SBansheeEngine/Source/BsScriptGUIScrollArea.cpp

@@ -79,7 +79,6 @@ namespace BansheeEngine
 
 
 	void ScriptGUIScrollArea::internal_destroyInstance(ScriptGUIScrollArea* nativeInstance)
 	void ScriptGUIScrollArea::internal_destroyInstance(ScriptGUIScrollArea* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 
 

+ 0 - 1
SBansheeEngine/Source/BsScriptGUITexture.cpp

@@ -74,7 +74,6 @@ namespace BansheeEngine
 
 
 	void ScriptGUITexture::internal_destroyInstance(ScriptGUITexture* nativeInstance)
 	void ScriptGUITexture::internal_destroyInstance(ScriptGUITexture* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 
 

+ 0 - 1
SBansheeEngine/Source/BsScriptGUIToggle.cpp

@@ -94,7 +94,6 @@ namespace BansheeEngine
 
 
 	void ScriptGUIToggle::internal_destroyInstance(ScriptGUIToggle* nativeInstance)
 	void ScriptGUIToggle::internal_destroyInstance(ScriptGUIToggle* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 
 

+ 0 - 1
SBansheeEngine/Source/BsScriptGUIToggleGroup.cpp

@@ -42,7 +42,6 @@ namespace BansheeEngine
 
 
 	void ScriptGUIToggleGroup::internal_destroyInstance(ScriptGUIToggleGroup* nativeInstance)
 	void ScriptGUIToggleGroup::internal_destroyInstance(ScriptGUIToggleGroup* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 }
 }

+ 6 - 0
SBansheeEngine/Source/BsScriptGameObjectManager.cpp

@@ -0,0 +1,6 @@
+#include "BsScriptGameObjectManager.h"
+
+namespace BansheeEngine
+{
+
+}

+ 0 - 1
SBansheeEngine/Source/BsScriptHString.cpp

@@ -40,7 +40,6 @@ namespace BansheeEngine
 
 
 	void ScriptHString::internal_destroyInstance(ScriptHString* nativeInstance)
 	void ScriptHString::internal_destroyInstance(ScriptHString* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
 		cm_delete(nativeInstance);
 		cm_delete(nativeInstance);
 	}
 	}
 
 

+ 125 - 0
SBansheeEngine/Source/BsScriptResourceManager.cpp

@@ -0,0 +1,125 @@
+#include "BsScriptResourceManager.h"
+#include "BsMonoManager.h"
+#include "BsMonoAssembly.h"
+#include "BsMonoClass.h"
+#include "BsScriptTexture2D.h"
+#include "BsScriptSpriteTexture.h"
+
+using namespace CamelotFramework;
+
+namespace BansheeEngine
+{
+	ScriptResourceManager::ScriptResourceManager()
+		:mTextureClass(nullptr), mSpriteTextureClass(nullptr)
+	{
+		MonoAssembly* assembly = MonoManager::instance().getAssembly(BansheeEngineAssemblyName);
+		if(assembly == nullptr)
+			CM_EXCEPT(InternalErrorException, "Cannot find \"" + String(BansheeEngineAssemblyName) + "\" assembly.");
+
+		mTextureClass = assembly->getClass("BansheeEngine", "Texture2D");
+		mSpriteTextureClass = assembly->getClass("BansheeEngine", "SpriteTexture");
+
+		if(mTextureClass == nullptr)
+			CM_EXCEPT(InternalErrorException, "Cannot find managed Texture2D class.");
+
+		if(mSpriteTextureClass == nullptr)
+			CM_EXCEPT(InternalErrorException, "Cannot find managed SpriteTexture class.");
+	}
+
+	ScriptTexture2D* ScriptResourceManager::createScriptTexture(const HTexture& resourceHandle)
+	{
+		MonoObject* monoInstance = mTextureClass->createInstance();
+
+		return createScriptTexture(monoInstance, resourceHandle);
+	}
+
+	ScriptTexture2D* ScriptResourceManager::createScriptTexture(MonoObject* instance, const HTexture& resourceHandle)
+	{
+		const String& uuid = resourceHandle.getUUID();
+		throwExceptionIfInvalidOrDuplicate(uuid);
+
+		ScriptTexture2D* scriptResource = new (cm_alloc<ScriptTexture2D>()) ScriptTexture2D(resourceHandle);
+		mScriptResources[uuid] = scriptResource;
+
+		scriptResource->createInstance(instance);
+		scriptResource->metaData.thisPtrField->setValue(instance, scriptResource);
+
+		return scriptResource;
+	}
+
+	ScriptSpriteTexture* ScriptResourceManager::createScriptSpriteTexture(const HSpriteTexture& resourceHandle)
+	{
+		MonoObject* monoInstance = mSpriteTextureClass->createInstance();
+
+		return createScriptSpriteTexture(monoInstance, resourceHandle);
+	}
+
+	ScriptSpriteTexture* ScriptResourceManager::createScriptSpriteTexture(MonoObject* instance, const HSpriteTexture& resourceHandle)
+	{
+		const String& uuid = resourceHandle.getUUID();
+		throwExceptionIfInvalidOrDuplicate(uuid);
+
+		ScriptSpriteTexture* scriptResource = new (cm_alloc<ScriptSpriteTexture>()) ScriptSpriteTexture(resourceHandle);
+		mScriptResources[uuid] = scriptResource;
+
+		scriptResource->createInstance(instance);
+		scriptResource->metaData.thisPtrField->setValue(instance, scriptResource);
+
+		return scriptResource;
+	}
+
+	ScriptTexture2D* ScriptResourceManager::getScriptTexture(const CM::HTexture& resourceHandle)
+	{
+		return static_cast<ScriptTexture2D*>(getScriptResource(resourceHandle));
+	}
+
+	ScriptSpriteTexture* ScriptResourceManager::getScriptSpriteTexture(const HSpriteTexture& resourceHandle)
+	{
+		return static_cast<ScriptSpriteTexture*>(getScriptResource(resourceHandle));
+	}
+
+	ScriptResource* ScriptResourceManager::getScriptResource(const CM::HResource& resourceHandle)
+	{
+		const String& uuid = resourceHandle.getUUID();
+
+		if(uuid == "")
+			CM_EXCEPT(InvalidParametersException, "Provided resource handle has an undefined resource UUID.");
+
+		auto findIter = mScriptResources.find(uuid);
+		if(findIter != mScriptResources.end())
+			return findIter->second;
+
+		return nullptr;
+	}
+
+	void ScriptResourceManager::destroyScriptResource(ScriptResource* resource)
+	{
+		HResource resourceHandle = resource->getNativeHandle();
+		const String& uuid = resourceHandle.getUUID();
+
+		if(uuid == "")
+			CM_EXCEPT(InvalidParametersException, "Provided resource handle has an undefined resource UUID.");
+
+		auto findIter = mScriptResources.find(uuid);
+		if(findIter != mScriptResources.end())
+		{
+			(resource)->~ScriptResource();
+			MemoryAllocator<GenAlloc>::free(resource);
+
+			mScriptResources.erase(findIter);
+		}
+	}
+
+	void ScriptResourceManager::throwExceptionIfInvalidOrDuplicate(const CM::String& uuid) const
+	{
+		if(uuid == "")
+			CM_EXCEPT(InvalidParametersException, "Provided resource handle has an undefined resource UUID.");
+
+		auto findIter = mScriptResources.find(uuid);
+		if(findIter != mScriptResources.end())
+		{
+			CM_EXCEPT(InvalidStateException, "Provided resource handle already has a script resource. \
+											 Retrieve the existing instance instead of creating a new one.");
+		}
+	}
+}

+ 3 - 6
SBansheeEngine/Source/BsScriptSpriteTexture.cpp

@@ -1,4 +1,5 @@
 #include "BsScriptSpriteTexture.h"
 #include "BsScriptSpriteTexture.h"
+#include "BsScriptResourceManager.h"
 #include "BsScriptMeta.h"
 #include "BsScriptMeta.h"
 #include "BsMonoField.h"
 #include "BsMonoField.h"
 #include "BsMonoClass.h"
 #include "BsMonoClass.h"
@@ -30,16 +31,12 @@ namespace BansheeEngine
 
 
 	void ScriptSpriteTexture::internal_createInstance(MonoObject* instance)
 	void ScriptSpriteTexture::internal_createInstance(MonoObject* instance)
 	{
 	{
-		ScriptSpriteTexture* nativeInstance = new (cm_alloc<ScriptSpriteTexture>()) ScriptSpriteTexture(SpriteTexture::dummy()); // TODO - DUMMY CODE!
-		nativeInstance->createInstance(instance);
-
-		metaData.thisPtrField->setValue(instance, nativeInstance);
+		ScriptResourceManager::instance().createScriptSpriteTexture(instance, SpriteTexture::dummy()); // TODO - DUMMY CODE!
 	}
 	}
 
 
 	void ScriptSpriteTexture::internal_destroyInstance(ScriptSpriteTexture* nativeInstance)
 	void ScriptSpriteTexture::internal_destroyInstance(ScriptSpriteTexture* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
-		cm_delete(nativeInstance);
+		ScriptResourceManager::instance().destroyScriptResource(nativeInstance);
 	}
 	}
 
 
 	void ScriptSpriteTexture::setNativeHandle(const HResource& resource) 
 	void ScriptSpriteTexture::setNativeHandle(const HResource& resource) 

+ 3 - 6
SBansheeEngine/Source/BsScriptTexture2D.cpp

@@ -1,4 +1,5 @@
 #include "BsScriptTexture2D.h"
 #include "BsScriptTexture2D.h"
+#include "BsScriptResourceManager.h"
 #include "BsScriptMeta.h"
 #include "BsScriptMeta.h"
 #include "BsMonoField.h"
 #include "BsMonoField.h"
 #include "BsMonoClass.h"
 #include "BsMonoClass.h"
@@ -51,16 +52,12 @@ namespace BansheeEngine
 
 
 		HTexture texture = Texture::create(TEX_TYPE_2D, width, height, numMips, texFormat, TU_STATIC, gammaCorrection);
 		HTexture texture = Texture::create(TEX_TYPE_2D, width, height, numMips, texFormat, TU_STATIC, gammaCorrection);
 
 
-		ScriptTexture2D* nativeInstance = new (cm_alloc<ScriptTexture2D>()) ScriptTexture2D(texture);
-		nativeInstance->createInstance(instance);
-
-		metaData.thisPtrField->setValue(instance, nativeInstance);
+		ScriptResourceManager::instance().createScriptTexture(instance, texture);
 	}
 	}
 
 
 	void ScriptTexture2D::internal_destroyInstance(ScriptTexture2D* nativeInstance)
 	void ScriptTexture2D::internal_destroyInstance(ScriptTexture2D* nativeInstance)
 	{
 	{
-		nativeInstance->destroyInstance();
-		cm_delete(nativeInstance);
+		ScriptResourceManager::instance().destroyScriptResource(nativeInstance);
 	}
 	}
 
 
 	void ScriptTexture2D::setNativeHandle(const HResource& resource) 
 	void ScriptTexture2D::setNativeHandle(const HResource& resource)