فهرست منبع

Inspector expand/collapse state is now persistent for all elements throughout a single session
Fixed a bug with EditorWindow initialization where OnInitialize during assembly refresh would get called while objects were still in the process of being restored
Fixed an issue where array/list/dictionary with non-serializable elements would be considered serializable

BearishSun 10 سال پیش
والد
کامیت
5ac0a74e64

+ 2 - 0
MBansheeEditor/Inspector/InspectableArray.cs

@@ -46,6 +46,8 @@ namespace BansheeEditor
             GUILayout arrayLayout = layout.AddLayoutY(layoutIndex);
             GUILayout arrayLayout = layout.AddLayoutY(layoutIndex);
 
 
             arrayGUIField = InspectableArrayGUI.Create(parent, title, path, property, arrayLayout, depth);
             arrayGUIField = InspectableArrayGUI.Create(parent, title, path, property, arrayLayout, depth);
+            arrayGUIField.IsExpanded = parent.Persistent.GetBool(path + "_Expanded");
+            arrayGUIField.OnExpand += x => parent.Persistent.SetBool(path + "_Expanded", x);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 2 - 0
MBansheeEditor/Inspector/InspectableDictionary.cs

@@ -48,6 +48,8 @@ namespace BansheeEditor
             GUILayout dictionaryLayout = layout.AddLayoutY(layoutIndex);
             GUILayout dictionaryLayout = layout.AddLayoutY(layoutIndex);
 
 
             dictionaryGUIField = InspectableDictionaryGUI.Create(parent, title, path, property, dictionaryLayout, depth);
             dictionaryGUIField = InspectableDictionaryGUI.Create(parent, title, path, property, dictionaryLayout, depth);
+            dictionaryGUIField.IsExpanded = parent.Persistent.GetBool(path + "_Expanded");
+            dictionaryGUIField.OnExpand += x => parent.Persistent.SetBool(path + "_Expanded", x);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 2 - 0
MBansheeEditor/Inspector/InspectableList.cs

@@ -48,6 +48,8 @@ namespace BansheeEditor
             GUILayout arrayLayout = layout.AddLayoutY(layoutIndex);
             GUILayout arrayLayout = layout.AddLayoutY(layoutIndex);
 
 
             listGUIField = InspectableListGUI.Create(parent, title, path, property, arrayLayout, depth);
             listGUIField = InspectableListGUI.Create(parent, title, path, property, arrayLayout, depth);
+            listGUIField.IsExpanded = parent.Persistent.GetBool(path + "_Expanded");
+            listGUIField.OnExpand += x => parent.Persistent.SetBool(path + "_Expanded", x);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 3 - 1
MBansheeEditor/Inspector/InspectableObject.cs

@@ -37,7 +37,7 @@ namespace BansheeEditor
             SerializableProperty property)
             SerializableProperty property)
             : base(parent, title, path, SerializableProperty.FieldType.Object, depth, layout, property)
             : base(parent, title, path, SerializableProperty.FieldType.Object, depth, layout, property)
         {
         {
-            
+            isExpanded = parent.Persistent.GetBool(path + "_Expanded");
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
@@ -232,6 +232,8 @@ namespace BansheeEditor
         /// <param name="expanded">Determines whether the contents were expanded or collapsed.</param>
         /// <param name="expanded">Determines whether the contents were expanded or collapsed.</param>
         private void OnFoldoutToggled(bool expanded)
         private void OnFoldoutToggled(bool expanded)
         {
         {
+            parent.Persistent.SetBool(path + "_Expanded", expanded);
+
             isExpanded = expanded;
             isExpanded = expanded;
             forceUpdate = true;
             forceUpdate = true;
         }
         }

+ 14 - 140
MBansheeEditor/Inspector/Inspector.cs

@@ -34,20 +34,29 @@ namespace BansheeEditor
             get { return inspectedObject; }
             get { return inspectedObject; }
         }
         }
 
 
+        /// <summary>
+        /// A set of properties that the inspector can read/write. They will be persisted even after the inspector is closed
+        /// and restored when it is re-opened.
+        /// </summary>
+        protected internal SerializableProperties Persistent
+        {
+            get { return persistent; }
+        }
+
         private GUIPanel rootGUI;
         private GUIPanel rootGUI;
         private GUIPanel mainPanel;
         private GUIPanel mainPanel;
         private GUILayoutY layout;
         private GUILayoutY layout;
         private object inspectedObject;
         private object inspectedObject;
-        private Dictionary<string, object> persistent;
+        private SerializableProperties persistent;
 
 
         /// <summary>
         /// <summary>
         /// Initializes the inspector. Must be called after construction.
         /// Initializes the inspector. Must be called after construction.
         /// </summary>
         /// </summary>
         /// <param name="gui">GUI panel to add the GUI elements to.</param>
         /// <param name="gui">GUI panel to add the GUI elements to.</param>
         /// <param name="instance">Instance of the object whose fields to display GUI for.</param>
         /// <param name="instance">Instance of the object whose fields to display GUI for.</param>
-        /// <param name="persistent">A set of properties that the inspector can read/write. They will be persisted for the 
-        ///                          inspector even after it is closed.</param>
-        internal virtual void Initialize(GUIPanel gui, object instance, Dictionary<string, object> persistent)
+        /// <param name="persistent">A set of properties that the inspector can read/write. They will be persisted even 
+        ///                          after the inspector is closed and restored when it is re-opened.</param>
+        internal virtual void Initialize(GUIPanel gui, object instance, SerializableProperties persistent)
         {
         {
             rootGUI = gui;
             rootGUI = gui;
             this.persistent = persistent;
             this.persistent = persistent;
@@ -80,142 +89,7 @@ namespace BansheeEditor
         {
         {
             rootGUI.Active = visible;
             rootGUI.Active = visible;
         }
         }
-
-        /// <summary>
-        /// Sets a persistent floating point property that will remain available for the inspector of this object, even
-        /// after it is closed and re-opened.
-        /// </summary>
-        /// <param name="name">Name to record the property under.</param>
-        /// <param name="value">Value of the property.</param>
-        protected internal void SetFloat(string name, float value)
-        {
-            persistent[name] = value;
-        }
-
-        /// <summary>
-        /// Sets a persistent integer property that will remain available for the inspector of this object, even after it 
-        /// is closed and re-opened.
-        /// </summary>
-        /// <param name="name">Name to record the property under.</param>
-        /// <param name="value">Value of the property.</param>
-        protected internal void SetInt(string name, int value)
-        {
-            persistent[name] = value;
-        }
-
-        /// <summary>
-        /// Sets a persistent boolean property that will remain available for the inspector of this object, even after it 
-        /// is closed and re-opened.
-        /// </summary>
-        /// <param name="name">Name to record the property under.</param>
-        /// <param name="value">Value of the property.</param>
-        protected internal void SetBool(string name, bool value)
-        {
-            persistent[name] = value;
-        }
-
-        /// <summary>
-        /// Sets a persistent string property that will remain available for the inspector of this object, even after it is
-        /// closed and re-opened.
-        /// </summary>
-        /// <param name="name">Name to record the property under.</param>
-        /// <param name="value">Value of the property.</param>
-        protected internal void SetString(string name, string value)
-        {
-            persistent[name] = value;
-        }
-
-        /// <summary>
-        /// Retrieves a persistent floating point property.
-        /// </summary>
-        /// <param name="name">Name of the property to retrieve.</param>
-        /// <param name="defaultValue">Default value to return if property cannot be found.</param>
-        /// <returns>Value of the property if it exists, otherwise the default value.</returns>
-        protected internal float GetFloat(string name, float defaultValue = 0.0f)
-        {
-            object value;
-            if (persistent.TryGetValue(name, out value))
-            {
-                if (value is float)
-                    return (float)value;
-            }
-
-            return defaultValue;
-        }
-
-        /// <summary>
-        /// Retrieves a persistent integer property.
-        /// </summary>
-        /// <param name="name">Name of the property to retrieve.</param>
-        /// <param name="defaultValue">Default value to return if property cannot be found.</param>
-        /// <returns>Value of the property if it exists, otherwise the default value.</returns>
-        protected internal int GetInt(string name, int defaultValue = 0)
-        {
-            object value;
-            if (persistent.TryGetValue(name, out value))
-            {
-                if (value is int)
-                    return (int)value;
-            }
-
-            return defaultValue;
-        }
-
-        /// <summary>
-        /// Retrieves a persistent boolean property.
-        /// </summary>
-        /// <param name="name">Name of the property to retrieve.</param>
-        /// <param name="defaultValue">Default value to return if property cannot be found.</param>
-        /// <returns>Value of the property if it exists, otherwise the default value.</returns>
-        protected internal bool GetBool(string name, bool defaultValue = false)
-        {
-            object value;
-            if (persistent.TryGetValue(name, out value))
-            {
-                if (value is bool)
-                    return (bool)value;
-            }
-
-            return defaultValue;
-        }
-
-        /// <summary>
-        /// Retrieves a persistent string property.
-        /// </summary>
-        /// <param name="name">Name of the property to retrieve.</param>
-        /// <param name="defaultValue">Default value to return if property cannot be found.</param>
-        /// <returns>Value of the property if it exists, otherwise the default value.</returns>
-        protected internal string GetString(string name, string defaultValue = "")
-        {
-            object value;
-            if (persistent.TryGetValue(name, out value))
-            {
-                if (value is string)
-                    return (string)value;
-            }
-
-            return defaultValue;
-        }
-
-        /// <summary>
-        /// Checks does a persistent property with the specified name exists.
-        /// </summary>
-        /// <param name="name">Name of the property to check.</param>
-        /// <returns>True if the property exists, false otherwise.</returns>
-        protected internal bool HasKey(string name)
-        {
-            return persistent.ContainsKey(name);
-        }
-
-        /// <summary>
-        /// Deletes a persistent property with the specified name.
-        /// </summary>
-        /// <param name="name">Name of the property to delete.</param>
-        protected internal void DeleteKey(string name)
-        {
-            persistent.Remove(name);
-        }
-
+        
         /// <summary>
         /// <summary>
         /// Destroys all inspector GUI elements.
         /// Destroys all inspector GUI elements.
         /// </summary>
         /// </summary>

+ 154 - 14
MBansheeEditor/Inspector/InspectorPersistentData.cs

@@ -9,24 +9,25 @@ namespace BansheeEditor
     internal class InspectorPersistentData : Component
     internal class InspectorPersistentData : Component
     {
     {
         [SerializeField]
         [SerializeField]
-        private Dictionary<ulong, Dictionary<string, object>> componentData =
-            new Dictionary<ulong, Dictionary<string, object>>();
+        private Dictionary<ulong, SerializableProperties> componentProperties =
+            new Dictionary<ulong, SerializableProperties>();
 
 
-        [SerializeField] private Dictionary<string, Dictionary<string, object>> resourceData =
-            new Dictionary<string, Dictionary<string, object>>();
+        [SerializeField]
+        private Dictionary<string, SerializableProperties> resourceProperties =
+            new Dictionary<string, SerializableProperties>();
 
 
         /// <summary>
         /// <summary>
         /// Returns existing, or creates new properties for a component with the specified id.
         /// Returns existing, or creates new properties for a component with the specified id.
         /// </summary>
         /// </summary>
         /// <param name="componentId">Internal ID of the component to retrieve properties for.</param>
         /// <param name="componentId">Internal ID of the component to retrieve properties for.</param>
         /// <returns>A set of key value pairs representing persistent properties of an inspectable component.</returns>
         /// <returns>A set of key value pairs representing persistent properties of an inspectable component.</returns>
-        public Dictionary<string, object> GetProperties(ulong componentId)
+        public SerializableProperties GetProperties(ulong componentId)
         {
         {
-            Dictionary<string, object> output;
-            if (!componentData.TryGetValue(componentId, out output))
+            SerializableProperties output;
+            if (!componentProperties.TryGetValue(componentId, out output))
             {
             {
-                output = new Dictionary<string, object>();
-                componentData[componentId] = output;
+                output = new SerializableProperties();
+                componentProperties[componentId] = output;
             }
             }
 
 
             return output;
             return output;
@@ -37,16 +38,155 @@ namespace BansheeEditor
         /// </summary>
         /// </summary>
         /// <param name="uuid">Unique identifier of the resource to retrieve properties for.</param>
         /// <param name="uuid">Unique identifier of the resource to retrieve properties for.</param>
         /// <returns>A set of key value pairs representing persistent properties of an inspectable resource.</returns>
         /// <returns>A set of key value pairs representing persistent properties of an inspectable resource.</returns>
-        public Dictionary<string, object> GetProperties(string uuid)
+        public SerializableProperties GetProperties(string uuid)
         {
         {
-            Dictionary<string, object> output;
-            if (!resourceData.TryGetValue(uuid, out output))
+            SerializableProperties output;
+            if (!resourceProperties.TryGetValue(uuid, out output))
             {
             {
-                output = new Dictionary<string, object>();
-                resourceData[uuid] = output;
+                output = new SerializableProperties(); ;
+                resourceProperties[uuid] = output;
             }
             }
 
 
             return output;
             return output;
         }
         }
     }
     }
+
+    /// <summary>
+    /// Stores a serializable set of key-value pairs of various types.
+    /// </summary>
+    [SerializeObject]
+    public class SerializableProperties
+    {
+        [SerializeField]
+        private Dictionary<string, bool> booleans = new Dictionary<string, bool>();
+        [SerializeField]
+        private Dictionary<string, float> floats = new Dictionary<string, float>();
+        [SerializeField]
+        private Dictionary<string, int> ints = new Dictionary<string, int>();
+        [SerializeField]
+        private Dictionary<string, string> strings = new Dictionary<string, string>();
+
+        /// <summary>
+        /// Sets a floating point value to a property with the specified name.
+        /// </summary>
+        /// <param name="name">Name to record the property under.</param>
+        /// <param name="value">Value of the property.</param>
+        protected internal void SetFloat(string name, float value)
+        {
+            floats[name] = value;
+        }
+
+        /// <summary>
+        /// Sets a integer value to a property with the specified name.
+        /// </summary>
+        /// <param name="name">Name to record the property under.</param>
+        /// <param name="value">Value of the property.</param>
+        protected internal void SetInt(string name, int value)
+        {
+            ints[name] = value;
+        }
+
+        /// <summary>
+        /// Sets a boolean value to a property with the specified name.
+        /// </summary>
+        /// <param name="name">Name to record the property under.</param>
+        /// <param name="value">Value of the property.</param>
+        protected internal void SetBool(string name, bool value)
+        {
+            booleans[name] = value;
+        }
+
+        /// <summary>
+        /// Sets a string value to a property with the specified name.
+        /// </summary>
+        /// <param name="name">Name to record the property under.</param>
+        /// <param name="value">Value of the property.</param>
+        protected internal void SetString(string name, string value)
+        {
+            strings[name] = value;
+        }
+
+        /// <summary>
+        /// Retrieves a value of a floating point property.
+        /// </summary>
+        /// <param name="name">Name of the property to retrieve.</param>
+        /// <param name="defaultValue">Default value to return if property cannot be found.</param>
+        /// <returns>Value of the property if it exists, otherwise the default value.</returns>
+        protected internal float GetFloat(string name, float defaultValue = 0.0f)
+        {
+            float value;
+            if (floats.TryGetValue(name, out value))
+                return value;
+
+            return defaultValue;
+        }
+
+        /// <summary>
+        /// Retrieves a value of an integer property.
+        /// </summary>
+        /// <param name="name">Name of the property to retrieve.</param>
+        /// <param name="defaultValue">Default value to return if property cannot be found.</param>
+        /// <returns>Value of the property if it exists, otherwise the default value.</returns>
+        protected internal int GetInt(string name, int defaultValue = 0)
+        {
+            int value;
+            if (ints.TryGetValue(name, out value))
+                return value;
+
+            return defaultValue;
+        }
+
+        /// <summary>
+        /// Retrieves a value of a boolean property.
+        /// </summary>
+        /// <param name="name">Name of the property to retrieve.</param>
+        /// <param name="defaultValue">Default value to return if property cannot be found.</param>
+        /// <returns>Value of the property if it exists, otherwise the default value.</returns>
+        protected internal bool GetBool(string name, bool defaultValue = false)
+        {
+            bool value;
+            if (booleans.TryGetValue(name, out value))
+                return value;
+
+            return defaultValue;
+        }
+
+        /// <summary>
+        /// Retrieves a value of a string property.
+        /// </summary>
+        /// <param name="name">Name of the property to retrieve.</param>
+        /// <param name="defaultValue">Default value to return if property cannot be found.</param>
+        /// <returns>Value of the property if it exists, otherwise the default value.</returns>
+        protected internal string GetString(string name, string defaultValue = "")
+        {
+            string value;
+            if (strings.TryGetValue(name, out value))
+                return value;
+
+            return defaultValue;
+        }
+
+        /// <summary>
+        /// Checks does a persistent property with the specified name exists.
+        /// </summary>
+        /// <param name="name">Name of the property to check.</param>
+        /// <returns>True if the property exists, false otherwise.</returns>
+        protected internal bool HasKey(string name)
+        {
+            return floats.ContainsKey(name) || ints.ContainsKey(name) || booleans.ContainsKey(name) ||
+                   strings.ContainsKey(name);
+        }
+
+        /// <summary>
+        /// Deletes a persistent property with the specified name.
+        /// </summary>
+        /// <param name="name">Name of the property to delete.</param>
+        protected internal void DeleteKey(string name)
+        {
+            floats.Remove(name);
+            ints.Remove(name);
+            booleans.Remove(name);
+            strings.Remove(name);
+        }
+    }
 }
 }

+ 7 - 3
MBansheeEditor/Inspector/InspectorWindow.cs

@@ -33,7 +33,6 @@ namespace BansheeEditor
             public GUILayout title;
             public GUILayout title;
             public GUIPanel panel;
             public GUIPanel panel;
             public Inspector inspector;
             public Inspector inspector;
-            public bool expanded = true;
             public UInt64 instanceId;
             public UInt64 instanceId;
         }
         }
 
 
@@ -199,7 +198,12 @@ namespace BansheeEditor
 
 
                 data.inspector = InspectorUtility.GetInspector(allComponents[i].GetType());
                 data.inspector = InspectorUtility.GetInspector(allComponents[i].GetType());
                 data.inspector.Initialize(data.panel, allComponents[i], persistentProperties);
                 data.inspector.Initialize(data.panel, allComponents[i], persistentProperties);
-                data.foldout.Value = true;
+
+                bool isExpanded = data.inspector.Persistent.GetBool(data.instanceId + "_Expanded", true);
+                data.foldout.Value = isExpanded;
+
+                if (!isExpanded)
+                    data.inspector.SetVisible(false);
 
 
                 Type curComponentType = allComponents[i].GetType();
                 Type curComponentType = allComponents[i].GetType();
                 data.foldout.OnToggled += (bool expanded) => OnComponentFoldoutToggled(data, expanded);
                 data.foldout.OnToggled += (bool expanded) => OnComponentFoldoutToggled(data, expanded);
@@ -632,7 +636,7 @@ namespace BansheeEditor
         /// <param name="expanded">Determines whether to display or hide component contents.</param>
         /// <param name="expanded">Determines whether to display or hide component contents.</param>
         private void OnComponentFoldoutToggled(InspectorComponent inspectorData, bool expanded)
         private void OnComponentFoldoutToggled(InspectorComponent inspectorData, bool expanded)
         {
         {
-            inspectorData.expanded = expanded;
+            inspectorData.inspector.Persistent.SetBool(inspectorData.instanceId + "_Expanded", expanded);
             inspectorData.inspector.SetVisible(expanded);
             inspectorData.inspector.SetVisible(expanded);
         }
         }
 
 

+ 243 - 239
MBansheeEditor/Inspectors/FontInspector.cs

@@ -1,239 +1,243 @@
-using System;
-using System.Collections.Generic;
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Renders an inspector for the <see cref="Font"/> resource.
-    /// </summary>
-    [CustomInspector(typeof(Font))]
-    internal class FontInspector : Inspector
-    {
-        private GUIArrayField<int, FontSizeArrayRow> fontSizes;
-        private GUIArrayField<CharRange, CharRangeArrayRow> charRanges;
-        private GUIEnumField renderModeField;
-        private GUIToggleField boldField;
-        private GUIToggleField italicField;
-        private GUIIntField dpiField;
-        private GUIButton reimportButton;
-
-        private FontImportOptions importOptions;
-
-        /// <inheritdoc/>
-        protected internal override void Initialize()
-        {
-            if (InspectedObject != null)
-            {
-                importOptions = GetImportOptions();
-                BuildGUI();
-            }
-        }
-
-        /// <inheritdoc/>
-        protected internal override InspectableState Refresh()
-        {
-            FontImportOptions newImportOptions = GetImportOptions();
-
-            bool rebuildGUI = false;
-
-            int[] newFontSizes = newImportOptions.FontSizes;
-            if (newFontSizes == null)
-                rebuildGUI |= fontSizes.Array != null;
-            else
-            {
-                if (fontSizes.Array == null)
-                    rebuildGUI = true;
-                else
-                    rebuildGUI |= newFontSizes.Length != fontSizes.Array.GetLength(0);
-            }
-
-            CharRange[] newCharRanges = newImportOptions.CharRanges;
-            if (newCharRanges == null)
-                rebuildGUI |= charRanges.Array != null;
-            else
-            {
-                if (charRanges.Array == null)
-                    rebuildGUI = true;
-                else
-                    rebuildGUI |= newCharRanges.Length != charRanges.Array.GetLength(0);
-            }
-
-            if (rebuildGUI)
-                BuildGUI();
-
-            fontSizes.Refresh();
-            charRanges.Refresh();
-
-            renderModeField.Value = (ulong)newImportOptions.RenderMode;
-            boldField.Value = newImportOptions.Bold;
-            italicField.Value = newImportOptions.Italic;
-            dpiField.Value = newImportOptions.DPI;
-            importOptions = newImportOptions;
-
-            return InspectableState.NotModified;
-        }
-
-        /// <summary>
-        /// Recreates all the GUI elements used by this inspector.
-        /// </summary>
-        private void BuildGUI()
-        {
-            Layout.Clear();
-
-            fontSizes = GUIArrayField<int, FontSizeArrayRow>.Create(
-                new LocEdString("Font sizes"), importOptions.FontSizes, Layout);
-            fontSizes.OnChanged += x => importOptions.FontSizes = x;
-
-            charRanges = GUIArrayField<CharRange, CharRangeArrayRow>.Create(
-                new LocEdString("Character ranges"), importOptions.CharRanges, Layout);
-            charRanges.OnChanged += x => importOptions.CharRanges = x;
-
-            renderModeField = new GUIEnumField(typeof(FontRenderMode), new LocEdString("Render mode"));
-            boldField = new GUIToggleField(new LocEdString("Bold"));
-            italicField = new GUIToggleField(new LocEdString("Italic"));
-            dpiField = new GUIIntField(new LocEdString("DPI"));
-
-            reimportButton = new GUIButton(new LocEdString("Reimport"));
-            reimportButton.OnClick += TriggerReimport;
-
-            Layout.AddElement(renderModeField);
-            Layout.AddElement(boldField);
-            Layout.AddElement(italicField);
-            Layout.AddElement(dpiField);
-            Layout.AddSpace(10);
-
-            GUILayout reimportButtonLayout = Layout.AddLayoutX();
-            reimportButtonLayout.AddFlexibleSpace();
-            reimportButtonLayout.AddElement(reimportButton);
-        }
-
-        /// <summary>
-        /// Retrieves import options for the texture we're currently inspecting.
-        /// </summary>
-        /// <returns>Font import options object.</returns>
-        private FontImportOptions GetImportOptions()
-        {
-            Font font = InspectedObject as Font;
-            FontImportOptions output = null;
-
-            if (font != null)
-            {
-                LibraryEntry texEntry = ProjectLibrary.GetEntry(ProjectLibrary.GetPath(font));
-                if (texEntry != null && texEntry.Type == LibraryEntryType.File)
-                {
-                    FileEntry texFileEntry = (FileEntry)texEntry;
-                    output = texFileEntry.Options as FontImportOptions;
-                }
-            }
-
-            if (output == null)
-            {
-                if (importOptions == null)
-                    output = new FontImportOptions();
-                else
-                    output = importOptions;
-            }
-
-            return output;
-        }
-
-        /// <summary>
-        /// Reimports the texture resource according to the currently set import options.
-        /// </summary>
-        private void TriggerReimport()
-        {
-            Texture2D texture = (Texture2D)InspectedObject;
-            string resourcePath = ProjectLibrary.GetPath(texture);
-
-            ProjectLibrary.Reimport(resourcePath, importOptions, true);
-        }
-
-        /// <summary>
-        /// Row element used for displaying GUI for font size array elements.
-        /// </summary>
-        public class FontSizeArrayRow : GUIListFieldRow
-        {
-            private GUIIntField sizeField;
-
-            /// <inheritdoc/>
-            protected override GUILayoutX CreateGUI(GUILayoutY layout)
-            {
-                GUILayoutX titleLayout = layout.AddLayoutX();
-                sizeField = new GUIIntField(new LocEdString(SeqIndex + ". "));
-                titleLayout.AddElement(sizeField);
-
-                sizeField.OnChanged += x => { SetValue(x); MarkAsModified(); };
-                sizeField.OnFocusLost += ConfirmModify;
-                sizeField.OnConfirmed += ConfirmModify;
-
-                return titleLayout;
-            }
-
-            /// <inheritdoc/>
-            internal protected override InspectableState Refresh()
-            {
-                sizeField.Value = GetValue<int>();
-
-                return base.Refresh();
-            }
-        }
-
-        /// <summary>
-        /// Row element used for displaying GUI for character range array elements.
-        /// </summary>
-        public class CharRangeArrayRow : GUIListFieldRow
-        {
-            private GUIIntField rangeStartField;
-            private GUIIntField rangeEndField;
-
-            /// <inheritdoc/>
-            protected override GUILayoutX CreateGUI(GUILayoutY layout)
-            {
-                GUILayoutX titleLayout = layout.AddLayoutX();
-
-                rangeStartField = new GUIIntField(new LocEdString(SeqIndex + ". Start"));
-                rangeEndField = new GUIIntField(new LocEdString("End"));
-
-                titleLayout.AddElement(rangeStartField);
-                titleLayout.AddElement(rangeEndField);
-
-                rangeStartField.OnChanged += x =>
-                {
-                    CharRange range = GetValue<CharRange>();
-                    range.start = x;
-                    SetValue(range);
-
-                    MarkAsModified();
-                };
-
-                rangeEndField.OnChanged += x =>
-                {
-                    CharRange range = GetValue<CharRange>();
-                    range.end = x;
-                    SetValue(range);
-
-                    MarkAsModified();
-                };
-
-                rangeStartField.OnFocusLost += ConfirmModify;
-                rangeStartField.OnConfirmed += ConfirmModify;
-
-                rangeEndField.OnFocusLost += ConfirmModify;
-                rangeEndField.OnConfirmed += ConfirmModify;
-
-                return titleLayout;
-            }
-
-            /// <inheritdoc/>
-            internal protected override InspectableState Refresh()
-            {
-                CharRange newValue = GetValue<CharRange>();
-                rangeStartField.Value = newValue.start;
-                rangeEndField.Value = newValue.end;
-
-                return base.Refresh();
-            }
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Renders an inspector for the <see cref="Font"/> resource.
+    /// </summary>
+    [CustomInspector(typeof(Font))]
+    internal class FontInspector : Inspector
+    {
+        private GUIArrayField<int, FontSizeArrayRow> fontSizes;
+        private GUIArrayField<CharRange, CharRangeArrayRow> charRanges;
+        private GUIEnumField renderModeField;
+        private GUIToggleField boldField;
+        private GUIToggleField italicField;
+        private GUIIntField dpiField;
+        private GUIButton reimportButton;
+
+        private FontImportOptions importOptions;
+
+        /// <inheritdoc/>
+        protected internal override void Initialize()
+        {
+            if (InspectedObject != null)
+            {
+                importOptions = GetImportOptions();
+                BuildGUI();
+            }
+        }
+
+        /// <inheritdoc/>
+        protected internal override InspectableState Refresh()
+        {
+            FontImportOptions newImportOptions = GetImportOptions();
+
+            bool rebuildGUI = false;
+
+            int[] newFontSizes = newImportOptions.FontSizes;
+            if (newFontSizes == null)
+                rebuildGUI |= fontSizes.Array != null;
+            else
+            {
+                if (fontSizes.Array == null)
+                    rebuildGUI = true;
+                else
+                    rebuildGUI |= newFontSizes.Length != fontSizes.Array.GetLength(0);
+            }
+
+            CharRange[] newCharRanges = newImportOptions.CharRanges;
+            if (newCharRanges == null)
+                rebuildGUI |= charRanges.Array != null;
+            else
+            {
+                if (charRanges.Array == null)
+                    rebuildGUI = true;
+                else
+                    rebuildGUI |= newCharRanges.Length != charRanges.Array.GetLength(0);
+            }
+
+            if (rebuildGUI)
+                BuildGUI();
+
+            fontSizes.Refresh();
+            charRanges.Refresh();
+
+            renderModeField.Value = (ulong)newImportOptions.RenderMode;
+            boldField.Value = newImportOptions.Bold;
+            italicField.Value = newImportOptions.Italic;
+            dpiField.Value = newImportOptions.DPI;
+            importOptions = newImportOptions;
+
+            return InspectableState.NotModified;
+        }
+
+        /// <summary>
+        /// Recreates all the GUI elements used by this inspector.
+        /// </summary>
+        private void BuildGUI()
+        {
+            Layout.Clear();
+
+            fontSizes = GUIArrayField<int, FontSizeArrayRow>.Create(
+                new LocEdString("Font sizes"), importOptions.FontSizes, Layout);
+            fontSizes.OnChanged += x => importOptions.FontSizes = x;
+            fontSizes.IsExpanded = Persistent.GetBool("fontSizes_Expanded");
+            fontSizes.OnExpand += x => Persistent.SetBool("fontSizes_Expanded", x);
+
+            charRanges = GUIArrayField<CharRange, CharRangeArrayRow>.Create(
+                new LocEdString("Character ranges"), importOptions.CharRanges, Layout);
+            charRanges.OnChanged += x => importOptions.CharRanges = x;
+            charRanges.IsExpanded = Persistent.GetBool("charRanges_Expanded");
+            charRanges.OnExpand += x => Persistent.SetBool("charRanges_Expanded", x);
+
+            renderModeField = new GUIEnumField(typeof(FontRenderMode), new LocEdString("Render mode"));
+            boldField = new GUIToggleField(new LocEdString("Bold"));
+            italicField = new GUIToggleField(new LocEdString("Italic"));
+            dpiField = new GUIIntField(new LocEdString("DPI"));
+
+            reimportButton = new GUIButton(new LocEdString("Reimport"));
+            reimportButton.OnClick += TriggerReimport;
+
+            Layout.AddElement(renderModeField);
+            Layout.AddElement(boldField);
+            Layout.AddElement(italicField);
+            Layout.AddElement(dpiField);
+            Layout.AddSpace(10);
+
+            GUILayout reimportButtonLayout = Layout.AddLayoutX();
+            reimportButtonLayout.AddFlexibleSpace();
+            reimportButtonLayout.AddElement(reimportButton);
+        }
+
+        /// <summary>
+        /// Retrieves import options for the texture we're currently inspecting.
+        /// </summary>
+        /// <returns>Font import options object.</returns>
+        private FontImportOptions GetImportOptions()
+        {
+            Font font = InspectedObject as Font;
+            FontImportOptions output = null;
+
+            if (font != null)
+            {
+                LibraryEntry texEntry = ProjectLibrary.GetEntry(ProjectLibrary.GetPath(font));
+                if (texEntry != null && texEntry.Type == LibraryEntryType.File)
+                {
+                    FileEntry texFileEntry = (FileEntry)texEntry;
+                    output = texFileEntry.Options as FontImportOptions;
+                }
+            }
+
+            if (output == null)
+            {
+                if (importOptions == null)
+                    output = new FontImportOptions();
+                else
+                    output = importOptions;
+            }
+
+            return output;
+        }
+
+        /// <summary>
+        /// Reimports the texture resource according to the currently set import options.
+        /// </summary>
+        private void TriggerReimport()
+        {
+            Texture2D texture = (Texture2D)InspectedObject;
+            string resourcePath = ProjectLibrary.GetPath(texture);
+
+            ProjectLibrary.Reimport(resourcePath, importOptions, true);
+        }
+
+        /// <summary>
+        /// Row element used for displaying GUI for font size array elements.
+        /// </summary>
+        public class FontSizeArrayRow : GUIListFieldRow
+        {
+            private GUIIntField sizeField;
+
+            /// <inheritdoc/>
+            protected override GUILayoutX CreateGUI(GUILayoutY layout)
+            {
+                GUILayoutX titleLayout = layout.AddLayoutX();
+                sizeField = new GUIIntField(new LocEdString(SeqIndex + ". "));
+                titleLayout.AddElement(sizeField);
+
+                sizeField.OnChanged += x => { SetValue(x); MarkAsModified(); };
+                sizeField.OnFocusLost += ConfirmModify;
+                sizeField.OnConfirmed += ConfirmModify;
+
+                return titleLayout;
+            }
+
+            /// <inheritdoc/>
+            internal protected override InspectableState Refresh()
+            {
+                sizeField.Value = GetValue<int>();
+
+                return base.Refresh();
+            }
+        }
+
+        /// <summary>
+        /// Row element used for displaying GUI for character range array elements.
+        /// </summary>
+        public class CharRangeArrayRow : GUIListFieldRow
+        {
+            private GUIIntField rangeStartField;
+            private GUIIntField rangeEndField;
+
+            /// <inheritdoc/>
+            protected override GUILayoutX CreateGUI(GUILayoutY layout)
+            {
+                GUILayoutX titleLayout = layout.AddLayoutX();
+
+                rangeStartField = new GUIIntField(new LocEdString(SeqIndex + ". Start"));
+                rangeEndField = new GUIIntField(new LocEdString("End"));
+
+                titleLayout.AddElement(rangeStartField);
+                titleLayout.AddElement(rangeEndField);
+
+                rangeStartField.OnChanged += x =>
+                {
+                    CharRange range = GetValue<CharRange>();
+                    range.start = x;
+                    SetValue(range);
+
+                    MarkAsModified();
+                };
+
+                rangeEndField.OnChanged += x =>
+                {
+                    CharRange range = GetValue<CharRange>();
+                    range.end = x;
+                    SetValue(range);
+
+                    MarkAsModified();
+                };
+
+                rangeStartField.OnFocusLost += ConfirmModify;
+                rangeStartField.OnConfirmed += ConfirmModify;
+
+                rangeEndField.OnFocusLost += ConfirmModify;
+                rangeEndField.OnConfirmed += ConfirmModify;
+
+                return titleLayout;
+            }
+
+            /// <inheritdoc/>
+            internal protected override InspectableState Refresh()
+            {
+                CharRange newValue = GetValue<CharRange>();
+                rangeStartField.Value = newValue.start;
+                rangeEndField.Value = newValue.end;
+
+                return base.Refresh();
+            }
+        }
+    }
+}

+ 628 - 626
MBansheeEditor/Inspectors/GUISkinInspector.cs

@@ -1,626 +1,628 @@
-using System;
-using System.Collections.Generic;
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Renders an inspector for the <see cref="GUISkin"/> resource.
-    /// </summary>
-    [CustomInspector(typeof(GUISkin))]
-    public class GUISkinInspector : Inspector
-    {
-        private GUIDictionaryField<string, GUIElementStyle, GUIElementStyleEntry> valuesField;
-
-        private Dictionary<string, GUIElementStyle> styles = new Dictionary<string, GUIElementStyle>();
-
-        /// <inheritdoc/>
-        protected internal override void Initialize()
-        {
-            BuildGUI();
-        }
-
-        /// <inheritdoc/>
-        protected internal override InspectableState Refresh()
-        {
-            valuesField.Refresh();
-
-            return InspectableState.NotModified;
-        }
-
-        /// <summary>
-        /// Recreates all the GUI elements used by this inspector.
-        /// </summary>
-        private void BuildGUI()
-        {
-            Layout.Clear();
-            styles.Clear();
-
-            GUISkin guiSkin = InspectedObject as GUISkin;
-            if (guiSkin == null)
-                return;
-
-            string[] styleNames = guiSkin.StyleNames;
-            foreach (var styleName in styleNames)
-                styles[styleName] = guiSkin.GetStyle(styleName);
-
-            valuesField = GUIDictionaryField<string, GUIElementStyle, GUIElementStyleEntry>.Create
-                (new LocEdString("Styles"), styles, Layout);
-
-            valuesField.OnChanged += x =>
-            {
-                if (x != null)
-                {
-                    foreach (var KVP in x)
-                    {
-                        if (guiSkin.HasStyle(KVP.Key))
-                        {
-                            GUIElementStyle oldValue = guiSkin.GetStyle(KVP.Key);
-                            if (oldValue != KVP.Value)
-                                guiSkin.SetStyle(KVP.Key, KVP.Value);
-                        }
-                        else
-                            guiSkin.SetStyle(KVP.Key, KVP.Value);
-                    }
-
-                    string[] oldStyleNames = guiSkin.StyleNames;
-                    foreach (var styleName in oldStyleNames)
-                    {
-                        if (!x.ContainsKey(styleName))
-                            guiSkin.RemoveStyle(styleName);
-                    }
-
-                    styles = x;
-                }
-                else
-                {
-                    foreach (var KVP in styles)
-                        guiSkin.RemoveStyle(KVP.Key);
-
-                    styles.Clear();
-                }
-
-                EditorApplication.SetDirty(guiSkin);
-            };
-
-            valuesField.OnValueChanged += x =>
-            {
-                guiSkin.SetStyle(x, styles[x]);
-                EditorApplication.SetDirty(guiSkin);
-            };
-
-            valuesField.OnValueRemoved += x =>
-            {
-                guiSkin.RemoveStyle(x);
-                EditorApplication.SetDirty(guiSkin);
-            };
-
-            Layout.AddSpace(10);
-        }
-
-        /// <summary>
-        /// Row element used for displaying GUI for GUI element style dictionary elements.
-        /// </summary>
-        public class GUIElementStyleEntry : GUIDictionaryFieldRow
-        {
-            private GUITextField keyField;
-            private GUIElementStyleGUI valueField;
-
-            /// <inheritdoc/>
-            protected override GUILayoutX CreateKeyGUI(GUILayoutY layout)
-            {
-                GUILayoutX titleLayout = layout.AddLayoutX();
-                keyField = new GUITextField(new LocEdString("Name"));
-                titleLayout.AddElement(keyField);
-
-                keyField.OnChanged += SetKey;
-
-                return titleLayout;
-            }
-
-            /// <inheritdoc/>
-            protected override void CreateValueGUI(GUILayoutY layout)
-            {
-                if(valueField == null)
-                    valueField = new GUIElementStyleGUI();
-
-                valueField.BuildGUI(layout, Depth);
-            }
-
-            /// <inheritdoc/>
-            protected override void OnEditModeChanged(bool editMode)
-            {
-                keyField.Disabled = !editMode;
-            }
-
-            /// <inheritdoc/>
-            internal protected override InspectableState Refresh()
-            {
-                keyField.Value = GetKey<string>();
-                return valueField.Refresh(GetValue<GUIElementStyle>());
-            }
-        }
-
-        /// <summary>
-        /// Creates GUI elements for editing/displaying <see cref="GUIElementStyle"/>
-        /// </summary>
-        private class GUIElementStyleGUI
-        {
-            private const int IndentAmount = 5;
-
-            private GUIResourceField fontField;
-            private GUIIntField fontSizeField;
-            private GUIEnumField horzAlignField;
-            private GUIEnumField vertAlignField;
-            private GUIEnumField imagePositionField;
-            private GUIToggleField wordWrapField;
-
-            private GUIElementStateStyleGUI normalGUI;
-            private GUIElementStateStyleGUI hoverGUI;
-            private GUIElementStateStyleGUI activeGUI;
-            private GUIElementStateStyleGUI focusedGUI;
-            private GUIElementStateStyleGUI normalOnGUI;
-            private GUIElementStateStyleGUI hoverOnGUI;
-            private GUIElementStateStyleGUI activeOnGUI;
-            private GUIElementStateStyleGUI focusedOnGUI;
-
-            private RectOffsetGUI borderGUI;
-            private RectOffsetGUI marginsGUI;
-            private RectOffsetGUI contentOffsetGUI;
-
-            private GUIToggleField fixedWidthField;
-            private GUIIntField widthField;
-            private GUIIntField minWidthField;
-            private GUIIntField maxWidthField;
-
-            private GUIToggleField fixedHeightField;
-            private GUIIntField heightField;
-            private GUIIntField minHeightField;
-            private GUIIntField maxHeightField;
-
-            private GUIElementStyle style;
-            private bool isExpanded;
-            private InspectableState modifiedState;
-
-            /// <summary>
-            /// Creates a new GUI element style GUI.
-            /// </summary>
-            public GUIElementStyleGUI()
-            {
-                normalGUI = new GUIElementStateStyleGUI();
-                hoverGUI = new GUIElementStateStyleGUI();
-                activeGUI = new GUIElementStateStyleGUI();
-                focusedGUI = new GUIElementStateStyleGUI();
-                normalOnGUI = new GUIElementStateStyleGUI();
-                hoverOnGUI = new GUIElementStateStyleGUI();
-                activeOnGUI = new GUIElementStateStyleGUI();
-                focusedOnGUI = new GUIElementStateStyleGUI();
-            }
-
-            /// <summary>
-            /// Builds GUI for the specified GUI element style.
-            /// </summary>
-            /// <param name="layout">Layout to append the GUI elements to.</param>
-            /// <param name="depth">Determines the depth at which the element is rendered.</param>
-            public void BuildGUI(GUILayout layout, int depth)
-            {
-                short backgroundDepth = (short)(Inspector.START_BACKGROUND_DEPTH - depth - 1);
-                string bgPanelStyle = depth % 2 == 0
-                    ? EditorStyles.InspectorContentBgAlternate
-                    : EditorStyles.InspectorContentBg;
-
-                GUIToggle foldout = new GUIToggle(new LocEdString("Style"), EditorStyles.Foldout);
-                GUITexture inspectorContentBg = new GUITexture(null, bgPanelStyle);
-
-                layout.AddElement(foldout);
-                GUIPanel panel = layout.AddPanel();
-                GUIPanel backgroundPanel = panel.AddPanel(backgroundDepth);
-                
-                backgroundPanel.AddElement(inspectorContentBg);
-
-                GUILayoutX guiIndentLayoutX = panel.AddLayoutX();
-                guiIndentLayoutX.AddSpace(IndentAmount);
-                GUILayoutY guiIndentLayoutY = guiIndentLayoutX.AddLayoutY();
-                guiIndentLayoutY.AddSpace(IndentAmount);
-                GUILayoutY contentLayout = guiIndentLayoutY.AddLayoutY();
-                guiIndentLayoutY.AddSpace(IndentAmount);
-                guiIndentLayoutX.AddSpace(IndentAmount);
-
-                fontField = new GUIResourceField(typeof (Font), new LocEdString("Font"));
-                fontSizeField = new GUIIntField(new LocEdString("Font size"));
-                horzAlignField = new GUIEnumField(typeof (TextHorzAlign), new LocEdString("Horizontal alignment"));
-                vertAlignField = new GUIEnumField(typeof(TextVertAlign), new LocEdString("Vertical alignment"));
-                imagePositionField = new GUIEnumField(typeof(GUIImagePosition), new LocEdString("Image position"));
-                wordWrapField = new GUIToggleField(new LocEdString("Word wrap"));
-
-                contentLayout.AddElement(fontField);
-                contentLayout.AddElement(fontSizeField);
-                contentLayout.AddElement(horzAlignField);
-                contentLayout.AddElement(vertAlignField);
-                contentLayout.AddElement(imagePositionField);
-                contentLayout.AddElement(wordWrapField);
-
-                normalGUI.BuildGUI(new LocEdString("Normal"), contentLayout);
-                hoverGUI.BuildGUI(new LocEdString("Hover"), contentLayout);
-                activeGUI.BuildGUI(new LocEdString("Active"), contentLayout);
-                focusedGUI.BuildGUI(new LocEdString("Focused"), contentLayout);
-                normalOnGUI.BuildGUI(new LocEdString("NormalOn"), contentLayout);
-                hoverOnGUI.BuildGUI(new LocEdString("HoverOn"), contentLayout);
-                activeOnGUI.BuildGUI(new LocEdString("ActiveOn"), contentLayout);
-                focusedOnGUI.BuildGUI(new LocEdString("FocusedOn"), contentLayout);
-
-                borderGUI = new RectOffsetGUI(new LocEdString("Border"), contentLayout);
-                marginsGUI = new RectOffsetGUI(new LocEdString("Margins"), contentLayout);
-                contentOffsetGUI = new RectOffsetGUI(new LocEdString("Content offset"), contentLayout);
-
-                fixedWidthField = new GUIToggleField(new LocEdString("Fixed width"));
-                widthField = new GUIIntField(new LocEdString("Width"));
-                minWidthField = new GUIIntField(new LocEdString("Min. width"));
-                maxWidthField = new GUIIntField(new LocEdString("Max. width"));
-
-                fixedHeightField = new GUIToggleField(new LocEdString("Fixed height"));
-                heightField = new GUIIntField(new LocEdString("Height"));
-                minHeightField = new GUIIntField(new LocEdString("Min. height"));
-                maxHeightField = new GUIIntField(new LocEdString("Max. height"));
-
-                contentLayout.AddElement(fixedWidthField);
-                contentLayout.AddElement(widthField);
-                contentLayout.AddElement(minWidthField);
-                contentLayout.AddElement(maxWidthField);
-
-                contentLayout.AddElement(fixedHeightField);
-                contentLayout.AddElement(heightField);
-                contentLayout.AddElement(minHeightField);
-                contentLayout.AddElement(maxHeightField);
-
-                foldout.OnToggled += x =>
-                {
-                    panel.Active = x;
-                    isExpanded = x;
-                };
-
-                fontField.OnChanged += x => 
-                {
-                    Font font = Resources.Load<Font>(x);
-
-                    GetStyle().Font = font; 
-                    MarkAsModified(); 
-                    ConfirmModify(); 
-                };
-                fontSizeField.OnChanged += x => { GetStyle().FontSize = x; MarkAsModified(); };
-                fontSizeField.OnFocusLost += ConfirmModify;
-                fontSizeField.OnConfirmed += ConfirmModify;
-                horzAlignField.OnSelectionChanged += x =>
-                {
-                    GetStyle().TextHorzAlign = (TextHorzAlign)x; 
-                    MarkAsModified(); 
-                    ConfirmModify();
-                };
-                vertAlignField.OnSelectionChanged += x =>
-                {
-                    GetStyle().TextVertAlign = (TextVertAlign)x; 
-                    MarkAsModified(); 
-                    ConfirmModify();
-                };
-                imagePositionField.OnSelectionChanged += x =>
-                {
-                    GetStyle().ImagePosition = (GUIImagePosition)x; 
-                    MarkAsModified(); 
-                    ConfirmModify();
-                };
-                wordWrapField.OnChanged += x => { GetStyle().WordWrap = x; MarkAsModified(); ConfirmModify(); };
-
-                normalGUI.OnChanged += x => { GetStyle().Normal = x; MarkAsModified(); ConfirmModify(); };
-                hoverGUI.OnChanged += x => { GetStyle().Hover = x; MarkAsModified(); ConfirmModify(); };
-                activeGUI.OnChanged += x => { GetStyle().Active = x; MarkAsModified(); ConfirmModify(); };
-                focusedGUI.OnChanged += x => { GetStyle().Focused = x; MarkAsModified(); ConfirmModify(); };
-                normalOnGUI.OnChanged += x => { GetStyle().NormalOn = x; MarkAsModified(); ConfirmModify(); };
-                hoverOnGUI.OnChanged += x => { GetStyle().HoverOn = x; MarkAsModified(); ConfirmModify(); };
-                activeOnGUI.OnChanged += x => { GetStyle().ActiveOn = x; MarkAsModified(); ConfirmModify(); };
-                focusedOnGUI.OnChanged += x => { GetStyle().FocusedOn = x; MarkAsModified(); ConfirmModify(); };
-
-                borderGUI.OnChanged += x => { GetStyle().Border = x; MarkAsModified(); };
-                marginsGUI.OnChanged += x => { GetStyle().Margins = x; MarkAsModified(); };
-                contentOffsetGUI.OnChanged += x => { GetStyle().ContentOffset = x; MarkAsModified(); };
-
-                borderGUI.OnConfirmed += ConfirmModify;
-                marginsGUI.OnConfirmed += ConfirmModify;
-                contentOffsetGUI.OnConfirmed += ConfirmModify;
-
-                fixedWidthField.OnChanged += x => { GetStyle().FixedWidth = x; MarkAsModified(); ConfirmModify(); };
-                widthField.OnChanged += x => GetStyle().Width = x;
-                widthField.OnFocusLost += ConfirmModify;
-                widthField.OnConfirmed += ConfirmModify;
-                minWidthField.OnChanged += x => GetStyle().MinWidth = x;
-                minWidthField.OnFocusLost += ConfirmModify;
-                minWidthField.OnConfirmed += ConfirmModify;
-                maxWidthField.OnChanged += x => GetStyle().MaxWidth = x;
-                maxWidthField.OnFocusLost += ConfirmModify;
-                maxWidthField.OnConfirmed += ConfirmModify;
-
-                fixedHeightField.OnChanged += x => { GetStyle().FixedHeight = x; MarkAsModified(); ConfirmModify(); };
-                heightField.OnChanged += x => GetStyle().Height = x;
-                heightField.OnFocusLost += ConfirmModify;
-                heightField.OnConfirmed += ConfirmModify;
-                minHeightField.OnChanged += x => GetStyle().MinHeight = x;
-                minHeightField.OnFocusLost += ConfirmModify;
-                minHeightField.OnConfirmed += ConfirmModify;
-                maxHeightField.OnChanged += x => GetStyle().MaxHeight = x;
-                maxHeightField.OnFocusLost += ConfirmModify;
-                maxHeightField.OnConfirmed += ConfirmModify;
-
-                foldout.Value = isExpanded;
-                panel.Active = isExpanded;
-            }
-
-            /// <summary>
-            /// Updates all GUI elements from the style if style changes.
-            /// </summary>
-            /// <param name="style">Style to display in the GUI.</param>
-            /// <returns>State representing was anything modified between two last calls to <see cref="Refresh"/>.</returns>
-            public InspectableState Refresh(GUIElementStyle style)
-            {
-                this.style = style;
-
-                InspectableState oldModifiedState = modifiedState;
-                if (modifiedState.HasFlag(InspectableState.Modified))
-                    modifiedState = InspectableState.NotModified;
-
-                if (style == null)
-                    return oldModifiedState;
-
-                fontField.Value = style.Font;
-                fontSizeField.Value = style.FontSize;
-                horzAlignField.Value = (ulong)style.TextHorzAlign;
-                vertAlignField.Value = (ulong)style.TextVertAlign;
-                imagePositionField.Value = (ulong)style.ImagePosition;
-                wordWrapField.Value = style.WordWrap;
-
-                normalGUI.Refresh(style.Normal);
-                hoverGUI.Refresh(style.Hover);
-                activeGUI.Refresh(style.Active);
-                focusedGUI.Refresh(style.Focused);
-                normalOnGUI.Refresh(style.NormalOn);
-                hoverOnGUI.Refresh(style.HoverOn);
-                activeOnGUI.Refresh(style.ActiveOn);
-                focusedOnGUI.Refresh(style.FocusedOn);
-
-                borderGUI.Refresh(style.Border);
-                marginsGUI.Refresh(style.Margins);
-                contentOffsetGUI.Refresh(style.ContentOffset);
-
-                fixedWidthField.Value = style.FixedWidth;
-                widthField.Value = style.Width;
-                minWidthField.Value = style.MinWidth;
-                maxWidthField.Value = style.MaxWidth;
-                fixedHeightField.Value = style.FixedHeight;
-                heightField.Value = style.Height;
-                minHeightField.Value = style.MinHeight;
-                maxHeightField.Value = style.MaxHeight;
-
-                widthField.Active = style.FixedWidth;
-                minWidthField.Active = !style.FixedWidth;
-                maxWidthField.Active = !style.FixedWidth;
-
-                heightField.Active = style.FixedHeight;
-                minHeightField.Active = !style.FixedHeight;
-                maxHeightField.Active = !style.FixedHeight;
-
-                return oldModifiedState;
-            }
-
-            /// <summary>
-            /// Returns the style displayed in the GUI.
-            /// </summary>
-            /// <returns>Style displayed in the GUI.</returns>
-            private GUIElementStyle GetStyle()
-            {
-                return style;
-            }
-
-            /// <summary>
-            /// Marks the contents of the style as modified.
-            /// </summary>
-            private void MarkAsModified()
-            {
-                modifiedState |= InspectableState.ModifyInProgress;
-            }
-
-            /// <summary>
-            /// Confirms any queued modifications, signaling parent element.
-            /// </summary>
-            private void ConfirmModify()
-            {
-                if (modifiedState.HasFlag(InspectableState.ModifyInProgress))
-                    modifiedState |= InspectableState.Modified;
-            }
-
-            /// <summary>
-            /// Creates GUI elements for editing/displaying <see cref="GUIElementStateStyle"/>
-            /// </summary>
-            private class GUIElementStateStyleGUI
-            {
-                private GUIElementStateStyle state;
-                private GUIToggle foldout;
-                private GUIResourceField textureField;
-                private GUIColorField textColorField;
-                private bool isExpanded;
-
-                /// <summary>
-                /// Triggered when some value in the style state changes.
-                /// </summary>
-                public Action<GUIElementStateStyle> OnChanged;
-
-                /// <summary>
-                /// Creates a new GUI element state style GUI.
-                /// </summary>
-                public GUIElementStateStyleGUI()
-                { }
-
-                /// <summary>
-                /// Builds the GUI for the specified state style.
-                /// </summary>
-                /// <param name="title">Text to display on the title bar.</param>
-                /// <param name="layout">Layout to append the GUI elements to.</param>
-                public void BuildGUI(LocString title, GUILayout layout)
-                {
-                    foldout = new GUIToggle(title, EditorStyles.Foldout);
-                    textureField = new GUIResourceField(typeof(SpriteTexture), new LocEdString("Texture"));
-                    textColorField = new GUIColorField(new LocEdString("Text color"));
-
-                    foldout.OnToggled += x =>
-                    {
-                        textureField.Active = x;
-                        textColorField.Active = x;
-                        isExpanded = x;
-                    };
-
-                    textureField.OnChanged += x =>
-                    {
-                        SpriteTexture texture = Resources.Load<SpriteTexture>(x);
-                        state.Texture = texture;
-
-                        if (OnChanged != null)
-                            OnChanged(state);
-                    };
-
-                    textColorField.OnChanged += x =>
-                    {
-                        state.TextColor = x;
-
-                        if (OnChanged != null)
-                            OnChanged(state);
-                    };
-
-                    layout.AddElement(foldout);
-                    layout.AddElement(textureField);
-                    layout.AddElement(textColorField);
-
-                    foldout.Value = isExpanded;
-                    textureField.Active = isExpanded;
-                    textColorField.Active = isExpanded;
-                }
-
-                /// <summary>
-                /// Updates all GUI elements from the current state values.
-                /// </summary>
-                /// <param name="state">State object to display in the GUI.</param>
-                public void Refresh(GUIElementStateStyle state)
-                {
-                    this.state = state;
-
-                    textureField.Value = state.Texture;
-                    textColorField.Value = state.TextColor;
-                }
-            }
-
-            /// <summary>
-            /// Creates GUI elements for editing/displaying <see cref="RectOffset"/>
-            /// </summary>
-            private class RectOffsetGUI
-            {
-                private RectOffset offset;
-                private GUIIntField offsetLeftField;
-                private GUIIntField offsetRightField;
-                private GUIIntField offsetTopField;
-                private GUIIntField offsetBottomField;
-
-                /// <summary>
-                /// Triggered when some value in the offset rectangle changes.
-                /// </summary>
-                public Action<RectOffset> OnChanged;
-
-                /// <summary>
-                /// Triggered when the user confirms input.
-                /// </summary>
-                public Action OnConfirmed;
-
-                /// <summary>
-                /// Creates a new rectangle offset GUI.
-                /// </summary>
-                /// <param name="title">Text to display on the title bar.</param>
-                /// <param name="layout">Layout to append the GUI elements to.</param>
-                public RectOffsetGUI(LocString title, GUILayout layout)
-                {
-                    GUILayoutX rectLayout = layout.AddLayoutX();
-                    rectLayout.AddElement(new GUILabel(title, GUIOption.FixedWidth(100)));
-                    GUILayoutY rectContentLayout = rectLayout.AddLayoutY();
-
-                    GUILayoutX rectTopRow = rectContentLayout.AddLayoutX();
-                    GUILayoutX rectBotRow = rectContentLayout.AddLayoutX();
-
-                    offsetLeftField = new GUIIntField(new LocEdString("Left"), 40);
-                    offsetRightField = new GUIIntField(new LocEdString("Right"), 40);
-                    offsetTopField = new GUIIntField(new LocEdString("Top"), 40);
-                    offsetBottomField = new GUIIntField(new LocEdString("Bottom"), 40);
-
-                    rectTopRow.AddElement(offsetLeftField);
-                    rectTopRow.AddElement(offsetRightField);
-                    rectBotRow.AddElement(offsetTopField);
-                    rectBotRow.AddElement(offsetBottomField);
-
-                    offsetLeftField.OnChanged += x =>
-                    {
-                        offset.left = x;
-
-                        if(OnChanged != null)
-                            OnChanged(offset);
-                    };
-
-                    offsetRightField.OnChanged += x =>
-                    {
-                        offset.right = x;
-
-                        if (OnChanged != null)
-                            OnChanged(offset);
-                    };
-
-                    offsetTopField.OnChanged += x =>
-                    {
-                        offset.top = x;
-
-                        if (OnChanged != null)
-                            OnChanged(offset);
-                    };
-
-                    offsetBottomField.OnChanged += x =>
-                    {
-                        offset.bottom = x;
-
-                        if (OnChanged != null)
-                            OnChanged(offset);
-                    };
-
-                    Action DoOnConfirmed = () =>
-                    {
-                        if (OnConfirmed != null)
-                            OnConfirmed();
-                    };
-
-                    offsetLeftField.OnConfirmed += DoOnConfirmed;
-                    offsetLeftField.OnFocusLost += DoOnConfirmed;
-                    offsetRightField.OnConfirmed += DoOnConfirmed;
-                    offsetRightField.OnFocusLost += DoOnConfirmed;
-                    offsetTopField.OnConfirmed += DoOnConfirmed;
-                    offsetTopField.OnFocusLost += DoOnConfirmed;
-                    offsetBottomField.OnConfirmed += DoOnConfirmed;
-                    offsetBottomField.OnFocusLost += DoOnConfirmed;
-                }
-
-                /// <summary>
-                /// Updates all GUI elements from the offset.
-                /// </summary>
-                /// <param name="offset">Offset to update the GUI to.</param>
-                public void Refresh(RectOffset offset)
-                {
-                    this.offset = offset;
-
-                    offsetLeftField.Value = offset.left;
-                    offsetRightField.Value = offset.right;
-                    offsetTopField.Value = offset.top;
-                    offsetBottomField.Value = offset.bottom;
-                }
-            }
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Renders an inspector for the <see cref="GUISkin"/> resource.
+    /// </summary>
+    [CustomInspector(typeof(GUISkin))]
+    public class GUISkinInspector : Inspector
+    {
+        private GUIDictionaryField<string, GUIElementStyle, GUIElementStyleEntry> valuesField;
+
+        private Dictionary<string, GUIElementStyle> styles = new Dictionary<string, GUIElementStyle>();
+
+        /// <inheritdoc/>
+        protected internal override void Initialize()
+        {
+            BuildGUI();
+        }
+
+        /// <inheritdoc/>
+        protected internal override InspectableState Refresh()
+        {
+            valuesField.Refresh();
+
+            return InspectableState.NotModified;
+        }
+
+        /// <summary>
+        /// Recreates all the GUI elements used by this inspector.
+        /// </summary>
+        private void BuildGUI()
+        {
+            Layout.Clear();
+            styles.Clear();
+
+            GUISkin guiSkin = InspectedObject as GUISkin;
+            if (guiSkin == null)
+                return;
+
+            string[] styleNames = guiSkin.StyleNames;
+            foreach (var styleName in styleNames)
+                styles[styleName] = guiSkin.GetStyle(styleName);
+
+            valuesField = GUIDictionaryField<string, GUIElementStyle, GUIElementStyleEntry>.Create
+                (new LocEdString("Styles"), styles, Layout);
+            valuesField.IsExpanded = Persistent.GetBool("valuesField_Expanded");
+            valuesField.OnExpand += x => Persistent.SetBool("valuesField_Expanded", x);
+
+            valuesField.OnChanged += x =>
+            {
+                if (x != null)
+                {
+                    foreach (var KVP in x)
+                    {
+                        if (guiSkin.HasStyle(KVP.Key))
+                        {
+                            GUIElementStyle oldValue = guiSkin.GetStyle(KVP.Key);
+                            if (oldValue != KVP.Value)
+                                guiSkin.SetStyle(KVP.Key, KVP.Value);
+                        }
+                        else
+                            guiSkin.SetStyle(KVP.Key, KVP.Value);
+                    }
+
+                    string[] oldStyleNames = guiSkin.StyleNames;
+                    foreach (var styleName in oldStyleNames)
+                    {
+                        if (!x.ContainsKey(styleName))
+                            guiSkin.RemoveStyle(styleName);
+                    }
+
+                    styles = x;
+                }
+                else
+                {
+                    foreach (var KVP in styles)
+                        guiSkin.RemoveStyle(KVP.Key);
+
+                    styles.Clear();
+                }
+
+                EditorApplication.SetDirty(guiSkin);
+            };
+
+            valuesField.OnValueChanged += x =>
+            {
+                guiSkin.SetStyle(x, styles[x]);
+                EditorApplication.SetDirty(guiSkin);
+            };
+
+            valuesField.OnValueRemoved += x =>
+            {
+                guiSkin.RemoveStyle(x);
+                EditorApplication.SetDirty(guiSkin);
+            };
+
+            Layout.AddSpace(10);
+        }
+
+        /// <summary>
+        /// Row element used for displaying GUI for GUI element style dictionary elements.
+        /// </summary>
+        public class GUIElementStyleEntry : GUIDictionaryFieldRow
+        {
+            private GUITextField keyField;
+            private GUIElementStyleGUI valueField;
+
+            /// <inheritdoc/>
+            protected override GUILayoutX CreateKeyGUI(GUILayoutY layout)
+            {
+                GUILayoutX titleLayout = layout.AddLayoutX();
+                keyField = new GUITextField(new LocEdString("Name"));
+                titleLayout.AddElement(keyField);
+
+                keyField.OnChanged += SetKey;
+
+                return titleLayout;
+            }
+
+            /// <inheritdoc/>
+            protected override void CreateValueGUI(GUILayoutY layout)
+            {
+                if(valueField == null)
+                    valueField = new GUIElementStyleGUI();
+
+                valueField.BuildGUI(layout, Depth);
+            }
+
+            /// <inheritdoc/>
+            protected override void OnEditModeChanged(bool editMode)
+            {
+                keyField.Disabled = !editMode;
+            }
+
+            /// <inheritdoc/>
+            internal protected override InspectableState Refresh()
+            {
+                keyField.Value = GetKey<string>();
+                return valueField.Refresh(GetValue<GUIElementStyle>());
+            }
+        }
+
+        /// <summary>
+        /// Creates GUI elements for editing/displaying <see cref="GUIElementStyle"/>
+        /// </summary>
+        private class GUIElementStyleGUI
+        {
+            private const int IndentAmount = 5;
+
+            private GUIResourceField fontField;
+            private GUIIntField fontSizeField;
+            private GUIEnumField horzAlignField;
+            private GUIEnumField vertAlignField;
+            private GUIEnumField imagePositionField;
+            private GUIToggleField wordWrapField;
+
+            private GUIElementStateStyleGUI normalGUI;
+            private GUIElementStateStyleGUI hoverGUI;
+            private GUIElementStateStyleGUI activeGUI;
+            private GUIElementStateStyleGUI focusedGUI;
+            private GUIElementStateStyleGUI normalOnGUI;
+            private GUIElementStateStyleGUI hoverOnGUI;
+            private GUIElementStateStyleGUI activeOnGUI;
+            private GUIElementStateStyleGUI focusedOnGUI;
+
+            private RectOffsetGUI borderGUI;
+            private RectOffsetGUI marginsGUI;
+            private RectOffsetGUI contentOffsetGUI;
+
+            private GUIToggleField fixedWidthField;
+            private GUIIntField widthField;
+            private GUIIntField minWidthField;
+            private GUIIntField maxWidthField;
+
+            private GUIToggleField fixedHeightField;
+            private GUIIntField heightField;
+            private GUIIntField minHeightField;
+            private GUIIntField maxHeightField;
+
+            private GUIElementStyle style;
+            private bool isExpanded;
+            private InspectableState modifiedState;
+
+            /// <summary>
+            /// Creates a new GUI element style GUI.
+            /// </summary>
+            public GUIElementStyleGUI()
+            {
+                normalGUI = new GUIElementStateStyleGUI();
+                hoverGUI = new GUIElementStateStyleGUI();
+                activeGUI = new GUIElementStateStyleGUI();
+                focusedGUI = new GUIElementStateStyleGUI();
+                normalOnGUI = new GUIElementStateStyleGUI();
+                hoverOnGUI = new GUIElementStateStyleGUI();
+                activeOnGUI = new GUIElementStateStyleGUI();
+                focusedOnGUI = new GUIElementStateStyleGUI();
+            }
+
+            /// <summary>
+            /// Builds GUI for the specified GUI element style.
+            /// </summary>
+            /// <param name="layout">Layout to append the GUI elements to.</param>
+            /// <param name="depth">Determines the depth at which the element is rendered.</param>
+            public void BuildGUI(GUILayout layout, int depth)
+            {
+                short backgroundDepth = (short)(Inspector.START_BACKGROUND_DEPTH - depth - 1);
+                string bgPanelStyle = depth % 2 == 0
+                    ? EditorStyles.InspectorContentBgAlternate
+                    : EditorStyles.InspectorContentBg;
+
+                GUIToggle foldout = new GUIToggle(new LocEdString("Style"), EditorStyles.Foldout);
+                GUITexture inspectorContentBg = new GUITexture(null, bgPanelStyle);
+
+                layout.AddElement(foldout);
+                GUIPanel panel = layout.AddPanel();
+                GUIPanel backgroundPanel = panel.AddPanel(backgroundDepth);
+                
+                backgroundPanel.AddElement(inspectorContentBg);
+
+                GUILayoutX guiIndentLayoutX = panel.AddLayoutX();
+                guiIndentLayoutX.AddSpace(IndentAmount);
+                GUILayoutY guiIndentLayoutY = guiIndentLayoutX.AddLayoutY();
+                guiIndentLayoutY.AddSpace(IndentAmount);
+                GUILayoutY contentLayout = guiIndentLayoutY.AddLayoutY();
+                guiIndentLayoutY.AddSpace(IndentAmount);
+                guiIndentLayoutX.AddSpace(IndentAmount);
+
+                fontField = new GUIResourceField(typeof (Font), new LocEdString("Font"));
+                fontSizeField = new GUIIntField(new LocEdString("Font size"));
+                horzAlignField = new GUIEnumField(typeof (TextHorzAlign), new LocEdString("Horizontal alignment"));
+                vertAlignField = new GUIEnumField(typeof(TextVertAlign), new LocEdString("Vertical alignment"));
+                imagePositionField = new GUIEnumField(typeof(GUIImagePosition), new LocEdString("Image position"));
+                wordWrapField = new GUIToggleField(new LocEdString("Word wrap"));
+
+                contentLayout.AddElement(fontField);
+                contentLayout.AddElement(fontSizeField);
+                contentLayout.AddElement(horzAlignField);
+                contentLayout.AddElement(vertAlignField);
+                contentLayout.AddElement(imagePositionField);
+                contentLayout.AddElement(wordWrapField);
+
+                normalGUI.BuildGUI(new LocEdString("Normal"), contentLayout);
+                hoverGUI.BuildGUI(new LocEdString("Hover"), contentLayout);
+                activeGUI.BuildGUI(new LocEdString("Active"), contentLayout);
+                focusedGUI.BuildGUI(new LocEdString("Focused"), contentLayout);
+                normalOnGUI.BuildGUI(new LocEdString("NormalOn"), contentLayout);
+                hoverOnGUI.BuildGUI(new LocEdString("HoverOn"), contentLayout);
+                activeOnGUI.BuildGUI(new LocEdString("ActiveOn"), contentLayout);
+                focusedOnGUI.BuildGUI(new LocEdString("FocusedOn"), contentLayout);
+
+                borderGUI = new RectOffsetGUI(new LocEdString("Border"), contentLayout);
+                marginsGUI = new RectOffsetGUI(new LocEdString("Margins"), contentLayout);
+                contentOffsetGUI = new RectOffsetGUI(new LocEdString("Content offset"), contentLayout);
+
+                fixedWidthField = new GUIToggleField(new LocEdString("Fixed width"));
+                widthField = new GUIIntField(new LocEdString("Width"));
+                minWidthField = new GUIIntField(new LocEdString("Min. width"));
+                maxWidthField = new GUIIntField(new LocEdString("Max. width"));
+
+                fixedHeightField = new GUIToggleField(new LocEdString("Fixed height"));
+                heightField = new GUIIntField(new LocEdString("Height"));
+                minHeightField = new GUIIntField(new LocEdString("Min. height"));
+                maxHeightField = new GUIIntField(new LocEdString("Max. height"));
+
+                contentLayout.AddElement(fixedWidthField);
+                contentLayout.AddElement(widthField);
+                contentLayout.AddElement(minWidthField);
+                contentLayout.AddElement(maxWidthField);
+
+                contentLayout.AddElement(fixedHeightField);
+                contentLayout.AddElement(heightField);
+                contentLayout.AddElement(minHeightField);
+                contentLayout.AddElement(maxHeightField);
+
+                foldout.OnToggled += x =>
+                {
+                    panel.Active = x;
+                    isExpanded = x;
+                };
+
+                fontField.OnChanged += x => 
+                {
+                    Font font = Resources.Load<Font>(x);
+
+                    GetStyle().Font = font; 
+                    MarkAsModified(); 
+                    ConfirmModify(); 
+                };
+                fontSizeField.OnChanged += x => { GetStyle().FontSize = x; MarkAsModified(); };
+                fontSizeField.OnFocusLost += ConfirmModify;
+                fontSizeField.OnConfirmed += ConfirmModify;
+                horzAlignField.OnSelectionChanged += x =>
+                {
+                    GetStyle().TextHorzAlign = (TextHorzAlign)x; 
+                    MarkAsModified(); 
+                    ConfirmModify();
+                };
+                vertAlignField.OnSelectionChanged += x =>
+                {
+                    GetStyle().TextVertAlign = (TextVertAlign)x; 
+                    MarkAsModified(); 
+                    ConfirmModify();
+                };
+                imagePositionField.OnSelectionChanged += x =>
+                {
+                    GetStyle().ImagePosition = (GUIImagePosition)x; 
+                    MarkAsModified(); 
+                    ConfirmModify();
+                };
+                wordWrapField.OnChanged += x => { GetStyle().WordWrap = x; MarkAsModified(); ConfirmModify(); };
+
+                normalGUI.OnChanged += x => { GetStyle().Normal = x; MarkAsModified(); ConfirmModify(); };
+                hoverGUI.OnChanged += x => { GetStyle().Hover = x; MarkAsModified(); ConfirmModify(); };
+                activeGUI.OnChanged += x => { GetStyle().Active = x; MarkAsModified(); ConfirmModify(); };
+                focusedGUI.OnChanged += x => { GetStyle().Focused = x; MarkAsModified(); ConfirmModify(); };
+                normalOnGUI.OnChanged += x => { GetStyle().NormalOn = x; MarkAsModified(); ConfirmModify(); };
+                hoverOnGUI.OnChanged += x => { GetStyle().HoverOn = x; MarkAsModified(); ConfirmModify(); };
+                activeOnGUI.OnChanged += x => { GetStyle().ActiveOn = x; MarkAsModified(); ConfirmModify(); };
+                focusedOnGUI.OnChanged += x => { GetStyle().FocusedOn = x; MarkAsModified(); ConfirmModify(); };
+
+                borderGUI.OnChanged += x => { GetStyle().Border = x; MarkAsModified(); };
+                marginsGUI.OnChanged += x => { GetStyle().Margins = x; MarkAsModified(); };
+                contentOffsetGUI.OnChanged += x => { GetStyle().ContentOffset = x; MarkAsModified(); };
+
+                borderGUI.OnConfirmed += ConfirmModify;
+                marginsGUI.OnConfirmed += ConfirmModify;
+                contentOffsetGUI.OnConfirmed += ConfirmModify;
+
+                fixedWidthField.OnChanged += x => { GetStyle().FixedWidth = x; MarkAsModified(); ConfirmModify(); };
+                widthField.OnChanged += x => GetStyle().Width = x;
+                widthField.OnFocusLost += ConfirmModify;
+                widthField.OnConfirmed += ConfirmModify;
+                minWidthField.OnChanged += x => GetStyle().MinWidth = x;
+                minWidthField.OnFocusLost += ConfirmModify;
+                minWidthField.OnConfirmed += ConfirmModify;
+                maxWidthField.OnChanged += x => GetStyle().MaxWidth = x;
+                maxWidthField.OnFocusLost += ConfirmModify;
+                maxWidthField.OnConfirmed += ConfirmModify;
+
+                fixedHeightField.OnChanged += x => { GetStyle().FixedHeight = x; MarkAsModified(); ConfirmModify(); };
+                heightField.OnChanged += x => GetStyle().Height = x;
+                heightField.OnFocusLost += ConfirmModify;
+                heightField.OnConfirmed += ConfirmModify;
+                minHeightField.OnChanged += x => GetStyle().MinHeight = x;
+                minHeightField.OnFocusLost += ConfirmModify;
+                minHeightField.OnConfirmed += ConfirmModify;
+                maxHeightField.OnChanged += x => GetStyle().MaxHeight = x;
+                maxHeightField.OnFocusLost += ConfirmModify;
+                maxHeightField.OnConfirmed += ConfirmModify;
+
+                foldout.Value = isExpanded;
+                panel.Active = isExpanded;
+            }
+
+            /// <summary>
+            /// Updates all GUI elements from the style if style changes.
+            /// </summary>
+            /// <param name="style">Style to display in the GUI.</param>
+            /// <returns>State representing was anything modified between two last calls to <see cref="Refresh"/>.</returns>
+            public InspectableState Refresh(GUIElementStyle style)
+            {
+                this.style = style;
+
+                InspectableState oldModifiedState = modifiedState;
+                if (modifiedState.HasFlag(InspectableState.Modified))
+                    modifiedState = InspectableState.NotModified;
+
+                if (style == null)
+                    return oldModifiedState;
+
+                fontField.Value = style.Font;
+                fontSizeField.Value = style.FontSize;
+                horzAlignField.Value = (ulong)style.TextHorzAlign;
+                vertAlignField.Value = (ulong)style.TextVertAlign;
+                imagePositionField.Value = (ulong)style.ImagePosition;
+                wordWrapField.Value = style.WordWrap;
+
+                normalGUI.Refresh(style.Normal);
+                hoverGUI.Refresh(style.Hover);
+                activeGUI.Refresh(style.Active);
+                focusedGUI.Refresh(style.Focused);
+                normalOnGUI.Refresh(style.NormalOn);
+                hoverOnGUI.Refresh(style.HoverOn);
+                activeOnGUI.Refresh(style.ActiveOn);
+                focusedOnGUI.Refresh(style.FocusedOn);
+
+                borderGUI.Refresh(style.Border);
+                marginsGUI.Refresh(style.Margins);
+                contentOffsetGUI.Refresh(style.ContentOffset);
+
+                fixedWidthField.Value = style.FixedWidth;
+                widthField.Value = style.Width;
+                minWidthField.Value = style.MinWidth;
+                maxWidthField.Value = style.MaxWidth;
+                fixedHeightField.Value = style.FixedHeight;
+                heightField.Value = style.Height;
+                minHeightField.Value = style.MinHeight;
+                maxHeightField.Value = style.MaxHeight;
+
+                widthField.Active = style.FixedWidth;
+                minWidthField.Active = !style.FixedWidth;
+                maxWidthField.Active = !style.FixedWidth;
+
+                heightField.Active = style.FixedHeight;
+                minHeightField.Active = !style.FixedHeight;
+                maxHeightField.Active = !style.FixedHeight;
+
+                return oldModifiedState;
+            }
+
+            /// <summary>
+            /// Returns the style displayed in the GUI.
+            /// </summary>
+            /// <returns>Style displayed in the GUI.</returns>
+            private GUIElementStyle GetStyle()
+            {
+                return style;
+            }
+
+            /// <summary>
+            /// Marks the contents of the style as modified.
+            /// </summary>
+            private void MarkAsModified()
+            {
+                modifiedState |= InspectableState.ModifyInProgress;
+            }
+
+            /// <summary>
+            /// Confirms any queued modifications, signaling parent element.
+            /// </summary>
+            private void ConfirmModify()
+            {
+                if (modifiedState.HasFlag(InspectableState.ModifyInProgress))
+                    modifiedState |= InspectableState.Modified;
+            }
+
+            /// <summary>
+            /// Creates GUI elements for editing/displaying <see cref="GUIElementStateStyle"/>
+            /// </summary>
+            private class GUIElementStateStyleGUI
+            {
+                private GUIElementStateStyle state;
+                private GUIToggle foldout;
+                private GUIResourceField textureField;
+                private GUIColorField textColorField;
+                private bool isExpanded;
+
+                /// <summary>
+                /// Triggered when some value in the style state changes.
+                /// </summary>
+                public Action<GUIElementStateStyle> OnChanged;
+
+                /// <summary>
+                /// Creates a new GUI element state style GUI.
+                /// </summary>
+                public GUIElementStateStyleGUI()
+                { }
+
+                /// <summary>
+                /// Builds the GUI for the specified state style.
+                /// </summary>
+                /// <param name="title">Text to display on the title bar.</param>
+                /// <param name="layout">Layout to append the GUI elements to.</param>
+                public void BuildGUI(LocString title, GUILayout layout)
+                {
+                    foldout = new GUIToggle(title, EditorStyles.Foldout);
+                    textureField = new GUIResourceField(typeof(SpriteTexture), new LocEdString("Texture"));
+                    textColorField = new GUIColorField(new LocEdString("Text color"));
+
+                    foldout.OnToggled += x =>
+                    {
+                        textureField.Active = x;
+                        textColorField.Active = x;
+                        isExpanded = x;
+                    };
+
+                    textureField.OnChanged += x =>
+                    {
+                        SpriteTexture texture = Resources.Load<SpriteTexture>(x);
+                        state.Texture = texture;
+
+                        if (OnChanged != null)
+                            OnChanged(state);
+                    };
+
+                    textColorField.OnChanged += x =>
+                    {
+                        state.TextColor = x;
+
+                        if (OnChanged != null)
+                            OnChanged(state);
+                    };
+
+                    layout.AddElement(foldout);
+                    layout.AddElement(textureField);
+                    layout.AddElement(textColorField);
+
+                    foldout.Value = isExpanded;
+                    textureField.Active = isExpanded;
+                    textColorField.Active = isExpanded;
+                }
+
+                /// <summary>
+                /// Updates all GUI elements from the current state values.
+                /// </summary>
+                /// <param name="state">State object to display in the GUI.</param>
+                public void Refresh(GUIElementStateStyle state)
+                {
+                    this.state = state;
+
+                    textureField.Value = state.Texture;
+                    textColorField.Value = state.TextColor;
+                }
+            }
+
+            /// <summary>
+            /// Creates GUI elements for editing/displaying <see cref="RectOffset"/>
+            /// </summary>
+            private class RectOffsetGUI
+            {
+                private RectOffset offset;
+                private GUIIntField offsetLeftField;
+                private GUIIntField offsetRightField;
+                private GUIIntField offsetTopField;
+                private GUIIntField offsetBottomField;
+
+                /// <summary>
+                /// Triggered when some value in the offset rectangle changes.
+                /// </summary>
+                public Action<RectOffset> OnChanged;
+
+                /// <summary>
+                /// Triggered when the user confirms input.
+                /// </summary>
+                public Action OnConfirmed;
+
+                /// <summary>
+                /// Creates a new rectangle offset GUI.
+                /// </summary>
+                /// <param name="title">Text to display on the title bar.</param>
+                /// <param name="layout">Layout to append the GUI elements to.</param>
+                public RectOffsetGUI(LocString title, GUILayout layout)
+                {
+                    GUILayoutX rectLayout = layout.AddLayoutX();
+                    rectLayout.AddElement(new GUILabel(title, GUIOption.FixedWidth(100)));
+                    GUILayoutY rectContentLayout = rectLayout.AddLayoutY();
+
+                    GUILayoutX rectTopRow = rectContentLayout.AddLayoutX();
+                    GUILayoutX rectBotRow = rectContentLayout.AddLayoutX();
+
+                    offsetLeftField = new GUIIntField(new LocEdString("Left"), 40);
+                    offsetRightField = new GUIIntField(new LocEdString("Right"), 40);
+                    offsetTopField = new GUIIntField(new LocEdString("Top"), 40);
+                    offsetBottomField = new GUIIntField(new LocEdString("Bottom"), 40);
+
+                    rectTopRow.AddElement(offsetLeftField);
+                    rectTopRow.AddElement(offsetRightField);
+                    rectBotRow.AddElement(offsetTopField);
+                    rectBotRow.AddElement(offsetBottomField);
+
+                    offsetLeftField.OnChanged += x =>
+                    {
+                        offset.left = x;
+
+                        if(OnChanged != null)
+                            OnChanged(offset);
+                    };
+
+                    offsetRightField.OnChanged += x =>
+                    {
+                        offset.right = x;
+
+                        if (OnChanged != null)
+                            OnChanged(offset);
+                    };
+
+                    offsetTopField.OnChanged += x =>
+                    {
+                        offset.top = x;
+
+                        if (OnChanged != null)
+                            OnChanged(offset);
+                    };
+
+                    offsetBottomField.OnChanged += x =>
+                    {
+                        offset.bottom = x;
+
+                        if (OnChanged != null)
+                            OnChanged(offset);
+                    };
+
+                    Action DoOnConfirmed = () =>
+                    {
+                        if (OnConfirmed != null)
+                            OnConfirmed();
+                    };
+
+                    offsetLeftField.OnConfirmed += DoOnConfirmed;
+                    offsetLeftField.OnFocusLost += DoOnConfirmed;
+                    offsetRightField.OnConfirmed += DoOnConfirmed;
+                    offsetRightField.OnFocusLost += DoOnConfirmed;
+                    offsetTopField.OnConfirmed += DoOnConfirmed;
+                    offsetTopField.OnFocusLost += DoOnConfirmed;
+                    offsetBottomField.OnConfirmed += DoOnConfirmed;
+                    offsetBottomField.OnFocusLost += DoOnConfirmed;
+                }
+
+                /// <summary>
+                /// Updates all GUI elements from the offset.
+                /// </summary>
+                /// <param name="offset">Offset to update the GUI to.</param>
+                public void Refresh(RectOffset offset)
+                {
+                    this.offset = offset;
+
+                    offsetLeftField.Value = offset.left;
+                    offsetRightField.Value = offset.right;
+                    offsetTopField.Value = offset.top;
+                    offsetBottomField.Value = offset.bottom;
+                }
+            }
+        }
+    }
+}

+ 2 - 0
MBansheeEditor/Inspectors/RenderableInspector.cs

@@ -122,6 +122,8 @@ namespace BansheeEditor
             materials = renderable.Materials;
             materials = renderable.Materials;
             materialsField = GUIArrayField<Material, MaterialArrayRow>.Create(new LocEdString("Materials"), materials, Layout);
             materialsField = GUIArrayField<Material, MaterialArrayRow>.Create(new LocEdString("Materials"), materials, Layout);
             materialsField.OnChanged += x => { materials = x; };
             materialsField.OnChanged += x => { materials = x; };
+            materialsField.IsExpanded = Persistent.GetBool("materialsField_Expanded");
+            materialsField.OnExpand += x => Persistent.SetBool("materialsField_Expanded", x);
 
 
             meshField.OnChanged += x =>
             meshField.OnChanged += x =>
             {
             {

+ 170 - 168
MBansheeEditor/Inspectors/StringTableInspector.cs

@@ -1,168 +1,170 @@
-using System;
-using System.Collections.Generic;
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Renders an inspector for the <see cref="StringTable"/> resource.
-    /// </summary>
-    [CustomInspector(typeof(StringTable))]
-    internal class StringTableInspector : Inspector
-    {
-        private GUIEnumField languageField;
-        private GUIDictionaryField<string, string, StringTableEntry> valuesField;
-
-        private Dictionary<string, string> strings = new Dictionary<string,string>();
-
-        /// <inheritdoc/>
-        protected internal override void Initialize()
-        {
-            BuildGUI();
-        }
-
-        /// <inheritdoc/>
-        protected internal override InspectableState Refresh()
-        {
-            // Note: We're ignoring changes to the string table made externally here in order to avoid a lot of checks.
-            if ((Language) languageField.Value != StringTables.ActiveLanguage)
-            {
-                languageField.Value = (ulong)StringTables.ActiveLanguage;
-                BuildGUI();
-            }
-
-            valuesField.Refresh();
-
-            return InspectableState.NotModified;
-        }
-
-        /// <summary>
-        /// Recreates all the GUI elements used by this inspector.
-        /// </summary>
-        private void BuildGUI()
-        {
-            Layout.Clear();
-            strings.Clear();
-
-            StringTable stringTable = InspectedObject as StringTable;
-            if(stringTable == null)
-                return;
-
-            string[] identifiers = stringTable.Identifiers;
-            foreach (var identifier in identifiers)
-                strings[identifier] = stringTable.GetString(identifier);
-
-            languageField = new GUIEnumField(typeof (Language));
-            languageField.OnSelectionChanged += x =>
-            {
-                StringTables.ActiveLanguage = (Language)x;
-                BuildGUI();
-                Refresh();
-            };
-
-            Layout.AddElement(languageField);
-
-            valuesField = GUIDictionaryField<string, string, StringTableEntry>.Create(
-                new LocEdString("Strings"), strings, Layout);
-
-            valuesField.OnChanged += x =>
-            {
-                if (x != null)
-                {
-                    foreach (var KVP in x)
-                    {
-                        if (stringTable.Contains(KVP.Key))
-                        {
-                            string oldValue = stringTable.GetString(KVP.Key);
-                            if (oldValue != KVP.Value)
-                                stringTable.SetString(KVP.Key, KVP.Value);
-                        }
-                        else
-                            stringTable.SetString(KVP.Key, KVP.Value);
-                    }
-
-                    string[] oldIdentifiers = stringTable.Identifiers;
-                    foreach (var identifier in oldIdentifiers)
-                    {
-                        if (!x.ContainsKey(identifier))
-                            stringTable.RemoveString(identifier);
-                    }
-
-                    strings = x;
-                }
-                else
-                {
-                    foreach (var KVP in strings)
-                        stringTable.RemoveString(KVP.Key);
-
-                    strings.Clear();
-                }
-
-                EditorApplication.SetDirty(stringTable);
-            };
-
-            valuesField.OnValueChanged += x =>
-            {
-                stringTable.SetString(x, strings[x]);
-                EditorApplication.SetDirty(stringTable);
-            };
-
-            valuesField.OnValueRemoved += x =>
-            {
-                stringTable.RemoveString(x);
-                EditorApplication.SetDirty(stringTable);
-            };
-            
-            Layout.AddSpace(10);
-        }
-
-        /// <summary>
-        /// Row element used for displaying GUI for string table dictionary elements.
-        /// </summary>
-        public class StringTableEntry : GUIDictionaryFieldRow
-        {
-            private GUITextField keyField;
-            private GUITextField valueField;
-
-            /// <inheritdoc/>
-            protected override GUILayoutX CreateKeyGUI(GUILayoutY layout)
-            {
-                GUILayoutX titleLayout = layout.AddLayoutX();
-                keyField = new GUITextField(new LocEdString("Identifier"));
-                titleLayout.AddElement(keyField);
-
-                keyField.OnChanged += SetKey;
-
-                return titleLayout;
-            }
-
-            /// <inheritdoc/>
-            protected override void CreateValueGUI(GUILayoutY layout)
-            {
-                string value = GetValue<string>();
-
-                valueField = new GUITextField(new LocEdString(value));
-                layout.AddElement(valueField);
-
-                valueField.OnChanged += x => { SetValue(x); MarkAsModified(); };
-                valueField.OnConfirmed += ConfirmModify;
-                valueField.OnFocusLost += ConfirmModify;
-            }
-
-            /// <inheritdoc/>
-            protected override void OnEditModeChanged(bool editMode)
-            {
-                keyField.Disabled = !editMode;
-            }
-
-            /// <inheritdoc/>
-            internal protected override InspectableState Refresh()
-            {
-                keyField.Value = GetKey<string>();
-                valueField.Value = GetValue<string>();
-
-                return base.Refresh();
-            }
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Renders an inspector for the <see cref="StringTable"/> resource.
+    /// </summary>
+    [CustomInspector(typeof(StringTable))]
+    internal class StringTableInspector : Inspector
+    {
+        private GUIEnumField languageField;
+        private GUIDictionaryField<string, string, StringTableEntry> valuesField;
+
+        private Dictionary<string, string> strings = new Dictionary<string,string>();
+
+        /// <inheritdoc/>
+        protected internal override void Initialize()
+        {
+            BuildGUI();
+        }
+
+        /// <inheritdoc/>
+        protected internal override InspectableState Refresh()
+        {
+            // Note: We're ignoring changes to the string table made externally here in order to avoid a lot of checks.
+            if ((Language) languageField.Value != StringTables.ActiveLanguage)
+            {
+                languageField.Value = (ulong)StringTables.ActiveLanguage;
+                BuildGUI();
+            }
+
+            valuesField.Refresh();
+
+            return InspectableState.NotModified;
+        }
+
+        /// <summary>
+        /// Recreates all the GUI elements used by this inspector.
+        /// </summary>
+        private void BuildGUI()
+        {
+            Layout.Clear();
+            strings.Clear();
+
+            StringTable stringTable = InspectedObject as StringTable;
+            if(stringTable == null)
+                return;
+
+            string[] identifiers = stringTable.Identifiers;
+            foreach (var identifier in identifiers)
+                strings[identifier] = stringTable.GetString(identifier);
+
+            languageField = new GUIEnumField(typeof (Language));
+            languageField.OnSelectionChanged += x =>
+            {
+                StringTables.ActiveLanguage = (Language)x;
+                BuildGUI();
+                Refresh();
+            };
+
+            Layout.AddElement(languageField);
+
+            valuesField = GUIDictionaryField<string, string, StringTableEntry>.Create(
+                new LocEdString("Strings"), strings, Layout);
+            valuesField.IsExpanded = Persistent.GetBool("valuesField_Expanded");
+            valuesField.OnExpand += x => Persistent.SetBool("valuesField_Expanded", x);
+
+            valuesField.OnChanged += x =>
+            {
+                if (x != null)
+                {
+                    foreach (var KVP in x)
+                    {
+                        if (stringTable.Contains(KVP.Key))
+                        {
+                            string oldValue = stringTable.GetString(KVP.Key);
+                            if (oldValue != KVP.Value)
+                                stringTable.SetString(KVP.Key, KVP.Value);
+                        }
+                        else
+                            stringTable.SetString(KVP.Key, KVP.Value);
+                    }
+
+                    string[] oldIdentifiers = stringTable.Identifiers;
+                    foreach (var identifier in oldIdentifiers)
+                    {
+                        if (!x.ContainsKey(identifier))
+                            stringTable.RemoveString(identifier);
+                    }
+
+                    strings = x;
+                }
+                else
+                {
+                    foreach (var KVP in strings)
+                        stringTable.RemoveString(KVP.Key);
+
+                    strings.Clear();
+                }
+
+                EditorApplication.SetDirty(stringTable);
+            };
+
+            valuesField.OnValueChanged += x =>
+            {
+                stringTable.SetString(x, strings[x]);
+                EditorApplication.SetDirty(stringTable);
+            };
+
+            valuesField.OnValueRemoved += x =>
+            {
+                stringTable.RemoveString(x);
+                EditorApplication.SetDirty(stringTable);
+            };
+            
+            Layout.AddSpace(10);
+        }
+
+        /// <summary>
+        /// Row element used for displaying GUI for string table dictionary elements.
+        /// </summary>
+        public class StringTableEntry : GUIDictionaryFieldRow
+        {
+            private GUITextField keyField;
+            private GUITextField valueField;
+
+            /// <inheritdoc/>
+            protected override GUILayoutX CreateKeyGUI(GUILayoutY layout)
+            {
+                GUILayoutX titleLayout = layout.AddLayoutX();
+                keyField = new GUITextField(new LocEdString("Identifier"));
+                titleLayout.AddElement(keyField);
+
+                keyField.OnChanged += SetKey;
+
+                return titleLayout;
+            }
+
+            /// <inheritdoc/>
+            protected override void CreateValueGUI(GUILayoutY layout)
+            {
+                string value = GetValue<string>();
+
+                valueField = new GUITextField(new LocEdString(value));
+                layout.AddElement(valueField);
+
+                valueField.OnChanged += x => { SetValue(x); MarkAsModified(); };
+                valueField.OnConfirmed += ConfirmModify;
+                valueField.OnFocusLost += ConfirmModify;
+            }
+
+            /// <inheritdoc/>
+            protected override void OnEditModeChanged(bool editMode)
+            {
+                keyField.Disabled = !editMode;
+            }
+
+            /// <inheritdoc/>
+            internal protected override InspectableState Refresh()
+            {
+                keyField.Value = GetKey<string>();
+                valueField.Value = GetValue<string>();
+
+                return base.Refresh();
+            }
+        }
+    }
+}

+ 4 - 7
SBansheeEditor/Source/BsScriptEditorWindow.cpp

@@ -135,11 +135,7 @@ namespace BansheeEngine
 		{
 		{
 			auto iterFind = OpenScriptEditorWindows.find(mName);
 			auto iterFind = OpenScriptEditorWindows.find(mName);
 			if (iterFind != OpenScriptEditorWindows.end())
 			if (iterFind != OpenScriptEditorWindows.end())
-			{
 				iterFind->second.gcHandle = mono_gchandle_new(mManagedInstance, false);
 				iterFind->second.gcHandle = mono_gchandle_new(mManagedInstance, false);
-			}
-
-			mEditorWidget->triggerOnInitialize();
 		}
 		}
 		else
 		else
 		{
 		{
@@ -415,6 +411,8 @@ namespace BansheeEngine
 			// for some extra speed.
 			// for some extra speed.
 			MonoUtil::invokeThunk(mOnInitializeThunk, mManagedInstance);
 			MonoUtil::invokeThunk(mOnInitializeThunk, mManagedInstance);
 		}
 		}
+
+		mIsInitialized = true;
 	}
 	}
 
 
 	void ScriptEditorWidget::triggerOnDestroy()
 	void ScriptEditorWidget::triggerOnDestroy()
@@ -425,15 +423,14 @@ namespace BansheeEngine
 			// for some extra speed.
 			// for some extra speed.
 			MonoUtil::invokeThunk(mOnDestroyThunk, mManagedInstance);
 			MonoUtil::invokeThunk(mOnDestroyThunk, mManagedInstance);
 		}
 		}
+
+		mIsInitialized = false;
 	}
 	}
 
 
 	void ScriptEditorWidget::update()
 	void ScriptEditorWidget::update()
 	{
 	{
 		if (!mIsInitialized)
 		if (!mIsInitialized)
-		{
 			triggerOnInitialize();
 			triggerOnInitialize();
-			mIsInitialized = true;
-		}
 
 
 		if (mUpdateThunk != nullptr && mManagedInstance != nullptr)
 		if (mUpdateThunk != nullptr && mManagedInstance != nullptr)
 		{
 		{

+ 562 - 557
SBansheeEngine/Source/BsScriptAssemblyManager.cpp

@@ -1,558 +1,563 @@
-#include "BsScriptAssemblyManager.h"
-#include "BsScriptResourceManager.h"
-#include "BsScriptGameObjectManager.h"
-#include "BsManagedSerializableObjectInfo.h"
-#include "BsMonoManager.h"
-#include "BsMonoAssembly.h"
-#include "BsMonoClass.h"
-#include "BsMonoField.h"
-#include "BsMonoMethod.h"
-#include "BsMonoProperty.h"
-#include "BsScriptManagedResource.h"
-#include "BsScriptTexture2D.h"
-#include "BsScriptTexture3D.h"
-#include "BsScriptTextureCube.h"
-#include "BsScriptSpriteTexture.h"
-#include "BsScriptMaterial.h"
-#include "BsScriptMesh.h"
-#include "BsScriptFont.h"
-#include "BsScriptShader.h"
-#include "BsScriptShaderInclude.h"
-#include "BsScriptPlainText.h"
-#include "BsScriptScriptCode.h"
-#include "BsScriptStringTable.h"
-#include "BsScriptGUISkin.h"
-#include "BsScriptPrefab.h"
-#include "BsMonoUtil.h"
-#include "BsRTTIType.h"
-
-namespace BansheeEngine
-{
-	ScriptAssemblyManager::ScriptAssemblyManager()
-		:mBaseTypesInitialized(false), mSerializeObjectAttribute(nullptr), mDontSerializeFieldAttribute(nullptr), 
-		mComponentClass(nullptr), mSceneObjectClass(nullptr), mSerializeFieldAttribute(nullptr), mHideInInspectorAttribute(nullptr), 
-		mSystemArrayClass(nullptr), mSystemGenericListClass(nullptr), mSystemGenericDictionaryClass(nullptr), mMissingComponentClass(nullptr),
-		mSystemTypeClass(nullptr)
-	{
-
-	}
-
-	ScriptAssemblyManager::~ScriptAssemblyManager()
-	{
-
-	}
-
-	Vector<String> ScriptAssemblyManager::getScriptAssemblies() const
-	{
-		Vector<String> initializedAssemblies;
-		for (auto& assemblyPair : mAssemblyInfos)
-			initializedAssemblies.push_back(assemblyPair.first);
-
-		return initializedAssemblies;
-	}
-
-	void ScriptAssemblyManager::loadAssemblyInfo(const String& assemblyName)
-	{
-		if(!mBaseTypesInitialized)
-			initializeBaseTypes();
-
-		// Process all classes and fields
-		UINT32 mUniqueTypeId = 1;
-
-		MonoAssembly* curAssembly = MonoManager::instance().getAssembly(assemblyName);
-		if(curAssembly == nullptr)
-			return;
-
-		std::shared_ptr<ManagedSerializableAssemblyInfo> assemblyInfo = bs_shared_ptr_new<ManagedSerializableAssemblyInfo>();
-		assemblyInfo->mName = assemblyName;
-
-		mAssemblyInfos[assemblyName] = assemblyInfo;
-
-		MonoClass* managedResourceClass = ScriptManagedResource::getMetaData()->scriptClass;
-
-		// Populate class data
-		const Vector<MonoClass*>& allClasses = curAssembly->getAllClasses();
-		for(auto& curClass : allClasses)
-		{
-			if ((curClass->isSubClassOf(mComponentClass) || curClass->isSubClassOf(managedResourceClass) ||
-				curClass->hasAttribute(mSerializeObjectAttribute)) && curClass != mComponentClass && curClass != managedResourceClass)
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoObject> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoObject>();
-				typeInfo->mTypeNamespace = curClass->getNamespace();
-				typeInfo->mTypeName = curClass->getTypeName();
-				typeInfo->mTypeId = mUniqueTypeId++;
-
-				MonoType* monoType = mono_class_get_type(curClass->_getInternalClass());
-				int monoPrimitiveType = mono_type_get_type(monoType);
-
-				if(monoPrimitiveType == MONO_TYPE_VALUETYPE)
-					typeInfo->mValueType = true;
-				else
-					typeInfo->mValueType = false;
-
-				std::shared_ptr<ManagedSerializableObjectInfo> objInfo = bs_shared_ptr_new<ManagedSerializableObjectInfo>();
-
-				objInfo->mTypeInfo = typeInfo;
-				objInfo->mMonoClass = curClass;
-
-				assemblyInfo->mTypeNameToId[objInfo->getFullTypeName()] = typeInfo->mTypeId;
-				assemblyInfo->mObjectInfos[typeInfo->mTypeId] = objInfo;
-			}
-		}
-
-		// Populate field data
-		for(auto& curClassInfo : assemblyInfo->mObjectInfos)
-		{
-			std::shared_ptr<ManagedSerializableObjectInfo> objInfo = curClassInfo.second;
-
-			UINT32 mUniqueFieldId = 1;
-			const Vector<MonoField*>& fields = objInfo->mMonoClass->getAllFields();
-
-			for(auto& field : fields)
-			{
-				if(field->isStatic())
-					continue;
-
-				ManagedSerializableTypeInfoPtr typeInfo = getTypeInfo(field->getType());
-				if (typeInfo == nullptr)
-					continue;
-
-				std::shared_ptr<ManagedSerializableFieldInfo> fieldInfo = bs_shared_ptr_new<ManagedSerializableFieldInfo>();
-				fieldInfo->mFieldId = mUniqueFieldId++;
-				fieldInfo->mName = field->getName();
-				fieldInfo->mMonoField = field;
-				fieldInfo->mTypeInfo = typeInfo;
-				fieldInfo->mParentTypeId = objInfo->mTypeInfo->mTypeId;
-				
-				MonoFieldVisibility visibility = field->getVisibility();
-				if (visibility == MonoFieldVisibility::Public)
-				{
-					if (!field->hasAttribute(mDontSerializeFieldAttribute))
-						fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Serializable);
-
-					if (!field->hasAttribute(mHideInInspectorAttribute))
-						fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Inspectable);
-				}
-				else
-				{
-					if (field->hasAttribute(mSerializeFieldAttribute))
-						fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Serializable);
-				}
-
-				objInfo->mFieldNameToId[fieldInfo->mName] = fieldInfo->mFieldId;
-				objInfo->mFields[fieldInfo->mFieldId] = fieldInfo;
-			}
-		}
-
-		// Form parent/child connections
-		for(auto& curClass : assemblyInfo->mObjectInfos)
-		{
-			MonoClass* base = curClass.second->mMonoClass->getBaseClass();
-			while(base != nullptr)
-			{
-				std::shared_ptr<ManagedSerializableObjectInfo> baseObjInfo;
-				if(getSerializableObjectInfo(base->getNamespace(), base->getTypeName(), baseObjInfo))
-				{
-					curClass.second->mBaseClass = baseObjInfo;
-					baseObjInfo->mDerivedClasses.push_back(curClass.second);
-
-					break;
-				}
-
-				base = base->getBaseClass();
-			}
-		}
-	}
-
-	void ScriptAssemblyManager::clearAssemblyInfo()
-	{
-		clearScriptObjects();
-		mAssemblyInfos.clear();
-	}
-
-	ManagedSerializableTypeInfoPtr ScriptAssemblyManager::getTypeInfo(MonoClass* monoClass)
-	{
-		if(!mBaseTypesInitialized)
-			BS_EXCEPT(InvalidStateException, "Calling determineType without previously initializing base types.");
-
-		MonoType* monoType = mono_class_get_type(monoClass->_getInternalClass());
-		int monoPrimitiveType = mono_type_get_type(monoType);
-		
-		// If enum get the enum base data type
-		bool isEnum = mono_class_is_enum(monoClass->_getInternalClass()) == 1;
-		if (isEnum)
-		{
-			MonoType* underlyingType = mono_type_get_underlying_type(monoType);
-			monoPrimitiveType = mono_type_get_type(underlyingType);
-		}
-
-		//  Determine field type
-		switch(monoPrimitiveType)
-		{
-		case MONO_TYPE_BOOLEAN:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::Bool;
-				return typeInfo;
-			}
-		case MONO_TYPE_CHAR:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::Char;
-				return typeInfo;
-			}
-		case MONO_TYPE_I1:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::I8;
-				return typeInfo;
-			}
-		case MONO_TYPE_U1:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::U8;
-				return typeInfo;
-			}
-		case MONO_TYPE_I2:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::I16;
-				return typeInfo;
-			}
-		case MONO_TYPE_U2:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::U16;
-				return typeInfo;
-			}
-		case MONO_TYPE_I4:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::I32;
-				return typeInfo;
-			}
-		case MONO_TYPE_U4:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::U32;
-				return typeInfo;
-			}
-		case MONO_TYPE_I8:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::I64;
-				return typeInfo;
-			}
-		case MONO_TYPE_U8:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::U64;
-				return typeInfo;
-			}
-		case MONO_TYPE_STRING:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::String;
-				return typeInfo;
-			}
-		case MONO_TYPE_R4:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::Float;
-				return typeInfo;
-			}
-		case MONO_TYPE_R8:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::Double;
-				return typeInfo;
-			}
-		case MONO_TYPE_CLASS:
-			if(monoClass->isSubClassOf(ScriptTexture2D::getMetaData()->scriptClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::Texture2DRef;
-				return typeInfo;
-			}
-			if (monoClass->isSubClassOf(ScriptTexture3D::getMetaData()->scriptClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::Texture3DRef;
-				return typeInfo;
-			}
-			if (monoClass->isSubClassOf(ScriptTextureCube::getMetaData()->scriptClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::TextureCubeRef;
-				return typeInfo;
-			}
-			else if (monoClass->isSubClassOf(ScriptSpriteTexture::getMetaData()->scriptClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::SpriteTextureRef;
-				return typeInfo;
-			}
-			else if (monoClass->isSubClassOf(ScriptManagedResource::getMetaData()->scriptClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::ManagedResourceRef;
-				return typeInfo;
-			}
-			else if (monoClass->isSubClassOf(ScriptShader::getMetaData()->scriptClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::ShaderRef;
-				return typeInfo;
-			}
-			else if (monoClass->isSubClassOf(ScriptShaderInclude::getMetaData()->scriptClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::ShaderIncludeRef;
-				return typeInfo;
-			}
-			else if (monoClass->isSubClassOf(ScriptMaterial::getMetaData()->scriptClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::MaterialRef;
-				return typeInfo;
-			}
-			else if (monoClass->isSubClassOf(ScriptMesh::getMetaData()->scriptClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::MeshRef;
-				return typeInfo;
-			}
-			else if (monoClass->isSubClassOf(ScriptPlainText::getMetaData()->scriptClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::PlainTextRef;
-				return typeInfo;
-			}
-			else if (monoClass->isSubClassOf(ScriptScriptCode::getMetaData()->scriptClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::ScriptCodeRef;
-				return typeInfo;
-			}
-			else if (monoClass->isSubClassOf(ScriptPrefab::getMetaData()->scriptClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::PrefabRef;
-				return typeInfo;
-			}
-			else if (monoClass->isSubClassOf(ScriptFont::getMetaData()->scriptClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::FontRef;
-				return typeInfo;
-			}
-			else if (monoClass->isSubClassOf(ScriptStringTable::getMetaData()->scriptClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::StringTableRef;
-				return typeInfo;
-			}
-			else if (monoClass->isSubClassOf(ScriptGUISkin::getMetaData()->scriptClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::GUISkinRef;
-				return typeInfo;
-			}
-			else if(monoClass->isSubClassOf(mSceneObjectClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::SceneObjectRef;
-				return typeInfo;
-			}
-			else if(monoClass->isSubClassOf(mComponentClass))
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
-				typeInfo->mType = ScriptPrimitiveType::ComponentRef;
-				return typeInfo;
-			}
-			else
-			{
-				std::shared_ptr<ManagedSerializableObjectInfo> objInfo;
-				if (getSerializableObjectInfo(monoClass->getNamespace(), monoClass->getTypeName(), objInfo))
-					return objInfo->mTypeInfo;
-			}
-
-			break;
-		case MONO_TYPE_VALUETYPE:
-			{
-				std::shared_ptr<ManagedSerializableObjectInfo> objInfo;
-				if (getSerializableObjectInfo(monoClass->getNamespace(), monoClass->getTypeName(), objInfo))
-					return objInfo->mTypeInfo;
-			}
-
-			break;
-		case MONO_TYPE_GENERICINST:
-			if(monoClass->getFullName() == mSystemGenericListClass->getFullName()) // Full name is part of CIL spec, so it is just fine to compare like this
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoList> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoList>();
-
-				MonoProperty& itemProperty = monoClass->getProperty("Item");
-				MonoClass* itemClass = itemProperty.getReturnType();
-
-				if(itemClass != nullptr)
-					typeInfo->mElementType = getTypeInfo(itemClass);
-
-				return typeInfo;
-			}
-			else if(monoClass->getFullName() == mSystemGenericDictionaryClass->getFullName())
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoDictionary> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoDictionary>();
-
-				MonoMethod* getEnumerator = monoClass->getMethod("GetEnumerator");
-				MonoClass* enumClass = getEnumerator->getReturnType();
-
-				MonoProperty& currentProp = enumClass->getProperty("Current");
-				MonoClass* keyValuePair = currentProp.getReturnType();
-
-				MonoProperty& keyProperty = keyValuePair->getProperty("Key");
-				MonoProperty& valueProperty = keyValuePair->getProperty("Value");
-
-				MonoClass* keyClass = keyProperty.getReturnType();
-				if(keyClass != nullptr)
-					typeInfo->mKeyType = getTypeInfo(keyClass);
-
-				MonoClass* valueClass = valueProperty.getReturnType();
-				if(valueClass != nullptr)
-					typeInfo->mValueType = getTypeInfo(valueClass);
-
-				return typeInfo;
-			}
-			break;
-		case MONO_TYPE_SZARRAY:
-		case MONO_TYPE_ARRAY:
-			{
-				std::shared_ptr<ManagedSerializableTypeInfoArray> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoArray>();
-
-				::MonoClass* elementClass = mono_class_get_element_class(monoClass->_getInternalClass());
-				if(elementClass != nullptr)
-				{
-					MonoClass* monoElementClass = MonoManager::instance().findClass(elementClass);
-					if(monoElementClass != nullptr)
-						typeInfo->mElementType = getTypeInfo(monoElementClass);
-				}
-
-				typeInfo->mRank = (UINT32)mono_class_get_rank(monoClass->_getInternalClass());
-
-				return typeInfo;
-			}
-		}
-
-		return nullptr;
-	}
-
-	void ScriptAssemblyManager::clearScriptObjects()
-	{
-		mBaseTypesInitialized = false;
-
-		mSystemArrayClass = nullptr;
-		mSystemGenericListClass = nullptr;
-		mSystemGenericDictionaryClass = nullptr;
-		mSystemTypeClass = nullptr;
-
-		mSerializeObjectAttribute = nullptr;
-		mDontSerializeFieldAttribute = nullptr;
-
-		mComponentClass = nullptr;
-		mSceneObjectClass = nullptr;
-		mMissingComponentClass = nullptr;
-
-		mSerializeFieldAttribute = nullptr;
-		mHideInInspectorAttribute = nullptr;
-	}
-
-	void ScriptAssemblyManager::initializeBaseTypes()
-	{
-		// Get necessary classes for detecting needed class & field information
-		MonoAssembly* corlib = MonoManager::instance().getAssembly("corlib");
-		if(corlib == nullptr)
-			BS_EXCEPT(InvalidStateException, "corlib assembly is not loaded.");
-
-		MonoAssembly* bansheeEngineAssembly = MonoManager::instance().getAssembly(ENGINE_ASSEMBLY);
-		if(bansheeEngineAssembly == nullptr)
-			BS_EXCEPT(InvalidStateException, String(ENGINE_ASSEMBLY) +  " assembly is not loaded.");
-
-		mSystemArrayClass = corlib->getClass("System", "Array");
-		if(mSystemArrayClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find System.Array managed class.");
-
-		mSystemGenericListClass = corlib->getClass("System.Collections.Generic", "List`1");
-		if(mSystemGenericListClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find List<T> managed class.");
-
-		mSystemGenericDictionaryClass = corlib->getClass("System.Collections.Generic", "Dictionary`2");
-		if(mSystemGenericDictionaryClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find Dictionary<TKey, TValue> managed class.");
-
-		mSystemTypeClass = corlib->getClass("System", "Type");
-		if (mSystemTypeClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find Type managed class.");
-
-		mSerializeObjectAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "SerializeObject");
-		if(mSerializeObjectAttribute == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find SerializableObject managed class.");
-
-		mDontSerializeFieldAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "DontSerializeField");
-		if(mDontSerializeFieldAttribute == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find DontSerializeField managed class.");
-
-		mComponentClass = bansheeEngineAssembly->getClass("BansheeEngine", "Component");
-		if(mComponentClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find Component managed class.");
-
-		mMissingComponentClass = bansheeEngineAssembly->getClass("BansheeEngine", "MissingComponent");
-		if (mMissingComponentClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find MissingComponent managed class.");
-
-		mSceneObjectClass = bansheeEngineAssembly->getClass("BansheeEngine", "SceneObject");
-		if(mSceneObjectClass == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find SceneObject managed class.");
-
-		mSerializeFieldAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "SerializeField");
-		if(mSerializeFieldAttribute == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find SerializeField managed class.");
-
-		mHideInInspectorAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "HideInInspector");
-		if(mHideInInspectorAttribute == nullptr)
-			BS_EXCEPT(InvalidStateException, "Cannot find HideInInspector managed class.");
-
-		mBaseTypesInitialized = true;
-	}
-
-	bool ScriptAssemblyManager::getSerializableObjectInfo(const String& ns, const String& typeName, std::shared_ptr<ManagedSerializableObjectInfo>& outInfo)
-	{
-		String fullName = ns + "." + typeName;
-		for(auto& curAssembly : mAssemblyInfos)
-		{
-			if (curAssembly.second == nullptr)
-				continue;
-
-			auto iterFind = curAssembly.second->mTypeNameToId.find(fullName);
-			if(iterFind != curAssembly.second->mTypeNameToId.end())
-			{
-				outInfo = curAssembly.second->mObjectInfos[iterFind->second];
-
-				return true;
-			}
-		}
-
-		return false;
-	}
-
-	bool ScriptAssemblyManager::hasSerializableObjectInfo(const String& ns, const String& typeName)
-	{
-		String fullName = ns + "." + typeName;
-		for(auto& curAssembly : mAssemblyInfos)
-		{
-			auto iterFind = curAssembly.second->mTypeNameToId.find(fullName);
-			if(iterFind != curAssembly.second->mTypeNameToId.end())
-				return true;
-		}
-
-		return false;
-	}
+#include "BsScriptAssemblyManager.h"
+#include "BsManagedSerializableObjectInfo.h"
+#include "BsMonoManager.h"
+#include "BsMonoAssembly.h"
+#include "BsMonoClass.h"
+#include "BsMonoField.h"
+#include "BsMonoMethod.h"
+#include "BsMonoProperty.h"
+#include "BsScriptManagedResource.h"
+#include "BsScriptTexture2D.h"
+#include "BsScriptTexture3D.h"
+#include "BsScriptTextureCube.h"
+#include "BsScriptSpriteTexture.h"
+#include "BsScriptMaterial.h"
+#include "BsScriptMesh.h"
+#include "BsScriptFont.h"
+#include "BsScriptShader.h"
+#include "BsScriptShaderInclude.h"
+#include "BsScriptPlainText.h"
+#include "BsScriptScriptCode.h"
+#include "BsScriptStringTable.h"
+#include "BsScriptGUISkin.h"
+#include "BsScriptPrefab.h"
+
+namespace BansheeEngine
+{
+	ScriptAssemblyManager::ScriptAssemblyManager()
+		:mBaseTypesInitialized(false), mSerializeObjectAttribute(nullptr), mDontSerializeFieldAttribute(nullptr), 
+		mComponentClass(nullptr), mSceneObjectClass(nullptr), mSerializeFieldAttribute(nullptr), mHideInInspectorAttribute(nullptr), 
+		mSystemArrayClass(nullptr), mSystemGenericListClass(nullptr), mSystemGenericDictionaryClass(nullptr), mMissingComponentClass(nullptr),
+		mSystemTypeClass(nullptr)
+	{
+
+	}
+
+	ScriptAssemblyManager::~ScriptAssemblyManager()
+	{
+
+	}
+
+	Vector<String> ScriptAssemblyManager::getScriptAssemblies() const
+	{
+		Vector<String> initializedAssemblies;
+		for (auto& assemblyPair : mAssemblyInfos)
+			initializedAssemblies.push_back(assemblyPair.first);
+
+		return initializedAssemblies;
+	}
+
+	void ScriptAssemblyManager::loadAssemblyInfo(const String& assemblyName)
+	{
+		if(!mBaseTypesInitialized)
+			initializeBaseTypes();
+
+		// Process all classes and fields
+		UINT32 mUniqueTypeId = 1;
+
+		MonoAssembly* curAssembly = MonoManager::instance().getAssembly(assemblyName);
+		if(curAssembly == nullptr)
+			return;
+
+		std::shared_ptr<ManagedSerializableAssemblyInfo> assemblyInfo = bs_shared_ptr_new<ManagedSerializableAssemblyInfo>();
+		assemblyInfo->mName = assemblyName;
+
+		mAssemblyInfos[assemblyName] = assemblyInfo;
+
+		MonoClass* managedResourceClass = ScriptManagedResource::getMetaData()->scriptClass;
+
+		// Populate class data
+		const Vector<MonoClass*>& allClasses = curAssembly->getAllClasses();
+		for(auto& curClass : allClasses)
+		{
+			if ((curClass->isSubClassOf(mComponentClass) || curClass->isSubClassOf(managedResourceClass) ||
+				curClass->hasAttribute(mSerializeObjectAttribute)) && curClass != mComponentClass && curClass != managedResourceClass)
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoObject> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoObject>();
+				typeInfo->mTypeNamespace = curClass->getNamespace();
+				typeInfo->mTypeName = curClass->getTypeName();
+				typeInfo->mTypeId = mUniqueTypeId++;
+
+				MonoType* monoType = mono_class_get_type(curClass->_getInternalClass());
+				int monoPrimitiveType = mono_type_get_type(monoType);
+
+				if(monoPrimitiveType == MONO_TYPE_VALUETYPE)
+					typeInfo->mValueType = true;
+				else
+					typeInfo->mValueType = false;
+
+				std::shared_ptr<ManagedSerializableObjectInfo> objInfo = bs_shared_ptr_new<ManagedSerializableObjectInfo>();
+
+				objInfo->mTypeInfo = typeInfo;
+				objInfo->mMonoClass = curClass;
+
+				assemblyInfo->mTypeNameToId[objInfo->getFullTypeName()] = typeInfo->mTypeId;
+				assemblyInfo->mObjectInfos[typeInfo->mTypeId] = objInfo;
+			}
+		}
+
+		// Populate field data
+		for(auto& curClassInfo : assemblyInfo->mObjectInfos)
+		{
+			std::shared_ptr<ManagedSerializableObjectInfo> objInfo = curClassInfo.second;
+
+			UINT32 mUniqueFieldId = 1;
+			const Vector<MonoField*>& fields = objInfo->mMonoClass->getAllFields();
+
+			for(auto& field : fields)
+			{
+				if(field->isStatic())
+					continue;
+
+				ManagedSerializableTypeInfoPtr typeInfo = getTypeInfo(field->getType());
+				if (typeInfo == nullptr)
+					continue;
+
+				std::shared_ptr<ManagedSerializableFieldInfo> fieldInfo = bs_shared_ptr_new<ManagedSerializableFieldInfo>();
+				fieldInfo->mFieldId = mUniqueFieldId++;
+				fieldInfo->mName = field->getName();
+				fieldInfo->mMonoField = field;
+				fieldInfo->mTypeInfo = typeInfo;
+				fieldInfo->mParentTypeId = objInfo->mTypeInfo->mTypeId;
+				
+				MonoFieldVisibility visibility = field->getVisibility();
+				if (visibility == MonoFieldVisibility::Public)
+				{
+					if (!field->hasAttribute(mDontSerializeFieldAttribute))
+						fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Serializable);
+
+					if (!field->hasAttribute(mHideInInspectorAttribute))
+						fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Inspectable);
+				}
+				else
+				{
+					if (field->hasAttribute(mSerializeFieldAttribute))
+						fieldInfo->mFlags = (ScriptFieldFlags)((UINT32)fieldInfo->mFlags | (UINT32)ScriptFieldFlags::Serializable);
+				}
+
+				objInfo->mFieldNameToId[fieldInfo->mName] = fieldInfo->mFieldId;
+				objInfo->mFields[fieldInfo->mFieldId] = fieldInfo;
+			}
+		}
+
+		// Form parent/child connections
+		for(auto& curClass : assemblyInfo->mObjectInfos)
+		{
+			MonoClass* base = curClass.second->mMonoClass->getBaseClass();
+			while(base != nullptr)
+			{
+				std::shared_ptr<ManagedSerializableObjectInfo> baseObjInfo;
+				if(getSerializableObjectInfo(base->getNamespace(), base->getTypeName(), baseObjInfo))
+				{
+					curClass.second->mBaseClass = baseObjInfo;
+					baseObjInfo->mDerivedClasses.push_back(curClass.second);
+
+					break;
+				}
+
+				base = base->getBaseClass();
+			}
+		}
+	}
+
+	void ScriptAssemblyManager::clearAssemblyInfo()
+	{
+		clearScriptObjects();
+		mAssemblyInfos.clear();
+	}
+
+	ManagedSerializableTypeInfoPtr ScriptAssemblyManager::getTypeInfo(MonoClass* monoClass)
+	{
+		if(!mBaseTypesInitialized)
+			BS_EXCEPT(InvalidStateException, "Calling determineType without previously initializing base types.");
+
+		MonoType* monoType = mono_class_get_type(monoClass->_getInternalClass());
+		int monoPrimitiveType = mono_type_get_type(monoType);
+		
+		// If enum get the enum base data type
+		bool isEnum = mono_class_is_enum(monoClass->_getInternalClass()) == 1;
+		if (isEnum)
+		{
+			MonoType* underlyingType = mono_type_get_underlying_type(monoType);
+			monoPrimitiveType = mono_type_get_type(underlyingType);
+		}
+
+		//  Determine field type
+		switch(monoPrimitiveType)
+		{
+		case MONO_TYPE_BOOLEAN:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::Bool;
+				return typeInfo;
+			}
+		case MONO_TYPE_CHAR:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::Char;
+				return typeInfo;
+			}
+		case MONO_TYPE_I1:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::I8;
+				return typeInfo;
+			}
+		case MONO_TYPE_U1:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::U8;
+				return typeInfo;
+			}
+		case MONO_TYPE_I2:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::I16;
+				return typeInfo;
+			}
+		case MONO_TYPE_U2:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::U16;
+				return typeInfo;
+			}
+		case MONO_TYPE_I4:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::I32;
+				return typeInfo;
+			}
+		case MONO_TYPE_U4:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::U32;
+				return typeInfo;
+			}
+		case MONO_TYPE_I8:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::I64;
+				return typeInfo;
+			}
+		case MONO_TYPE_U8:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::U64;
+				return typeInfo;
+			}
+		case MONO_TYPE_STRING:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::String;
+				return typeInfo;
+			}
+		case MONO_TYPE_R4:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::Float;
+				return typeInfo;
+			}
+		case MONO_TYPE_R8:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::Double;
+				return typeInfo;
+			}
+		case MONO_TYPE_CLASS:
+			if(monoClass->isSubClassOf(ScriptTexture2D::getMetaData()->scriptClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::Texture2DRef;
+				return typeInfo;
+			}
+			if (monoClass->isSubClassOf(ScriptTexture3D::getMetaData()->scriptClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::Texture3DRef;
+				return typeInfo;
+			}
+			if (monoClass->isSubClassOf(ScriptTextureCube::getMetaData()->scriptClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::TextureCubeRef;
+				return typeInfo;
+			}
+			else if (monoClass->isSubClassOf(ScriptSpriteTexture::getMetaData()->scriptClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::SpriteTextureRef;
+				return typeInfo;
+			}
+			else if (monoClass->isSubClassOf(ScriptManagedResource::getMetaData()->scriptClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::ManagedResourceRef;
+				return typeInfo;
+			}
+			else if (monoClass->isSubClassOf(ScriptShader::getMetaData()->scriptClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::ShaderRef;
+				return typeInfo;
+			}
+			else if (monoClass->isSubClassOf(ScriptShaderInclude::getMetaData()->scriptClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::ShaderIncludeRef;
+				return typeInfo;
+			}
+			else if (monoClass->isSubClassOf(ScriptMaterial::getMetaData()->scriptClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::MaterialRef;
+				return typeInfo;
+			}
+			else if (monoClass->isSubClassOf(ScriptMesh::getMetaData()->scriptClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::MeshRef;
+				return typeInfo;
+			}
+			else if (monoClass->isSubClassOf(ScriptPlainText::getMetaData()->scriptClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::PlainTextRef;
+				return typeInfo;
+			}
+			else if (monoClass->isSubClassOf(ScriptScriptCode::getMetaData()->scriptClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::ScriptCodeRef;
+				return typeInfo;
+			}
+			else if (monoClass->isSubClassOf(ScriptPrefab::getMetaData()->scriptClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::PrefabRef;
+				return typeInfo;
+			}
+			else if (monoClass->isSubClassOf(ScriptFont::getMetaData()->scriptClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::FontRef;
+				return typeInfo;
+			}
+			else if (monoClass->isSubClassOf(ScriptStringTable::getMetaData()->scriptClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::StringTableRef;
+				return typeInfo;
+			}
+			else if (monoClass->isSubClassOf(ScriptGUISkin::getMetaData()->scriptClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::GUISkinRef;
+				return typeInfo;
+			}
+			else if(monoClass->isSubClassOf(mSceneObjectClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::SceneObjectRef;
+				return typeInfo;
+			}
+			else if(monoClass->isSubClassOf(mComponentClass))
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoPrimitive> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoPrimitive>();
+				typeInfo->mType = ScriptPrimitiveType::ComponentRef;
+				return typeInfo;
+			}
+			else
+			{
+				std::shared_ptr<ManagedSerializableObjectInfo> objInfo;
+				if (getSerializableObjectInfo(monoClass->getNamespace(), monoClass->getTypeName(), objInfo))
+					return objInfo->mTypeInfo;
+			}
+
+			break;
+		case MONO_TYPE_VALUETYPE:
+			{
+				std::shared_ptr<ManagedSerializableObjectInfo> objInfo;
+				if (getSerializableObjectInfo(monoClass->getNamespace(), monoClass->getTypeName(), objInfo))
+					return objInfo->mTypeInfo;
+			}
+
+			break;
+		case MONO_TYPE_GENERICINST:
+			if(monoClass->getFullName() == mSystemGenericListClass->getFullName()) // Full name is part of CIL spec, so it is just fine to compare like this
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoList> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoList>();
+
+				MonoProperty& itemProperty = monoClass->getProperty("Item");
+				MonoClass* itemClass = itemProperty.getReturnType();
+
+				if (itemClass != nullptr)
+					typeInfo->mElementType = getTypeInfo(itemClass);
+				
+				if (typeInfo->mElementType == nullptr)
+					return nullptr;
+
+				return typeInfo;
+			}
+			else if(monoClass->getFullName() == mSystemGenericDictionaryClass->getFullName())
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoDictionary> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoDictionary>();
+
+				MonoMethod* getEnumerator = monoClass->getMethod("GetEnumerator");
+				MonoClass* enumClass = getEnumerator->getReturnType();
+
+				MonoProperty& currentProp = enumClass->getProperty("Current");
+				MonoClass* keyValuePair = currentProp.getReturnType();
+
+				MonoProperty& keyProperty = keyValuePair->getProperty("Key");
+				MonoProperty& valueProperty = keyValuePair->getProperty("Value");
+
+				MonoClass* keyClass = keyProperty.getReturnType();
+				if(keyClass != nullptr)
+					typeInfo->mKeyType = getTypeInfo(keyClass);
+
+				MonoClass* valueClass = valueProperty.getReturnType();
+				if(valueClass != nullptr)
+					typeInfo->mValueType = getTypeInfo(valueClass);
+
+				if (typeInfo->mKeyType == nullptr || typeInfo->mValueType == nullptr)
+					return nullptr;
+
+				return typeInfo;
+			}
+			break;
+		case MONO_TYPE_SZARRAY:
+		case MONO_TYPE_ARRAY:
+			{
+				std::shared_ptr<ManagedSerializableTypeInfoArray> typeInfo = bs_shared_ptr_new<ManagedSerializableTypeInfoArray>();
+
+				::MonoClass* elementClass = mono_class_get_element_class(monoClass->_getInternalClass());
+				if(elementClass != nullptr)
+				{
+					MonoClass* monoElementClass = MonoManager::instance().findClass(elementClass);
+					if(monoElementClass != nullptr)
+						typeInfo->mElementType = getTypeInfo(monoElementClass);
+				}
+
+				if (typeInfo->mElementType == nullptr)
+					return nullptr;
+
+				typeInfo->mRank = (UINT32)mono_class_get_rank(monoClass->_getInternalClass());
+
+				return typeInfo;
+			}
+		}
+
+		return nullptr;
+	}
+
+	void ScriptAssemblyManager::clearScriptObjects()
+	{
+		mBaseTypesInitialized = false;
+
+		mSystemArrayClass = nullptr;
+		mSystemGenericListClass = nullptr;
+		mSystemGenericDictionaryClass = nullptr;
+		mSystemTypeClass = nullptr;
+
+		mSerializeObjectAttribute = nullptr;
+		mDontSerializeFieldAttribute = nullptr;
+
+		mComponentClass = nullptr;
+		mSceneObjectClass = nullptr;
+		mMissingComponentClass = nullptr;
+
+		mSerializeFieldAttribute = nullptr;
+		mHideInInspectorAttribute = nullptr;
+	}
+
+	void ScriptAssemblyManager::initializeBaseTypes()
+	{
+		// Get necessary classes for detecting needed class & field information
+		MonoAssembly* corlib = MonoManager::instance().getAssembly("corlib");
+		if(corlib == nullptr)
+			BS_EXCEPT(InvalidStateException, "corlib assembly is not loaded.");
+
+		MonoAssembly* bansheeEngineAssembly = MonoManager::instance().getAssembly(ENGINE_ASSEMBLY);
+		if(bansheeEngineAssembly == nullptr)
+			BS_EXCEPT(InvalidStateException, String(ENGINE_ASSEMBLY) +  " assembly is not loaded.");
+
+		mSystemArrayClass = corlib->getClass("System", "Array");
+		if(mSystemArrayClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find System.Array managed class.");
+
+		mSystemGenericListClass = corlib->getClass("System.Collections.Generic", "List`1");
+		if(mSystemGenericListClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find List<T> managed class.");
+
+		mSystemGenericDictionaryClass = corlib->getClass("System.Collections.Generic", "Dictionary`2");
+		if(mSystemGenericDictionaryClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find Dictionary<TKey, TValue> managed class.");
+
+		mSystemTypeClass = corlib->getClass("System", "Type");
+		if (mSystemTypeClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find Type managed class.");
+
+		mSerializeObjectAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "SerializeObject");
+		if(mSerializeObjectAttribute == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find SerializableObject managed class.");
+
+		mDontSerializeFieldAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "DontSerializeField");
+		if(mDontSerializeFieldAttribute == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find DontSerializeField managed class.");
+
+		mComponentClass = bansheeEngineAssembly->getClass("BansheeEngine", "Component");
+		if(mComponentClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find Component managed class.");
+
+		mMissingComponentClass = bansheeEngineAssembly->getClass("BansheeEngine", "MissingComponent");
+		if (mMissingComponentClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find MissingComponent managed class.");
+
+		mSceneObjectClass = bansheeEngineAssembly->getClass("BansheeEngine", "SceneObject");
+		if(mSceneObjectClass == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find SceneObject managed class.");
+
+		mSerializeFieldAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "SerializeField");
+		if(mSerializeFieldAttribute == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find SerializeField managed class.");
+
+		mHideInInspectorAttribute = bansheeEngineAssembly->getClass("BansheeEngine", "HideInInspector");
+		if(mHideInInspectorAttribute == nullptr)
+			BS_EXCEPT(InvalidStateException, "Cannot find HideInInspector managed class.");
+
+		mBaseTypesInitialized = true;
+	}
+
+	bool ScriptAssemblyManager::getSerializableObjectInfo(const String& ns, const String& typeName, std::shared_ptr<ManagedSerializableObjectInfo>& outInfo)
+	{
+		String fullName = ns + "." + typeName;
+		for(auto& curAssembly : mAssemblyInfos)
+		{
+			if (curAssembly.second == nullptr)
+				continue;
+
+			auto iterFind = curAssembly.second->mTypeNameToId.find(fullName);
+			if(iterFind != curAssembly.second->mTypeNameToId.end())
+			{
+				outInfo = curAssembly.second->mObjectInfos[iterFind->second];
+
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	bool ScriptAssemblyManager::hasSerializableObjectInfo(const String& ns, const String& typeName)
+	{
+		String fullName = ns + "." + typeName;
+		for(auto& curAssembly : mAssemblyInfos)
+		{
+			auto iterFind = curAssembly.second->mTypeNameToId.find(fullName);
+			if(iterFind != curAssembly.second->mTypeNameToId.end())
+				return true;
+		}
+
+		return false;
+	}
 }
 }