Added Isp, Mass & Thrust to Flight Engineer.
Added Isp, Mass & Thrust to Flight Engineer.

--- /dev/null
+++ b/KerbalEngineer/Flight/IUpdatable.cs
@@ -1,1 +1,14 @@
-
+// Project:	KerbalEngineer

+// Author:	CYBUTEK

+// License:	Attribution-NonCommercial-ShareAlike 3.0 Unported

+

+namespace KerbalEngineer.Flight

+{

+    /// <summary>

+    /// Interface which enabled updating via the flight engineer core.

+    /// </summary>

+    public interface IUpdatable

+    {

+        void Update();

+    }

+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/TargetSelector.cs
@@ -1,1 +1,340 @@
-
+// Project:	KerbalEngineer

+// Author:	CYBUTEK

+// License:	Attribution-NonCommercial-ShareAlike 3.0 Unported

+

+#region Using Directives

+

+using UnityEngine;

+

+#endregion

+

+namespace KerbalEngineer.Flight.Readouts.Rendezvous

+{

+    public class TargetSelector : ReadoutModule

+    {

+        #region Fields

+

+        private readonly float typeButtonWidth;

+        private string searchQuery = string.Empty;

+        private string searchText = string.Empty;

+        private int targetCount;

+        private bool typeIsBody;

+        private bool usingSearch;

+        private VesselType vesselType = VesselType.Unknown;

+

+        #endregion

+

+        #region Initialisation

+

+        public TargetSelector()

+        {

+            this.Name = "Target Selector";

+            this.Category = ReadoutCategory.Rendezvous;

+            this.HelpString = "A tool to allow easy browsing, searching and selection of targets.";

+            this.typeButtonWidth = Mathf.Round(this.ContentWidth * 0.5f);

+        }

+

+        #endregion

+

+        #region Drawing

+

+        /// <summary>

+        ///     Draws the target selector structure.

+        /// </summary>

+        public override void Draw()

+        {

+            if (FlightGlobals.fetch.VesselTarget == null)

+            {

+                if (this.vesselType == VesselType.Unknown && !this.typeIsBody)

+                {

+                    this.DrawSearch();

+                    if (this.searchQuery.Length == 0)

+                    {

+                        this.DrawTypes();

+                    }

+                    else

+                    {

+                        this.DrawTargetList();

+                    }

+                }

+                else

+                {

+                    this.DrawBackToTypes();

+                    this.DrawTargetList();

+                }

+            }

+            else

+            {

+                this.DrawTarget();

+            }

+        }

+

+        /// <summary>

+        ///     Draws the search bar.

+        /// </summary>

+        private void DrawSearch()

+        {

+            GUILayout.BeginHorizontal();

+            GUILayout.Label("SEARCH:", this.FlexiLabelStyle, GUILayout.Width(60.0f));

+

+            this.searchText = GUILayout.TextField(this.searchText, this.TextFieldStyle);

+

+            if (this.searchText.Length > 0 || this.searchQuery.Length > 0)

+            {

+                this.searchQuery = this.searchText.ToLower();

+

+                if (!this.usingSearch)

+                {

+                    this.usingSearch = true;

+                    this.ResizeRequested = true;

+                }

+            }

+            else if (this.usingSearch)

+            {

+                this.usingSearch = false;

+            }

+

+            GUILayout.EndHorizontal();

+        }

+

+        /// <summary>

+        ///     Draws the button list of target types.

+        /// </summary>

+        private void DrawTypes()

+        {

+            GUILayout.BeginHorizontal();

+            if (GUILayout.Button("Celestial Bodies", this.ButtonStyle, GUILayout.Width(this.typeButtonWidth)))

+            {

+                this.SetTypeAsBody();

+            }

+            if (GUILayout.Button("Debris", this.ButtonStyle, GUILayout.Width(this.typeButtonWidth)))

+            {

+                this.SetTypeAs(VesselType.Debris);

+            }

+            GUILayout.EndHorizontal();

+

+            GUILayout.BeginHorizontal();

+            if (GUILayout.Button("Probes", this.ButtonStyle, GUILayout.Width(this.typeButtonWidth)))

+            {

+                this.SetTypeAs(VesselType.Probe);

+            }

+

+            if (GUILayout.Button("Rovers", this.ButtonStyle, GUILayout.Width(this.typeButtonWidth)))

+            {

+                this.SetTypeAs(VesselType.Rover);

+            }

+            GUILayout.EndHorizontal();

+

+            GUILayout.BeginHorizontal();

+            if (GUILayout.Button("Landers", this.ButtonStyle, GUILayout.Width(this.typeButtonWidth)))

+            {

+                this.SetTypeAs(VesselType.Lander);

+            }

+            if (GUILayout.Button("Ships", this.ButtonStyle, GUILayout.Width(this.typeButtonWidth)))

+            {

+                this.SetTypeAs(VesselType.Ship);

+            }

+            GUILayout.EndHorizontal();

+

+            GUILayout.BeginHorizontal();

+            if (GUILayout.Button("Stations", this.ButtonStyle, GUILayout.Width(this.typeButtonWidth)))

+            {

+                this.SetTypeAs(VesselType.Station);

+            }

+            if (GUILayout.Button("Bases", this.ButtonStyle, GUILayout.Width(this.typeButtonWidth)))

+            {

+                this.SetTypeAs(VesselType.Base);

+            }

+            GUILayout.EndHorizontal();

+

+            GUILayout.BeginHorizontal();

+            if (GUILayout.Button("EVAs", this.ButtonStyle, GUILayout.Width(this.typeButtonWidth)))

+            {

+                this.SetTypeAs(VesselType.EVA);

+            }

+            if (GUILayout.Button("Flags", this.ButtonStyle, GUILayout.Width(this.typeButtonWidth)))

+            {

+                this.SetTypeAs(VesselType.Flag);

+            }

+            GUILayout.EndHorizontal();

+        }

+

+        /// <summary>

+        ///     Draws the target information when selected.

+        /// </summary>

+        private void DrawTarget()

+        {

+            if (GUILayout.Button("Go Back to Target Selection", this.ButtonStyle))

+            {

+                FlightGlobals.fetch.SetVesselTarget(null);

+                this.ResizeRequested = true;

+            }

+

+            GUILayout.Space(3f);

+

+            this.DrawLine("Selected Target", FlightGlobals.fetch.VesselTarget.GetName());

+        }

+

+        /// <summary>

+        ///     Draws the back to types button.

+        /// </summary>

+        private void DrawBackToTypes()

+        {

+            if (GUILayout.Button("Go Back to Type Selection", this.ButtonStyle))

+            {

+                this.typeIsBody = false;

+                this.vesselType = VesselType.Unknown;

+                this.ResizeRequested = true;

+            }

+

+            GUILayout.Space(3f);

+        }

+

+        /// <summary>

+        ///     Draws the target list.

+        /// </summary>

+        private void DrawTargetList()

+        {

+            var count = 0;

+

+            if (this.searchQuery.Length == 0)

+            {

+                if (this.typeIsBody)

+                {

+                    count += this.DrawMoons();

+                    count += this.DrawPlanets();

+                }

+                else

+                {

+                    count += this.DrawVessels();

+                }

+            }

+            else

+            {

+                count += this.DrawVessels();

+                count += this.DrawMoons();

+                count += this.DrawPlanets();

+            }

+

+            if (count == 0)

+            {

+                this.DrawMessageLine("No targets found!");

+            }

+

+            if (count != this.targetCount)

+            {

+                this.targetCount = count;

+                this.ResizeRequested = true;

+            }

+        }

+

+        /// <summary>

+        ///     Draws targetable moons.

+        /// </summary>

+        private int DrawMoons()

+        {

+            var count = 0;

+

+            foreach (var body in FlightGlobals.Bodies)

+            {

+                if (FlightGlobals.ActiveVessel.mainBody != body.referenceBody || body == Planetarium.fetch.Sun)

+                {

+                    continue;

+                }

+

+                if (this.searchQuery.Length > 0 && !body.bodyName.ToLower().Contains(this.searchQuery))

+                {

+                    continue;

+                }

+

+                count++;

+                if (GUILayout.Button(body.bodyName, this.ButtonStyle))

+                {

+                    this.SetTargetAs(body);

+                }

+            }

+            return count;

+        }

+

+        /// <summary>

+        ///     Draws the targetable planets.

+        /// </summary>

+        private int DrawPlanets()

+        {

+            var count = 0;

+            foreach (var body in FlightGlobals.Bodies)

+            {

+                if (FlightGlobals.ActiveVessel.mainBody.referenceBody != body.referenceBody || body == Planetarium.fetch.Sun || body == FlightGlobals.ActiveVessel.mainBody)

+                {

+                    continue;

+                }

+

+                if (this.searchQuery.Length > 0 && !body.bodyName.ToLower().Contains(this.searchQuery))

+                {

+                    continue;

+                }

+

+                count++;

+                if (GUILayout.Button(body.GetName(), this.ButtonStyle))

+                {

+                    this.SetTargetAs(body);

+                }

+            }

+            return count;

+        }

+

+        /// <summary>

+        ///     Draws targetable vessels.

+        /// </summary>

+        private int DrawVessels()

+        {

+            var count = 0;

+            foreach (var vessel in FlightGlobals.Vessels)

+            {

+                if (vessel == FlightGlobals.ActiveVessel || vessel.vesselType != this.vesselType)

+                {

+                    continue;

+                }

+

+                if (this.searchQuery.Length == 0)

+                {

+                    count++;

+

+                    if (GUILayout.Button(vessel.GetName(), this.ButtonStyle))

+                    {

+                        this.SetTargetAs(vessel);

+                    }

+                }

+                else if (vessel.vesselName.ToLower().Contains(this.searchQuery))

+                {

+                    count++;

+                    if (GUILayout.Button(vessel.GetName(), this.ButtonStyle))

+                    {

+                        this.SetTargetAs(vessel);

+                    }

+                }

+            }

+            return count;

+        }

+

+        private void SetTypeAs(VesselType vesselType)

+        {

+            this.vesselType = vesselType;

+            this.ResizeRequested = true;

+        }

+

+        private void SetTypeAsBody()

+        {

+            this.typeIsBody = true;

+            this.ResizeRequested = true;

+        }

+

+        private void SetTargetAs(ITargetable target)

+        {

+            FlightGlobals.fetch.SetVesselTarget(target);

+            this.ResizeRequested = true;

+        }

+

+        #endregion

+    }

+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Surface/AtmosphericDetails.cs
@@ -1,1 +1,99 @@
-
+// Project:	KerbalEngineer

+// Author:	CYBUTEK

+// License:	Attribution-NonCommercial-ShareAlike 3.0 Unported

+

+#region Using Directives

+

+using System;

+using System.Linq;

+

+using KerbalEngineer.Extensions;

+

+#endregion

+

+namespace KerbalEngineer.Flight.Readouts.Surface

+{

+    public class AtmosphericDetails : IUpdatable

+    {

+        #region Instance

+

+        private static AtmosphericDetails instance;

+

+        /// <summary>

+        ///     Gets the current instance of atmospheric details.

+        /// </summary>

+        public static AtmosphericDetails Instance

+        {

+            get { return instance ?? (instance = new AtmosphericDetails()); }

+        }

+

+        #endregion

+

+        #region Fields

+

+        private bool updateRequested;

+

+        #endregion

+

+        #region Properties

+

+        private double efficiency;

+        private double terminalVelocity;

+

+        /// <summary>

+        ///     Gets whether an update has been requested.

+        /// </summary>

+        public bool UpdateRequested

+        {

+            get { return this.updateRequested; }

+        }

+

+        /// <summary>

+        ///     Gets the terminal velocity of the active vessel.

+        /// </summary>

+        public double TerminalVelocity

+        {

+            get { return this.terminalVelocity; }

+        }

+

+        /// <summary>

+        ///     Gets the difference between current velocity and terminal velocity.

+        /// </summary>

+        public double Efficiency

+        {

+            get { return this.efficiency; }

+        }

+

+        #endregion

+

+        /// <summary>

+        ///     Updated the details by recalculating if requested.

+        /// </summary>

+        public void Update()

+        {

+            if (!this.updateRequested || FlightGlobals.ActiveVessel.atmDensity == 0)

+            {

+                return;

+            }

+

+            this.updateRequested = false;

+

+            var mass = FlightGlobals.ActiveVessel.parts.Sum(p => p.GetWetMass());

+            var drag = FlightGlobals.ActiveVessel.parts.Sum(p => p.GetWetMass() * p.maximum_drag);

+            var grav = FlightGlobals.getGeeForceAtPosition(FlightGlobals.ActiveVessel.CoM).magnitude;

+            var atmo = FlightGlobals.ActiveVessel.atmDensity;

+            var coef = FlightGlobals.DragMultiplier;

+

+            this.terminalVelocity = Math.Sqrt((2 * mass * grav) / (atmo * drag * coef));

+            this.efficiency = FlightGlobals.ActiveVessel.srf_velocity.magnitude / this.terminalVelocity;

+        }

+

+        /// <summary>

+        ///     Request an update to recalculate the details.

+        /// </summary>

+        public void RequestUpdate()

+        {

+            this.updateRequested = true;

+        }

+    }

+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Surface/AtmosphericEfficiency.cs
@@ -1,1 +1,34 @@
-
+// Project:	KerbalEngineer

+// Author:	CYBUTEK

+// License:	Attribution-NonCommercial-ShareAlike 3.0 Unported

+

+namespace KerbalEngineer.Flight.Readouts.Surface

+{

+    public class AtmosphericEfficiency : ReadoutModule

+    {

+        public AtmosphericEfficiency()

+        {

+            this.Name = "Atmos. Efficiency";

+            this.Category = ReadoutCategory.Surface;

+            this.HelpString = "Shows you vessel's efficiency as a ratio of the current velocity and terminal velocity.  Less than 1 means that you are losing efficiency due to gravity and greater than 1 is due to drag.";

+        }

+

+        public override void Update()

+        {

+            AtmosphericDetails.Instance.RequestUpdate();

+        }

+

+        public override void Draw()

+        {

+            if (FlightGlobals.ActiveVessel.atmDensity > 0)

+            {

+                this.DrawLine(AtmosphericDetails.Instance.Efficiency.ToString("F2"));

+            }

+        }

+

+        public override void Reset()

+        {

+            FlightEngineerCore.Instance.AddUpdatable(AtmosphericDetails.Instance);

+        }

+    }

+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Surface/TerminalVelocity.cs
@@ -1,1 +1,37 @@
-
+// Project:	KerbalEngineer

+// Author:	CYBUTEK

+// License:	Attribution-NonCommercial-ShareAlike 3.0 Unported

+

+#region Using Directives

+

+using KerbalEngineer.Extensions;

+

+#endregion

+

+namespace KerbalEngineer.Flight.Readouts.Surface

+{

+    public class TerminalVelocity : ReadoutModule

+    {

+        public TerminalVelocity()

+        {

+            this.Name = "Terminal Velocity";

+            this.Category = ReadoutCategory.Surface;

+            this.HelpString = "Shows the velocity where the efforts of thrust and drag are equalled out.";

+        }

+

+        public override void Update()

+        {

+            AtmosphericDetails.Instance.RequestUpdate();

+        }

+

+        public override void Draw()

+        {

+            this.DrawLine(AtmosphericDetails.Instance.TerminalVelocity.ToSpeed());

+        }

+

+        public override void Reset()

+        {

+            FlightEngineerCore.Instance.AddUpdatable(AtmosphericDetails.Instance);

+        }

+    }

+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/DeltaVTotal.cs
@@ -1,1 +1,37 @@
-
+// Project:	KerbalEngineer

+// Author:	CYBUTEK

+// License:	Attribution-NonCommercial-ShareAlike 3.0 Unported

+

+#region Using Directives

+

+using KerbalEngineer.Simulation;

+

+#endregion

+

+namespace KerbalEngineer.Flight.Readouts.Vessel

+{

+    public class DeltaVTotal : ReadoutModule

+    {

+        public DeltaVTotal()

+        {

+            this.Name = "DeltaV Total";

+            this.Category = ReadoutCategory.Vessel;

+            this.HelpString = "Shows the vessel's total delta velocity.";

+        }

+

+        public override void Update()

+        {

+            SimulationManager.Instance.RequestSimulation();

+        }

+

+        public override void Draw()

+        {

+            this.DrawLine(SimulationManager.Instance.LastStage.TotalDeltaV.ToString("N0") + "m/s");

+        }

+

+        public override void Reset()

+        {

+            FlightEngineerCore.Instance.AddUpdatable(SimulationManager.Instance);

+        }

+    }

+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Mass.cs
@@ -1,1 +1,37 @@
-
+// Project:	KerbalEngineer

+// Author:	CYBUTEK

+// License:	Attribution-NonCommercial-ShareAlike 3.0 Unported

+

+#region Using Directives

+

+using KerbalEngineer.Extensions;

+using KerbalEngineer.Simulation;

+

+#endregion

+

+namespace KerbalEngineer.Flight.Readouts.Vessel

+{

+    public class Mass : ReadoutModule

+    {

+        public Mass()

+        {

+            this.Name = "Mass";

+            this.Category = ReadoutCategory.Vessel;

+        }

+

+        public override void Update()

+        {

+            SimulationManager.Instance.RequestSimulation();

+        }

+

+        public override void Draw()

+        {

+            this.DrawLine(SimulationManager.Instance.LastStage.Mass.ToMass(false) + " / " + SimulationManager.Instance.LastStage.TotalMass.ToMass());

+        }

+

+        public override void Reset()

+        {

+            FlightEngineerCore.Instance.AddUpdatable(SimulationManager.Instance);

+        }

+    }

+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/SpecificImpulse.cs
@@ -1,1 +1,36 @@
-
+// Project:	KerbalEngineer

+// Author:	CYBUTEK

+// License:	Attribution-NonCommercial-ShareAlike 3.0 Unported

+

+#region Using Directives

+

+using KerbalEngineer.Simulation;

+

+#endregion

+

+namespace KerbalEngineer.Flight.Readouts.Vessel

+{

+    public class SpecificImpulse : ReadoutModule

+    {

+        public SpecificImpulse()

+        {

+            this.Name = "Specific Impulse";

+            this.Category = ReadoutCategory.Vessel;

+        }

+

+        public override void Update()

+        {

+            SimulationManager.Instance.RequestSimulation();

+        }

+

+        public override void Draw()

+        {

+            this.DrawLine(SimulationManager.Instance.LastStage.Isp.ToString("F1") + "s");

+        }

+

+        public override void Reset()

+        {

+            FlightEngineerCore.Instance.AddUpdatable(SimulationManager.Instance);

+        }

+    }

+}