Added TimeFormatter helper.
[VesselSimulator.git] / KerbalEngineer / Editor / BuildAdvanced.cs
blob:a/KerbalEngineer/Editor/BuildAdvanced.cs -> blob:b/KerbalEngineer/Editor/BuildAdvanced.cs
--- a/KerbalEngineer/Editor/BuildAdvanced.cs
+++ b/KerbalEngineer/Editor/BuildAdvanced.cs
@@ -24,6 +24,7 @@
 
 using KerbalEngineer.Extensions;
 using KerbalEngineer.Flight;
+using KerbalEngineer.Helpers;
 using KerbalEngineer.Settings;
 using KerbalEngineer.UIControls;
 using KerbalEngineer.VesselSimulator;
@@ -37,54 +38,80 @@
     [KSPAddon(KSPAddon.Startup.EditorAny, false)]
     public class BuildAdvanced : MonoBehaviour
     {
-        #region Instance
-
-        /// <summary>
-        ///     Gets the current instance if started or returns null.
-        /// </summary>
-        public static BuildAdvanced Instance { get; private set; }
-
-        #endregion
-
         #region Fields
 
+        private GUIStyle areaSettingStyle;
+        private GUIStyle areaStyle;
         private float atmosphericPercentage = 1.0f;
         private float atmosphericVelocity;
+        private GUIStyle bodiesButtonActiveStyle;
+        private GUIStyle bodiesButtonStyle;
         private DropDown bodiesList;
+        private Rect bodiesListPosition;
+        private GUIStyle buttonStyle;
         private int compactCheck;
         private bool compactCollapseRight;
+        private bool compactMode;
         private float compactRight;
         private bool hasChanged;
+        private GUIStyle infoStyle;
         private bool isEditorLocked;
         private int numberOfStages;
-        private Stage[] stages;
         private Rect position = new Rect(265.0f, 45.0f, 0, 0);
-        private Rect bodiesListPosition;
-
-        #region Styles
-
-        private GUIStyle areaSettingStyle;
-        private GUIStyle areaStyle;
-        private GUIStyle buttonStyle;
-        private GUIStyle infoStyle;
         private GUIStyle settingAtmoStyle;
         private GUIStyle settingStyle;
-        private GUIStyle titleStyle;
-        private GUIStyle windowStyle;
-        private GUIStyle bodiesButtonStyle;
-        private GUIStyle bodiesButtonActiveStyle;
-
-        #endregion
-
-        #endregion
-
-        #region Properties
-
-        private bool compactMode;
         private bool showAllStages;
         private bool showAtmosphericDetails;
         private bool showSettings;
+        private Stage[] stages;
+        private GUIStyle titleStyle;
         private bool visible = true;
+        private GUIStyle windowStyle;
+
+        #endregion
+
+        #region Properties
+
+        /// <summary>
+        ///     Gets the current instance if started or returns null.
+        /// </summary>
+        public static BuildAdvanced Instance { get; private set; }
+
+        /// <summary>
+        ///     Gets and sets whether to show in compact mode.
+        /// </summary>
+        public bool CompactMode
+        {
+            get { return this.compactMode; }
+            set { this.compactMode = value; }
+        }
+
+        /// <summary>
+        ///     Gets and sets whether to show all stages.
+        /// </summary>
+        public bool ShowAllStages
+        {
+            get { return this.showAllStages; }
+            set { this.showAllStages = value; }
+        }
+
+        /// <summary>
+        ///     Gets and sets whether to use atmospheric details.
+        /// </summary>
+        public bool ShowAtmosphericDetails
+        {
+            get { return this.showAtmosphericDetails; }
+            set { this.showAtmosphericDetails = value; }
+        }
+
+        /// <summary>
+        ///     Gets and sets whether to show the settings display.
+        /// </summary>
+        public bool ShowSettings
+        {
+            get { return this.showSettings; }
+            set { this.showSettings = value; }
+        }
 
         /// <summary>
         ///     Gets and sets whether the display is enabled.
@@ -95,45 +122,9 @@
             set { this.visible = value; }
         }
 
-        /// <summary>
-        ///     Gets and sets whether to show in compact mode.
-        /// </summary>
-        public bool CompactMode
-        {
-            get { return this.compactMode; }
-            set { this.compactMode = value; }
-        }
-
-        /// <summary>
-        ///     Gets and sets whether to show all stages.
-        /// </summary>
-        public bool ShowAllStages
-        {
-            get { return this.showAllStages; }
-            set { this.showAllStages = value; }
-        }
-
-        /// <summary>
-        ///     Gets and sets whether to use atmospheric details.
-        /// </summary>
-        public bool ShowAtmosphericDetails
-        {
-            get { return this.showAtmosphericDetails; }
-            set { this.showAtmosphericDetails = value; }
-        }
-
-        /// <summary>
-        ///     Gets and sets whether to show the settings display.
-        /// </summary>
-        public bool ShowSettings
-        {
-            get { return this.showSettings; }
-            set { this.showSettings = value; }
-        }
-
         #endregion
 
-        #region Initialisation
+        #region Methods: private
 
         private void Awake()
         {
@@ -143,207 +134,6 @@
             this.Load();
         }
 
-        private void Start()
-        {
-            this.InitialiseStyles();
-            GuiDisplaySize.OnSizeChanged += this.OnSizeChanged;
-        }
-
-        /// <summary>
-        ///     Initialises all the styles that are required.
-        /// </summary>
-        private void InitialiseStyles()
-        {
-            try
-            {
-                this.windowStyle = new GUIStyle(HighLogic.Skin.window)
-                {
-                    alignment = TextAnchor.UpperLeft
-                };
-
-                this.areaStyle = new GUIStyle(HighLogic.Skin.box)
-                {
-                    padding = new RectOffset(0, 0, 9, 0)
-                };
-
-                this.areaSettingStyle = new GUIStyle(HighLogic.Skin.box)
-                {
-                    padding = new RectOffset(10, 10, 10, 10)
-                };
-
-                this.buttonStyle = new GUIStyle(HighLogic.Skin.button)
-                {
-                    normal =
-                    {
-                        textColor = Color.white
-                    },
-                    fontSize = (int)(11 * GuiDisplaySize.Offset),
-                    fontStyle = FontStyle.Bold,
-                    alignment = TextAnchor.MiddleCenter
-                };
-
-                this.titleStyle = new GUIStyle(HighLogic.Skin.label)
-                {
-                    normal =
-                    {
-                        textColor = Color.white
-                    },
-                    fontSize = (int)(11 * GuiDisplaySize.Offset),
-                    fontStyle = FontStyle.Bold,
-                    alignment = TextAnchor.MiddleCenter,
-                    stretchWidth = true,
-                };
-
-                this.infoStyle = new GUIStyle(HighLogic.Skin.label)
-                {
-                    fontSize = (int)(11 * GuiDisplaySize.Offset),
-                    fontStyle = FontStyle.Bold,
-                    alignment = TextAnchor.MiddleCenter,
-                    stretchWidth = true
-                };
-
-                this.settingStyle = new GUIStyle(this.titleStyle)
-                {
-                    alignment = TextAnchor.MiddleLeft,
-                    stretchWidth = true,
-                    stretchHeight = true
-                };
-
-                this.settingAtmoStyle = new GUIStyle(this.titleStyle)
-                {
-                    margin = new RectOffset(),
-                    padding = new RectOffset(),
-                    alignment = TextAnchor.UpperLeft
-                };
-
-                this.bodiesButtonStyle = new GUIStyle(HighLogic.Skin.button)
-                {
-                    margin = new RectOffset(0, 0, 2, 0),
-                    padding = new RectOffset(5, 5, 5, 5),
-                    normal =
-                    {
-                        textColor = Color.white
-                    },
-                    active =
-                    {
-                        textColor = Color.white
-                    },
-                    fontSize = (int)(11 * GuiDisplaySize.Offset),
-                    fontStyle = FontStyle.Bold,
-                    alignment = TextAnchor.MiddleCenter,
-                    fixedHeight = 20.0f
-                };
-
-                this.bodiesButtonActiveStyle = new GUIStyle(this.bodiesButtonStyle)
-                {
-                    normal = this.bodiesButtonStyle.onNormal,
-                    hover = this.bodiesButtonStyle.onHover
-                };
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "BuildAdvanced->InitialiseStyles");
-            }
-        }
-
-        private void OnSizeChanged()
-        {
-            this.InitialiseStyles();
-            this.hasChanged = true;
-        }
-
-        #endregion
-
-        #region Update and Drawing
-
-        private void Update()
-        {
-            try
-            {
-                if (!this.visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0)
-                {
-                    this.bodiesList.enabled = false;
-                    return;
-                }
-
-                // Configure the simulation parameters based on the selected reference body.
-                SimManager.Gravity = CelestialBodies.SelectedBody.Gravity;
-
-                if (this.showAtmosphericDetails)
-                {
-                    SimManager.Atmosphere = CelestialBodies.SelectedBody.Atmosphere * 0.01d * this.atmosphericPercentage;
-                }
-                else
-                {
-                    SimManager.Atmosphere = 0;
-                }
-
-                SimManager.Velocity = this.atmosphericVelocity;
-                SimManager.TryStartSimulation();
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "BuildAdvanced->Update");
-            }
-        }
-
-        private 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.stages = SimManager.Stages;
-                }
-
-                SimManager.RequestSimulation();
-
-                if (this.stages == null)
-                {
-                    return;
-                }
-
-                // Change the window title based on whether in compact mode or not.
-                var title = !this.compactMode ? "KERBAL ENGINEER REDUX " + EngineerGlobals.AssemblyVersion : "K.E.R. " + EngineerGlobals.AssemblyVersion;
-
-                // Reset the window size when the staging or something else has changed.
-                var stageCount = this.stages.Count(stage => this.showAllStages || stage.deltaV > 0);
-                if (this.hasChanged || stageCount != this.numberOfStages)
-                {
-                    this.hasChanged = false;
-                    this.numberOfStages = stageCount;
-
-                    this.position.width = 0;
-                    this.position.height = 0;
-                }
-
-                GUI.skin = null;
-                this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, title, this.windowStyle).ClampToScreen();
-
-                if (this.compactCheck > 0 && this.compactCollapseRight)
-                {
-                    this.position.x = this.compactRight - this.position.width;
-                    this.compactCheck--;
-                }
-                else if (this.compactCheck > 0)
-                {
-                    this.compactCheck = 0;
-                }
-
-                // Check editor lock to manage click-through.
-                this.CheckEditorLock();
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "BuildAdvanced->OnDraw");
-            }
-        }
-
         /// <summary>
         ///     Checks whether the editor should be locked to stop click-through.
         /// </summary>
@@ -365,94 +155,6 @@
             catch (Exception ex)
             {
                 Logger.Exception(ex, "BuildAdvanced->CheckEditorLock");
-            }
-        }
-
-        /// <summary>
-        ///     Draws the OnGUI window.
-        /// </summary>
-        private void Window(int windowId)
-        {
-            try
-            {
-                // Draw the compact mode toggle.
-                if (GUI.Toggle(new Rect(this.position.width - 70.0f * GuiDisplaySize.Offset, 5.0f, 65.0f * GuiDisplaySize.Offset, 20.0f), this.compactMode, "COMPACT", this.buttonStyle) != this.compactMode)
-                {
-                    this.hasChanged = true;
-                    this.compactCheck = 2;
-                    this.compactRight = this.position.xMax;
-                    this.compactMode = !this.compactMode;
-                }
-
-                // When not in compact mode draw the 'All Stages' and 'Atmospheric' toggles.
-                if (!this.compactMode)
-                {
-                    if (GUI.Toggle(new Rect(this.position.width - 143.0f * GuiDisplaySize.Offset, 5.0f, 70.0f * GuiDisplaySize.Offset, 20.0f), this.showSettings, "SETTINGS", this.buttonStyle) != this.showSettings)
-                    {
-                        this.hasChanged = true;
-                        this.showSettings = !this.showSettings;
-                    }
-
-                    if (GUI.Toggle(new Rect(this.position.width - 226.0f * GuiDisplaySize.Offset, 5.0f, 80.0f * GuiDisplaySize.Offset, 20.0f), this.showAllStages, "ALL STAGES", this.buttonStyle) != this.showAllStages)
-                    {
-                        this.hasChanged = true;
-                        this.showAllStages = !this.showAllStages;
-                    }
-
-                    if (GUI.Toggle(new Rect(this.position.width - 324.0f * GuiDisplaySize.Offset, 5.0f, 95.0f * GuiDisplaySize.Offset, 20.0f), this.showAtmosphericDetails, "ATMOSPHERIC", this.buttonStyle) != this.showAtmosphericDetails)
-                    {
-                        this.hasChanged = true;
-                        this.showAtmosphericDetails = !this.showAtmosphericDetails;
-                    }
-
-                    this.bodiesListPosition = new Rect(this.position.width - 452.0f * GuiDisplaySize.Offset, 5.0f, 125.0f * GuiDisplaySize.Offset, 20.0f);
-                    this.bodiesList.enabled = GUI.Toggle(this.bodiesListPosition, this.bodiesList.enabled, "BODY: " + CelestialBodies.SelectedBody.Name.ToUpper(), this.buttonStyle);
-                    this.bodiesList.SetPosition(this.bodiesListPosition.Translate(this.position));
-                }
-
-                // Draw the main informational display box.
-                if (!this.compactMode)
-                {
-                    GUILayout.BeginHorizontal(this.areaStyle);
-                    this.DrawStageNumbers();
-                    //this.DrawPartCount();
-                    this.DrawCost();
-                    this.DrawMass();
-                    this.DrawIsp();
-                    this.DrawThrust();
-                    this.DrawTwr();
-                    this.DrawDeltaV();
-                    this.DrawBurnTime();
-                    GUILayout.EndHorizontal();
-
-                    if (this.showAtmosphericDetails)
-                    {
-                        GUILayout.BeginVertical(this.areaSettingStyle);
-                        this.DrawAtmosphericDetails();
-                        GUILayout.EndVertical();
-                    }
-
-                    if (this.showSettings)
-                    {
-                        GUILayout.BeginVertical(this.areaSettingStyle);
-                        this.DrawSettings();
-                        GUILayout.EndVertical();
-                    }
-                }
-                else // Draw only a few details when in compact mode.
-                {
-                    GUILayout.BeginHorizontal(this.areaStyle);
-                    this.DrawStageNumbers();
-                    this.DrawTwr();
-                    this.DrawDeltaV();
-                    GUILayout.EndHorizontal();
-                }
-
-                GUI.DragWindow();
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "BuildAdvanced->Window");
             }
         }
 
@@ -493,6 +195,199 @@
             }
         }
 
+        private void DrawBodiesList()
+        {
+            try
+            {
+                if (CelestialBodies.SystemBody == CelestialBodies.SelectedBody)
+                {
+                    this.DrawBody(CelestialBodies.SystemBody);
+                }
+                else
+                {
+                    foreach (var body in CelestialBodies.SystemBody.Children)
+                    {
+                        this.DrawBody(body);
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        private void DrawBody(CelestialBodies.BodyInfo bodyInfo, int depth = 0)
+        {
+            try
+            {
+                GUILayout.BeginHorizontal();
+                GUILayout.Space(20.0f * depth);
+                if (GUILayout.Button(bodyInfo.Children.Count > 0 ? bodyInfo.Name + " [" + bodyInfo.Children.Count + "]" : bodyInfo.Name, bodyInfo.Selected && bodyInfo.SelectedDepth == 0 ? this.bodiesButtonActiveStyle : this.bodiesButtonStyle))
+                {
+                    CelestialBodies.SetSelectedBody(bodyInfo.Name);
+                    this.bodiesList.Resize = true;
+                }
+                GUILayout.EndHorizontal();
+
+                if (bodyInfo.Selected)
+                {
+                    foreach (var body in bodyInfo.Children)
+                    {
+                        this.DrawBody(body, depth + 1);
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        /// <summary>
+        ///     Draws the burn time column.
+        /// </summary>
+        private void DrawBurnTime()
+        {
+            try
+            {
+                GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
+                GUILayout.Label("BURN", this.titleStyle);
+                foreach (var stage in this.stages)
+                {
+                    if (this.showAllStages || stage.deltaV > 0)
+                    {
+                        GUILayout.Label(TimeFormatter.ConvertToString(stage.time), this.infoStyle);
+                    }
+                }
+                GUILayout.EndVertical();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex, "BuildAdvanced->DrawBurnTime");
+            }
+        }
+
+        /// <summary>
+        ///     Draws the cost column.
+        /// </summary>
+        private void DrawCost()
+        {
+            try
+            {
+                GUILayout.BeginVertical(GUILayout.Width(110.0f * GuiDisplaySize.Offset));
+                GUILayout.Label("COST", this.titleStyle);
+                foreach (var stage in this.stages)
+                {
+                    if (this.showAllStages || stage.deltaV > 0)
+                    {
+                        GUILayout.Label(stage.cost.ToString("N0") + " / " + stage.totalCost.ToString("N0"), this.infoStyle);
+                    }
+                }
+                GUILayout.EndVertical();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex, "BuildAdvanced->DrawCost");
+            }
+        }
+
+        /// <summary>
+        ///     Draws the deltaV column.
+        /// </summary>
+        private void DrawDeltaV()
+        {
+            try
+            {
+                GUILayout.BeginVertical(GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+                GUILayout.Label("DELTA-V", this.titleStyle);
+                foreach (var stage in this.stages)
+                {
+                    if (this.showAllStages || stage.deltaV > 0)
+                    {
+                        GUILayout.Label(stage.deltaV.ToString("N0") + " / " + stage.inverseTotalDeltaV.ToString("N0") + "m/s", this.infoStyle);
+                    }
+                }
+                GUILayout.EndVertical();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex, "BuildAdvanced->DrawDeltaV");
+            }
+        }
+
+        /// <summary>
+        ///     Draws the specific impluse column.
+        /// </summary>
+        private void DrawIsp()
+        {
+            try
+            {
+                GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
+                GUILayout.Label("ISP", this.titleStyle);
+                foreach (var stage in this.stages)
+                {
+                    if (this.showAllStages || stage.deltaV > 0)
+                    {
+                        GUILayout.Label(stage.isp.ToString("F1") + "s", this.infoStyle);
+                    }
+                }
+                GUILayout.EndVertical();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex, "BuildAdvanced->DrawIsp");
+            }
+        }
+
+        /// <summary>
+        ///     Draws the mass column.
+        /// </summary>
+        private void DrawMass()
+        {
+            try
+            {
+                GUILayout.BeginVertical(GUILayout.Width(110.0f * GuiDisplaySize.Offset));
+                GUILayout.Label("MASS", this.titleStyle);
+                foreach (var stage in this.stages)
+                {
+                    if (this.showAllStages || stage.deltaV > 0)
+                    {
+                        GUILayout.Label(stage.mass.ToMass(false) + " / " + stage.totalMass.ToMass(), this.infoStyle);
+                    }
+                }
+                GUILayout.EndVertical();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex, "BuildAdvanced->DrawMass");
+            }
+        }
+
+        /// <summary>
+        ///     Draws the part count column.
+        /// </summary>
+        private void DrawPartCount()
+        {
+            try
+            {
+                GUILayout.BeginVertical(GUILayout.Width(50.0f * GuiDisplaySize.Offset));
+                GUILayout.Label("PARTS", this.titleStyle);
+                foreach (var stage in this.stages)
+                {
+                    if (this.showAllStages || stage.deltaV > 0)
+                    {
+                        //GUILayout.Label(stage.PartCount.ToString("N0"), this.infoStyle);
+                    }
+                }
+                GUILayout.EndVertical();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex, "BuildAdvanced->DrawPartCount");
+            }
+        }
+
         /// <summary>
         ///     Draws the settings panel.
         /// </summary>
@@ -571,102 +466,6 @@
         }
 
         /// <summary>
-        ///     Draws the part count column.
-        /// </summary>
-        private void DrawPartCount()
-        {
-            try
-            {
-                GUILayout.BeginVertical(GUILayout.Width(50.0f * GuiDisplaySize.Offset));
-                GUILayout.Label("PARTS", this.titleStyle);
-                foreach (var stage in this.stages)
-                {
-                    if (this.showAllStages || stage.deltaV > 0)
-                    {
-                        //GUILayout.Label(stage.PartCount.ToString("N0"), this.infoStyle);
-                    }
-                }
-                GUILayout.EndVertical();
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "BuildAdvanced->DrawPartCount");
-            }
-        }
-
-        /// <summary>
-        ///     Draws the cost column.
-        /// </summary>
-        private void DrawCost()
-        {
-            try
-            {
-                GUILayout.BeginVertical(GUILayout.Width(110.0f * GuiDisplaySize.Offset));
-                GUILayout.Label("COST", this.titleStyle);
-                foreach (var stage in this.stages)
-                {
-                    if (this.showAllStages || stage.deltaV > 0)
-                    {
-                        GUILayout.Label(stage.cost.ToString("N0") + " / " + stage.totalCost.ToString("N0"), this.infoStyle);
-                    }
-                }
-                GUILayout.EndVertical();
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "BuildAdvanced->DrawCost");
-            }
-        }
-
-        /// <summary>
-        ///     Draws the mass column.
-        /// </summary>
-        private void DrawMass()
-        {
-            try
-            {
-                GUILayout.BeginVertical(GUILayout.Width(110.0f * GuiDisplaySize.Offset));
-                GUILayout.Label("MASS", this.titleStyle);
-                foreach (var stage in this.stages)
-                {
-                    if (this.showAllStages || stage.deltaV > 0)
-                    {
-                        GUILayout.Label(stage.mass.ToMass(false) + " / " + stage.totalMass.ToMass(), this.infoStyle);
-                    }
-                }
-                GUILayout.EndVertical();
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "BuildAdvanced->DrawMass");
-            }
-        }
-
-        /// <summary>
-        ///     Draws the specific impluse column.
-        /// </summary>
-        private void DrawIsp()
-        {
-            try
-            {
-                GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
-                GUILayout.Label("ISP", this.titleStyle);
-                foreach (var stage in this.stages)
-                {
-                    if (this.showAllStages || stage.deltaV > 0)
-                    {
-                        GUILayout.Label(stage.isp.ToString("F1") + "s", this.infoStyle);
-                    }
-                }
-                GUILayout.EndVertical();
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "BuildAdvanced->DrawIsp");
-            }
-        }
-
-        /// <summary>
         ///     Draws the thrust column.
         /// </summary>
         private void DrawThrust()
@@ -715,105 +514,125 @@
         }
 
         /// <summary>
-        ///     Draws the deltaV column.
-        /// </summary>
-        private void DrawDeltaV()
-        {
-            try
-            {
-                GUILayout.BeginVertical(GUILayout.Width(100.0f * GuiDisplaySize.Offset));
-                GUILayout.Label("DELTA-V", this.titleStyle);
-                foreach (var stage in this.stages)
-                {
-                    if (this.showAllStages || stage.deltaV > 0)
-                    {
-                        GUILayout.Label(stage.deltaV.ToString("N0") + " / " + stage.inverseTotalDeltaV.ToString("N0") + "m/s", this.infoStyle);
-                    }
-                }
-                GUILayout.EndVertical();
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "BuildAdvanced->DrawDeltaV");
-            }
-        }
-
-        /// <summary>
-        ///     Draws the burn time column.
-        /// </summary>
-        private void DrawBurnTime()
-        {
-            try
-            {
-                GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
-                GUILayout.Label("BURN", this.titleStyle);
-                foreach (var stage in this.stages)
-                {
-                    if (this.showAllStages || stage.deltaV > 0)
-                    {
-                        GUILayout.Label(stage.time.ToTime(), this.infoStyle);
-                    }
-                }
-                GUILayout.EndVertical();
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "BuildAdvanced->DrawBurnTime");
-            }
-        }
-
-        private void DrawBodiesList()
-        {
-            try
-            {
-                if (CelestialBodies.SystemBody == CelestialBodies.SelectedBody)
-                {
-                    this.DrawBody(CelestialBodies.SystemBody);
-                }
-                else
-                {
-                    foreach (var body in CelestialBodies.SystemBody.Children)
-                    {
-                        this.DrawBody(body);
-                    }
-                }
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex);
-            }
-        }
-
-        private void DrawBody(CelestialBodies.BodyInfo bodyInfo, int depth = 0)
-        {
-            try
-            {
-                GUILayout.BeginHorizontal();
-                GUILayout.Space(20.0f * depth);
-                if (GUILayout.Button(bodyInfo.Children.Count > 0 ? bodyInfo.Name + " [" + bodyInfo.Children.Count + "]" : bodyInfo.Name, bodyInfo.Selected && bodyInfo.SelectedDepth == 0 ? this.bodiesButtonActiveStyle : this.bodiesButtonStyle))
-                {
-                    CelestialBodies.SetSelectedBody(bodyInfo.Name);
-                    this.bodiesList.Resize = true;
-                }
-                GUILayout.EndHorizontal();
-
-                if (bodyInfo.Selected)
-                {
-                    foreach (var body in bodyInfo.Children)
-                    {
-                        this.DrawBody(body, depth + 1);
-                    }
-                }
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex);
-            }
-        }
-
-        #endregion
-
-        #region Save and Load
+        ///     Initialises all the styles that are required.
+        /// </summary>
+        private void InitialiseStyles()
+        {
+            try
+            {
+                this.windowStyle = new GUIStyle(HighLogic.Skin.window)
+                {
+                    alignment = TextAnchor.UpperLeft
+                };
+
+                this.areaStyle = new GUIStyle(HighLogic.Skin.box)
+                {
+                    padding = new RectOffset(0, 0, 9, 0)
+                };
+
+                this.areaSettingStyle = new GUIStyle(HighLogic.Skin.box)
+                {
+                    padding = new RectOffset(10, 10, 10, 10)
+                };
+
+                this.buttonStyle = new GUIStyle(HighLogic.Skin.button)
+                {
+                    normal =
+                    {
+                        textColor = Color.white
+                    },
+                    fontSize = (int)(11 * GuiDisplaySize.Offset),
+                    fontStyle = FontStyle.Bold,
+                    alignment = TextAnchor.MiddleCenter
+                };
+
+                this.titleStyle = new GUIStyle(HighLogic.Skin.label)
+                {
+                    normal =
+                    {
+                        textColor = Color.white
+                    },
+                    fontSize = (int)(11 * GuiDisplaySize.Offset),
+                    fontStyle = FontStyle.Bold,
+                    alignment = TextAnchor.MiddleCenter,
+                    stretchWidth = true,
+                };
+
+                this.infoStyle = new GUIStyle(HighLogic.Skin.label)
+                {
+                    fontSize = (int)(11 * GuiDisplaySize.Offset),
+                    fontStyle = FontStyle.Bold,
+                    alignment = TextAnchor.MiddleCenter,
+                    stretchWidth = true
+                };
+
+                this.settingStyle = new GUIStyle(this.titleStyle)
+                {
+                    alignment = TextAnchor.MiddleLeft,
+                    stretchWidth = true,
+                    stretchHeight = true
+                };
+
+                this.settingAtmoStyle = new GUIStyle(this.titleStyle)
+                {
+                    margin = new RectOffset(),
+                    padding = new RectOffset(),
+                    alignment = TextAnchor.UpperLeft
+                };
+
+                this.bodiesButtonStyle = new GUIStyle(HighLogic.Skin.button)
+                {
+                    margin = new RectOffset(0, 0, 2, 0),
+                    padding = new RectOffset(5, 5, 5, 5),
+                    normal =
+                    {
+                        textColor = Color.white
+                    },
+                    active =
+                    {
+                        textColor = Color.white
+                    },
+                    fontSize = (int)(11 * GuiDisplaySize.Offset),
+                    fontStyle = FontStyle.Bold,
+                    alignment = TextAnchor.MiddleCenter,
+                    fixedHeight = 20.0f
+                };
+
+                this.bodiesButtonActiveStyle = new GUIStyle(this.bodiesButtonStyle)
+                {
+                    normal = this.bodiesButtonStyle.onNormal,
+                    hover = this.bodiesButtonStyle.onHover
+                };
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex, "BuildAdvanced->InitialiseStyles");
+            }
+        }
+
+        /// <summary>
+        ///     Loads the settings when this object is created.
+        /// </summary>
+        private void Load()
+        {
+            try
+            {
+                var handler = SettingHandler.Load("BuildAdvanced.xml");
+                handler.Get("visible", ref this.visible);
+                this.position.x = handler.Get("windowPositionX", this.position.x);
+                this.position.y = handler.Get("windowPositionY", this.position.y);
+                handler.Get("compactMode", ref this.compactMode);
+                handler.Get("compactCollapseRight", ref this.compactCollapseRight);
+                handler.Get("showAllStages", ref this.showAllStages);
+                handler.Get("showAtmosphericDetails", ref this.showAtmosphericDetails);
+                handler.Get("showSettings", ref this.showSettings);
+                CelestialBodies.SetSelectedBody(handler.Get("selectedBodyName", CelestialBodies.SelectedBody.Name));
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex, "BuildAdvanced->Load");
+            }
+        }
 
         /// <summary>
         ///     Saves the settings when this object is destroyed.
@@ -841,27 +660,191 @@
             }
         }
 
-        /// <summary>
-        ///     Loads the settings when this object is created.
-        /// </summary>
-        private void Load()
-        {
-            try
-            {
-                var handler = SettingHandler.Load("BuildAdvanced.xml");
-                handler.Get("visible", ref this.visible);
-                this.position.x = handler.Get("windowPositionX", this.position.x);
-                this.position.y = handler.Get("windowPositionY", this.position.y);
-                handler.Get("compactMode", ref this.compactMode);
-                handler.Get("compactCollapseRight", ref this.compactCollapseRight);
-                handler.Get("showAllStages", ref this.showAllStages);
-                handler.Get("showAtmosphericDetails", ref this.showAtmosphericDetails);
-                handler.Get("showSettings", ref this.showSettings);
-                CelestialBodies.SetSelectedBody(handler.Get("selectedBodyName", CelestialBodies.SelectedBody.Name));
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "BuildAdvanced->Load");
+        private 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.stages = SimManager.Stages;
+                }
+
+                SimManager.RequestSimulation();
+
+                if (this.stages == null)
+                {
+                    return;
+                }
+
+                // Change the window title based on whether in compact mode or not.
+                var title = !this.compactMode ? "KERBAL ENGINEER REDUX " + EngineerGlobals.AssemblyVersion : "K.E.R. " + EngineerGlobals.AssemblyVersion;
+
+                // Reset the window size when the staging or something else has changed.
+                var stageCount = this.stages.Count(stage => this.showAllStages || stage.deltaV > 0);
+                if (this.hasChanged || stageCount != this.numberOfStages)
+                {
+                    this.hasChanged = false;
+                    this.numberOfStages = stageCount;
+
+                    this.position.width = 0;
+                    this.position.height = 0;
+                }
+
+                GUI.skin = null;
+                this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, title, this.windowStyle).ClampToScreen();
+
+                if (this.compactCheck > 0 && this.compactCollapseRight)
+                {
+                    this.position.x = this.compactRight - this.position.width;
+                    this.compactCheck--;
+                }
+                else if (this.compactCheck > 0)
+                {
+                    this.compactCheck = 0;
+                }
+
+                // Check editor lock to manage click-through.
+                this.CheckEditorLock();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex, "BuildAdvanced->OnDraw");
+            }
+        }
+
+        private void OnSizeChanged()
+        {
+            this.InitialiseStyles();
+            this.hasChanged = true;
+        }
+
+        private void Start()
+        {
+            this.InitialiseStyles();
+            GuiDisplaySize.OnSizeChanged += this.OnSizeChanged;
+        }
+
+        private void Update()
+        {
+            try
+            {
+                if (!this.visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0)
+                {
+                    this.bodiesList.enabled = false;
+                    return;
+                }
+
+                // Configure the simulation parameters based on the selected reference body.
+                SimManager.Gravity = CelestialBodies.SelectedBody.Gravity;
+
+                if (this.showAtmosphericDetails)
+                {
+                    SimManager.Atmosphere = CelestialBodies.SelectedBody.Atmosphere * 0.01d * this.atmosphericPercentage;
+                }
+                else
+                {
+                    SimManager.Atmosphere = 0;
+                }
+
+                SimManager.Velocity = this.atmosphericVelocity;
+                SimManager.TryStartSimulation();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex, "BuildAdvanced->Update");
+            }
+        }
+
+        /// <summary>
+        ///     Draws the OnGUI window.
+        /// </summary>
+        private void Window(int windowId)
+        {
+            try
+            {
+                // Draw the compact mode toggle.
+                if (GUI.Toggle(new Rect(this.position.width - 70.0f * GuiDisplaySize.Offset, 5.0f, 65.0f * GuiDisplaySize.Offset, 20.0f), this.compactMode, "COMPACT", this.buttonStyle) != this.compactMode)
+                {
+                    this.hasChanged = true;
+                    this.compactCheck = 2;
+                    this.compactRight = this.position.xMax;
+                    this.compactMode = !this.compactMode;
+                }
+
+                // When not in compact mode draw the 'All Stages' and 'Atmospheric' toggles.
+                if (!this.compactMode)
+                {
+                    if (GUI.Toggle(new Rect(this.position.width - 143.0f * GuiDisplaySize.Offset, 5.0f, 70.0f * GuiDisplaySize.Offset, 20.0f), this.showSettings, "SETTINGS", this.buttonStyle) != this.showSettings)
+                    {
+                        this.hasChanged = true;
+                        this.showSettings = !this.showSettings;
+                    }
+
+                    if (GUI.Toggle(new Rect(this.position.width - 226.0f * GuiDisplaySize.Offset, 5.0f, 80.0f * GuiDisplaySize.Offset, 20.0f), this.showAllStages, "ALL STAGES", this.buttonStyle) != this.showAllStages)
+                    {
+                        this.hasChanged = true;
+                        this.showAllStages = !this.showAllStages;
+                    }
+
+                    if (GUI.Toggle(new Rect(this.position.width - 324.0f * GuiDisplaySize.Offset, 5.0f, 95.0f * GuiDisplaySize.Offset, 20.0f), this.showAtmosphericDetails, "ATMOSPHERIC", this.buttonStyle) != this.showAtmosphericDetails)
+                    {
+                        this.hasChanged = true;
+                        this.showAtmosphericDetails = !this.showAtmosphericDetails;
+                    }
+
+                    this.bodiesListPosition = new Rect(this.position.width - 452.0f * GuiDisplaySize.Offset, 5.0f, 125.0f * GuiDisplaySize.Offset, 20.0f);
+                    this.bodiesList.enabled = GUI.Toggle(this.bodiesListPosition, this.bodiesList.enabled, "BODY: " + CelestialBodies.SelectedBody.Name.ToUpper(), this.buttonStyle);
+                    this.bodiesList.SetPosition(this.bodiesListPosition.Translate(this.position));
+                }
+
+                // Draw the main informational display box.
+                if (!this.compactMode)
+                {
+                    GUILayout.BeginHorizontal(this.areaStyle);
+                    this.DrawStageNumbers();
+                    //this.DrawPartCount();
+                    this.DrawCost();
+                    this.DrawMass();
+                    this.DrawIsp();
+                    this.DrawThrust();
+                    this.DrawTwr();
+                    this.DrawDeltaV();
+                    this.DrawBurnTime();
+                    GUILayout.EndHorizontal();
+
+                    if (this.showAtmosphericDetails)
+                    {
+                        GUILayout.BeginVertical(this.areaSettingStyle);
+                        this.DrawAtmosphericDetails();
+                        GUILayout.EndVertical();
+                    }
+
+                    if (this.showSettings)
+                    {
+                        GUILayout.BeginVertical(this.areaSettingStyle);
+                        this.DrawSettings();
+                        GUILayout.EndVertical();
+                    }
+                }
+                else // Draw only a few details when in compact mode.
+                {
+                    GUILayout.BeginHorizontal(this.areaStyle);
+                    this.DrawStageNumbers();
+                    this.DrawTwr();
+                    this.DrawDeltaV();
+                    GUILayout.EndHorizontal();
+                }
+
+                GUI.DragWindow();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex, "BuildAdvanced->Window");
             }
         }