Browse Source

More work on Inspector

Marko Pintera 11 years ago
parent
commit
3540e822e7

+ 59 - 30
Inspector.txt

@@ -29,7 +29,6 @@ Get rid of the CamelotFramework namespace
 Undocking a window wont remove the tabbed title bar
 While dragging an undocked window, dropping it over the main window (not over dock overlays) will not restore it
 
-REFACTOR c++ GUI a bit:
  - GameObjectField
    - When dragging over GameObjectField cursor needs to change depending whether drop will be accepted or not
    - How will I limit it to just certain component types?
@@ -40,30 +39,24 @@ Make a common class for ScriptGUIElement as they all share:
 Add InsertElement to GUILayout
 
 -------------
-Implementation order:
- - Component foldout
- - Color picker modular window
-   - Possibly a generic ModularWindow class
-   - EditorUtility::showColorPicker
- - GameObject/resource field
- - Matrix fields
- - Refactor C# GUI
- - Basic InspectableObject and basic Inspector that open Inspector window, display SceneManager base fields and a list of components
- - Per-component generic and custom inspectors
-
--------------
-IMPORTANT:
- - I should probably consider making each Component part of the inspector its own separate GUIWidget, otherwise I wont
-   be able to use multiple GUIAreas in the Inspectors, which is fairly limiting.
-     - Each has a separate EditorGUI instance?
-
-
-TOMORROW:
- - InspectableObject calls a C++ method which gets all SerializableFields, and C++ in turn
-   generates a list of InspectableFields
-     - They should have a type, name, and get/set methods
-
-Dont forget to implement SceneObject.GetComponents
+Get rid of EditorGUI and GUI classes and instead make them a single class GUIPanel
+ - IMPORANT. Consider replacing InspectorArea with GUIPanels (they internally in C++ are just clipped GUIAreas). This way I have a generic system
+
+IMPLEMENT:
+EditorWindow
+ WindowResized
+ Internal_GetWidth
+ Internal_GetHeight
+ Internal_CreateGUIPanel
+GUIPanel
+ Internal_SetArea
+ Internal_Destroy
+SceneObject
+ GetComponents
+GUIArea
+ SetArea
+Refactor existing ScriptGUI and ScriptEditorGUI and add support for GUIPanel instead
+Remove support for resizable areas
 
 Tab indexes
  - EditorFields should have SetNextField method that allow you to set tab order directly
@@ -98,10 +91,46 @@ UndoRedo
     - but when I click outside maybe I just want to undo to the previous state before I even focused on that text field
       - plus it doesn't make sense for example to undo a text field if I'm currently focusing on something in scene
 
-IMPLEMENTATION
- - Add a Foldout GUI type and its C# version
- - Attempt to display a list of Components on a SceneObject just by using the foldouts
+---------------------------
+
+SerializableObject(object obj)
+ - GetFields()
+
+SerializableField
+ - Type
+ - GetInt/SetInt
+ - GetString/SetString
+ - GetObject/SetObject
+ - GetArray/SetArray
+ - etc.
+
+SerializableArray
+ - GetInt(arrayIdx)/SetInt(arrayIdx)
+ - GetKVP(arrayIdx)/SetKVP(arrayIdx)
+ - etc.
+
+SerializableDictionary
+ - GetInt(key)/SetInt(key)
+ - GetKVP(key)/SetKVP(key)
+ - etc.
+
+----------------
+
+InspectableObject(SerializableObject)
+ - Internally creates a list of InspectorFields (does not initialize any GUI elements)
+ - CreateGUI(GUILayout) <- populates the GUI layout with every InspectorField
+     - For nested objects it creates child layouts and indents them appropriately
+
+InspectorField(SerializableField)
+ - CreateGUI(GUILayout) <- Inserts the corresponding GUI element into the layout
+
+-------------------
 
- - Add basic IntField and hook it up with InspectableField (get/set methods and everything)
+When creating a custom inspector, where will I store InspectorFields? Require user to store them?
+ - I guess. If user doesn't store them they get destructed and upon destruction they remove their GUI element from the layout.
+ - But what happens when Destroy is called? GUI elements get destroyed as normal and InspectorField will need to check for that, in which case it will essentially do nothing.
 
- - Add Multi-rank array, List & Dictionary types
+How do I refresh Inspector fields if source object changes?
+ - Keep all InspectorFields in InspectorManager class, which will call Update on it regularily
+ - If InspectorField GUI elements were destroyed then Update will show a warning
+ - Otherwise you are required to call destroy on an InspectorField to properly remove it

+ 0 - 17
MBansheeEditor/EditorGUI.cs

@@ -1,17 +0,0 @@
-using System.Runtime.CompilerServices;
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    public sealed class EditorGUI : GUIBase
-    {
-        internal EditorGUI(EditorWindow parentWindow)
-        {
-            Internal_CreateInstance(this, parentWindow);
-            Initialize();
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(EditorGUI instance, EditorWindow parentWindow);
-    }
-}

+ 14 - 3
MBansheeEditor/EditorWindow.cs

@@ -9,7 +9,7 @@ namespace BansheeEditor
         internal int width { get { return Internal_GetWidth(); } }
         internal int height { get { return Internal_GetHeight(); } }
 
-        protected EditorGUI GUI;
+        protected GUIPanel GUI;
 
         public static EditorWindow OpenWindow<T>() where T : EditorWindow
         {
@@ -18,17 +18,28 @@ namespace BansheeEditor
 
         protected EditorWindow()
         {
-            GUI = new EditorGUI(this);
+            GUI = CreatePanel(0, 0, width, height);
         }
 
         protected virtual void WindowResized(int width, int height)
         {
-            
+            GUI.SetArea(0, 0, width, height);
+        }
+
+        internal GUIPanel CreatePanel(int x, int y, int width, int height)
+        {
+            GUIPanel newPanel = Internal_CreateGUIPanel(mCachedPtr);
+            newPanel.SetArea(x, y, width, height);
+
+            return newPanel;
         }
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern EditorWindow Internal_CreateOrGetInstance(string ns, string typeName);
 
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern GUIPanel Internal_CreateGUIPanel(IntPtr nativeInstance);
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern int Internal_GetWidth();
 

+ 0 - 11
MBansheeEditor/Inspector/EditorField.cs

@@ -1,11 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace BansheeEditor
-{
-    public class EditorField
-    {
-    }
-}

+ 3 - 1
MBansheeEditor/Inspector/GenericInspector.cs

@@ -10,7 +10,9 @@ namespace BansheeEditor
     {
         internal override void Refresh()
         {
-            throw new NotImplementedException();
+            InspectableObject obj = new InspectableObject(serializableObject);
+
+            obj.CreateGUI(GUI.layout);
         }
 
         internal override int GetOptimalHeight()

+ 0 - 15
MBansheeEditor/Inspector/InspectableArray.cs

@@ -1,15 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace BansheeEditor
-{
-    public class InspectableArray : InspectableObjectBase
-    {
-        public InspectableArray(Array array)
-        {
-            // TODO - Populate "fields" array
-        }
-    }
-}

+ 0 - 65
MBansheeEditor/Inspector/InspectableField.cs

@@ -1,65 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Text;
-
-namespace BansheeEditor
-{
-    public class InspectableField
-    {
-        public enum Type
-        {
-            Int,
-            Float,
-            Bool,
-            String,
-            Color,
-            Vector2,
-            Vector3,
-            Vector4,
-            GameObjectRef,
-            ResourceRef,
-            Object,
-            Array,
-            List,
-            Dictionary
-        }
-
-        private EditorField guiField; // TODO - This will likely be a specific EditorField type, not a generic base one
-        private InspectableObjectBase parent;
-        private Type type;
-
-        // TODO - Add getters/setters for all fields
-        
-        // TODO - Make sure "guiField" is created properly
-
-        public void Refresh()
-        {
-            // TODO - Update "guiField" from the field value by calling "Internal_Get*" method
-        }
-
-        public void Destroy()
-        {
-            // TODO - Called by the parent
-            //  Release "guiField"
-        }
-
-        private void OnValueChangedInt32(Int32 newValue)
-        {
-            // TODO - Callback from "guiField"
-            //  Need separate methods for all types
-            //  Call "Internal_Set*" method to update the actual field
-            //  Register an "Undo" action
-        }
-
-        // TODO - I need a set of these methods for all possible "Type"s
-        //  Internally they should use SerializableField methods for setting/getting values
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetInt32(IntPtr nativeInstance, Int32 value);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern Int32 Internal_GetInt32(IntPtr nativeInstance);
-    }
-}

+ 97 - 3
MBansheeEditor/Inspector/InspectableObject.cs

@@ -2,14 +2,108 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
+using BansheeEngine;
 
 namespace BansheeEditor
 {
-    public class InspectableObject : InspectableObjectBase
+    public sealed class InspectableObject
     {
-        public InspectableObject(object obj)
+        private const int IndentAmount = 15;
+
+        private SerializableObject serializableObject;
+        private SerializableArray serializableArray;
+
+        public InspectableObject(SerializableObject serializableObject)
+        {
+            this.serializableObject = serializableObject;
+        }
+
+        public InspectableObject(SerializableArray serializableArray)
+        {
+            this.serializableArray = serializableArray;
+        }
+
+        public void CreateGUI(GUILayout layout)
+        {
+            if (serializableObject != null)
+            {
+                foreach (var field in serializableObject.fields)
+                {
+                    CreateGUI(layout, field.Name, field.Type, field.GetValue());
+                }
+            }
+            else if (serializableArray != null)
+            {
+                // TODO - Handle multi-rank arrays
+
+                int length = serializableArray.GetDimension(0);
+                for (int i = 0; i < length; i++)
+                {
+                    CreateGUI(layout, i.ToString(), serializableArray.ElementType, serializableArray.GetValue(i));
+                }
+            }
+
+            // TODO - Handle List & Dictionary
+        }
+
+        private void CreateGUI(GUILayout layout, string name, SerializableField.FieldType type, SerializableValue value)
+        {
+            switch (type)
+            {
+                case SerializableField.FieldType.Object:
+                    CreateComplexField(layout, name, type, value);
+                    break;
+                case SerializableField.FieldType.Array:
+                    goto case SerializableField.FieldType.Object;
+                case SerializableField.FieldType.List:
+                    goto case SerializableField.FieldType.Object;
+                case SerializableField.FieldType.Dictionary:
+                    goto case SerializableField.FieldType.Object;
+                default:
+                    CreatePrimitiveField(layout, name, type, value);
+                    break;
+            }
+        }
+
+        private void CreatePrimitiveField(GUILayout layout, string name, SerializableField.FieldType type, SerializableValue value)
         {
-            // TODO - Populate "fields" array
+            layout.AddElement(new GUILabel(name)); // TODO - Use an IntEditorField, or others for other types
+        }
+
+        private void CreateComplexField(GUILayout layout, string name, SerializableField.FieldType type, SerializableValue value)
+        {
+            layout.AddElement(new GUILabel(name)); // TODO - Add foldout and hook up its callbacks
+
+            GUILayout childLayout = layout.AddLayoutX();
+            childLayout.AddSpace(IndentAmount);
+
+            GUILayout childContent = childLayout.AddLayoutY();
+
+            switch (type)
+            {
+                case SerializableField.FieldType.Object:
+                    {
+                        SerializableObject childObj = new SerializableObject(value.GetValue<object>());
+                        InspectableObject childInspectable = new InspectableObject(childObj);
+                        childInspectable.CreateGUI(childContent);
+                    }
+                    break;
+                case SerializableField.FieldType.Array:
+                    {
+                        SerializableArray childArr = new SerializableArray(value.GetValue<object>());
+                        InspectableObject childInspectable = new InspectableObject(childArr);
+                        childInspectable.CreateGUI(childContent);
+                    }
+                    break;
+                case SerializableField.FieldType.List:
+                    // TODO
+                    break;
+                case SerializableField.FieldType.Dictionary:
+                    // TODO
+                    break;
+                default:
+                    throw new Exception("Invalid complex field type.");
+            }
         }
     }
 }

+ 0 - 44
MBansheeEditor/Inspector/InspectableObjectBase.cs

@@ -1,44 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace BansheeEditor
-{
-    public abstract class InspectableObjectBase
-    {
-        private bool _isExpanded = false;
-        private InspectableField[] _fields;
-
-        public bool isExpanded { get { return _isExpanded; } }
-        public InspectableField[] fields { get { return _fields; } }
-
-        public void Expand()
-        {
-            // TODO - Show all child "fields"
-            //  Reposition all visual child elements
-            //  Re-do tab indexes
-            _isExpanded = true;
-        }
-
-        public void Collapse()
-        {
-            // TODO - Hide all child "fields"
-            //  Reposition all visual child elements
-            //  Re-do tab indexes
-            _isExpanded = false;
-        }
-
-        public void Refresh()
-        {
-            for (int i = 0; i < fields.Length; i++)
-                fields[i].Refresh();
-        }
-
-        public void Destroy()
-        {
-            for (int i = 0; i < fields.Length; i++)
-                fields[i].Destroy();
-        }
-    }
-}

+ 0 - 76
MBansheeEditor/Inspector/InspectorArea.cs

@@ -1,76 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    public class InspectorArea
-    {
-        private GUIArea guiArea;
-        private Inspector owner;
-
-        private int parentX, parentY, parentWidth, parentHeight;
-        private int x, y, width, height;
-        private short depth;
-
-        public GUILayout layout
-        {
-            get { return guiArea.layout; }
-        }
-
-        internal InspectorArea(Inspector owner, EditorGUI parentGUI)
-        {
-            this.owner = owner;
-            guiArea = parentGUI.AddArea(0, 0, 0, 0);
-        }
-
-        public void Destroy()
-        {
-            owner.Remove(this);
-
-            guiArea.Destroy();
-        }
-
-        public void SetArea(int x, int y, int width, int height, short depth)
-        {
-            this.x = x;
-            this.y = y;
-            this.width = width;
-            this.height = height;
-            this.depth = depth;
-
-            UpdateGUIArea();
-        }
-
-        internal void SetParentArea(int x, int y, int width, int height)
-        {
-            parentX = x;
-            parentY = y;
-            parentWidth = width;
-            parentHeight = height;
-
-            UpdateGUIArea();
-        }
-
-        private void UpdateGUIArea()
-        {
-            int guiX = parentX + x;
-            int guiY = parentY + y;
-
-            int guiRight = guiX + width;
-            guiRight = MathEx.Min(guiRight, parentX + parentWidth);
-
-            int guiWidth = MathEx.Max(0, guiRight - guiX);
-
-            int guiBottom = guiY + height;
-            guiBottom = MathEx.Min(guiBottom, parentY + parentHeight);
-
-            int guiHeight = MathEx.Max(0, guiBottom - guiY);
-
-            guiArea.SetArea(guiX, guiY, guiWidth, guiHeight, depth);
-        }
-    }
-}

+ 44 - 0
MBansheeEditor/Inspector/SerializableArray.cs

@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BansheeEditor
+{
+    public sealed class SerializableArray
+    {
+        public SerializableArray(object obj)
+        {
+            // TODO - Initialize the array - handle it properly in case obj isn't a valid array
+        }
+
+        public SerializableField.FieldType ElementType;
+        private int[] dimensions;
+        private int rank;
+
+        public int GetDimension(int rank)
+        {
+            return dimensions[rank];
+        }
+
+        public int Rank
+        {
+            get { return rank;  }
+        }
+
+        public SerializableValue GetValue(int id)
+        {
+            return null; // TODO - Return actual SerializableValue
+        }
+
+        // TODO - Add getters/setters for all fields
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetInt32(IntPtr nativeInstance, int arrayIdx, Int32 value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern Int32 Internal_GetInt32(IntPtr nativeInstance, int arrayIdx);
+    }
+}

+ 23 - 0
MBansheeEditor/Inspector/SerializableObject.cs

@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BansheeEditor
+{
+    public sealed class SerializableObject
+    {
+        private SerializableField[] _fields;
+
+        public SerializableObject(object obj)
+        {
+            // TODO - Populate _fields
+        }
+
+        public SerializableField[] fields
+        {
+            get { return _fields; }
+        }
+    }
+}

+ 37 - 0
MBansheeEditor/Inspector/SerializableValue.cs

@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BansheeEditor
+{
+    public sealed class SerializableValue
+    {
+        internal delegate void Setter(object value);
+        internal delegate object Getter();
+
+        private Setter setter;
+        private Getter getter;
+
+        internal SerializableValue(Setter setter, Getter getter)
+        {
+            this.setter = setter;
+            this.getter = getter;
+        }
+
+        public T GetValue<T>()
+        {
+            // TODO - Check for valid type?
+
+            return (T) getter();
+        }
+
+        public void SetValue<T>(T value)
+        {
+            // TODO - Check for valid type?
+
+            setter(value);
+        }
+    }
+}

+ 4 - 6
MBansheeEditor/MBansheeEditor.csproj

@@ -42,18 +42,16 @@
     <Compile Include="DbgCustomInspector.cs" />
     <Compile Include="DbgEditorWindow.cs" />
     <Compile Include="EditorApplication.cs" />
-    <Compile Include="EditorGUI.cs" />
     <Compile Include="EditorWindow.cs" />
     <Compile Include="Inspector\CustomInspector.cs" />
-    <Compile Include="Inspector\EditorField.cs" />
     <Compile Include="Inspector\GenericInspector.cs" />
-    <Compile Include="Inspector\InspectableArray.cs" />
-    <Compile Include="Inspector\InspectableField.cs" />
+    <Compile Include="Inspector\SerializableArray.cs" />
+    <Compile Include="Inspector\SerializableField.cs" />
     <Compile Include="Inspector\InspectableObject.cs" />
-    <Compile Include="Inspector\InspectableObjectBase.cs" />
     <Compile Include="Inspector\Inspector.cs" />
-    <Compile Include="Inspector\InspectorArea.cs" />
     <Compile Include="Inspector\InspectorWindow.cs" />
+    <Compile Include="Inspector\SerializableObject.cs" />
+    <Compile Include="Inspector\SerializableValue.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>

+ 0 - 38
MBansheeEngine/GUI/GUI.cs

@@ -1,38 +0,0 @@
-using System;
-using System.Runtime.CompilerServices;
-
-namespace BansheeEngine
-{
-    public sealed class GUI : GUIBase
-    {
-        private static GUI instance = new GUI();
-
-        internal GUI()
-        {
-            Internal_CreateInstance(this);
-        }
-
-        public new static GUIArea AddArea(int x, int y, int width = 0, int height = 0, short depth = 0)
-        {
-            return ((GUIBase)instance).AddArea(x, y, width, height, depth);
-        }
-
-        public new static GUIArea AddResizableAreaX(int offsetLeft, int offsetRight, int offsetTop, int height, short depth = 0)
-        {
-            return ((GUIBase)instance).AddResizableAreaX(offsetLeft, offsetRight, offsetTop, height, depth);
-        }
-
-        public new static GUIArea AddResizableAreaY(int offsetTop, int offsetBottom, int offsetLeft, int width, short depth = 0)
-        {
-            return ((GUIBase)instance).AddResizableAreaY(offsetTop, offsetBottom, offsetLeft, width, depth);
-        }
-
-        public new static GUIArea AddResizableAreaXY(int offsetLeft, int offsetRight, int offsetTop, int offsetBottom, short depth = 0)
-        {
-            return ((GUIBase)instance).AddResizableAreaXY(offsetLeft, offsetRight, offsetTop, offsetBottom, depth);
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(GUI instance);
-    }
-}

+ 10 - 10
MBansheeEngine/GUI/GUIArea.cs

@@ -6,7 +6,7 @@ namespace BansheeEngine
     public sealed class GUIArea : ScriptObject
     {
         private GUILayout _layout;
-        private GUIBase parent;
+        private GUIPanel parent;
         private bool isDestroyed;
 
         public GUILayout layout
@@ -17,7 +17,7 @@ namespace BansheeEngine
         internal GUIArea()
         { }
 
-        internal void SetParent(GUIBase parent)
+        internal void SetParent(GUIPanel parent)
         {
             if (this.parent != null)
                 this.parent.childAreas.Remove(this);
@@ -27,7 +27,7 @@ namespace BansheeEngine
             parent.childAreas.Add(this);
         }
 
-        internal static GUIArea Create(GUIBase parent, int x, int y, int width, int height, short depth)
+        internal static GUIArea Create(GUIPanel parent, int x, int y, int width, int height, short depth)
         {
             GUIArea newArea = new GUIArea();
             Internal_CreateInstance(newArea, parent, x, y, width, height, depth);
@@ -36,7 +36,7 @@ namespace BansheeEngine
             return newArea;
         }
 
-        internal static GUIArea CreateResizableX(GUIBase parent, int offsetLeft, int offsetRight, int offsetTop, int height, short depth)
+        internal static GUIArea CreateResizableX(GUIPanel parent, int offsetLeft, int offsetRight, int offsetTop, int height, short depth)
         {
             GUIArea newArea = new GUIArea();
             Internal_CreateInstanceResizableX(newArea, parent, offsetLeft, offsetRight, offsetTop, height, depth);
@@ -45,7 +45,7 @@ namespace BansheeEngine
             return newArea;
         }
 
-        internal static GUIArea CreateResizableY(GUIBase parent, int offsetTop, int offsetBottom, int offsetLeft, int width, short depth)
+        internal static GUIArea CreateResizableY(GUIPanel parent, int offsetTop, int offsetBottom, int offsetLeft, int width, short depth)
         {
             GUIArea newArea = new GUIArea();
             Internal_CreateInstanceResizableY(newArea, parent, offsetTop, offsetBottom, offsetLeft, width, depth);
@@ -54,7 +54,7 @@ namespace BansheeEngine
             return newArea;
         }
 
-        internal static GUIArea CreateResizableXY(GUIBase parent, int offsetLeft, int offsetRight, int offsetTop, int offsetBottom, short depth)
+        internal static GUIArea CreateResizableXY(GUIPanel parent, int offsetLeft, int offsetRight, int offsetTop, int offsetBottom, short depth)
         {
             GUIArea newArea = new GUIArea();
             Internal_CreateInstanceResizableXY(newArea, parent, offsetLeft, offsetRight, offsetTop, offsetBottom, depth);
@@ -88,18 +88,18 @@ namespace BansheeEngine
         }
 
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(GUIArea instance, GUIBase parent, int x, int y, int width, int height, short depth);
+        private static extern void Internal_CreateInstance(GUIArea instance, GUIPanel parent, int x, int y, int width, int height, short depth);
 
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstanceResizableX(GUIArea instance, GUIBase parent, int offsetLeft, int offsetRight, int offsetTop, 
+        private static extern void Internal_CreateInstanceResizableX(GUIArea instance, GUIPanel parent, int offsetLeft, int offsetRight, int offsetTop, 
             int height, short depth);
 
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstanceResizableY(GUIArea instance, GUIBase parent, int offsetTop, int offsetBottom, int offsetLeft,
+        private static extern void Internal_CreateInstanceResizableY(GUIArea instance, GUIPanel parent, int offsetTop, int offsetBottom, int offsetLeft,
             int width, short depth);
 
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstanceResizableXY(GUIArea instance, GUIBase parent, int offsetLeft, int offsetRight, int offsetTop,
+        private static extern void Internal_CreateInstanceResizableXY(GUIArea instance, GUIPanel parent, int offsetLeft, int offsetRight, int offsetTop,
             int offsetBottom, short depth);
 
         [MethodImpl(MethodImplOptions.InternalCall)]

+ 0 - 71
MBansheeEngine/GUI/GUIBase.cs

@@ -1,71 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-
-namespace BansheeEngine
-{
-    public abstract class GUIBase : ScriptObject
-    {
-        private GUIArea mainArea;
-        private GUILayout _mainLayout;
-
-        internal List<GUIArea> childAreas = new List<GUIArea>();
-
-        public GUILayout layout
-        {
-            get { return _mainLayout; }
-        }
-
-        public GUISkin skin; // TODO
-
-        internal GUIBase()
-        { }
-
-        ~GUIBase()
-        {
-            GUIArea[] childArray = childAreas.ToArray(); // Iterating over it will modify it so make a copy
-            for (int i = 0; i < childArray.Length; i++)
-                childArray[i].Destroy();
-
-            childAreas.Clear();
-        }
-
-        internal void Initialize()
-        {
-            mainArea = AddResizableAreaXY(0, 0, 0, 0);
-            _mainLayout = mainArea.layout;
-        }
-
-        public GUIArea AddArea(int x, int y, int width, int height, short depth = 0)
-        {
-            GUIArea area = GUIArea.Create(this, x, y, width, height, depth);
-            area.SetParent(this);
-
-            return area;
-        }
-
-        public GUIArea AddResizableAreaX(int offsetLeft, int offsetRight, int offsetTop, int height, short depth = 0)
-        {
-            GUIArea area = GUIArea.CreateResizableX(this, offsetLeft, offsetRight, offsetTop, height, depth);
-            area.SetParent(this);
-
-            return area;
-        }
-
-        public GUIArea AddResizableAreaY(int offsetTop, int offsetBottom, int offsetLeft, int width, short depth = 0)
-        {
-            GUIArea area = GUIArea.CreateResizableY(this, offsetTop, offsetBottom, offsetLeft, width, depth);
-            area.SetParent(this);
-
-            return area;
-        }
-
-        public GUIArea AddResizableAreaXY(int offsetLeft, int offsetRight, int offsetTop, int offsetBottom, short depth = 0)
-        {
-            GUIArea area = GUIArea.CreateResizableXY(this, offsetLeft, offsetRight, offsetTop, offsetBottom, depth);
-            area.SetParent(this);
-
-            return area;
-        }
-    }
-}

+ 5 - 0
MBansheeEngine/GUI/GUILabel.cs

@@ -10,6 +10,11 @@ namespace BansheeEngine
             Internal_CreateInstance(this, content, style, options);
         }
 
+        public GUILabel(GUIContent content, string style = "")
+        {
+            Internal_CreateInstance(this, content, style, new GUIOption[0]);
+        }
+
         public void SetContent(GUIContent content)
         {
             Internal_SetContent(mCachedPtr, content);

+ 76 - 0
MBansheeEngine/GUI/GUIPanel.cs

@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace BansheeEngine
+{
+    public sealed class GUIPanel : ScriptObject
+    {
+        private GUIArea mainArea;
+        private GUILayout _mainLayout;
+
+        internal List<GUIArea> childAreas = new List<GUIArea>();
+
+        public GUILayout layout
+        {
+            get { return _mainLayout; }
+        }
+
+        public GUISkin skin; // TODO
+
+        internal GUIPanel()
+        {
+            Internal_CreateInstance(this);
+        }
+
+        ~GUIPanel()
+        {
+            GUIArea[] childArray = childAreas.ToArray(); // Iterating over it will modify it so make a copy
+            for (int i = 0; i < childArray.Length; i++)
+                childArray[i].Destroy();
+
+            childAreas.Clear();
+        }
+
+        internal void Initialize()
+        {
+            mainArea = AddArea(0, 0, 0, 0);
+            _mainLayout = mainArea.layout;
+        }
+
+        public GUIArea AddArea(int x, int y, int width, int height, short depth = 0)
+        {
+            GUIArea area = GUIArea.Create(this, x, y, width, height, depth);
+            area.SetParent(this);
+
+            return area;
+        }
+
+        internal void SetArea(int x, int y, int width, int height)
+        {
+            Internal_SetArea(x, y, width, height);
+
+            mainArea.SetArea(x, y, width, height);
+        }
+
+        internal void Destroy()
+        {
+            GUIArea[] tempAreas = childAreas.ToArray();
+            for (int i = 0; i < tempAreas.Length; i++)
+                tempAreas[i].Destroy();
+
+            childAreas.Clear();
+
+            Internal_Destroy(mCachedPtr);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetArea(int x, int y, int width, int height);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(GUIPanel instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Destroy(IntPtr nativeInstance);
+    }
+}

+ 1 - 2
MBansheeEngine/MBansheeEngine.csproj

@@ -53,9 +53,8 @@
     <Compile Include="DontSerializeField.cs" />
     <Compile Include="Font.cs" />
     <Compile Include="GameObject.cs" />
-    <Compile Include="GUI\GUI.cs" />
     <Compile Include="GUI\GUIArea.cs" />
-    <Compile Include="GUI\GUIBase.cs" />
+    <Compile Include="GUI\GUIPanel.cs" />
     <Compile Include="GUI\GUIButton.cs" />
     <Compile Include="GUI\GUIContent.cs" />
     <Compile Include="GUI\GUIElement.cs" />