Implemented vessel and resources overlay panels.
Implemented vessel and resources overlay panels.

file:a/.gitignore -> file:b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -112,3 +112,4 @@
 App_Data/*.ldf
 
 [Gg]ame/
+[Rr]elease/

--- a/KerbalEngineer/Editor/BuildAdvanced.cs
+++ b/KerbalEngineer/Editor/BuildAdvanced.cs
@@ -141,20 +141,22 @@
         {
             try
             {
-                if ((this.position.MouseIsOver() || this.bodiesList.Position.MouseIsOver()) && this.isEditorLocked == false)
-                {
-                    EditorLogic.fetch.State = EditorLogic.EditorState.GUI_SELECTED;
+                if ((this.position.MouseIsOver() || this.bodiesList.Position.MouseIsOver()) && !this.isEditorLocked)
+                {
+                    EditorLogic.fetch.Lock(true, true, true, "KER_BuildAdvanced");
+                    BuildOverlay.BuildOverlayPartInfo.Hidden = true;
                     this.isEditorLocked = true;
                 }
                 else if (!this.position.MouseIsOver() && !this.bodiesList.Position.MouseIsOver() && this.isEditorLocked)
                 {
-                    EditorLogic.fetch.State = EditorLogic.EditorState.PAD_UNSELECTED;
+                    EditorLogic.fetch.Unlock("KER_BuildAdvanced");
+                    BuildOverlay.BuildOverlayPartInfo.Hidden = false;
                     this.isEditorLocked = false;
                 }
             }
             catch (Exception ex)
             {
-                Logger.Exception(ex, "BuildAdvanced->CheckEditorLock");
+                Logger.Exception(ex);
             }
         }
 
@@ -402,16 +404,10 @@
                 GUILayout.EndHorizontal();
 
                 GUILayout.BeginHorizontal();
-                GUILayout.Label("Build Engineer Overlay (Vessel):", this.settingStyle);
-                BuildOverlay.Instance.Visible = GUILayout.Toggle(BuildOverlay.Instance.Visible, "ENABLED", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
-                BuildOverlay.Instance.Visible = !GUILayout.Toggle(!BuildOverlay.Instance.Visible, "DISABLED", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
-                GUILayout.EndHorizontal();
-
-                GUILayout.BeginHorizontal();
-                GUILayout.Label("Build Engineer Overlay (Part Info):", this.settingStyle);
-                BuildOverlayPartInfo.Visible = GUILayout.Toggle(BuildOverlayPartInfo.Visible, "VISIBLE", 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.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));
                 GUILayout.EndHorizontal();
 
                 GUILayout.BeginHorizontal();

--- a/KerbalEngineer/Editor/BuildOverlay.cs
+++ b/KerbalEngineer/Editor/BuildOverlay.cs
@@ -20,10 +20,9 @@
 #region Using Directives
 
 using System;
-using System.Diagnostics;
-
+
+using KerbalEngineer.Helpers;
 using KerbalEngineer.Settings;
-using KerbalEngineer.VesselSimulator;
 
 using UnityEngine;
 
@@ -36,32 +35,186 @@
     {
         #region Fields
 
-        private GUIStyle infoStyle;
-        private Stage lastStage;
-
-        private GUIStyle titleStyle;
-        private bool visible = true;
-        private int windowId;
-        private Rect windowPosition = new Rect(300.0f, 0, 0, 0);
-        private GUIStyle windowStyle;
+        private static BuildOverlay instance;
+
+        private static float minimumWidth = 200.0f;
+        private static GUIStyle nameStyle;
+        private static float tabSpeed = 5.0f;
+        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
 
-        /// <summary>
-        ///     Gets the current instance if started or returns null.
-        /// </summary>
-        public static BuildOverlay Instance { get; private set; }
-
-
-        /// <summary>
-        ///     Gets and sets whether the display is enabled.
-        /// </summary>
-        public bool Visible
-        {
-            get { return this.visible; }
-            set { this.visible = value; }
+        public static BuildOverlayPartInfo BuildOverlayPartInfo
+        {
+            get { return instance.buildOverlayPartInfo; }
+        }
+
+        public static BuildOverlayResources BuildOverlayResources
+        {
+            get { return instance.buildOverlayResources; }
+        }
+
+        public static BuildOverlayVessel BuildOverlayVessel
+        {
+            get { return instance.buildOverlayVessel; }
+        }
+
+        public static float MinimumWidth
+        {
+            get { return minimumWidth; }
+            set { minimumWidth = value; }
+        }
+
+        public static GUIStyle NameStyle
+        {
+            get
+            {
+                return nameStyle ?? (nameStyle = new GUIStyle
+                {
+                    normal =
+                    {
+                        textColor = Color.white
+                    },
+                    fontSize = 11,
+                    fontStyle = FontStyle.Bold,
+                    alignment = TextAnchor.UpperLeft,
+                    stretchWidth = true
+                });
+            }
+        }
+
+        public static float TabSpeed
+        {
+            get { return tabSpeed; }
+            set { tabSpeed = value; }
+        }
+
+        public static GUIStyle TabStyle
+        {
+            get
+            {
+                return tabStyle ?? (tabStyle = new GUIStyle
+                {
+                    normal =
+                    {
+                        background = TextureHelper.CreateTextureFromColour(new Color(0.0f, 0.0f, 0.0f, 0.5f)),
+                        textColor = Color.yellow
+                    },
+                    hover =
+                    {
+                        background = TextureHelper.CreateTextureFromColour(new Color(0.0f, 0.0f, 0.0f, 0.75f)),
+                        textColor = Color.yellow
+                    },
+                    onNormal =
+                    {
+                        background = TextureHelper.CreateTextureFromColour(new Color(0.0f, 0.0f, 0.0f, 0.5f)),
+                        textColor = Color.yellow
+                    },
+                    onHover =
+                    {
+                        background = TextureHelper.CreateTextureFromColour(new Color(0.0f, 0.0f, 0.0f, 0.75f)),
+                        textColor = Color.yellow
+                    },
+                    padding = new RectOffset(20, 20, 0, 0),
+                    fontSize = 11,
+                    fontStyle = FontStyle.Bold,
+                    alignment = TextAnchor.MiddleCenter,
+                    fixedHeight = 15.0f,
+                    stretchWidth = true
+                });
+            }
+        }
+
+        public static GUIStyle TitleStyle
+        {
+            get
+            {
+                return titleStyle ?? (titleStyle = new GUIStyle
+                {
+                    normal =
+                    {
+                        textColor = Color.yellow
+                    },
+                    fontSize = 11,
+                    fontStyle = FontStyle.Bold,
+                    stretchWidth = true
+                });
+            }
+        }
+
+        public static GUIStyle ValueStyle
+        {
+            get
+            {
+                return valueStyle ?? (valueStyle = new GUIStyle
+                {
+                    normal =
+                    {
+                        textColor = HighLogic.Skin.label.normal.textColor
+                    },
+                    fontSize = 11,
+                    fontStyle = FontStyle.Normal,
+                    alignment = TextAnchor.UpperRight,
+                    stretchWidth = true
+                });
+            }
+        }
+
+        public static bool Visible
+        {
+            get { return visible; }
+            set { visible = value; }
+        }
+
+        public static GUIStyle WindowStyle
+        {
+            get
+            {
+                return windowStyle ?? (windowStyle = new GUIStyle
+                {
+                    normal =
+                    {
+                        background = TextureHelper.CreateTextureFromColour(new Color(0.0f, 0.0f, 0.0f, 0.5f))
+                    },
+                    padding = new RectOffset(5, 5, 3, 3),
+                });
+            }
+        }
+
+        #endregion
+
+        #region Methods: public
+
+        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.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.Save("BuildOverlay.xml");
         }
 
         #endregion
@@ -72,8 +225,16 @@
         {
             try
             {
-                Instance = this;
-                GuiDisplaySize.OnSizeChanged += this.OnSizeChanged;
+                if (instance != null)
+                {
+                    Destroy(this);
+                    return;
+                }
+                instance = this;
+                this.buildOverlayPartInfo = this.gameObject.AddComponent<BuildOverlayPartInfo>();
+                this.buildOverlayVessel = this.gameObject.AddComponent<BuildOverlayVessel>();
+                this.buildOverlayResources = this.gameObject.AddComponent<BuildOverlayResources>();
+                Load();
             }
             catch (Exception ex)
             {
@@ -81,178 +242,23 @@
             }
         }
 
-        /// <summary>
-        ///     Saves the settings when this object is destroyed.
-        /// </summary>
         protected void OnDestroy()
         {
             try
             {
-                this.Save();
-                GuiDisplaySize.OnSizeChanged -= this.OnSizeChanged;
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex);
-            }
-        }
-
-        protected void OnGUI()
-        {
-            try
-            {
-                if (!this.visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0 || EditorLogic.fetch.editorScreen != EditorLogic.EditorScreen.Parts)
-                {
-                    return;
-                }
-
-                if (SimManager.ResultsReady())
-                {
-                    this.lastStage = SimManager.LastStage;
-                }
-
-                SimManager.RequestSimulation();
-
-                if (this.lastStage == null)
-                {
-                    return;
-                }
-
-                GUI.skin = null;
-                this.windowPosition = GUILayout.Window(this.windowId, this.windowPosition, this.Window, string.Empty, this.windowStyle);
-
-                // Check and set that the window is at the bottom of the screen.
-                if (this.windowPosition.y + this.windowPosition.height != Screen.height - 5.0f)
-                {
-                    this.windowPosition.y = Screen.height - this.windowPosition.height - 5.0f;
-                }
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex);
-            }
-        }
-
-        protected void Start()
-        {
-            try
-            {
-                this.windowId = this.GetHashCode();
-                this.InitialiseStyles();
-                this.Load();
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex);
-            }
-        }
-
-        protected void Update()
-        {
-            try
-            {
-                if (!this.visible || BuildAdvanced.Instance == null || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0 || EditorLogic.fetch.editorScreen != EditorLogic.EditorScreen.Parts)
-                {
-                    return;
-                }
-
-                // Configure the simulation parameters based on the selected reference body.
-                SimManager.Gravity = CelestialBodies.SelectedBody.Gravity;
-
-                if (BuildAdvanced.Instance.ShowAtmosphericDetails)
-                {
-                    SimManager.Atmosphere = CelestialBodies.SelectedBody.Atmosphere * 0.01d;
-                }
-                else
-                {
-                    SimManager.Atmosphere = 0;
-                }
-
-                SimManager.TryStartSimulation();
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex);
-            }
-        }
-
-        #endregion
-
-        #region Methods: private
-
-        private void InitialiseStyles()
-        {
-            this.windowStyle = new GUIStyle(GUIStyle.none)
-            {
-                margin = new RectOffset(),
-                padding = new RectOffset()
-            };
-
-            this.titleStyle = new GUIStyle(HighLogic.Skin.label)
-            {
-                normal =
-                {
-                    textColor = Color.white
-                },
-                margin = new RectOffset(),
-                padding = new RectOffset(),
-                fontSize = (int)(11 * GuiDisplaySize.Offset),
-                fontStyle = FontStyle.Bold,
-                stretchWidth = true
-            };
-
-            this.infoStyle = new GUIStyle(HighLogic.Skin.label)
-            {
-                margin = new RectOffset(),
-                padding = new RectOffset(),
-                fontSize = (int)(11 * GuiDisplaySize.Offset),
-                fontStyle = FontStyle.Bold,
-                stretchWidth = true
-            };
-
-        }
-
-        private void Load()
-        {
-            var handler = SettingHandler.Load("BuildOverlay.xml");
-            handler.Get("visible", ref this.visible);
-        }
-
-        private void OnSizeChanged()
-        {
-            this.InitialiseStyles();
-            this.windowPosition.width = 0;
-            this.windowPosition.height = 0;
-        }
-
-        private void Save()
-        {
-            var handler = new SettingHandler();
-            handler.Set("visible", this.visible);
-            handler.Save("BuildOverlay.xml");
-        }
-
-        private void Window(int windowId)
-        {
-            try
-            {
-                GUILayout.BeginHorizontal();
-
-                // Titles
-                GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
-                GUILayout.Label("Parts:", this.titleStyle);
-                GUILayout.Label("Delta-V:", this.titleStyle);
-                GUILayout.Label("TWR:", this.titleStyle);
-                GUILayout.EndVertical();
-
-                // Details
-                GUILayout.BeginVertical(GUILayout.Width(100.0f * GuiDisplaySize.Offset));
-                GUILayout.Label(this.lastStage.partCount.ToString("N0"), this.infoStyle);
-                GUILayout.Label(this.lastStage.totalDeltaV.ToString("N0") + " m/s", this.infoStyle);
-                GUILayout.Label(this.lastStage.thrustToWeight.ToString("F2"), this.infoStyle);
-                GUILayout.EndVertical();
-
-                GUILayout.EndHorizontal();
+                Save();
+                if (this.buildOverlayPartInfo != null)
+                {
+                    Destroy(this.buildOverlayPartInfo);
+                }
+                if (this.buildOverlayVessel != null)
+                {
+                    Destroy(this.buildOverlayVessel);
+                }
+                if (this.buildOverlayResources != null)
+                {
+                    Destroy(this.buildOverlayResources);
+                }
             }
             catch (Exception ex)
             {

--- a/KerbalEngineer/Editor/BuildOverlayPartInfo.cs
+++ b/KerbalEngineer/Editor/BuildOverlayPartInfo.cs
@@ -25,7 +25,6 @@
 
 using KerbalEngineer.Extensions;
 using KerbalEngineer.Helpers;
-using KerbalEngineer.Settings;
 
 using UnityEngine;
 
@@ -33,94 +32,50 @@
 
 namespace KerbalEngineer.Editor
 {
-    [KSPAddon(KSPAddon.Startup.EditorAny, false)]
     public class BuildOverlayPartInfo : MonoBehaviour
     {
         #region Fields
 
-        private static bool clickToOpen = true;
-        private static bool namesOnly;
-        private static bool visible = true;
-
-        private readonly List<InfoItem> infoItems = new List<InfoItem>();
-        private GUIStyle nameStyle;
+        private readonly List<PartInfoItem> infoItems = new List<PartInfoItem>();
+        private bool clickToOpen = true;
+        private bool namesOnly;
+
         private Rect position;
         private Part selectedPart;
         private bool showInfo;
-        private GUIStyle titleStyle;
-        private GUIStyle valueStyle;
-        private GUIStyle windowStyle;
 
         #endregion
 
         #region Properties
 
-        public static bool ClickToOpen
-        {
-            get { return clickToOpen; }
-            set
-            {
-                clickToOpen = value;
-                Save();
-            }
-        }
-
-        public static bool NamesOnly
-        {
-            get { return namesOnly; }
-            set
-            {
-                namesOnly = value;
-                Save();
-            }
-        }
-
-        public static bool Visible
-        {
-            get { return visible; }
-            set
-            {
-                visible = value;
-                Save();
-            }
+        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; }
         }
 
         #endregion
 
-        #region Methods: public
-
-        public static void Load()
-        {
-            var handler = SettingHandler.Load("BuildOverlayPartInfo.xml");
-            handler.GetSet("visible", ref visible);
-            handler.GetSet("namesOnly", ref namesOnly);
-            handler.GetSet("clickToOpen", ref clickToOpen);
-            handler.Save("BuildOverlayPartInfo.xml");
-        }
-
-        public static void Save()
-        {
-            var handler = SettingHandler.Load("BuildOverlayPartInfo.xml");
-            handler.Set("visible", visible);
-            handler.Set("namesOnly", namesOnly);
-            handler.Set("clickToOpen", clickToOpen);
-            handler.Save("BuildOverlayPartInfo.xml");
-        }
-
-        #endregion
-
         #region Methods: protected
 
         protected void OnGUI()
         {
             try
             {
-                if (this.selectedPart == null || !Visible)
+                if (!BuildOverlay.Visible || this.Hidden || this.selectedPart == null)
                 {
                     return;
                 }
 
-                this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, String.Empty, this.windowStyle);
+                this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, String.Empty, BuildOverlay.WindowStyle);
             }
             catch (Exception ex)
 
@@ -129,24 +84,11 @@
             }
         }
 
-        protected void Start()
+        protected void Update()
         {
             try
             {
-                this.InitialiseStyles();
-                Load();
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex);
-            }
-        }
-
-        protected void Update()
-        {
-            try
-            {
-                if (!Visible)
+                if (!BuildOverlay.Visible || this.Hidden || EditorLogic.startPod == null)
                 {
                     return;
                 }
@@ -163,7 +105,7 @@
                 }
 
                 this.infoItems.Clear();
-                var part = EditorLogic.SortedShipList.Find(p => p.stackIcon.highlightIcon) ?? EditorLogic.SelectedPart;
+                var part = EditorLogic.fetch.ship.parts.Find(p => p.stackIcon.highlightIcon) ?? EditorLogic.SelectedPart;
                 if (part != null)
                 {
                     if (!part.Equals(this.selectedPart))
@@ -171,12 +113,12 @@
                         this.selectedPart = part;
                         this.ResetInfo();
                     }
-                    if (NamesOnly)
+                    if (this.NamesOnly)
                     {
                         return;
                     }
 
-                    this.infoItems.Add(new InfoItem("Cost", this.selectedPart.partInfo.cost.ToString("N0")));
+                    this.infoItems.Add(new PartInfoItem("Cost", this.selectedPart.partInfo.cost.ToString("N0")));
                     this.SetMassItems();
                     this.SetResourceItems();
                     this.SetEngineInfo();
@@ -198,7 +140,7 @@
                     {
                         this.showInfo = true;
                     }
-                    else if (ClickToOpen && this.showInfo && Input.GetMouseButtonDown(2))
+                    else if (this.ClickToOpen && this.showInfo && Input.GetMouseButtonDown(2))
                     {
                         this.ResetInfo();
                     }
@@ -218,48 +160,10 @@
 
         #region Methods: private
 
-        private void InitialiseStyles()
-        {
-            this.windowStyle = new GUIStyle
-            {
-                normal =
-                {
-                    background = TextureHelper.CreateTextureFromColour(new Color(0.0f, 0.0f, 0.0f, 0.5f))
-                },
-                padding = new RectOffset(5, 5, 3, 3),
-            };
-
-            this.titleStyle = new GUIStyle
-            {
-                normal =
-                {
-                    textColor = Color.yellow
-                },
-                fontSize = (int)(11 * GuiDisplaySize.Offset),
-                fontStyle = FontStyle.Bold,
-                stretchWidth = true
-            };
-
-            this.nameStyle = new GUIStyle(this.titleStyle)
-            {
-                normal =
-                {
-                    textColor = Color.white
-                },
-                padding = new RectOffset(0, 0, 2, 0),
-                fontStyle = FontStyle.Normal
-            };
-
-            this.valueStyle = new GUIStyle(this.nameStyle)
-            {
-                alignment = TextAnchor.UpperRight
-            };
-        }
-
         private void ResetInfo()
         {
-            this.showInfo = !clickToOpen;
-            this.position.width = namesOnly || clickToOpen ? 0.0f : 200.0f;
+            this.showInfo = !this.clickToOpen;
+            this.position.width = this.namesOnly || this.clickToOpen ? 0.0f : 200.0f;
             this.position.height = 0.0f;
         }
 
@@ -271,10 +175,10 @@
             }
 
             var alternator = this.selectedPart.GetModule<ModuleAlternator>();
-            this.infoItems.Add(new InfoItem("Alternator"));
+            this.infoItems.Add(new PartInfoItem("Alternator"));
             foreach (var resource in alternator.outputResources)
             {
-                this.infoItems.Add(new InfoItem("\t" + resource.name, resource.rate.ToRate()));
+                this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
             }
         }
 
@@ -286,10 +190,10 @@
             }
 
             var decoupler = this.selectedPart.GetProtoModuleDecoupler();
-            this.infoItems.Add(new InfoItem("Ejection Force", decoupler.EjectionForce.ToForce()));
+            this.infoItems.Add(new PartInfoItem("Ejection Force", decoupler.EjectionForce.ToForce()));
             if (decoupler.IsOmniDecoupler)
             {
-                this.infoItems.Add(new InfoItem("Omni-directional"));
+                this.infoItems.Add(new PartInfoItem("Omni-directional"));
             }
         }
 
@@ -301,15 +205,15 @@
             }
 
             var engine = this.selectedPart.GetProtoModuleEngine();
-            this.infoItems.Add(new InfoItem("Thrust", Units.ToForce(engine.MinimumThrust, engine.MaximumThrust)));
-            this.infoItems.Add(new InfoItem("Isp", Units.Concat(engine.GetSpecificImpulse(1.0f), engine.GetSpecificImpulse(0.0f)) + "s"));
+            this.infoItems.Add(new PartInfoItem("Thrust", Units.ToForce(engine.MinimumThrust, engine.MaximumThrust)));
+            this.infoItems.Add(new PartInfoItem("Isp", Units.Concat(engine.GetSpecificImpulse(1.0f), engine.GetSpecificImpulse(0.0f)) + "s"));
             if (engine.Propellants.Count > 0)
             {
-                this.infoItems.Add(new InfoItem("Propellants"));
+                this.infoItems.Add(new PartInfoItem("Propellants"));
                 var totalRatio = engine.Propellants.Sum(p => p.ratio);
                 foreach (var propellant in engine.Propellants)
                 {
-                    this.infoItems.Add(new InfoItem("\t" + propellant.name, (propellant.ratio / totalRatio).ToPercent()));
+                    this.infoItems.Add(new PartInfoItem("\t" + propellant.name, (propellant.ratio / totalRatio).ToPercent()));
                 }
             }
         }
@@ -324,23 +228,23 @@
             var generator = this.selectedPart.GetModule<ModuleGenerator>();
             if (generator.inputList.Count > 0)
             {
-                this.infoItems.Add(new InfoItem("Generator Input"));
+                this.infoItems.Add(new PartInfoItem("Generator Input"));
                 foreach (var resource in generator.inputList)
                 {
-                    this.infoItems.Add(new InfoItem("\t" + resource.name, resource.rate.ToRate()));
+                    this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
                 }
             }
             if (generator.outputList.Count > 0)
             {
-                this.infoItems.Add(new InfoItem("Generator Output"));
+                this.infoItems.Add(new PartInfoItem("Generator Output"));
                 foreach (var resource in generator.outputList)
                 {
-                    this.infoItems.Add(new InfoItem("\t" + resource.name, resource.rate.ToRate()));
+                    this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
                 }
             }
             if (generator.isAlwaysActive)
             {
-                this.infoItems.Add(new InfoItem("Generator is Always Active"));
+                this.infoItems.Add(new PartInfoItem("Generator is Always Active"));
             }
         }
 
@@ -352,14 +256,14 @@
             }
 
             var gimbal = this.selectedPart.GetModule<ModuleGimbal>();
-            this.infoItems.Add(new InfoItem("Thrust Vectoring", gimbal.gimbalRange.ToString("F2")));
+            this.infoItems.Add(new PartInfoItem("Thrust Vectoring", gimbal.gimbalRange.ToString("F2")));
         }
 
         private void SetMassItems()
         {
             if (this.selectedPart.physicalSignificance == Part.PhysicalSignificance.FULL)
             {
-                this.infoItems.Add(new InfoItem("Mass", Units.ToMass(this.selectedPart.GetDryMass(), this.selectedPart.GetWetMass())));
+                this.infoItems.Add(new PartInfoItem("Mass", Units.ToMass(this.selectedPart.GetDryMass(), this.selectedPart.GetWetMass())));
             }
         }
 
@@ -371,9 +275,9 @@
             }
 
             var parachute = this.selectedPart.GetModule<ModuleParachute>();
-            this.infoItems.Add(new InfoItem("Deployed Drag", Units.Concat(parachute.semiDeployedDrag, parachute.fullyDeployedDrag)));
-            this.infoItems.Add(new InfoItem("Deployment Altitude", parachute.deployAltitude.ToDistance()));
-            this.infoItems.Add(new InfoItem("Deployment Pressure", parachute.minAirPressureToOpen.ToString("F2")));
+            this.infoItems.Add(new PartInfoItem("Deployed Drag", Units.Concat(parachute.semiDeployedDrag, parachute.fullyDeployedDrag)));
+            this.infoItems.Add(new PartInfoItem("Deployment Altitude", parachute.deployAltitude.ToDistance()));
+            this.infoItems.Add(new PartInfoItem("Deployment Pressure", parachute.minAirPressureToOpen.ToString("F2")));
         }
 
         private void SetRcsInfo()
@@ -384,8 +288,8 @@
             }
 
             var rcs = this.selectedPart.GetModule<ModuleRCS>();
-            this.infoItems.Add(new InfoItem("Thruster Power", rcs.thrusterPower.ToForce()));
-            this.infoItems.Add(new InfoItem("Specific Impulse", Units.Concat(rcs.atmosphereCurve.Evaluate(1.0f), rcs.atmosphereCurve.Evaluate(0.0f)) + "s"));
+            this.infoItems.Add(new PartInfoItem("Thruster Power", rcs.thrusterPower.ToForce()));
+            this.infoItems.Add(new PartInfoItem("Specific Impulse", Units.Concat(rcs.atmosphereCurve.Evaluate(1.0f), rcs.atmosphereCurve.Evaluate(0.0f)) + "s"));
         }
 
         private void SetReactionWheelInfo()
@@ -396,13 +300,13 @@
             }
 
             var reactionWheel = this.selectedPart.GetModule<ModuleReactionWheel>();
-            this.infoItems.Add(new InfoItem("Reaction Wheel Torque"));
-            this.infoItems.Add(new InfoItem("\tPitch", reactionWheel.PitchTorque.ToForce()));
-            this.infoItems.Add(new InfoItem("\tRoll", reactionWheel.RollTorque.ToForce()));
-            this.infoItems.Add(new InfoItem("\tYaw", reactionWheel.YawTorque.ToForce()));
+            this.infoItems.Add(new PartInfoItem("Reaction Wheel Torque"));
+            this.infoItems.Add(new PartInfoItem("\tPitch", reactionWheel.PitchTorque.ToForce()));
+            this.infoItems.Add(new PartInfoItem("\tRoll", reactionWheel.RollTorque.ToForce()));
+            this.infoItems.Add(new PartInfoItem("\tYaw", reactionWheel.YawTorque.ToForce()));
             foreach (var resource in reactionWheel.inputResources)
             {
-                this.infoItems.Add(new InfoItem("\t" + resource.name, resource.rate.ToRate()));
+                this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
             }
         }
 
@@ -410,12 +314,12 @@
         {
             if (this.selectedPart.Resources.list.Any(r => !r.hideFlow))
             {
-                this.infoItems.Add(new InfoItem("Resources"));
+                this.infoItems.Add(new PartInfoItem("Resources"));
                 foreach (var resource in this.selectedPart.Resources.list.Where(r => !r.hideFlow))
                 {
                     this.infoItems.Add(resource.GetDensity() > 0
-                        ? new InfoItem("\t" + resource.info.name, "(" + resource.GetMass().ToMass() + ") " + resource.amount.ToString("F1"))
-                        : new InfoItem("\t" + resource.info.name, resource.amount.ToString("F1")));
+                        ? new PartInfoItem("\t" + resource.info.name, "(" + resource.GetMass().ToMass() + ") " + resource.amount.ToString("F1"))
+                        : new PartInfoItem("\t" + resource.info.name, resource.amount.ToString("F1")));
                 }
             }
         }
@@ -424,7 +328,7 @@
         {
             if (this.selectedPart.HasModule<ModuleSAS>())
             {
-                this.infoItems.Add(new InfoItem("SAS Equiped"));
+                this.infoItems.Add(new PartInfoItem("SAS Equiped"));
             }
         }
 
@@ -432,7 +336,7 @@
         {
             if (this.selectedPart.HasModule<ModuleScienceContainer>())
             {
-                this.infoItems.Add(new InfoItem("Science Container"));
+                this.infoItems.Add(new PartInfoItem("Science Container"));
             }
         }
 
@@ -444,11 +348,11 @@
             }
 
             var experiment = this.selectedPart.GetModule<ModuleScienceExperiment>();
-            this.infoItems.Add(new InfoItem("Science Experiment", experiment.experimentActionName));
-            this.infoItems.Add(new InfoItem("\tTransmit Efficiency", experiment.xmitDataScalar.ToPercent()));
+            this.infoItems.Add(new PartInfoItem("Science Experiment", experiment.experimentActionName));
+            this.infoItems.Add(new PartInfoItem("\tTransmit Efficiency", experiment.xmitDataScalar.ToPercent()));
             if (!experiment.rerunnable)
             {
-                this.infoItems.Add(new InfoItem("\tSingle Usage"));
+                this.infoItems.Add(new PartInfoItem("\tSingle Usage"));
             }
         }
 
@@ -456,7 +360,7 @@
         {
             if (this.selectedPart.HasModule<ModuleAnimateGeneric>(m => m.isOneShot))
             {
-                this.infoItems.Add(new InfoItem("Single Activation"));
+                this.infoItems.Add(new PartInfoItem("Single Activation"));
             }
         }
 
@@ -468,14 +372,14 @@
             }
 
             var solarPanel = this.selectedPart.GetModule<ModuleDeployableSolarPanel>();
-            this.infoItems.Add(new InfoItem("Charge Rate", solarPanel.chargeRate.ToRate()));
+            this.infoItems.Add(new PartInfoItem("Charge Rate", solarPanel.chargeRate.ToRate()));
             if (solarPanel.isBreakable)
             {
-                this.infoItems.Add(new InfoItem("Breakable"));
+                this.infoItems.Add(new PartInfoItem("Breakable"));
             }
             if (solarPanel.sunTracking)
             {
-                this.infoItems.Add(new InfoItem("Sun Tracking"));
+                this.infoItems.Add(new PartInfoItem("Sun Tracking"));
             }
         }
 
@@ -487,73 +391,45 @@
             }
 
             var transmitter = this.selectedPart.GetModule<ModuleDataTransmitter>();
-            this.infoItems.Add(new InfoItem("Packet Size", transmitter.packetSize.ToString("F2") + " Mits"));
-            this.infoItems.Add(new InfoItem("Bandwidth", (transmitter.packetInterval * transmitter.packetSize).ToString("F2") + "Mits/sec"));
-            this.infoItems.Add(new InfoItem(transmitter.requiredResource, transmitter.packetResourceCost.ToString("F2") + "/Packet"));
+            this.infoItems.Add(new PartInfoItem("Packet Size", transmitter.packetSize.ToString("F2") + " Mits"));
+            this.infoItems.Add(new PartInfoItem("Bandwidth", (transmitter.packetInterval * transmitter.packetSize).ToString("F2") + "Mits/sec"));
+            this.infoItems.Add(new PartInfoItem(transmitter.requiredResource, transmitter.packetResourceCost.ToString("F2") + "/Packet"));
         }
 
         private void Window(int windowId)
         {
             try
             {
-                GUILayout.Label(this.selectedPart.partInfo.title, this.titleStyle);
+                GUILayout.Label(this.selectedPart.partInfo.title, BuildOverlay.TitleStyle);
                 if (this.showInfo)
                 {
                     foreach (var item in this.infoItems)
                     {
+                        GUILayout.Space(2.0f);
                         GUILayout.BeginHorizontal();
                         if (item.Value != null)
                         {
-                            GUILayout.Label(item.Name + ":", this.nameStyle);
+                            GUILayout.Label(item.Name + ":", BuildOverlay.NameStyle);
                             GUILayout.Space(25.0f);
-                            GUILayout.Label(item.Value, this.valueStyle);
+                            GUILayout.Label(item.Value, BuildOverlay.ValueStyle);
                         }
                         else
                         {
-                            GUILayout.Label(item.Name, this.nameStyle);
+                            GUILayout.Label(item.Name, BuildOverlay.NameStyle);
                         }
                         GUILayout.EndHorizontal();
                     }
                 }
-                else if (!NamesOnly)
-                {
-                    GUILayout.Label("Click middle mouse to show more info...", this.nameStyle);
+                else if (!this.NamesOnly)
+                {
+                    GUILayout.Space(2.0f);
+                    GUILayout.Label("Click middle mouse to show more info...", BuildOverlay.NameStyle);
                 }
             }
             catch (Exception ex)
             {
                 Logger.Exception(ex);
             }
-        }
-
-        #endregion
-
-        #region Nested Type: InfoItem
-
-        public class InfoItem
-        {
-            #region Constructors
-
-            public InfoItem(string name)
-            {
-                this.Name = name;
-            }
-
-            public InfoItem(string name, string value)
-            {
-                this.Name = name;
-                this.Value = value;
-            }
-
-            #endregion
-
-            #region Properties
-
-            public string Name { get; set; }
-
-            public string Value { get; set; }
-
-            #endregion
         }
 
         #endregion

--- a/KerbalEngineer/Editor/BuildToolbar.cs
+++ b/KerbalEngineer/Editor/BuildToolbar.cs
@@ -20,7 +20,6 @@
 #region Using Directives
 
 using System;
-using System.IO;
 
 using UnityEngine;
 
@@ -31,12 +30,28 @@
     [KSPAddon(KSPAddon.Startup.EditorAny, false)]
     public class BuildToolbar : MonoBehaviour
     {
+        #region Fields
+
         private ApplicationLauncherButton button;
+
+        #endregion
+
+        #region Methods: private
 
         private void Awake()
         {
             GameEvents.onGUIApplicationLauncherReady.Add(this.OnGuiAppLauncherReady);
             Logger.Log("BuildToolbar->Awake");
+        }
+
+        private void OnDestroy()
+        {
+            GameEvents.onGUIApplicationLauncherReady.Remove(this.OnGuiAppLauncherReady);
+            if (this.button != null)
+            {
+                ApplicationLauncher.Instance.RemoveModApplication(this.button);
+            }
+            Logger.Log("BuildToolbar->OnDestroy");
         }
 
         private void OnGuiAppLauncherReady()
@@ -92,14 +107,6 @@
             }
         }
 
-        private void OnDestroy()
-        {
-            GameEvents.onGUIApplicationLauncherReady.Remove(this.OnGuiAppLauncherReady);
-            if (this.button != null)
-            {
-                ApplicationLauncher.Instance.RemoveModApplication(this.button);
-            }
-            Logger.Log("BuildToolbar->OnDestroy");
-        }
+        #endregion
     }
 }

--- a/KerbalEngineer/Flight/FlightEngineerPartless.cs
+++ b/KerbalEngineer/Flight/FlightEngineerPartless.cs
@@ -88,7 +88,6 @@
                         handler.Save("FlightEngineerPartless.xml");
                     }
                     isPartless = value;
-                    Logger.Log("FlightEngineerPartless->IsPartless = " + value);
                 }
                 catch (Exception ex)
                 {

--- a/KerbalEngineer/KerbalEngineer.csproj
+++ b/KerbalEngineer/KerbalEngineer.csproj
@@ -60,7 +60,11 @@
     <Compile Include="Editor\BuildOverlay.cs" />
     <Compile Include="CelestialBodies.cs" />
     <Compile Include="Editor\BuildOverlayPartInfo.cs" />
+    <Compile Include="Editor\BuildOverlayResources.cs" />
+    <Compile Include="Editor\BuildOverlayVessel.cs" />
     <Compile Include="Editor\BuildToolbar.cs" />
+    <Compile Include="Editor\PartInfoItem.cs" />
+    <Compile Include="Editor\ResourceInfoItem.cs" />
     <Compile Include="Extensions\FloatExtensions.cs" />
     <Compile Include="Extensions\OrbitExtensions.cs" />
     <Compile Include="Flight\ActionMenuGui.cs" />

 Binary files a/Output/KerbalEngineer/KerbalEngineer.dll and b/Output/KerbalEngineer/KerbalEngineer.dll differ
 Binary files a/Release/KerbalEngineer-1.0.8.1.zip and b/Release/KerbalEngineer-1.0.8.1.zip differ