Started implementation of the Control Centre.
Started implementation of the Control Centre.

--- a/Documents/CHANGES.txt
+++ b/Documents/CHANGES.txt
@@ -1,23 +1,23 @@
 1.0.9.0
-	Added: Build Engineer now also implements the '\' backslash show/hide shortcut.
-	Added: New readouts to the vessel category:
-		- Current Stage DeltaV
-		- Surface Thrust to Weight Ratio
+    Added: Build Engineer now also implements the '\' backslash show/hide shortcut.
+    Added: New readouts to the vessel category:
+        - Current Stage DeltaV
+        - Surface Thrust to Weight Ratio
 
-	Added: New editor overlay system.
-		- Sleeker design.
-		- Hover over part information options:
-			- Name only
-			- Middle click to show
-			- Always show
-		- Slide out overlay displays:
-			- Vessel information
-			- Resources list
+    Added: New editor overlay system.
+        - Sleeker design.
+        - Hover over part information options:
+            - Name only
+            - Middle click to show
+            - Always show
+        - Slide out overlay displays:
+            - Vessel information
+            - Resources list
 
-	Fixed: Cost calculation now works with mods implementing IPartCostModifier.
+    Fixed: Cost calculation now works with mods implementing IPartCostModifier.
 
 1.0.8.1
-	Fixed: Bug which caused rendezvous readouts to freeze the game or show all zeros.
+    Fixed: Bug which caused rendezvous readouts to freeze the game or show all zeros.
 
 1.0.8.0
     Added: New readouts to the vessel category:

--- /dev/null
+++ b/KerbalEngineer/Control/ControlCentre.cs
@@ -1,1 +1,245 @@
-
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
+
+#region Using Directives
+
+using System;
+using System.Collections.Generic;
+
+using KerbalEngineer.Control.Panels;
+
+using UnityEngine;
+
+#endregion
+
+namespace KerbalEngineer.Control
+{
+    [KSPAddon(KSPAddon.Startup.Instantly, false)]
+    public class ControlCentre : MonoBehaviour
+    {
+        #region Fields
+
+        private static readonly List<IControlPanel> panels = new List<IControlPanel>();
+
+        private static GUIStyle button;
+        private static ControlCentre instance;
+        private static GUIStyle label;
+        private static GUIStyle title;
+
+        private Vector2 contentsScrollPosition;
+        private GUIStyle panelSelectorStyle;
+        private Rect position = new Rect(Screen.width, Screen.height, 900.0f, 500.0f);
+        private IControlPanel selectedPanel;
+        private bool shouldCentre = true;
+
+        #endregion
+
+        #region Properties
+
+        public static GUIStyle Button
+        {
+            get
+            {
+                return button ?? (button = new GUIStyle(HighLogic.Skin.button)
+                {
+                    normal =
+                    {
+                        textColor = Color.white
+                    },
+                    fixedHeight = 30.0f
+                });
+            }
+        }
+
+        public static bool Enabled
+        {
+            get { return instance.enabled; }
+            set { instance.enabled = value; }
+        }
+
+        public static GUIStyle Label
+        {
+            get
+            {
+                return label ?? (label = new GUIStyle(HighLogic.Skin.label)
+                {
+                    normal =
+                    {
+                        textColor = Color.white
+                    },
+                    fontStyle = FontStyle.Bold,
+                    fixedHeight = 30.0f,
+                    alignment = TextAnchor.MiddleLeft,
+                    stretchWidth = true,
+                });
+            }
+        }
+
+        public static List<IControlPanel> Panels
+        {
+            get { return panels; }
+        }
+
+        public static GUIStyle Title
+        {
+            get
+            {
+                return title ?? (title = new GUIStyle(HighLogic.Skin.label)
+                {
+                    normal =
+                    {
+                        textColor = Color.white
+                    },
+                    fontSize = 26,
+                    fontStyle = FontStyle.Bold,
+                    alignment = TextAnchor.UpperCenter,
+                    stretchWidth = true,
+                });
+            }
+        }
+
+        #endregion
+
+        #region Methods: protected
+
+        protected void Awake()
+        {
+            try
+            {
+                if (instance == null)
+                {
+                    DontDestroyOnLoad(this);
+                    instance = this;
+                    this.enabled = true;
+                    return;
+                }
+                Destroy(this);
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        protected void OnGUI()
+        {
+            try
+            {
+                GUI.skin = null;
+                this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, "KERBAL ENGINEER REDUX " + EngineerGlobals.AssemblyVersion + " - CONTROL CENTRE", HighLogic.Skin.window);
+                this.CentreWindow();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        protected void Start()
+        {
+            try
+            {
+                this.InitialiseStyles();
+                LoadPanels();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        #endregion
+
+        #region Methods: private
+
+        private static void LoadPanels()
+        {
+            panels.Add(new BuildEngineerPanel());
+            panels.Add(new BuildOverlayPanel());
+        }
+
+        private void CentreWindow()
+        {
+            if (this.shouldCentre && this.position.width > 0.0f && this.position.height > 0.0f)
+            {
+                this.position.center = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f);
+                this.shouldCentre = false;
+            }
+        }
+
+        private void DrawContents()
+        {
+            GUI.skin = HighLogic.Skin;
+            this.contentsScrollPosition = GUILayout.BeginScrollView(this.contentsScrollPosition, false, true);
+            GUI.skin = null;
+
+            if (this.selectedPanel != null)
+            {
+                this.selectedPanel.Draw();
+            }
+
+            GUILayout.FlexibleSpace();
+            GUILayout.EndScrollView();
+        }
+
+        private void DrawSelectors()
+        {
+            GUILayout.BeginVertical(HighLogic.Skin.box, GUILayout.Width(225.0f));
+            foreach (var panel in panels)
+            {
+                if (GUILayout.Toggle(this.selectedPanel == panel, panel.Name, this.panelSelectorStyle))
+                {
+                    this.selectedPanel = panel;
+                }
+            }
+            GUILayout.FlexibleSpace();
+            if (GUILayout.Button("CLOSE", Button))
+            {
+                this.enabled = false;
+            }
+            GUILayout.EndVertical();
+        }
+
+        private void InitialiseStyles()
+        {
+            this.panelSelectorStyle = new GUIStyle(Button)
+            {
+                fontSize = 16,
+                fixedHeight = 40.0f
+            };
+        }
+
+        private void Window(int windowId)
+        {
+            try
+            {
+                GUILayout.BeginHorizontal();
+                this.DrawSelectors();
+                this.DrawContents();
+                GUILayout.EndHorizontal();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        #endregion
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/Control/IControlPanel.cs
@@ -1,1 +1,36 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+namespace KerbalEngineer.Control
+{
+    public interface IControlPanel
+    {
+        #region Properties
+
+        string Name { get; }
+
+        #endregion
+
+        #region Methods: public
+
+        void Draw();
+
+        #endregion
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/Control/Panels/BuildEngineerPanel.cs
@@ -1,1 +1,39 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+namespace KerbalEngineer.Control.Panels
+{
+    public class BuildEngineerPanel : IControlPanel
+    {
+        #region Properties
+
+        public string Name
+        {
+            get { return "Build Engineer"; }
+        }
+
+        #endregion
+
+        #region Methods: public
+
+        public void Draw() { }
+
+        #endregion
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/Control/Panels/BuildOverlayPanel.cs
@@ -1,1 +1,84 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+#region Using Directives
+
+using KerbalEngineer.Editor;
+
+using UnityEngine;
+
+#endregion
+
+namespace KerbalEngineer.Control.Panels
+{
+    public class BuildOverlayPanel : IControlPanel
+    {
+        #region Properties
+
+        public string Name
+        {
+            get { return "Build Overlay"; }
+        }
+
+        #endregion
+
+        #region Methods: public
+
+        public void Draw()
+        {
+            GUILayout.Label("Build Overlay", ControlCentre.Title);
+            DrawPartInfo();
+            GUILayout.Space(10.0f);
+            DrawDisplays();
+        }
+
+        #endregion
+
+        #region Methods: private
+
+        private static void DrawPartInfo()
+        {
+            GUILayout.Label("Part Information (Hover Tooltips)", ControlCentre.Label);
+            GUILayout.BeginHorizontal();
+            BuildOverlayPartInfo.Visible = GUILayout.Toggle(BuildOverlayPartInfo.Visible, "Visible", ControlCentre.Button, GUILayout.Width(150.0f));
+            if (BuildOverlayPartInfo.Visible)
+            {
+                BuildOverlayPartInfo.NamesOnly = GUILayout.Toggle(BuildOverlayPartInfo.NamesOnly, "Show Names Only", ControlCentre.Button, GUILayout.Width(150.0f));
+                if (!BuildOverlayPartInfo.NamesOnly)
+                {
+                    BuildOverlayPartInfo.ClickToOpen = GUILayout.Toggle(BuildOverlayPartInfo.ClickToOpen, "Click To Open", ControlCentre.Button, GUILayout.Width(150.0f));
+                }
+            }
+            
+            
+            GUILayout.EndHorizontal();
+        }
+
+        private static void DrawDisplays()
+        {
+            GUILayout.Label("Informational Displays", ControlCentre.Label);
+            GUILayout.BeginHorizontal();
+            BuildOverlayVessel.Visible = GUILayout.Toggle(BuildOverlayVessel.Visible, "Vessel Details", ControlCentre.Button, GUILayout.Width(150.0f));
+            BuildOverlayResources.Visible = GUILayout.Toggle(BuildOverlayResources.Visible, "Resources List", ControlCentre.Button, GUILayout.Width(150.0f));
+            GUILayout.EndHorizontal();
+        }
+
+        #endregion
+    }
+}

--- a/KerbalEngineer/Editor/BuildAdvanced.cs
+++ b/KerbalEngineer/Editor/BuildAdvanced.cs
@@ -285,13 +285,13 @@
             if ((this.position.MouseIsOver() || this.bodiesList.Position.MouseIsOver()) && !this.isEditorLocked)
             {
                 EditorLogic.fetch.Lock(true, true, true, "KER_BuildAdvanced");
-                BuildOverlay.BuildOverlayPartInfo.Hidden = true;
+                BuildOverlayPartInfo.Hidden = true;
                 this.isEditorLocked = true;
             }
             else if (!this.position.MouseIsOver() && !this.bodiesList.Position.MouseIsOver() && this.isEditorLocked)
             {
                 EditorLogic.fetch.Unlock("KER_BuildAdvanced");
-                BuildOverlay.BuildOverlayPartInfo.Hidden = false;
+                BuildOverlayPartInfo.Hidden = false;
                 this.isEditorLocked = false;
             }
         }
@@ -477,8 +477,8 @@
             GUILayout.BeginHorizontal();
             GUILayout.Label("Build Engineer Overlay:", this.settingStyle);
             BuildOverlay.Visible = GUILayout.Toggle(BuildOverlay.Visible, "VISIBLE", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
-            BuildOverlay.BuildOverlayPartInfo.NamesOnly = GUILayout.Toggle(BuildOverlay.BuildOverlayPartInfo.NamesOnly, "NAMES ONLY", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
-            BuildOverlay.BuildOverlayPartInfo.ClickToOpen = GUILayout.Toggle(BuildOverlay.BuildOverlayPartInfo.ClickToOpen, "CLICK TO OPEN", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            BuildOverlayPartInfo.NamesOnly = GUILayout.Toggle(BuildOverlayPartInfo.NamesOnly, "NAMES ONLY", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+            BuildOverlayPartInfo.ClickToOpen = GUILayout.Toggle(BuildOverlayPartInfo.ClickToOpen, "CLICK TO OPEN", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
             GUILayout.EndHorizontal();
 
             GUILayout.BeginHorizontal();

--- a/KerbalEngineer/Editor/BuildOverlay.cs
+++ b/KerbalEngineer/Editor/BuildOverlay.cs
@@ -35,6 +35,9 @@
     {
         #region Fields
 
+        private static BuildOverlayPartInfo buildOverlayPartInfo;
+        private static BuildOverlayResources buildOverlayResources;
+        private static BuildOverlayVessel buildOverlayVessel;
         private static BuildOverlay instance;
 
         private static float minimumWidth = 200.0f;
@@ -43,30 +46,25 @@
         private static GUIStyle tabStyle;
         private static GUIStyle titleStyle;
         private static GUIStyle valueStyle;
-        private static bool visible = true;
         private static GUIStyle windowStyle;
 
-        private BuildOverlayPartInfo buildOverlayPartInfo;
-        private BuildOverlayResources buildOverlayResources;
-        private BuildOverlayVessel buildOverlayVessel;
-
         #endregion
 
         #region Properties
 
         public static BuildOverlayPartInfo BuildOverlayPartInfo
         {
-            get { return instance.buildOverlayPartInfo; }
+            get { return buildOverlayPartInfo; }
         }
 
         public static BuildOverlayResources BuildOverlayResources
         {
-            get { return instance.buildOverlayResources; }
+            get { return buildOverlayResources; }
         }
 
         public static BuildOverlayVessel BuildOverlayVessel
         {
-            get { return instance.buildOverlayVessel; }
+            get { return buildOverlayVessel; }
         }
 
         public static float MinimumWidth
@@ -172,8 +170,8 @@
 
         public static bool Visible
         {
-            get { return visible; }
-            set { visible = value; }
+            get { return BuildOverlayPartInfo.Visible && BuildOverlayVessel.Visible && BuildOverlayResources.Visible; }
+            set { BuildOverlayPartInfo.Visible = BuildOverlayVessel.Visible = BuildOverlayResources.Visible = value; }
         }
 
         public static GUIStyle WindowStyle
@@ -198,22 +196,22 @@
         public static void Load()
         {
             var handler = SettingHandler.Load("BuildOverlay.xml");
-            handler.GetSet("visible", visible);
-            instance.buildOverlayPartInfo.NamesOnly = handler.GetSet("namesOnly", instance.buildOverlayPartInfo.NamesOnly);
-            instance.buildOverlayPartInfo.ClickToOpen = handler.GetSet("clickToOpen", instance.buildOverlayPartInfo.ClickToOpen);
-            instance.buildOverlayVessel.Open = handler.GetSet("vesselOpen", instance.buildOverlayVessel.Open);
-            instance.buildOverlayResources.Open = handler.GetSet("resourcesOpen", instance.buildOverlayResources.Open);
+            handler.GetSet("visible", Visible);
+            BuildOverlayPartInfo.NamesOnly = handler.GetSet("namesOnly", BuildOverlayPartInfo.NamesOnly);
+            BuildOverlayPartInfo.ClickToOpen = handler.GetSet("clickToOpen", BuildOverlayPartInfo.ClickToOpen);
+            buildOverlayVessel.Open = handler.GetSet("vesselOpen", buildOverlayVessel.Open);
+            buildOverlayResources.Open = handler.GetSet("resourcesOpen", buildOverlayResources.Open);
             handler.Save("BuildOverlay.xml");
         }
 
         public static void Save()
         {
             var handler = SettingHandler.Load("BuildOverlay.xml");
-            handler.Set("visible", visible);
-            handler.Set("namesOnly", instance.buildOverlayPartInfo.NamesOnly);
-            handler.Set("clickToOpen", instance.buildOverlayPartInfo.ClickToOpen);
-            handler.Set("vesselOpen", instance.buildOverlayVessel.Open);
-            handler.Set("resourcesOpen", instance.buildOverlayResources.Open);
+            handler.Set("visible", Visible);
+            handler.Set("namesOnly", BuildOverlayPartInfo.NamesOnly);
+            handler.Set("clickToOpen", BuildOverlayPartInfo.ClickToOpen);
+            handler.Set("vesselOpen", buildOverlayVessel.Open);
+            handler.Set("resourcesOpen", buildOverlayResources.Open);
             handler.Save("BuildOverlay.xml");
         }
 
@@ -231,9 +229,9 @@
                     return;
                 }
                 instance = this;
-                this.buildOverlayPartInfo = this.gameObject.AddComponent<BuildOverlayPartInfo>();
-                this.buildOverlayVessel = this.gameObject.AddComponent<BuildOverlayVessel>();
-                this.buildOverlayResources = this.gameObject.AddComponent<BuildOverlayResources>();
+                buildOverlayPartInfo = this.gameObject.AddComponent<BuildOverlayPartInfo>();
+                buildOverlayVessel = this.gameObject.AddComponent<BuildOverlayVessel>();
+                buildOverlayResources = this.gameObject.AddComponent<BuildOverlayResources>();
                 Load();
             }
             catch (Exception ex)
@@ -247,17 +245,17 @@
             try
             {
                 Save();
-                if (this.buildOverlayPartInfo != null)
-                {
-                    Destroy(this.buildOverlayPartInfo);
-                }
-                if (this.buildOverlayVessel != null)
-                {
-                    Destroy(this.buildOverlayVessel);
-                }
-                if (this.buildOverlayResources != null)
-                {
-                    Destroy(this.buildOverlayResources);
+                if (buildOverlayPartInfo != null)
+                {
+                    Destroy(buildOverlayPartInfo);
+                }
+                if (buildOverlayVessel != null)
+                {
+                    Destroy(buildOverlayVessel);
+                }
+                if (buildOverlayResources != null)
+                {
+                    Destroy(buildOverlayResources);
                 }
             }
             catch (Exception ex)

--- a/KerbalEngineer/Editor/BuildOverlayPartInfo.cs
+++ b/KerbalEngineer/Editor/BuildOverlayPartInfo.cs
@@ -36,9 +36,11 @@
     {
         #region Fields
 
+        private static bool clickToOpen = true;
+        private static bool namesOnly;
+        private static bool visible = true;
+
         private readonly List<PartInfoItem> infoItems = new List<PartInfoItem>();
-        private bool clickToOpen = true;
-        private bool namesOnly;
 
         private Rect position;
         private Part selectedPart;
@@ -48,18 +50,24 @@
 
         #region Properties
 
-        public bool ClickToOpen
-        {
-            get { return this.clickToOpen; }
-            set { this.clickToOpen = value; }
-        }
-
-        public bool Hidden { get; set; }
-
-        public bool NamesOnly
-        {
-            get { return this.namesOnly; }
-            set { this.namesOnly = value; }
+        public static bool ClickToOpen
+        {
+            get { return clickToOpen; }
+            set { clickToOpen = value; }
+        }
+
+        public static bool Hidden { get; set; }
+
+        public static bool NamesOnly
+        {
+            get { return namesOnly; }
+            set { namesOnly = value; }
+        }
+
+        public static bool Visible
+        {
+            get { return visible; }
+            set { visible = value; }
         }
 
         #endregion
@@ -70,7 +78,7 @@
         {
             try
             {
-                if (!BuildOverlay.Visible || this.Hidden || this.selectedPart == null)
+                if (!Visible || Hidden || this.selectedPart == null)
                 {
                     return;
                 }
@@ -88,7 +96,7 @@
         {
             try
             {
-                if (!BuildOverlay.Visible || this.Hidden || EditorLogic.startPod == null)
+                if (!Visible || Hidden || EditorLogic.startPod == null)
                 {
                     return;
                 }
@@ -113,7 +121,7 @@
                         this.selectedPart = part;
                         this.ResetInfo();
                     }
-                    if (this.NamesOnly)
+                    if (NamesOnly)
                     {
                         return;
                     }
@@ -140,7 +148,7 @@
                     {
                         this.showInfo = true;
                     }
-                    else if (this.ClickToOpen && this.showInfo && Input.GetMouseButtonDown(2))
+                    else if (ClickToOpen && this.showInfo && Input.GetMouseButtonDown(2))
                     {
                         this.ResetInfo();
                     }
@@ -162,8 +170,8 @@
 
         private void ResetInfo()
         {
-            this.showInfo = !this.clickToOpen;
-            this.position.width = this.namesOnly || this.clickToOpen ? 0.0f : 200.0f;
+            this.showInfo = !clickToOpen;
+            this.position.width = namesOnly || clickToOpen ? 0.0f : 200.0f;
             this.position.height = 0.0f;
         }
 
@@ -425,7 +433,7 @@
                         GUILayout.EndHorizontal();
                     }
                 }
-                else if (!this.NamesOnly)
+                else if (!NamesOnly)
                 {
                     GUILayout.Space(2.0f);
                     GUILayout.Label("Click middle mouse to show more info...", BuildOverlay.NameStyle);

--- a/KerbalEngineer/Editor/BuildOverlayResources.cs
+++ b/KerbalEngineer/Editor/BuildOverlayResources.cs
@@ -35,7 +35,10 @@
     {
         #region Fields
 
+        private static bool visible = true;
+
         private readonly Dictionary<int, ResourceInfoItem> resources = new Dictionary<int, ResourceInfoItem>();
+
         private bool open = true;
         private float openPercent;
         private GUIContent tabContent;
@@ -46,6 +49,12 @@
         #endregion
 
         #region Properties
+
+        public static bool Visible
+        {
+            get { return visible; }
+            set { visible = value; }
+        }
 
         public bool Open
         {

--- a/KerbalEngineer/Editor/BuildOverlayVessel.cs
+++ b/KerbalEngineer/Editor/BuildOverlayVessel.cs
@@ -34,6 +34,8 @@
     public class BuildOverlayVessel : MonoBehaviour
     {
         #region Fields
+
+        private static bool visible = true;
 
         private readonly List<PartInfoItem> infoItems = new List<PartInfoItem>();
 
@@ -49,6 +51,12 @@
 
         #region Properties
 
+        public static bool Visible
+        {
+            get { return visible; }
+            set { visible = value; }
+        }
+
         public bool Open
         {
             get { return this.open; }
@@ -68,7 +76,7 @@
         {
             try
             {
-                if (!BuildOverlay.Visible || EditorLogic.startPod == null || this.lastStage == null)
+                if (!Visible || EditorLogic.startPod == null || this.lastStage == null)
                 {
                     return;
                 }
@@ -100,7 +108,7 @@
 
         protected void Update()
         {
-            if (!BuildOverlay.Visible || EditorLogic.startPod == null)
+            if (!Visible || EditorLogic.startPod == null)
             {
                 return;
             }

--- a/KerbalEngineer/KerbalEngineer.csproj
+++ b/KerbalEngineer/KerbalEngineer.csproj
@@ -56,6 +56,9 @@
     </Reference>
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Control\IControlPanel.cs" />
+    <Compile Include="Control\Panels\BuildOverlayPanel.cs" />
+    <Compile Include="Control\Panels\BuildEngineerPanel.cs" />
     <Compile Include="Editor\BuildAdvanced.cs" />
     <Compile Include="Editor\BuildOverlay.cs" />
     <Compile Include="CelestialBodies.cs" />
@@ -108,6 +111,7 @@
     <Compile Include="Helpers\Units.cs" />
     <Compile Include="Helpers\TimeFormatter.cs" />
     <Compile Include="KeyBinder.cs" />
+    <Compile Include="Control\ControlCentre.cs" />
     <Compile Include="UIControls\DropDown.cs" />
     <Compile Include="Logger.cs" />
     <Compile Include="EngineerGlobals.cs" />
@@ -180,6 +184,7 @@
     <Compile Include="Settings\SettingHandler.cs" />
     <Compile Include="Settings\SettingItem.cs" />
     <Compile Include="TapeDriveAnimator.cs" />
+    <Compile Include="UIControls\WindowObject.cs" />
     <Compile Include="VesselSimulator\AttachNodeSim.cs" />
     <Compile Include="VesselSimulator\EngineSim.cs" />
     <Compile Include="VesselSimulator\PartSim.cs" />

--- /dev/null
+++ b/KerbalEngineer/UIControls/WindowObject.cs
@@ -1,1 +1,166 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+#region Using Directives
+
+using System;
+
+using UnityEngine;
+
+#endregion
+
+namespace KerbalEngineer.UIControls
+{
+    public class WindowObject : MonoBehaviour
+    {
+        #region Fields
+
+        private Rect position;
+        private bool shouldCentre;
+
+        #endregion
+
+        #region Properties
+
+        public bool Draggable { get; set; }
+
+        public Callback DrawCallback { get; set; }
+
+        public float Height
+        {
+            get { return this.position.height; }
+            set { this.position.height = value; }
+        }
+
+        public Rect Position
+        {
+            get { return this.position; }
+            set { this.position = value; }
+        }
+
+        public string Title { get; set; }
+
+        public Callback UpdateCallback { get; set; }
+
+        public bool Visible { get; set; }
+
+        public float Width
+        {
+            get { return this.position.width; }
+            set { this.position.width = value; }
+        }
+
+        public float X
+        {
+            get { return this.position.x; }
+            set { this.position.x = value; }
+        }
+
+        public float Y
+        {
+            get { return this.position.y; }
+            set { this.position.y = value; }
+        }
+
+        #endregion
+
+        #region Methods: public
+
+        public void Centre()
+        {
+            this.shouldCentre = true;
+        }
+
+        #endregion
+
+        #region Methods: protected
+
+        protected void OnGUI()
+        {
+            try
+            {
+                if (!this.Visible)
+                {
+                    return;
+                }
+                this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, this.Title, HighLogic.Skin.window);
+                this.CentreTheWindow();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        protected void Update()
+        {
+            try
+            {
+                if (!this.Visible || this.UpdateCallback == null)
+                {
+                    return;
+                }
+                this.UpdateCallback();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        #endregion
+
+        #region Methods: private
+
+        private void CentreTheWindow()
+        {
+            if (this.shouldCentre && this.position.width > 0.0f && this.position.height > 0.0f)
+            {
+                this.position.center = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f);
+                this.shouldCentre = false;
+            }
+        }
+
+        private void Window(int windowId)
+        {
+            try
+            {
+                if (this.DrawCallback != null)
+                {
+                    this.DrawCallback();
+                }
+                else
+                {
+                    GUILayout.FlexibleSpace();
+                }
+
+                if (this.Draggable)
+                {
+                    GUI.DragWindow();
+                }
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        #endregion
+    }
+}

 Binary files a/Output/KerbalEngineer/KerbalEngineer.dll and b/Output/KerbalEngineer/KerbalEngineer.dll differ