Simplified null or empty check for readability.
Simplified null or empty check for readability.

--- a/Documents/CHANGES.txt
+++ b/Documents/CHANGES.txt
@@ -1,5 +1,28 @@
-1.0.17.1
+1.0.19.1, 09-11-15
+    Added: Key binding editor accessible under 'Settings' on the Build Engineer.
+    Added: Added current vessel name readout. (antplant)
+    Added: 'Relative Radial Velocity' and 'Time To Rendezvous' readouts. (itwtx)
+    Added: Readout help strings. (harryyoung)
+    Changed: The 'Torque' value in the editor is now precise to two decimal places.
+    Changed: Time formatting reference (Kerbin/Earth) is now based on the in-game setting.
+    Changed: Eccentric Anomaly, Mean Anomaly and Mean Anomaly At Epoc now display in degrees rather than radians.
+    Fixed: Optimised time formatting. (itwtx)
+    Fixed: TimeToAtmosphere checks that the Apoapsis is outside atmosphere. (Kerbas-ad-astra)
+    Fixed: Issue with stage priority flow. Caused Rapier calculations to fail if LF and O are drawn from different tanks. (Padishar)
+    Fixed: Issue with angle to prograde/retrograde calculations on highly inclined orbits.
+    Fixed: Editor input locks not being reset when a scene change is forced (e.g. via Kerbal Construction Time).
+    Fixed: Roll axis readout now shows the correct sign.
+    Removed: Time Formatter readout as it's not required anymore.
+
+1.0.18.0
+    Added: Orbital readouts - "Speed at Periapsis" and "Speed at Apoapsis". (Padishar)
+    Added: Manoeuvre readouts - "Post-burn Apoapsis" and "Post-burn Periapsis". (Padishar)
+    Added: Orbital readout - "Time to Atmosphere".
     Fixed: Synched the minimum simulation time sliders and stopped them from snapping back after 999ms. (saybur)
+    Fixed: Added workaround for the bug in Vessel.horizontalSrfSpeed (Padishar)
+    Fixed: Physically insignificant part mass was not being correctly cascaded down through multiple parent parts.
+    Fixed: Intake air demand calculation not working.
+    Fixed: Some build engineer settings labels do not scale with UI size.
 
 1.0.17.0
     Added: 'Mach Number' readout under the 'Surface' category and included it on the default surface HUD.
@@ -21,8 +44,8 @@
 
     Changed: Mach on the Build Engineer now accurate to 2 decimal places.
     Changed: Max mach in the Build Engineer defaults to 1.00 even when no jet engines are present.
-    Changed: Increased eccentricity readout to 5 decimal places.  
-    Changed: Implemented Sarbian's object pooling. 
+    Changed: Increased eccentricity readout to 5 decimal places.
+    Changed: Implemented Sarbian's object pooling.
     Changed: The default selected body is now assigned via 'Planitarium.Home'.
     Changed: HUDs to clamp fully inside the screen instead of allowing them to run off the edge by a certain amount.
     Fixed: Physically insignificant part mass is now associated with the parent part.
@@ -76,7 +99,7 @@
 
 1.0.15.1, 13-02-2015
     Rebuild
-    
+
 1.0.15.0, 08-02-2015
     Padishar's Fixes:
         Added: Support KIDS ISP thrust correction.
@@ -86,7 +109,7 @@
 
 1.0.14.1, 28-12-2014
     Fixed: Missing texture on the ER-7500 model.
-    
+
 1.0.14.0, 28-12-2014
     Added: Career mode that limits the Flight Engineer by:
         - Requiring an Engineer Kerbal of any level, or placement of an Engineer Chip or ER-7500 part.
@@ -206,7 +229,7 @@
     Added: New readout to the surface category:
         - Vertical Acceleration
         - Horizontal Acceleration
-    
+
     Changed: Atmospheric efficiency readout now shows as a percentage.
     Changed: Atmospheric settings (pressure/velocity) in the editor condensed onto a single line.
     Fixed: Bug where the overlays in the editor would stay open outside of parts screen.
@@ -363,6 +386,7 @@
     Added: Stock toolbar support in the Flight Engineer.
     Changed: Orbital Period has higher precision.
     Fixed: Various NullRefs in editor window and overlay.
-    
+
 1.0.0.0, 24-07-2014
     Initial release for public testing.
+

--- a/KerbalEngineer/Editor/BuildAdvanced.cs
+++ b/KerbalEngineer/Editor/BuildAdvanced.cs
@@ -1,7 +1,5 @@
 // 
-//     Kerbal Engineer Redux
-// 
-//     Copyright (C) 2014 CYBUTEK
+//     Copyright (C) 2015 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
@@ -19,23 +17,26 @@
 
 namespace KerbalEngineer.Editor
 {
-    #region Using Directives
     using System;
     using Extensions;
     using Flight;
     using Helpers;
+    using KeyBinding;
     using Settings;
     using UIControls;
     using UnityEngine;
     using VesselSimulator;
 
-    #endregion
-
     [KSPAddon(KSPAddon.Startup.EditorAny, false)]
     public class BuildAdvanced : MonoBehaviour
     {
-        #region Fields
-        public static float Altitude = 0.0f;
+        public static float Altitude;
+
+        private static Rect compactModeRect = new Rect(0.0f, 5.0f, 0.0f, 20.0f);
+        private static Stage stage;
+        private static int stagesCount;
+        private static int stagesLength;
+        private static string title;
 
         private GUIStyle areaSettingStyle;
         private GUIStyle areaStyle;
@@ -64,9 +65,7 @@
         private GUIStyle titleStyle;
         private bool visible = true;
         private GUIStyle windowStyle;
-        #endregion
-
-        #region Properties
+
         /// <summary>
         ///     Gets the current instance if started or returns null.
         /// </summary>
@@ -146,14 +145,6 @@
                 visible = value;
             }
         }
-        #endregion
-
-        #region Methods
-        private static Rect compactModeRect = new Rect(0.0f, 5.0f, 0.0f, 20.0f);
-        private static Stage stage;
-        private static int stagesCount;
-        private static int stagesLength;
-        private static string title;
 
         protected void Awake()
         {
@@ -179,6 +170,8 @@
         /// </summary>
         protected void OnDestroy()
         {
+            Logger.Log("BuildAdvanced->OnDestroy");
+
             try
             {
                 SettingHandler handler = new SettingHandler();
@@ -198,6 +191,8 @@
             {
                 Logger.Exception(ex, "BuildAdvanced.OnDestroy()");
             }
+
+            EditorLock(false);
         }
 
         protected void OnGUI()
@@ -552,6 +547,14 @@
             GUILayout.EndHorizontal();
 
             GUILayout.BeginHorizontal();
+            GUILayout.Label("Key Bindings:", settingStyle);
+            if (GUILayout.Button("EDIT KEY BINDINGS", buttonStyle, GUILayout.Width(200.0f * GuiDisplaySize.Offset)))
+            {
+                KeyBinder.Show();
+            }
+            GUILayout.EndHorizontal();
+
+            GUILayout.BeginHorizontal();
             GUILayout.Label("GUI Size: " + GuiDisplaySize.Increment, settingStyle);
             if (GUILayout.Button("<", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)))
             {
@@ -566,6 +569,7 @@
             GUILayout.Label("Minimum delay between simulations: " + SimManager.minSimTime.TotalMilliseconds + "ms", settingStyle);
             GUI.skin = HighLogic.Skin;
             SimManager.minSimTime = TimeSpan.FromMilliseconds(GUILayout.HorizontalSlider((float)SimManager.minSimTime.TotalMilliseconds, 0, 2000.0f));
+
             GUI.skin = null;
         }
 
@@ -706,7 +710,7 @@
                 fontSize = (int)(11 * GuiDisplaySize.Offset),
                 fontStyle = FontStyle.Bold,
                 alignment = TextAnchor.MiddleCenter,
-                stretchWidth = true,
+                stretchWidth = true
             };
 
             infoStyle = new GUIStyle(HighLogic.Skin.label)
@@ -884,6 +888,5 @@
                 Logger.Exception(ex, "BuildAdvanced.Window()");
             }
         }
-        #endregion
     }
 }

--- a/KerbalEngineer/EngineerGlobals.cs
+++ b/KerbalEngineer/EngineerGlobals.cs
@@ -25,11 +25,12 @@
         /// <summary>
         ///     Current version of the Kerbal Engineer assembly.
         /// </summary>
-        public const string ASSEMBLY_VERSION = "1.0.17.0";
+        public const string ASSEMBLY_VERSION = "1.0.19.2";
 
         private static string assemblyFile;
         private static string assemblyName;
         private static string assemblyPath;
+        private static string settingsPath;
 
         /// <summary>
         ///     Gets the Kerbal Engineer assembly's path including the file name.
@@ -63,5 +64,20 @@
                 return assemblyPath ?? (assemblyPath = AssemblyFile.Replace(new FileInfo(AssemblyFile).Name, ""));
             }
         }
+
+        /// <summary>
+        ///     Gets the settings directory path.
+        /// </summary>
+        public static string SettingsPath
+        {
+            get
+            {
+                if (string.IsNullOrEmpty(settingsPath))
+                {
+                    settingsPath = Path.Combine(AssemblyPath, "Settings");
+                }
+                return settingsPath;
+            }
+        }
     }
 }

--- a/KerbalEngineer/Extensions/OrbitExtensions.cs
+++ b/KerbalEngineer/Extensions/OrbitExtensions.cs
@@ -61,12 +61,15 @@
                 return 0.0;
             }
 
-            var angle = AngleHelper.GetAngleBetweenVectors(orbit.getRelativePositionAtUT(universalTime),
-                                                           Vector3d.Exclude(orbit.GetOrbitNormal(), orbit.referenceBody.orbit.getRelativePositionAtUT(universalTime)));
+            Vector3d orbitVector = orbit.getRelativePositionAtUT(universalTime);
+            orbitVector.z = 0.0;
 
-            angle = AngleHelper.Clamp360(angle - 90.0);
+            Vector3d bodyVector = orbit.referenceBody.orbit.getOrbitalVelocityAtUT(universalTime);
+            bodyVector.z = 0.0;
 
-            return orbit.inclination > 90.0 ? angle : 360.0 - angle;
+            double angle = AngleHelper.GetAngleBetweenVectors(bodyVector, orbitVector);
+
+            return AngleHelper.Clamp360(orbit.inclination < 90.0 ? angle : 360.0 - angle);
         }
 
         public static double GetAngleToRetrograde(this Orbit orbit)
@@ -81,12 +84,15 @@
                 return 0.0;
             }
 
-            var angle = AngleHelper.GetAngleBetweenVectors(orbit.getRelativePositionAtUT(universalTime),
-                                                           Vector3d.Exclude(orbit.GetOrbitNormal(), orbit.referenceBody.orbit.getRelativePositionAtUT(universalTime)));
+            Vector3d orbitVector = orbit.getRelativePositionAtUT(universalTime);
+            orbitVector.z = 0.0;
 
-            angle = AngleHelper.Clamp360(angle + 90.0);
+            Vector3d bodyVector = orbit.referenceBody.orbit.getOrbitalVelocityAtUT(universalTime);
+            bodyVector.z = 0.0;
 
-            return orbit.inclination > 90.0 ? angle : 360.0 - angle;
+            double angle = AngleHelper.GetAngleBetweenVectors(-bodyVector, orbitVector);
+
+            return AngleHelper.Clamp360(orbit.inclination < 90.0 ? angle : 360.0 - angle);
         }
 
         public static double GetAngleToTrueAnomaly(this Orbit orbit, double trueAnomaly)

--- a/KerbalEngineer/Flight/DisplayStack.cs
+++ b/KerbalEngineer/Flight/DisplayStack.cs
@@ -33,6 +33,7 @@
 
 namespace KerbalEngineer.Flight
 {
+    using KeyBinding;
     using Upgradeables;
 
     /// <summary>

--- a/KerbalEngineer/Flight/Readouts/Miscellaneous/Separator.cs
+++ b/KerbalEngineer/Flight/Readouts/Miscellaneous/Separator.cs
@@ -45,7 +45,7 @@
         {
             this.Name = "Separator";
             this.Category = ReadoutCategory.GetCategory("Miscellaneous");
-            this.HelpString = String.Empty;
+            this.HelpString = "Creats a line to help seperate subsections in a module.";
             this.IsDefault = false;
             this.Cloneable = true;
 

--- a/KerbalEngineer/Flight/Readouts/Miscellaneous/SystemTime.cs
+++ b/KerbalEngineer/Flight/Readouts/Miscellaneous/SystemTime.cs
@@ -40,7 +40,7 @@
         {
             this.Name = "System Time";
             this.Category = ReadoutCategory.GetCategory("Miscellaneous");
-            this.HelpString = String.Empty;
+            this.HelpString = "Shows the System Time in 12 hour format (AM/PM)";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Miscellaneous/TimeReference.cs
+++ /dev/null
@@ -1,66 +1,1 @@
-// 
-//     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 KerbalEngineer.Flight.Sections;
-using KerbalEngineer.Helpers;
-
-using UnityEngine;
-
-#endregion
-
-namespace KerbalEngineer.Flight.Readouts.Miscellaneous
-{
-    public class TimeReference : ReadoutModule
-    {
-        #region Constructors
-
-        public TimeReference()
-        {
-            this.Name = "Time Reference Adjuster";
-            this.Category = ReadoutCategory.GetCategory("Miscellaneous");
-            this.HelpString = String.Empty;
-            this.IsDefault = false;
-        }
-
-        #endregion
-
-        #region Methods: public
-
-        public override void Draw(SectionModule section)
-        {
-            GUILayout.BeginHorizontal();
-            GUILayout.Label("Time Ref.: " + TimeFormatter.Reference, this.NameStyle);
-            if (GUILayout.Button("Earth", this.ButtonStyle))
-            {
-                TimeFormatter.SetReference();
-            }
-            if (GUILayout.Button("Kerbin", this.ButtonStyle))
-            {
-                TimeFormatter.SetReference(PSystemManager.Instance.localBodies.Find(body => body.bodyName.Equals("Kerbin")));
-            }
-            GUILayout.EndHorizontal();
-        }
-
-        #endregion
-    }
-}

--- a/KerbalEngineer/Flight/Readouts/Orbital/AngleToEquatorialAscendingNode.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/AngleToEquatorialAscendingNode.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Angle to Equ. AN";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = string.Empty;
+            this.HelpString = "Angular Distance from the vessel to crossing the Equator of the central body, going north of it.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/AngleToEquatorialDescendingNode.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/AngleToEquatorialDescendingNode.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Angle to Equ. DN";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = string.Empty;
+            this.HelpString = "Angular Distance from the vessel to crossing the Equator of the central body, going south of it.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/AngleToPrograde.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/AngleToPrograde.cs
@@ -36,7 +36,7 @@
         {
             this.Name = "Angle to Prograde";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = String.Empty;
+            this.HelpString = "Angular Distance from the vessel to crossing the Orbit of the central body on it's retrograde side.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/AngleToRetrograde.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/AngleToRetrograde.cs
@@ -36,7 +36,7 @@
         {
             this.Name = "Angle to Retrograde";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = String.Empty;
+            this.HelpString = "Angular Distance from the vessel to crossing the Orbit of the central body on it's retrograde side.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/ApoapsisHeight.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ApoapsisHeight.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Apoapsis Height";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = "Shows the vessel's apoapsis height relative to sea level.  (Apoapsis is the highest point of an orbit.)";
+            this.HelpString = "Shows the vessel's apoapsis height relative to sea level. (Apoapsis is the highest point of an orbit.)";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/EccentricAnomaly.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/EccentricAnomaly.cs
@@ -1,7 +1,7 @@
 // 
 //     Kerbal Engineer Redux
 // 
-//     Copyright (C) 2014 CYBUTEK
+//     Copyright (C) 2015 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
@@ -17,38 +17,25 @@
 //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // 
 
-#region Using Directives
-
-using System;
-
-using KerbalEngineer.Extensions;
-using KerbalEngineer.Flight.Sections;
-
-#endregion
-
 namespace KerbalEngineer.Flight.Readouts.Orbital
 {
+    using Extensions;
+    using Helpers;
+    using Sections;
+
     public class EccentricAnomaly : ReadoutModule
     {
-        #region Constructors
-
         public EccentricAnomaly()
         {
-            this.Name = "Eccentric Anomaly";
-            this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = String.Empty;
-            this.IsDefault = false;
+            Name = "Eccentric Anomaly";
+            Category = ReadoutCategory.GetCategory("Orbital");
+            HelpString = string.Empty;
+            IsDefault = false;
         }
-
-        #endregion
-
-        #region Methods: public
 
         public override void Draw(SectionModule section)
         {
-            this.DrawLine(FlightGlobals.ship_orbit.eccentricAnomaly.ToAngle(), section.IsHud);
+            DrawLine((FlightGlobals.ship_orbit.eccentricAnomaly * Units.RAD_TO_DEG).ToAngle(), section.IsHud);
         }
-
-        #endregion
     }
 }

--- a/KerbalEngineer/Flight/Readouts/Orbital/Inclination.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/Inclination.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Inclination";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = "Shows the vessel's orbital inclination.";
+            this.HelpString = "Shows the vessel's orbital inclination relative to the Equator.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/ManoeuvreProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/ManoeuvreProcessor.cs
@@ -63,6 +63,10 @@
 
         public static double NormalDeltaV { get; private set; }
 
+        public static double PostBurnAp { get; private set; }
+
+        public static double PostBurnPe { get; private set; }
+
         public static double ProgradeDeltaV { get; private set; }
 
         public static double RadialDeltaV { get; private set; }
@@ -110,6 +114,8 @@
             NormalDeltaV = deltaV.y;
             RadialDeltaV = deltaV.x;
             TotalDeltaV = node.GetBurnVector(FlightGlobals.ship_orbit).magnitude;
+            PostBurnAp = node.nextPatch != null ? node.nextPatch.ApA : 0;
+            PostBurnPe = node.nextPatch != null ? node.nextPatch.PeA : 0;
 
             UniversalTime = FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes[0].UT;
             AngleToPrograde = FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes[0].patch.GetAngleToPrograde(UniversalTime);

--- a/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeAngleToPrograde.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeAngleToPrograde.cs
@@ -36,7 +36,7 @@
         {
             this.Name = "Manoeuvre Node Angle to Prograde";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = String.Empty;
+            this.HelpString = "Angular Distance from the Node to crossing the Orbit of the central body on it's prograde side.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeAngleToRetrograde.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeAngleToRetrograde.cs
@@ -36,7 +36,7 @@
         {
             this.Name = "Manoeuvre Node Angle to Retrograde";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = String.Empty;
+            this.HelpString = "Angular Distance from the Node to crossing the Orbit of the central body on it's retrograde side.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeBurnTime.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeBurnTime.cs
@@ -36,7 +36,7 @@
         {
             this.Name = "Manoeuvre Node Burn Time";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = String.Empty;
+            this.HelpString = "The burn's total duration.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeHalfBurnTime.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeHalfBurnTime.cs
@@ -36,7 +36,7 @@
         {
             this.Name = "Manoeuvre Node Half Burn Time";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = String.Empty;
+            this.HelpString = "Half of the burn's total duration.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeNormalDeltaV.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeNormalDeltaV.cs
@@ -36,7 +36,7 @@
         {
             this.Name = "Manoeuvre Node DeltaV (Normal)";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = String.Empty;
+            this.HelpString = "Normal component of the total change in velocity.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeProgradeDeltaV.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeProgradeDeltaV.cs
@@ -36,7 +36,7 @@
         {
             this.Name = "Manoeuvre Node DeltaV (Prograde)";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = String.Empty;
+            this.HelpString = "Prograde/Retrograde component of the total change in velocity.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeRadialDeltaV.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeRadialDeltaV.cs
@@ -36,7 +36,7 @@
         {
             this.Name = "Manoeuvre Node DeltaV (Radial)";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = String.Empty;
+            this.HelpString = "Radial component of the total change in velocity.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeTimeToHalfBurn.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeTimeToHalfBurn.cs
@@ -36,7 +36,7 @@
         {
             this.Name = "Time to Manoeuvre Burn";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = String.Empty;
+            this.HelpString = "Time until the Manoeuvre should be started.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeTimeToManoeuvre.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeTimeToManoeuvre.cs
@@ -36,7 +36,7 @@
         {
             this.Name = "Time to Manoeuvre Node";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = String.Empty;
+            this.HelpString = "Time until the vessel reaches the position of the Manoeuvre Node.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeTotalDeltaV.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeTotalDeltaV.cs
@@ -36,7 +36,7 @@
         {
             this.Name = "Manoeuvre Node DeltaV (Total)";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = String.Empty;
+            this.HelpString = "Total change in velocity during the burn.";
             this.IsDefault = true;
         }
 

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/PostBurnApoapsis.cs
@@ -1,1 +1,69 @@
+// 
+//     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 KerbalEngineer.Extensions;
+using KerbalEngineer.Flight.Sections;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Orbital.ManoeuvreNode
+{
+    public class PostBurnApoapsis : ReadoutModule
+    {
+        #region Constructors
+
+        public PostBurnApoapsis()
+        {
+            this.Name = "Post-burn Apoapsis";
+            this.Category = ReadoutCategory.GetCategory("Orbital");
+            this.HelpString = "Farthest point of the vessel's ofbit after the burn.";
+            this.IsDefault = false;
+        }
+
+        #endregion
+
+        #region Methods: public
+
+        public override void Draw(SectionModule section)
+        {
+            if (!ManoeuvreProcessor.ShowDetails)
+            {
+                return;
+            }
+
+            this.DrawLine("Post-burn Apoapsis", ManoeuvreProcessor.PostBurnAp.ToDistance(), section.IsHud);
+        }
+
+        public override void Reset()
+        {
+            ManoeuvreProcessor.Reset();
+        }
+
+        public override void Update()
+        {
+            ManoeuvreProcessor.RequestUpdate();
+        }
+
+        #endregion
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/PostBurnPeriapsis.cs
@@ -1,1 +1,69 @@
+// 
+//     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 KerbalEngineer.Extensions;
+using KerbalEngineer.Flight.Sections;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Orbital.ManoeuvreNode
+{
+    public class PostBurnPeriapsis : ReadoutModule
+    {
+        #region Constructors
+
+        public PostBurnPeriapsis()
+        {
+            this.Name = "Post-burn Periapsis";
+            this.Category = ReadoutCategory.GetCategory("Orbital");
+            this.HelpString = "Closest point of the vessel's ofbit after the burn.";
+            this.IsDefault = false;
+        }
+
+        #endregion
+
+        #region Methods: public
+
+        public override void Draw(SectionModule section)
+        {
+            if (!ManoeuvreProcessor.ShowDetails)
+            {
+                return;
+            }
+
+            this.DrawLine("Post-burn Periapsis", ManoeuvreProcessor.PostBurnPe.ToDistance(), section.IsHud);
+        }
+
+        public override void Reset()
+        {
+            ManoeuvreProcessor.Reset();
+        }
+
+        public override void Update()
+        {
+            ManoeuvreProcessor.RequestUpdate();
+        }
+
+        #endregion
+    }
+}

--- a/KerbalEngineer/Flight/Readouts/Orbital/MeanAnomaly.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/MeanAnomaly.cs
@@ -1,7 +1,7 @@
 // 
 //     Kerbal Engineer Redux
 // 
-//     Copyright (C) 2014 CYBUTEK
+//     Copyright (C) 2015 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
@@ -17,38 +17,25 @@
 //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // 
 
-#region Using Directives
-
-using System;
-
-using KerbalEngineer.Extensions;
-using KerbalEngineer.Flight.Sections;
-
-#endregion
-
 namespace KerbalEngineer.Flight.Readouts.Orbital
 {
+    using Extensions;
+    using Helpers;
+    using Sections;
+
     public class MeanAnomaly : ReadoutModule
     {
-        #region Constructors
-
         public MeanAnomaly()
         {
-            this.Name = "Mean Anomaly";
-            this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = String.Empty;
-            this.IsDefault = false;
+            Name = "Mean Anomaly";
+            Category = ReadoutCategory.GetCategory("Orbital");
+            HelpString = string.Empty;
+            IsDefault = false;
         }
-
-        #endregion
-
-        #region Methods: public
 
         public override void Draw(SectionModule section)
         {
-            this.DrawLine(FlightGlobals.ship_orbit.meanAnomaly.ToAngle(), section.IsHud);
+            DrawLine((FlightGlobals.ship_orbit.meanAnomaly * Units.RAD_TO_DEG).ToAngle(), section.IsHud);
         }
-
-        #endregion
     }
 }

--- a/KerbalEngineer/Flight/Readouts/Orbital/MeanAnomalyAtEpoc.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/MeanAnomalyAtEpoc.cs
@@ -1,7 +1,7 @@
 // 
 //     Kerbal Engineer Redux
 // 
-//     Copyright (C) 2014 CYBUTEK
+//     Copyright (C) 2015 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
@@ -17,38 +17,25 @@
 //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // 
 
-#region Using Directives
-
-using System;
-
-using KerbalEngineer.Extensions;
-using KerbalEngineer.Flight.Sections;
-
-#endregion
-
 namespace KerbalEngineer.Flight.Readouts.Orbital
 {
+    using Extensions;
+    using Helpers;
+    using Sections;
+
     public class MeanAnomalyAtEpoc : ReadoutModule
     {
-        #region Constructors
-
         public MeanAnomalyAtEpoc()
         {
-            this.Name = "Mean Anomaly at Epoc";
-            this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = String.Empty;
-            this.IsDefault = false;
+            Name = "Mean Anomaly at Epoc";
+            Category = ReadoutCategory.GetCategory("Orbital");
+            HelpString = string.Empty;
+            IsDefault = false;
         }
-
-        #endregion
-
-        #region Methods: public
 
         public override void Draw(SectionModule section)
         {
-            this.DrawLine(FlightGlobals.ship_orbit.meanAnomalyAtEpoch.ToAngle(), section.IsHud);
+            DrawLine((FlightGlobals.ship_orbit.meanAnomalyAtEpoch * Units.RAD_TO_DEG).ToAngle(), section.IsHud);
         }
-
-        #endregion
     }
 }

--- a/KerbalEngineer/Flight/Readouts/Orbital/PeriapsisHeight.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/PeriapsisHeight.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Periapsis Height";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = "Shows the vessel's periapsis height relative to sea level. (Periapsis is the lowest point of an orbit.";
+            this.HelpString = "Shows the vessel's periapsis height relative to sea level. (Periapsis is the lowest point of an orbit.)";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/TimeToAtmosphere.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/TimeToAtmosphere.cs
@@ -37,7 +37,7 @@
         {
             this.Name = "Time to Atmosphere";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = "Shows the time until the vessel enters or leaves atmosphere.";
+            this.HelpString = "Shows the time until the vessel enters or leaves the atmosphere.";
             this.IsDefault = false;
         }
 
@@ -50,7 +50,7 @@
             String str;
             Orbit orbit = FlightGlobals.ship_orbit;
 
-            if (orbit.referenceBody.atmosphere && orbit.PeA < orbit.referenceBody.atmosphereDepth)
+			if (orbit.referenceBody.atmosphere && orbit.PeA < orbit.referenceBody.atmosphereDepth && orbit.ApA > orbit.referenceBody.atmosphereDepth)
             {
                 double tA = orbit.TrueAnomalyAtRadius(orbit.referenceBody.atmosphereDepth + orbit.referenceBody.Radius);
                 //log.buf.AppendFormat("tA = {0}\n", tA);
@@ -87,7 +87,7 @@
             else
             {
                 str = "---s";
-                //log.buf.AppendLine("no atmosphere or pe > atmosphere");
+                //log.buf.AppendLine("no atmosphere, pe > atmosphere, or ap < atmosphere");
             }
 
             //log.Flush();

--- a/KerbalEngineer/Flight/Readouts/Orbital/TimeToEquatorialAscendingNode.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/TimeToEquatorialAscendingNode.cs
@@ -35,7 +35,7 @@
         {
             this.Name = "Time to Equ. AN";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the time until the vessel corsses the Equator, going north of it.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Orbital/TimeToEquatorialDescendingNode.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/TimeToEquatorialDescendingNode.cs
@@ -35,7 +35,7 @@
         {
             this.Name = "Time to Equ. DN";
             this.Category = ReadoutCategory.GetCategory("Orbital");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the time until the vessel corsses the Equator, going south of it.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/ReadoutLibrary.cs
+++ b/KerbalEngineer/Flight/Readouts/ReadoutLibrary.cs
@@ -91,6 +91,8 @@
                 readouts.Add(new NodeTimeToHalfBurn());
                 readouts.Add(new NodeAngleToPrograde());
                 readouts.Add(new NodeAngleToRetrograde());
+                readouts.Add(new PostBurnApoapsis());
+                readouts.Add(new PostBurnPeriapsis());
                 readouts.Add(new SpeedAtApoapsis());
                 readouts.Add(new SpeedAtPeriapsis());
                 readouts.Add(new TimeToAtmosphere());
@@ -118,6 +120,7 @@
                 readouts.Add(new ImpactBiome());
 
                 // Vessel
+                readouts.Add(new Name());
                 readouts.Add(new DeltaVStaged());
                 readouts.Add(new DeltaVCurrent());
                 readouts.Add(new DeltaVTotal());
@@ -165,6 +168,8 @@
                 readouts.Add(new Rendezvous.OrbitalPeriod());
                 readouts.Add(new Rendezvous.SemiMajorAxis());
                 readouts.Add(new Rendezvous.SemiMinorAxis());
+                readouts.Add(new Rendezvous.RelativeRadialVelocity());
+                readouts.Add(new Rendezvous.TimeToRendezvous());
 
                 // Thermal
                 readouts.Add(new InternalFlux());
@@ -185,7 +190,6 @@
                 readouts.Add(new Separator());
                 readouts.Add(new GuiSizeAdjustor());
                 readouts.Add(new SimulationDelay());
-                readouts.Add(new TimeReference());
                 readouts.Add(new VectoredThrustToggle());
                 readouts.Add(new SystemTime());
 

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/AltitudeSeaLevel.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/AltitudeSeaLevel.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Altitude (Sea Level)";
             this.Category = ReadoutCategory.GetCategory("Rendezvous");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the target's altitude above sea level.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/AngleToRelativeAscendingNode.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/AngleToRelativeAscendingNode.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Angle to Rel. AN";
             this.Category = ReadoutCategory.GetCategory("Rendezvous");
-            this.HelpString = string.Empty;
+            this.HelpString = "Angular Distance from the vessel to crossing the orbit of the target object, going north of it.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/AngleToRelativeDescendingNode.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/AngleToRelativeDescendingNode.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Angle to Rel. DN";
             this.Category = ReadoutCategory.GetCategory("Rendezvous");
-            this.HelpString = string.Empty;
+            this.HelpString = "Angular Distance from the vessel to crossing the orbit of the target object, going south of it.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/ApoapsisHeight.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/ApoapsisHeight.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Apoapsis Height";
             this.Category = ReadoutCategory.GetCategory("Rendezvous");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the targets's apoapsis height relative to sea level. (Apoapsis is the highest point of an orbit.)";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/Distance.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/Distance.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Distance";
             this.Category = ReadoutCategory.GetCategory("Rendezvous");
-            this.HelpString = string.Empty;
+            this.HelpString = "Current distance between the vessel and the target object.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/OrbitalPeriod.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/OrbitalPeriod.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Orbital Period";
             this.Category = ReadoutCategory.GetCategory("Rendezvous");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the amount of time it will take the target object to complete a full orbit.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/PeriapsisHeight.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/PeriapsisHeight.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Periapsis Height";
             this.Category = ReadoutCategory.GetCategory("Rendezvous");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the targets's periapsis height relative to sea level. (Periapsis is the lowest point of an orbit.)";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/PhaseAngle.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/PhaseAngle.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Phase Angle";
             this.Category = ReadoutCategory.GetCategory("Rendezvous");
-            this.HelpString = string.Empty;
+            this.HelpString = "Angular distance of the vessel relative to the target object.";
             this.IsDefault = true;
         }
 

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/RelativeRadialVelocity.cs
@@ -1,1 +1,66 @@
+// 
+//     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.Extensions;
+using KerbalEngineer.Flight.Sections;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Rendezvous
+{
+    public class RelativeRadialVelocity : ReadoutModule
+    {
+        #region Constructors
+
+        public RelativeRadialVelocity()
+        {
+            this.Name = "Relative Radial Velocity";
+            this.Category = ReadoutCategory.GetCategory("Rendezvous");
+            this.HelpString = "Relative radial velocity between your vessel and the target object";
+            this.IsDefault = false;
+        }
+
+        #endregion
+
+        #region Methods: public
+
+        public override void Draw(SectionModule section)
+        {
+            if (RendezvousProcessor.ShowDetails)
+            {
+               this.DrawLine(RendezvousProcessor.RelativeRadialVelocity.ToSpeed(), section.IsHud);
+            }
+        }
+
+        public override void Reset()
+        {
+            FlightEngineerCore.Instance.AddUpdatable(RendezvousProcessor.Instance);
+        }
+
+        public override void Update()
+        {
+            RendezvousProcessor.RequestUpdate();
+        }
+
+        #endregion
+    }
+}
+

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/RendezvousProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/RendezvousProcessor.cs
@@ -135,6 +135,16 @@
         ///     Gets the target's time to periapsis.
         /// </summary>
         public static double TimeToPeriapsis { get; private set; }
+
+        /// <summary>
+        ///     Gets the relative radial velocity.
+        /// </summary>
+        public static double RelativeRadialVelocity { get; private set; }
+
+        /// <summary>
+        ///     Gets approximate (linearly) time to the minimum distance between objects.
+        /// </summary>
+        public static double TimeToRendezvous { get; private set; }
 
         /// <summary>
         ///     Gets and sets whether the updatable object should be updated.
@@ -193,6 +203,14 @@
 
             Distance = Vector3d.Distance(targetOrbit.pos, originOrbit.pos);
             OrbitalPeriod = targetOrbit.period;
+
+            // beware that the order/sign of coordinates is inconsistent across different exposed variables
+            // in particular, v below does not equal to FlightGlobals.ship_tgtVelocity
+            Vector3d x = targetOrbit.pos - originOrbit.pos;
+            Vector3d v = targetOrbit.vel - originOrbit.vel;
+            double xv = Vector3d.Dot(x, v);
+            TimeToRendezvous = - xv / Vector3d.SqrMagnitude(v);
+            RelativeRadialVelocity = xv / Vector3d.Magnitude(x);
         }
 
         private double CalcInterceptAngle()

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/SemiMajorAxis.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/SemiMajorAxis.cs
@@ -36,7 +36,7 @@
         {
             this.Name = "Semi-major Axis";
             this.Category = ReadoutCategory.GetCategory("Rendezvous");
-            this.HelpString = String.Empty;
+            this.HelpString = "Shows the distance from the centre of the target's orbit to the farthest edge.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/SemiMinorAxis.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/SemiMinorAxis.cs
@@ -36,7 +36,7 @@
         {
             this.Name = "Semi-minor Axis";
             this.Category = ReadoutCategory.GetCategory("Rendezvous");
-            this.HelpString = String.Empty;
+            this.HelpString = "Shows the distance from the centre of the target's orbit to the nearest edge.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/TimeToApoapsis.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/TimeToApoapsis.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Time to Apoapsis";
             this.Category = ReadoutCategory.GetCategory("Rendezvous");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the time until the target reaches apoapsis, the highest point of the orbit.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/TimeToPeriapsis.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/TimeToPeriapsis.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Time to Periapsis";
             this.Category = ReadoutCategory.GetCategory("Rendezvous");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the time until the target reaches periapsis, the lowest point of the orbit.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/TimeToRelativeAscendingNode.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/TimeToRelativeAscendingNode.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Time to Rel. AN";
             this.Category = ReadoutCategory.GetCategory("Rendezvous");
-            this.HelpString = string.Empty;
+            this.HelpString = "Time until the vessel crosses the target's orbit, going north.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/TimeToRelativeDescendingNode.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/TimeToRelativeDescendingNode.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Time to Rel. DN";
             this.Category = ReadoutCategory.GetCategory("Rendezvous");
-            this.HelpString = string.Empty;
+            this.HelpString = "Time until the vessel crosses the target's orbit, going south.";
             this.IsDefault = true;
         }
 

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/TimeToRendezvous.cs
@@ -1,1 +1,65 @@
+// 
+//     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.Flight.Sections;
+using KerbalEngineer.Helpers;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Rendezvous
+{
+    public class TimeToRendezvous : ReadoutModule
+    {
+        #region Constructors
+
+        public TimeToRendezvous()
+        {
+            this.Name = "Time to Rendezvous";
+            this.Category = ReadoutCategory.GetCategory("Rendezvous");
+            this.HelpString = "Approximate (linearly) time to the minimum distance between objects.";
+            this.IsDefault = false;
+        }
+
+        #endregion
+
+        #region Methods: public
+
+        public override void Draw(SectionModule section)
+        {
+            if (RendezvousProcessor.ShowDetails)
+            {
+               this.DrawLine(TimeFormatter.ConvertToString(RendezvousProcessor.TimeToRendezvous), section.IsHud);
+            }
+        }
+
+        public override void Reset()
+        {
+            FlightEngineerCore.Instance.AddUpdatable(RendezvousProcessor.Instance);
+        }
+
+        public override void Update()
+        {
+            RendezvousProcessor.RequestUpdate();
+        }
+
+        #endregion
+    }
+}

--- a/KerbalEngineer/Flight/Readouts/Surface/HorizontalSpeed.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/HorizontalSpeed.cs
@@ -21,6 +21,7 @@
 
 using KerbalEngineer.Extensions;
 using KerbalEngineer.Flight.Sections;
+using System;
 
 #endregion
 
@@ -44,7 +45,11 @@
 
         public override void Draw(SectionModule section)
         {
-            this.DrawLine(FlightGlobals.ActiveVessel.horizontalSrfSpeed.ToSpeed(), section.IsHud);
+            // Used to do this but the bug-fix to horizontalSrfSpeed in KSP 1.0.3 actually made it worse so workaround
+            //this.DrawLine(FlightGlobals.ActiveVessel.horizontalSrfSpeed.ToSpeed(), section.IsHud);
+            var ves = FlightGlobals.ActiveVessel;
+            double horizSpeed = Math.Sqrt(ves.srfSpeed * ves.srfSpeed - ves.verticalSpeed * ves.verticalSpeed);
+            this.DrawLine(horizSpeed.ToSpeed(), section.IsHud);
         }
 
         #endregion

--- a/KerbalEngineer/Flight/Readouts/Surface/ImpactAltitude.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/ImpactAltitude.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Impact Altitude";
             this.Category = ReadoutCategory.GetCategory("Surface");
-            this.HelpString = string.Empty;
+            this.HelpString = "Altitude at which the Vessel will impact.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Surface/ImpactBiome.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/ImpactBiome.cs
@@ -33,7 +33,7 @@
         {
             this.Name = "Impact Biome";
             this.Category = ReadoutCategory.GetCategory("Surface");
-            this.HelpString = string.Empty;
+            this.HelpString = "Biome the Vessel will impact in.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Surface/ImpactLatitude.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/ImpactLatitude.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Impact Latitude";
             this.Category = ReadoutCategory.GetCategory("Surface");
-            this.HelpString = string.Empty;
+            this.HelpString = "Latitude of the impact position.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Surface/ImpactLongitude.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/ImpactLongitude.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Impact Longitude";
             this.Category = ReadoutCategory.GetCategory("Surface");
-            this.HelpString = string.Empty;
+            this.HelpString = "Longditude of the impact position.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Surface/ImpactTime.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/ImpactTime.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Impact Time";
             this.Category = ReadoutCategory.GetCategory("Surface");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows time until the vessel impacts the central object.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Surface/Latitude.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/Latitude.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Latitude";
             this.Category = ReadoutCategory.GetCategory("Surface");
-            this.HelpString = "Shows the vessel's latitude position around the celestial body.  Latitude is the angle from the equator to poles.";
+            this.HelpString = "Shows the vessel's latitude position around the celestial body. Latitude is the angle from the equator to poles.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Surface/Longitude.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/Longitude.cs
@@ -28,7 +28,7 @@
         {
             Name = "Longitude";
             Category = ReadoutCategory.GetCategory("Surface");
-            HelpString = "Shows the vessel's longitude around a celestial body.  Longitude is the angle from the bodies prime meridian.";
+            HelpString = "Shows the vessel's longitude around a celestial body. Longitude is the angle from the bodies prime meridian.";
             IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Surface/Situation.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/Situation.cs
@@ -33,7 +33,7 @@
         {
             this.Name = "Situation";
             this.Category = ReadoutCategory.GetCategory("Surface");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the vessel's current scientific situation. (Landed, Splashed, Flying Low/High, In Space Low/High)";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Thermal/CoolestPart.cs
+++ b/KerbalEngineer/Flight/Readouts/Thermal/CoolestPart.cs
@@ -27,7 +27,7 @@
         {
             Name = "Coolest Part";
             Category = ReadoutCategory.GetCategory("Thermal");
-            HelpString = string.Empty;
+            HelpString = "The part of the vessel that is enduring the lowest temperature.";
             IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Thermal/CoolestSkinTemperature.cs
+++ b/KerbalEngineer/Flight/Readouts/Thermal/CoolestSkinTemperature.cs
@@ -28,7 +28,7 @@
         {
             Name = "Coolest Skin Temperature";
             Category = ReadoutCategory.GetCategory("Thermal");
-            HelpString = string.Empty;
+            HelpString = "Lowest external Temperature on the Vessel.";
             IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Thermal/CoolestTemperature.cs
+++ b/KerbalEngineer/Flight/Readouts/Thermal/CoolestTemperature.cs
@@ -28,7 +28,7 @@
         {
             Name = "Coolest Temperature";
             Category = ReadoutCategory.GetCategory("Thermal");
-            HelpString = string.Empty;
+            HelpString = "Lowest internal Temperature on the Vessel.";
             IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Thermal/CriticalPart.cs
+++ b/KerbalEngineer/Flight/Readouts/Thermal/CriticalPart.cs
@@ -27,7 +27,7 @@
         {
             Name = "Critical Part";
             Category = ReadoutCategory.GetCategory("Thermal");
-            HelpString = string.Empty;
+            HelpString = "This part is structually most critical. If it endures too high temperature there is a high chance for major structual failure!";
             IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Thermal/CriticalSkinTemperature.cs
+++ b/KerbalEngineer/Flight/Readouts/Thermal/CriticalSkinTemperature.cs
@@ -28,7 +28,7 @@
         {
             Name = "Critical Skin Temperature";
             Category = ReadoutCategory.GetCategory("Thermal");
-            HelpString = string.Empty;
+            HelpString = "Highest external Temperature on the part of the Vessel that is structually most critical.";
             IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Thermal/CriticalTemperature.cs
+++ b/KerbalEngineer/Flight/Readouts/Thermal/CriticalTemperature.cs
@@ -28,7 +28,7 @@
         {
             Name = "Critical Temperature";
             Category = ReadoutCategory.GetCategory("Thermal");
-            HelpString = string.Empty;
+            HelpString = "Internal Temperature on the part of the Vessel that is structually most critical.";
             IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Thermal/CriticalThermalPercentage.cs
+++ b/KerbalEngineer/Flight/Readouts/Thermal/CriticalThermalPercentage.cs
@@ -28,7 +28,7 @@
         {
             Name = "Critical Thermal Percentage";
             Category = ReadoutCategory.GetCategory("Thermal");
-            HelpString = string.Empty;
+            HelpString = "Shows how high a temperature the critical Part is enduring relative to it's maximal temperature.";
             IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Thermal/HottestPart.cs
+++ b/KerbalEngineer/Flight/Readouts/Thermal/HottestPart.cs
@@ -27,7 +27,7 @@
         {
             Name = "Hottest Part";
             Category = ReadoutCategory.GetCategory("Thermal");
-            HelpString = string.Empty;
+            HelpString = "The part of the vessel that is enduring the highest temperature.";
             IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Thermal/HottestSkinTemperature.cs
+++ b/KerbalEngineer/Flight/Readouts/Thermal/HottestSkinTemperature.cs
@@ -28,7 +28,7 @@
         {
             Name = "Hottest Skin Temperature";
             Category = ReadoutCategory.GetCategory("Thermal");
-            HelpString = string.Empty;
+            HelpString = "Highest external Temperature on the Vessel.";
             IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Thermal/HottestTemperature.cs
+++ b/KerbalEngineer/Flight/Readouts/Thermal/HottestTemperature.cs
@@ -28,7 +28,7 @@
         {
             Name = "Hottest Temperature";
             Category = ReadoutCategory.GetCategory("Thermal");
-            HelpString = string.Empty;
+            HelpString = "Highest internal Temperature on the Vessel.";
             IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Vessel/Acceleration.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Acceleration.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Acceleration";
             this.Category = ReadoutCategory.GetCategory("Vessel");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the current and maximum acceleration of the craft.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Vessel/AttitudeProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/AttitudeProcessor.cs
@@ -110,8 +110,8 @@
                 ? 360.0f - this.surfaceRotation.eulerAngles.x
                 : -this.surfaceRotation.eulerAngles.x;
             this.roll = this.surfaceRotation.eulerAngles.z > 180.0f
-                ? this.surfaceRotation.eulerAngles.z - 360.0f
-                : this.surfaceRotation.eulerAngles.z;
+                ? 360.0f - this.surfaceRotation.eulerAngles.z
+                : -this.surfaceRotation.eulerAngles.z;
 
             this.headingRate = this.heading - this.previousHeading;
             this.pitchRate = this.pitch - this.previousPitch;

--- a/KerbalEngineer/Flight/Readouts/Vessel/Heading.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Heading.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Heading";
             this.Category = ReadoutCategory.GetCategory("Vessel");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the current Heading.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Vessel/HeadingRate.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/HeadingRate.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Heading Rate";
             this.Category = ReadoutCategory.GetCategory("Vessel");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the current change in Heading.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Vessel/IntakeAirDemand.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/IntakeAirDemand.cs
@@ -39,7 +39,7 @@
         {
             this.Name = "Intake Air (Demand)";
             this.Category = ReadoutCategory.GetCategory("Vessel");
-            this.HelpString = string.Empty;
+            this.HelpString = "Displays the Amount of Intake Air required.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Vessel/IntakeAirDemandSupply.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/IntakeAirDemandSupply.cs
@@ -42,7 +42,7 @@
         {
             this.Name = "Intake Air (D/S)";
             this.Category = ReadoutCategory.GetCategory("Vessel");
-            this.HelpString = string.Empty;
+            this.HelpString = "Displays the Ration between required and available Intake Air.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Vessel/IntakeAirSupply.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/IntakeAirSupply.cs
@@ -39,7 +39,7 @@
         {
             this.Name = "Intake Air (Supply)";
             this.Category = ReadoutCategory.GetCategory("Vessel");
-            this.HelpString = string.Empty;
+            this.HelpString = "Displays the available Intake Air.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Vessel/IntakeAirUsage.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/IntakeAirUsage.cs
@@ -42,7 +42,7 @@
         {
             this.Name = "Intake Air (Usage)";
             this.Category = ReadoutCategory.GetCategory("Vessel");
-            this.HelpString = string.Empty;
+            this.HelpString = "Displays the consumption of Intake Air.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Vessel/Mass.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Mass.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Mass";
             this.Category = ReadoutCategory.GetCategory("Vessel");
-            this.HelpString = string.Empty;
+            this.HelpString = "Displays the total Mass of the Vessel.";
             this.IsDefault = true;
         }
 

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Name.cs
@@ -1,1 +1,55 @@
+// 
+//     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.Flight.Sections;
+using KerbalEngineer.Helpers;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+    public class Name : ReadoutModule
+    {
+        #region Constructors
+
+        public Name()
+        {
+            Name = "Name";
+            Category = ReadoutCategory.GetCategory("Vessel");
+            HelpString = "Displays the name of the current vessel.";
+            IsDefault = true;
+        }
+
+        #endregion
+
+        #region Methods: public
+
+        public override void Draw(SectionModule section)
+        {
+            if (SimulationProcessor.ShowDetails)
+            {
+                DrawLine(FlightGlobals.ActiveVessel.vesselName);
+            }
+        }
+
+        #endregion
+    }
+}

--- a/KerbalEngineer/Flight/Readouts/Vessel/PartCount.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/PartCount.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Part Count";
             this.Category = ReadoutCategory.GetCategory("Vessel");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the total number of Parts the current and next stage.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Vessel/Pitch.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Pitch.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Pitch";
             this.Category = ReadoutCategory.GetCategory("Vessel");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the current Pitch angle.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Vessel/PitchRate.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/PitchRate.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Pitch Rate";
             this.Category = ReadoutCategory.GetCategory("Vessel");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the current Pitch speed.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Vessel/Roll.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Roll.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Roll";
             this.Category = ReadoutCategory.GetCategory("Vessel");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the current Roll angle.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Vessel/RollRate.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/RollRate.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Roll Rate";
             this.Category = ReadoutCategory.GetCategory("Vessel");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the current Roll speed.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Vessel/SpecificImpulse.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/SpecificImpulse.cs
@@ -33,7 +33,7 @@
         {
             this.Name = "Specific Impulse";
             this.Category = ReadoutCategory.GetCategory("Vessel");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the average Specific Impulse of all engines in the current stage.";
             this.IsDefault = false;
         }
 

--- a/KerbalEngineer/Flight/Readouts/Vessel/Thrust.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Thrust.cs
@@ -34,7 +34,7 @@
         {
             this.Name = "Thrust";
             this.Category = ReadoutCategory.GetCategory("Vessel");
-            this.HelpString = string.Empty;
+            this.HelpString = "Shows the current and maximum thrust the vessel can put out.";
             this.IsDefault = true;
         }
 

--- a/KerbalEngineer/Helpers/TimeFormatter.cs
+++ b/KerbalEngineer/Helpers/TimeFormatter.cs
@@ -1,7 +1,5 @@
 // 
-//     Kerbal Engineer Redux
-// 
-//     Copyright (C) 2014 CYBUTEK
+//     Copyright (C) 2015 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
@@ -17,147 +15,46 @@
 //     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // 
 
-#region Using Directives
-
-using System;
-
-using KerbalEngineer.Settings;
-
-#endregion
-
 namespace KerbalEngineer.Helpers
 {
     public static class TimeFormatter
     {
-        #region Constructors
-
-        static TimeFormatter()
-        {
-            SetReference(false);
-            Load();
-        }
-
-        #endregion
-
-        #region Properties
-
-        public static string Reference { get; set; }
-
-        public static double SecondsPerDay { get; set; }
-
-        public static double SecondsPerHour { get; set; }
-
-        public static double SecondsPerMinute { get; set; }
-
-        public static double SecondsPerYear { get; set; }
-
-        #endregion
-
-        #region Methods: public
-
         public static string ConvertToString(double seconds, string format = "F1")
         {
-            var years = 0;
-            while (seconds >= SecondsPerYear)
+            int years = 0;
+            int days = 0;
+            int hours = 0;
+            int minutes = 0;
+
+            if (seconds > 0.0)
             {
-                years++;
-                seconds -= SecondsPerYear;
-            }
+                years = (int)(seconds / KSPUtil.Year);
+                seconds -= years * KSPUtil.Year;
 
-            var days = 0;
-            while (seconds >= SecondsPerDay)
-            {
-                days++;
-                seconds -= SecondsPerDay;
-            }
+                days = (int)(seconds / KSPUtil.Day);
+                seconds -= days * KSPUtil.Day;
 
-            var hours = 0;
-            while (seconds >= SecondsPerHour)
-            {
-                hours++;
-                seconds -= SecondsPerHour;
-            }
+                hours = (int)(seconds / 3600.0);
+                seconds -= hours * 3600.0;
 
-            var minutes = 0;
-            while (seconds >= SecondsPerMinute)
-            {
-                minutes++;
-                seconds -= SecondsPerMinute;
+                minutes = (int)(seconds / 60.0);
+                seconds -= minutes * 60.0;
             }
 
             if (years > 0)
             {
-                return String.Format("{0}y {1}d {2}h {3}m {4}s", years, days, hours, minutes, seconds.ToString(format));
+                return string.Format("{0}y {1}d {2}h {3}m {4}s", years, days, hours, minutes, seconds.ToString(format));
             }
             if (days > 0)
             {
-                return String.Format("{0}d {1}h {2}m {3}s", days, hours, minutes, seconds.ToString(format));
+                return string.Format("{0}d {1}h {2}m {3}s", days, hours, minutes, seconds.ToString(format));
             }
             if (hours > 0)
             {
-                return String.Format("{0}h {1}m {2}s", hours, minutes, seconds.ToString(format));
+                return string.Format("{0}h {1}m {2}s", hours, minutes, seconds.ToString(format));
             }
 
-            return minutes > 0 ? String.Format("{0}m {1}s", minutes, seconds.ToString(format)) : String.Format("{0}s", seconds.ToString(format));
+            return minutes > 0 ? string.Format("{0}m {1}s", minutes, seconds.ToString(format)) : string.Format("{0}s", seconds.ToString(format));
         }
-
-        public static void Load()
-        {
-            var handler = SettingHandler.Load("TimeFormatter.xml");
-            SecondsPerMinute = handler.Get("SecondsPerMinute", SecondsPerMinute);
-            SecondsPerHour = handler.Get("SecondsPerHour", SecondsPerHour);
-            SecondsPerDay = handler.Get("SecondsPerDay", SecondsPerDay);
-            SecondsPerYear = handler.Get("SecondsPerYear", SecondsPerYear);
-            Reference = handler.Get("Reference", Reference);
-        }
-
-        public static void Save()
-        {
-            var handler = SettingHandler.Load("TimeFormatter.xml");
-            handler.Set("SecondsPerMinute", SecondsPerMinute);
-            handler.Set("SecondsPerHour", SecondsPerHour);
-            handler.Set("SecondsPerDay", SecondsPerDay);
-            handler.Set("SecondsPerYear", SecondsPerYear);
-            handler.Set("Reference", Reference);
-            handler.Save("TimeFormatter.xml");
-        }
-
-        public static void SetReference(bool save = true)
-        {
-            const double minute = 60.0;
-            const double hour = minute * 60.0;
-            const double day = hour * 24.0;
-            const double year = day * 365.0;
-            SetReference(minute, hour, day, year, "Earth", save);
-        }
-
-        public static void SetReference(CelestialBody body, bool save = true)
-        {
-            SetReference(SecondsPerMinute, SecondsPerHour, body.rotationPeriod, body.orbit.period, body.bodyName, save);
-        }
-
-        public static void SetReference(double minute, double hour, double day, double year, string reference, bool save = true)
-        {
-            SecondsPerMinute = minute;
-            SecondsPerHour = hour;
-            SecondsPerDay = day;
-            SecondsPerYear = year;
-            Reference = reference;
-
-            if (save)
-            {
-                Save();
-            }
-        }
-
-        public new static string ToString()
-        {
-            return String.Format("SecondsPerMinute: {0}", SecondsPerMinute) + Environment.NewLine +
-                   String.Format("SecondsPerHour: {0}", SecondsPerHour) + Environment.NewLine +
-                   String.Format("SecondsPerDay: {0}", SecondsPerDay) + Environment.NewLine +
-                   String.Format("SecondsPerYear: {0}", SecondsPerYear) + Environment.NewLine;
-        }
-
-        #endregion
     }
 }

--- a/KerbalEngineer/Helpers/Units.cs
+++ b/KerbalEngineer/Helpers/Units.cs
@@ -24,6 +24,8 @@
     public static class Units
     {
         public const double GRAVITY = 9.80665;
+        public const double RAD_TO_DEG = 180.0 / Math.PI;
+        public const double DEG_TO_RAD = Math.PI / 180.0;
 
         public static string Concat(int value1, int value2)
         {
@@ -91,7 +93,7 @@
             int min = (int)Math.Floor(rem * 60);
             rem -= ((double)min / 60);
             int sec = (int)Math.Floor(rem * 3600);
-            return String.Format("{0:0}° {1:00}' {2:00}\"", deg, min, sec);
+            return string.Format("{0:0}° {1:00}' {2:00}\"", deg, min, sec);
         }
 
         public static string ToDistance(double value, int decimals = 1)
@@ -130,13 +132,13 @@
 
         public static string ToForce(double value)
         {
-            return value.ToString((value < 100000.0) ? (value < 10000.0) ? (value < 100.0) ? (Math.Abs(value) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0") + "kN";
+            return value.ToString((value < 100000.0) ? (value < 10000.0) ? (value < 100.0) ? (Math.Abs(value) < double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0") + "kN";
         }
 
         public static string ToForce(double value1, double value2)
         {
-            string format1 = (value1 < 100000.0) ? (value1 < 10000.0) ? (value1 < 100.0) ? (Math.Abs(value1) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0";
-            string format2 = (value2 < 100000.0) ? (value2 < 10000.0) ? (value2 < 100.0) ? (Math.Abs(value2) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0";
+            string format1 = (value1 < 100000.0) ? (value1 < 10000.0) ? (value1 < 100.0) ? (Math.Abs(value1) < double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0";
+            string format2 = (value2 < 100000.0) ? (value2 < 10000.0) ? (value2 < 100.0) ? (Math.Abs(value2) < double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0";
             return value1.ToString(format1) + " / " + value2.ToString(format2) + "kN";
         }
 
@@ -205,7 +207,7 @@
 
         public static string ToTorque(double value)
         {
-            return value.ToString((value < 100.0) ? (Math.Abs(value) < Double.Epsilon) ? "N0" : "N1" : "N0") + "kNm";
+            return value.ToString((value < 100.0) ? (Math.Abs(value) < double.Epsilon) ? "N0" : "N2" : "N0") + "kNm";
         }
     }
 }

--- /dev/null
+++ b/KerbalEngineer/Helpers/XmlHelper.cs
@@ -1,1 +1,67 @@
+namespace KerbalEngineer.Helpers
+{
+    using System;
+    using System.IO;
+    using System.Text;
+    using System.Xml.Serialization;
 
+    public static class XmlHelper
+    {
+        /// <summary>
+        ///     Loads an object from disk.
+        /// </summary>
+        public static T LoadObject<T>(string path)
+        {
+            T obj = default(T);
+
+            if (File.Exists(path))
+            {
+                try
+                {
+                    using (StreamReader stream = new StreamReader(path, Encoding.UTF8))
+                    {
+                        obj = (T)new XmlSerializer(typeof(T)).Deserialize(stream);
+                    }
+                }
+                catch (Exception ex)
+                {
+                    Logger.Exception(ex);
+                }
+            }
+
+            return obj;
+        }
+
+        /// <summary>
+        ///     Loads and object from disk.
+        /// </summary>
+        public static bool LoadObject<T>(string path, out T obj)
+        {
+            obj = LoadObject<T>(path);
+            return (obj != null);
+        }
+
+        /// <summary>
+        ///     Saves an object to disk.
+        /// </summary>
+        public static void SaveObject<T>(string path, T obj)
+        {
+            if (obj == null || string.IsNullOrEmpty(path))
+            {
+                return;
+            }
+
+            try
+            {
+                using (StreamWriter stream = new StreamWriter(path, false, Encoding.UTF8))
+                {
+                    new XmlSerializer(typeof(T)).Serialize(stream, obj);
+                }
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+    }
+}

--- a/KerbalEngineer/KerbalEngineer.csproj
+++ b/KerbalEngineer/KerbalEngineer.csproj
@@ -53,7 +53,6 @@
     <Compile Include="Flight\Presets\Preset.cs" />
     <Compile Include="Flight\Readouts\Miscellaneous\SystemTime.cs" />
     <Compile Include="Flight\Readouts\Miscellaneous\VectoredThrustToggle.cs" />
-    <Compile Include="Flight\Readouts\Miscellaneous\TimeReference.cs" />
     <Compile Include="Flight\Readouts\Miscellaneous\Separator.cs" />
     <Compile Include="Flight\Readouts\Miscellaneous\GuiSizeAdjustor.cs" />
     <Compile Include="Flight\Readouts\Orbital\AngleToEquatorialDescendingNode.cs" />
@@ -71,6 +70,8 @@
     <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeAngleToPrograde.cs" />
     <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeTotalDeltaV.cs" />
     <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeProgradeDeltaV.cs" />
+    <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\PostBurnApoapsis.cs" />
+    <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\PostBurnPeriapsis.cs" />
     <Compile Include="Flight\Readouts\Orbital\MeanAnomalyAtEpoc.cs" />
     <Compile Include="Flight\Readouts\Orbital\MeanAnomaly.cs" />
     <Compile Include="Flight\Readouts\Orbital\EccentricAnomaly.cs" />
@@ -113,6 +114,7 @@
     <Compile Include="Flight\Readouts\Thermal\HottestTemperature.cs" />
     <Compile Include="Flight\Readouts\Thermal\HottestPart.cs" />
     <Compile Include="Flight\Readouts\Thermal\ThermalProcessor.cs" />
+    <Compile Include="Flight\Readouts\Vessel\Name.cs" />
     <Compile Include="Flight\Readouts\Vessel\AttitudeProcessor.cs" />
     <Compile Include="Flight\Readouts\Vessel\DeltaVCurrentTotal.cs" />
     <Compile Include="Flight\Readouts\Vessel\PitchRate.cs" />
@@ -146,8 +148,10 @@
     <Compile Include="Helpers\TextureHelper.cs" />
     <Compile Include="Helpers\Units.cs" />
     <Compile Include="Helpers\TimeFormatter.cs" />
-    <Compile Include="KeyBinder.cs" />
+    <Compile Include="Helpers\XmlHelper.cs" />
+    <Compile Include="KeyBinding\KeyBinder.cs" />
     <Compile Include="Control\ControlCentre.cs" />
+    <Compile Include="KeyBinding\KeyBindingsObject.cs" />
     <Compile Include="UIControls\DropDown.cs" />
     <Compile Include="Logger.cs" />
     <Compile Include="EngineerGlobals.cs" />
@@ -219,6 +223,7 @@
     <Compile Include="Settings\SettingHandler.cs" />
     <Compile Include="Settings\SettingItem.cs" />
     <Compile Include="TapeDriveAnimator.cs" />
+    <Compile Include="KeyBinding\KeyBindPopup.cs" />
     <Compile Include="UIControls\WindowObject.cs" />
     <Compile Include="VesselSimulator\AttachNodeSim.cs" />
     <Compile Include="VesselSimulator\EngineSim.cs" />
@@ -228,10 +233,12 @@
     <Compile Include="VesselSimulator\SimManager.cs" />
     <Compile Include="VesselSimulator\Simulation.cs" />
     <Compile Include="VesselSimulator\Stage.cs" />
+    <Compile Include="Flight\Readouts\Rendezvous\RelativeRadialVelocity.cs" />
+    <Compile Include="Flight\Readouts\Rendezvous\TimeToRendezvous.cs" />
   </ItemGroup>
   <ItemGroup>
     <Reference Include="Assembly-CSharp">
-      <HintPath>..\Game\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
+      <HintPath>..\..\Game\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
       <Private>False</Private>
     </Reference>
     <Reference Include="System">
@@ -243,7 +250,7 @@
       <Private>False</Private>
     </Reference>
     <Reference Include="UnityEngine">
-      <HintPath>..\Game\KSP_Data\Managed\UnityEngine.dll</HintPath>
+      <HintPath>..\..\Game\KSP_Data\Managed\UnityEngine.dll</HintPath>
       <Private>False</Private>
     </Reference>
   </ItemGroup>
@@ -262,7 +269,7 @@
         $(PostBuildEventDependsOn);
         PostBuildMacros;
       </PostBuildEventDependsOn>
-    <PostBuildEvent>xcopy "$(SolutionDir)Output\*" "$(SolutionDir)Game\GameData\*" /E /Y
+    <PostBuildEvent>xcopy "$(SolutionDir)Output\*" "$(SolutionDir)..\Game\GameData\*" /E /Y
 del "$(SolutionDir)Release\*" /Q
 xcopy "$(SolutionDir)Documents\*" "$(SolutionDir)Release\Documents\*" /E /Y
 7z.exe a -tzip -mx3 "$(SolutionDir)Release\$(ProjectName)-@(VersionNumber).zip" "$(SolutionDir)Output\*"

--- a/KerbalEngineer/KeyBinder.cs
+++ /dev/null
@@ -1,35 +1,1 @@
-// 
-//     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/>.
-// 
 
-using UnityEngine;
-
-namespace KerbalEngineer
-{
-    public class KeyBinder
-    {
-        public static KeyCode EditorShowHide { get; set; }
-
-        public static KeyCode FlightShowHide { get; set; }
-
-        static KeyBinder()
-        {
-            EditorShowHide = FlightShowHide = KeyCode.Backslash;
-        }
-    }
-}

--- /dev/null
+++ b/KerbalEngineer/KeyBinding/KeyBindPopup.cs
@@ -1,1 +1,243 @@
-
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2015 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.KeyBinding
+{
+    using System;
+    using Extensions;
+    using UnityEngine;
+
+    public class KeyBindPopup : MonoBehaviour
+    {
+        private const string LOCK_ID = "KER_KeyBindPopup";
+        private static Rect position = new Rect(Screen.width, Screen.height, 250.0f, 0.0f);
+        private static bool hasCentred;
+        private static KeyBindPopup instance;
+        private readonly Array availableBindings = Enum.GetValues(typeof(KeyCode));
+
+        /// <summary>
+        ///     Gets the delegate to be invoked when accepted button is clicked.
+        /// </summary>
+        public Action<KeyCode> AcceptClicked { get; private set; }
+
+        /// <summary>
+        ///     Gets the name of the binding to change.
+        /// </summary>
+        public string Name { get; private set; }
+
+        /// <summary>
+        ///     Gets the selected binding.
+        /// </summary>
+        public KeyCode Binding { get; private set; }
+
+        /// <summary>
+        ///     Gets whether a key bind popup is already open.
+        /// </summary>
+        public static bool IsOpen
+        {
+            get
+            {
+                return (instance != null);
+            }
+        }
+
+        /// <summary>
+        ///     Gets and sets the input lock state.
+        /// </summary>
+        public bool InputLock
+        {
+            get
+            {
+                return InputLockManager.GetControlLock(LOCK_ID) != ControlTypes.None;
+            }
+            set
+            {
+                if (value)
+                {
+                    InputLockManager.SetControlLock(ControlTypes.All, LOCK_ID);
+                }
+                else
+                {
+                    InputLockManager.SetControlLock(ControlTypes.None, LOCK_ID);
+                }
+            }
+        }
+
+        /// <summary>
+        ///     Shows a key bind popup allowing the user to select a key for binding.
+        /// </summary>
+        public static void Show(string name, KeyCode currentBinding, Action<KeyCode> acceptClicked)
+        {
+            if (instance == null)
+            {
+                instance = new GameObject("SelectKeyBind").AddComponent<KeyBindPopup>();
+            }
+
+            instance.Name = name;
+            instance.Binding = currentBinding;
+            instance.AcceptClicked = acceptClicked;
+        }
+
+        /// <summary>
+        ///     Handles the accept button click event.
+        /// </summary>
+        public void OnAccept()
+        {
+            if (AcceptClicked != null)
+            {
+                AcceptClicked.Invoke(Binding);
+            }
+            Destroy(gameObject);
+        }
+
+        /// <summary>
+        ///     Handles the cancel button click event.
+        /// </summary>
+        public void OnCancel()
+        {
+            Destroy(gameObject);
+        }
+
+        /// <summary>
+        ///     Called by unity when the component is created.
+        /// </summary>
+        protected virtual void Awake()
+        {
+            if (instance == null)
+            {
+                instance = this;
+            }
+            else if (instance != this)
+            {
+                OnCancel();
+            }
+        }
+
+        /// <summary>
+        ///     Called by unity when the component is destroyed.
+        /// </summary>
+        protected virtual void OnDestroy()
+        {
+            InputLock = false;
+        }
+
+        /// <summary>
+        ///     Called by unity each frame to render the GUI.
+        /// </summary>
+        protected virtual void OnGUI()
+        {
+            position = GUILayout.Window(GetInstanceID(), position, RenderWindow, "Select Key Bind", HighLogic.Skin.window).ClampToScreen();
+            CentreWindow();
+        }
+
+        /// <summary>
+        ///     Called by unity every frame.
+        /// </summary>
+        protected virtual void Update()
+        {
+            CentreWindow();
+            UpdateBinding();
+            UpdateInputLock();
+        }
+
+        /// <summary>
+        ///     Centres the window on the screen.
+        /// </summary>
+        private static void CentreWindow()
+        {
+            if (hasCentred == false && position.width > 0.0f && position.height > 0.0f)
+            {
+                hasCentred = true;
+                position.center = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f);
+            }
+        }
+
+        /// <summary>
+        ///     Renders the window content.
+        /// </summary>
+        private void RenderWindow(int id)
+        {
+            GUILayout.Label("Press the desired key to change it.");
+
+            // Binding labels.
+            GUILayout.BeginVertical(HighLogic.Skin.textArea);
+            GUILayout.Label("Key Bind: " + Name);
+            GUILayout.Label("Selected: " + Binding);
+            GUILayout.EndVertical();
+
+            // Window buttons.
+            GUILayout.BeginHorizontal();
+            if (GUILayout.Button("Cancel", HighLogic.Skin.button))
+            {
+                OnCancel();
+            }
+
+            if (GUILayout.Button("Accept", HighLogic.Skin.button))
+            {
+                OnAccept();
+            }
+            GUILayout.EndHorizontal();
+
+            // Make the window to be draggable.
+            GUI.DragWindow();
+        }
+
+        /// <summary>
+        ///     Updates the binding selected by the user.
+        /// </summary>
+        private void UpdateBinding()
+        {
+            for (int i = 0; i < availableBindings.Length; ++i)
+            {
+                KeyCode keyCode = (KeyCode)availableBindings.GetValue(i);
+
+                if (keyCode == KeyCode.Mouse0)
+                {
+                    continue;
+                }
+
+                if (Input.GetKeyDown(keyCode))
+                {
+                    if (Input.GetKeyDown(keyCode))
+                    {
+                        Binding = keyCode;
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        ///     Updates the input lock.
+        /// </summary>
+        private void UpdateInputLock()
+        {
+            bool mouseOver = position.MouseIsOver();
+            bool inputLock = InputLock;
+
+            if (mouseOver && inputLock == false)
+            {
+                InputLock = true;
+            }
+            else if (mouseOver == false && inputLock)
+            {
+                InputLock = false;
+            }
+        }
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/KeyBinding/KeyBinder.cs
@@ -1,1 +1,255 @@
-
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2015 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.KeyBinding
+{
+    using System;
+    using System.IO;
+    using Extensions;
+    using Helpers;
+    using UnityEngine;
+
+    public class KeyBinder : MonoBehaviour
+    {
+        private const string LOCK_ID = "KER_KeyBinder";
+        private static readonly string filePath = Path.Combine(EngineerGlobals.SettingsPath, "KeyBinds.xml");
+        private static KeyBindingsObject bindings;
+        private static Rect position = new Rect(Screen.width, Screen.height, 500.0f, 0.0f);
+        private static bool hasCentred;
+
+        static KeyBinder()
+        {
+            Load();
+        }
+
+        /// <summary>
+        ///     Gets whether the key binder window is open.
+        /// </summary>
+        public static bool IsOpen { get; private set; }
+
+        /// <summary>
+        ///     Gets and sets the key bindings object.
+        /// </summary>
+        public static KeyBindingsObject Bindings
+        {
+            get
+            {
+                if (bindings == null)
+                {
+                    bindings = new KeyBindingsObject();
+                }
+                return bindings;
+            }
+            private set
+            {
+                if (value != null)
+                {
+                    bindings = value;
+                }
+            }
+        }
+
+        /// <summary>
+        ///     Gets and sets the editor show/hide binding.
+        /// </summary>
+        public static KeyCode EditorShowHide
+        {
+            get
+            {
+                return Bindings.EditorShowHide;
+            }
+            set
+            {
+                Bindings.EditorShowHide = value;
+                Save();
+            }
+        }
+
+        /// <summary>
+        ///     Gets and sets the flight show/hide binding.
+        /// </summary>
+        public static KeyCode FlightShowHide
+        {
+            get
+            {
+                return Bindings.FlightShowHide;
+            }
+            set
+            {
+                Bindings.FlightShowHide = value;
+                Save();
+            }
+        }
+
+        /// <summary>
+        ///     Gets and sets the input lock state.
+        /// </summary>
+        public bool InputLock
+        {
+            get
+            {
+                return InputLockManager.GetControlLock(LOCK_ID) != ControlTypes.None;
+            }
+            set
+            {
+                if (value)
+                {
+                    InputLockManager.SetControlLock(ControlTypes.All, LOCK_ID);
+                }
+                else
+                {
+                    InputLockManager.SetControlLock(ControlTypes.None, LOCK_ID);
+                }
+            }
+        }
+
+        /// <summary>
+        ///     Loads the key bindings from disk.
+        /// </summary>
+        public static void Load()
+        {
+            Bindings = XmlHelper.LoadObject<KeyBindingsObject>(filePath);
+        }
+
+        /// <summary>
+        ///     Saves the key bindings to disk.
+        /// </summary>
+        public static void Save()
+        {
+            XmlHelper.SaveObject(filePath, Bindings);
+        }
+
+        /// <summary>
+        ///     Shows the key binding window.
+        /// </summary>
+        public static void Show()
+        {
+            if (IsOpen)
+            {
+                return;
+            }
+
+            new GameObject("KeyBinder").AddComponent<KeyBinder>();
+        }
+
+        /// <summary>
+        ///     Called by unity when component is created.
+        /// </summary>
+        protected virtual void Awake()
+        {
+            if (IsOpen)
+            {
+                Destroy(gameObject);
+            }
+            else
+            {
+                IsOpen = true;
+                position.height = 0.0f;
+            }
+        }
+
+        /// <summary>
+        ///     Called by unity when component is destroyed.
+        /// </summary>
+        protected virtual void OnDestroy()
+        {
+            IsOpen = false;
+            InputLock = false;
+        }
+
+        /// <summary>
+        ///     Called by unity to draw the GUI.
+        /// </summary>
+        protected virtual void OnGUI()
+        {
+            position = GUILayout.Window(GetInstanceID(), position, RenderWindow, "Kerbal Engineer Redux - Key Bindings", HighLogic.Skin.window).ClampToScreen();
+            CentreWindow();
+        }
+
+        /// <summary>
+        ///     Called by unity every frame.
+        /// </summary>
+        protected virtual void Update()
+        {
+            UpdateInputLock();
+        }
+
+        /// <summary>
+        ///     Renders a key bind option.
+        /// </summary>
+        private static void RenderKeyBind(string name, KeyCode currentBinding, Action<KeyCode> acceptClicked)
+        {
+            GUILayout.BeginHorizontal();
+            GUILayout.Label(name);
+            if (GUILayout.Button(currentBinding.ToString(), HighLogic.Skin.button, GUILayout.Width(100.0f)))
+            {
+                KeyBindPopup.Show(name, currentBinding, acceptClicked);
+            }
+            GUILayout.EndHorizontal();
+        }
+
+        /// <summary>
+        ///     Centres the window on screen.
+        /// </summary>
+        private void CentreWindow()
+        {
+            if (hasCentred == false && position.width > 0.0f && position.height > 0.0f)
+            {
+                hasCentred = true;
+                position.center = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f);
+            }
+        }
+
+        /// <summary>
+        ///     Renders the GUI window contents.
+        /// </summary>
+        private void RenderWindow(int id)
+        {
+            GUILayout.BeginVertical(HighLogic.Skin.textArea);
+            RenderKeyBind("Editor Show/Hide", EditorShowHide, binding => EditorShowHide = binding);
+            RenderKeyBind("Flight Show/Hide", FlightShowHide, binding => FlightShowHide = binding);
+            GUILayout.EndVertical();
+
+            if (GUILayout.Button("Close", HighLogic.Skin.button))
+            {
+                Destroy(gameObject);
+            }
+
+            GUI.DragWindow();
+        }
+
+        /// <summary>
+        ///     Updates the input lock.
+        /// </summary>
+        private void UpdateInputLock()
+        {
+            bool mouseOver = position.MouseIsOver();
+            bool inputLock = InputLock;
+
+            if (mouseOver && inputLock == false)
+            {
+                InputLock = true;
+            }
+            else if (mouseOver == false && inputLock)
+            {
+                InputLock = false;
+            }
+        }
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/KeyBinding/KeyBindingsObject.cs
@@ -1,1 +1,31 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2015 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.KeyBinding
+{
+    using System.Xml.Serialization;
+    using UnityEngine;
+
+    public class KeyBindingsObject
+    {
+        public KeyCode EditorShowHide { get; set; }
+
+        public KeyCode FlightShowHide { get; set; }
+    }
+}

--- a/KerbalEngineer/LogMsg.cs
+++ b/KerbalEngineer/LogMsg.cs
@@ -15,7 +15,8 @@
 
         public void Flush()
         {
-            MonoBehaviour.print(this.buf);
+            if (this.buf.Length > 0)
+                MonoBehaviour.print(this.buf);
             this.buf.Length = 0;
         }
     }

--- a/KerbalEngineer/VesselSimulator/EngineSim.cs
+++ b/KerbalEngineer/VesselSimulator/EngineSim.cs
@@ -273,14 +273,36 @@
 
         HashSet<PartSim> visited = new HashSet<PartSim>();
 
+        public void DumpSourcePartSets(String msg)
+        {
+            MonoBehaviour.print("DumpSourcePartSets " + msg);
+            foreach (int type in sourcePartSets.Keys)
+            {
+                MonoBehaviour.print("SourcePartSet for " + ResourceContainer.GetResourceName(type));
+                HashSet<PartSim> sourcePartSet = sourcePartSets[type];
+                if (sourcePartSet.Count > 0)
+                {
+                    foreach (PartSim partSim in sourcePartSet)
+                    {
+                        MonoBehaviour.print("Part " + partSim.name + ":" + partSim.partId);
+                    }
+                }
+                else
+                {
+                    MonoBehaviour.print("No parts");
+                }
+            }
+        }
+
         public bool SetResourceDrains(List<PartSim> allParts, List<PartSim> allFuelLines, HashSet<PartSim> drainingParts)
         {
             LogMsg log = null;
-            
+            //DumpSourcePartSets("before clear");
             foreach (HashSet<PartSim> sourcePartSet in sourcePartSets.Values)
             {
                 sourcePartSet.Clear();
             }
+            //DumpSourcePartSets("after clear");
 
             for (int index = 0; index < this.resourceConsumptions.Types.Count; index++)
             {
@@ -305,6 +327,7 @@
                         break;
 
                     case ResourceFlowMode.ALL_VESSEL:
+                    case ResourceFlowMode.ALL_VESSEL_BALANCE:
                         for (int i = 0; i < allParts.Count; i++)
                         {
                             PartSim aPartSim = allParts[i];
@@ -316,6 +339,7 @@
                         break;
 
                     case ResourceFlowMode.STAGE_PRIORITY_FLOW:
+                    case ResourceFlowMode.STAGE_PRIORITY_FLOW_BALANCE:
 
                         foreach (HashSet<PartSim> stagePartSet in stagePartSets.Values)
                         {
@@ -338,25 +362,34 @@
                                 maxStage = stage;
                             }
 
-                            if (!stagePartSets.TryGetValue(stage, out sourcePartSet))
+                            HashSet<PartSim> tempPartSet;
+                            if (!stagePartSets.TryGetValue(stage, out tempPartSet))
                             {
-                                sourcePartSet = new HashSet<PartSim>();
-                                stagePartSets.Add(stage, sourcePartSet);
+                                tempPartSet = new HashSet<PartSim>();
+                                stagePartSets.Add(stage, tempPartSet);
                             }
-                            sourcePartSet.Add(aPartSim);
-                        }
-
-                        for (int j = 0; j <= maxStage; j++)
+                            tempPartSet.Add(aPartSim);
+                        }
+
+                        for (int j = maxStage; j >= 0; j--)
                         {
                             HashSet<PartSim> stagePartSet;
                             if (stagePartSets.TryGetValue(j, out stagePartSet) && stagePartSet.Count > 0)
                             {
-                                sourcePartSet = stagePartSet;
+                                // We have to copy the contents of the set here rather than copying the set reference or 
+                                // bad things (tm) happen
+                                foreach (PartSim aPartSim in stagePartSet)
+                                {
+                                    sourcePartSet.Add(aPartSim);
+                                }
+                                break;
                             }
                         }
                         break;
 
                     case ResourceFlowMode.STACK_PRIORITY_SEARCH:
+                    case ResourceFlowMode.STAGE_STACK_FLOW:
+                    case ResourceFlowMode.STAGE_STACK_FLOW_BALANCE:
                         visited.Clear();
 
                         if (SimManager.logOutput)
@@ -376,11 +409,9 @@
                         break;
                 }
 
-
-                if (sourcePartSet.Count > 0)
-                {
-                    sourcePartSets[type] = sourcePartSet;
-                    if (SimManager.logOutput)
+                if (SimManager.logOutput)
+                {
+                    if (sourcePartSet.Count > 0)
                     {
                         log = new LogMsg();
                         log.buf.AppendLine("Source parts for " + ResourceContainer.GetResourceName(type) + ":");
@@ -391,6 +422,8 @@
                         MonoBehaviour.print(log.buf);
                     }
                 }
+
+                //DumpSourcePartSets("after " + ResourceContainer.GetResourceName(type));
             }
             
             // If we don't have sources for all the needed resources then return false without setting up any drains
@@ -409,6 +442,7 @@
                     return false;
                 }
             }
+
             // Now we set the drains on the members of the sets and update the draining parts set
             for (int i = 0; i < this.resourceConsumptions.Types.Count; i++)
             {

--- a/KerbalEngineer/VesselSimulator/PartSim.cs
+++ b/KerbalEngineer/VesselSimulator/PartSim.cs
@@ -519,9 +519,7 @@
                     {
                         if (attachSim.nodeType == AttachNode.NodeType.Stack)
                         {
-                            if (
-                                !(this.noCrossFeedNodeKey != null && this.noCrossFeedNodeKey.Length > 0 &&
-                                  attachSim.id.Contains(this.noCrossFeedNodeKey)))
+                            if ((string.IsNullOrEmpty(noCrossFeedNodeKey) == false && attachSim.id.Contains(noCrossFeedNodeKey)) == false)
                             {
                                 if (visited.Contains(attachSim.attachedPartSim))
                                 {
@@ -549,7 +547,7 @@
             // type was not disabled [Experiment]) and it contains fuel, it returns itself.
             // Rule 6: If the part is fuel container for searched type of fuel (i.e. it has capability to contain that type of fuel and the fuel 
             // type was not disabled) but it does not contain the requested fuel, it returns empty list. [Experiment]
-            if (resources.HasType(type) && resourceFlowStates[type] != 0)
+            if (resources.HasType(type) && resourceFlowStates[type] > 0.0)
             {
                 if (resources[type] > SimManager.RESOURCE_MIN)
                 {

--- a/KerbalEngineer/VesselSimulator/Simulation.cs
+++ b/KerbalEngineer/VesselSimulator/Simulation.cs
@@ -30,6 +30,7 @@
 
 namespace KerbalEngineer.VesselSimulator
 {
+    using System.ComponentModel;
     using CompoundParts;
     using Extensions;
     using Helpers;
@@ -675,21 +676,28 @@
             for (int i = 0; i < this.allParts.Count; i++)
             {
                 PartSim part = this.allParts[i];
-                // If the part has a parent
-                if (part.parent != null)
-                {
-                    if (part.isNoPhysics)
-                    {
-                        if (part.parent.isNoPhysics && part.parent.parent != null)
-                        {
-                            part.baseMass = 0d;
-                            part.baseMassForCoM = 0d;
-                        }
-                        else
-                        {
-                            part.parent.baseMassForCoM += part.baseMassForCoM;
-                            part.baseMassForCoM = 0d;
-                        }
+
+                // Check if part should pass it's mass onto its parent.
+                if (part.isNoPhysics && part.parent != null)
+                {
+                    PartSim partParent = part.parent;
+
+                    // Loop through all parents until a physically significant parent is found.
+                    while (partParent != null)
+                    {
+                        // Check if parent is physically significant.
+                        if (partParent.isNoPhysics == false)
+                        {
+                            // Apply the mass to the parent and remove it from the originating part.
+                            partParent.baseMassForCoM += part.baseMassForCoM;
+                            part.baseMassForCoM = 0.0;
+
+                            // Break out of the recursive loop.
+                            break;
+                        }
+
+                        // Recursively loop through the parent parts.
+                        partParent = partParent.parent;
                     }
                 }
             }

 Binary files a/Output/KerbalEngineer/KerbalEngineer.dll and b/Output/KerbalEngineer/KerbalEngineer.dll differ
--- a/Output/KerbalEngineer/KerbalEngineer.version
+++ b/Output/KerbalEngineer/KerbalEngineer.version
@@ -1,17 +1,18 @@
 {
-	"NAME":"Kerbal Engineer Redux 1.0",
+	"NAME":"Kerbal Engineer Redux",
 	"URL":"http://ksp-avc.cybutek.net/version.php?id=6",
 	"VERSION":
 	{
 		"MAJOR":1,
 		"MINOR":0,
-		"PATCH":17,
-		"BUILD":0
+		"PATCH":19,
+		"BUILD":2
 	},
 	"KSP_VERSION":
 	{
 		"MAJOR":1,
 		"MINOR":0,
-		"PATCH":4
+		"PATCH":5
 	}
 }
+