Bladeren bron

Refactored InspectableArray and InspectableList so they use the common GUIListField for displaying the array GUI

BearishSun 10 jaren geleden
bovenliggende
commit
98f239d4ab

+ 125 - 101
MBansheeEditor/GUI/GUIListField.cs

@@ -15,9 +15,6 @@ namespace BansheeEditor
     {
     {
         private const int IndentAmount = 5;
         private const int IndentAmount = 5;
 
 
-        protected IList list;
-        protected Type listType;
-
         protected List<GUIListFieldRow> rows = new List<GUIListFieldRow>();
         protected List<GUIListFieldRow> rows = new List<GUIListFieldRow>();
         protected GUIIntField guiSizeField;
         protected GUIIntField guiSizeField;
         protected GUILayoutX guiChildLayout;
         protected GUILayoutX guiChildLayout;
@@ -25,11 +22,6 @@ namespace BansheeEditor
         protected GUILayoutY guiContentLayout;
         protected GUILayoutY guiContentLayout;
         protected bool isExpanded;
         protected bool isExpanded;
 
 
-        /// <summary>
-        /// Triggered when an element in the list has been changed.
-        /// </summary>
-        public Action OnValueChanged;
-
         /// <summary>
         /// <summary>
         /// Constructs a new GUI list.
         /// Constructs a new GUI list.
         /// </summary>
         /// </summary>
@@ -41,16 +33,12 @@ namespace BansheeEditor
         /// </summary>
         /// </summary>
         /// <typeparam name="T">Type of rows that are used to handle GUI for individual list elements.</typeparam>
         /// <typeparam name="T">Type of rows that are used to handle GUI for individual list elements.</typeparam>
         /// <param name="title">Label to display on the list GUI title.</param>
         /// <param name="title">Label to display on the list GUI title.</param>
-        /// <param name="list">Object containing the list data. Can be null.</param>
-        /// <param name="listType">Type of the <paramref name="list"/> parameter. Needs to be specified in case that
-        ///                        parameter is null.</param>
+        /// <param name="empty">Should the created field represent a null object.</param>
+        /// <param name="numRows">Number of rows to create GUI for. Only matters for a non-empty list.</param>
         /// <param name="layout">Layout to which to append the list GUI elements to.</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 : GUIListFieldRow, new()
+        protected void Construct<T>(LocString title, bool empty, int numRows, GUILayout layout) where T : GUIListFieldRow, new()
         {
         {
-            this.list = list;
-            this.listType = listType;
-
-            if (list == null)
+            if (empty)
             {
             {
                 guiChildLayout = null;
                 guiChildLayout = null;
                 guiContentLayout = null;
                 guiContentLayout = null;
@@ -86,9 +74,9 @@ namespace BansheeEditor
                 guiTitleLayout.AddElement(guiResizeBtn);
                 guiTitleLayout.AddElement(guiResizeBtn);
                 guiTitleLayout.AddElement(guiClearBtn);
                 guiTitleLayout.AddElement(guiClearBtn);
 
 
-                guiSizeField.Value = list.Count;
+                guiSizeField.Value = numRows;
 
 
-                if (list.Count > 0)
+                if (numRows > 0)
                 {
                 {
                     guiChildLayout = layout.AddLayoutX();
                     guiChildLayout = layout.AddLayoutX();
                     guiChildLayout.AddSpace(IndentAmount);
                     guiChildLayout.AddSpace(IndentAmount);
@@ -108,10 +96,10 @@ namespace BansheeEditor
                     GUITexture inspectorContentBg = new GUITexture(null, EditorStyles.InspectorContentBg);
                     GUITexture inspectorContentBg = new GUITexture(null, EditorStyles.InspectorContentBg);
                     backgroundPanel.AddElement(inspectorContentBg);
                     backgroundPanel.AddElement(inspectorContentBg);
 
 
-                    for (int i = 0; i < list.Count; i++)
+                    for (int i = 0; i < numRows; i++)
                     {
                     {
                         GUIListFieldRow newRow = new T();
                         GUIListFieldRow newRow = new T();
-                        newRow.Update(this, guiContentLayout, i);
+                        newRow.BuildGUI(this, guiContentLayout, i);
 
 
                         rows.Add(newRow);
                         rows.Add(newRow);
                     }
                     }
@@ -119,6 +107,36 @@ namespace BansheeEditor
             }
             }
         }
         }
 
 
+        /// <summary>
+        /// Returns the layout that is used for positioning the elements in the title bar.
+        /// </summary>
+        /// <returns>Horizontal layout for positioning the title bar elements.</returns>
+        public GUILayoutX GetTitleLayout()
+        {
+            return guiTitleLayout;
+        }
+
+        /// <summary>
+        /// Refreshes contents of all list rows and checks if anything was modified.
+        /// </summary>
+        /// <returns>True if any entry in the list was modified, false otherwise.</returns>
+        public bool Refresh()
+        {
+            bool anythingModified = false;
+
+            for (int i = 0; i < rows.Count; i++)
+            {
+                bool updateGUI;
+
+                anythingModified |= rows[i].Refresh(out updateGUI);
+
+                if (updateGUI)
+                    rows[i].BuildGUI(this, guiContentLayout, i);
+            }
+
+            return anythingModified;
+        }
+
         /// <summary>
         /// <summary>
         /// Destroys the GUI elements.
         /// Destroys the GUI elements.
         /// </summary>
         /// </summary>
@@ -147,23 +165,14 @@ namespace BansheeEditor
         /// </summary>
         /// </summary>
         /// <param name="seqIndex">Sequential index of the element whose value to retrieve.</param>
         /// <param name="seqIndex">Sequential index of the element whose value to retrieve.</param>
         /// <returns>Value of the list element at the specified index.</returns>
         /// <returns>Value of the list element at the specified index.</returns>
-        protected internal virtual object GetValue(int seqIndex)
-        {
-            return list[seqIndex];
-        }
+        protected internal abstract object GetValue(int seqIndex);
 
 
         /// <summary>
         /// <summary>
         /// Sets a value of an element at the specified index in the list.
         /// Sets a value of an element at the specified index in the list.
         /// </summary>
         /// </summary>
         /// <param name="seqIndex">Sequential index of the element whose value to set.</param>
         /// <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>
         /// <param name="value">Value to assign to the element. Caller must ensure it is of valid type.</param>
-        protected internal virtual void SetValue(int seqIndex, object value)
-        {
-            list[seqIndex] = value;
-
-            if (OnValueChanged != null)
-                OnValueChanged();
-        }
+        protected internal abstract void SetValue(int seqIndex, object value);
 
 
         /// <summary>
         /// <summary>
         /// Triggered when the user clicks on the expand/collapse toggle in the title bar.
         /// Triggered when the user clicks on the expand/collapse toggle in the title bar.
@@ -213,38 +222,14 @@ namespace BansheeEditor
         /// list index to the one right before it, if not at zero.
         /// list index to the one right before it, if not at zero.
         /// </summary>
         /// </summary>
         /// <param name="index">Sequential index of the element in the list to move.</param>
         /// <param name="index">Sequential index of the element in the list to move.</param>
-        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();
-            }
-        }
+        protected internal abstract void OnMoveUpButtonClicked(int index);
 
 
         /// <summary>
         /// <summary>
         /// Triggered when the user clicks on the move down button next to the list entry. Moves an element from the current
         /// 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.
         /// list index to the one right after it, if the element isn't already the last element.
         /// </summary>
         /// </summary>
         /// <param name="index">Sequential index of the element in the list to move.</param>
         /// <param name="index">Sequential index of the element in the list to move.</param>
-        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();
-            }
-        }
+        protected internal abstract void OnMoveDownButtonClicked(int index);
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -259,10 +244,18 @@ namespace BansheeEditor
         /// </summary>
         /// </summary>
         public Action<Array> OnChanged;
         public Action<Array> OnChanged;
 
 
+        /// <summary>
+        /// Triggered when an element in the list has been changed.
+        /// </summary>
+        public Action OnValueChanged;
+
         /// <summary>
         /// <summary>
         /// Array object whose contents are displayed.
         /// Array object whose contents are displayed.
         /// </summary>
         /// </summary>
-        public Array Array { get { return (Array)list; } }
+        public Array Array { get { return array; } }
+
+        protected Array array;
+        protected Type arrayType;
 
 
         /// <summary>
         /// <summary>
         /// Constructs a new GUI array.
         /// Constructs a new GUI array.
@@ -282,39 +275,40 @@ namespace BansheeEditor
             where RowType : GUIListFieldRow, new() 
             where RowType : GUIListFieldRow, new() 
         {
         {
             GUIArrayField newArrayField = new GUIArrayField();
             GUIArrayField newArrayField = new GUIArrayField();
-            newArrayField.Construct<RowType>(title, array, typeof(ElementType[]), layout);
+
+            if (array != null)
+                newArrayField.Construct<RowType>(title, false, array.Length, layout);
+            else
+                newArrayField.Construct<RowType>(title, true, 0, layout);
+
+            newArrayField.arrayType = typeof (ElementType[]);
+            newArrayField.array = array;
 
 
             return newArrayField;
             return newArrayField;
         }
         }
 
 
-        /// <summary>
-        /// Refreshes contents of all array rows and checks if anything was modified.
-        /// </summary>
-        /// <returns>True if any entry in the array was modified, false otherwise.</returns>
-        public bool Refresh()
+        /// <inheritdoc/>
+        protected internal override object GetValue(int seqIndex)
         {
         {
-            bool anythingModified = false;
-
-            for (int i = 0; i < rows.Count; i++)
-            {
-                bool updateGUI;
-
-                anythingModified |= rows[i].Refresh(out updateGUI);
+            return array.GetValue(seqIndex);
+        }
 
 
-                if (updateGUI)
-                    rows[i].Update(this, guiContentLayout, i);
-            }
+        /// <inheritdoc/>
+        protected internal override void SetValue(int seqIndex, object value)
+        {
+            array.SetValue(value, seqIndex);
 
 
-            return anythingModified;
+            if (OnValueChanged != null)
+                OnValueChanged();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
         protected override void OnCreateButtonClicked()
         protected override void OnCreateButtonClicked()
         {
         {
-            list = Array.CreateInstance(listType.GetElementType(), 0);
+            array = Array.CreateInstance(arrayType.GetElementType(), 0);
 
 
             if (OnChanged != null)
             if (OnChanged != null)
-                OnChanged((Array)list);
+                OnChanged(array);
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
@@ -322,60 +316,60 @@ namespace BansheeEditor
         {
         {
             int size = guiSizeField.Value;
             int size = guiSizeField.Value;
 
 
-            Array newArray = Array.CreateInstance(listType.GetElementType(), size);
+            Array newArray = Array.CreateInstance(arrayType.GetElementType(), size);
 
 
-            int maxSize = MathEx.Min(size, list.Count);
+            int maxSize = MathEx.Min(size, array.GetLength(0));
 
 
             for (int i = 0; i < maxSize; i++)
             for (int i = 0; i < maxSize; i++)
-                newArray.SetValue(list[i], i);
+                newArray.SetValue(array.GetValue(i), i);
 
 
-            list = newArray;
+            array = newArray;
 
 
             if(OnChanged != null)
             if(OnChanged != null)
-                OnChanged((Array)list);
+                OnChanged(array);
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
         protected override void OnClearButtonClicked()
         protected override void OnClearButtonClicked()
         {
         {
-            list = null;
+            array = null;
 
 
             if (OnChanged != null)
             if (OnChanged != null)
-                OnChanged((Array)list);
+                OnChanged(array);
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
         protected internal override void OnDeleteButtonClicked(int index)
         protected internal override void OnDeleteButtonClicked(int index)
         {
         {
-            int size = MathEx.Max(0, list.Count - 1);
-            Array newArray = Array.CreateInstance(listType.GetElementType(), size);
+            int size = MathEx.Max(0, array.GetLength(0) - 1);
+            Array newArray = Array.CreateInstance(arrayType.GetElementType(), size);
 
 
             int destIdx = 0;
             int destIdx = 0;
-            for (int i = 0; i < list.Count; i++)
+            for (int i = 0; i < array.GetLength(0); i++)
             {
             {
                 if (i == index)
                 if (i == index)
                     continue;
                     continue;
 
 
-                newArray.SetValue(list[i], destIdx);
+                newArray.SetValue(array.GetValue(i), destIdx);
                 destIdx++;
                 destIdx++;
             }
             }
 
 
-            list = newArray;
+            array = newArray;
 
 
             if (OnChanged != null)
             if (OnChanged != null)
-                OnChanged((Array)list);
+                OnChanged(array);
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
         protected internal override void OnCloneButtonClicked(int index)
         protected internal override void OnCloneButtonClicked(int index)
         {
         {
-            int size = list.Count + 1;
-            Array newArray = Array.CreateInstance(listType.GetElementType(), size);
+            int size = array.GetLength(0) + 1;
+            Array newArray = Array.CreateInstance(arrayType.GetElementType(), size);
 
 
             object clonedEntry = null;
             object clonedEntry = null;
-            for (int i = 0; i < list.Count; i++)
+            for (int i = 0; i < array.GetLength(0); i++)
             {
             {
-                object value = list[i];
+                object value = array.GetValue(i);
                 newArray.SetValue(value, i);
                 newArray.SetValue(value, i);
 
 
                 if (i == index)
                 if (i == index)
@@ -402,10 +396,40 @@ namespace BansheeEditor
 
 
             newArray.SetValue(clonedEntry, size - 1);
             newArray.SetValue(clonedEntry, size - 1);
 
 
-            list = newArray;
+            array = newArray;
 
 
             if (OnChanged != null)
             if (OnChanged != null)
-                OnChanged((Array)list);
+                OnChanged(array);
+        }
+
+        /// <inheritdoc/>
+        protected internal override void OnMoveUpButtonClicked(int index)
+        {
+            if ((index - 1) >= 0)
+            {
+                object previousEntry = array.GetValue(index - 1);
+
+                array.SetValue(array.GetValue(index), index - 1);
+                array.SetValue(previousEntry, index);
+
+                if (OnValueChanged != null)
+                    OnValueChanged();
+            }
+        }
+
+        /// <inheritdoc/>
+        protected internal override void OnMoveDownButtonClicked(int index)
+        {
+            if ((index + 1) < array.GetLength(0))
+            {
+                object nextEntry = array.GetValue(index + 1);
+
+                array.SetValue(array.GetValue(index), index + 1);
+                array.SetValue(nextEntry, index);
+
+                if (OnValueChanged != null)
+                    OnValueChanged();
+            }
         }
         }
     }
     }
 
 
@@ -428,12 +452,12 @@ namespace BansheeEditor
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Recreates all row GUI elements.
+        /// (Re)creates all row GUI elements.
         /// </summary>
         /// </summary>
         /// <param name="parent">Parent array GUI object that the entry is contained in.</param>
         /// <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="parentLayout">Parent layout that row GUI elements will be added to.</param>
         /// <param name="seqIndex">Sequential index of the array entry.</param>
         /// <param name="seqIndex">Sequential index of the array entry.</param>
-        public void Update(GUIListFieldBase parent, GUILayout parentLayout, int seqIndex)
+        public void BuildGUI(GUIListFieldBase parent, GUILayout parentLayout, int seqIndex)
         {
         {
             this.parent = parent;
             this.parent = parent;
             this.seqIndex = seqIndex;
             this.seqIndex = seqIndex;
@@ -486,11 +510,11 @@ namespace BansheeEditor
         /// <summary>
         /// <summary>
         /// Refreshes the GUI for the list row and checks if anything was modified.
         /// Refreshes the GUI for the list row and checks if anything was modified.
         /// </summary>
         /// </summary>
-        /// <param name="updateGUI">Determines should the field's GUI elements be updated due to modifications.</param>
+        /// <param name="rebuildGUI">Determines should the field's GUI elements be updated due to modifications.</param>
         /// <returns>True if any modifications were made, false otherwise.</returns>
         /// <returns>True if any modifications were made, false otherwise.</returns>
-        internal protected virtual bool Refresh(out bool updateGUI)
+        internal protected virtual bool Refresh(out bool rebuildGUI)
         {
         {
-            updateGUI = false;
+            rebuildGUI = false;
             return false;
             return false;
         }
         }
 
 

+ 1 - 3
MBansheeEditor/Inspector/GenericInspector.cs

@@ -43,9 +43,7 @@ namespace BansheeEditor
             int currentIndex = 0;
             int currentIndex = 0;
             foreach (var field in inspectableFields)
             foreach (var field in inspectableFields)
             {
             {
-                bool dummy;
-
-                anythingModified |= field.Refresh(currentIndex, out dummy);
+                anythingModified |= field.Refresh(currentIndex);
                 currentIndex += field.GetNumLayoutElements();
                 currentIndex += field.GetNumLayoutElements();
             }
             }
 
 

+ 172 - 320
MBansheeEditor/Inspector/InspectableArray.cs

@@ -1,8 +1,4 @@
 using System;
 using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
 using BansheeEngine;
 using BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor
@@ -13,90 +9,9 @@ namespace BansheeEditor
     /// </summary>
     /// </summary>
     public class InspectableArray : InspectableField
     public class InspectableArray : InspectableField
     {
     {
-        /// <summary>
-        /// Contains GUI elements for a single entry in the array.
-        /// </summary>
-        private class EntryRow
-        {
-            public GUILayoutY contentLayout;
-            private GUILayoutX rowLayout;
-            private GUILayoutX titleLayout;
-            private bool ownsTitleLayout;
-
-            /// <summary>
-            /// Constructs a new entry row object.
-            /// </summary>
-            /// <param name="parentLayout">Parent layout that row GUI elements will be added to.</param>
-            public EntryRow(GUILayout parentLayout)
-            {
-                rowLayout = parentLayout.AddLayoutX();
-                contentLayout = rowLayout.AddLayoutY();
-            }
-
-            /// <summary>
-            /// Recreates all row GUI elements.
-            /// </summary>
-            /// <param name="child">Inspectable field of the array entry.</param>
-            /// <param name="seqIndex">Sequential index of the array entry.</param>
-            /// <param name="parent">Parent array object that the entry is contained in.</param>
-            public void Refresh(InspectableField child, int seqIndex, InspectableArray parent)
-            {
-                if (ownsTitleLayout || (titleLayout != null && titleLayout == child.GetTitleLayout()))
-                    return;
-
-                titleLayout = child.GetTitleLayout();
-                if (titleLayout == null)
-                {
-                    GUILayoutY buttonCenter = rowLayout.AddLayoutY();
-                    buttonCenter.AddFlexibleSpace();
-                    titleLayout = buttonCenter.AddLayoutX();
-                    buttonCenter.AddFlexibleSpace();
-
-                    ownsTitleLayout = true;
-                }
-
-                GUIContent cloneIcon = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.Clone));
-                GUIContent deleteIcon = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.Delete));
-                GUIContent moveUp = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.MoveUp));
-                GUIContent moveDown = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.MoveDown));
-
-                GUIButton cloneBtn = new GUIButton(cloneIcon, GUIOption.FixedWidth(30));
-                GUIButton deleteBtn = new GUIButton(deleteIcon, GUIOption.FixedWidth(30));
-                GUIButton moveUpBtn = new GUIButton(moveUp, GUIOption.FixedWidth(30));
-                GUIButton moveDownBtn = new GUIButton(moveDown, GUIOption.FixedWidth(30));
-
-                cloneBtn.OnClick += () => parent.OnCloneButtonClicked(seqIndex);
-                deleteBtn.OnClick += () => parent.OnDeleteButtonClicked(seqIndex);
-                moveUpBtn.OnClick += () => parent.OnMoveUpButtonClicked(seqIndex);
-                moveDownBtn.OnClick += () => parent.OnMoveDownButtonClicked(seqIndex);
-
-                titleLayout.AddElement(cloneBtn);
-                titleLayout.AddElement(deleteBtn);
-                titleLayout.AddElement(moveUpBtn);
-                titleLayout.AddElement(moveDownBtn);
-            }
-
-            /// <summary>
-            /// Destroys all row GUI elements.
-            /// </summary>
-            public void Destroy()
-            {
-                rowLayout.Destroy();
-            }
-        }
-
-        private const int IndentAmount = 5;
-
         private object propertyValue; // TODO - This will unnecessarily hold references to the object
         private object propertyValue; // TODO - This will unnecessarily hold references to the object
         private int numArrayElements;
         private int numArrayElements;
-
-        private List<EntryRow> rows = new List<EntryRow>();
-        private GUIIntField guiSizeField;
-        private GUILayoutX guiChildLayout;
-        private GUILayoutX guiTitleLayout;
-        private bool isExpanded;
-
-        private bool forceUpdate = true;
+        private InspectableArrayGUI arrayGUIField;
 
 
         /// <summary>
         /// <summary>
         /// Creates a new inspectable array GUI for the specified property.
         /// Creates a new inspectable array GUI for the specified property.
@@ -115,317 +30,254 @@ namespace BansheeEditor
         /// <inheritdoc/>
         /// <inheritdoc/>
         public override GUILayoutX GetTitleLayout()
         public override GUILayoutX GetTitleLayout()
         {
         {
-            return guiTitleLayout;
+            return arrayGUIField.GetTitleLayout();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override bool IsModified(out bool rebuildGUI)
+        public override bool IsModified()
         {
         {
-            if (forceUpdate)
-            {
-                rebuildGUI = true;
-                return true;
-            }
-
             object newPropertyValue = property.GetValue<object>();
             object newPropertyValue = property.GetValue<object>();
             if (propertyValue == null)
             if (propertyValue == null)
-            {
-                rebuildGUI = newPropertyValue != null;
-                return rebuildGUI;
-            }
+                return newPropertyValue != null;
 
 
             if (newPropertyValue == null)
             if (newPropertyValue == null)
-            {
-                rebuildGUI = propertyValue != null;
-                return rebuildGUI;
-            }
+                return propertyValue != null;
                 
                 
             SerializableArray array = property.GetArray();
             SerializableArray array = property.GetArray();
             if (array.GetLength() != numArrayElements)
             if (array.GetLength() != numArrayElements)
-            {
-                rebuildGUI = true;
                 return true;
                 return true;
-            }
-                
-            return base.IsModified(out rebuildGUI);
+
+            return base.IsModified();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        public override bool Refresh(int layoutIndex, out bool updateGUI)
+        public override bool Refresh(int layoutIndex)
         {
         {
-            bool anythingModified = false;
-
-            if (IsModified(out updateGUI))
-            {
-                Update(layoutIndex, updateGUI);
-                anythingModified = true;
-            }
-                
-            for (int i = 0; i < ChildCount; i++)
-            {
-                bool dummy;
-
-                InspectableField child = GetChild(i);
-                bool childModified = child.Refresh(0, out dummy);
-
-                if (childModified)
-                    rows[i].Refresh(child, i, this);
-
-                anythingModified |= childModified;
-            }
+            bool anythingModified = IsModified();
 
 
+            anythingModified |= arrayGUIField.Refresh();
             return anythingModified;
             return anythingModified;
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override void BuildGUI(int layoutIndex)
+        public override bool GetRebuildOnModify()
         {
         {
-            guiTitleLayout = null;
-            guiChildLayout = null;
-
-            foreach (var row in rows)
-                row.Destroy();
+            return true;
+        }
 
 
-            rows.Clear();
-            layout.DestroyElements();
+        /// <inheritdoc/>
+        protected internal override void BuildGUI(int layoutIndex)
+        {
+            GUILayout arrayLayout = layout.AddLayoutY(layoutIndex);
 
 
-            if (property.Type != SerializableProperty.FieldType.Array || property.InternalType.GetArrayRank() != 1) // We don't support multirank arrays
-                return;
+            arrayGUIField = InspectableArrayGUI.Create(title, property, arrayLayout);
+        }
 
 
+        /// <inheritdoc/>
+        protected internal override void Update(int layoutIndex)
+        {
             propertyValue = property.GetValue<object>();
             propertyValue = property.GetValue<object>();
-            if (propertyValue == null)
+            if (propertyValue != null)
             {
             {
-                guiChildLayout = null;
-                guiTitleLayout = layout.AddLayoutX(layoutIndex);
+                SerializableArray array = property.GetArray();
+                numArrayElements = array.GetLength();
+            }
+            else
+                numArrayElements = 0;
 
 
-                guiTitleLayout.AddElement(new GUILabel(title));
-                guiTitleLayout.AddElement(new GUILabel("Empty", GUIOption.FixedWidth(100)));
+            layout.DestroyElements();
+            BuildGUI(layoutIndex);
+        }
 
 
-                if (!property.IsValueType)
-                {
-                    GUIContent createIcon = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.Create));
-                    GUIButton createBtn = new GUIButton(createIcon, GUIOption.FixedWidth(30));
-                    createBtn.OnClick += OnCreateButtonClicked;
-                    guiTitleLayout.AddElement(createBtn);
-                }
+        /// <summary>
+        /// Handles creation of GUI elements for a GUI list field that displays a <see cref="SerializableArray"/> object.
+        /// </summary>
+        private class InspectableArrayGUI : GUIListFieldBase
+        {
+            private SerializableProperty property;
 
 
-                numArrayElements = 0;
-            }
-            else
+            /// <summary>
+            /// Creates a new inspectable GUI array.
+            /// </summary>
+            /// <param name="title">Label to display on the list GUI title.</param>
+            /// <param name="property">Serializable property referencing a single-dimensional array.</param>
+            /// <param name="layout">Layout to which to append the list GUI elements to.</param>
+            /// <returns>Newly created inspectable GUI array object.</returns>
+            public static InspectableArrayGUI Create(LocString title, SerializableProperty property, GUILayout layout)
             {
             {
-                GUIToggle guiFoldout = new GUIToggle(title, EditorStyles.Foldout);
-                guiFoldout.Value = isExpanded;
-                guiFoldout.OnToggled += OnFoldoutToggled;
-                guiSizeField = new GUIIntField("", GUIOption.FixedWidth(50));
-                guiSizeField.SetRange(0, int.MaxValue);
-
-                GUIContent resizeIcon = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.Resize));
-                GUIButton guiResizeBtn = new GUIButton(resizeIcon, GUIOption.FixedWidth(30));
-                guiResizeBtn.OnClick += OnResizeButtonClicked;
-
-                GUIContent clearIcon = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.Clear));
-                GUIButton guiClearBtn = new GUIButton(clearIcon, GUIOption.FixedWidth(30));
-                guiClearBtn.OnClick += OnClearButtonClicked;
-
-                guiTitleLayout = layout.AddLayoutX(layoutIndex);
-                guiTitleLayout.AddElement(guiFoldout);
-                guiTitleLayout.AddElement(guiSizeField);
-                guiTitleLayout.AddElement(guiResizeBtn);
-                guiTitleLayout.AddElement(guiClearBtn);
+                InspectableArrayGUI newArrayField = new InspectableArrayGUI();
 
 
-                SerializableArray array = property.GetArray();
-                numArrayElements = array.GetLength();
-                guiSizeField.Value = numArrayElements;
-
-                if (isExpanded)
+                object propertyValue = property.GetValue<object>();
+                if (propertyValue != null)
                 {
                 {
-                    if (numArrayElements > 0)
-                    {
-                        guiChildLayout = layout.AddLayoutX(layoutIndex);
-                        guiChildLayout.AddSpace(IndentAmount);
-
-                        GUIPanel guiContentPanel = guiChildLayout.AddPanel();
-                        GUILayoutX guiIndentLayoutX = guiContentPanel.AddLayoutX();
-                        guiIndentLayoutX.AddSpace(IndentAmount);
-                        GUILayoutY guiIndentLayoutY = guiIndentLayoutX.AddLayoutY();
-                        guiIndentLayoutY.AddSpace(IndentAmount);
-                        GUILayoutY guiContentLayout = guiIndentLayoutY.AddLayoutY();
-                        guiIndentLayoutY.AddSpace(IndentAmount);
-                        guiIndentLayoutX.AddSpace(IndentAmount);
-                        guiChildLayout.AddSpace(IndentAmount);
-
-                        short backgroundDepth = (short)(Inspector.START_BACKGROUND_DEPTH - depth - 1);
-                        string bgPanelStyle = depth % 2 == 0
-                            ? EditorStyles.InspectorContentBgAlternate
-                            : EditorStyles.InspectorContentBg;
-
-                        GUIPanel backgroundPanel = guiContentPanel.AddPanel(backgroundDepth);
-                        GUITexture inspectorContentBg = new GUITexture(null, bgPanelStyle);
-                        backgroundPanel.AddElement(inspectorContentBg);
-
-                        for (int i = 0; i < numArrayElements; i++)
-                        {
-                            EntryRow newRow = new EntryRow(guiContentLayout);
-                            rows.Add(newRow);
-
-                            InspectableField childObj = CreateInspectable(i + ".", 0, depth + 1,
-                                new InspectableFieldLayout(newRow.contentLayout), array.GetProperty(i));
-                            AddChild(childObj);
-
-                            rows[i].Refresh(childObj, i, this);
-                        }
-                    }
+                    SerializableArray array = property.GetArray();
+                    newArrayField.Construct<InspectableArrayGUIRow>(title, false, array.GetLength(), layout);
                 }
                 }
                 else
                 else
-                    guiChildLayout = null;
+                    newArrayField.Construct<InspectableArrayGUIRow>(title, true, 0, layout);
+
+                newArrayField.property = property;
+
+                return newArrayField;
             }
             }
-        }
 
 
-        /// <inheritdoc/>
-        protected override void Update(int layoutIndex, bool rebuildGUI)
-        {
-            base.Update(layoutIndex, true);
-            BuildGUI(layoutIndex);
+            /// <inheritdoc/>
+            protected internal override object GetValue(int seqIndex)
+            {
+                SerializableArray array = property.GetArray();
 
 
-            forceUpdate = false;
-            
-        }
+                return array.GetProperty(seqIndex);
+            }
 
 
-        /// <summary>
-        /// Triggered when the user clicks on the expand/collapse toggle in the title bar.
-        /// </summary>
-        /// <param name="expanded">Determines whether the contents were expanded or collapsed.</param>
-        private void OnFoldoutToggled(bool expanded)
-        {
-            isExpanded = expanded;
-            forceUpdate = true;
-        }
+            /// <inheritdoc/>
+            protected internal override void SetValue(int seqIndex, object value)
+            {
+                // Setting the value should be done through the property
+                throw new InvalidOperationException();
+            }
 
 
-        /// <summary>
-        /// Triggered when the user clicks on the resize button on the title bar. Changes the size of the array while
-        /// preserving existing contents.
-        /// </summary>
-        private void OnResizeButtonClicked()
-        {
-            int size = guiSizeField.Value; // TODO - Support multi-rank arrays
+            /// <inheritdoc/>
+            protected override void OnCreateButtonClicked()
+            {
+                property.SetValue(property.CreateArrayInstance(new int[1] { 0 }));
+            }
 
 
-            Array newArray = property.CreateArrayInstance(new int[] {size});
-            Array array = property.GetValue<Array>();
+            /// <inheritdoc/>
+            protected override void OnResizeButtonClicked()
+            {
+                int size = guiSizeField.Value; // TODO - Support multi-rank arrays
 
 
-            int maxSize = MathEx.Min(size, array.Length);
+                Array newArray = property.CreateArrayInstance(new int[] { size });
+                Array array = property.GetValue<Array>();
 
 
-            for (int i = 0; i < maxSize; i++)
-                newArray.SetValue(array.GetValue(i), i);
+                int maxSize = MathEx.Min(size, array.Length);
 
 
-            property.SetValue(newArray);
-        }
+                for (int i = 0; i < maxSize; i++)
+                    newArray.SetValue(array.GetValue(i), i);
 
 
-        /// <summary>
-        /// Triggered when the user clicks on the delete button next to the array entry. Deletes an element in the array.
-        /// </summary>
-        /// <param name="index">Sequential index of the element in the array to remove.</param>
-        private void OnDeleteButtonClicked(int index)
-        {
-            Array array = property.GetValue<Array>();
+                property.SetValue(newArray);
+            }
 
 
-            int size = MathEx.Max(0, array.Length - 1);
-            Array newArray = property.CreateArrayInstance(new int[] { size });
+            /// <inheritdoc/>
+            protected override void OnClearButtonClicked()
+            {
+                property.SetValue<object>(null);
+            }
 
 
-            int destIdx = 0;
-            for (int i = 0; i < array.Length; i++)
+            /// <inheritdoc/>
+            protected internal override void OnDeleteButtonClicked(int index)
             {
             {
-                if (i == index)
-                    continue;
+                Array array = property.GetValue<Array>();
 
 
-                newArray.SetValue(array.GetValue(i), destIdx);
-                destIdx++;
-            }
+                int size = MathEx.Max(0, array.Length - 1);
+                Array newArray = property.CreateArrayInstance(new int[] { size });
 
 
-            property.SetValue(newArray);
-        }
+                int destIdx = 0;
+                for (int i = 0; i < array.Length; i++)
+                {
+                    if (i == index)
+                        continue;
 
 
-        /// <summary>
-        /// Triggered when the user clicks on the clone button next to the array entry. Clones an element in the array and
-        /// adds the clone to the back of the array.
-        /// </summary>
-        /// <param name="index">Sequential index of the element in the array to clone.</param>
-        private void OnCloneButtonClicked(int index)
-        {
-            SerializableArray array = property.GetArray();
+                    newArray.SetValue(array.GetValue(i), destIdx);
+                    destIdx++;
+                }
 
 
-            int size = array.GetLength() + 1;
-            Array newArray = property.CreateArrayInstance(new int[] { size });
+                property.SetValue(newArray);
+            }
 
 
-            object clonedEntry = null;
-            for (int i = 0; i < array.GetLength(); i++)
+            /// <inheritdoc/>
+            protected internal override void OnCloneButtonClicked(int index)
             {
             {
-                object value = array.GetProperty(i).GetValue<object>();
+                SerializableArray array = property.GetArray();
 
 
-                newArray.SetValue(value, i);
+                int size = array.GetLength() + 1;
+                Array newArray = property.CreateArrayInstance(new int[] { size });
 
 
-                if (i == index)
+                object clonedEntry = null;
+                for (int i = 0; i < array.GetLength(); i++)
                 {
                 {
-                    clonedEntry = array.GetProperty(i).GetValueCopy<object>();
+                    object value = array.GetProperty(i).GetValue<object>();
+
+                    newArray.SetValue(value, i);
+
+                    if (i == index)
+                    {
+                        clonedEntry = array.GetProperty(i).GetValueCopy<object>();
+                    }
                 }
                 }
+
+                newArray.SetValue(clonedEntry, size - 1);
+
+                property.SetValue(newArray);
             }
             }
 
 
-            newArray.SetValue(clonedEntry, size - 1);
+            /// <inheritdoc/>
+            protected internal override void OnMoveUpButtonClicked(int index)
+            {
+                Array array = property.GetValue<Array>();
 
 
-            property.SetValue(newArray);
-        }
+                if ((index - 1) >= 0)
+                {
+                    object previousEntry = array.GetValue(index - 1);
 
 
-        /// <summary>
-        /// Triggered when the user clicks on the move up button next to the array entry. Moves an element from the current
-        /// array index to the one right before it, if not at zero.
-        /// </summary>
-        /// <param name="index">Sequential index of the element in the array to move.</param>
-        private void OnMoveUpButtonClicked(int index)
-        {
-            Array array = property.GetValue<Array>();
+                    array.SetValue(array.GetValue(index), index - 1);
+                    array.SetValue(previousEntry, index);
+                }
+            }
 
 
-            if ((index - 1) >= 0)
+            /// <inheritdoc/>
+            protected internal override void OnMoveDownButtonClicked(int index)
             {
             {
-                object previousEntry = array.GetValue(index - 1);
+                Array array = property.GetValue<Array>();
+
+                if ((index + 1) < array.Length)
+                {
+                    object nextEntry = array.GetValue(index + 1);
 
 
-                array.SetValue(array.GetValue(index), index - 1);
-                array.SetValue(previousEntry, index);
+                    array.SetValue(array.GetValue(index), index + 1);
+                    array.SetValue(nextEntry, index);
+                }
             }
             }
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Triggered when the user clicks on the move down button next to the array entry. Moves an element from the current
-        /// array index to the one right after it, if the element isn't already the last element.
+        /// Contains GUI elements for a single entry in the array.
         /// </summary>
         /// </summary>
-        /// <param name="index">Sequential index of the element in the array to move.</param>
-        private void OnMoveDownButtonClicked(int index)
+        private class InspectableArrayGUIRow : GUIListFieldRow
         {
         {
-            Array array = property.GetValue<Array>();
+            private InspectableField field;
 
 
-            if ((index + 1) < array.Length)
+            /// <inheritdoc/>
+            protected override GUILayoutX CreateGUI(GUILayoutY layout)
             {
             {
-                object nextEntry = array.GetValue(index + 1);
+                SerializableProperty property = GetValue<SerializableProperty>();
 
 
-                array.SetValue(array.GetValue(index), index + 1);
-                array.SetValue(nextEntry, index);
+                field = CreateInspectable(seqIndex + ".", 0, 0,
+                    new InspectableFieldLayout(layout), property);
+
+                return field.GetTitleLayout();
             }
             }
-        }
 
 
-        /// <summary>
-        /// Triggered when the user clicks on the create button on the title bar. Creates a brand new array with zero
-        /// elements in the place of the current array.
-        /// </summary>
-        private void OnCreateButtonClicked()
-        {
-            property.SetValue(property.CreateArrayInstance(new int[1] { 0 }));
-        }
+            /// <inheritdoc/>
+            protected internal override bool Refresh(out bool rebuildGUI)
+            {
+                if (field.IsModified())
+                {
+                    // If rebuild GUI is set to true, we will just rebuild the entire inspectable field, so no need to 
+                    // call Update on the existing one.
+                    if (!field.GetRebuildOnModify())
+                    {
+                        rebuildGUI = false;
+                        return field.Refresh(0);
+                    }
 
 
-        /// <summary>
-        /// Triggered when the user clicks on the clear button on the title bar. Deletes the current array and sets
-        /// the reference to the array in the parent object to null.
-        /// </summary>
-        private void OnClearButtonClicked()
-        {
-            property.SetValue<object>(null);
+                    rebuildGUI = true;
+                    return true;
+                }
+
+                rebuildGUI = false;
+                return field.Refresh(0);
+            }
         }
         }
     }
     }
 }
 }

+ 4 - 13
MBansheeEditor/Inspector/InspectableBool.cs

@@ -1,8 +1,4 @@
 using System;
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using BansheeEngine;
 using BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor
@@ -30,7 +26,7 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritoc/>
         /// <inheritoc/>
-        protected override void BuildGUI(int layoutIndex)
+        protected internal override void BuildGUI(int layoutIndex)
         {
         {
             if (property.Type == SerializableProperty.FieldType.Bool)
             if (property.Type == SerializableProperty.FieldType.Bool)
             {
             {
@@ -42,23 +38,18 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override bool IsModified(out bool rebuildGUI)
+        public override bool IsModified()
         {
         {
             bool newPropertyValue = property.GetValue<bool>();
             bool newPropertyValue = property.GetValue<bool>();
             if (propertyValue != newPropertyValue)
             if (propertyValue != newPropertyValue)
-            {
-                rebuildGUI = false;
                 return true;
                 return true;
-            }
                 
                 
-            return base.IsModified(out rebuildGUI);
+            return base.IsModified();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex, bool rebuildGUI)
+        protected internal override void Update(int layoutIndex)
         {
         {
-            base.Update(layoutIndex, rebuildGUI);
-
             propertyValue = property.GetValue<bool>();
             propertyValue = property.GetValue<bool>();
             if (guiField != null)
             if (guiField != null)
                 guiField.Value = propertyValue;
                 guiField.Value = propertyValue;

+ 5 - 15
MBansheeEditor/Inspector/InspectableColor.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using BansheeEngine;
+using BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor
 {
 {
@@ -31,7 +26,7 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritoc/>
         /// <inheritoc/>
-        protected override void BuildGUI(int layoutIndex)
+        protected internal override void BuildGUI(int layoutIndex)
         {
         {
             if (property.Type == SerializableProperty.FieldType.Color)
             if (property.Type == SerializableProperty.FieldType.Color)
             {
             {
@@ -43,23 +38,18 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override bool IsModified(out bool rebuildGUI)
+        public override bool IsModified()
         {
         {
             Color newPropertyValue = property.GetValue<Color>();
             Color newPropertyValue = property.GetValue<Color>();
             if (propertyValue != newPropertyValue)
             if (propertyValue != newPropertyValue)
-            {
-                rebuildGUI = false;
                 return true;
                 return true;
-            }
                 
                 
-            return base.IsModified(out rebuildGUI);
+            return base.IsModified();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex, bool rebuildGUI)
+        protected internal override void Update(int layoutIndex)
         {
         {
-            base.Update(layoutIndex, rebuildGUI);
-
             // TODO - Skip update if it currently has input focus so user can modify the value in peace
             // TODO - Skip update if it currently has input focus so user can modify the value in peace
 
 
             propertyValue = property.GetValue<Color>();
             propertyValue = property.GetValue<Color>();

+ 15 - 94
MBansheeEditor/Inspector/InspectableField.cs

@@ -1,8 +1,4 @@
 using System;
 using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
 using BansheeEngine;
 using BansheeEngine;
  
  
 namespace BansheeEditor
 namespace BansheeEditor
@@ -15,9 +11,6 @@ namespace BansheeEditor
     /// </summary>
     /// </summary>
     public abstract class InspectableField
     public abstract class InspectableField
     {
     {
-        private List<InspectableField> children = new List<InspectableField>();
-        private InspectableField parent;
-        
         protected InspectableFieldLayout layout;
         protected InspectableFieldLayout layout;
         protected SerializableProperty property;
         protected SerializableProperty property;
         protected string title;
         protected string title;
@@ -39,58 +32,22 @@ namespace BansheeEditor
             this.depth = depth;
             this.depth = depth;
         }
         }
 
 
-        /// <summary>
-        /// Registers an inspectable field as a child of this field. 
-        /// </summary>
-        /// <param name="child">Inspectable field to register as a child.</param>
-        protected void AddChild(InspectableField child)
-        {
-            if (child.parent == this)
-                return;
-
-            if (child.parent != null)
-                child.parent.RemoveChild(child);
-
-            children.Add(child);
-            child.parent = this;
-        }
-
-        /// <summary>
-        /// Unregisters an inspectable field as a child of this field. Call this when manually destroying a child field.
-        /// </summary>
-        /// <param name="child">Inspectable field to unregister.</param>
-        protected void RemoveChild(InspectableField child)
-        {
-            children.Remove(child);
-            child.parent = null;
-        }
-
         /// <summary>
         /// <summary>
         /// Checks if contents of the field have been modified, and updates them if needed.
         /// Checks if contents of the field have been modified, and updates them if needed.
         /// </summary>
         /// </summary>
         /// <param name="layoutIndex">Index in the parent's layout at which to insert the GUI elements for this field.
         /// <param name="layoutIndex">Index in the parent's layout at which to insert the GUI elements for this field.
         ///                           </param>
         ///                           </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>
         /// <returns>True if there were any modifications in this field, or any child fields.</returns>
-        public virtual bool Refresh(int layoutIndex, out bool rebuildGUI)
+        public virtual bool Refresh(int layoutIndex)
         {
         {
             bool anythingModified = false;
             bool anythingModified = false;
 
 
-            if (IsModified(out rebuildGUI))
+            if (IsModified())
             {
             {
-                Update(layoutIndex, rebuildGUI);
+                Update(layoutIndex);
                 anythingModified = true;
                 anythingModified = true;
             }
             }
                 
                 
-            int currentIndex = 0;
-            for (int i = 0; i < children.Count; i++)
-            {
-                bool dummy;
-
-                anythingModified |= children[i].Refresh(currentIndex, out dummy);
-                currentIndex += children[i].GetNumLayoutElements();
-            }
-
             return anythingModified;
             return anythingModified;
         }
         }
 
 
@@ -118,57 +75,32 @@ namespace BansheeEditor
         /// Checks have the values in the referenced serializable property have been changed compare to the value currently
         /// Checks have the values in the referenced serializable property have been changed compare to the value currently
         /// displayed in the field.
         /// displayed in the field.
         /// </summary>
         /// </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>
         /// <returns>True if the value has been modified and needs updating.</returns>
-        protected virtual bool IsModified(out bool rebuildGUI)
+        public virtual bool IsModified()
         {
         {
-            rebuildGUI = false;
             return false;
             return false;
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Reconstructs the GUI by using the most up to date values from the referenced serializable property.
+        /// Checks does the field GUI has to be rebuilt if the field is marked as modified.
         /// </summary>
         /// </summary>
-        /// <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>
-        protected virtual void Update(int layoutIndex, bool rebuildGUI)
+        /// <returns>True if field GUI has to be rebuilt if the field is marked as modified.</returns>
+        public virtual bool GetRebuildOnModify()
         {
         {
-            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++)
-            {
-                childrenCopy[i].Destroy();
-            }
-
-            children.Clear();
+            return false;
         }
         }
 
 
         /// <summary>
         /// <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.
+        /// Reconstructs the GUI by using the most up to date values from the referenced serializable property.
         /// </summary>
         /// </summary>
-        /// <param name="index">Sequential index of the field.</param>
-        /// <returns>Child inspectable field at the specified index.</returns>
-        protected InspectableField GetChild(int index)
-        {
-            return children[index];
-        }
+        /// <param name="layoutIndex">Index in the parent's layout at which to insert the GUI elements for this field.</param>
+        protected internal abstract void Update(int layoutIndex);
 
 
         /// <summary>
         /// <summary>
-        /// Number of child inspectable fields.
+        /// Initializes the GUI elements for the field.
         /// </summary>
         /// </summary>
-        protected int ChildCount
-        {
-            get { return children.Count; }
-        }
+        /// <param name="layoutIndex">Index at which to insert the GUI elements.</param>
+        protected internal abstract void BuildGUI(int layoutIndex);
 
 
         /// <summary>
         /// <summary>
         /// Destroys all GUI elements in the inspectable field.
         /// Destroys all GUI elements in the inspectable field.
@@ -176,15 +108,6 @@ namespace BansheeEditor
         public virtual void Destroy()
         public virtual void Destroy()
         {
         {
             layout.DestroyElements();
             layout.DestroyElements();
-
-            InspectableField[] childrenCopy = children.ToArray();
-            for (int i = 0; i < childrenCopy.Length; i++)
-                childrenCopy[i].Destroy();
-
-            children.Clear();
-
-            if (parent != null)
-                parent.RemoveChild(this);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -261,9 +184,7 @@ namespace BansheeEditor
                 throw new Exception("No inspector exists for the provided field type.");
                 throw new Exception("No inspector exists for the provided field type.");
 
 
             field.BuildGUI(layoutIndex);
             field.BuildGUI(layoutIndex);
-
-            bool dummy;
-            field.Refresh(layoutIndex, out dummy);
+            field.Refresh(layoutIndex);
 
 
             return field;
             return field;
         }
         }

+ 1 - 2
MBansheeEditor/Inspector/InspectableFieldLayout.cs

@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
 using BansheeEngine;
 using BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor

+ 5 - 15
MBansheeEditor/Inspector/InspectableFloat.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using BansheeEngine;
+using BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor
 {
 {
@@ -30,7 +25,7 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritoc/>
         /// <inheritoc/>
-        protected override void BuildGUI(int layoutIndex)
+        protected internal override void BuildGUI(int layoutIndex)
         {
         {
             if (property.Type == SerializableProperty.FieldType.Float)
             if (property.Type == SerializableProperty.FieldType.Float)
             {
             {
@@ -42,23 +37,18 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override bool IsModified(out bool rebuildGUI)
+        public override bool IsModified()
         {
         {
             float newPropertyValue = property.GetValue<float>();
             float newPropertyValue = property.GetValue<float>();
             if (propertyValue != newPropertyValue)
             if (propertyValue != newPropertyValue)
-            {
-                rebuildGUI = false;
                 return true;
                 return true;
-            }
                 
                 
-            return base.IsModified(out rebuildGUI);
+            return base.IsModified();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex, bool rebuildGUI)
+        protected internal override void Update(int layoutIndex)
         {
         {
-            base.Update(layoutIndex, rebuildGUI);
-
             propertyValue = property.GetValue<float>();
             propertyValue = property.GetValue<float>();
             if (guiFloatField != null)
             if (guiFloatField != null)
             {
             {

+ 5 - 15
MBansheeEditor/Inspector/InspectableGameObjectRef.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using BansheeEngine;
+using BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor
 {
 {
@@ -30,7 +25,7 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritoc/>
         /// <inheritoc/>
-        protected override void BuildGUI(int layoutIndex)
+        protected internal override void BuildGUI(int layoutIndex)
         {
         {
             if (property.Type == SerializableProperty.FieldType.GameObjectRef)
             if (property.Type == SerializableProperty.FieldType.GameObjectRef)
             {
             {
@@ -42,23 +37,18 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override bool IsModified(out bool rebuildGUI)
+        public override bool IsModified()
         {
         {
             GameObject newPropertyValue = property.GetValue<GameObject>();
             GameObject newPropertyValue = property.GetValue<GameObject>();
             if (propertyValue != newPropertyValue)
             if (propertyValue != newPropertyValue)
-            {
-                rebuildGUI = false;
                 return true;
                 return true;
-            }
                 
                 
-            return base.IsModified(out rebuildGUI);
+            return base.IsModified();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex, bool rebuildGUI)
+        protected internal override void Update(int layoutIndex)
         {
         {
-            base.Update(layoutIndex, rebuildGUI);
-
             propertyValue = property.GetValue<GameObject>();
             propertyValue = property.GetValue<GameObject>();
             if (guiField != null)
             if (guiField != null)
                 guiField.Value = propertyValue;
                 guiField.Value = propertyValue;

+ 5 - 15
MBansheeEditor/Inspector/InspectableInt.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using BansheeEngine;
+using BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor
 {
 {
@@ -30,7 +25,7 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override void BuildGUI(int layoutIndex)
+        protected internal override void BuildGUI(int layoutIndex)
         {
         {
             if (property.Type == SerializableProperty.FieldType.Int)
             if (property.Type == SerializableProperty.FieldType.Int)
             {
             {
@@ -42,23 +37,18 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override bool IsModified(out bool rebuildGUI)
+        public override bool IsModified()
         {
         {
             int newPropertyValue = property.GetValue<int>();
             int newPropertyValue = property.GetValue<int>();
             if (propertyValue != newPropertyValue)
             if (propertyValue != newPropertyValue)
-            {
-                rebuildGUI = false;
                 return true;
                 return true;
-            }
 
 
-            return base.IsModified(out rebuildGUI);
+            return base.IsModified();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex, bool rebuildGUI)
+        protected internal override void Update(int layoutIndex)
         {
         {
-            base.Update(layoutIndex, rebuildGUI);
-
             propertyValue = property.GetValue<int>();
             propertyValue = property.GetValue<int>();
             if (guiIntField != null)
             if (guiIntField != null)
             {
             {

+ 153 - 300
MBansheeEditor/Inspector/InspectableList.cs

@@ -1,8 +1,6 @@
 using System;
 using System;
 using System.Collections;
 using System.Collections;
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
 using BansheeEngine;
 using BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor
@@ -13,90 +11,9 @@ namespace BansheeEditor
     /// </summary>
     /// </summary>
     public class InspectableList : InspectableField
     public class InspectableList : InspectableField
     {
     {
-        /// <summary>
-        /// Contains GUI elements for a single entry in the list.
-        /// </summary>
-        private class EntryRow
-        {
-            public GUILayoutY contentLayout;
-            private GUILayoutX rowLayout;
-            private GUILayoutX titleLayout;
-            private bool ownsTitleLayout;
-
-            /// <summary>
-            /// Constructs a new entry row object.
-            /// </summary>
-            /// <param name="parentLayout">Parent layout that row GUI elements will be added to.</param>
-            public EntryRow(GUILayout parentLayout)
-            {
-                rowLayout = parentLayout.AddLayoutX();
-                contentLayout = rowLayout.AddLayoutY();
-            }
-
-            /// <summary>
-            /// Recreates all row GUI elements.
-            /// </summary>
-            /// <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 BuildGUI(InspectableField child, int seqIndex, InspectableList parent)
-            {
-                if (ownsTitleLayout || (titleLayout != null && titleLayout == child.GetTitleLayout()))
-                    return;
-
-                titleLayout = child.GetTitleLayout();
-                if (titleLayout == null)
-                {
-                    GUILayoutY buttonCenter = rowLayout.AddLayoutY();
-                    buttonCenter.AddFlexibleSpace();
-                    titleLayout = buttonCenter.AddLayoutX();
-                    buttonCenter.AddFlexibleSpace();
-
-                    ownsTitleLayout = true;
-                }
-
-                GUIContent cloneIcon = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.Clone));
-                GUIContent deleteIcon = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.Delete));
-                GUIContent moveUp = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.MoveUp));
-                GUIContent moveDown = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.MoveDown));
-
-                GUIButton cloneBtn = new GUIButton(cloneIcon, GUIOption.FixedWidth(30));
-                GUIButton deleteBtn = new GUIButton(deleteIcon, GUIOption.FixedWidth(30));
-                GUIButton moveUpBtn = new GUIButton(moveUp, GUIOption.FixedWidth(30));
-                GUIButton moveDownBtn = new GUIButton(moveDown, GUIOption.FixedWidth(30));
-
-                cloneBtn.OnClick += () => parent.OnCloneButtonClicked(seqIndex);
-                deleteBtn.OnClick += () => parent.OnDeleteButtonClicked(seqIndex);
-                moveUpBtn.OnClick += () => parent.OnMoveUpButtonClicked(seqIndex);
-                moveDownBtn.OnClick += () => parent.OnMoveDownButtonClicked(seqIndex);
-
-                titleLayout.AddElement(cloneBtn);
-                titleLayout.AddElement(deleteBtn);
-                titleLayout.AddElement(moveUpBtn);
-                titleLayout.AddElement(moveDownBtn);
-            }
-
-            /// <summary>
-            /// Destroys all row GUI elements.
-            /// </summary>
-            public void Destroy()
-            {
-                rowLayout.Destroy();
-            }
-        }
-
-        private const int IndentAmount = 5;
-
         private object propertyValue; // TODO - This will unnecessarily hold references to the object
         private object propertyValue; // TODO - This will unnecessarily hold references to the object
         private int numArrayElements;
         private int numArrayElements;
-
-        private GUIIntField guiSizeField;
-        private GUILayoutX guiChildLayout;
-        private GUILayoutX guiTitleLayout;
-        private List<EntryRow> rows = new List<EntryRow>();
-
-        private bool forceUpdate = true;
-        private bool isExpanded;
+        private InspectableListGUI listGUIField;
 
 
         /// <summary>
         /// <summary>
         /// Creates a new inspectable list GUI for the specified property.
         /// Creates a new inspectable list GUI for the specified property.
@@ -115,289 +32,225 @@ namespace BansheeEditor
         /// <inheritdoc/>
         /// <inheritdoc/>
         public override GUILayoutX GetTitleLayout()
         public override GUILayoutX GetTitleLayout()
         {
         {
-            return guiTitleLayout;
+            return listGUIField.GetTitleLayout();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override bool IsModified(out bool rebuildGUI)
+        public override bool IsModified()
         {
         {
-            if (forceUpdate)
-            {
-                rebuildGUI = true;
-                return true;
-            }
-                
             object newPropertyValue = property.GetValue<object>();
             object newPropertyValue = property.GetValue<object>();
             if (propertyValue == null)
             if (propertyValue == null)
-            {
-                rebuildGUI = newPropertyValue != null;
-                return rebuildGUI;
-            }
+                return newPropertyValue != null;
 
 
             if (newPropertyValue == null)
             if (newPropertyValue == null)
-            {
-                rebuildGUI = propertyValue != null;
-                return rebuildGUI;
-            }
+                return propertyValue != null;
 
 
             SerializableList list = property.GetList();
             SerializableList list = property.GetList();
             if (list.GetLength() != numArrayElements)
             if (list.GetLength() != numArrayElements)
-            {
-                rebuildGUI = true;
                 return true;
                 return true;
-            }
 
 
-            return base.IsModified(out rebuildGUI);
+            return base.IsModified();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        public override bool Refresh(int layoutIndex, out bool rebuildGUI)
+        public override bool Refresh(int layoutIndex)
         {
         {
-            bool anythingModified = false;
+            bool anythingModified = IsModified();
 
 
-            if (IsModified(out rebuildGUI))
-            {
-                Update(layoutIndex, rebuildGUI);
-                anythingModified = true;
-            }
-
-            for (int i = 0; i < ChildCount; i++)
-            {
-                InspectableField child = GetChild(i);
-
-                bool childGUIRebuilt;
-                bool childModified = child.Refresh(0, out childGUIRebuilt);
+            anythingModified |= listGUIField.Refresh();
+            return anythingModified;
+        }
 
 
-                if (childGUIRebuilt)
-                    rows[i].BuildGUI(child, i, this);
+        /// <inheritdoc/>
+        public override bool GetRebuildOnModify()
+        {
+            return true;
+        }
 
 
-                anythingModified |= childModified;
-            }
+        /// <inheritdoc/>
+        protected internal override void BuildGUI(int layoutIndex)
+        {
+            GUILayout arrayLayout = layout.AddLayoutY(layoutIndex);
 
 
-            return anythingModified;
+            listGUIField = InspectableListGUI.Create(title, property, arrayLayout);
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override void BuildGUI(int layoutIndex)
+        protected internal override void Update(int layoutIndex)
         {
         {
-            guiTitleLayout = null;
-
-            foreach (var row in rows)
-                row.Destroy();
+            propertyValue = property.GetValue<object>();
+            if (propertyValue != null)
+            {
+                SerializableList list = property.GetList();
+                numArrayElements = list.GetLength();
+            }
+            else
+                numArrayElements = 0;
 
 
-            rows.Clear();
             layout.DestroyElements();
             layout.DestroyElements();
+            BuildGUI(layoutIndex);
+        }
 
 
-            if (property.Type != SerializableProperty.FieldType.List)
-                return;
+        /// <summary>
+        /// Handles creation of GUI elements for a GUI list field that displays a <see cref="SerializableList"/> object.
+        /// </summary>
+        private class InspectableListGUI : GUIListFieldBase
+        {
+            private SerializableProperty property;
 
 
-            propertyValue = property.GetValue<object>();
-            if (propertyValue == null)
+            /// <summary>
+            /// Creates a new inspectable GUI list.
+            /// </summary>
+            /// <param name="title">Label to display on the list GUI title.</param>
+            /// <param name="property">Serializable property referencing a list.</param>
+            /// <param name="layout">Layout to which to append the list GUI elements to.</param>
+            /// <returns>Newly created inspectable GUI list object.</returns>
+            public static InspectableListGUI Create(LocString title, SerializableProperty property, GUILayout layout)
             {
             {
-                guiChildLayout = null;
-                guiTitleLayout = layout.AddLayoutX(layoutIndex);
-
-                guiTitleLayout.AddElement(new GUILabel(title));
-                guiTitleLayout.AddElement(new GUILabel("Empty", GUIOption.FixedWidth(100)));
+                InspectableListGUI newArrayField = new InspectableListGUI();
 
 
-                if (!property.IsValueType)
+                object propertyValue = property.GetValue<object>();
+                if (propertyValue != null)
                 {
                 {
-                    GUIContent createIcon = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.Create));
-                    GUIButton createBtn = new GUIButton(createIcon, GUIOption.FixedWidth(30));
-                    createBtn.OnClick += OnCreateButtonClicked;
-                    guiTitleLayout.AddElement(createBtn);
+                    SerializableList list = property.GetList();
+                    newArrayField.Construct<InspectableArrayGUIRow>(title, false, list.GetLength(), layout);
                 }
                 }
+                else
+                    newArrayField.Construct<InspectableArrayGUIRow>(title, true, 0, layout);
 
 
-                numArrayElements = 0;
+                newArrayField.property = property;
+
+                return newArrayField;
             }
             }
-            else
+
+            /// <inheritdoc/>
+            protected internal override object GetValue(int seqIndex)
             {
             {
-                GUIToggle guiFoldout = new GUIToggle(title, EditorStyles.Foldout);
-                guiFoldout.Value = isExpanded;
-                guiFoldout.OnToggled += OnFoldoutToggled;
-                guiSizeField = new GUIIntField("", GUIOption.FixedWidth(50));
-                guiSizeField.SetRange(0, int.MaxValue);
-
-                GUIContent resizeIcon = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.Resize));
-                GUIButton guiResizeBtn = new GUIButton(resizeIcon, GUIOption.FixedWidth(30));
-                guiResizeBtn.OnClick += OnResizeButtonClicked;
-
-                GUIContent clearIcon = new GUIContent(EditorBuiltin.GetInspectorWindowIcon(InspectorWindowIcon.Clear));
-                GUIButton guiClearBtn = new GUIButton(clearIcon, GUIOption.FixedWidth(30));
-                guiClearBtn.OnClick += OnClearButtonClicked;
-
-                guiTitleLayout = layout.AddLayoutX(layoutIndex);
-                guiTitleLayout.AddElement(guiFoldout);
-                guiTitleLayout.AddElement(guiSizeField);
-                guiTitleLayout.AddElement(guiResizeBtn);
-                guiTitleLayout.AddElement(guiClearBtn);
+                SerializableList array = property.GetList();
 
 
-                SerializableList list = property.GetList();
-                numArrayElements = list.GetLength();
-                guiSizeField.Value = numArrayElements;
+                return array.GetProperty(seqIndex);
+            }
 
 
-                if (isExpanded)
-                {
-                    if (numArrayElements > 0)
-                    {
-                        guiChildLayout = layout.AddLayoutX(layoutIndex);
-                        guiChildLayout.AddSpace(IndentAmount);
-
-                        GUIPanel guiContentPanel = guiChildLayout.AddPanel();
-                        GUILayoutX guiIndentLayoutX = guiContentPanel.AddLayoutX();
-                        guiIndentLayoutX.AddSpace(IndentAmount);
-                        GUILayoutY guiIndentLayoutY = guiIndentLayoutX.AddLayoutY();
-                        guiIndentLayoutY.AddSpace(IndentAmount);
-                        GUILayoutY guiContentLayout = guiIndentLayoutY.AddLayoutY();
-                        guiIndentLayoutY.AddSpace(IndentAmount);
-                        guiIndentLayoutX.AddSpace(IndentAmount);
-                        guiChildLayout.AddSpace(IndentAmount);
-
-                        short backgroundDepth = (short)(Inspector.START_BACKGROUND_DEPTH - depth - 1);
-                        string bgPanelStyle = depth % 2 == 0
-                            ? EditorStyles.InspectorContentBgAlternate
-                            : EditorStyles.InspectorContentBg;
-
-                        GUIPanel backgroundPanel = guiContentPanel.AddPanel(backgroundDepth);
-                        GUITexture inspectorContentBg = new GUITexture(null, bgPanelStyle);
-                        backgroundPanel.AddElement(inspectorContentBg);
-
-                        for (int i = 0; i < numArrayElements; i++)
-                        {
-                            EntryRow newRow = new EntryRow(guiContentLayout);
-                            rows.Add(newRow);
-
-                            InspectableField childObj = CreateInspectable(i + ".", 0, depth + 1,
-                                new InspectableFieldLayout(newRow.contentLayout), list.GetProperty(i));
-                            AddChild(childObj);
-
-                            rows[i].BuildGUI(childObj, i, this);
-                        }
-                    }
-                }
-                else
-                    guiChildLayout = null;
+            /// <inheritdoc/>
+            protected internal override void SetValue(int seqIndex, object value)
+            {
+                // Setting the value should be done through the property
+                throw new InvalidOperationException();
             }
             }
-        }
 
 
-        /// <inheritdoc/>
-        protected override void Update(int layoutIndex, bool rebuildGUI)
-        {
-            base.Update(layoutIndex, true);
-            BuildGUI(layoutIndex);
-            forceUpdate = false;
-        }
+            /// <inheritdoc/>
+            protected override void OnCreateButtonClicked()
+            {
+                property.SetValue(property.CreateListInstance(0));
+            }
 
 
-        /// <summary>
-        /// Triggered when the user clicks on the expand/collapse toggle in the title bar.
-        /// </summary>
-        /// <param name="expanded">Determines whether the contents were expanded or collapsed.</param>
-        private void OnFoldoutToggled(bool expanded)
-        {
-            isExpanded = expanded;
-            forceUpdate = true;
-        }
+            /// <inheritdoc/>
+            protected override void OnResizeButtonClicked()
+            {
+                int size = guiSizeField.Value;
 
 
-        /// <summary>
-        /// Triggered when the user clicks on the resize button on the title bar. Changes the size of the list while
-        /// preserving existing contents.
-        /// </summary>
-        private void OnResizeButtonClicked()
-        {
-            int size = guiSizeField.Value;
+                IList newList = property.CreateListInstance(size);
+                IList list = property.GetValue<IList>();
 
 
-            IList newList = property.CreateListInstance(size);
-            IList list = property.GetValue<IList>();
+                int maxSize = MathEx.Min(size, list.Count);
+                for (int i = 0; i < maxSize; i++)
+                    newList[i] = list[i];
 
 
-            int maxSize = MathEx.Min(size, list.Count);
-            for (int i = 0; i < maxSize; i++)
-                newList[i] = list[i];
+                property.SetValue(newList);
+            }
 
 
-            property.SetValue(newList);
-        }
+            /// <inheritdoc/>
+            protected override void OnClearButtonClicked()
+            {
+                property.SetValue<object>(null);
+            }
 
 
-        /// <summary>
-        /// Triggered when the user clicks on the delete button next to the list entry. Deletes an element in the list.
-        /// </summary>
-        /// <param name="index">Sequential index of the element in the list to remove.</param>
-        private void OnDeleteButtonClicked(int index)
-        {
-            IList list = property.GetValue<IList>();
+            /// <inheritdoc/>
+            protected internal override void OnDeleteButtonClicked(int index)
+            {
+                IList list = property.GetValue<IList>();
 
 
-            if (index >= 0 && index < list.Count)
-                list.RemoveAt(index);
-        }
+                if (index >= 0 && index < list.Count)
+                    list.RemoveAt(index);
+            }
 
 
-        /// <summary>
-        /// Triggered when the user clicks on the clone button next to the list entry. Clones an element in the list and
-        /// adds the clone to the back of the list.
-        /// </summary>
-        /// <param name="index">Sequential index of the element in the list to clone.</param>
-        private void OnCloneButtonClicked(int index)
-        {
-            SerializableList serializableList = property.GetList();
-            IList list = property.GetValue<IList>();
+            /// <inheritdoc/>
+            protected internal override void OnCloneButtonClicked(int index)
+            {
+                SerializableList serializableList = property.GetList();
+                IList list = property.GetValue<IList>();
 
 
-            int size = serializableList.GetLength() + 1;
+                if (index >= 0 && index < list.Count)
+                    list.Add(serializableList.GetProperty(index).GetValueCopy<object>());
+            }
 
 
-            if (index >= 0 && index < list.Count)
+            /// <inheritdoc/>
+            protected internal override void OnMoveUpButtonClicked(int index)
             {
             {
-                list.Add(serializableList.GetProperty(index).GetValueCopy<object>());
-            }
-        }
+                IList list = property.GetValue<IList>();
 
 
-        /// <summary>
-        /// Triggered when the user clicks on the move up button next to the list entry. Moves an element from the current
-        /// 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>
-        private void OnMoveUpButtonClicked(int index)
-        {
-            IList list = property.GetValue<IList>();
+                if ((index - 1) >= 0)
+                {
+                    object previousEntry = list[index - 1];
 
 
-            if ((index - 1) >= 0)
+                    list[index - 1] = list[index];
+                    list[index] = previousEntry;
+                }
+            }
+
+            /// <inheritdoc/>
+            protected internal override void OnMoveDownButtonClicked(int index)
             {
             {
-                object previousEntry = list[index - 1];
+                IList list = property.GetValue<IList>();
+
+                if ((index + 1) < list.Count)
+                {
+                    object nextEntry = list[index + 1];
 
 
-                list[index - 1] = list[index];
-                list[index] = previousEntry;
+                    list[index + 1] = list[index];
+                    list[index] = nextEntry;
+                }
             }
             }
         }
         }
 
 
         /// <summary>
         /// <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.
+        /// Contains GUI elements for a single entry in the array.
         /// </summary>
         /// </summary>
-        /// <param name="index">Sequential index of the element in the list to move.</param>
-        private void OnMoveDownButtonClicked(int index)
+        private class InspectableArrayGUIRow : GUIListFieldRow
         {
         {
-            IList list = property.GetValue<IList>();
+            private InspectableField field;
 
 
-            if ((index + 1) < list.Count)
+            /// <inheritdoc/>
+            protected override GUILayoutX CreateGUI(GUILayoutY layout)
             {
             {
-                object nextEntry = list[index + 1];
+                SerializableProperty property = GetValue<SerializableProperty>();
+
+                field = CreateInspectable(seqIndex + ".", 0, 0,
+                    new InspectableFieldLayout(layout), property);
 
 
-                list[index + 1] = list[index];
-                list[index] = nextEntry;
+                return field.GetTitleLayout();
             }
             }
-        }
 
 
-        /// <summary>
-        /// Triggered when the user clicks on the create button on the title bar. Creates a brand new list with zero
-        /// elements in the place of the current list.
-        /// </summary>
-        private void OnCreateButtonClicked()
-        {
-            property.SetValue(property.CreateListInstance(0));
-        }
+            /// <inheritdoc/>
+            protected internal override bool Refresh(out bool rebuildGUI)
+            {
+                if (field.IsModified())
+                {
+                    // If rebuild GUI is set to true, we will just rebuild the entire inspectable field, so no need to 
+                    // call Update on the existing one.
+                    if (!field.GetRebuildOnModify())
+                    {
+                        rebuildGUI = false;
+                        return field.Refresh(0);
+                    }
 
 
-        /// <summary>
-        /// Triggered when the user clicks on the clear button on the title bar. Deletes the current list and sets
-        /// the reference to the list in the parent object to null.
-        /// </summary>
-        private void OnClearButtonClicked()
-        {
-            property.SetValue<object>(null);
+                    rebuildGUI = true;
+                    return true;
+                }
+
+                rebuildGUI = false;
+                return field.Refresh(0);
+            }
         }
         }
     }
     }
 }
 }

+ 34 - 22
MBansheeEditor/Inspector/InspectableObject.cs

@@ -1,8 +1,4 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+using System.Collections.Generic;
 using BansheeEngine;
 using BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor
@@ -16,6 +12,7 @@ namespace BansheeEditor
         private const int IndentAmount = 5;
         private const int IndentAmount = 5;
 
 
         private object propertyValue;
         private object propertyValue;
+        private List<InspectableField> children = new List<InspectableField>();
 
 
         private GUILayoutX guiChildLayout;
         private GUILayoutX guiChildLayout;
         private GUILayoutX guiTitleLayout;
         private GUILayoutX guiTitleLayout;
@@ -43,32 +40,44 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override bool IsModified(out bool rebuildGUI)
+        public override bool IsModified()
         {
         {
             if (forceUpdate)
             if (forceUpdate)
-            {
-                rebuildGUI = true;
                 return true;
                 return true;
-            }
                 
                 
             object newPropertyValue = property.GetValue<object>();
             object newPropertyValue = property.GetValue<object>();
             if (propertyValue == null)
             if (propertyValue == null)
-            {
-                rebuildGUI = newPropertyValue != null;
-                return rebuildGUI;
-            }
+                return newPropertyValue != null;
 
 
             if (newPropertyValue == null)
             if (newPropertyValue == null)
+                return propertyValue != null;
+
+            return base.IsModified();
+        }
+
+        /// <inheritdoc/>
+        public override bool Refresh(int layoutIndex)
+        {
+            bool anythingModified = base.Refresh(layoutIndex);
+
+            int currentIndex = 0;
+            for (int i = 0; i < children.Count; i++)
             {
             {
-                rebuildGUI = propertyValue != null;
-                return rebuildGUI;
+                anythingModified |= children[i].Refresh(currentIndex);
+                currentIndex += children[i].GetNumLayoutElements();
             }
             }
 
 
-            return base.IsModified(out rebuildGUI);
+            return anythingModified;
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override void BuildGUI(int index)
+        public override bool GetRebuildOnModify()
+        {
+            return true;
+        }
+
+        /// <inheritdoc/>
+        protected internal override void BuildGUI(int index)
         {
         {
             guiTitleLayout = null;
             guiTitleLayout = null;
             guiChildLayout = null;
             guiChildLayout = null;
@@ -78,7 +87,6 @@ namespace BansheeEditor
             if (property.Type != SerializableProperty.FieldType.Object)
             if (property.Type != SerializableProperty.FieldType.Object)
                 return;
                 return;
 
 
-            propertyValue = property.GetValue<object>();
             if (propertyValue == null)
             if (propertyValue == null)
             {
             {
                 guiChildLayout = null;
                 guiChildLayout = null;
@@ -144,7 +152,7 @@ namespace BansheeEditor
                             InspectableField inspectable = CreateInspectable(field.Name, currentIndex, depth + 1,
                             InspectableField inspectable = CreateInspectable(field.Name, currentIndex, depth + 1,
                                 new InspectableFieldLayout(guiContentLayout), field.GetProperty());
                                 new InspectableFieldLayout(guiContentLayout), field.GetProperty());
 
 
-                            AddChild(inspectable);
+                            children.Add(inspectable);
                             currentIndex += inspectable.GetNumLayoutElements();
                             currentIndex += inspectable.GetNumLayoutElements();
                         }
                         }
                     }
                     }
@@ -155,11 +163,15 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex, bool rebuildGUI)
+        protected internal override void Update(int layoutIndex)
         {
         {
-            base.Update(layoutIndex, true);
-            BuildGUI(layoutIndex);
+            foreach (var child in children)
+                child.Destroy();
+
+            children.Clear();
 
 
+            propertyValue = property.GetValue<object>();
+            BuildGUI(layoutIndex);
             forceUpdate = false;
             forceUpdate = false;
         }
         }
 
 

+ 5 - 15
MBansheeEditor/Inspector/InspectableResourceRef.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using BansheeEngine;
+using BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor
 {
 {
@@ -30,7 +25,7 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritoc/>
         /// <inheritoc/>
-        protected override void BuildGUI(int layoutIndex)
+        protected internal override void BuildGUI(int layoutIndex)
         {
         {
             if (property.Type == SerializableProperty.FieldType.ResourceRef)
             if (property.Type == SerializableProperty.FieldType.ResourceRef)
             {
             {
@@ -42,23 +37,18 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override bool IsModified(out bool rebuildGUI)
+        public override bool IsModified()
         {
         {
             Resource newPropertyValue = property.GetValue<Resource>();
             Resource newPropertyValue = property.GetValue<Resource>();
             if (propertyValue != newPropertyValue)
             if (propertyValue != newPropertyValue)
-            {
-                rebuildGUI = false;
                 return true;
                 return true;
-            }
 
 
-            return base.IsModified(out rebuildGUI);
+            return base.IsModified();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex, bool rebuildGUI)
+        protected internal override void Update(int layoutIndex)
         {
         {
-            base.Update(layoutIndex, rebuildGUI);
-
             propertyValue = property.GetValue<Resource>();
             propertyValue = property.GetValue<Resource>();
             if (guiField != null)
             if (guiField != null)
                 guiField.Value = propertyValue;
                 guiField.Value = propertyValue;

+ 5 - 15
MBansheeEditor/Inspector/InspectableString.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using BansheeEngine;
+using BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor
 {
 {
@@ -30,7 +25,7 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritoc/>
         /// <inheritoc/>
-        protected override void BuildGUI(int layoutIndex)
+        protected internal override void BuildGUI(int layoutIndex)
         {
         {
             if (property.Type == SerializableProperty.FieldType.String)
             if (property.Type == SerializableProperty.FieldType.String)
             {
             {
@@ -42,23 +37,18 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override bool IsModified(out bool rebuildGUI)
+        public override bool IsModified()
         {
         {
             string newPropertyValue = property.GetValue<string>();
             string newPropertyValue = property.GetValue<string>();
             if (propertyValue != newPropertyValue)
             if (propertyValue != newPropertyValue)
-            {
-                rebuildGUI = false;
                 return true;
                 return true;
-            }
 
 
-            return base.IsModified(out rebuildGUI);
+            return base.IsModified();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex, bool rebuildGUI)
+        protected internal override void Update(int layoutIndex)
         {
         {
-            base.Update(layoutIndex, rebuildGUI);
-
             propertyValue = property.GetValue<string>();
             propertyValue = property.GetValue<string>();
             if (guiField != null)
             if (guiField != null)
             {
             {

+ 5 - 15
MBansheeEditor/Inspector/InspectableVector2.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using BansheeEngine;
+using BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor
 {
 {
@@ -30,7 +25,7 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritoc/>
         /// <inheritoc/>
-        protected override void BuildGUI(int layoutIndex)
+        protected internal override void BuildGUI(int layoutIndex)
         {
         {
             if (property.Type == SerializableProperty.FieldType.Vector2)
             if (property.Type == SerializableProperty.FieldType.Vector2)
             {
             {
@@ -42,23 +37,18 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override bool IsModified(out bool rebuildGUI)
+        public override bool IsModified()
         {
         {
             Vector2 newPropertyValue = property.GetValue<Vector2>();
             Vector2 newPropertyValue = property.GetValue<Vector2>();
             if (propertyValue != newPropertyValue)
             if (propertyValue != newPropertyValue)
-            {
-                rebuildGUI = false;
                 return true;
                 return true;
-            }
 
 
-            return base.IsModified(out rebuildGUI);
+            return base.IsModified();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex, bool rebuildGUI)
+        protected internal override void Update(int layoutIndex)
         {
         {
-            base.Update(layoutIndex, rebuildGUI);
-
             propertyValue = property.GetValue<Vector2>();
             propertyValue = property.GetValue<Vector2>();
             if (guiField != null)
             if (guiField != null)
             {
             {

+ 5 - 15
MBansheeEditor/Inspector/InspectableVector3.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using BansheeEngine;
+using BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor
 {
 {
@@ -30,7 +25,7 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritoc/>
         /// <inheritoc/>
-        protected override void BuildGUI(int layoutIndex)
+        protected internal override void BuildGUI(int layoutIndex)
         {
         {
             if (property.Type == SerializableProperty.FieldType.Vector3)
             if (property.Type == SerializableProperty.FieldType.Vector3)
             {
             {
@@ -42,23 +37,18 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override bool IsModified(out bool rebuildGUI)
+        public override bool IsModified()
         {
         {
             Vector3 newPropertyValue = property.GetValue<Vector3>();
             Vector3 newPropertyValue = property.GetValue<Vector3>();
             if (propertyValue != newPropertyValue)
             if (propertyValue != newPropertyValue)
-            {
-                rebuildGUI = false;
                 return true;
                 return true;
-            }
 
 
-            return base.IsModified(out rebuildGUI);
+            return base.IsModified();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex, bool rebuildGUI)
+        protected internal override void Update(int layoutIndex)
         {
         {
-            base.Update(layoutIndex, rebuildGUI);
-
             propertyValue = property.GetValue<Vector3>();
             propertyValue = property.GetValue<Vector3>();
             if (guiField != null)
             if (guiField != null)
             {
             {

+ 5 - 15
MBansheeEditor/Inspector/InspectableVector4.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using BansheeEngine;
+using BansheeEngine;
 
 
 namespace BansheeEditor
 namespace BansheeEditor
 {
 {
@@ -30,7 +25,7 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritoc/>
         /// <inheritoc/>
-        protected override void BuildGUI(int layoutIndex)
+        protected internal override void BuildGUI(int layoutIndex)
         {
         {
             if (property.Type == SerializableProperty.FieldType.Vector4)
             if (property.Type == SerializableProperty.FieldType.Vector4)
             {
             {
@@ -42,23 +37,18 @@ namespace BansheeEditor
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override bool IsModified(out bool rebuildGUI)
+        public override bool IsModified()
         {
         {
             Vector4 newPropertyValue = property.GetValue<Vector4>();
             Vector4 newPropertyValue = property.GetValue<Vector4>();
             if (propertyValue != newPropertyValue)
             if (propertyValue != newPropertyValue)
-            {
-                rebuildGUI = false;
                 return true;
                 return true;
-            }
 
 
-            return base.IsModified(out rebuildGUI);
+            return base.IsModified();
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected override void Update(int layoutIndex, bool rebuildGUI)
+        protected internal override void Update(int layoutIndex)
         {
         {
-            base.Update(layoutIndex, rebuildGUI);
-
             propertyValue = property.GetValue<Vector4>();
             propertyValue = property.GetValue<Vector4>();
             if (guiField != null)
             if (guiField != null)
             {
             {

+ 4 - 4
MBansheeEditor/Inspectors/FontInspector.cs

@@ -184,9 +184,9 @@ namespace BansheeEditor
             }
             }
 
 
             /// <inheritdoc/>
             /// <inheritdoc/>
-            internal protected override bool Refresh(out bool updateGUI)
+            internal protected override bool Refresh(out bool rebuildGUI)
             {
             {
-                updateGUI = false;
+                rebuildGUI = false;
 
 
                 int newValue = GetValue<int>();
                 int newValue = GetValue<int>();
                 if (sizeField.Value != newValue)
                 if (sizeField.Value != newValue)
@@ -236,9 +236,9 @@ namespace BansheeEditor
             }
             }
 
 
             /// <inheritdoc/>
             /// <inheritdoc/>
-            internal protected override bool Refresh(out bool updateGUI)
+            internal protected override bool Refresh(out bool rebuildGUI)
             {
             {
-                updateGUI = false;
+                rebuildGUI = false;
 
 
                 bool anythingModified = false;
                 bool anythingModified = false;
 
 

+ 2 - 2
MBansheeEditor/Inspectors/RenderableInspector.cs

@@ -173,9 +173,9 @@ namespace BansheeEditor
             }
             }
 
 
             /// <inheritdoc/>
             /// <inheritdoc/>
-            internal protected override bool Refresh(out bool updateGUI)
+            internal protected override bool Refresh(out bool rebuildGUI)
             {
             {
-                updateGUI = false;
+                rebuildGUI = false;
 
 
                 Material newValue = GetValue<Material>();
                 Material newValue = GetValue<Material>();
                 if (materialField.Value != newValue)
                 if (materialField.Value != newValue)