Explorar el Código

Inspector refactor - Better abstraction, separated property and GUI modifications into two reported values (WIP)

BearishSun hace 10 años
padre
commit
db37436e98
Se han modificado 30 ficheros con 907 adiciones y 930 borrados
  1. 98 100
      MBansheeEditor/GUI/GUIListField.cs
  2. 15 19
      MBansheeEditor/Inspector/GenericInspector.cs
  3. 45 23
      MBansheeEditor/Inspector/InspectableArray.cs
  4. 10 19
      MBansheeEditor/Inspector/InspectableBool.cs
  5. 10 19
      MBansheeEditor/Inspector/InspectableColor.cs
  6. 83 40
      MBansheeEditor/Inspector/InspectableField.cs
  7. 10 19
      MBansheeEditor/Inspector/InspectableFloat.cs
  8. 10 19
      MBansheeEditor/Inspector/InspectableGameObjectRef.cs
  9. 9 18
      MBansheeEditor/Inspector/InspectableInt.cs
  10. 41 22
      MBansheeEditor/Inspector/InspectableList.cs
  11. 37 15
      MBansheeEditor/Inspector/InspectableObject.cs
  12. 9 18
      MBansheeEditor/Inspector/InspectableResourceRef.cs
  13. 9 18
      MBansheeEditor/Inspector/InspectableString.cs
  14. 9 18
      MBansheeEditor/Inspector/InspectableVector2.cs
  15. 9 18
      MBansheeEditor/Inspector/InspectableVector3.cs
  16. 9 18
      MBansheeEditor/Inspector/InspectableVector4.cs
  17. 11 6
      MBansheeEditor/Inspector/Inspector.cs
  18. 2 8
      MBansheeEditor/Inspector/InspectorWindow.cs
  19. 95 95
      MBansheeEditor/Inspectors/CameraInspector.cs
  20. 86 94
      MBansheeEditor/Inspectors/FontInspector.cs
  21. 30 37
      MBansheeEditor/Inspectors/LightInspector.cs
  22. 34 30
      MBansheeEditor/Inspectors/MaterialInspector.cs
  23. 45 55
      MBansheeEditor/Inspectors/MeshInspector.cs
  24. 21 19
      MBansheeEditor/Inspectors/PlainTextInspector.cs
  25. 6 13
      MBansheeEditor/Inspectors/PrefabInspector.cs
  26. 69 68
      MBansheeEditor/Inspectors/RenderableInspector.cs
  27. 24 22
      MBansheeEditor/Inspectors/ScriptCodeInspector.cs
  28. 26 24
      MBansheeEditor/Inspectors/SpriteTextureInspector.cs
  29. 44 55
      MBansheeEditor/Inspectors/Texture2DInspector.cs
  30. 1 1
      MBansheeEditor/MBansheeEditor.csproj

+ 98 - 100
MBansheeEditor/GUI/GUIArray.cs → MBansheeEditor/GUI/GUIListField.cs

@@ -11,23 +11,29 @@ namespace BansheeEditor
     /// <summary>
     /// Base class for objects that display GUI for a modifyable list of elements. Elements can be added, removed and moved.
     /// </summary>
-    public abstract class GUIListBase
+    public abstract class GUIListFieldBase
     {
         private const int IndentAmount = 5;
 
         protected IList list;
         protected Type listType;
 
-        protected List<GUIListRow> rows = new List<GUIListRow>();
+        protected List<GUIListFieldRow> rows = new List<GUIListFieldRow>();
         protected GUIIntField guiSizeField;
         protected GUILayoutX guiChildLayout;
         protected GUILayoutX guiTitleLayout;
+        protected GUILayoutY guiContentLayout;
         protected bool isExpanded;
 
+        /// <summary>
+        /// Triggered when an element in the list has been changed.
+        /// </summary>
+        public Action OnValueChanged;
+
         /// <summary>
         /// Constructs a new GUI list.
         /// </summary>
-        protected GUIListBase()
+        protected GUIListFieldBase()
         { }
 
         /// <summary>
@@ -39,7 +45,7 @@ namespace BansheeEditor
         /// <param name="listType">Type of the <paramref name="list"/> parameter. Needs to be specified in case that
         ///                        parameter is null.</param>
         /// <param name="layout">Layout to which to append the list GUI elements to.</param>
-        protected void Construct<T>(LocString title, IList list, Type listType, GUILayout layout) where T : GUIListRow, new()
+        protected void Construct<T>(LocString title, IList list, Type listType, GUILayout layout) where T : GUIListFieldRow, new()
         {
             this.list = list;
             this.listType = listType;
@@ -47,6 +53,7 @@ namespace BansheeEditor
             if (list == null)
             {
                 guiChildLayout = null;
+                guiContentLayout = null;
                 guiTitleLayout = layout.AddLayoutX();
 
                 guiTitleLayout.AddElement(new GUILabel(title));
@@ -92,7 +99,7 @@ namespace BansheeEditor
                     guiIndentLayoutX.AddSpace(IndentAmount);
                     GUILayoutY guiIndentLayoutY = guiIndentLayoutX.AddLayoutY();
                     guiIndentLayoutY.AddSpace(IndentAmount);
-                    GUILayoutY guiContentLayout = guiIndentLayoutY.AddLayoutY();
+                    guiContentLayout = guiIndentLayoutY.AddLayoutY();
                     guiIndentLayoutY.AddSpace(IndentAmount);
                     guiIndentLayoutX.AddSpace(IndentAmount);
                     guiChildLayout.AddSpace(IndentAmount);
@@ -103,7 +110,7 @@ namespace BansheeEditor
 
                     for (int i = 0; i < list.Count; i++)
                     {
-                        GUIListRow newRow = new T();
+                        GUIListFieldRow newRow = new T();
                         newRow.Update(this, guiContentLayout, i);
 
                         rows.Add(newRow);
@@ -112,19 +119,51 @@ namespace BansheeEditor
             }
         }
 
+        /// <summary>
+        /// Destroys the GUI elements.
+        /// </summary>
+        public void Destroy()
+        {
+            if (guiTitleLayout != null)
+            {
+                guiTitleLayout.Destroy();
+                guiTitleLayout = null;
+            }
+
+            if (guiChildLayout != null)
+            {
+                guiChildLayout.Destroy();
+                guiChildLayout = null;
+            }
+
+            for (int i = 0; i < rows.Count; i++)
+                rows[i].Destroy();
+
+            rows.Clear();
+        }
+
         /// <summary>
         /// Gets a value of an element at the specified index in the list.
         /// </summary>
         /// <param name="seqIndex">Sequential index of the element whose value to retrieve.</param>
         /// <returns>Value of the list element at the specified index.</returns>
-        protected internal abstract object GetValue(int seqIndex);
+        protected internal virtual object GetValue(int seqIndex)
+        {
+            return list[seqIndex];
+        }
 
         /// <summary>
         /// Sets a value of an element at the specified index in the list.
         /// </summary>
         /// <param name="seqIndex">Sequential index of the element whose value to set.</param>
         /// <param name="value">Value to assign to the element. Caller must ensure it is of valid type.</param>
-        protected internal abstract void SetValue(int seqIndex, object value);
+        protected internal virtual void SetValue(int seqIndex, object value)
+        {
+            list[seqIndex] = value;
+
+            if (OnValueChanged != null)
+                OnValueChanged();
+        }
 
         /// <summary>
         /// Triggered when the user clicks on the expand/collapse toggle in the title bar.
@@ -174,21 +213,45 @@ namespace BansheeEditor
         /// list index to the one right before it, if not at zero.
         /// </summary>
         /// <param name="index">Sequential index of the element in the list to move.</param>
-        protected internal abstract void OnMoveUpButtonClicked(int index);
+        protected internal virtual void OnMoveUpButtonClicked(int index)
+        {
+            if ((index - 1) >= 0)
+            {
+                object previousEntry = list[index - 1];
+
+                list[index - 1] = list[index];
+                list[index] = previousEntry;
+
+                if (OnValueChanged != null)
+                    OnValueChanged();
+            }
+        }
 
         /// <summary>
         /// Triggered when the user clicks on the move down button next to the list entry. Moves an element from the current
         /// list index to the one right after it, if the element isn't already the last element.
         /// </summary>
         /// <param name="index">Sequential index of the element in the list to move.</param>
-        protected internal abstract void OnMoveDownButtonClicked(int index);
+        protected internal virtual void OnMoveDownButtonClicked(int index)
+        {
+            if ((index + 1) < list.Count)
+            {
+                object nextEntry = list[index + 1];
+
+                list[index + 1] = list[index];
+                list[index] = nextEntry;
+
+                if (OnValueChanged != null)
+                    OnValueChanged();
+            }
+        }
     }
 
     /// <summary>
     /// Creates GUI elements that allow viewing and manipulation of a <see cref="System.Array"/>. When constructing the
     /// object user can provide a custom type that manages GUI for individual array elements.
     /// </summary>
-    public class GUIArray : GUIListBase
+    public class GUIArrayField : GUIListFieldBase
     {
         /// <summary>
         /// Triggered when the reference array has been changed. This does not include changes that only happen to its 
@@ -196,11 +259,6 @@ namespace BansheeEditor
         /// </summary>
         public Action<Array> OnChanged;
 
-        /// <summary>
-        /// Triggered when an element in the array has been changed.
-        /// </summary>
-        public Action OnValueChanged;
-
         /// <summary>
         /// Array object whose contents are displayed.
         /// </summary>
@@ -209,7 +267,7 @@ namespace BansheeEditor
         /// <summary>
         /// Constructs a new GUI array.
         /// </summary>
-        private GUIArray()
+        private GUIArrayField()
         { }
 
         /// <summary>
@@ -220,13 +278,13 @@ namespace BansheeEditor
         /// <param name="title">Label to display on the list GUI title.</param>
         /// <param name="array">Object containing the list data. Cannot be null.</param>
         /// <param name="layout">Layout to which to append the list GUI elements to.</param>
-        public static GUIArray Create<RowType, ElementType>(LocString title, ElementType[] array, GUILayout layout) 
-            where RowType : GUIListRow, new() 
+        public static GUIArrayField Create<RowType, ElementType>(LocString title, ElementType[] array, GUILayout layout) 
+            where RowType : GUIListFieldRow, new() 
         {
-            GUIArray newArray = new GUIArray();
-            newArray.Construct<RowType>(title, array, typeof(ElementType[]), layout);
+            GUIArrayField newArrayField = new GUIArrayField();
+            newArrayField.Construct<RowType>(title, array, typeof(ElementType[]), layout);
 
-            return newArray;
+            return newArrayField;
         }
 
         /// <summary>
@@ -238,32 +296,16 @@ namespace BansheeEditor
             bool anythingModified = false;
 
             for (int i = 0; i < rows.Count; i++)
-                anythingModified |= rows[i].Refresh();
-
-            return anythingModified;
-        }
-
-        /// <summary>
-        /// Destroys the GUI elements.
-        /// </summary>
-        public void Destroy()
-        {
-            if (guiTitleLayout != null)
             {
-                guiTitleLayout.Destroy();
-                guiTitleLayout = null;
-            }
+                bool updateGUI;
 
-            if (guiChildLayout != null)
-            {
-                guiChildLayout.Destroy();
-                guiChildLayout = null;
-            }
+                anythingModified |= rows[i].Refresh(out updateGUI);
 
-            for (int i = 0; i < rows.Count; i++)
-                rows[i].Destroy();
+                if (updateGUI)
+                    rows[i].Update(this, guiContentLayout, i);
+            }
 
-            rows.Clear();
+            return anythingModified;
         }
 
         /// <inheritdoc/>
@@ -302,21 +344,6 @@ namespace BansheeEditor
                 OnChanged((Array)list);
         }
 
-        /// <inheritdoc/>
-        protected internal override object GetValue(int seqIndex)
-        {
-            return list[seqIndex];
-        }
-
-        /// <inheritdoc/>
-        protected internal override void SetValue(int seqIndex, object value)
-        {
-            list[seqIndex] = value;
-
-            if (OnValueChanged != null)
-                OnValueChanged();
-        }
-
         /// <inheritdoc/>
         protected internal override void OnDeleteButtonClicked(int index)
         {
@@ -380,52 +407,22 @@ namespace BansheeEditor
             if (OnChanged != null)
                 OnChanged((Array)list);
         }
-
-        /// <inheritdoc/>
-        protected internal override void OnMoveUpButtonClicked(int index)
-        {
-            if ((index - 1) >= 0)
-            {
-                object previousEntry = list[index - 1];
-
-                list[index - 1] = list[index];
-                list[index] = previousEntry;
-
-                if (OnValueChanged != null)
-                    OnValueChanged();
-            }
-        }
-
-        /// <inheritdoc/>
-        protected internal override void OnMoveDownButtonClicked(int index)
-        {
-            if ((index + 1) < list.Count)
-            {
-                object nextEntry = list[index + 1];
-
-                list[index + 1] = list[index];
-                list[index] = nextEntry;
-
-                if (OnValueChanged != null)
-                    OnValueChanged();
-            }
-        }
     }
 
     /// <summary>
     /// Contains GUI elements for a single entry in a list.
     /// </summary>
-    public abstract class GUIListRow
+    public abstract class GUIListFieldRow
     {
         private GUILayoutX rowLayout;
-        private GUIListBase parent;
+        private GUIListFieldBase parent;
 
         protected int seqIndex;
 
         /// <summary>
         /// Constructs a new array row object.
         /// </summary>
-        protected GUIListRow()
+        protected GUIListFieldRow()
         {
 
         }
@@ -436,18 +433,16 @@ namespace BansheeEditor
         /// <param name="parent">Parent array GUI object that the entry is contained in.</param>
         /// <param name="parentLayout">Parent layout that row GUI elements will be added to.</param>
         /// <param name="seqIndex">Sequential index of the array entry.</param>
-        public void Update(GUIListBase parent, GUILayout parentLayout, int seqIndex)
+        public void Update(GUIListFieldBase parent, GUILayout parentLayout, int seqIndex)
         {
             this.parent = parent;
             this.seqIndex = seqIndex;
 
-            if (rowLayout != null)
-            {
-                rowLayout.Destroy();
-                rowLayout = null;
-            }
+            if (rowLayout == null)
+                rowLayout = parentLayout.AddLayoutX();
+            else
+                rowLayout.Clear();
 
-            rowLayout = parentLayout.AddLayoutX();
             GUILayoutY contentLayout = rowLayout.AddLayoutY();
 
             GUILayoutX titleLayout = CreateGUI(contentLayout);
@@ -491,9 +486,11 @@ namespace BansheeEditor
         /// <summary>
         /// Refreshes the GUI for the list row and checks if anything was modified.
         /// </summary>
+        /// <param name="updateGUI">Determines should the field's GUI elements be updated due to modifications.</param>
         /// <returns>True if any modifications were made, false otherwise.</returns>
-        internal protected virtual bool Refresh()
+        internal protected virtual bool Refresh(out bool updateGUI)
         {
+            updateGUI = false;
             return false;
         }
 
@@ -523,6 +520,7 @@ namespace BansheeEditor
         public void Destroy()
         {
             rowLayout.Destroy();
+            rowLayout = null;
         }
     }
 }

+ 15 - 19
MBansheeEditor/Inspector/GenericInspector.cs

@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Collections.Generic;
 using BansheeEngine;
 
 namespace BansheeEditor
@@ -13,43 +9,43 @@ namespace BansheeEditor
     /// </summary>
     internal sealed class GenericInspector : Inspector
     {
-        private bool isInitialized;
         private bool isEmpty = true;
         private List<InspectableField> inspectableFields = new List<InspectableField>();
 
-        /// <summary>
-        /// Initializes required data the first time <see cref="Refresh"/> is called.
-        /// </summary>
-        private void Initialize()
+        /// <inheritdoc/>
+        protected internal override void Initialize()
         {
             if (referencedObject != null)
             {
+                int currentIndex = 0;
                 SerializableObject serializableObject = new SerializableObject(referencedObject.GetType(), referencedObject);
                 foreach (var field in serializableObject.Fields)
                 {
                     if (!field.Inspectable)
                         continue;
 
-                    inspectableFields.Add(InspectableField.CreateInspectable(field.Name, 0, new InspectableFieldLayout(layout), field.GetProperty()));
+                    InspectableField inspectableField = InspectableField.CreateInspectable(field.Name, currentIndex, 0,
+                        new InspectableFieldLayout(layout), field.GetProperty());
+
+                    inspectableFields.Add(inspectableField);
                     isEmpty = false;
+
+                    currentIndex += inspectableField.GetNumLayoutElements();
                 }
             }
-
-            isInitialized = true;
         }
 
         /// <inheritdoc/>
-        internal override bool Refresh()
+        protected internal override bool Refresh()
         {
-            if (!isInitialized)
-                Initialize();
-
             bool anythingModified = false;
 
             int currentIndex = 0;
             foreach (var field in inspectableFields)
             {
-                anythingModified |= field.Refresh(currentIndex);
+                bool dummy;
+
+                anythingModified |= field.Refresh(currentIndex, out dummy);
                 currentIndex += field.GetNumLayoutElements();
             }
 
@@ -59,7 +55,7 @@ namespace BansheeEditor
         /// <inheritdoc/>
         internal override void SetVisible(bool visible)
         {
-            RootGUI.Enabled = !isEmpty && visible;
+            base.SetVisible(!isEmpty && visible);
         }
     }
 }

+ 45 - 23
MBansheeEditor/Inspector/InspectableArray.cs

@@ -119,40 +119,54 @@ namespace BansheeEditor
         }
 
         /// <inheritdoc/>
-        protected override bool IsModified()
+        protected override bool IsModified(out bool rebuildGUI)
         {
             if (forceUpdate)
+            {
+                rebuildGUI = true;
                 return true;
+            }
 
             object newPropertyValue = property.GetValue<object>();
             if (propertyValue == null)
-                return newPropertyValue != null;
+            {
+                rebuildGUI = newPropertyValue != null;
+                return rebuildGUI;
+            }
 
             if (newPropertyValue == null)
-                return propertyValue != null;
-
+            {
+                rebuildGUI = propertyValue != null;
+                return rebuildGUI;
+            }
+                
             SerializableArray array = property.GetArray();
             if (array.GetLength() != numArrayElements)
+            {
+                rebuildGUI = true;
                 return true;
-
-            return base.IsModified();
+            }
+                
+            return base.IsModified(out rebuildGUI);
         }
 
         /// <inheritdoc/>
-        public override bool Refresh(int layoutIndex)
+        public override bool Refresh(int layoutIndex, out bool updateGUI)
         {
             bool anythingModified = false;
 
-            if (IsModified())
+            if (IsModified(out updateGUI))
             {
-                Update(layoutIndex);
+                Update(layoutIndex, updateGUI);
                 anythingModified = true;
             }
-
+                
             for (int i = 0; i < ChildCount; i++)
             {
+                bool dummy;
+
                 InspectableField child = GetChild(i);
-                bool childModified = child.Refresh(0);
+                bool childModified = child.Refresh(0, out dummy);
 
                 if (childModified)
                     rows[i].Refresh(child, i, this);
@@ -164,14 +178,10 @@ namespace BansheeEditor
         }
 
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex)
+        protected override void BuildGUI(int layoutIndex)
         {
-            base.Update(layoutIndex);
-            forceUpdate = false;
             guiTitleLayout = null;
-
-            if (property.Type != SerializableProperty.FieldType.Array || property.InternalType.GetArrayRank() != 1) // We don't support multirank arrays
-                return;
+            guiChildLayout = null;
 
             foreach (var row in rows)
                 row.Destroy();
@@ -179,6 +189,9 @@ namespace BansheeEditor
             rows.Clear();
             layout.DestroyElements();
 
+            if (property.Type != SerializableProperty.FieldType.Array || property.InternalType.GetArrayRank() != 1) // We don't support multirank arrays
+                return;
+
             propertyValue = property.GetValue<object>();
             if (propertyValue == null)
             {
@@ -227,7 +240,7 @@ namespace BansheeEditor
                 if (isExpanded)
                 {
                     if (numArrayElements > 0)
-                    { 
+                    {
                         guiChildLayout = layout.AddLayoutX(layoutIndex);
                         guiChildLayout.AddSpace(IndentAmount);
 
@@ -242,10 +255,10 @@ namespace BansheeEditor
                         guiChildLayout.AddSpace(IndentAmount);
 
                         short backgroundDepth = (short)(Inspector.START_BACKGROUND_DEPTH - depth - 1);
-                        string bgPanelStyle = depth % 2 == 0 
-                            ? EditorStyles.InspectorContentBgAlternate 
+                        string bgPanelStyle = depth % 2 == 0
+                            ? EditorStyles.InspectorContentBgAlternate
                             : EditorStyles.InspectorContentBg;
-                        
+
                         GUIPanel backgroundPanel = guiContentPanel.AddPanel(backgroundDepth);
                         GUITexture inspectorContentBg = new GUITexture(null, bgPanelStyle);
                         backgroundPanel.AddElement(inspectorContentBg);
@@ -255,11 +268,10 @@ namespace BansheeEditor
                             EntryRow newRow = new EntryRow(guiContentLayout);
                             rows.Add(newRow);
 
-                            InspectableField childObj = CreateInspectable(i + ".", depth + 1, 
+                            InspectableField childObj = CreateInspectable(i + ".", 0, depth + 1,
                                 new InspectableFieldLayout(newRow.contentLayout), array.GetProperty(i));
                             AddChild(childObj);
 
-                            childObj.Refresh(0);
                             rows[i].Refresh(childObj, i, this);
                         }
                     }
@@ -269,6 +281,16 @@ namespace BansheeEditor
             }
         }
 
+        /// <inheritdoc/>
+        protected override void Update(int layoutIndex, bool rebuildGUI)
+        {
+            base.Update(layoutIndex, true);
+            BuildGUI(layoutIndex);
+
+            forceUpdate = false;
+            
+        }
+
         /// <summary>
         /// Triggered when the user clicks on the expand/collapse toggle in the title bar.
         /// </summary>

+ 10 - 19
MBansheeEditor/Inspector/InspectableBool.cs

@@ -14,7 +14,6 @@ namespace BansheeEditor
     {
         private bool propertyValue;
         private GUIToggleField guiField;
-        private bool isInitialized;
 
         /// <summary>
         /// Creates a new inspectable boolean GUI for the specified property.
@@ -30,11 +29,8 @@ namespace BansheeEditor
 
         }
 
-        /// <summary>
-        /// Initializes the GUI elements the first time <see cref="Update"/> gets called.
-        /// </summary>
-        /// <param name="layoutIndex">Index at which to insert the GUI elements.</param>
-        private void Initialize(int layoutIndex)
+        /// <inheritoc/>
+        protected override void BuildGUI(int layoutIndex)
         {
             if (property.Type == SerializableProperty.FieldType.Bool)
             {
@@ -43,30 +39,25 @@ namespace BansheeEditor
 
                 layout.AddElement(layoutIndex, guiField);
             }
-
-            isInitialized = true;
         }
 
         /// <inheritdoc/>
-        protected override bool IsModified()
+        protected override bool IsModified(out bool rebuildGUI)
         {
-            if (!isInitialized)
-                return true;
-
             bool newPropertyValue = property.GetValue<bool>();
             if (propertyValue != newPropertyValue)
+            {
+                rebuildGUI = false;
                 return true;
-
-            return base.IsModified();
+            }
+                
+            return base.IsModified(out rebuildGUI);
         }
 
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex)
+        protected override void Update(int layoutIndex, bool rebuildGUI)
         {
-            base.Update(layoutIndex);
-
-            if (!isInitialized)
-                Initialize(layoutIndex);
+            base.Update(layoutIndex, rebuildGUI);
 
             propertyValue = property.GetValue<bool>();
             if (guiField != null)

+ 10 - 19
MBansheeEditor/Inspector/InspectableColor.cs

@@ -15,7 +15,6 @@ namespace BansheeEditor
     {
         private Color propertyValue;
         private GUIColorField guiField;
-        private bool isInitialized;
 
         /// <summary>
         /// Creates a new inspectable color GUI for the specified property.
@@ -31,11 +30,8 @@ namespace BansheeEditor
 
         }
 
-        /// <summary>
-        /// Initializes the GUI elements the first time <see cref="Update"/> gets called.
-        /// </summary>
-        /// <param name="layoutIndex">Index at which to insert the GUI elements.</param>
-        private void Initialize(int layoutIndex)
+        /// <inheritoc/>
+        protected override void BuildGUI(int layoutIndex)
         {
             if (property.Type == SerializableProperty.FieldType.Color)
             {
@@ -44,30 +40,25 @@ namespace BansheeEditor
 
                 layout.AddElement(layoutIndex, guiField);
             }
-
-            isInitialized = true;
         }
 
         /// <inheritdoc/>
-        protected override bool IsModified()
+        protected override bool IsModified(out bool rebuildGUI)
         {
-            if (!isInitialized)
-                return true;
-
             Color newPropertyValue = property.GetValue<Color>();
             if (propertyValue != newPropertyValue)
+            {
+                rebuildGUI = false;
                 return true;
-
-            return base.IsModified();
+            }
+                
+            return base.IsModified(out rebuildGUI);
         }
 
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex)
+        protected override void Update(int layoutIndex, bool rebuildGUI)
         {
-            base.Update(layoutIndex);
-
-            if (!isInitialized)
-                Initialize(layoutIndex);
+            base.Update(layoutIndex, rebuildGUI);
 
             // TODO - Skip update if it currently has input focus so user can modify the value in peace
 

+ 83 - 40
MBansheeEditor/Inspector/InspectableField.cs

@@ -13,7 +13,7 @@ namespace BansheeEditor
     /// can and should be created recursively - normally complex types like objects and arrays will contain fields of their 
     /// own, while primitive types like integer or boolean will consist of only a GUI element.
     /// </summary>
-    public class InspectableField
+    public abstract class InspectableField
     {
         private List<InspectableField> children = new List<InspectableField>();
         private InspectableField parent;
@@ -68,22 +68,26 @@ namespace BansheeEditor
         /// <summary>
         /// Checks if contents of the field have been modified, and updates them if needed.
         /// </summary>
-        /// <param name="layoutIndex">Index in the parent's layout at which to insert the GUI elements for this field.</param>
+        /// <param name="layoutIndex">Index in the parent's layout at which to insert the GUI elements for this field.
+        ///                           </param>
+        /// <param name="rebuildGUI">Determines should the field's GUI elements be recreated due to modifications.</param>
         /// <returns>True if there were any modifications in this field, or any child fields.</returns>
-        public virtual bool Refresh(int layoutIndex)
+        public virtual bool Refresh(int layoutIndex, out bool rebuildGUI)
         {
             bool anythingModified = false;
 
-            if (IsModified())
+            if (IsModified(out rebuildGUI))
             {
-                Update(layoutIndex);
+                Update(layoutIndex, rebuildGUI);
                 anythingModified = true;
             }
-
+                
             int currentIndex = 0;
             for (int i = 0; i < children.Count; i++)
             {
-                anythingModified |= children[i].Refresh(currentIndex);
+                bool dummy;
+
+                anythingModified |= children[i].Refresh(currentIndex, out dummy);
                 currentIndex += children[i].GetNumLayoutElements();
             }
 
@@ -114,9 +118,11 @@ namespace BansheeEditor
         /// Checks have the values in the referenced serializable property have been changed compare to the value currently
         /// displayed in the field.
         /// </summary>
+        /// <param name="rebuildGUI">Determines should the field's GUI elements be recreated due to modifications.</param>
         /// <returns>True if the value has been modified and needs updating.</returns>
-        protected virtual bool IsModified()
+        protected virtual bool IsModified(out bool rebuildGUI)
         {
+            rebuildGUI = false;
             return false;
         }
 
@@ -124,8 +130,12 @@ namespace BansheeEditor
         /// Reconstructs the GUI by using the most up to date values from the referenced serializable property.
         /// </summary>
         /// <param name="layoutIndex">Index in the parent's layout at which to insert the GUI elements for this field.</param>
-        protected virtual void Update(int layoutIndex)
+        /// <param name="rebuildGUI">Determines should the field's GUI elements be recreated due to modifications.</param>
+        protected virtual void Update(int layoutIndex, bool rebuildGUI)
         {
+            if (!rebuildGUI)
+                return;
+
             // Destroy all children as we expect update to rebuild them
             InspectableField[] childrenCopy = children.ToArray();
             for (int i = 0; i < childrenCopy.Length; i++)
@@ -136,6 +146,12 @@ namespace BansheeEditor
             children.Clear();
         }
 
+        /// <summary>
+        /// Initializes the GUI elements for the field.
+        /// </summary>
+        /// <param name="layoutIndex">Index at which to insert the GUI elements.</param>
+        protected abstract void BuildGUI(int layoutIndex);
+
         /// <summary>
         /// Returns an inspectable field at the specified index.
         /// </summary>
@@ -178,51 +194,78 @@ namespace BansheeEditor
         /// <see cref="CustomInspector"/> attribute.
         /// </summary>
         /// <param name="title">Name of the property, or some other value to set as the title.</param>
+        /// <param name="layoutIndex">Index into the parent layout at which to insert the GUI elements for the field .</param>
         /// <param name="depth">Determines how deep within the inspector nesting hierarchy is this field. Some fields may
         ///                     contain other fields, in which case you should increase this value by one.</param>
         /// <param name="layout">Parent layout that all the field elements will be added to.</param>
         /// <param name="property">Serializable property referencing the array whose contents to display.</param>
         /// <returns>Inspectable field implementation that can be used for displaying the GUI for a serializable property
         ///          of the provided type.</returns>
-        public static InspectableField CreateInspectable(string title, int depth, InspectableFieldLayout layout, SerializableProperty property)
+        public static InspectableField CreateInspectable(string title, int layoutIndex, int depth, 
+            InspectableFieldLayout layout, SerializableProperty property)
         {
+            InspectableField field = null;
+
             Type customInspectable = InspectorUtility.GetCustomInspectable(property.InternalType);
             if (customInspectable != null)
             {
-                return (InspectableField)Activator.CreateInstance(customInspectable, depth, title, property);
+                field = (InspectableField) Activator.CreateInstance(customInspectable, depth, title, property);
             }
-
-            switch (property.Type)
+            else
             {
-                case SerializableProperty.FieldType.Int:
-                    return new InspectableInt(title, depth, layout, property);
-                case SerializableProperty.FieldType.Float:
-                    return new InspectableFloat(title, depth, layout, property);
-                case SerializableProperty.FieldType.Bool:
-                    return new InspectableBool(title, depth, layout, property);
-                case SerializableProperty.FieldType.Color:
-                    return new InspectableColor(title, depth, layout, property);
-                case SerializableProperty.FieldType.String:
-                    return new InspectableString(title, depth, layout, property);
-                case SerializableProperty.FieldType.Vector2:
-                    return new InspectableVector2(title, depth, layout, property);
-                case SerializableProperty.FieldType.Vector3:
-                    return new InspectableVector3(title, depth, layout, property);
-                case SerializableProperty.FieldType.Vector4:
-                    return new InspectableVector4(title, depth, layout, property);
-                case SerializableProperty.FieldType.ResourceRef:
-                    return new InspectableResourceRef(title, depth, layout, property);
-                case SerializableProperty.FieldType.GameObjectRef:
-                    return new InspectableGameObjectRef(title, depth, layout, property);
-                case SerializableProperty.FieldType.Object:
-                    return new InspectableObject(title, depth, layout, property);
-                case SerializableProperty.FieldType.Array:
-                    return new InspectableArray(title, depth, layout, property);
-                case SerializableProperty.FieldType.List:
-                    return new InspectableList(title, depth, layout, property);
+                switch (property.Type)
+                {
+                    case SerializableProperty.FieldType.Int:
+                        field = new InspectableInt(title, depth, layout, property);
+                        break;
+                    case SerializableProperty.FieldType.Float:
+                        field = new InspectableFloat(title, depth, layout, property);
+                        break;
+                    case SerializableProperty.FieldType.Bool:
+                        field = new InspectableBool(title, depth, layout, property);
+                        break;
+                    case SerializableProperty.FieldType.Color:
+                        field = new InspectableColor(title, depth, layout, property);
+                        break;
+                    case SerializableProperty.FieldType.String:
+                        field = new InspectableString(title, depth, layout, property);
+                        break;
+                    case SerializableProperty.FieldType.Vector2:
+                        field = new InspectableVector2(title, depth, layout, property);
+                        break;
+                    case SerializableProperty.FieldType.Vector3:
+                        field = new InspectableVector3(title, depth, layout, property);
+                        break;
+                    case SerializableProperty.FieldType.Vector4:
+                        field = new InspectableVector4(title, depth, layout, property);
+                        break;
+                    case SerializableProperty.FieldType.ResourceRef:
+                        field = new InspectableResourceRef(title, depth, layout, property);
+                        break;
+                    case SerializableProperty.FieldType.GameObjectRef:
+                        field = new InspectableGameObjectRef(title, depth, layout, property);
+                        break;
+                    case SerializableProperty.FieldType.Object:
+                        field = new InspectableObject(title, depth, layout, property);
+                        break;
+                    case SerializableProperty.FieldType.Array:
+                        field = new InspectableArray(title, depth, layout, property);
+                        break;
+                    case SerializableProperty.FieldType.List:
+                        field = new InspectableList(title, depth, layout, property);
+                        break;
+                }
             }
 
-            throw new Exception("No inspector exists for the provided field type.");
+            if (field == null)
+                throw new Exception("No inspector exists for the provided field type.");
+
+            field.BuildGUI(layoutIndex);
+
+            bool dummy;
+            field.Refresh(layoutIndex, out dummy);
+
+            return field;
         }
     }
 }

+ 10 - 19
MBansheeEditor/Inspector/InspectableFloat.cs

@@ -14,7 +14,6 @@ namespace BansheeEditor
     {
         private float propertyValue;
         private GUIFloatField guiFloatField;
-        private bool isInitialized;
 
         /// <summary>
         /// Creates a new inspectable float GUI for the specified property.
@@ -30,11 +29,8 @@ namespace BansheeEditor
 
         }
 
-        /// <summary>
-        /// Initializes the GUI elements the first time <see cref="Update"/> gets called.
-        /// </summary>
-        /// <param name="layoutIndex">Index at which to insert the GUI elements.</param>
-        private void Initialize(int layoutIndex)
+        /// <inheritoc/>
+        protected override void BuildGUI(int layoutIndex)
         {
             if (property.Type == SerializableProperty.FieldType.Float)
             {
@@ -43,30 +39,25 @@ namespace BansheeEditor
 
                 layout.AddElement(layoutIndex, guiFloatField);
             }
-
-            isInitialized = true;
         }
 
         /// <inheritdoc/>
-        protected override bool IsModified()
+        protected override bool IsModified(out bool rebuildGUI)
         {
-            if (!isInitialized)
-                return true;
-
             float newPropertyValue = property.GetValue<float>();
             if (propertyValue != newPropertyValue)
+            {
+                rebuildGUI = false;
                 return true;
-
-            return base.IsModified();
+            }
+                
+            return base.IsModified(out rebuildGUI);
         }
 
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex)
+        protected override void Update(int layoutIndex, bool rebuildGUI)
         {
-            base.Update(layoutIndex);
-
-            if (!isInitialized)
-                Initialize(layoutIndex);
+            base.Update(layoutIndex, rebuildGUI);
 
             propertyValue = property.GetValue<float>();
             if (guiFloatField != null)

+ 10 - 19
MBansheeEditor/Inspector/InspectableGameObjectRef.cs

@@ -14,7 +14,6 @@ namespace BansheeEditor
     {
         private GameObject propertyValue;
         private GUIGameObjectField guiField;
-        private bool isInitialized;
 
         /// <summary>
         /// Creates a new inspectable game object reference GUI for the specified property.
@@ -30,11 +29,8 @@ namespace BansheeEditor
 
         }
 
-        /// <summary>
-        /// Initializes the GUI elements the first time <see cref="Update"/> gets called.
-        /// </summary>
-        /// <param name="layoutIndex">Index at which to insert the GUI elements.</param>
-        private void Initialize(int layoutIndex)
+        /// <inheritoc/>
+        protected override void BuildGUI(int layoutIndex)
         {
             if (property.Type == SerializableProperty.FieldType.GameObjectRef)
             {
@@ -43,30 +39,25 @@ namespace BansheeEditor
 
                 layout.AddElement(layoutIndex, guiField);
             }
-
-            isInitialized = true;
         }
 
         /// <inheritdoc/>
-        protected override bool IsModified()
+        protected override bool IsModified(out bool rebuildGUI)
         {
-            if (!isInitialized)
-                return true;
-
             GameObject newPropertyValue = property.GetValue<GameObject>();
             if (propertyValue != newPropertyValue)
+            {
+                rebuildGUI = false;
                 return true;
-
-            return base.IsModified();
+            }
+                
+            return base.IsModified(out rebuildGUI);
         }
 
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex)
+        protected override void Update(int layoutIndex, bool rebuildGUI)
         {
-            base.Update(layoutIndex);
-
-            if (!isInitialized)
-                Initialize(layoutIndex);
+            base.Update(layoutIndex, rebuildGUI);
 
             propertyValue = property.GetValue<GameObject>();
             if (guiField != null)

+ 9 - 18
MBansheeEditor/Inspector/InspectableInt.cs

@@ -14,7 +14,6 @@ namespace BansheeEditor
     {
         private int propertyValue;
         private GUIIntField guiIntField;
-        private bool isInitialized;
 
         /// <summary>
         /// Creates a new inspectable integer GUI for the specified property.
@@ -30,11 +29,8 @@ namespace BansheeEditor
 
         }
 
-        /// <summary>
-        /// Initializes the GUI elements the first time <see cref="Update"/> gets called.
-        /// </summary>
-        /// <param name="layoutIndex">Index at which to insert the GUI elements.</param>
-        private void Initialize(int layoutIndex)
+        /// <inheritdoc/>
+        protected override void BuildGUI(int layoutIndex)
         {
             if (property.Type == SerializableProperty.FieldType.Int)
             {
@@ -43,30 +39,25 @@ namespace BansheeEditor
 
                 layout.AddElement(layoutIndex, guiIntField);
             }
-
-            isInitialized = true;
         }
 
         /// <inheritdoc/>
-        protected override bool IsModified()
+        protected override bool IsModified(out bool rebuildGUI)
         {
-            if (!isInitialized)
-                return true;
-
             int newPropertyValue = property.GetValue<int>();
             if (propertyValue != newPropertyValue)
+            {
+                rebuildGUI = false;
                 return true;
+            }
 
-            return base.IsModified();
+            return base.IsModified(out rebuildGUI);
         }
 
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex)
+        protected override void Update(int layoutIndex, bool rebuildGUI)
         {
-            base.Update(layoutIndex);
-
-            if (!isInitialized)
-                Initialize(layoutIndex);
+            base.Update(layoutIndex, rebuildGUI);
 
             propertyValue = property.GetValue<int>();
             if (guiIntField != null)

+ 41 - 22
MBansheeEditor/Inspector/InspectableList.cs

@@ -39,7 +39,7 @@ namespace BansheeEditor
             /// <param name="child">Inspectable field of the list entry.</param>
             /// <param name="seqIndex">Sequential index of the list entry.</param>
             /// <param name="parent">Parent list object that the entry is contained in.</param>
-            public void Refresh(InspectableField child, int seqIndex, InspectableList parent)
+            public void BuildGUI(InspectableField child, int seqIndex, InspectableList parent)
             {
                 if (ownsTitleLayout || (titleLayout != null && titleLayout == child.GetTitleLayout()))
                     return;
@@ -119,43 +119,57 @@ namespace BansheeEditor
         }
 
         /// <inheritdoc/>
-        protected override bool IsModified()
+        protected override bool IsModified(out bool rebuildGUI)
         {
             if (forceUpdate)
+            {
+                rebuildGUI = true;
                 return true;
-
+            }
+                
             object newPropertyValue = property.GetValue<object>();
             if (propertyValue == null)
-                return newPropertyValue != null;
+            {
+                rebuildGUI = newPropertyValue != null;
+                return rebuildGUI;
+            }
 
             if (newPropertyValue == null)
-                return propertyValue != null;
+            {
+                rebuildGUI = propertyValue != null;
+                return rebuildGUI;
+            }
 
             SerializableList list = property.GetList();
             if (list.GetLength() != numArrayElements)
+            {
+                rebuildGUI = true;
                 return true;
+            }
 
-            return base.IsModified();
+            return base.IsModified(out rebuildGUI);
         }
 
         /// <inheritdoc/>
-        public override bool Refresh(int layoutIndex)
+        public override bool Refresh(int layoutIndex, out bool rebuildGUI)
         {
             bool anythingModified = false;
 
-            if (IsModified())
+            if (IsModified(out rebuildGUI))
             {
-                Update(layoutIndex);
+                Update(layoutIndex, rebuildGUI);
                 anythingModified = true;
             }
 
             for (int i = 0; i < ChildCount; i++)
             {
                 InspectableField child = GetChild(i);
-                bool childModified = child.Refresh(0);
 
-                if (childModified)
-                    rows[i].Refresh(child, i, this);
+                bool childGUIRebuilt;
+                bool childModified = child.Refresh(0, out childGUIRebuilt);
+
+                if (childGUIRebuilt)
+                    rows[i].BuildGUI(child, i, this);
 
                 anythingModified |= childModified;
             }
@@ -164,21 +178,19 @@ namespace BansheeEditor
         }
 
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex)
+        protected override void BuildGUI(int layoutIndex)
         {
-            base.Update(layoutIndex);
-            forceUpdate = false;
             guiTitleLayout = null;
 
-            if (property.Type != SerializableProperty.FieldType.List)
-                return;
-
             foreach (var row in rows)
                 row.Destroy();
 
             rows.Clear();
             layout.DestroyElements();
 
+            if (property.Type != SerializableProperty.FieldType.List)
+                return;
+
             propertyValue = property.GetValue<object>();
             if (propertyValue == null)
             {
@@ -241,7 +253,7 @@ namespace BansheeEditor
                         guiIndentLayoutX.AddSpace(IndentAmount);
                         guiChildLayout.AddSpace(IndentAmount);
 
-                        short backgroundDepth = (short) (Inspector.START_BACKGROUND_DEPTH - depth - 1);
+                        short backgroundDepth = (short)(Inspector.START_BACKGROUND_DEPTH - depth - 1);
                         string bgPanelStyle = depth % 2 == 0
                             ? EditorStyles.InspectorContentBgAlternate
                             : EditorStyles.InspectorContentBg;
@@ -255,12 +267,11 @@ namespace BansheeEditor
                             EntryRow newRow = new EntryRow(guiContentLayout);
                             rows.Add(newRow);
 
-                            InspectableField childObj = CreateInspectable(i + ".", depth + 1,
+                            InspectableField childObj = CreateInspectable(i + ".", 0, depth + 1,
                                 new InspectableFieldLayout(newRow.contentLayout), list.GetProperty(i));
                             AddChild(childObj);
 
-                            childObj.Refresh(0);
-                            rows[i].Refresh(childObj, i, this);
+                            rows[i].BuildGUI(childObj, i, this);
                         }
                     }
                 }
@@ -269,6 +280,14 @@ namespace BansheeEditor
             }
         }
 
+        /// <inheritdoc/>
+        protected override void Update(int layoutIndex, bool rebuildGUI)
+        {
+            base.Update(layoutIndex, true);
+            BuildGUI(layoutIndex);
+            forceUpdate = false;
+        }
+
         /// <summary>
         /// Triggered when the user clicks on the expand/collapse toggle in the title bar.
         /// </summary>

+ 37 - 15
MBansheeEditor/Inspector/InspectableObject.cs

@@ -43,33 +43,41 @@ namespace BansheeEditor
         }
 
         /// <inheritdoc/>
-        protected override bool IsModified()
+        protected override bool IsModified(out bool rebuildGUI)
         {
             if (forceUpdate)
+            {
+                rebuildGUI = true;
                 return true;
-
+            }
+                
             object newPropertyValue = property.GetValue<object>();
             if (propertyValue == null)
-                return newPropertyValue != null;
-            
+            {
+                rebuildGUI = newPropertyValue != null;
+                return rebuildGUI;
+            }
+
             if (newPropertyValue == null)
-                return propertyValue != null;
-            
-            return base.IsModified();
+            {
+                rebuildGUI = propertyValue != null;
+                return rebuildGUI;
+            }
+
+            return base.IsModified(out rebuildGUI);
         }
 
         /// <inheritdoc/>
-        protected override void Update(int index)
+        protected override void BuildGUI(int index)
         {
-            base.Update(index);
-            forceUpdate = false;
             guiTitleLayout = null;
+            guiChildLayout = null;
+
+            layout.DestroyElements();
 
             if (property.Type != SerializableProperty.FieldType.Object)
                 return;
 
-            layout.DestroyElements();
-
             propertyValue = property.GetValue<object>();
             if (propertyValue == null)
             {
@@ -107,7 +115,7 @@ namespace BansheeEditor
                     SerializableField[] fields = serializableObject.Fields;
 
                     if (fields.Length > 0)
-                    { 
+                    {
                         guiChildLayout = layout.AddLayoutX(index);
                         guiChildLayout.AddSpace(IndentAmount);
 
@@ -121,18 +129,23 @@ namespace BansheeEditor
                         guiIndentLayoutX.AddSpace(IndentAmount);
                         guiChildLayout.AddSpace(IndentAmount);
 
-                        short backgroundDepth = (short) (Inspector.START_BACKGROUND_DEPTH - depth - 1);
+                        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);
 
+                        int currentIndex = 0;
                         foreach (var field in fields)
                         {
                             if (!field.Inspectable)
                                 continue;
 
-                            AddChild(CreateInspectable(field.Name, depth + 1, new InspectableFieldLayout(guiContentLayout), field.GetProperty()));
+                            InspectableField inspectable = CreateInspectable(field.Name, currentIndex, depth + 1,
+                                new InspectableFieldLayout(guiContentLayout), field.GetProperty());
+
+                            AddChild(inspectable);
+                            currentIndex += inspectable.GetNumLayoutElements();
                         }
                     }
                 }
@@ -141,6 +154,15 @@ namespace BansheeEditor
             }
         }
 
+        /// <inheritdoc/>
+        protected override void Update(int layoutIndex, bool rebuildGUI)
+        {
+            base.Update(layoutIndex, true);
+            BuildGUI(layoutIndex);
+
+            forceUpdate = false;
+        }
+
         /// <summary>
         /// Triggered when the user clicks on the expand/collapse toggle in the title bar.
         /// </summary>

+ 9 - 18
MBansheeEditor/Inspector/InspectableResourceRef.cs

@@ -14,7 +14,6 @@ namespace BansheeEditor
     {
         private Resource propertyValue;
         private GUIResourceField guiField;
-        private bool isInitialized;
 
         /// <summary>
         /// Creates a new inspectable resource reference GUI for the specified property.
@@ -30,11 +29,8 @@ namespace BansheeEditor
 
         }
 
-        /// <summary>
-        /// Initializes the GUI elements the first time <see cref="Update"/> gets called.
-        /// </summary>
-        /// <param name="layoutIndex">Index at which to insert the GUI elements.</param>
-        private void Initialize(int layoutIndex)
+        /// <inheritoc/>
+        protected override void BuildGUI(int layoutIndex)
         {
             if (property.Type == SerializableProperty.FieldType.ResourceRef)
             {
@@ -43,30 +39,25 @@ namespace BansheeEditor
 
                 layout.AddElement(layoutIndex, guiField);
             }
-
-            isInitialized = true;
         }
 
         /// <inheritdoc/>
-        protected override bool IsModified()
+        protected override bool IsModified(out bool rebuildGUI)
         {
-            if (!isInitialized)
-                return true;
-
             Resource newPropertyValue = property.GetValue<Resource>();
             if (propertyValue != newPropertyValue)
+            {
+                rebuildGUI = false;
                 return true;
+            }
 
-            return base.IsModified();
+            return base.IsModified(out rebuildGUI);
         }
 
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex)
+        protected override void Update(int layoutIndex, bool rebuildGUI)
         {
-            base.Update(layoutIndex);
-
-            if (!isInitialized)
-                Initialize(layoutIndex);
+            base.Update(layoutIndex, rebuildGUI);
 
             propertyValue = property.GetValue<Resource>();
             if (guiField != null)

+ 9 - 18
MBansheeEditor/Inspector/InspectableString.cs

@@ -14,7 +14,6 @@ namespace BansheeEditor
     {
         private string propertyValue;
         private GUITextField guiField;
-        private bool isInitialized;
 
         /// <summary>
         /// Creates a new inspectable string GUI for the specified property.
@@ -30,11 +29,8 @@ namespace BansheeEditor
 
         }
 
-        /// <summary>
-        /// Initializes the GUI elements the first time <see cref="Update"/> gets called.
-        /// </summary>
-        /// <param name="layoutIndex">Index at which to insert the GUI elements.</param>
-        private void Initialize(int layoutIndex)
+        /// <inheritoc/>
+        protected override void BuildGUI(int layoutIndex)
         {
             if (property.Type == SerializableProperty.FieldType.String)
             {
@@ -43,30 +39,25 @@ namespace BansheeEditor
 
                 layout.AddElement(layoutIndex, guiField);
             }
-
-            isInitialized = true;
         }
 
         /// <inheritdoc/>
-        protected override bool IsModified()
+        protected override bool IsModified(out bool rebuildGUI)
         {
-            if (!isInitialized)
-                return true;
-
             string newPropertyValue = property.GetValue<string>();
             if (propertyValue != newPropertyValue)
+            {
+                rebuildGUI = false;
                 return true;
+            }
 
-            return base.IsModified();
+            return base.IsModified(out rebuildGUI);
         }
 
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex)
+        protected override void Update(int layoutIndex, bool rebuildGUI)
         {
-            base.Update(layoutIndex);
-
-            if (!isInitialized)
-                Initialize(layoutIndex);
+            base.Update(layoutIndex, rebuildGUI);
 
             propertyValue = property.GetValue<string>();
             if (guiField != null)

+ 9 - 18
MBansheeEditor/Inspector/InspectableVector2.cs

@@ -14,7 +14,6 @@ namespace BansheeEditor
     {
         private Vector2 propertyValue;
         private GUIVector2Field guiField;
-        private bool isInitialized;
 
         /// <summary>
         /// Creates a new inspectable 2D vector GUI for the specified property.
@@ -30,11 +29,8 @@ namespace BansheeEditor
 
         }
 
-        /// <summary>
-        /// Initializes the GUI elements the first time <see cref="Update"/> gets called.
-        /// </summary>
-        /// <param name="layoutIndex">Index at which to insert the GUI elements.</param>
-        private void Initialize(int layoutIndex)
+        /// <inheritoc/>
+        protected override void BuildGUI(int layoutIndex)
         {
             if (property.Type == SerializableProperty.FieldType.Vector2)
             {
@@ -43,30 +39,25 @@ namespace BansheeEditor
 
                 layout.AddElement(layoutIndex, guiField);
             }
-
-            isInitialized = true;
         }
 
         /// <inheritdoc/>
-        protected override bool IsModified()
+        protected override bool IsModified(out bool rebuildGUI)
         {
-            if (!isInitialized)
-                return true;
-
             Vector2 newPropertyValue = property.GetValue<Vector2>();
             if (propertyValue != newPropertyValue)
+            {
+                rebuildGUI = false;
                 return true;
+            }
 
-            return base.IsModified();
+            return base.IsModified(out rebuildGUI);
         }
 
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex)
+        protected override void Update(int layoutIndex, bool rebuildGUI)
         {
-            base.Update(layoutIndex);
-
-            if (!isInitialized)
-                Initialize(layoutIndex);
+            base.Update(layoutIndex, rebuildGUI);
 
             propertyValue = property.GetValue<Vector2>();
             if (guiField != null)

+ 9 - 18
MBansheeEditor/Inspector/InspectableVector3.cs

@@ -14,7 +14,6 @@ namespace BansheeEditor
     {
         private Vector3 propertyValue;
         private GUIVector3Field guiField;
-        private bool isInitialized;
 
         /// <summary>
         /// Creates a new inspectable 3D vector GUI for the specified property.
@@ -30,11 +29,8 @@ namespace BansheeEditor
 
         }
 
-        /// <summary>
-        /// Initializes the GUI elements the first time <see cref="Update"/> gets called.
-        /// </summary>
-        /// <param name="layoutIndex">Index at which to insert the GUI elements.</param>
-        private void Initialize(int layoutIndex)
+        /// <inheritoc/>
+        protected override void BuildGUI(int layoutIndex)
         {
             if (property.Type == SerializableProperty.FieldType.Vector3)
             {
@@ -43,30 +39,25 @@ namespace BansheeEditor
 
                 layout.AddElement(layoutIndex, guiField);
             }
-
-            isInitialized = true;
         }
 
         /// <inheritdoc/>
-        protected override bool IsModified()
+        protected override bool IsModified(out bool rebuildGUI)
         {
-            if (!isInitialized)
-                return true;
-
             Vector3 newPropertyValue = property.GetValue<Vector3>();
             if (propertyValue != newPropertyValue)
+            {
+                rebuildGUI = false;
                 return true;
+            }
 
-            return base.IsModified();
+            return base.IsModified(out rebuildGUI);
         }
 
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex)
+        protected override void Update(int layoutIndex, bool rebuildGUI)
         {
-            base.Update(layoutIndex);
-
-            if (!isInitialized)
-                Initialize(layoutIndex);
+            base.Update(layoutIndex, rebuildGUI);
 
             propertyValue = property.GetValue<Vector3>();
             if (guiField != null)

+ 9 - 18
MBansheeEditor/Inspector/InspectableVector4.cs

@@ -14,7 +14,6 @@ namespace BansheeEditor
     {
         private Vector4 propertyValue;
         private GUIVector4Field guiField;
-        private bool isInitialized;
 
         /// <summary>
         /// Creates a new inspectable 4D vector GUI for the specified property.
@@ -30,11 +29,8 @@ namespace BansheeEditor
 
         }
 
-        /// <summary>
-        /// Initializes the GUI elements the first time <see cref="Update"/> gets called.
-        /// </summary>
-        /// <param name="layoutIndex">Index at which to insert the GUI elements.</param>
-        private void Initialize(int layoutIndex)
+        /// <inheritoc/>
+        protected override void BuildGUI(int layoutIndex)
         {
             if (property.Type == SerializableProperty.FieldType.Vector4)
             {
@@ -43,30 +39,25 @@ namespace BansheeEditor
 
                 layout.AddElement(layoutIndex, guiField);
             }
-
-            isInitialized = true;
         }
 
         /// <inheritdoc/>
-        protected override bool IsModified()
+        protected override bool IsModified(out bool rebuildGUI)
         {
-            if (!isInitialized)
-                return true;
-
             Vector4 newPropertyValue = property.GetValue<Vector4>();
             if (propertyValue != newPropertyValue)
+            {
+                rebuildGUI = false;
                 return true;
+            }
 
-            return base.IsModified();
+            return base.IsModified(out rebuildGUI);
         }
 
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex)
+        protected override void Update(int layoutIndex, bool rebuildGUI)
         {
-            base.Update(layoutIndex);
-
-            if (!isInitialized)
-                Initialize(layoutIndex);
+            base.Update(layoutIndex, rebuildGUI);
 
             propertyValue = property.GetValue<Vector4>();
             if (guiField != null)

+ 11 - 6
MBansheeEditor/Inspector/Inspector.cs

@@ -13,20 +13,18 @@ namespace BansheeEditor
     {
         public const short START_BACKGROUND_DEPTH = 50;
 
-        protected GUIPanel RootGUI;
         protected GUIPanel GUI;
         protected GUILayoutY layout;
         protected object referencedObject;
 
-        private InspectorWindow parentWindow;
+        private GUIPanel RootGUI;
 
         /// <summary>
         /// Initializes the inspector. Must be called after construction.
         /// </summary>
-        /// <param name="parentWindow">Parent window to render the GUI 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>
-        internal virtual void Initialize(InspectorWindow parentWindow, GUIPanel gui, object instance)
+        internal virtual void Initialize(GUIPanel gui, object instance)
         {
             RootGUI = gui;
 
@@ -45,7 +43,9 @@ namespace BansheeEditor
             GUI = contentPanel;
             layout = GUI.AddLayoutY();
             referencedObject = instance;
-            this.parentWindow = parentWindow;
+
+            Initialize();
+            Refresh();
         }
 
         /// <summary>
@@ -66,10 +66,15 @@ namespace BansheeEditor
             GUI.Destroy();
         }
 
+        /// <summary>
+        /// Called when the inspector is first created.
+        /// </summary>
+        protected internal abstract void Initialize();
+
         /// <summary>
         /// Checks if contents of the inspector have been modified, and updates them if needed.
         /// </summary>
         /// <returns>True if there were any modifications, false otherwise.</returns>
-        internal abstract bool Refresh();
+        protected internal abstract bool Refresh();
     }
 }

+ 2 - 8
MBansheeEditor/Inspector/InspectorWindow.cs

@@ -140,8 +140,7 @@ namespace BansheeEditor
             inspectorResource.panel = inspectorLayout.AddPanel();
 
             inspectorResource.inspector = InspectorUtility.GetInspector(activeResource.GetType());
-            inspectorResource.inspector.Initialize(this, inspectorResource.panel, activeResource);
-            inspectorResource.inspector.Refresh();
+            inspectorResource.inspector.Initialize(inspectorResource.panel, activeResource);
 
             inspectorLayout.AddFlexibleSpace();
         }
@@ -191,8 +190,7 @@ namespace BansheeEditor
 
                 data.panel = inspectorLayout.AddPanel();
                 data.inspector = InspectorUtility.GetInspector(allComponents[i].GetType());
-                data.inspector.Initialize(this, data.panel, allComponents[i]);
-                data.inspector.SetVisible(true);
+                data.inspector.Initialize(data.panel, allComponents[i]);
                 data.foldout.Value = true;
 
                 Type curComponentType = allComponents[i].GetType();
@@ -200,8 +198,6 @@ namespace BansheeEditor
                 data.removeBtn.OnClick += () => OnComponentRemoveClicked(curComponentType);
 
                 inspectorComponents.Add(data);
-
-                inspectorComponents[i].inspector.Refresh();
             }
 
             inspectorLayout.AddFlexibleSpace();
@@ -417,9 +413,7 @@ namespace BansheeEditor
                     RefreshSceneObjectFields(false);
 
                     for (int i = 0; i < inspectorComponents.Count; i++)
-                    {
                         inspectorComponents[i].inspector.Refresh();
-                    }
                 }
             }
             else if (currentType == InspectorType.Resource)

+ 95 - 95
MBansheeEditor/Inspectors/CameraInspector.cs

@@ -9,7 +9,6 @@ namespace BansheeEditor
     [CustomInspector(typeof(Camera))]
     public class CameraInspector : Inspector
     {
-        private bool isInitialized;
         private GUIEnumField projectionTypeField = new GUIEnumField(typeof(ProjectionType), new LocEdString("Projection type"));
         private GUISliderField fieldOfView = new GUISliderField(1, 360, new LocEdString("Field of view"));
         private GUIFloatField orthoHeight = new GUIFloatField(new LocEdString("Orthographic height"));
@@ -29,105 +28,15 @@ namespace BansheeEditor
 
         private ulong layersValue = 0;
 
-        /// <summary>
-        /// Initializes required data the first time <see cref="Refresh"/> is called.
-        /// </summary>
-        private void Initialize()
-        {
-            if (referencedObject != null)
-            {
-                Camera camera = (Camera) referencedObject;
-
-                projectionTypeField.OnSelectionChanged += x =>
-                {
-                    camera.ProjectionType = (ProjectionType)x;
-                    ToggleTypeSpecificFields((ProjectionType) x);
-                };
-
-                fieldOfView.OnChanged += x => camera.FieldOfView = x;
-                orthoHeight.OnChanged += x => camera.OrthoHeight = x;
-                aspectField.OnChanged += x => camera.AspectRatio = x;
-                nearPlaneField.OnChanged += x => camera.NearClipPlane = x;
-                farPlaneField.OnChanged += x => camera.FarClipPlane = x;
-                viewportXField.OnChanged += x => 
-                    { Rect2 rect = camera.ViewportRect; rect.x = x; camera.ViewportRect = rect; };
-                viewportYField.OnChanged += x => 
-                    { Rect2 rect = camera.ViewportRect; rect.y = x; camera.ViewportRect = rect; };
-                viewportWidthField.OnChanged += x => 
-                    { Rect2 rect = camera.ViewportRect; rect.width = x; camera.ViewportRect = rect; };
-                viewportHeightField.OnChanged += x => 
-                    { Rect2 rect = camera.ViewportRect; rect.height = x; camera.ViewportRect = rect; };
-                clearFlagsFields.OnSelectionChanged += x => camera.ClearFlags = (ClearFlags)x;
-                clearStencilField.OnChanged += x => camera.ClearStencil = (ushort)x;
-                clearDepthField.OnChanged += x => camera.ClearDepth = x;
-                clearColorField.OnChanged += x => camera.ClearColor = x;
-                priorityField.OnChanged += x => camera.Priority = x;
-                layersField.OnSelectionChanged += x =>
-                {
-                    ulong layers = 0;
-                    bool[] states = layersField.States;
-                    for (int i = 0; i < states.Length; i++)
-                        layers |= states[i] ? Layers.Values[i] : 0;
-
-                    layersValue = layers;
-                    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();
-                viewportTopLayout.AddElement(new GUILabel(new LocEdString("Viewport"), GUIOption.FixedWidth(100)));
-                GUILayoutY viewportContentLayout = viewportTopLayout.AddLayoutY();
-
-                GUILayoutX viewportTopRow = viewportContentLayout.AddLayoutX();
-                viewportTopRow.AddElement(viewportXField);
-                viewportTopRow.AddElement(viewportWidthField);
-
-                GUILayoutX viewportBotRow = viewportContentLayout.AddLayoutX();
-                viewportBotRow.AddElement(viewportYField);
-                viewportBotRow.AddElement(viewportHeightField);
-
-                layout.AddElement(clearFlagsFields);
-                layout.AddElement(clearColorField);
-                layout.AddElement(clearDepthField);
-                layout.AddElement(clearStencilField);
-                layout.AddElement(priorityField);
-                layout.AddElement(layersField);
-
-                ToggleTypeSpecificFields(camera.ProjectionType);
-            }
-
-            isInitialized = true;
-        }
-
-        /// <summary>
-        /// Enables or disables different GUI elements depending on the projection type.
-        /// </summary>
-        /// <param name="type">Projection type to show GUI elements for.</param>
-        private void ToggleTypeSpecificFields(ProjectionType type)
+        /// <inheritdoc/>
+        protected internal override void Initialize()
         {
-            if (type == ProjectionType.Orthographic)
-            {
-                fieldOfView.Enabled = false;
-                orthoHeight.Enabled = true;
-            }
-            else
-            {
-                fieldOfView.Enabled = true;
-                orthoHeight.Enabled = false;
-            }
+            BuildGUI();
         }
 
         /// <inheritdoc/>
-        internal override bool Refresh()
+        protected internal override bool Refresh()
         {
-            if (!isInitialized)
-                Initialize();
-
             Camera camera = referencedObject as Camera;
             if (camera == null)
                 return false;
@@ -241,5 +150,96 @@ namespace BansheeEditor
 
             return anythingModified;
         }
+
+        /// <summary>
+        /// Recreates all the GUI elements used by this inspector.
+        /// </summary>
+        private void BuildGUI()
+        {
+            if (referencedObject != null)
+            {
+                Camera camera = (Camera)referencedObject;
+
+                projectionTypeField.OnSelectionChanged += x =>
+                {
+                    camera.ProjectionType = (ProjectionType)x;
+                    ToggleTypeSpecificFields((ProjectionType)x);
+                };
+
+                fieldOfView.OnChanged += x => camera.FieldOfView = x;
+                orthoHeight.OnChanged += x => camera.OrthoHeight = x;
+                aspectField.OnChanged += x => camera.AspectRatio = x;
+                nearPlaneField.OnChanged += x => camera.NearClipPlane = x;
+                farPlaneField.OnChanged += x => camera.FarClipPlane = x;
+                viewportXField.OnChanged += x =>
+                { Rect2 rect = camera.ViewportRect; rect.x = x; camera.ViewportRect = rect; };
+                viewportYField.OnChanged += x =>
+                { Rect2 rect = camera.ViewportRect; rect.y = x; camera.ViewportRect = rect; };
+                viewportWidthField.OnChanged += x =>
+                { Rect2 rect = camera.ViewportRect; rect.width = x; camera.ViewportRect = rect; };
+                viewportHeightField.OnChanged += x =>
+                { Rect2 rect = camera.ViewportRect; rect.height = x; camera.ViewportRect = rect; };
+                clearFlagsFields.OnSelectionChanged += x => camera.ClearFlags = (ClearFlags)x;
+                clearStencilField.OnChanged += x => camera.ClearStencil = (ushort)x;
+                clearDepthField.OnChanged += x => camera.ClearDepth = x;
+                clearColorField.OnChanged += x => camera.ClearColor = x;
+                priorityField.OnChanged += x => camera.Priority = x;
+                layersField.OnSelectionChanged += x =>
+                {
+                    ulong layers = 0;
+                    bool[] states = layersField.States;
+                    for (int i = 0; i < states.Length; i++)
+                        layers |= states[i] ? Layers.Values[i] : 0;
+
+                    layersValue = layers;
+                    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();
+                viewportTopLayout.AddElement(new GUILabel(new LocEdString("Viewport"), GUIOption.FixedWidth(100)));
+                GUILayoutY viewportContentLayout = viewportTopLayout.AddLayoutY();
+
+                GUILayoutX viewportTopRow = viewportContentLayout.AddLayoutX();
+                viewportTopRow.AddElement(viewportXField);
+                viewportTopRow.AddElement(viewportWidthField);
+
+                GUILayoutX viewportBotRow = viewportContentLayout.AddLayoutX();
+                viewportBotRow.AddElement(viewportYField);
+                viewportBotRow.AddElement(viewportHeightField);
+
+                layout.AddElement(clearFlagsFields);
+                layout.AddElement(clearColorField);
+                layout.AddElement(clearDepthField);
+                layout.AddElement(clearStencilField);
+                layout.AddElement(priorityField);
+                layout.AddElement(layersField);
+
+                ToggleTypeSpecificFields(camera.ProjectionType);
+            }
+        }
+
+        /// <summary>
+        /// Enables or disables different GUI elements depending on the projection type.
+        /// </summary>
+        /// <param name="type">Projection type to show GUI elements for.</param>
+        private void ToggleTypeSpecificFields(ProjectionType type)
+        {
+            if (type == ProjectionType.Orthographic)
+            {
+                fieldOfView.Enabled = false;
+                orthoHeight.Enabled = true;
+            }
+            else
+            {
+                fieldOfView.Enabled = true;
+                orthoHeight.Enabled = false;
+            }
+        }
     }
 }

+ 86 - 94
MBansheeEditor/Inspectors/FontInspector.cs

@@ -10,85 +10,102 @@ namespace BansheeEditor
     [CustomInspector(typeof(Font))]
     internal class FontInspector : Inspector
     {
-        private bool isInitialized;
-        private GUIArray fontSizes;
-        private GUIArray charRanges;
+        private GUIArrayField fontSizes;
+        private GUIArrayField charRanges;
         private GUIToggleField antialiasingField;
         private GUIIntField dpiField;
         private GUIButton reimportButton;
 
         private FontImportOptions importOptions;
 
-        /// <summary>
-        /// Initializes required data the first time <see cref="Refresh"/> is called.
-        /// </summary>
-        private void Initialize()
+        /// <inheritdoc/>
+        protected internal override void Initialize()
         {
             if (referencedObject != null)
             {
                 importOptions = GetImportOptions();
-
-                RebuildGUI();
+                BuildGUI();
             }
-
-            isInitialized = true;
         }
 
-        /// <summary>
-        /// Retrieves import options for the texture we're currently inspecting.
-        /// </summary>
-        /// <returns>Font import options object.</returns>
-        private FontImportOptions GetImportOptions()
+        /// <inheritdoc/>
+        protected internal override bool Refresh()
         {
-            Font font = referencedObject as Font;
-            FontImportOptions output = null;
+            FontImportOptions newImportOptions = GetImportOptions();
 
-            if (font != null)
+            bool rebuildGUI = false;
+
+            int[] newFontSizes = newImportOptions.FontSizes;
+            if (newFontSizes == null)
+                rebuildGUI |= fontSizes.Array != null;
+            else
             {
-                LibraryEntry texEntry = ProjectLibrary.GetEntry(ProjectLibrary.GetPath(font));
-                if (texEntry != null && texEntry.Type == LibraryEntryType.File)
-                {
-                    FileEntry texFileEntry = (FileEntry)texEntry;
-                    output = texFileEntry.Options as FontImportOptions;
-                }
+                if (fontSizes.Array == null)
+                    rebuildGUI = true;
+                else
+                    rebuildGUI |= newFontSizes.Length != fontSizes.Array.GetLength(0);
             }
 
-            if (output == null)
+            CharRange[] newCharRanges = newImportOptions.CharRanges;
+            if (newCharRanges == null)
+                rebuildGUI |= charRanges.Array != null;
+            else
             {
-                if (importOptions == null)
-                    output = new FontImportOptions();
+                if (charRanges.Array == null)
+                    rebuildGUI = true;
                 else
-                    output = importOptions;
+                    rebuildGUI |= newCharRanges.Length != charRanges.Array.GetLength(0);
             }
 
-            return output;
+            if (rebuildGUI)
+                BuildGUI();
+
+            bool anythingModified = fontSizes.Refresh();
+            anythingModified |= charRanges.Refresh();
+
+            if (antialiasingField.Value != newImportOptions.Antialiasing)
+            {
+                antialiasingField.Value = newImportOptions.Antialiasing;
+                anythingModified = true;
+            }
+
+            if (dpiField.Value != newImportOptions.DPI)
+            {
+                dpiField.Value = newImportOptions.DPI;
+                anythingModified = true;
+            }
+
+            if (anythingModified)
+                importOptions = newImportOptions;
+
+            return anythingModified;
         }
 
         /// <summary>
         /// Recreates all the GUI elements used by this inspector.
         /// </summary>
-        private void RebuildGUI()
+        private void BuildGUI()
         {
             layout.Clear();
 
-            fontSizes = GUIArray.Create<FontSizeArrayRow, int>(
+            fontSizes = GUIArrayField.Create<FontSizeArrayRow, int>(
                 new LocEdString("Font sizes"), importOptions.FontSizes, layout);
             fontSizes.OnChanged += x =>
             {
                 int[] newFontSizes = x as int[];
                 importOptions.FontSizes = newFontSizes;
 
-                RebuildGUI();
+                BuildGUI();
             };
 
-            charRanges = GUIArray.Create<CharRangeArrayRow, CharRange>(
+            charRanges = GUIArrayField.Create<CharRangeArrayRow, CharRange>(
                 new LocEdString("Character ranges"), importOptions.CharRanges, layout);
             charRanges.OnChanged += x =>
             {
                 CharRange[] newRanges = x as CharRange[];
                 importOptions.CharRanges = newRanges;
 
-                RebuildGUI();
+                BuildGUI();
             };
 
             antialiasingField = new GUIToggleField(new LocEdString("Antialiasing"));
@@ -107,79 +124,50 @@ namespace BansheeEditor
         }
 
         /// <summary>
-        /// Reimports the texture resource according to the currently set import options.
+        /// Retrieves import options for the texture we're currently inspecting.
         /// </summary>
-        private void TriggerReimport()
-        {
-            Texture2D texture = (Texture2D)referencedObject;
-            string resourcePath = ProjectLibrary.GetPath(texture);
-
-            ProjectLibrary.Reimport(resourcePath, importOptions, true);
-        }
-
-        /// <inheritdoc/>
-        internal override bool Refresh()
+        /// <returns>Font import options object.</returns>
+        private FontImportOptions GetImportOptions()
         {
-            if (!isInitialized)
-            {
-                Initialize();
-                isInitialized = true;
-            }
-
-            FontImportOptions newImportOptions = GetImportOptions();
-
-            bool rebuildGUI = false;
+            Font font = referencedObject as Font;
+            FontImportOptions output = null;
 
-            int[] newFontSizes = newImportOptions.FontSizes;
-            if (newFontSizes == null)
-                rebuildGUI |= fontSizes.Array != null;
-            else
+            if (font != null)
             {
-                if (fontSizes.Array == null)
-                    rebuildGUI = true;
-                else
-                    rebuildGUI |= newFontSizes.Length != fontSizes.Array.GetLength(0);
+                LibraryEntry texEntry = ProjectLibrary.GetEntry(ProjectLibrary.GetPath(font));
+                if (texEntry != null && texEntry.Type == LibraryEntryType.File)
+                {
+                    FileEntry texFileEntry = (FileEntry)texEntry;
+                    output = texFileEntry.Options as FontImportOptions;
+                }
             }
 
-            CharRange[] newCharRanges = newImportOptions.CharRanges;
-            if (newCharRanges == null)
-                rebuildGUI |= charRanges.Array != null;
-            else
+            if (output == null)
             {
-                if (charRanges.Array == null)
-                    rebuildGUI = true;
+                if (importOptions == null)
+                    output = new FontImportOptions();
                 else
-                    rebuildGUI |= newCharRanges.Length != charRanges.Array.GetLength(0);
-            }
-
-            if (rebuildGUI)
-                RebuildGUI();
-
-            bool anythingModified = fontSizes.Refresh();
-            anythingModified |= charRanges.Refresh();
-
-            if (antialiasingField.Value != newImportOptions.Antialiasing)
-            {
-                antialiasingField.Value = newImportOptions.Antialiasing;
-                anythingModified = true;
+                    output = importOptions;
             }
 
-            if (dpiField.Value != newImportOptions.DPI)
-            {
-                dpiField.Value = newImportOptions.DPI;
-                anythingModified = true;
-            }
+            return output;
+        }
 
-            if (anythingModified)
-                importOptions = newImportOptions;
+        /// <summary>
+        /// Reimports the texture resource according to the currently set import options.
+        /// </summary>
+        private void TriggerReimport()
+        {
+            Texture2D texture = (Texture2D)referencedObject;
+            string resourcePath = ProjectLibrary.GetPath(texture);
 
-            return anythingModified;
+            ProjectLibrary.Reimport(resourcePath, importOptions, true);
         }
 
         /// <summary>
         /// Row element used for displaying GUI for font size array elements.
         /// </summary>
-        public class FontSizeArrayRow : GUIListRow
+        public class FontSizeArrayRow : GUIListFieldRow
         {
             private GUIIntField sizeField;
 
@@ -196,8 +184,10 @@ namespace BansheeEditor
             }
 
             /// <inheritdoc/>
-            internal protected override bool Refresh()
+            internal protected override bool Refresh(out bool updateGUI)
             {
+                updateGUI = false;
+
                 int newValue = GetValue<int>();
                 if (sizeField.Value != newValue)
                 {
@@ -212,7 +202,7 @@ namespace BansheeEditor
         /// <summary>
         /// Row element used for displaying GUI for character range array elements.
         /// </summary>
-        public class CharRangeArrayRow : GUIListRow
+        public class CharRangeArrayRow : GUIListFieldRow
         {
             private GUIIntField rangeStartField;
             private GUIIntField rangeEndField;
@@ -246,8 +236,10 @@ namespace BansheeEditor
             }
 
             /// <inheritdoc/>
-            internal protected override bool Refresh()
+            internal protected override bool Refresh(out bool updateGUI)
             {
+                updateGUI = false;
+
                 bool anythingModified = false;
 
                 CharRange newValue = GetValue<CharRange>();

+ 30 - 37
MBansheeEditor/Inspectors/LightInspector.cs

@@ -9,7 +9,6 @@ namespace BansheeEditor
     [CustomInspector(typeof(Light))]
     public class LightInspector : Inspector
     {
-        private bool isInitialized;
         private GUIEnumField lightTypeField = new GUIEnumField(typeof(LightType), new LocEdString("Light type"));
         private GUIColorField colorField = new GUIColorField(new LocEdString("Color"));
         private GUIFloatField rangeField = new GUIFloatField(new LocEdString("Range"));
@@ -18,10 +17,8 @@ namespace BansheeEditor
         private GUISliderField spotFalloffAngleField = new GUISliderField(1, 180, new LocEdString("Spot falloff angle"));
         private GUIToggleField castShadowField = new GUIToggleField(new LocEdString("Cast shadow"));
 
-        /// <summary>
-        /// Initializes required data the first time <see cref="Refresh"/> is called.
-        /// </summary>
-        private void Initialize()
+        /// <inheritdoc/>
+        protected internal override void Initialize()
         {
             if (referencedObject != null)
             {
@@ -51,42 +48,11 @@ namespace BansheeEditor
 
                 ToggleTypeSpecificFields(light.Type);
             }
-
-            isInitialized = true;
-        }
-
-        /// <summary>
-        /// Enables or disables different GUI elements depending on the light type.
-        /// </summary>
-        /// <param name="type">Light type to show GUI elements for.</param>
-        private void ToggleTypeSpecificFields(LightType type)
-        {
-            if (type == LightType.Directional)
-            {
-                rangeField.Enabled = false;
-                spotAngleField.Enabled = false;
-                spotFalloffAngleField.Enabled = false;
-            }
-            else if (type == LightType.Point)
-            {
-                rangeField.Enabled = true;
-                spotAngleField.Enabled = false;
-                spotFalloffAngleField.Enabled = false;
-            }
-            else
-            {
-                rangeField.Enabled = true;
-                spotAngleField.Enabled = true;
-                spotFalloffAngleField.Enabled = true;
-            }
         }
 
         /// <inheritdoc/>
-        internal override bool Refresh()
+        protected internal override bool Refresh()
         {
-            if (!isInitialized)
-                Initialize();
-
             Light light = referencedObject as Light;
             if (light == null)
                 return false;
@@ -139,5 +105,32 @@ namespace BansheeEditor
 
             return anythingModified;
         }
+
+        /// <summary>
+        /// Enables or disables different GUI elements depending on the light type.
+        /// </summary>
+        /// <param name="type">Light type to show GUI elements for.</param>
+        private void ToggleTypeSpecificFields(LightType type)
+        {
+            if (type == LightType.Directional)
+            {
+                rangeField.Enabled = false;
+                spotAngleField.Enabled = false;
+                spotFalloffAngleField.Enabled = false;
+            }
+            else if (type == LightType.Point)
+            {
+                rangeField.Enabled = true;
+                spotAngleField.Enabled = false;
+                spotFalloffAngleField.Enabled = false;
+            }
+            else
+            {
+                rangeField.Enabled = true;
+                spotAngleField.Enabled = true;
+                spotFalloffAngleField.Enabled = true;
+            }
+        }
+
     }
 }

+ 34 - 30
MBansheeEditor/Inspectors/MaterialInspector.cs

@@ -6,53 +6,38 @@ namespace BansheeEditor
     /// <summary>
     /// Renders an inspector for the <see cref="Material"/> resource.
     /// </summary>
-    [CustomInspector(typeof(Material))]
+    [CustomInspector(typeof (Material))]
     internal class MaterialInspector : Inspector
     {
         private MaterialParamGUI[] guiParams;
         private GUIResourceField shaderField;
-        private bool isInitialized;
 
-        /// <summary>
-        /// Recreates GUI elements for all material parameters.
-        /// </summary>
-        /// <param name="material">Material to create parameters for</param>
-        private void RebuildParamGUI(Material material)
+        /// <inheritdoc/>
+        protected internal override void Initialize()
         {
-            if (guiParams != null)
+            Material material = referencedObject as Material;
+            if (material == null)
+                return;
+
+            shaderField = new GUIResourceField(typeof(Shader), new LocEdString("Shader"));
+            shaderField.OnChanged += (x) =>
             {
-                foreach (var param in guiParams)
-                    param.Destroy();
+                material.Shader = x as Shader;
+                RebuildParamGUI(material);
+            };
 
-                guiParams = null;
-            }
+            layout.AddElement(shaderField);
 
-            if (material != null && material.Shader != null)
-                guiParams = CreateMaterialGUI(material, layout);
+            RebuildParamGUI(material);
         }
 
         /// <inheritdoc/>
-        internal override bool Refresh()
+        protected internal override bool Refresh()
         {
             Material material = referencedObject as Material;
             if (material == null)
                 return false;
 
-            if (!isInitialized)
-            {
-                shaderField = new GUIResourceField(typeof(Shader), new LocEdString("Shader"));
-                shaderField.OnChanged += (x) =>
-                {
-                    material.Shader = x as Shader;
-                    RebuildParamGUI(material);
-                };
-
-                layout.AddElement(shaderField);
-
-                RebuildParamGUI(material);
-                isInitialized = true;
-            }
-
             bool anythingModified = false;
 
             if (material.Shader != shaderField.Value)
@@ -71,6 +56,25 @@ namespace BansheeEditor
             return anythingModified;
         }
 
+        /// <summary>
+        /// Recreates GUI elements for all material parameters.
+        /// </summary>
+        /// <param name="material">Material to create parameters for</param>
+        private void RebuildParamGUI(Material material)
+        {
+            if (guiParams != null)
+            {
+                foreach (var param in guiParams)
+                    param.Destroy();
+
+                guiParams = null;
+            }
+
+            if (material != null && material.Shader != null)
+                guiParams = CreateMaterialGUI(material, layout);
+        }
+
+
         /// <summary>
         /// Creates a set of objects in which each object represents a GUI for a material parameter.
         /// </summary>

+ 45 - 55
MBansheeEditor/Inspectors/MeshInspector.cs

@@ -9,7 +9,6 @@ namespace BansheeEditor
     [CustomInspector(typeof(Mesh))]
     internal class MeshInspector : Inspector
     {
-        private bool isInitialized;
         private GUIToggleField normalsField = new GUIToggleField(new LocEdString("Import Normals"));
         private GUIToggleField tangentsField = new GUIToggleField(new LocEdString("Import Tangents"));
         private GUIToggleField skinField = new GUIToggleField(new LocEdString("Import Skin"));
@@ -21,10 +20,8 @@ namespace BansheeEditor
 
         private MeshImportOptions importOptions;
 
-        /// <summary>
-        /// Initializes required data the first time <see cref="Refresh"/> is called.
-        /// </summary>
-        private void Initialize()
+        /// <inheritdoc/>
+        protected internal override void Initialize()
         {
             if (referencedObject != null)
             {
@@ -53,60 +50,11 @@ namespace BansheeEditor
                 reimportButtonLayout.AddFlexibleSpace();
                 reimportButtonLayout.AddElement(reimportButton);
             }
-
-            isInitialized = true;
-        }
-
-        /// <summary>
-        /// Retrieves import options for the mesh we're currently inspecting.
-        /// </summary>
-        /// <returns>Mesh import options object.</returns>
-        private MeshImportOptions GetImportOptions()
-        {
-            Mesh mesh = referencedObject as Mesh;
-            MeshImportOptions output = null;
-
-            if (mesh != null)
-            {
-                LibraryEntry meshEntry = ProjectLibrary.GetEntry(ProjectLibrary.GetPath(mesh));
-                if (meshEntry != null && meshEntry.Type == LibraryEntryType.File)
-                {
-                    FileEntry meshFileEntry = (FileEntry)meshEntry;
-                    output = meshFileEntry.Options as MeshImportOptions;
-                }
-            }
-
-            if (output == null)
-            {
-                if (importOptions == null)
-                    output = new MeshImportOptions();
-                else
-                    output = importOptions;
-            }
-
-            return output;
-        }
-
-        /// <summary>
-        /// Reimports the texture resource according to the currently set import options.
-        /// </summary>
-        private void TriggerReimport()
-        {
-            Mesh mesh = (Mesh)referencedObject;
-            string resourcePath = ProjectLibrary.GetPath(mesh);
-
-            ProjectLibrary.Reimport(resourcePath, importOptions, true);
         }
 
         /// <inheritdoc/>
-        internal override bool Refresh()
+        protected internal override bool Refresh()
         {
-            if (!isInitialized)
-            {
-                Initialize();
-                isInitialized = true;
-            }
-
             MeshImportOptions newImportOptions = GetImportOptions();
 
             bool anythingModified = false;
@@ -158,5 +106,47 @@ namespace BansheeEditor
 
             return anythingModified;
         }
+
+
+        /// <summary>
+        /// Retrieves import options for the mesh we're currently inspecting.
+        /// </summary>
+        /// <returns>Mesh import options object.</returns>
+        private MeshImportOptions GetImportOptions()
+        {
+            Mesh mesh = referencedObject as Mesh;
+            MeshImportOptions output = null;
+
+            if (mesh != null)
+            {
+                LibraryEntry meshEntry = ProjectLibrary.GetEntry(ProjectLibrary.GetPath(mesh));
+                if (meshEntry != null && meshEntry.Type == LibraryEntryType.File)
+                {
+                    FileEntry meshFileEntry = (FileEntry)meshEntry;
+                    output = meshFileEntry.Options as MeshImportOptions;
+                }
+            }
+
+            if (output == null)
+            {
+                if (importOptions == null)
+                    output = new MeshImportOptions();
+                else
+                    output = importOptions;
+            }
+
+            return output;
+        }
+
+        /// <summary>
+        /// Reimports the texture resource according to the currently set import options.
+        /// </summary>
+        private void TriggerReimport()
+        {
+            Mesh mesh = (Mesh)referencedObject;
+            string resourcePath = ProjectLibrary.GetPath(mesh);
+
+            ProjectLibrary.Reimport(resourcePath, importOptions, true);
+        }
     }
 }

+ 21 - 19
MBansheeEditor/Inspectors/PlainTextInspector.cs

@@ -13,33 +13,35 @@ namespace BansheeEditor
 
         private GUILabel textLabel = new GUILabel("", EditorStyles.MultiLineLabel, GUIOption.FixedHeight(500));
         private GUITexture textBg = new GUITexture(null, EditorStyles.ScrollAreaBg);
-        private bool isInitialized;
 
         private string shownText = "";
 
         /// <inheritdoc/>
-        internal override bool Refresh()
+        protected internal override void Initialize()
         {
             PlainText plainText = referencedObject as PlainText;
             if (plainText == null)
-                return false;
+                return;
+
+            GUIPanel textPanel = layout.AddPanel();
+            GUILayout textLayoutY = textPanel.AddLayoutY();
+            textLayoutY.AddSpace(5);
+            GUILayout textLayoutX = textLayoutY.AddLayoutX();
+            textLayoutX.AddSpace(5);
+            textLayoutX.AddElement(textLabel);
+            textLayoutX.AddSpace(5);
+            textLayoutY.AddSpace(5);
+
+            GUIPanel textBgPanel = textPanel.AddPanel(1);
+            textBgPanel.AddElement(textBg);
+        }
 
-            if (!isInitialized)
-            {
-                GUIPanel textPanel = layout.AddPanel();
-                GUILayout textLayoutY = textPanel.AddLayoutY();
-                textLayoutY.AddSpace(5);
-                GUILayout textLayoutX = textLayoutY.AddLayoutX();
-                textLayoutX.AddSpace(5);
-                textLayoutX.AddElement(textLabel);
-                textLayoutX.AddSpace(5);
-                textLayoutY.AddSpace(5);
-
-                GUIPanel textBgPanel = textPanel.AddPanel(1);
-                textBgPanel.AddElement(textBg);
-
-                isInitialized = true;
-            }
+        /// <inheritdoc/>
+        protected internal override bool Refresh()
+        {
+            PlainText plainText = referencedObject as PlainText;
+            if (plainText == null)
+                return false;
 
             bool anythingModified = false;
 

+ 6 - 13
MBansheeEditor/Inspectors/PrefabInspector.cs

@@ -9,22 +9,15 @@ namespace BansheeEditor
     [CustomInspector(typeof(Prefab))]
     internal class PrefabInspector : Inspector
     {
-        private bool isInitialized;
-
         /// <inheritdoc/>
-        internal override bool Refresh()
+        protected internal override void Initialize()
         {
-            Prefab prefab = referencedObject as Prefab;
-            if (prefab == null)
-                return false;
-
-            if (!isInitialized)
-            {
-                // No GUI for prefab resource
-
-                isInitialized = true;
-            }
+            // No GUI for prefab resource
+        }
 
+        /// <inheritdoc/>
+        protected internal override bool Refresh()
+        {
             return false;
         }
     }

+ 69 - 68
MBansheeEditor/Inspectors/RenderableInspector.cs

@@ -7,89 +7,30 @@ namespace BansheeEditor
     /// <summary>
     /// Renders an inspector for the <see cref="Renderable"/> component.
     /// </summary>
-    [CustomInspector(typeof(Renderable))]
+    [CustomInspector(typeof (Renderable))]
     internal class RenderableInspector : Inspector
     {
         private GUIResourceField meshField;
         private GUIListBoxField layersField;
-        private GUIArray materialsField;
+        private GUIArrayField materialsField;
         private List<MaterialParamGUI[]> materialParams = new List<MaterialParamGUI[]>();
-        private bool isInitialized;
 
         private ulong layersValue = 0;
         private Material[] materials;
 
-        /// <summary>
-        /// Recreates all the GUI elements used by this inspector.
-        /// </summary>
-        private void RebuildGUI()
+        /// <inheritdoc/>
+        protected internal override void Initialize()
         {
-            layout.Clear();
-
-            Renderable renderable = referencedObject 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);
-
-            layersValue = 0;
-            materials = renderable.Materials;
-            materialsField = GUIArray.Create<MaterialArrayRow, Material>(new LocEdString("Materials"), materials, layout);
-
-            materialsField.OnChanged += x =>
-            {
-                renderable.Materials = (Material[]) x;
-                RebuildGUI();
-            };
-            meshField.OnChanged += x => renderable.Mesh = x as Mesh;
-            layersField.OnSelectionChanged += x =>
-            {
-                ulong layers = 0;
-                bool[] states = layersField.States;
-                for (int i = 0; i < states.Length; i++)
-                    layers |= states[i] ? Layers.Values[i] : 0;
-
-                layersValue = layers;
-                renderable.Layers = layers;
-            };
-
-            materialParams.Clear();
-            if (materials != null)
-            {
-                for (int i = 0; i < materials.Length; i++)
-                {
-                    if (materials[i] == null)
-                    {
-                        materialParams.Add(new MaterialParamGUI[0]);
-                        continue;
-                    }
-
-                    layout.AddSpace(10);
-
-                    MaterialParamGUI[] matParams = MaterialInspector.CreateMaterialGUI(materials[i], layout);
-                    materialParams.Add(matParams);
-                }
-            }
+            BuildGUI();
         }
 
         /// <inheritdoc/>
-        internal override bool Refresh()
+        protected internal override bool Refresh()
         {
             Renderable renderable = referencedObject as Renderable;
             if (renderable == null)
                 return false;
 
-            if (!isInitialized)
-            {
-                RebuildGUI();
-
-                isInitialized = true;
-            }
-
             bool rebuildGUI = false;
 
             Material[] newMaterials = renderable.Materials;
@@ -118,7 +59,7 @@ namespace BansheeEditor
             }
 
             if (rebuildGUI)
-                RebuildGUI();
+                BuildGUI();
 
             bool anythingModified = materialsField.Refresh();
 
@@ -155,10 +96,67 @@ namespace BansheeEditor
             return anythingModified;
         }
 
+        /// <summary>
+        /// Recreates all the GUI elements used by this inspector.
+        /// </summary>
+        private void BuildGUI()
+        {
+            layout.Clear();
+
+            Renderable renderable = referencedObject 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);
+
+            layersValue = 0;
+            materials = renderable.Materials;
+            materialsField = GUIArrayField.Create<MaterialArrayRow, Material>(new LocEdString("Materials"), materials, layout);
+
+            materialsField.OnChanged += x =>
+            {
+                renderable.Materials = (Material[])x;
+                BuildGUI();
+            };
+            meshField.OnChanged += x => renderable.Mesh = x as Mesh;
+            layersField.OnSelectionChanged += x =>
+            {
+                ulong layers = 0;
+                bool[] states = layersField.States;
+                for (int i = 0; i < states.Length; i++)
+                    layers |= states[i] ? Layers.Values[i] : 0;
+
+                layersValue = layers;
+                renderable.Layers = layers;
+            };
+
+            materialParams.Clear();
+            if (materials != null)
+            {
+                for (int i = 0; i < materials.Length; i++)
+                {
+                    if (materials[i] == null)
+                    {
+                        materialParams.Add(new MaterialParamGUI[0]);
+                        continue;
+                    }
+
+                    layout.AddSpace(10);
+
+                    MaterialParamGUI[] matParams = MaterialInspector.CreateMaterialGUI(materials[i], layout);
+                    materialParams.Add(matParams);
+                }
+            }
+        }
+
         /// <summary>
         /// Row element used for displaying GUI for material array elements.
         /// </summary>
-        public class MaterialArrayRow : GUIListRow
+        public class MaterialArrayRow : GUIListFieldRow
         {
             private GUIResourceField materialField;
 
@@ -175,12 +173,15 @@ namespace BansheeEditor
             }
 
             /// <inheritdoc/>
-            internal protected override bool Refresh()
+            internal protected override bool Refresh(out bool updateGUI)
             {
+                updateGUI = false;
+
                 Material newValue = GetValue<Material>();
                 if (materialField.Value != newValue)
                 {
                     materialField.Value = newValue;
+
                     return true;
                 }
 

+ 24 - 22
MBansheeEditor/Inspectors/ScriptCodeInspector.cs

@@ -14,41 +14,43 @@ namespace BansheeEditor
         private GUILabel textLabel = new GUILabel("", EditorStyles.MultiLineLabel, GUIOption.FixedHeight(500));
         private GUITexture textBg = new GUITexture(null, EditorStyles.ScrollAreaBg);
         private GUIToggleField isEditorField = new GUIToggleField(new LocEdString("Is editor script"));
-        private bool isInitialized;
 
         private string shownText = "";
 
         /// <inheritdoc/>
-        internal override bool Refresh()
+        protected internal override void Initialize()
         {
             ScriptCode scriptCode = referencedObject as ScriptCode;
             if (scriptCode == null)
-                return false;
+                return;
 
-            if (!isInitialized)
+            isEditorField.OnChanged += x =>
             {
-                isEditorField.OnChanged += x =>
-                {
-                    scriptCode.EditorScript = x;
-                    EditorApplication.SetDirty(scriptCode);
-                };
+                scriptCode.EditorScript = x;
+                EditorApplication.SetDirty(scriptCode);
+            };
 
-                GUIPanel textPanel = layout.AddPanel();
-                GUILayout textLayoutY = textPanel.AddLayoutY();
-                textLayoutY.AddSpace(5);
-                GUILayout textLayoutX = textLayoutY.AddLayoutX();
-                textLayoutX.AddSpace(5);
-                textLayoutX.AddElement(textLabel);
-                textLayoutX.AddSpace(5);
-                textLayoutY.AddSpace(5);
+            GUIPanel textPanel = layout.AddPanel();
+            GUILayout textLayoutY = textPanel.AddLayoutY();
+            textLayoutY.AddSpace(5);
+            GUILayout textLayoutX = textLayoutY.AddLayoutX();
+            textLayoutX.AddSpace(5);
+            textLayoutX.AddElement(textLabel);
+            textLayoutX.AddSpace(5);
+            textLayoutY.AddSpace(5);
 
-                GUIPanel textBgPanel = textPanel.AddPanel(1);
-                textBgPanel.AddElement(textBg);
+            GUIPanel textBgPanel = textPanel.AddPanel(1);
+            textBgPanel.AddElement(textBg);
 
-                layout.AddElement(isEditorField);
+            layout.AddElement(isEditorField);
+        }
 
-                isInitialized = true;
-            }
+        /// <inheritdoc/>
+        protected internal override bool Refresh()
+        {
+            ScriptCode scriptCode = referencedObject as ScriptCode;
+            if (scriptCode == null)
+                return false;
 
             bool anythingModified = false;
 

+ 26 - 24
MBansheeEditor/Inspectors/SpriteTextureInspector.cs

@@ -12,41 +12,43 @@ namespace BansheeEditor
         private GUITextureField textureField = new GUITextureField(new LocEdString("Texture"));
         private GUIVector2Field offsetField = new GUIVector2Field(new LocEdString("Offset"));
         private GUIVector2Field scaleField = new GUIVector2Field(new LocEdString("Scale"));
-        private bool isInitialized;
 
         /// <inheritdoc/>
-        internal override bool Refresh()
+        protected internal override void Initialize()
         {
             SpriteTexture spriteTexture = referencedObject as SpriteTexture;
             if (spriteTexture == null)
-                return false;
+                return;
 
-            if (!isInitialized)
+            textureField.OnChanged += (x) =>
             {
-                textureField.OnChanged += (x) =>
-                {
-                    spriteTexture.Texture = x as Texture2D;
-                    EditorApplication.SetDirty(spriteTexture);
-                };
+                spriteTexture.Texture = x as Texture2D;
+                EditorApplication.SetDirty(spriteTexture);
+            };
 
-                offsetField.OnChanged += (x) =>
-                {
-                    spriteTexture.Offset = x;
-                    EditorApplication.SetDirty(spriteTexture);
-                };
+            offsetField.OnChanged += (x) =>
+            {
+                spriteTexture.Offset = x;
+                EditorApplication.SetDirty(spriteTexture);
+            };
 
-                scaleField.OnChanged += (x) =>
-                {
-                    spriteTexture.Scale = x;
-                    EditorApplication.SetDirty(spriteTexture);
-                };
+            scaleField.OnChanged += (x) =>
+            {
+                spriteTexture.Scale = x;
+                EditorApplication.SetDirty(spriteTexture);
+            };
 
-                layout.AddElement(textureField);
-                layout.AddElement(offsetField);
-                layout.AddElement(scaleField);
+            layout.AddElement(textureField);
+            layout.AddElement(offsetField);
+            layout.AddElement(scaleField);
+        }
 
-                isInitialized = true;
-            }
+        /// <inheritdoc/>
+        protected internal override bool Refresh()
+        {
+            SpriteTexture spriteTexture = referencedObject as SpriteTexture;
+            if (spriteTexture == null)
+                return false;
 
             bool anythingModified = false;
 

+ 44 - 55
MBansheeEditor/Inspectors/Texture2DInspector.cs

@@ -9,7 +9,6 @@ namespace BansheeEditor
     [CustomInspector(typeof(Texture2D))]
     internal class Texture2DInspector : Inspector
     {
-        private bool isInitialized;
         private GUIEnumField formatField = new GUIEnumField(typeof(PixelFormat), new LocEdString("Format"));
         private GUIToggleField generateMipsField = new GUIToggleField(new LocEdString("Generate mipmaps"));
         private GUIIntField maximumMipsField = new GUIIntField(new LocEdString("Maximum mipmap level"));
@@ -19,10 +18,8 @@ namespace BansheeEditor
 
         private TextureImportOptions importOptions;
 
-        /// <summary>
-        /// Initializes required data the first time <see cref="Refresh"/> is called.
-        /// </summary>
-        private void Initialize()
+        /// <inheritdoc/>
+        protected internal override void Initialize()
         {
             if (referencedObject != null)
             {
@@ -47,60 +44,11 @@ namespace BansheeEditor
                 reimportButtonLayout.AddFlexibleSpace();
                 reimportButtonLayout.AddElement(reimportButton);
             }
-
-            isInitialized = true;
-        }
-
-        /// <summary>
-        /// Retrieves import options for the texture we're currently inspecting.
-        /// </summary>
-        /// <returns>Texture import options object.</returns>
-        private TextureImportOptions GetImportOptions()
-        {
-            Texture2D texture = referencedObject as Texture2D;
-            TextureImportOptions output = null;
-
-            if (texture != null)
-            {
-                LibraryEntry texEntry = ProjectLibrary.GetEntry(ProjectLibrary.GetPath(texture));
-                if (texEntry != null && texEntry.Type == LibraryEntryType.File)
-                {
-                    FileEntry texFileEntry = (FileEntry) texEntry;
-                    output = texFileEntry.Options as TextureImportOptions;
-                }
-            }
-
-            if (output == null)
-            {
-                if (importOptions == null)
-                    output = new TextureImportOptions();
-                else
-                    output = importOptions;
-            }
-
-            return output;
-        }
-
-        /// <summary>
-        /// Reimports the texture resource according to the currently set import options.
-        /// </summary>
-        private void TriggerReimport()
-        {
-            Texture2D texture = (Texture2D)referencedObject;
-            string resourcePath = ProjectLibrary.GetPath(texture);
-
-            ProjectLibrary.Reimport(resourcePath, importOptions, true);
         }
 
         /// <inheritdoc/>
-        internal override bool Refresh()
+        protected internal override bool Refresh()
         {
-            if (!isInitialized)
-            {
-                Initialize();
-                isInitialized = true;
-            }
-
             TextureImportOptions newImportOptions = GetImportOptions();
 
             bool anythingModified = false;
@@ -140,5 +88,46 @@ namespace BansheeEditor
 
             return anythingModified;
         }
+
+        /// <summary>
+        /// Retrieves import options for the texture we're currently inspecting.
+        /// </summary>
+        /// <returns>Texture import options object.</returns>
+        private TextureImportOptions GetImportOptions()
+        {
+            Texture2D texture = referencedObject as Texture2D;
+            TextureImportOptions output = null;
+
+            if (texture != null)
+            {
+                LibraryEntry texEntry = ProjectLibrary.GetEntry(ProjectLibrary.GetPath(texture));
+                if (texEntry != null && texEntry.Type == LibraryEntryType.File)
+                {
+                    FileEntry texFileEntry = (FileEntry)texEntry;
+                    output = texFileEntry.Options as TextureImportOptions;
+                }
+            }
+
+            if (output == null)
+            {
+                if (importOptions == null)
+                    output = new TextureImportOptions();
+                else
+                    output = importOptions;
+            }
+
+            return output;
+        }
+
+        /// <summary>
+        /// Reimports the texture resource according to the currently set import options.
+        /// </summary>
+        private void TriggerReimport()
+        {
+            Texture2D texture = (Texture2D)referencedObject;
+            string resourcePath = ProjectLibrary.GetPath(texture);
+
+            ProjectLibrary.Reimport(resourcePath, importOptions, true);
+        }
     }
 }

+ 1 - 1
MBansheeEditor/MBansheeEditor.csproj

@@ -48,7 +48,7 @@
     <Compile Include="DropDownWindow.cs" />
     <Compile Include="FolderMonitor.cs" />
     <Compile Include="GameWindow.cs" />
-    <Compile Include="GUI\GUIArray.cs" />
+    <Compile Include="GUI\GUIListField.cs" />
     <Compile Include="GUI\GUIEnumField.cs" />
     <Compile Include="GUI\GUIListBoxField.cs" />
     <Compile Include="GUI\GUISceneTreeView.cs" />