Просмотр исходного кода

Refactored Inspector and Inspectable objects so they are added to the layout in a more flexible way

Marko Pintera 11 лет назад
Родитель
Сommit
78eba7518c

+ 7 - 0
BansheeCore/Source/BsCoreApplication.cpp

@@ -48,10 +48,17 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+	void atExit()
+	{
+		BS_EXCEPT(InternalErrorException, "exit() called. Please shut down Banshee normally and do not use exit().");
+	}
+
 	CoreApplication::CoreApplication(START_UP_DESC& desc)
 	CoreApplication::CoreApplication(START_UP_DESC& desc)
 		:mPrimaryWindow(nullptr), mIsFrameRenderingFinished(true), mRunMainLoop(false), 
 		:mPrimaryWindow(nullptr), mIsFrameRenderingFinished(true), mRunMainLoop(false), 
 		mSceneManagerPlugin(nullptr), mRendererPlugin(nullptr)
 		mSceneManagerPlugin(nullptr), mRendererPlugin(nullptr)
 	{
 	{
+		atexit(atExit);
+
 		UINT32 numWorkerThreads = BS_THREAD_HARDWARE_CONCURRENCY - 1; // Number of cores while excluding current thread.
 		UINT32 numWorkerThreads = BS_THREAD_HARDWARE_CONCURRENCY - 1; // Number of cores while excluding current thread.
 
 
 		Platform::_startUp();
 		Platform::_startUp();

+ 2 - 2
BansheeUtility/Include/BsTestOutput.h

@@ -5,7 +5,7 @@
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	/**
 	/**
-	 * @brief	Abstract interfaced used for outputting unit test results.
+	 * @brief	Abstract interface used for outputting unit test results.
 	 */
 	 */
 	class BS_UTILITY_EXPORT TestOutput
 	class BS_UTILITY_EXPORT TestOutput
 	{
 	{
@@ -32,6 +32,6 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc	TestOutput::outputFail
 		 * @copydoc	TestOutput::outputFail
 		 */
 		 */
-		void outputFail(const String& desc, const String& function, const String& file, long line);
+		void outputFail(const String& desc, const String& function, const String& file, long line) final;
 	};
 	};
 }
 }

+ 20 - 22
Inspector.txt

@@ -1,4 +1,4 @@
-Update C# GUIElementStyle
+Update C# GUIElementStyle with sub styles
 Update GUIFoldout with sub styles
 Update GUIFoldout with sub styles
 
 
 Test if drag and dropping scene objects works with object and resource fields. Especially custom resources and components.
 Test if drag and dropping scene objects works with object and resource fields. Especially custom resources and components.
@@ -7,21 +7,21 @@ Test custom resources:
  - Can I load them? (Will likely need ProjectLIbrary::load)
  - Can I load them? (Will likely need ProjectLIbrary::load)
  - Can I reference them in Component and will the reference be held after after cloning?
  - Can I reference them in Component and will the reference be held after after cloning?
 
 
-Test CmdRecordSO.
- - Figure out how to properly restore all handles. Requirements:
-   1. Any active game object needs to replaced with the restored version
-   2. Replaced game objects must be destroyed
-   3. All handles to the object must be kept intact
-   4. All handles (internal and external) on the restored object must be kept intact
- - Create hierarchy with three layers. One SO needs to have a couple of components. One components should reference child SO,
-   other component should reference outside SO. Outside component should reference one SO in hierarchy, and one component in hierarchy.
-   Then I perform Record.
-   Modify some plain values
-   Perform undo
-   Check that number of game objects remained the same and that they all have original IDs
-   Check that all above mentioned references are still active
-
-   Repeat the similar test but this time instead of modfying plain values, modify number of components and the hierarchy.
+ARRAY
+> MyArray    [_________] [Resize]
+   1. [_________] [X] [C] [^] [¡]
+   2. [_________] [X] [C] [^] [¡]
+   3. [_________] [X] [C] [^] [¡]
+
+ARRAY TODO:
+ - Add a size field and a resize button that updates the array
+ - Add Delete/Clone/MoveUp/MoveDown buttons
+ - Ensure that case when array is null is handled properly. Will likely need a [Create] button
+ - Need a GUIFoldout that doesn't have BG and is just a single button.
+
+Inspectable Refresh/Refactor TODO:
+Parent layout element destruction should be automatic
+Child Inspectable element destruction should also probably be automatic
 
 
 TODO:
 TODO:
  - Hook up int field set/get callbacks
  - Hook up int field set/get callbacks
@@ -39,12 +39,6 @@ TODO:
  - GUIColor needs to be hooked up to a window that actually changes its value.
  - GUIColor needs to be hooked up to a window that actually changes its value.
  - I need to register UndoRedo command after user finishes modifying a field. This should be referencing an object using an URI?
  - I need to register UndoRedo command after user finishes modifying a field. This should be referencing an object using an URI?
 
 
-TO PONDER:
- - How will I create undo/redo operations for serializable fields?
-   - UndoRedo.RecordField - Saves current state of the field, before you modify it
-     - Accepts a source object and a path that allows us to follow its properties to the exact modified field
-	 - Source object will be stored by its ID (it can either be GameObject or Resource, nothing else)
-
 KEEP IN MIND:
 KEEP IN MIND:
  - Clicking on an object/resource in inspector should ping it in their window
  - Clicking on an object/resource in inspector should ping it in their window
  - Inspector needs to be organized in such a way that scroll areas work. That should be possible with GUIPanelContainer.
  - Inspector needs to be organized in such a way that scroll areas work. That should be possible with GUIPanelContainer.
@@ -83,6 +77,10 @@ KEEP IN MIND:
 
 
 
 
 
 
+
+
+
+
 
 
 
 
 
 

+ 1 - 0
MBansheeEditor/Debug_Component1.cs

@@ -9,5 +9,6 @@ namespace BansheeEngine
     {
     {
         public int value1;
         public int value1;
         public int value2;
         public int value2;
+        public int[] intArray = new int[5];
     }
     }
 }
 }

+ 5 - 3
MBansheeEditor/Inspector/GenericInspector.cs

@@ -24,9 +24,9 @@ namespace BansheeEditor
                         continue;
                         continue;
 
 
                     if (field.HasCustomInspector)
                     if (field.HasCustomInspector)
-                        inspectableFields.Add(InspectableObjectBase.CreateCustomInspectable(field.CustomInspectorType, field.Name, field.GetProperty()));
+                        inspectableFields.Add(InspectableObjectBase.CreateCustomInspectable(field.CustomInspectorType, field.Name, new InspectableFieldLayout(layout), field.GetProperty()));
                     else
                     else
-                        inspectableFields.Add(InspectableObjectBase.CreateDefaultInspectable(field.Name, field.GetProperty()));
+                        inspectableFields.Add(InspectableObjectBase.CreateDefaultInspectable(field.Name, new InspectableFieldLayout(layout), field.GetProperty()));
                 }
                 }
             }
             }
 
 
@@ -38,9 +38,11 @@ namespace BansheeEditor
             if (!isInitialized)
             if (!isInitialized)
                 Initialize();
                 Initialize();
 
 
+            int currentIndex = 0;
             foreach (var field in inspectableFields)
             foreach (var field in inspectableFields)
             {
             {
-                field.Refresh(layout);
+                field.Refresh(currentIndex);
+                currentIndex += field.GetNumLayoutElements();
             }
             }
         }
         }
 
 

+ 23 - 41
MBansheeEditor/Inspector/InspectableArray.cs

@@ -11,31 +11,31 @@ namespace BansheeEditor
     {
     {
         private const int IndentAmount = 15;
         private const int IndentAmount = 15;
 
 
-        private object oldPropertyValue;
-        private List<InspectableObjectBase> arrayElements = new List<InspectableObjectBase>();
+        private object oldPropertyValue; // TODO - This will unnecessarily hold references to the object
+        private int numArrayElements;
 
 
         private GUILabel guiLabel;
         private GUILabel guiLabel;
         private GUILayout guiChildLayout;
         private GUILayout guiChildLayout;
-        private GUILayout guiContentLayout;
+        private GUILayoutY guiContentLayout;
         private bool isInitialized;
         private bool isInitialized;
 
 
-        public InspectableArray(string title, SerializableProperty property)
-            : base(title, property)
+        public InspectableArray(string title, InspectableFieldLayout layout, SerializableProperty property)
+            : base(title, layout, property)
         {
         {
 
 
         }
         }
 
 
-        protected void Initialize(GUILayout layout)
+        private void Initialize(int layoutIndex)
         {
         {
             if (property.Type != SerializableProperty.FieldType.Array)
             if (property.Type != SerializableProperty.FieldType.Array)
                 return;
                 return;
 
 
-            guiLabel = new GUILabel(title);
-            layout.AddElement(guiLabel); // TODO - Add foldout and hook up its callbacks
+            guiLabel = new GUILabel(title); // TODO - Add foldout and hook up its callbacks
+            layout.AddElement(layoutIndex, guiLabel);
 
 
-            guiChildLayout = layout.AddLayoutX();
-            guiChildLayout.AddSpace(IndentAmount);
+            guiChildLayout = layout.AddLayoutX(layoutIndex);
 
 
+            guiChildLayout.AddSpace(IndentAmount);
             guiContentLayout = guiChildLayout.AddLayoutY();
             guiContentLayout = guiChildLayout.AddLayoutY();
 
 
             isInitialized = true;
             isInitialized = true;
@@ -43,6 +43,9 @@ namespace BansheeEditor
 
 
         protected override bool IsModified()
         protected override bool IsModified()
         {
         {
+            if (!isInitialized)
+                return true;
+
             object newPropertyValue = property.GetValue<object>();
             object newPropertyValue = property.GetValue<object>();
             if (oldPropertyValue != newPropertyValue)
             if (oldPropertyValue != newPropertyValue)
             {
             {
@@ -52,52 +55,31 @@ namespace BansheeEditor
             }
             }
 
 
             SerializableArray array = property.GetArray();
             SerializableArray array = property.GetArray();
-            if (array.GetLength() != arrayElements.Count)
+            if (array.GetLength() != numArrayElements)
                 return true;
                 return true;
 
 
             return base.IsModified();
             return base.IsModified();
         }
         }
 
 
-        protected override void Update(GUILayout layout)
+        protected override void Update(int layoutIndex)
         {
         {
-            base.Update(layout);
+            base.Update(layoutIndex);
 
 
             if (!isInitialized)
             if (!isInitialized)
-                Initialize(layout);
-
-            // TODO - Update base GUI elements
+                Initialize(layoutIndex);
 
 
             SerializableArray array = property.GetArray();
             SerializableArray array = property.GetArray();
 
 
-            for (int i = arrayElements.Count; i < array.GetLength(); i++)
+            int childLayoutIndex = 0;
+            numArrayElements = array.GetLength();
+            for (int i = 0; i < numArrayElements; i++)
             {
             {
-                InspectableObjectBase childObj = CreateDefaultInspectable(i + ".", array.GetProperty(i));
+                InspectableObjectBase childObj = CreateDefaultInspectable(i + ".", new InspectableFieldLayout(guiContentLayout), array.GetProperty(i));
                 AddChild(childObj);
                 AddChild(childObj);
-                arrayElements.Add(childObj);
-
-                childObj.Refresh(layout);
-            }
 
 
-            for (int i = array.GetLength(); i < arrayElements.Count; i++)
-            {
-                arrayElements[i].Destroy();
+                childObj.Refresh(childLayoutIndex);
+                childLayoutIndex += childObj.GetNumLayoutElements();
             }
             }
-
-            arrayElements.RemoveRange(array.GetLength(), arrayElements.Count - array.GetLength());
-        }
-
-        public override void Destroy()
-        {
-            if (guiLabel != null)
-                guiLabel.Destroy();
-
-            if (guiContentLayout != null)
-                guiContentLayout.Destroy();
-
-            if (guiChildLayout != null)
-                guiChildLayout.Destroy();
-
-            base.Destroy();
         }
         }
     }
     }
 }
 }

+ 54 - 0
MBansheeEditor/Inspector/InspectableFieldLayout.cs

@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    public class InspectableFieldLayout
+    {
+        private GUILayoutY parentLayout;
+        private List<GUIElement> elements = new List<GUIElement>();
+
+        public InspectableFieldLayout(GUILayoutY parentLayout)
+        {
+            this.parentLayout = parentLayout;
+        }
+
+        public int GetNumElements() { return elements.Count; }
+
+        public void AddElement(int index, GUIElement element)
+        {
+            parentLayout.InsertElement(index + elements.Count, element);
+            elements.Add(element);
+        }
+
+        public GUILayoutX AddLayoutX(int index)
+        {
+            GUILayoutX layout = parentLayout.InsertLayoutX(index + elements.Count);
+            elements.Add(layout);
+
+            return layout;
+        }
+
+        public GUILayoutY AddLayoutY(int index)
+        {
+            GUILayoutY layout = parentLayout.InsertLayoutY(index + elements.Count);
+            elements.Add(layout);
+
+            return layout;
+        }
+
+        public void DestroyElements()
+        {
+            foreach (var element in elements)
+            {
+                element.Destroy();
+            }
+
+            elements.Clear();
+        }
+    }
+}

+ 12 - 18
MBansheeEditor/Inspector/InspectableInt.cs

@@ -11,21 +11,22 @@ namespace BansheeEditor
     {
     {
         private int oldPropertyValue;
         private int oldPropertyValue;
         private GUIIntField guiIntField;
         private GUIIntField guiIntField;
-        private bool isInitialized = false;
+        private bool isInitialized;
 
 
-        public InspectableInt(string title, SerializableProperty property)
-            :base(title, property)
+        public InspectableInt(string title, InspectableFieldLayout layout, SerializableProperty property)
+            : base(title, layout, property)
         {
         {
 
 
         }
         }
 
 
-        protected void Initialize(GUILayout layout)
+        private void Initialize(int layoutIndex)
         {
         {
-            if(property.Type == SerializableProperty.FieldType.Int)
+            if (property.Type == SerializableProperty.FieldType.Int)
             {
             {
                 guiIntField = new GUIIntField(new GUIContent(title));
                 guiIntField = new GUIIntField(new GUIContent(title));
                 guiIntField.OnChanged += OnFieldValueChanged;
                 guiIntField.OnChanged += OnFieldValueChanged;
-                layout.AddElement(guiIntField); 
+
+                layout.AddElement(layoutIndex, guiIntField);
             }
             }
 
 
             isInitialized = true;
             isInitialized = true;
@@ -47,29 +48,22 @@ namespace BansheeEditor
             return base.IsModified();
             return base.IsModified();
         }
         }
 
 
-        protected override void Update(GUILayout layout)
+        protected override void Update(int layoutIndex)
         {
         {
-            base.Update(layout);
+            base.Update(layoutIndex);
 
 
             if (!isInitialized)
             if (!isInitialized)
-                Initialize(layout);
+                Initialize(layoutIndex);
 
 
             // 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
 
 
-            guiIntField.Value = property.GetValue<int>();
+            if(guiIntField != null)
+                guiIntField.Value = property.GetValue<int>();
         }
         }
 
 
         private void OnFieldValueChanged(int newValue)
         private void OnFieldValueChanged(int newValue)
         {
         {
             property.SetValue<int>(newValue);
             property.SetValue<int>(newValue);
         }
         }
-
-        public override void Destroy()
-        {
-            if (guiIntField != null)
-                guiIntField.Destroy();
-
-            base.Destroy();
-        }
     }
     }
 }
 }

+ 14 - 25
MBansheeEditor/Inspector/InspectableObject.cs

@@ -15,24 +15,24 @@ namespace BansheeEditor
 
 
         private GUILabel guiLabel;
         private GUILabel guiLabel;
         private GUILayout guiChildLayout;
         private GUILayout guiChildLayout;
-        private GUILayout guiContentLayout;
+        private GUILayoutY guiContentLayout;
         private bool isInitialized;
         private bool isInitialized;
 
 
-        public InspectableObject(string title, SerializableProperty property)
-            : base(title, property)
+        public InspectableObject(string title, InspectableFieldLayout layout, SerializableProperty property)
+            : base(title, layout, property)
         {
         {
             
             
         }
         }
 
 
-        protected void Initialize(GUILayout layout)
+        protected void Initialize(int layoutIndex)
         {
         {
             if (property.Type != SerializableProperty.FieldType.Object)
             if (property.Type != SerializableProperty.FieldType.Object)
                 return;
                 return;
 
 
             guiLabel = new GUILabel(title);
             guiLabel = new GUILabel(title);
-            layout.AddElement(guiLabel);
+            layout.AddElement(layoutIndex, guiLabel);
 
 
-            guiChildLayout = layout.AddLayoutX();
+            guiChildLayout = layout.AddLayoutX(layoutIndex);
             guiChildLayout.AddSpace(IndentAmount);
             guiChildLayout.AddSpace(IndentAmount);
 
 
             guiContentLayout = guiChildLayout.AddLayoutY();
             guiContentLayout = guiChildLayout.AddLayoutY();
@@ -45,9 +45,9 @@ namespace BansheeEditor
                     continue;
                     continue;
 
 
                 if (field.HasCustomInspector)
                 if (field.HasCustomInspector)
-                    AddChild(CreateCustomInspectable(field.CustomInspectorType, field.Name, field.GetProperty()));
+                    AddChild(CreateCustomInspectable(field.CustomInspectorType, field.Name, new InspectableFieldLayout(guiContentLayout), field.GetProperty()));
                 else
                 else
-                    AddChild(CreateDefaultInspectable(field.Name, field.GetProperty()));
+                    AddChild(CreateDefaultInspectable(field.Name, new InspectableFieldLayout(guiContentLayout), field.GetProperty()));
             }
             }
 
 
             isInitialized = true;
             isInitialized = true;
@@ -55,6 +55,9 @@ namespace BansheeEditor
 
 
         protected override bool IsModified()
         protected override bool IsModified()
         {
         {
+            if (!isInitialized)
+                return true;
+
             object newPropertyValue = property.GetValue<object>();
             object newPropertyValue = property.GetValue<object>();
             if (oldPropertyValue != newPropertyValue)
             if (oldPropertyValue != newPropertyValue)
             {
             {
@@ -66,28 +69,14 @@ namespace BansheeEditor
             return base.IsModified();
             return base.IsModified();
         }
         }
 
 
-        protected override void Update(GUILayout layout)
+        protected override void Update(int index)
         {
         {
-            base.Update(layout);
+            base.Update(index);
 
 
             if (!isInitialized)
             if (!isInitialized)
-                Initialize(layout);
+                Initialize(index);
 
 
             // TODO - Update GUI element(s) with value from property
             // TODO - Update GUI element(s) with value from property
         }
         }
-
-        public override void Destroy()
-        {
-            if (guiLabel != null)
-                guiLabel.Destroy();
-
-            if (guiContentLayout != null)
-                guiContentLayout.Destroy();
-
-            if (guiChildLayout != null)
-                guiChildLayout.Destroy();
-
-            base.Destroy();
-        }
     }
     }
 }
 }

+ 31 - 12
MBansheeEditor/Inspector/InspectableObjectBase.cs

@@ -11,12 +11,14 @@ namespace BansheeEditor
     {
     {
         private List<InspectableObjectBase> children = new List<InspectableObjectBase>();
         private List<InspectableObjectBase> children = new List<InspectableObjectBase>();
         private InspectableObjectBase parent;
         private InspectableObjectBase parent;
-
+        
+        protected InspectableFieldLayout layout;
         protected SerializableProperty property;
         protected SerializableProperty property;
         protected string title;
         protected string title;
 
 
-        public InspectableObjectBase(string title, SerializableProperty property)
+        public InspectableObjectBase(string title, InspectableFieldLayout layout, SerializableProperty property)
         {
         {
+            this.layout = layout;
             this.title = title;
             this.title = title;
             this.property = property;
             this.property = property;
         }
         }
@@ -39,13 +41,22 @@ namespace BansheeEditor
             child.parent = null;
             child.parent = null;
         }
         }
 
 
-        public virtual void Refresh(GUILayout layout)
+        public virtual void Refresh(int layoutIndex)
         {
         {
             if (IsModified())
             if (IsModified())
-                Update(layout);
+                Update(layoutIndex);
 
 
+            int currentIndex = 0;
             for (int i = 0; i < children.Count; i++)
             for (int i = 0; i < children.Count; i++)
-                children[i].Refresh(layout);
+            {
+                children[i].Refresh(currentIndex);
+                currentIndex += children[i].GetNumLayoutElements();
+            }
+        }
+
+        public int GetNumLayoutElements()
+        {
+            return layout.GetNumElements();
         }
         }
 
 
         protected virtual bool IsModified()
         protected virtual bool IsModified()
@@ -53,13 +64,21 @@ namespace BansheeEditor
             return false;
             return false;
         }
         }
 
 
-        protected virtual void Update(GUILayout layout)
+        protected virtual void Update(int layoutIndex)
         {
         {
-            // Do nothing
+            // Destroy all children as we expect update to rebuild them
+
+            InspectableObjectBase[] childrenCopy = children.ToArray();
+            for (int i = 0; i < childrenCopy.Length; i++)
+                children[i].Destroy();
+
+            children.Clear();
         }
         }
 
 
         public virtual void Destroy()
         public virtual void Destroy()
         {
         {
+            layout.DestroyElements();
+
             InspectableObjectBase[] childrenCopy = children.ToArray();
             InspectableObjectBase[] childrenCopy = children.ToArray();
             for (int i = 0; i < childrenCopy.Length; i++)
             for (int i = 0; i < childrenCopy.Length; i++)
                 children[i].Destroy();
                 children[i].Destroy();
@@ -70,23 +89,23 @@ namespace BansheeEditor
                 parent.RemoveChild(this);
                 parent.RemoveChild(this);
         }
         }
 
 
-        public static InspectableObjectBase CreateDefaultInspectable(string title, SerializableProperty property)
+        public static InspectableObjectBase CreateDefaultInspectable(string title, InspectableFieldLayout layout, SerializableProperty property)
         {
         {
             switch (property.Type)
             switch (property.Type)
             {
             {
                 case SerializableProperty.FieldType.Int:
                 case SerializableProperty.FieldType.Int:
-                    return new InspectableInt(title, property);
+                    return new InspectableInt(title, layout, property);
                 case SerializableProperty.FieldType.Object:
                 case SerializableProperty.FieldType.Object:
-                    return new InspectableObject(title, property);
+                    return new InspectableObject(title, layout, property);
                 case SerializableProperty.FieldType.Array:
                 case SerializableProperty.FieldType.Array:
-                    return new InspectableArray(title, property);
+                    return new InspectableArray(title, layout, property);
                 // TODO - Add all other types
                 // TODO - Add all other types
             }
             }
 
 
             throw new Exception("No inspector exists for the provided field type.");
             throw new Exception("No inspector exists for the provided field type.");
         }
         }
 
 
-        public static InspectableObjectBase CreateCustomInspectable(Type inspectableType, string title, SerializableProperty property)
+        public static InspectableObjectBase CreateCustomInspectable(Type inspectableType, string title, InspectableFieldLayout layout, SerializableProperty property)
         {
         {
             if (!inspectableType.IsSubclassOf(typeof (InspectableObjectBase)))
             if (!inspectableType.IsSubclassOf(typeof (InspectableObjectBase)))
                 throw new Exception("Invalid inspector type.");
                 throw new Exception("Invalid inspector type.");

+ 1 - 1
MBansheeEditor/Inspector/Inspector.cs

@@ -9,7 +9,7 @@ namespace BansheeEditor
     public abstract class Inspector
     public abstract class Inspector
     {
     {
         protected GUIPanel GUI;
         protected GUIPanel GUI;
-        protected GUILayout layout;
+        protected GUILayoutY layout;
         protected object referencedObject;
         protected object referencedObject;
 
 
         internal void Initialize(GUIPanel gui, object instance)
         internal void Initialize(GUIPanel gui, object instance)

+ 1 - 0
MBansheeEditor/MBansheeEditor.csproj

@@ -61,6 +61,7 @@
     <Compile Include="Inspector\CustomInspector.cs" />
     <Compile Include="Inspector\CustomInspector.cs" />
     <Compile Include="Inspector\GenericInspector.cs" />
     <Compile Include="Inspector\GenericInspector.cs" />
     <Compile Include="Inspector\InspectableArray.cs" />
     <Compile Include="Inspector\InspectableArray.cs" />
+    <Compile Include="Inspector\InspectableFieldLayout.cs" />
     <Compile Include="Inspector\InspectableObject.cs" />
     <Compile Include="Inspector\InspectableObject.cs" />
     <Compile Include="Inspector\InspectableObjectBase.cs" />
     <Compile Include="Inspector\InspectableObjectBase.cs" />
     <Compile Include="Inspector\InspectableInt.cs" />
     <Compile Include="Inspector\InspectableInt.cs" />

+ 0 - 8
MBansheeEngine/GUI/GUIElement.cs

@@ -15,11 +15,6 @@ namespace BansheeEngine
                 parent.Remove(this);
                 parent.Remove(this);
 
 
             parent = layout;
             parent = layout;
-
-            if (parent != null)
-                parent.children.Add(this);
-
-            Internal_SetParent(mCachedPtr, layout);
         }
         }
 
 
         internal virtual bool IsStatic()
         internal virtual bool IsStatic()
@@ -50,9 +45,6 @@ namespace BansheeEngine
             Internal_SetLayoutOptions(mCachedPtr, options);
             Internal_SetLayoutOptions(mCachedPtr, options);
         }
         }
 
 
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetParent(IntPtr nativeInstance, GUILayout parent);
-
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_SetLayoutOptions(IntPtr nativeInstance, GUIOption[] options);
         private static extern void Internal_SetLayoutOptions(IntPtr nativeInstance, GUIOption[] options);
 
 

+ 89 - 6
MBansheeEngine/GUI/GUILayout.cs

@@ -13,16 +13,42 @@ namespace BansheeEngine
             return true;
             return true;
         }
         }
 
 
-        internal void AddElementInternal(GUIElement element)
+        internal bool AddElementInternal(GUIElement element)
         {
         {
             if (IsDestroyed())
             if (IsDestroyed())
             {
             {
                 Debug.LogWarning("Attempting to add an element to a destroyed layout. Ignoring operation.");
                 Debug.LogWarning("Attempting to add an element to a destroyed layout. Ignoring operation.");
-                return;
+                return false;
             }
             }
 
 
             if (!children.Contains(element))
             if (!children.Contains(element))
+            {
                 element.SetParent(this);
                 element.SetParent(this);
+                children.Add(element);
+
+                return true;
+            }
+
+            return false;
+        }
+
+        internal bool InsertElementInternal(int index, GUIElement element)
+        {
+            if (IsDestroyed())
+            {
+                Debug.LogWarning("Attempting to add an element to a destroyed layout. Ignoring operation.");
+                return false;
+            }
+
+            if (!children.Contains(element))
+            {
+                element.SetParent(this);
+                children.Insert(index, element);
+
+                return true;
+            }
+
+            return false;
         }
         }
 
 
         internal override void SetParent(GUILayout layout)
         internal override void SetParent(GUILayout layout)
@@ -44,7 +70,20 @@ namespace BansheeEngine
                 return;
                 return;
             }
             }
 
 
-            AddElementInternal(element);
+            if(AddElementInternal(element))
+                Internal_AddElement(mCachedPtr, element.mCachedPtr);
+        }
+
+        public void InsertElement(int index, GUIElement element)
+        {
+            if (element.IsStatic())
+            {
+                Debug.LogWarning("You are trying to change parent of a static GUI element. Ignoring operation.");
+                return;
+            }
+
+            if (InsertElementInternal(index, element))
+                Internal_InsertElement(mCachedPtr, index, element.mCachedPtr);
         }
         }
 
 
         public GUIFixedSpace AddSpace(int size)
         public GUIFixedSpace AddSpace(int size)
@@ -55,6 +94,14 @@ namespace BansheeEngine
             return fixedSpace;
             return fixedSpace;
         }
         }
 
 
+        public GUIFixedSpace InsertSpace(int index, int size)
+        {
+            GUIFixedSpace fixedSpace = new GUIFixedSpace(this, index, size);
+            InsertElementInternal(index, fixedSpace);
+
+            return fixedSpace;
+        }
+
         public GUIFlexibleSpace AddFlexibleSpace()
         public GUIFlexibleSpace AddFlexibleSpace()
         {
         {
             GUIFlexibleSpace flexibleSpace = new GUIFlexibleSpace(this);
             GUIFlexibleSpace flexibleSpace = new GUIFlexibleSpace(this);
@@ -63,6 +110,14 @@ namespace BansheeEngine
             return flexibleSpace;
             return flexibleSpace;
         }
         }
 
 
+        public GUIFlexibleSpace InsertFlexibleSpace(int index)
+        {
+            GUIFlexibleSpace flexibleSpace = new GUIFlexibleSpace(this, index);
+            InsertElementInternal(index, flexibleSpace);
+
+            return flexibleSpace;
+        }
+
         public GUILayoutX AddLayoutX()
         public GUILayoutX AddLayoutX()
         {
         {
             GUILayoutX layoutX = new GUILayoutX(this);
             GUILayoutX layoutX = new GUILayoutX(this);
@@ -71,6 +126,14 @@ namespace BansheeEngine
             return layoutX;
             return layoutX;
         }
         }
 
 
+        public GUILayoutX InsertLayoutX(int index)
+        {
+            GUILayoutX layoutX = new GUILayoutX(this, index);
+            InsertElementInternal(index, layoutX);
+
+            return layoutX;
+        }
+
         public GUILayoutY AddLayoutY()
         public GUILayoutY AddLayoutY()
         {
         {
             GUILayoutY layoutY = new GUILayoutY(this);
             GUILayoutY layoutY = new GUILayoutY(this);
@@ -79,6 +142,14 @@ namespace BansheeEngine
             return layoutY;
             return layoutY;
         }
         }
 
 
+        public GUILayoutY InsertLayoutY(int index)
+        {
+            GUILayoutY layoutY = new GUILayoutY(this, index);
+            InsertElementInternal(index, layoutY);
+
+            return layoutY;
+        }
+
         public void Remove(GUIElement element)
         public void Remove(GUIElement element)
         {
         {
             if (children.Contains(element))
             if (children.Contains(element))
@@ -122,12 +193,24 @@ namespace BansheeEngine
         protected static extern void Internal_CreateInstanceXFromArea(GUILayout instance, GUIArea parentArea);
         protected static extern void Internal_CreateInstanceXFromArea(GUILayout instance, GUIArea parentArea);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        protected static extern void Internal_CreateInstanceXFromLayout(GUILayout instance, GUILayout parentLayout);
+        protected static extern void Internal_CreateInstanceYFromScrollArea(GUILayout instance, GUIScrollArea parentArea);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        protected static extern void Internal_CreateInstanceYFromScrollArea(GUILayout instance, GUIScrollArea parentArea);
+        protected static extern void Internal_CreateInstanceXFromLayoutAdd(GUILayout instance, GUILayout parentLayout);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        protected static extern void Internal_CreateInstanceYFromLayoutAdd(GUILayout instance, GUILayout parentLayout);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        protected static extern void Internal_CreateInstanceXFromLayoutInsert(GUILayout instance, GUILayout parentLayout, int index);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        protected static extern void Internal_CreateInstanceYFromLayoutInsert(GUILayout instance, GUILayout parentLayout, int index);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        protected static extern void Internal_AddElement(IntPtr instance, IntPtr element);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        protected static extern void Internal_CreateInstanceYFromLayout(GUILayout instance, GUILayout parentLayout);
+        protected static extern void Internal_InsertElement(IntPtr instance, int index, IntPtr element);
     }
     }
 }
 }

+ 6 - 1
MBansheeEngine/GUI/GUILayoutX.cs

@@ -12,7 +12,12 @@ namespace BansheeEngine
 
 
         internal GUILayoutX(GUILayout parentLayout)
         internal GUILayoutX(GUILayout parentLayout)
         {
         {
-            Internal_CreateInstanceXFromLayout(this, parentLayout);
+            Internal_CreateInstanceXFromLayoutAdd(this, parentLayout);
+        }
+
+        internal GUILayoutX(GUILayout parentLayout, int index)
+        {
+            Internal_CreateInstanceXFromLayoutInsert(this, parentLayout, index);
         }
         }
     }
     }
 }
 }

+ 6 - 1
MBansheeEngine/GUI/GUILayoutY.cs

@@ -7,12 +7,17 @@ namespace BansheeEngine
     {
     {
         internal GUILayoutY(GUILayout parentLayout)
         internal GUILayoutY(GUILayout parentLayout)
         {
         {
-            Internal_CreateInstanceYFromLayout(this, parentLayout);
+            Internal_CreateInstanceYFromLayoutAdd(this, parentLayout);
         }
         }
 
 
         internal GUILayoutY(GUIScrollArea parentArea)
         internal GUILayoutY(GUIScrollArea parentArea)
         {
         {
             Internal_CreateInstanceYFromScrollArea(this, parentArea);
             Internal_CreateInstanceYFromScrollArea(this, parentArea);
         }
         }
+
+        internal GUILayoutY(GUILayout parentLayout, int index)
+        {
+            Internal_CreateInstanceYFromLayoutInsert(this, parentLayout, index);
+        }
     }
     }
 }
 }

+ 20 - 4
MBansheeEngine/GUI/GUISpace.cs

@@ -7,7 +7,12 @@ namespace BansheeEngine
     {
     {
         internal GUIFixedSpace(GUILayout parentLayout, int size)
         internal GUIFixedSpace(GUILayout parentLayout, int size)
         {
         {
-            Internal_CreateInstance(this, parentLayout, size);
+            Internal_CreateInstanceAdd(this, parentLayout, size);
+        }
+
+        internal GUIFixedSpace(GUILayout parentLayout, int index, int size)
+        {
+            Internal_CreateInstanceInsert(this, parentLayout, index, size);
         }
         }
 
 
         internal override bool IsStatic()
         internal override bool IsStatic()
@@ -33,7 +38,10 @@ namespace BansheeEngine
         }
         }
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(GUIFixedSpace instance, GUILayout parentLayout, int size);
+        private static extern void Internal_CreateInstanceAdd(GUIFixedSpace instance, GUILayout parentLayout, int size);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstanceInsert(GUIFixedSpace instance, GUILayout parentLayout, int index, int size);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_SetSize(IntPtr nativeInstance, int size);
         private static extern void Internal_SetSize(IntPtr nativeInstance, int size);
@@ -43,7 +51,12 @@ namespace BansheeEngine
     {
     {
         internal GUIFlexibleSpace(GUILayout parentLayout)
         internal GUIFlexibleSpace(GUILayout parentLayout)
         {
         {
-            Internal_CreateInstance(this, parentLayout);
+            Internal_CreateInstanceAdd(this, parentLayout);
+        }
+
+        internal GUIFlexibleSpace(GUILayout parentLayout, int index)
+        {
+            Internal_CreateInstanceInsert(this, parentLayout, index);
         }
         }
 
 
         internal override bool IsStatic()
         internal override bool IsStatic()
@@ -64,6 +77,9 @@ namespace BansheeEngine
         }
         }
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(GUIFlexibleSpace instance, GUILayout parentLayout);
+        private static extern void Internal_CreateInstanceAdd(GUIFlexibleSpace instance, GUILayout parentLayout);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstanceInsert(GUIFlexibleSpace instance, GUILayout parentLayout, int index);
     }
     }
 }
 }

+ 1 - 1
MBansheeEngine/ScriptObject.cs

@@ -5,7 +5,7 @@ namespace BansheeEngine
 {
 {
     public class ScriptObject
     public class ScriptObject
     {
     {
-        protected IntPtr mCachedPtr;
+        internal IntPtr mCachedPtr;
 
 
         ~ScriptObject()
         ~ScriptObject()
         {
         {

+ 2 - 0
Notes.txt

@@ -65,6 +65,8 @@ Reminders:
   - GUIElementBase::_getElementAreas is currently only implemented for layouts. It will work of child elements of layouts and layouts themselves but will not 
   - GUIElementBase::_getElementAreas is currently only implemented for layouts. It will work of child elements of layouts and layouts themselves but will not 
     work for child elements of custom element types. This method is used for calculating size and position of an element in its parent.
     work for child elements of custom element types. This method is used for calculating size and position of an element in its parent.
   - I shouldn't use WeakRef with GameObjects. They need be deserialized in the order of their hierarchy and weak ref can break that.
   - I shouldn't use WeakRef with GameObjects. They need be deserialized in the order of their hierarchy and weak ref can break that.
+  - Make sure to add fixedUpdate() to run your game logic in. This should have an adjustable update rate. See: http://gameprogrammingpatterns.com/game-loop.html
+  - Will also need GameObject::destroy and GameObject::destroyImmediate. So I can remove GameObjects that might still be referenced that same frame (destroy() would just queue for destruction)
 
 
 Potential optimizations:
 Potential optimizations:
  - bulkPixelConversion is EXTREMELY poorly unoptimized. Each pixel it calls a separate method that does redudant operations every pixel.
  - bulkPixelConversion is EXTREMELY poorly unoptimized. Each pixel it calls a separate method that does redudant operations every pixel.

+ 0 - 3
SBansheeEngine/Include/BsScriptGUIElement.h

@@ -15,7 +15,6 @@ namespace BansheeEngine
 		GUIElementBase* getGUIElement() const { return (GUIElementBase*)mElement; }
 		GUIElementBase* getGUIElement() const { return (GUIElementBase*)mElement; }
 
 
 		virtual void destroy() = 0;
 		virtual void destroy() = 0;
-		virtual void setParent(GUILayout* layout) = 0;
 		virtual void setLayoutOptions(GUIOptions options) { }
 		virtual void setLayoutOptions(GUIOptions options) { }
 
 
 	protected:
 	protected:
@@ -56,7 +55,6 @@ namespace BansheeEngine
 		virtual ~ScriptGUIElementTBase() {}
 		virtual ~ScriptGUIElementTBase() {}
 
 
 		virtual void destroy();
 		virtual void destroy();
-		virtual void setParent(GUILayout* layout);
 		virtual void setLayoutOptions(GUIOptions options);
 		virtual void setLayoutOptions(GUIOptions options);
 	};
 	};
 
 
@@ -92,7 +90,6 @@ namespace BansheeEngine
 	private:
 	private:
 		static void internal_destroy(ScriptGUIElementBaseTBase* nativeInstance);
 		static void internal_destroy(ScriptGUIElementBaseTBase* nativeInstance);
 		static void internal_setVisible(ScriptGUIElementBaseTBase* nativeInstance, bool visible);
 		static void internal_setVisible(ScriptGUIElementBaseTBase* nativeInstance, bool visible);
-		static void internal_setParent(ScriptGUIElementBaseTBase* nativeInstance, MonoObject* parentLayout);
 		static void internal_setLayoutOptions(ScriptGUIElementBaseTBase* nativeInstance, MonoArray* guiOptions);
 		static void internal_setLayoutOptions(ScriptGUIElementBaseTBase* nativeInstance, MonoArray* guiOptions);
 
 
 		ScriptGUIElement(MonoObject* instance);
 		ScriptGUIElement(MonoObject* instance);

+ 2 - 2
SBansheeEngine/Include/BsScriptGUIFixedSpace.h

@@ -11,13 +11,13 @@ namespace BansheeEngine
 		SCRIPT_OBJ(BansheeEngineAssemblyName, "BansheeEngine", "GUIFixedSpace")
 		SCRIPT_OBJ(BansheeEngineAssemblyName, "BansheeEngine", "GUIFixedSpace")
 
 
 	private:
 	private:
-		static void internal_createInstance(MonoObject* instance, MonoObject* parentLayout, UINT32 size);
+		static void internal_createInstanceAdd(MonoObject* instance, MonoObject* parentLayout, UINT32 size);
+		static void internal_createInstanceInsert(MonoObject* instance, MonoObject* parentLayout, UINT32 index, UINT32 size);
 		static void internal_setSize(ScriptGUIFixedSpace* nativeInstance, UINT32 size);
 		static void internal_setSize(ScriptGUIFixedSpace* nativeInstance, UINT32 size);
 
 
 		ScriptGUIFixedSpace(MonoObject* instance, GUIFixedSpace& fixedSpace, GUILayout* parentLayout);
 		ScriptGUIFixedSpace(MonoObject* instance, GUIFixedSpace& fixedSpace, GUILayout* parentLayout);
 
 
 		void destroy();
 		void destroy();
-		void setParent(GUILayout* parentLayout);
 
 
 		GUIFixedSpace& mFixedSpace;
 		GUIFixedSpace& mFixedSpace;
 		GUILayout* mParentLayout;
 		GUILayout* mParentLayout;

+ 2 - 2
SBansheeEngine/Include/BsScriptGUIFlexibleSpace.h

@@ -11,12 +11,12 @@ namespace BansheeEngine
 		SCRIPT_OBJ(BansheeEngineAssemblyName, "BansheeEngine", "GUIFlexibleSpace")
 		SCRIPT_OBJ(BansheeEngineAssemblyName, "BansheeEngine", "GUIFlexibleSpace")
 
 
 	private:
 	private:
-		static void internal_createInstance(MonoObject* instance, MonoObject* parentLayout);
+		static void internal_createInstanceAdd(MonoObject* instance, MonoObject* parentLayout);
+		static void internal_createInstanceInsert(MonoObject* instance, MonoObject* parentLayout, UINT32 index);
 
 
 		ScriptGUIFlexibleSpace(MonoObject* instance, GUIFlexibleSpace& flexibleSpace, GUILayout* parentLayout);
 		ScriptGUIFlexibleSpace(MonoObject* instance, GUIFlexibleSpace& flexibleSpace, GUILayout* parentLayout);
 
 
 		void destroy();
 		void destroy();
-		void setParent(GUILayout* parentLayout);
 
 
 		GUIFlexibleSpace& mFlexibleSpace;
 		GUIFlexibleSpace& mFlexibleSpace;
 		GUILayout* mParentLayout;
 		GUILayout* mParentLayout;

+ 6 - 3
SBansheeEngine/Include/BsScriptGUILayout.h

@@ -15,14 +15,17 @@ namespace BansheeEngine
 
 
 	private:
 	private:
 		static void internal_createInstanceXFromArea(MonoObject* instance, MonoObject* parentArea);
 		static void internal_createInstanceXFromArea(MonoObject* instance, MonoObject* parentArea);
-		static void internal_createInstanceXFromLayout(MonoObject* instance, MonoObject* parentLayout);
-		static void internal_createInstanceYFromLayout(MonoObject* instance, MonoObject* parentLayout);
+		static void internal_createInstanceXFromLayoutAdd(MonoObject* instance, MonoObject* parentLayout);
+		static void internal_createInstanceYFromLayoutAdd(MonoObject* instance, MonoObject* parentLayout);
+		static void internal_createInstanceXFromLayoutInsert(MonoObject* instance, MonoObject* parentLayout, UINT32 index);
+		static void internal_createInstanceYFromLayoutInsert(MonoObject* instance, MonoObject* parentLayout, UINT32 index);
 		static void internal_createInstanceYFromScrollArea(MonoObject* instance, MonoObject* parentScrollArea);
 		static void internal_createInstanceYFromScrollArea(MonoObject* instance, MonoObject* parentScrollArea);
+		static void internal_addElement(ScriptGUILayout* instance, ScriptGUIElementTBase* element);
+		static void internal_insertElement(ScriptGUILayout* instance, UINT32 index, ScriptGUIElementTBase* element);
 
 
 		ScriptGUILayout(MonoObject* instance, GUILayout* layout, GUILayout* parentLayout);
 		ScriptGUILayout(MonoObject* instance, GUILayout* layout, GUILayout* parentLayout);
 
 
 		void destroy();
 		void destroy();
-		void setParent(GUILayout* parentLayout);
 
 
 		GUILayout* mLayout;
 		GUILayout* mLayout;
 		GUILayout* mParentLayout;
 		GUILayout* mParentLayout;

+ 0 - 14
SBansheeEngine/Source/BsScriptGUIElement.cpp

@@ -42,11 +42,6 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
-	void ScriptGUIElementTBase::setParent(GUILayout* layout)
-	{
-		layout->addElement((GUIElement*)mElement);
-	}
-
 	void ScriptGUIElementTBase::setLayoutOptions(GUIOptions options)
 	void ScriptGUIElementTBase::setLayoutOptions(GUIOptions options)
 	{
 	{
 		GUIElement* element = static_cast<GUIElement*>(mElement);
 		GUIElement* element = static_cast<GUIElement*>(mElement);
@@ -63,7 +58,6 @@ namespace BansheeEngine
 	{
 	{
 		metaData.scriptClass->addInternalCall("Internal_Destroy", &ScriptGUIElement::internal_destroy);
 		metaData.scriptClass->addInternalCall("Internal_Destroy", &ScriptGUIElement::internal_destroy);
 		metaData.scriptClass->addInternalCall("Internal_SetVisible", &ScriptGUIElement::internal_setVisible);
 		metaData.scriptClass->addInternalCall("Internal_SetVisible", &ScriptGUIElement::internal_setVisible);
-		metaData.scriptClass->addInternalCall("Internal_SetParent", &ScriptGUIElement::internal_setParent);
 		metaData.scriptClass->addInternalCall("Internal_SetLayoutOptions", &ScriptGUIElement::internal_setLayoutOptions);
 		metaData.scriptClass->addInternalCall("Internal_SetLayoutOptions", &ScriptGUIElement::internal_setLayoutOptions);
 	}
 	}
 
 
@@ -80,14 +74,6 @@ namespace BansheeEngine
 			nativeInstance->getGUIElement()->disableRecursively();
 			nativeInstance->getGUIElement()->disableRecursively();
 	}
 	}
 
 
-	void ScriptGUIElement::internal_setParent(ScriptGUIElementBaseTBase* nativeInstance, MonoObject* parentLayout)
-	{
-		ScriptGUILayout* scriptLayout = ScriptGUILayout::toNative(parentLayout);
-		GUILayout* nativeLayout = scriptLayout->getInternalValue();
-
-		nativeInstance->setParent(nativeLayout);
-	}
-
 	void ScriptGUIElement::internal_setLayoutOptions(ScriptGUIElementBaseTBase* nativeInstance, MonoArray* guiOptions)
 	void ScriptGUIElement::internal_setLayoutOptions(ScriptGUIElementBaseTBase* nativeInstance, MonoArray* guiOptions)
 	{
 	{
 		GUIOptions options;
 		GUIOptions options;

+ 10 - 5
SBansheeEngine/Source/BsScriptGUIFixedSpace.cpp

@@ -19,7 +19,8 @@ namespace BansheeEngine
 
 
 	void ScriptGUIFixedSpace::initRuntimeData()
 	void ScriptGUIFixedSpace::initRuntimeData()
 	{
 	{
-		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptGUIFixedSpace::internal_createInstance);
+		metaData.scriptClass->addInternalCall("Internal_CreateInstanceAdd", &ScriptGUIFixedSpace::internal_createInstanceAdd);
+		metaData.scriptClass->addInternalCall("Internal_CreateInstanceInsert", &ScriptGUIFixedSpace::internal_createInstanceInsert);
 		metaData.scriptClass->addInternalCall("Internal_SetSize", &ScriptGUIFixedSpace::internal_setSize);
 		metaData.scriptClass->addInternalCall("Internal_SetSize", &ScriptGUIFixedSpace::internal_setSize);
 	}
 	}
 
 
@@ -34,16 +35,20 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
-	void ScriptGUIFixedSpace::setParent(GUILayout* parentLayout)
+	void ScriptGUIFixedSpace::internal_createInstanceAdd(MonoObject* instance, MonoObject* parentLayout, UINT32 size)
 	{
 	{
-		// FixedSpace parent is static, so do nothing
+		ScriptGUILayout* scriptLayout = ScriptGUILayout::toNative(parentLayout);
+		GUILayout* nativeLayout = scriptLayout->getInternalValue();
+		GUIFixedSpace& space = nativeLayout->addSpace(size);
+
+		ScriptGUIFixedSpace* nativeInstance = new (bs_alloc<ScriptGUIFixedSpace>()) ScriptGUIFixedSpace(instance, space, nativeLayout);
 	}
 	}
 
 
-	void ScriptGUIFixedSpace::internal_createInstance(MonoObject* instance, MonoObject* parentLayout, UINT32 size)
+	void ScriptGUIFixedSpace::internal_createInstanceInsert(MonoObject* instance, MonoObject* parentLayout, UINT32 index, UINT32 size)
 	{
 	{
 		ScriptGUILayout* scriptLayout = ScriptGUILayout::toNative(parentLayout);
 		ScriptGUILayout* scriptLayout = ScriptGUILayout::toNative(parentLayout);
 		GUILayout* nativeLayout = scriptLayout->getInternalValue();
 		GUILayout* nativeLayout = scriptLayout->getInternalValue();
-		GUIFixedSpace& space = nativeLayout->addSpace(size);
+		GUIFixedSpace& space = nativeLayout->insertSpace(index, size);
 
 
 		ScriptGUIFixedSpace* nativeInstance = new (bs_alloc<ScriptGUIFixedSpace>()) ScriptGUIFixedSpace(instance, space, nativeLayout);
 		ScriptGUIFixedSpace* nativeInstance = new (bs_alloc<ScriptGUIFixedSpace>()) ScriptGUIFixedSpace(instance, space, nativeLayout);
 	}
 	}

+ 10 - 5
SBansheeEngine/Source/BsScriptGUIFlexibleSpace.cpp

@@ -19,7 +19,8 @@ namespace BansheeEngine
 
 
 	void ScriptGUIFlexibleSpace::initRuntimeData()
 	void ScriptGUIFlexibleSpace::initRuntimeData()
 	{
 	{
-		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptGUIFlexibleSpace::internal_createInstance);
+		metaData.scriptClass->addInternalCall("Internal_CreateInstanceAdd", &ScriptGUIFlexibleSpace::internal_createInstanceAdd);
+		metaData.scriptClass->addInternalCall("Internal_CreateInstanceInsert", &ScriptGUIFlexibleSpace::internal_createInstanceInsert);
 	}
 	}
 
 
 	void ScriptGUIFlexibleSpace::destroy()
 	void ScriptGUIFlexibleSpace::destroy()
@@ -33,16 +34,20 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
-	void ScriptGUIFlexibleSpace::setParent(GUILayout* parentLayout)
+	void ScriptGUIFlexibleSpace::internal_createInstanceAdd(MonoObject* instance, MonoObject* parentLayout)
 	{
 	{
-		// FlexibleSpace parent is static, so do nothing
+		ScriptGUILayout* scriptLayout = ScriptGUILayout::toNative(parentLayout);
+		GUILayout* nativeLayout = scriptLayout->getInternalValue();
+		GUIFlexibleSpace& space = nativeLayout->addFlexibleSpace();
+
+		ScriptGUIFlexibleSpace* nativeInstance = new (bs_alloc<ScriptGUIFlexibleSpace>()) ScriptGUIFlexibleSpace(instance, space, nativeLayout);
 	}
 	}
 
 
-	void ScriptGUIFlexibleSpace::internal_createInstance(MonoObject* instance, MonoObject* parentLayout)
+	void ScriptGUIFlexibleSpace::internal_createInstanceInsert(MonoObject* instance, MonoObject* parentLayout, UINT32 index)
 	{
 	{
 		ScriptGUILayout* scriptLayout = ScriptGUILayout::toNative(parentLayout);
 		ScriptGUILayout* scriptLayout = ScriptGUILayout::toNative(parentLayout);
 		GUILayout* nativeLayout = scriptLayout->getInternalValue();
 		GUILayout* nativeLayout = scriptLayout->getInternalValue();
-		GUIFlexibleSpace& space = nativeLayout->addFlexibleSpace();
+		GUIFlexibleSpace& space = nativeLayout->insertFlexibleSpace(index);
 
 
 		ScriptGUIFlexibleSpace* nativeInstance = new (bs_alloc<ScriptGUIFlexibleSpace>()) ScriptGUIFlexibleSpace(instance, space, nativeLayout);
 		ScriptGUIFlexibleSpace* nativeInstance = new (bs_alloc<ScriptGUIFlexibleSpace>()) ScriptGUIFlexibleSpace(instance, space, nativeLayout);
 	}
 	}

+ 38 - 9
SBansheeEngine/Source/BsScriptGUILayout.cpp

@@ -20,9 +20,13 @@ namespace BansheeEngine
 	void ScriptGUILayout::initRuntimeData()
 	void ScriptGUILayout::initRuntimeData()
 	{
 	{
 		metaData.scriptClass->addInternalCall("Internal_CreateInstanceXFromArea", &ScriptGUILayout::internal_createInstanceXFromArea);
 		metaData.scriptClass->addInternalCall("Internal_CreateInstanceXFromArea", &ScriptGUILayout::internal_createInstanceXFromArea);
-		metaData.scriptClass->addInternalCall("Internal_CreateInstanceXFromLayout", &ScriptGUILayout::internal_createInstanceXFromLayout);
-		metaData.scriptClass->addInternalCall("Internal_CreateInstanceYFromLayout", &ScriptGUILayout::internal_createInstanceYFromLayout);
+		metaData.scriptClass->addInternalCall("Internal_CreateInstanceXFromLayoutAdd", &ScriptGUILayout::internal_createInstanceXFromLayoutAdd);
+		metaData.scriptClass->addInternalCall("Internal_CreateInstanceYFromLayoutAdd", &ScriptGUILayout::internal_createInstanceYFromLayoutAdd);
+		metaData.scriptClass->addInternalCall("Internal_CreateInstanceXFromLayoutInsert", &ScriptGUILayout::internal_createInstanceXFromLayoutInsert);
+		metaData.scriptClass->addInternalCall("Internal_CreateInstanceYFromLayoutInsert", &ScriptGUILayout::internal_createInstanceYFromLayoutInsert);
 		metaData.scriptClass->addInternalCall("Internal_CreateInstanceYFromScrollArea", &ScriptGUILayout::internal_createInstanceYFromScrollArea);
 		metaData.scriptClass->addInternalCall("Internal_CreateInstanceYFromScrollArea", &ScriptGUILayout::internal_createInstanceYFromScrollArea);
+		metaData.scriptClass->addInternalCall("Internal_AddElement", &ScriptGUILayout::internal_addElement);
+		metaData.scriptClass->addInternalCall("Internal_InsertElement", &ScriptGUILayout::internal_insertElement);
 	}
 	}
 
 
 	void ScriptGUILayout::destroy()
 	void ScriptGUILayout::destroy()
@@ -39,11 +43,6 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
-	void ScriptGUILayout::setParent(GUILayout* parentLayout)
-	{
-		// FixedSpace parent is static, so do nothing
-	}
-
 	void ScriptGUILayout::internal_createInstanceXFromArea(MonoObject* instance, MonoObject* parentArea)
 	void ScriptGUILayout::internal_createInstanceXFromArea(MonoObject* instance, MonoObject* parentArea)
 	{
 	{
 		ScriptGUIArea* scriptArea = ScriptGUIArea::toNative(parentArea);
 		ScriptGUIArea* scriptArea = ScriptGUIArea::toNative(parentArea);
@@ -53,7 +52,7 @@ namespace BansheeEngine
 			ScriptGUILayout(instance, &nativeArea->getLayout(), nullptr);
 			ScriptGUILayout(instance, &nativeArea->getLayout(), nullptr);
 	}
 	}
 
 
-	void ScriptGUILayout::internal_createInstanceXFromLayout(MonoObject* instance, MonoObject* parentLayout)
+	void ScriptGUILayout::internal_createInstanceXFromLayoutAdd(MonoObject* instance, MonoObject* parentLayout)
 	{
 	{
 		ScriptGUILayout* scriptLayout = ScriptGUILayout::toNative(parentLayout);
 		ScriptGUILayout* scriptLayout = ScriptGUILayout::toNative(parentLayout);
 		GUILayout* nativeLayout = scriptLayout->getInternalValue();
 		GUILayout* nativeLayout = scriptLayout->getInternalValue();
@@ -63,7 +62,7 @@ namespace BansheeEngine
 			ScriptGUILayout(instance, &layout, nativeLayout);
 			ScriptGUILayout(instance, &layout, nativeLayout);
 	}
 	}
 
 
-	void ScriptGUILayout::internal_createInstanceYFromLayout(MonoObject* instance, MonoObject* parentLayout)
+	void ScriptGUILayout::internal_createInstanceYFromLayoutAdd(MonoObject* instance, MonoObject* parentLayout)
 	{
 	{
 		ScriptGUILayout* scriptLayout = ScriptGUILayout::toNative(parentLayout);
 		ScriptGUILayout* scriptLayout = ScriptGUILayout::toNative(parentLayout);
 		GUILayout* nativeLayout = scriptLayout->getInternalValue();
 		GUILayout* nativeLayout = scriptLayout->getInternalValue();
@@ -73,6 +72,26 @@ namespace BansheeEngine
 			ScriptGUILayout(instance, &layout, nativeLayout);
 			ScriptGUILayout(instance, &layout, nativeLayout);
 	}
 	}
 
 
+	void ScriptGUILayout::internal_createInstanceXFromLayoutInsert(MonoObject* instance, MonoObject* parentLayout, UINT32 index)
+	{
+		ScriptGUILayout* scriptLayout = ScriptGUILayout::toNative(parentLayout);
+		GUILayout* nativeLayout = scriptLayout->getInternalValue();
+		GUILayout& layout = nativeLayout->insertLayoutX(index);
+
+		ScriptGUILayout* nativeInstance = new (bs_alloc<ScriptGUILayout>())
+			ScriptGUILayout(instance, &layout, nativeLayout);
+	}
+
+	void ScriptGUILayout::internal_createInstanceYFromLayoutInsert(MonoObject* instance, MonoObject* parentLayout, UINT32 index)
+	{
+		ScriptGUILayout* scriptLayout = ScriptGUILayout::toNative(parentLayout);
+		GUILayout* nativeLayout = scriptLayout->getInternalValue();
+		GUILayout& layout = nativeLayout->insertLayoutY(index);
+
+		ScriptGUILayout* nativeInstance = new (bs_alloc<ScriptGUILayout>())
+			ScriptGUILayout(instance, &layout, nativeLayout);
+	}
+
 	void ScriptGUILayout::internal_createInstanceYFromScrollArea(MonoObject* instance, MonoObject* parentScrollArea)
 	void ScriptGUILayout::internal_createInstanceYFromScrollArea(MonoObject* instance, MonoObject* parentScrollArea)
 	{
 	{
 		ScriptGUIScrollArea* scriptScrollArea = ScriptGUIScrollArea::toNative(parentScrollArea);
 		ScriptGUIScrollArea* scriptScrollArea = ScriptGUIScrollArea::toNative(parentScrollArea);
@@ -83,4 +102,14 @@ namespace BansheeEngine
 		ScriptGUILayout* nativeInstance = new (bs_alloc<ScriptGUILayout>()) 
 		ScriptGUILayout* nativeInstance = new (bs_alloc<ScriptGUILayout>()) 
 			ScriptGUILayout(instance, nativeLayout, nativeLayout);
 			ScriptGUILayout(instance, nativeLayout, nativeLayout);
 	}
 	}
+
+	void ScriptGUILayout::internal_addElement(ScriptGUILayout* instance, ScriptGUIElementTBase* element)
+	{
+		instance->getInternalValue()->addElement(static_cast<GUIElement*>(element->getGUIElement()));
+	}
+
+	void ScriptGUILayout::internal_insertElement(ScriptGUILayout* instance, UINT32 index, ScriptGUIElementTBase* element)
+	{
+		instance->getInternalValue()->insertElement(index, static_cast<GUIElement*>(element->getGUIElement()));
+	}
 }
 }