Przeglądaj źródła

Various fixes to GUI dictionary
Refactored C# GUIElementStyle so it's less bug prone (uses structs instead of classes for child states)

BearishSun 10 lat temu
rodzic
commit
a634379664

+ 1 - 1
BansheeMono/Include/BsScriptMeta.h

@@ -15,7 +15,7 @@ namespace BansheeEngine
 		String ns; /**< Namespace the script class is located in. */
 		String name; /**< Type name of the script class. */
 		String assembly; /**< Name of the assembly the script class is located in. */
-		std::function<void()> initCallback; /**< Callback that will be triggered when assembly containing the class is loaded. Used for one time initialization. */
+		std::function<void()> initCallback; /**< Callback that will be triggered when assembly containing the class is loaded or refreshed. Used for one time initialization. */
 		MonoClass* scriptClass; /**< Class object describing the script class. Only valid after assembly containing this type was loaded. */			
 		MonoField* thisPtrField; /**< Field object that contains a pointer to the native instance of the script object. Only valid after assembly containing this type was loaded. */
 	};

+ 91 - 57
MBansheeEditor/GUI/GUIDictionaryField.cs

@@ -49,6 +49,8 @@ namespace BansheeEditor
             Destroy();
 
             this.depth = depth;
+            this.editKey = CreateKey();
+            this.editValue = CreateValue();
 
             if (empty)
             {
@@ -68,7 +70,7 @@ namespace BansheeEditor
             {
                 GUIToggle guiFoldout = new GUIToggle(title, EditorStyles.Foldout);
                 guiFoldout.Value = isExpanded;
-                guiFoldout.OnToggled += OnFoldoutToggled;
+                guiFoldout.OnToggled += ToggleFoldout;
 
                 GUIContent clearIcon = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.Clear));
                 GUIButton guiClearBtn = new GUIButton(clearIcon, GUIOption.FixedWidth(30));
@@ -83,43 +85,41 @@ namespace BansheeEditor
                 guiTitleLayout.AddElement(guiAddBtn);
                 guiTitleLayout.AddElement(guiClearBtn);
 
-                if (numRows > 0)
-                {
-                    guiChildLayout = layout.AddLayoutX();
-                    guiChildLayout.AddSpace(IndentAmount);
-                    guiChildLayout.Enabled = isExpanded;
-
-                    GUIPanel guiContentPanel = guiChildLayout.AddPanel();
-                    GUILayoutX guiIndentLayoutX = guiContentPanel.AddLayoutX();
-                    guiIndentLayoutX.AddSpace(IndentAmount);
-                    GUILayoutY guiIndentLayoutY = guiIndentLayoutX.AddLayoutY();
-                    guiIndentLayoutY.AddSpace(IndentAmount);
-                    guiContentLayout = guiIndentLayoutY.AddLayoutY();
-                    guiIndentLayoutY.AddSpace(IndentAmount);
-                    guiIndentLayoutX.AddSpace(IndentAmount);
-                    guiChildLayout.AddSpace(IndentAmount);
-
-                    short backgroundDepth = (short)(Inspector.START_BACKGROUND_DEPTH - depth - 1);
-                    string bgPanelStyle = depth % 2 == 0
-                        ? EditorStyles.InspectorContentBgAlternate
-                        : EditorStyles.InspectorContentBg;
-
-                    GUIPanel backgroundPanel = guiContentPanel.AddPanel(backgroundDepth);
-                    GUITexture inspectorContentBg = new GUITexture(null, bgPanelStyle);
-                    backgroundPanel.AddElement(inspectorContentBg);
-
-                    for (int i = 0; i < numRows; i++)
-                    {
-                        GUIDictionaryFieldRow newRow = new T();
-                        newRow.BuildGUI(this, guiContentLayout, i, depth);
+                guiChildLayout = layout.AddLayoutX();
+                guiChildLayout.AddSpace(IndentAmount);
+
+                GUIPanel guiContentPanel = guiChildLayout.AddPanel();
+                GUILayoutX guiIndentLayoutX = guiContentPanel.AddLayoutX();
+                guiIndentLayoutX.AddSpace(IndentAmount);
+                GUILayoutY guiIndentLayoutY = guiIndentLayoutX.AddLayoutY();
+                guiIndentLayoutY.AddSpace(IndentAmount);
+                guiContentLayout = guiIndentLayoutY.AddLayoutY();
+                guiIndentLayoutY.AddSpace(IndentAmount);
+                guiIndentLayoutX.AddSpace(IndentAmount);
+                guiChildLayout.AddSpace(IndentAmount);
+
+                short backgroundDepth = (short)(Inspector.START_BACKGROUND_DEPTH - depth - 1);
+                string bgPanelStyle = depth % 2 == 0
+                    ? EditorStyles.InspectorContentBgAlternate
+                    : EditorStyles.InspectorContentBg;
+
+                GUIPanel backgroundPanel = guiContentPanel.AddPanel(backgroundDepth);
+                GUITexture inspectorContentBg = new GUITexture(null, bgPanelStyle);
+                backgroundPanel.AddElement(inspectorContentBg);
+
+                editRow = new T();
+                editRow.BuildGUI(this, guiContentLayout, numRows, depth);
+                editRow.Enabled = false;
 
-                        rows.Add(i, newRow);
-                    }
+                for (int i = 0; i < numRows; i++)
+                {
+                    GUIDictionaryFieldRow newRow = new T();
+                    newRow.BuildGUI(this, guiContentLayout, i, depth);
 
-                    editRow = new T();
-                    editRow.BuildGUI(this, guiContentLayout, numRows, depth);
-                    editRow.Enabled = false;
+                    rows.Add(i, newRow);
                 }
+
+                ToggleFoldout(isExpanded);
             }
         }
 
@@ -146,7 +146,7 @@ namespace BansheeEditor
                     rows[i].BuildGUI(this, guiContentLayout, i, depth);
             }
 
-            if (editRow.Enabled)
+            if (editRow != null && editRow.Enabled)
             {
                 if (editRow.Refresh())
                     editRow.BuildGUI(this, guiContentLayout, rows.Count, depth);
@@ -177,7 +177,8 @@ namespace BansheeEditor
 
             rows.Clear();
 
-            editRow.Destroy();
+            if (editRow != null)
+                editRow.Destroy();
         }
 
         /// <summary>
@@ -190,6 +191,15 @@ namespace BansheeEditor
             return rowIdx == rows.Count;
         }
 
+        /// <summary>
+        /// Checks is any row being currently edited.
+        /// </summary>
+        /// <returns>True if a row is being edited, false otherwise.</returns>
+        private bool IsEditInProgress()
+        {
+            return editRowIdx != -1;
+        }
+
         /// <summary>
         /// Gets a value of an element at the specified index in the list. Also handles temporary edit fields.
         /// </summary>
@@ -197,7 +207,7 @@ namespace BansheeEditor
         /// <returns>Value of the list element at the specified key.</returns>
         protected internal virtual object GetValueInternal(int rowIdx)
         {
-            if (rowIdx == editRowIdx)
+            if (rowIdx == editRowIdx || IsTemporaryRow(rowIdx))
                 return editValue;
             else
                 return GetValue(GetKey(rowIdx));
@@ -210,7 +220,7 @@ namespace BansheeEditor
         /// <param name="value">Value to assign to the element. Caller must ensure it is of valid type.</param>
         protected internal virtual void SetValueInternal(int rowIdx, object value)
         {
-            if (rowIdx == editRowIdx)
+            if (rowIdx == editRowIdx || IsTemporaryRow(rowIdx))
                 editValue = value;
             else
                 SetValue(GetKey(rowIdx), value);
@@ -232,11 +242,24 @@ namespace BansheeEditor
             editKey = key;
         }
 
+        /// <summary>
+        /// Gets a key for a row at the specified index. Handles the special case for the currently edited row.
+        /// </summary>
+        /// <param name="rowIdx">Sequential index of the row for which to retrieve the key.</param>
+        /// <returns>Key for a row at the specified index.</returns>
+        protected internal object GetKeyInternal(int rowIdx)
+        {
+            if (editRowIdx == rowIdx || IsTemporaryRow(rowIdx))
+                return editKey;
+
+            return GetKey(rowIdx);
+        }
+
         /// <summary>
         /// Gets a key for a row at the specified index.
         /// </summary>
         /// <param name="rowIdx">Sequential index of the row for which to retrieve the key.</param>
-        /// <returns>Key for a row at the specified index..</returns>
+        /// <returns>Key for a row at the specified index.</returns>
         protected internal abstract object GetKey(int rowIdx);
 
         /// <summary>
@@ -286,15 +309,15 @@ namespace BansheeEditor
         protected internal abstract bool Contains(object key);
 
         /// <summary>
-        /// Triggered when the user clicks on the expand/collapse toggle in the title bar.
+        /// Hides or shows the dictionary rows.
         /// </summary>
-        /// <param name="expanded">Determines whether the contents were expanded or collapsed.</param>
-        private void OnFoldoutToggled(bool expanded)
+        /// <param name="expanded">True if the rows should be displayed, false otherwise.</param>
+        private void ToggleFoldout(bool expanded)
         {
             isExpanded = expanded;
 
             if (guiChildLayout != null)
-                guiChildLayout.Enabled = isExpanded;
+                guiChildLayout.Enabled = isExpanded && (rows.Count > 0 || IsEditInProgress());
         }
 
         /// <summary>
@@ -308,7 +331,7 @@ namespace BansheeEditor
         /// </summary>
         protected virtual void OnAddButtonClicked()
         {
-            if (editRowIdx != -1)
+            if (IsEditInProgress())
             {
                 DialogBox.Open(
                     new LocEdString("Edit in progress."),
@@ -346,7 +369,7 @@ namespace BansheeEditor
         /// <param name="rowIdx">Sequential row index of the entry that was clicked.</param>
         protected internal virtual void OnDeleteButtonClicked(int rowIdx)
         {
-            if (editRowIdx != -1)
+            if (IsEditInProgress())
                 DiscardChanges();
             else
                 RemoveEntry(GetKey(rowIdx));
@@ -359,7 +382,7 @@ namespace BansheeEditor
         /// <param name="rowIdx">Sequential row index of the entry that was clicked.</param>
         protected internal virtual void OnCloneButtonClicked(int rowIdx)
         {
-            if (editRowIdx != -1)
+            if (IsEditInProgress())
             {
                 DialogBox.Open(
                     new LocEdString("Edit in progress."),
@@ -396,7 +419,7 @@ namespace BansheeEditor
                 ApplyChanges();
             else
             {
-                if (editRowIdx != -1)
+                if (IsEditInProgress())
                 {
                     DialogBox.Open(
                         new LocEdString("Edit in progress."),
@@ -438,6 +461,7 @@ namespace BansheeEditor
             editRowIdx = rowIdx;
 
             rows[rowIdx].EditMode = true;
+            guiChildLayout.Enabled = rows.Count > 0 && isExpanded;
         }
 
         /// <summary>
@@ -453,6 +477,8 @@ namespace BansheeEditor
 
             editRow.Enabled = true;
             editRow.EditMode = true;
+
+            ToggleFoldout(isExpanded);
         }
 
         /// <summary>
@@ -470,6 +496,8 @@ namespace BansheeEditor
 
             editRow.Enabled = true;
             editRow.EditMode = true;
+
+            ToggleFoldout(isExpanded);
         }
 
         /// <summary>
@@ -479,7 +507,7 @@ namespace BansheeEditor
         ///          </returns>
         private bool ApplyChanges()
         {
-            if (editRowIdx == -1)
+            if (!IsEditInProgress())
                 return true;
 
             if (Contains(editKey))
@@ -507,11 +535,12 @@ namespace BansheeEditor
                 }
 
                 AddEntry(editKey, editValue);
-                editKey = null;
-                editValue = null;
+                editKey = CreateKey();
+                editValue = CreateValue();
                 editOriginalKey = null;
                 editRowIdx = -1;
 
+                ToggleFoldout(isExpanded);
                 return true;
             }
         }
@@ -521,13 +550,15 @@ namespace BansheeEditor
         /// </summary>
         private void DiscardChanges()
         {
-            if (editRowIdx != -1)
+            if (IsEditInProgress())
             {
-                editKey = null;
-                editValue = null;
+                editKey = CreateKey();
+                editValue = CreateValue();
                 editOriginalKey = null;
                 editRow.Enabled = false;
                 editRowIdx = -1;
+
+                ToggleFoldout(isExpanded);
             }
         }
     }
@@ -854,7 +885,7 @@ namespace BansheeEditor
         /// <returns>Key in this dictionary's row.</returns>
         protected T GetKey<T>()
         {
-            return (T)parent.GetKey(rowIdx);
+            return (T)parent.GetKeyInternal(rowIdx);
         }
 
         /// <summary>
@@ -892,8 +923,11 @@ namespace BansheeEditor
         /// </summary>
         public void Destroy()
         {
-            rowLayout.Destroy();
-            rowLayout = null;
+            if (rowLayout != null)
+            {
+                rowLayout.Destroy();
+                rowLayout = null;
+            }
         }
     }
 }

+ 5 - 2
MBansheeEditor/GUI/GUIListField.cs

@@ -695,8 +695,11 @@ namespace BansheeEditor
         /// </summary>
         public void Destroy()
         {
-            rowLayout.Destroy();
-            rowLayout = null;
+            if (rowLayout != null)
+            {
+                rowLayout.Destroy();
+                rowLayout = null;
+            }
         }
     }
 }

+ 3 - 3
MBansheeEditor/Inspector/GenericInspector.cs

@@ -15,17 +15,17 @@ namespace BansheeEditor
         /// <inheritdoc/>
         protected internal override void Initialize()
         {
-            if (referencedObject != null)
+            if (InspectedObject != null)
             {
                 int currentIndex = 0;
-                SerializableObject serializableObject = new SerializableObject(referencedObject.GetType(), referencedObject);
+                SerializableObject serializableObject = new SerializableObject(InspectedObject.GetType(), InspectedObject);
                 foreach (var field in serializableObject.Fields)
                 {
                     if (!field.Inspectable)
                         continue;
 
                     InspectableField inspectableField = InspectableField.CreateInspectable(field.Name, currentIndex, 0,
-                        new InspectableFieldLayout(layout), field.GetProperty());
+                        new InspectableFieldLayout(Layout), field.GetProperty());
 
                     inspectableFields.Add(inspectableField);
                     isEmpty = false;

+ 32 - 9
MBansheeEditor/Inspector/Inspector.cs

@@ -13,11 +13,34 @@ namespace BansheeEditor
     {
         public const short START_BACKGROUND_DEPTH = 50;
 
-        protected GUIPanel GUI;
-        protected GUILayoutY layout;
-        protected object referencedObject;
+        /// <summary>
+        /// Returns the main GUI layout for the inspector.
+        /// </summary>
+        protected GUILayoutY Layout
+        {
+            get { return layout; }
+        }
+
+        /// <summary>
+        /// Returns the main GUI panel for the inspector. <see cref="Layout"/> is a child of this panel.
+        /// </summary>
+        protected GUIPanel GUI
+        {
+            get { return mainPanel; }
+        }
+
+        /// <summary>
+        /// Returns the object the inspector is currently displaying.
+        /// </summary>
+        protected object InspectedObject
+        {
+            get { return inspectedObject; }
+        }
 
-        private GUIPanel RootGUI;
+        private GUIPanel rootGUI;
+        private GUIPanel mainPanel;
+        private GUILayoutY layout;
+        private object inspectedObject;
 
         /// <summary>
         /// Initializes the inspector. Must be called after construction.
@@ -26,7 +49,7 @@ namespace BansheeEditor
         /// <param name="instance">Instance of the object whose fields to display GUI for.</param>
         internal virtual void Initialize(GUIPanel gui, object instance)
         {
-            RootGUI = gui;
+            rootGUI = gui;
 
             GUILayout contentLayoutX = gui.AddLayoutX();
             contentLayoutX.AddSpace(5);
@@ -40,9 +63,9 @@ namespace BansheeEditor
             GUITexture inspectorContentBg = new GUITexture(null, EditorStyles.InspectorContentBg);
             backgroundPanel.AddElement(inspectorContentBg);
 
-            GUI = contentPanel;
+            mainPanel = contentPanel;
             layout = GUI.AddLayoutY();
-            referencedObject = instance;
+            inspectedObject = instance;
 
             Initialize();
             Refresh();
@@ -54,7 +77,7 @@ namespace BansheeEditor
         /// <param name="visible">True to make the GUI elements visible.</param>
         internal virtual void SetVisible(bool visible)
         {
-            RootGUI.Enabled = visible;
+            rootGUI.Enabled = visible;
         }
 
         /// <summary>
@@ -62,7 +85,7 @@ namespace BansheeEditor
         /// </summary>
         internal void Destroy()
         {
-            layout.Destroy();
+            Layout.Destroy();
             GUI.Destroy();
         }
 

+ 16 - 16
MBansheeEditor/Inspectors/CameraInspector.cs

@@ -37,7 +37,7 @@ namespace BansheeEditor
         /// <inheritdoc/>
         protected internal override void Refresh()
         {
-            Camera camera = referencedObject as Camera;
+            Camera camera = InspectedObject as Camera;
             if (camera == null)
                 return;
 
@@ -79,9 +79,9 @@ namespace BansheeEditor
         /// </summary>
         private void BuildGUI()
         {
-            if (referencedObject != null)
+            if (InspectedObject != null)
             {
-                Camera camera = (Camera)referencedObject;
+                Camera camera = (Camera)InspectedObject;
 
                 projectionTypeField.OnSelectionChanged += x =>
                 {
@@ -118,13 +118,13 @@ namespace BansheeEditor
                     camera.Layers = layers;
                 };
 
-                layout.AddElement(projectionTypeField);
-                layout.AddElement(fieldOfView);
-                layout.AddElement(orthoHeight);
-                layout.AddElement(aspectField);
-                layout.AddElement(nearPlaneField);
-                layout.AddElement(farPlaneField);
-                GUILayoutX viewportTopLayout = layout.AddLayoutX();
+                Layout.AddElement(projectionTypeField);
+                Layout.AddElement(fieldOfView);
+                Layout.AddElement(orthoHeight);
+                Layout.AddElement(aspectField);
+                Layout.AddElement(nearPlaneField);
+                Layout.AddElement(farPlaneField);
+                GUILayoutX viewportTopLayout = Layout.AddLayoutX();
                 viewportTopLayout.AddElement(new GUILabel(new LocEdString("Viewport"), GUIOption.FixedWidth(100)));
                 GUILayoutY viewportContentLayout = viewportTopLayout.AddLayoutY();
 
@@ -136,12 +136,12 @@ namespace BansheeEditor
                 viewportBotRow.AddElement(viewportYField);
                 viewportBotRow.AddElement(viewportHeightField);
 
-                layout.AddElement(clearFlagsFields);
-                layout.AddElement(clearColorField);
-                layout.AddElement(clearDepthField);
-                layout.AddElement(clearStencilField);
-                layout.AddElement(priorityField);
-                layout.AddElement(layersField);
+                Layout.AddElement(clearFlagsFields);
+                Layout.AddElement(clearColorField);
+                Layout.AddElement(clearDepthField);
+                Layout.AddElement(clearStencilField);
+                Layout.AddElement(priorityField);
+                Layout.AddElement(layersField);
 
                 ToggleTypeSpecificFields(camera.ProjectionType);
             }

+ 10 - 10
MBansheeEditor/Inspectors/FontInspector.cs

@@ -21,7 +21,7 @@ namespace BansheeEditor
         /// <inheritdoc/>
         protected internal override void Initialize()
         {
-            if (referencedObject != null)
+            if (InspectedObject != null)
             {
                 importOptions = GetImportOptions();
                 BuildGUI();
@@ -73,10 +73,10 @@ namespace BansheeEditor
         /// </summary>
         private void BuildGUI()
         {
-            layout.Clear();
+            Layout.Clear();
 
             fontSizes.Update<FontSizeArrayRow>(
-                new LocEdString("Font sizes"), importOptions.FontSizes, layout);
+                new LocEdString("Font sizes"), importOptions.FontSizes, Layout);
             fontSizes.OnChanged += x =>
             {
                 int[] newFontSizes = x as int[];
@@ -87,7 +87,7 @@ namespace BansheeEditor
             };
 
             charRanges.Update<CharRangeArrayRow>(
-                new LocEdString("Character ranges"), importOptions.CharRanges, layout);
+                new LocEdString("Character ranges"), importOptions.CharRanges, Layout);
             charRanges.OnChanged += x =>
             {
                 CharRange[] newRanges = x as CharRange[];
@@ -103,11 +103,11 @@ namespace BansheeEditor
             reimportButton = new GUIButton(new LocEdString("Reimport"));
             reimportButton.OnClick += TriggerReimport;
 
-            layout.AddElement(antialiasingField);
-            layout.AddElement(dpiField);
-            layout.AddSpace(10);
+            Layout.AddElement(antialiasingField);
+            Layout.AddElement(dpiField);
+            Layout.AddSpace(10);
 
-            GUILayout reimportButtonLayout = layout.AddLayoutX();
+            GUILayout reimportButtonLayout = Layout.AddLayoutX();
             reimportButtonLayout.AddFlexibleSpace();
             reimportButtonLayout.AddElement(reimportButton);
         }
@@ -118,7 +118,7 @@ namespace BansheeEditor
         /// <returns>Font import options object.</returns>
         private FontImportOptions GetImportOptions()
         {
-            Font font = referencedObject as Font;
+            Font font = InspectedObject as Font;
             FontImportOptions output = null;
 
             if (font != null)
@@ -147,7 +147,7 @@ namespace BansheeEditor
         /// </summary>
         private void TriggerReimport()
         {
-            Texture2D texture = (Texture2D)referencedObject;
+            Texture2D texture = (Texture2D)InspectedObject;
             string resourcePath = ProjectLibrary.GetPath(texture);
 
             ProjectLibrary.Reimport(resourcePath, importOptions, true);

+ 69 - 28
MBansheeEditor/Inspectors/GUISkinInspector.cs

@@ -31,10 +31,10 @@ namespace BansheeEditor
         /// </summary>
         private void BuildGUI()
         {
-            layout.Clear();
+            Layout.Clear();
             styles.Clear();
 
-            GUISkin guiSkin = referencedObject as GUISkin;
+            GUISkin guiSkin = InspectedObject as GUISkin;
             if (guiSkin == null)
                 return;
 
@@ -42,25 +42,33 @@ namespace BansheeEditor
             foreach (var styleName in styleNames)
                 styles[styleName] = guiSkin.GetStyle(styleName);
 
-            valuesField.Update<GUIElementStyleEntry>(new LocEdString("Styles"), styles, layout);
+            valuesField.Update<GUIElementStyleEntry>(new LocEdString("Styles"), styles, Layout);
 
             valuesField.OnChanged += x =>
             {
-                foreach (var KVP in x)
+                if (x != null)
                 {
-                    GUIElementStyle oldValue;
-                    if (styles.TryGetValue(KVP.Key, out oldValue))
+                    foreach (var KVP in x)
                     {
-                        if (oldValue != KVP.Value)
+                        GUIElementStyle oldValue;
+                        if (styles.TryGetValue(KVP.Key, out oldValue))
+                        {
+                            if (oldValue != KVP.Value)
+                                guiSkin.SetStyle(KVP.Key, KVP.Value);
+                        }
+                        else
                             guiSkin.SetStyle(KVP.Key, KVP.Value);
                     }
-                    else
-                        guiSkin.SetStyle(KVP.Key, KVP.Value);
-                }
 
-                foreach (var KVP in styles)
+                    foreach (var KVP in styles)
+                    {
+                        if (!x.ContainsKey(KVP.Key))
+                            guiSkin.RemoveStyle(KVP.Key);
+                    }
+                }
+                else
                 {
-                    if (!x.ContainsKey(KVP.Key))
+                    foreach (var KVP in styles)
                         guiSkin.RemoveStyle(KVP.Key);
                 }
 
@@ -76,7 +84,7 @@ namespace BansheeEditor
                 EditorApplication.SetDirty(guiSkin);
             };
 
-            layout.AddSpace(10);
+            Layout.AddSpace(10);
         }
 
         /// <summary>
@@ -165,6 +173,9 @@ namespace BansheeEditor
             {
                 this.style = style;
 
+                if (style == null)
+                    return;
+
                 fontField = new GUIResourceField(typeof (Font), new LocEdString("Font"));
                 fontSizeField = new GUIIntField(new LocEdString("Font size"));
                 horzAlignField = new GUIEnumField(typeof (TextHorzAlign), new LocEdString("Horizontal alignment"));
@@ -219,6 +230,15 @@ namespace BansheeEditor
                 imagePositionField.OnSelectionChanged += x => style.ImagePosition = (GUIImagePosition)x;
                 wordWrapField.OnChanged += x => style.WordWrap = x;
 
+                normalGUI.OnChanged += x => style.Normal = x;
+                hoverGUI.OnChanged += x => style.Hover = x;
+                activeGUI.OnChanged += x => style.Active = x;
+                focusedGUI.OnChanged += x => style.Focused = x;
+                normalOnGUI.OnChanged += x => style.NormalOn = x;
+                hoverOnGUI.OnChanged += x => style.HoverOn = x;
+                activeOnGUI.OnChanged += x => style.ActiveOn = x;
+                focusedOnGUI.OnChanged += x => style.FocusedOn = x;
+
                 borderGUI.OnChanged += x => style.Border = x;
                 marginsGUI.OnChanged += x => style.Margins = x;
                 contentOffsetGUI.OnChanged += x => style.ContentOffset = x;
@@ -251,6 +271,9 @@ namespace BansheeEditor
             /// </summary>
             public void Refresh()
             {
+                if (style == null)
+                    return;
+
                 fontField.Value = style.Font;
                 fontSizeField.Value = style.FontSize;
                 horzAlignField.Value = (ulong)style.TextHorzAlign;
@@ -258,14 +281,14 @@ namespace BansheeEditor
                 imagePositionField.Value = (ulong)style.ImagePosition;
                 wordWrapField.Value = style.WordWrap;
 
-                normalGUI.Refresh();
-                hoverGUI.Refresh();
-                activeGUI.Refresh();
-                focusedGUI.Refresh();
-                normalOnGUI.Refresh();
-                hoverOnGUI.Refresh();
-                activeOnGUI.Refresh();
-                focusedOnGUI.Refresh();
+                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);
@@ -290,7 +313,10 @@ namespace BansheeEditor
                 private GUIResourceField textureField;
                 private GUIColorField textColorField;
 
-                private GUIElementStateStyle state;
+                /// <summary>
+                /// Triggered when some value in the style state changes.
+                /// </summary>
+                public Action<GUIElementStateStyle> OnChanged;
 
                 /// <summary>
                 /// Creates a new GUI element state style GUI.
@@ -300,8 +326,6 @@ namespace BansheeEditor
                 /// <param name="layout">Layout to append the GUI elements to.</param>
                 public GUIElementStateStyleGUI(LocString title, GUIElementStateStyle state, GUILayout layout)
                 {
-                    this.state = state;
-
                     foldout = new GUIToggleField(title);
                     textureField = new GUIResourceField(typeof(SpriteTexture), new LocEdString("Texture"));
                     textColorField = new GUIColorField(new LocEdString("Text color"));
@@ -312,15 +336,32 @@ namespace BansheeEditor
                         textColorField.Enabled = x;
                     };
 
+                    textureField.OnChanged += x =>
+                    {
+                        state.Texture = x as SpriteTexture;
+
+                        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);
                 }
 
                 /// <summary>
-                /// Updates all GUI elements from the state if state changes.
+                /// Updates all GUI elements from the current state values.
                 /// </summary>
-                public void Refresh()
+                /// <param name="state">State to update the GUI to.</param>
+                public void Refresh(GUIElementStateStyle state)
                 {
                     textureField.Value = state.Texture;
                     textColorField.Value = state.TextColor;
@@ -401,9 +442,9 @@ namespace BansheeEditor
                 }
 
                 /// <summary>
-                /// Updates all GUI elements from the offset if offset changes.
+                /// Updates all GUI elements from the offset.
                 /// </summary>
-                /// <param name="offset">New (potentially modified) offset.</param>
+                /// <param name="offset">Offset to update the GUI to.</param>
                 public void Refresh(RectOffset offset)
                 {
                     offsetLeftField.Value = offset.left;

+ 10 - 10
MBansheeEditor/Inspectors/LightInspector.cs

@@ -20,9 +20,9 @@ namespace BansheeEditor
         /// <inheritdoc/>
         protected internal override void Initialize()
         {
-            if (referencedObject != null)
+            if (InspectedObject != null)
             {
-                Light light = (Light)referencedObject;
+                Light light = (Light)InspectedObject;
 
                 lightTypeField.OnSelectionChanged += x =>
                 {
@@ -38,13 +38,13 @@ namespace BansheeEditor
                 spotFalloffAngleField.OnChanged += x => light.SpotFalloffAngle = x;
                 castShadowField.OnChanged += x => light.CastsShadow = x;
                 
-                layout.AddElement(lightTypeField);
-                layout.AddElement(colorField);
-                layout.AddElement(intensityField);
-                layout.AddElement(rangeField);
-                layout.AddElement(spotAngleField);
-                layout.AddElement(spotFalloffAngleField);
-                layout.AddElement(castShadowField);
+                Layout.AddElement(lightTypeField);
+                Layout.AddElement(colorField);
+                Layout.AddElement(intensityField);
+                Layout.AddElement(rangeField);
+                Layout.AddElement(spotAngleField);
+                Layout.AddElement(spotFalloffAngleField);
+                Layout.AddElement(castShadowField);
 
                 ToggleTypeSpecificFields(light.Type);
             }
@@ -53,7 +53,7 @@ namespace BansheeEditor
         /// <inheritdoc/>
         protected internal override void Refresh()
         {
-            Light light = referencedObject as Light;
+            Light light = InspectedObject as Light;
             if (light == null)
                 return;
 

+ 4 - 4
MBansheeEditor/Inspectors/MaterialInspector.cs

@@ -15,7 +15,7 @@ namespace BansheeEditor
         /// <inheritdoc/>
         protected internal override void Initialize()
         {
-            Material material = referencedObject as Material;
+            Material material = InspectedObject as Material;
             if (material == null)
                 return;
 
@@ -26,7 +26,7 @@ namespace BansheeEditor
                 RebuildParamGUI(material);
             };
 
-            layout.AddElement(shaderField);
+            Layout.AddElement(shaderField);
 
             RebuildParamGUI(material);
         }
@@ -34,7 +34,7 @@ namespace BansheeEditor
         /// <inheritdoc/>
         protected internal override void Refresh()
         {
-            Material material = referencedObject as Material;
+            Material material = InspectedObject as Material;
             if (material == null)
                 return;
 
@@ -66,7 +66,7 @@ namespace BansheeEditor
             }
 
             if (material != null && material.Shader != null)
-                guiParams = CreateMaterialGUI(material, layout);
+                guiParams = CreateMaterialGUI(material, Layout);
         }
 
 

+ 12 - 12
MBansheeEditor/Inspectors/MeshInspector.cs

@@ -23,7 +23,7 @@ namespace BansheeEditor
         /// <inheritdoc/>
         protected internal override void Initialize()
         {
-            if (referencedObject != null)
+            if (InspectedObject != null)
             {
                 importOptions = GetImportOptions();
 
@@ -37,16 +37,16 @@ namespace BansheeEditor
 
                 reimportButton.OnClick += TriggerReimport;
 
-                layout.AddElement(normalsField);
-                layout.AddElement(tangentsField);
-                layout.AddElement(skinField);
-                layout.AddElement(blendShapesField);
-                layout.AddElement(animationField);
-                layout.AddElement(scaleField);
-                layout.AddElement(cpuReadableField);
-                layout.AddSpace(10);
+                Layout.AddElement(normalsField);
+                Layout.AddElement(tangentsField);
+                Layout.AddElement(skinField);
+                Layout.AddElement(blendShapesField);
+                Layout.AddElement(animationField);
+                Layout.AddElement(scaleField);
+                Layout.AddElement(cpuReadableField);
+                Layout.AddSpace(10);
 
-                GUILayout reimportButtonLayout = layout.AddLayoutX();
+                GUILayout reimportButtonLayout = Layout.AddLayoutX();
                 reimportButtonLayout.AddFlexibleSpace();
                 reimportButtonLayout.AddElement(reimportButton);
             }
@@ -75,7 +75,7 @@ namespace BansheeEditor
         /// <returns>Mesh import options object.</returns>
         private MeshImportOptions GetImportOptions()
         {
-            Mesh mesh = referencedObject as Mesh;
+            Mesh mesh = InspectedObject as Mesh;
             MeshImportOptions output = null;
 
             if (mesh != null)
@@ -104,7 +104,7 @@ namespace BansheeEditor
         /// </summary>
         private void TriggerReimport()
         {
-            Mesh mesh = (Mesh)referencedObject;
+            Mesh mesh = (Mesh)InspectedObject;
             string resourcePath = ProjectLibrary.GetPath(mesh);
 
             ProjectLibrary.Reimport(resourcePath, importOptions, true);

+ 3 - 3
MBansheeEditor/Inspectors/PlainTextInspector.cs

@@ -19,11 +19,11 @@ namespace BansheeEditor
         /// <inheritdoc/>
         protected internal override void Initialize()
         {
-            PlainText plainText = referencedObject as PlainText;
+            PlainText plainText = InspectedObject as PlainText;
             if (plainText == null)
                 return;
 
-            GUIPanel textPanel = layout.AddPanel();
+            GUIPanel textPanel = Layout.AddPanel();
             GUILayout textLayoutY = textPanel.AddLayoutY();
             textLayoutY.AddSpace(5);
             GUILayout textLayoutX = textLayoutY.AddLayoutX();
@@ -39,7 +39,7 @@ namespace BansheeEditor
         /// <inheritdoc/>
         protected internal override void Refresh()
         {
-            PlainText plainText = referencedObject as PlainText;
+            PlainText plainText = InspectedObject as PlainText;
             if (plainText == null)
                 return;
 

+ 8 - 8
MBansheeEditor/Inspectors/RenderableInspector.cs

@@ -27,7 +27,7 @@ namespace BansheeEditor
         /// <inheritdoc/>
         protected internal override void Refresh()
         {
-            Renderable renderable = referencedObject as Renderable;
+            Renderable renderable = InspectedObject as Renderable;
             if (renderable == null)
                 return;
 
@@ -91,21 +91,21 @@ namespace BansheeEditor
         /// </summary>
         private void BuildGUI()
         {
-            layout.Clear();
+            Layout.Clear();
 
-            Renderable renderable = referencedObject as Renderable;
+            Renderable renderable = InspectedObject as Renderable;
             if (renderable == null)
                 return;
 
             meshField = new GUIResourceField(typeof(Mesh), new LocEdString("Mesh"));
             layersField = new GUIListBoxField(Layers.Names, true, new LocEdString("Layers"));
 
-            layout.AddElement(meshField);
-            layout.AddElement(layersField);
+            Layout.AddElement(meshField);
+            Layout.AddElement(layersField);
 
             layersValue = 0;
             materials = renderable.Materials;
-            materialsField.Update<MaterialArrayRow>(new LocEdString("Materials"), materials, layout);
+            materialsField.Update<MaterialArrayRow>(new LocEdString("Materials"), materials, Layout);
 
             materialsField.OnChanged += x =>
             {
@@ -136,9 +136,9 @@ namespace BansheeEditor
                         continue;
                     }
 
-                    layout.AddSpace(10);
+                    Layout.AddSpace(10);
 
-                    MaterialParamGUI[] matParams = MaterialInspector.CreateMaterialGUI(materials[i], layout);
+                    MaterialParamGUI[] matParams = MaterialInspector.CreateMaterialGUI(materials[i], Layout);
                     materialParams.Add(matParams);
                 }
             }

+ 4 - 4
MBansheeEditor/Inspectors/ScriptCodeInspector.cs

@@ -20,7 +20,7 @@ namespace BansheeEditor
         /// <inheritdoc/>
         protected internal override void Initialize()
         {
-            ScriptCode scriptCode = referencedObject as ScriptCode;
+            ScriptCode scriptCode = InspectedObject as ScriptCode;
             if (scriptCode == null)
                 return;
 
@@ -30,7 +30,7 @@ namespace BansheeEditor
                 EditorApplication.SetDirty(scriptCode);
             };
 
-            GUIPanel textPanel = layout.AddPanel();
+            GUIPanel textPanel = Layout.AddPanel();
             GUILayout textLayoutY = textPanel.AddLayoutY();
             textLayoutY.AddSpace(5);
             GUILayout textLayoutX = textLayoutY.AddLayoutX();
@@ -42,13 +42,13 @@ namespace BansheeEditor
             GUIPanel textBgPanel = textPanel.AddPanel(1);
             textBgPanel.AddElement(textBg);
 
-            layout.AddElement(isEditorField);
+            Layout.AddElement(isEditorField);
         }
 
         /// <inheritdoc/>
         protected internal override void Refresh()
         {
-            ScriptCode scriptCode = referencedObject as ScriptCode;
+            ScriptCode scriptCode = InspectedObject as ScriptCode;
             if (scriptCode == null)
                 return;
 

+ 5 - 5
MBansheeEditor/Inspectors/SpriteTextureInspector.cs

@@ -16,7 +16,7 @@ namespace BansheeEditor
         /// <inheritdoc/>
         protected internal override void Initialize()
         {
-            SpriteTexture spriteTexture = referencedObject as SpriteTexture;
+            SpriteTexture spriteTexture = InspectedObject as SpriteTexture;
             if (spriteTexture == null)
                 return;
 
@@ -38,15 +38,15 @@ namespace BansheeEditor
                 EditorApplication.SetDirty(spriteTexture);
             };
 
-            layout.AddElement(textureField);
-            layout.AddElement(offsetField);
-            layout.AddElement(scaleField);
+            Layout.AddElement(textureField);
+            Layout.AddElement(offsetField);
+            Layout.AddElement(scaleField);
         }
 
         /// <inheritdoc/>
         protected internal override void Refresh()
         {
-            SpriteTexture spriteTexture = referencedObject as SpriteTexture;
+            SpriteTexture spriteTexture = InspectedObject as SpriteTexture;
             if (spriteTexture == null)
                 return;
 

+ 22 - 14
MBansheeEditor/Inspectors/StringTableInspector.cs

@@ -39,10 +39,10 @@ namespace BansheeEditor
         /// </summary>
         private void BuildGUI()
         {
-            layout.Clear();
+            Layout.Clear();
             strings.Clear();
 
-            StringTable stringTable = referencedObject as StringTable;
+            StringTable stringTable = InspectedObject as StringTable;
             if(stringTable == null)
                 return;
 
@@ -58,27 +58,35 @@ namespace BansheeEditor
                 Refresh();
             };
 
-            layout.AddElement(languageField);
+            Layout.AddElement(languageField);
 
-            valuesField.Update<StringTableEntry>(new LocEdString("Strings"), strings, layout);
+            valuesField.Update<StringTableEntry>(new LocEdString("Strings"), strings, Layout);
 
             valuesField.OnChanged += x =>
             {
-                foreach (var KVP in x)
+                if (x != null)
                 {
-                    string oldValue;
-                    if (strings.TryGetValue(KVP.Key, out oldValue))
+                    foreach (var KVP in x)
                     {
-                        if (oldValue != KVP.Value)
+                        string oldValue;
+                        if (strings.TryGetValue(KVP.Key, out oldValue))
+                        {
+                            if (oldValue != KVP.Value)
+                                stringTable.SetString(KVP.Key, KVP.Value);
+                        }
+                        else
                             stringTable.SetString(KVP.Key, KVP.Value);
                     }
-                    else
-                        stringTable.SetString(KVP.Key, KVP.Value);
-                }
 
-                foreach (var KVP in strings)
+                    foreach (var KVP in strings)
+                    {
+                        if (!x.ContainsKey(KVP.Key))
+                            stringTable.RemoveString(KVP.Key);
+                    }
+                }
+                else
                 {
-                    if (!x.ContainsKey(KVP.Key))
+                    foreach (var KVP in strings)
                         stringTable.RemoveString(KVP.Key);
                 }
 
@@ -94,7 +102,7 @@ namespace BansheeEditor
                 EditorApplication.SetDirty(stringTable);
             };
             
-            layout.AddSpace(10);
+            Layout.AddSpace(10);
         }
 
         /// <summary>

+ 10 - 10
MBansheeEditor/Inspectors/Texture2DInspector.cs

@@ -21,7 +21,7 @@ namespace BansheeEditor
         /// <inheritdoc/>
         protected internal override void Initialize()
         {
-            if (referencedObject != null)
+            if (InspectedObject != null)
             {
                 importOptions = GetImportOptions();
 
@@ -33,14 +33,14 @@ namespace BansheeEditor
 
                 reimportButton.OnClick += TriggerReimport;
 
-                layout.AddElement(formatField);
-                layout.AddElement(generateMipsField);
-                layout.AddElement(maximumMipsField);
-                layout.AddElement(srgbField);
-                layout.AddElement(cpuReadableField);
-                layout.AddSpace(10);
+                Layout.AddElement(formatField);
+                Layout.AddElement(generateMipsField);
+                Layout.AddElement(maximumMipsField);
+                Layout.AddElement(srgbField);
+                Layout.AddElement(cpuReadableField);
+                Layout.AddSpace(10);
 
-                GUILayout reimportButtonLayout = layout.AddLayoutX();
+                GUILayout reimportButtonLayout = Layout.AddLayoutX();
                 reimportButtonLayout.AddFlexibleSpace();
                 reimportButtonLayout.AddElement(reimportButton);
             }
@@ -66,7 +66,7 @@ namespace BansheeEditor
         /// <returns>Texture import options object.</returns>
         private TextureImportOptions GetImportOptions()
         {
-            Texture2D texture = referencedObject as Texture2D;
+            Texture2D texture = InspectedObject as Texture2D;
             TextureImportOptions output = null;
 
             if (texture != null)
@@ -95,7 +95,7 @@ namespace BansheeEditor
         /// </summary>
         private void TriggerReimport()
         {
-            Texture2D texture = (Texture2D)referencedObject;
+            Texture2D texture = (Texture2D)InspectedObject;
             string resourcePath = ProjectLibrary.GetPath(texture);
 
             ProjectLibrary.Reimport(resourcePath, importOptions, true);

+ 3 - 32
MBansheeEngine/GUI/GUIElementStateStyle.cs

@@ -6,45 +6,16 @@ namespace BansheeEngine
     /// <summary>
     /// Container for texture and text color used in a particular GUI element style.
     /// </summary>
-    public sealed class GUIElementStateStyle : ScriptObject
+    public struct GUIElementStateStyle
     {
-        /// <summary>
-        /// Constructs a new GUI element state style with default values.
-        /// </summary>
-        public GUIElementStateStyle()
-        {
-            Internal_CreateInstance(this);
-        }
-
         /// <summary>
         /// Texture used by the GUI element style state. Can be null.
         /// </summary>
-        public SpriteTexture Texture
-        {
-            get { SpriteTexture value; Internal_GetTexture(mCachedPtr, out value); return value; }
-            set { Internal_SetTexture(mCachedPtr, value); }
-        }
+        public SpriteTexture Texture;
 
         /// <summary>
         /// Color applied to the text when GUI element style state is active.
         /// </summary>
-        public Color TextColor
-        {
-            get { Color value; Internal_GetTextColor(mCachedPtr, out value); return value; }
-            set { Internal_SetTextColor(mCachedPtr, ref value); }
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(GUIElementStateStyle instance);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_GetTexture(IntPtr nativeInstance, out SpriteTexture value);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetTexture(IntPtr nativeInstance, SpriteTexture value);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_GetTextColor(IntPtr nativeInstance, out Color value);
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetTextColor(IntPtr nativeInstance, ref Color value);
+        public Color TextColor;
     };
 }

+ 11 - 28
SBansheeEngine/Include/BsScriptGUIElementStateStyle.h

@@ -2,52 +2,35 @@
 
 #include "BsScriptEnginePrerequisites.h"
 #include "BsScriptObject.h"
-#include "BsMonoClass.h"
 #include "BsGUIElementStyle.h"
 #include "BsScriptSpriteTexture.h"
 
 namespace BansheeEngine
 {
 	/**
-	 * @brief	Interop class between C++ & CLR for GUIElementStateStyle.
+	 * @brief	Performs conversion between managed GUIElementStateStyle and native GUIElementStyle::GUIElementStateStyle.
 	 */
 	class BS_SCR_BE_EXPORT ScriptGUIElementStateStyle : public ScriptObject<ScriptGUIElementStateStyle>
 	{
 	public:
 		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "GUIElementStateStyle")
 
-		~ScriptGUIElementStateStyle();
-
-		/**
-		 * @brief	Returns a copy of the internal GUIElementStateStyle.
-		 */
-		GUIElementStyle::GUIElementStateStyle getInternalValue() const { return *mElementStateStyle; }
-
-	private:
 		/**
-		 * @brief	Creates the interop object with a brand new default style.
+		 * @brief	Creates a new managed instance of GUIElementStateStyle.
+		 *
+		 * @param	state	Native GUI element style state to copy to the managed instance.
 		 */
-		ScriptGUIElementStateStyle(MonoObject* instance);
+		static MonoObject* toManaged(const GUIElementStyle::GUIElementStateStyle& state);
 
 		/**
-		 * @brief	Creates the interop object by referencing an existing style instance.
+		 * @brief	Converts a managed instance of GUIElementStateStyle to a native GUI element style state.
 		 */
-		ScriptGUIElementStateStyle(MonoObject* instance, GUIElementStyle::GUIElementStateStyle* externalStyle);
-
-		GUIElementStyle::GUIElementStateStyle* mElementStateStyle;
-		ScriptSpriteTexture* mSpriteTexture;
-		bool mOwnsStyle;
-
-		/************************************************************************/
-		/* 								CLR HOOKS						   		*/
-		/************************************************************************/
-		static void internal_createInstance(MonoObject* instance);
-		static void internal_createInstanceExternal(MonoObject* instance, GUIElementStyle::GUIElementStateStyle* externalStateStyle);
+		static GUIElementStyle::GUIElementStateStyle toNative(MonoObject* instance);
 
-		static void internal_GetTexture(ScriptGUIElementStateStyle* nativeInstance, MonoObject** value);
-		static void internal_SetTexture(ScriptGUIElementStateStyle* nativeInstance, MonoObject* value);
+	private:
+		ScriptGUIElementStateStyle(MonoObject* instance);
 
-		static void internal_GetTextColor(ScriptGUIElementStateStyle* nativeInstance, Color* value);
-		static void internal_SetTextColor(ScriptGUIElementStateStyle* nativeInstance, Color* value);
+		static MonoField* sTextureField;
+		static MonoField* sTextColorField;
 	};
 }

+ 0 - 10
SBansheeEngine/Include/BsScriptGUIElementStyle.h

@@ -43,16 +43,6 @@ namespace BansheeEngine
 		String mName;
 		GUIElementStyle mElementStyle;
 
-		ScriptFont* mFont;
-		ScriptGUIElementStateStyle* mNormal;
-		ScriptGUIElementStateStyle* mHover;
-		ScriptGUIElementStateStyle* mActive;
-		ScriptGUIElementStateStyle* mFocused;
-		ScriptGUIElementStateStyle* mNormalOn;
-		ScriptGUIElementStateStyle* mHoverOn;
-		ScriptGUIElementStateStyle* mActiveOn;
-		ScriptGUIElementStateStyle* mFocusedOn;
-
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/

+ 35 - 46
SBansheeEngine/Source/BsScriptGUIElementStateStyle.cpp

@@ -4,73 +4,62 @@
 #include "BsMonoClass.h"
 #include "BsMonoManager.h"
 #include "BsScriptSpriteTexture.h"
-#include "BsException.h"
+#include "BsScriptResourceManager.h"
 #include "BsGUIElementStyle.h"
 
 namespace BansheeEngine
 {
+	MonoField* ScriptGUIElementStateStyle::sTextureField = nullptr;
+	MonoField* ScriptGUIElementStateStyle::sTextColorField = nullptr;
+
 	ScriptGUIElementStateStyle::ScriptGUIElementStateStyle(MonoObject* instance)
-		:ScriptObject(instance), mElementStateStyle(bs_new<GUIElementStyle::GUIElementStateStyle>()), mSpriteTexture(nullptr), mOwnsStyle(true)
+		:ScriptObject(instance)
 	{
 
 	}
 
-	ScriptGUIElementStateStyle::ScriptGUIElementStateStyle(MonoObject* instance, GUIElementStyle::GUIElementStateStyle* externalStyle)
-		:ScriptObject(instance), mElementStateStyle(externalStyle), mSpriteTexture(nullptr), mOwnsStyle(false)
+	void ScriptGUIElementStateStyle::initRuntimeData()
 	{
-
+		sTextureField = metaData.scriptClass->getField("Texture");
+		sTextColorField = metaData.scriptClass->getField("TextColor");
 	}
 
-	ScriptGUIElementStateStyle::~ScriptGUIElementStateStyle()
+	MonoObject* ScriptGUIElementStateStyle::toManaged(const GUIElementStyle::GUIElementStateStyle& state)
 	{
-		if(mOwnsStyle)
-			bs_delete(mElementStateStyle);
-	}
+		ScriptSpriteTexture* scriptTexture = nullptr;
 
-	void ScriptGUIElementStateStyle::initRuntimeData()
-	{
-		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptGUIElementStateStyle::internal_createInstance);
-		metaData.scriptClass->addInternalCall("Internal_GetTexture", &ScriptGUIElementStateStyle::internal_GetTexture);	
-		metaData.scriptClass->addInternalCall("Internal_SetTexture", &ScriptGUIElementStateStyle::internal_SetTexture);
-		metaData.scriptClass->addInternalCall("Internal_GetTextColor", &ScriptGUIElementStateStyle::internal_GetTextColor);
-		metaData.scriptClass->addInternalCall("Internal_SetTextColor", &ScriptGUIElementStateStyle::internal_SetTextColor);
-	}
+		if (state.texture != nullptr)
+			ScriptResourceManager::instance().getScriptResource(state.texture, &scriptTexture, true);
 
-	void ScriptGUIElementStateStyle::internal_createInstance(MonoObject* instance)
-	{
-		ScriptGUIElementStateStyle* nativeInstance = new (bs_alloc<ScriptGUIElementStateStyle>()) ScriptGUIElementStateStyle(instance);
-	}
+		MonoObject* instance = metaData.scriptClass->createInstance();
 
-	void ScriptGUIElementStateStyle::internal_createInstanceExternal(MonoObject* instance, GUIElementStyle::GUIElementStateStyle* externalStyle)
-	{
-		ScriptGUIElementStateStyle* nativeInstance = new (bs_alloc<ScriptGUIElementStateStyle>()) ScriptGUIElementStateStyle(instance, externalStyle);
+		if (scriptTexture != nullptr)
+			sTextureField->setValue(instance, scriptTexture->getManagedInstance());
+		else
+			sTextureField->setValue(instance, nullptr);
+
+		sTextColorField->setValue(instance, (void*)&state.textColor);
+		return instance;
 	}
 
-	void ScriptGUIElementStateStyle::internal_GetTexture(ScriptGUIElementStateStyle* nativeInstance, MonoObject** value)
+	GUIElementStyle::GUIElementStateStyle ScriptGUIElementStateStyle::toNative(MonoObject* instance)
 	{
-		if (nativeInstance->mSpriteTexture != nullptr)
-		{	
-			*value = nativeInstance->mSpriteTexture->getManagedInstance();
-			return;
-		}
+		GUIElementStyle::GUIElementStateStyle output;
 
-		*value = nullptr;
-	}
+		if (instance == nullptr)
+			return output;
 
-	void ScriptGUIElementStateStyle::internal_SetTexture(ScriptGUIElementStateStyle* nativeInstance, MonoObject* value)
-	{
-		ScriptSpriteTexture* nativeValue = ScriptSpriteTexture::toNative(value);
-		nativeInstance->mElementStateStyle->texture = nativeValue->getHandle();
-		nativeInstance->mSpriteTexture = nativeValue;
-	}
+		MonoObject* monoTexture = nullptr;
+		sTextureField->getValue(instance, &monoTexture);
 
-	void ScriptGUIElementStateStyle::internal_GetTextColor(ScriptGUIElementStateStyle* nativeInstance, Color* value)
-	{
-		*value = nativeInstance->mElementStateStyle->textColor;
-	}
+		if (monoTexture != nullptr)
+		{
+			ScriptSpriteTexture* scriptTexture = ScriptSpriteTexture::toNative(monoTexture);
+			output.texture = scriptTexture->getHandle();
+		}
 
-	void ScriptGUIElementStateStyle::internal_SetTextColor(ScriptGUIElementStateStyle* nativeInstance, Color* value)
-	{
-		nativeInstance->mElementStateStyle->textColor = *value;
-	}	
+		sTextColorField->getValue(instance, &output.textColor);
+
+		return output;
+	}
 }

+ 34 - 93
SBansheeEngine/Source/BsScriptGUIElementStyle.cpp

@@ -8,19 +8,18 @@
 #include "BsGUIElementStyle.h"
 #include "BsScriptGUIElementStateStyle.h"
 #include "BsMonoUtil.h"
+#include "BsScriptResourceManager.h"
 
 namespace BansheeEngine
 {
 	ScriptGUIElementStyle::ScriptGUIElementStyle(MonoObject* instance, const String& name)
-		:ScriptObject(instance), mName(name), mFont(nullptr), mNormal(nullptr), mHover(nullptr),
-		mActive(nullptr), mFocused(nullptr), mNormalOn(nullptr), mHoverOn(nullptr), mActiveOn(nullptr), mFocusedOn(nullptr)
+		:ScriptObject(instance), mName(name)
 	{
 
 	}
 
 	ScriptGUIElementStyle::ScriptGUIElementStyle(MonoObject* instance, const String& name, const GUIElementStyle& externalStyle)
-		:ScriptObject(instance), mName(name), mElementStyle(externalStyle), mFont(nullptr), mNormal(nullptr), mHover(nullptr),
-		mActive(nullptr), mFocused(nullptr), mNormalOn(nullptr), mHoverOn(nullptr), mActiveOn(nullptr), mFocusedOn(nullptr)
+		:ScriptObject(instance), mName(name), mElementStyle(externalStyle)
 	{
 
 	}
@@ -124,20 +123,27 @@ namespace BansheeEngine
 
 	void ScriptGUIElementStyle::internal_GetFont(ScriptGUIElementStyle* nativeInstance, MonoObject** value)
 	{
-		if (nativeInstance->mFont != nullptr)
+		const GUIElementStyle& style = nativeInstance->mElementStyle;
+		if (style.font != nullptr)
 		{
-			*value = nativeInstance->mFont->getManagedInstance();
-			return;
-		}
+			ScriptFont* scriptFont;
+			ScriptResourceManager::instance().getScriptResource(style.font, &scriptFont, true);
 
-		*value = nullptr;
+			*value = scriptFont->getManagedInstance();
+		}
+		else
+			*value = nullptr;
 	}
 
 	void ScriptGUIElementStyle::internal_SetFont(ScriptGUIElementStyle* nativeInstance, MonoObject* value)
 	{
-		ScriptFont* nativeValue = ScriptFont::toNative(value);
-		nativeInstance->mElementStyle.font = static_resource_cast<Font>(nativeValue->getHandle());
-		nativeInstance->mFont = nativeValue;
+		if (value != nullptr)
+		{
+			ScriptFont* nativeValue = ScriptFont::toNative(value);
+			nativeInstance->mElementStyle.font = nativeValue->getHandle();
+		}
+		else
+			nativeInstance->mElementStyle.font = nullptr;
 	}
 
 	void ScriptGUIElementStyle::internal_GetFontSize(ScriptGUIElementStyle* nativeInstance, UINT32* value)
@@ -192,147 +198,82 @@ namespace BansheeEngine
 
 	void ScriptGUIElementStyle::internal_GetNormal(ScriptGUIElementStyle* nativeInstance, MonoObject** value)
 	{
-		if (nativeInstance->mNormal != nullptr)
-		{
-			*value = nativeInstance->mNormal->getManagedInstance();
-			return;	
-		}
-
-		*value = nullptr;
+		*value = ScriptGUIElementStateStyle::toManaged(nativeInstance->mElementStyle.normal);
 	}
 
 	void ScriptGUIElementStyle::internal_SetNormal(ScriptGUIElementStyle* nativeInstance, MonoObject* value)
 	{
-		ScriptGUIElementStateStyle* nativeValue = ScriptGUIElementStateStyle::toNative(value);
-		nativeInstance->mElementStyle.normal = nativeValue->getInternalValue();
-		nativeInstance->mNormal = nativeValue;
+		nativeInstance->mElementStyle.normal = ScriptGUIElementStateStyle::toNative(value);
 	}
 
-
 	void ScriptGUIElementStyle::internal_GetHover(ScriptGUIElementStyle* nativeInstance, MonoObject** value)
 	{
-		if (nativeInstance->mHover != nullptr)
-		{
-			*value = nativeInstance->mHover->getManagedInstance();
-			return;
-		}
-
-		*value = nullptr;
+		*value = ScriptGUIElementStateStyle::toManaged(nativeInstance->mElementStyle.hover);
 	}
 
 	void ScriptGUIElementStyle::internal_SetHover(ScriptGUIElementStyle* nativeInstance, MonoObject* value)
 	{
-		ScriptGUIElementStateStyle* nativeValue = ScriptGUIElementStateStyle::toNative(value);
-		nativeInstance->mElementStyle.hover = nativeValue->getInternalValue();
-		nativeInstance->mHover = nativeValue;
+		nativeInstance->mElementStyle.hover = ScriptGUIElementStateStyle::toNative(value);
 	}
 
 	void ScriptGUIElementStyle::internal_GetActive(ScriptGUIElementStyle* nativeInstance, MonoObject** value)
 	{
-		if (nativeInstance->mActive != nullptr)
-		{
-			*value = nativeInstance->mActive->getManagedInstance();
-			return;
-		}
-
-		*value = nullptr;
+		*value = ScriptGUIElementStateStyle::toManaged(nativeInstance->mElementStyle.active);
 	}
 
 	void ScriptGUIElementStyle::internal_SetActive(ScriptGUIElementStyle* nativeInstance, MonoObject* value)
 	{
-		ScriptGUIElementStateStyle* nativeValue = ScriptGUIElementStateStyle::toNative(value);
-		nativeInstance->mElementStyle.active = nativeValue->getInternalValue();
-		nativeInstance->mActive = nativeValue;
+		nativeInstance->mElementStyle.active = ScriptGUIElementStateStyle::toNative(value);
 	}
 
 	void ScriptGUIElementStyle::internal_GetFocused(ScriptGUIElementStyle* nativeInstance, MonoObject** value)
 	{
-		if (nativeInstance->mFocused != nullptr)
-		{
-			*value = nativeInstance->mFocused->getManagedInstance();
-			return;
-		}
-
-		*value = nullptr;
+		*value = ScriptGUIElementStateStyle::toManaged(nativeInstance->mElementStyle.focused);
 	}
 
 	void ScriptGUIElementStyle::internal_SetFocused(ScriptGUIElementStyle* nativeInstance, MonoObject* value)
 	{
-		ScriptGUIElementStateStyle* nativeValue = ScriptGUIElementStateStyle::toNative(value);
-		nativeInstance->mElementStyle.focused = nativeValue->getInternalValue();
-		nativeInstance->mFocused = nativeValue;
+		nativeInstance->mElementStyle.focused = ScriptGUIElementStateStyle::toNative(value);
 	}
 
 	void ScriptGUIElementStyle::internal_GetNormalOn(ScriptGUIElementStyle* nativeInstance, MonoObject** value)
 	{
-		if (nativeInstance->mNormalOn != nullptr)
-		{
-			*value = nativeInstance->mNormalOn->getManagedInstance();
-			return;
-		}
-
-		*value = nullptr;
+		*value = ScriptGUIElementStateStyle::toManaged(nativeInstance->mElementStyle.normalOn);
 	}
 
 	void ScriptGUIElementStyle::internal_SetNormalOn(ScriptGUIElementStyle* nativeInstance, MonoObject* value)
 	{
-		ScriptGUIElementStateStyle* nativeValue = ScriptGUIElementStateStyle::toNative(value);
-		nativeInstance->mElementStyle.normalOn = nativeValue->getInternalValue();
-		nativeInstance->mNormalOn = nativeValue;
+		nativeInstance->mElementStyle.normalOn = ScriptGUIElementStateStyle::toNative(value);
 	}
 
 	void ScriptGUIElementStyle::internal_GetHoverOn(ScriptGUIElementStyle* nativeInstance, MonoObject** value)
 	{
-		if (nativeInstance->mHoverOn != nullptr)
-		{
-			*value = nativeInstance->mHoverOn->getManagedInstance();
-			return;
-		}
-
-		*value = nullptr;
+		*value = ScriptGUIElementStateStyle::toManaged(nativeInstance->mElementStyle.hoverOn);
 	}
 
 	void ScriptGUIElementStyle::internal_SetHoverOn(ScriptGUIElementStyle* nativeInstance, MonoObject* value)
 	{
-		ScriptGUIElementStateStyle* nativeValue = ScriptGUIElementStateStyle::toNative(value);
-		nativeInstance->mElementStyle.hoverOn = nativeValue->getInternalValue();
-		nativeInstance->mHoverOn = nativeValue;
+		nativeInstance->mElementStyle.hoverOn = ScriptGUIElementStateStyle::toNative(value);
 	}
 
 	void ScriptGUIElementStyle::internal_GetActiveOn(ScriptGUIElementStyle* nativeInstance, MonoObject** value)
 	{
-		if (nativeInstance->mActiveOn != nullptr)
-		{
-			*value = nativeInstance->mActiveOn->getManagedInstance();
-			return;
-		}
-
-		*value = nullptr;
+		*value = ScriptGUIElementStateStyle::toManaged(nativeInstance->mElementStyle.activeOn);
 	}
 
 	void ScriptGUIElementStyle::internal_SetActiveOn(ScriptGUIElementStyle* nativeInstance, MonoObject* value)
 	{
-		ScriptGUIElementStateStyle* nativeValue = ScriptGUIElementStateStyle::toNative(value);
-		nativeInstance->mElementStyle.activeOn = nativeValue->getInternalValue();
-		nativeInstance->mActiveOn = nativeValue;
+		nativeInstance->mElementStyle.activeOn = ScriptGUIElementStateStyle::toNative(value);
 	}
 
 	void ScriptGUIElementStyle::internal_GetFocusedOn(ScriptGUIElementStyle* nativeInstance, MonoObject** value)
 	{
-		if (nativeInstance->mFocusedOn != nullptr)
-		{
-			*value = nativeInstance->mFocusedOn->getManagedInstance();
-			return;
-		}
-
-		*value = nullptr;
+		*value = ScriptGUIElementStateStyle::toManaged(nativeInstance->mElementStyle.focusedOn);
 	}
 
 	void ScriptGUIElementStyle::internal_SetFocusedOn(ScriptGUIElementStyle* nativeInstance, MonoObject* value)
 	{
-		ScriptGUIElementStateStyle* nativeValue = ScriptGUIElementStateStyle::toNative(value);
-		nativeInstance->mElementStyle.focusedOn = nativeValue->getInternalValue();
-		nativeInstance->mFocusedOn = nativeValue;
+		nativeInstance->mElementStyle.focusedOn = ScriptGUIElementStateStyle::toNative(value);
 	}
 
 	void ScriptGUIElementStyle::internal_GetBorder(ScriptGUIElementStyle* nativeInstance, RectOffset* value)