Merge branch 'master' into flowmodeoverride
--- a/Documents/CHANGES.txt
+++ b/Documents/CHANGES.txt
@@ -1,3 +1,25 @@
+1.0.17.0
+ Added: 'Mach Number' readout under the 'Surface' category and included it on the default surface HUD.
+ Added 'Thermal' readouts category including:
+ Internal Flux
+ Convection Flux
+ Radiation Flux
+ Critical Part Name
+ Critical Part Temperature
+ Critical Part Percentage of Max Temperature
+ Hottest Part Name
+ Hottest Part Temperature
+ Coldest Part Name
+ Coldest Part Temperature
+
+ 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.
+ Fixed: Physically insignificant part mass is now associated with the parent part.
+ Fixed: Longitude and Latitude readouts now use a KER formatter instead of Squad's incorrect implementation.
+ Fixed: Possible null reference in the Rendezvous Processor.
+
1.0.16.6, 02-05-15
Fixed: Separately staged fairing mass jettisons are now calculated in the editor.
--- a/KerbalEngineer/Extensions/DoubleExtensions.cs
+++ b/KerbalEngineer/Extensions/DoubleExtensions.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,18 +17,12 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using KerbalEngineer.Helpers;
-
-#endregion
-
namespace KerbalEngineer.Extensions
{
+ using Helpers;
+
public static class DoubleExtensions
{
- #region Methods: public
-
public static double Clamp(this double value, double lower, double higher)
{
return value < lower ? lower : value > higher ? higher : value;
@@ -49,14 +43,19 @@
return Units.ToDistance(value);
}
- public static string ToTorque(this double value)
+ public static string ToFlux(this double value)
{
- return Units.ToTorque(value);
+ return Units.ToFlux(value);
}
public static string ToForce(this double value)
{
return Units.ToForce(value);
+ }
+
+ public static string ToMach(this double value)
+ {
+ return Units.ToMach(value);
}
public static string ToMass(this double value)
@@ -79,6 +78,14 @@
return Units.ToSpeed(value);
}
- #endregion
+ public static string ToTemperature(this double value)
+ {
+ return Units.ToTemperature(value);
+ }
+
+ public static string ToTorque(this double value)
+ {
+ return Units.ToTorque(value);
+ }
}
}
--- a/KerbalEngineer/Extensions/FloatExtensions.cs
+++ b/KerbalEngineer/Extensions/FloatExtensions.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,18 +17,12 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using KerbalEngineer.Helpers;
-
-#endregion
-
namespace KerbalEngineer.Extensions
{
+ using Helpers;
+
public static class FloatExtensions
{
- #region Methods: public
-
public static string ToAcceleration(this float value)
{
return Units.ToAcceleration(value);
@@ -44,14 +38,19 @@
return Units.ToDistance(value);
}
+ public static string ToFlux(this float value)
+ {
+ return Units.ToFlux(value);
+ }
+
public static string ToForce(this float value)
{
return Units.ToForce(value);
}
- public static string ToTorque(this float value)
+ public static string ToMach(this float value)
{
- return Units.ToTorque(value);
+ return Units.ToMach(value);
}
public static string ToMass(this float value)
@@ -74,6 +73,14 @@
return Units.ToSpeed(value);
}
- #endregion
+ public static string ToTemperature(this float value)
+ {
+ return Units.ToTemperature(value);
+ }
+
+ public static string ToTorque(this float value)
+ {
+ return Units.ToTorque(value);
+ }
}
}
--- a/KerbalEngineer/Extensions/PartExtensions.cs
+++ b/KerbalEngineer/Extensions/PartExtensions.cs
@@ -55,6 +55,7 @@
/// <summary>
/// Gets whether the part has fuel.
/// </summary>
+ /* not used
public static bool EngineHasFuel(this Part part)
{
PartModule cachePartModule = GetModule<ModuleEngines>(part);
@@ -71,7 +72,7 @@
return false;
}
-
+ */
/// <summary>
/// Gets the cost of the part excluding resources.
/// </summary>
@@ -123,6 +124,7 @@
/// <summary>
/// Gets the maximum thrust of the part if it's an engine.
/// </summary>
+ /* not used
public static double GetMaxThrust(this Part part)
{
PartModule cachePartModule = GetModule<ModuleEngines>(part);
@@ -139,6 +141,7 @@
return 0.0;
}
+ */
/// <summary>
/// Gets the first typed PartModule in the part's module list.
@@ -221,13 +224,17 @@
public static ModuleEnginesFX GetModuleMultiModeEngine(this Part part)
{
ModuleEnginesFX moduleEngineFx;
- string mode = GetModule<MultiModeEngine>(part).mode;
- for (int i = 0; i < part.Modules.Count; ++i)
- {
- moduleEngineFx = part.Modules[i] as ModuleEnginesFX;
- if (moduleEngineFx != null && moduleEngineFx.engineID == mode)
- {
- return moduleEngineFx;
+ MultiModeEngine multiMod = GetModule<MultiModeEngine>(part);
+ if (multiMod != null)
+ {
+ string mode = multiMod.mode;
+ for (int i = 0; i < part.Modules.Count; ++i)
+ {
+ moduleEngineFx = part.Modules[i] as ModuleEnginesFX;
+ if (moduleEngineFx != null && moduleEngineFx.engineID == mode)
+ {
+ return moduleEngineFx;
+ }
}
}
return null;
@@ -343,6 +350,7 @@
/// <summary>
/// Gets the current specific impulse for the engine.
/// </summary>
+ /* not used
public static double GetSpecificImpulse(this Part part, float atmosphere)
{
PartModule cachePartModule = GetModule<ModuleEngines>(part);
@@ -359,6 +367,7 @@
return 0.0;
}
+ */
/// <summary>
/// Gets the total mass of the part including resources.
@@ -588,6 +597,12 @@
}
}
+ // This needs updating to handle multi-mode engines and engines with multiple ModuleEngines correctly.
+ // It currently just shows the stats of the currently active module for multi-mode engines and just
+ // the first ModuleEngines for engines with multiple modules.
+ // It should really show all the modes for multi-mode engines as separate sections.
+ // For other engines with multiple ModuleEngines it should combine the separate modules into a single set of data
+ // The constructor should be changed to take the Part itself. It can be called if HasModule<ModuleEngines>() is true.
public class ProtoModuleEngine
{
private readonly PartModule module;
@@ -627,19 +642,6 @@
MinimumThrust = engine.minThrust;
Propellants = engine.propellants;
}
-
- private void SetModuleEnginesFx()
- {
- ModuleEnginesFX engine = module as ModuleEnginesFX;
- if (engine == null)
- {
- return;
- }
-
- MaximumThrust = engine.maxThrust * (engine.thrustPercentage * 0.01);
- MinimumThrust = engine.minThrust;
- Propellants = engine.propellants;
- }
}
}
}
--- /dev/null
+++ b/KerbalEngineer/Extensions/StringExtensions.cs
@@ -1,1 +1,33 @@
+//
+// 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.Extensions
+{
+ public static class StringExtensions
+ {
+ public static string ToLength(this string value, int length)
+ {
+ if (value != null && value.Length > length)
+ {
+ value = value.Substring(0, length) + "...";
+ }
+ return value;
+ }
+ }
+}
--- a/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/ManoeuvreProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/ManoeuvreProcessor.cs
@@ -30,6 +30,8 @@
namespace KerbalEngineer.Flight.Readouts.Orbital.ManoeuvreNode
{
+ using Helpers;
+
public class ManoeuvreProcessor : IUpdatable, IUpdateRequest
{
#region Fields
@@ -163,7 +165,7 @@
deltaVDrain = deltaV.Clamp(0.0, stageDeltaV);
}
- var exhaustVelocity = stage.isp * 9.82;
+ var exhaustVelocity = stage.isp * Units.GRAVITY;
var flowRate = stage.thrust / exhaustVelocity;
var endMass = Math.Exp(Math.Log(startMass) - deltaVDrain / exhaustVelocity);
var deltaMass = (startMass - endMass) * Math.Exp(-(deltaVDrain * 0.001) / exhaustVelocity);
--- a/KerbalEngineer/Flight/Readouts/ReadoutLibrary.cs
+++ b/KerbalEngineer/Flight/Readouts/ReadoutLibrary.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
@@ -19,8 +19,6 @@
namespace KerbalEngineer.Flight.Readouts
{
- #region Using Directives
-
using System;
using System.Collections.Generic;
using System.Linq;
@@ -30,6 +28,7 @@
using Rendezvous;
using Settings;
using Surface;
+ using Thermal;
using Vessel;
using AltitudeSeaLevel = Surface.AltitudeSeaLevel;
using ApoapsisHeight = Orbital.ApoapsisHeight;
@@ -40,17 +39,9 @@
using TimeToApoapsis = Orbital.TimeToApoapsis;
using TimeToPeriapsis = Orbital.TimeToPeriapsis;
- #endregion
-
public static class ReadoutLibrary
{
- #region Fields
-
private static List<ReadoutModule> readouts = new List<ReadoutModule>();
-
- #endregion
-
- #region Constructors
/// <summary>
/// Sets up and populates the readout library with the stock readouts.
@@ -63,6 +54,7 @@
ReadoutCategory.SetCategory("Surface", "Surface and atmospheric readouts.");
ReadoutCategory.SetCategory("Vessel", "Vessel performance statistics.");
ReadoutCategory.SetCategory("Rendezvous", "Readouts for rendezvous manovoeures.");
+ ReadoutCategory.SetCategory("Thermal", "Thermal characteristics readouts.");
ReadoutCategory.SetCategory("Miscellaneous", "Miscellaneous readouts.");
ReadoutCategory.Selected = ReadoutCategory.GetCategory("Orbital");
@@ -109,6 +101,7 @@
readouts.Add(new VerticalAcceleration());
readouts.Add(new HorizontalSpeed());
readouts.Add(new HorizontalAcceleration());
+ readouts.Add(new MachNumber());
readouts.Add(new Latitude());
readouts.Add(new Longitude());
readouts.Add(new GeeForce());
@@ -171,7 +164,19 @@
readouts.Add(new Rendezvous.OrbitalPeriod());
readouts.Add(new Rendezvous.SemiMajorAxis());
readouts.Add(new Rendezvous.SemiMinorAxis());
-
+
+ // Thermal
+ readouts.Add(new InternalFlux());
+ readouts.Add(new ConvectionFlux());
+ readouts.Add(new RadiationFlux());
+ readouts.Add(new CriticalPart());
+ readouts.Add(new CriticalTemperature());
+ readouts.Add(new CriticalPercentage());
+ readouts.Add(new HottestPart());
+ readouts.Add(new HottestTemperature());
+ readouts.Add(new CoolestPart());
+ readouts.Add(new CoolestTemperature());
+
// Misc
readouts.Add(new Separator());
readouts.Add(new GuiSizeAdjustor());
@@ -188,22 +193,20 @@
}
}
- #endregion
-
- #region Properties
-
/// <summary>
/// Gets and sets the available readout modules.
/// </summary>
public static List<ReadoutModule> Readouts
{
- get { return readouts; }
- set { readouts = value; }
- }
-
- #endregion
-
- #region Methods
+ get
+ {
+ return readouts;
+ }
+ set
+ {
+ readouts = value;
+ }
+ }
/// <summary>
/// Gets a list of readout modules which are associated with the specified category.
@@ -226,7 +229,7 @@
/// </summary>
public static void Reset()
{
- foreach (var readout in readouts)
+ foreach (ReadoutModule readout in readouts)
{
readout.Reset();
}
@@ -239,8 +242,8 @@
{
try
{
- var handler = SettingHandler.Load("HelpStrings.xml");
- foreach (var readout in readouts)
+ SettingHandler handler = SettingHandler.Load("HelpStrings.xml");
+ foreach (ReadoutModule readout in readouts)
{
readout.HelpString = handler.GetSet(readout.Category + "." + readout.GetType().Name, readout.HelpString);
}
@@ -251,7 +254,5 @@
Logger.Exception(ex);
}
}
-
- #endregion
}
}
--- a/KerbalEngineer/Flight/Readouts/ReadoutModule.cs
+++ b/KerbalEngineer/Flight/Readouts/ReadoutModule.cs
@@ -29,6 +29,8 @@
namespace KerbalEngineer.Flight.Readouts
{
+ using Extensions;
+
public abstract class ReadoutModule
{
#region Fields
@@ -178,13 +180,13 @@
{
GUILayout.Label(this.Name, this.NameStyle);
GUILayout.FlexibleSpace();
- GUILayout.Label(value, this.ValueStyle);
+ GUILayout.Label(value.ToLength(20), this.ValueStyle);
}
else
{
GUILayout.Label(this.Name, this.NameStyle, GUILayout.Height(this.NameStyle.fontSize * 1.2f));
GUILayout.FlexibleSpace();
- GUILayout.Label(value, this.ValueStyle, GUILayout.Height(this.ValueStyle.fontSize * 1.2f));
+ GUILayout.Label(value.ToLength(20), this.ValueStyle, GUILayout.Height(this.ValueStyle.fontSize * 1.2f));
}
GUILayout.EndHorizontal();
@@ -198,13 +200,13 @@
{
GUILayout.Label(name, this.NameStyle);
GUILayout.FlexibleSpace();
- GUILayout.Label(value, this.ValueStyle);
+ GUILayout.Label(value.ToLength(20), this.ValueStyle);
}
else
{
GUILayout.Label(name, this.NameStyle, GUILayout.Height(this.NameStyle.fontSize * 1.2f));
GUILayout.FlexibleSpace();
- GUILayout.Label(value, this.ValueStyle, GUILayout.Height(this.ValueStyle.fontSize * 1.2f));
+ GUILayout.Label(value.ToLength(20), this.ValueStyle, GUILayout.Height(this.ValueStyle.fontSize * 1.2f));
}
GUILayout.EndHorizontal();
--- a/KerbalEngineer/Flight/Readouts/Rendezvous/RendezvousProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/RendezvousProcessor.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,30 +17,19 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using System;
-
-using KerbalEngineer.Extensions;
-using KerbalEngineer.Helpers;
-
-#endregion
-
namespace KerbalEngineer.Flight.Readouts.Rendezvous
{
+ using System;
+ using Extensions;
+ using Helpers;
+
public class RendezvousProcessor : IUpdatable, IUpdateRequest
{
- #region Fields
-
private static readonly RendezvousProcessor instance = new RendezvousProcessor();
private Orbit originOrbit;
private Orbit targetOrbit;
- #endregion
-
- #region Properties
-
/// <summary>
/// Gets the target's altitude above its reference body.
/// </summary>
@@ -71,7 +60,10 @@
/// </summary>
public static RendezvousProcessor Instance
{
- get { return instance; }
+ get
+ {
+ return instance;
+ }
}
/// <summary>
@@ -149,10 +141,6 @@
/// </summary>
public bool UpdateRequested { get; set; }
- #endregion
-
- #region Methods: public
-
/// <summary>
/// Request and update to calculate the details.
/// </summary>
@@ -166,7 +154,13 @@
/// </summary>
public void Update()
{
- if (FlightGlobals.fetch.VesselTarget == null)
+ if (FlightGlobals.fetch == null ||
+ FlightGlobals.fetch.VesselTarget == null ||
+ FlightGlobals.ActiveVessel == null ||
+ FlightGlobals.ActiveVessel.targetObject == null ||
+ FlightGlobals.ActiveVessel.targetObject.GetOrbit() == null ||
+ FlightGlobals.ship_orbit == null ||
+ FlightGlobals.ship_orbit.referenceBody == null)
{
ShowDetails = false;
return;
@@ -174,55 +168,50 @@
ShowDetails = true;
- this.targetOrbit = FlightGlobals.fetch.VesselTarget.GetOrbit();
- this.originOrbit = (FlightGlobals.ship_orbit.referenceBody == Planetarium.fetch.Sun || FlightGlobals.ship_orbit.referenceBody == FlightGlobals.ActiveVessel.targetObject.GetOrbit().referenceBody)
+ targetOrbit = FlightGlobals.fetch.VesselTarget.GetOrbit();
+ originOrbit = (FlightGlobals.ship_orbit.referenceBody == Planetarium.fetch.Sun ||
+ FlightGlobals.ship_orbit.referenceBody == FlightGlobals.ActiveVessel.targetObject.GetOrbit().referenceBody)
? FlightGlobals.ship_orbit
: FlightGlobals.ship_orbit.referenceBody.orbit;
- RelativeInclination = this.originOrbit.GetRelativeInclination(this.targetOrbit);
+ RelativeInclination = originOrbit.GetRelativeInclination(targetOrbit);
RelativeVelocity = FlightGlobals.ship_tgtSpeed;
- RelativeSpeed = FlightGlobals.ship_obtSpeed - this.targetOrbit.orbitalSpeed;
- PhaseAngle = this.originOrbit.GetPhaseAngle(this.targetOrbit);
- InterceptAngle = this.CalcInterceptAngle();
- TimeToAscendingNode = this.originOrbit.GetTimeToVector(this.GetAscendingNode());
- TimeToDescendingNode = this.originOrbit.GetTimeToVector(this.GetDescendingNode());
- AngleToAscendingNode = this.originOrbit.GetAngleToVector(this.GetAscendingNode());
- AngleToDescendingNode = this.originOrbit.GetAngleToVector(this.GetDescendingNode());
- AltitudeSeaLevel = this.targetOrbit.altitude;
- ApoapsisHeight = this.targetOrbit.ApA;
- PeriapsisHeight = this.targetOrbit.PeA;
- TimeToApoapsis = this.targetOrbit.timeToAp;
- TimeToPeriapsis = this.targetOrbit.timeToPe;
- SemiMajorAxis = this.targetOrbit.semiMajorAxis;
- SemiMinorAxis = this.targetOrbit.semiMinorAxis;
-
- Distance = Vector3d.Distance(this.targetOrbit.pos, this.originOrbit.pos);
- OrbitalPeriod = this.targetOrbit.period;
- }
-
- #endregion
-
- #region Methods: private
+ RelativeSpeed = FlightGlobals.ship_obtSpeed - targetOrbit.orbitalSpeed;
+ PhaseAngle = originOrbit.GetPhaseAngle(targetOrbit);
+ InterceptAngle = CalcInterceptAngle();
+ TimeToAscendingNode = originOrbit.GetTimeToVector(GetAscendingNode());
+ TimeToDescendingNode = originOrbit.GetTimeToVector(GetDescendingNode());
+ AngleToAscendingNode = originOrbit.GetAngleToVector(GetAscendingNode());
+ AngleToDescendingNode = originOrbit.GetAngleToVector(GetDescendingNode());
+ AltitudeSeaLevel = targetOrbit.altitude;
+ ApoapsisHeight = targetOrbit.ApA;
+ PeriapsisHeight = targetOrbit.PeA;
+ TimeToApoapsis = targetOrbit.timeToAp;
+ TimeToPeriapsis = targetOrbit.timeToPe;
+ SemiMajorAxis = targetOrbit.semiMajorAxis;
+ SemiMinorAxis = targetOrbit.semiMinorAxis;
+
+ Distance = Vector3d.Distance(targetOrbit.pos, originOrbit.pos);
+ OrbitalPeriod = targetOrbit.period;
+ }
private double CalcInterceptAngle()
{
- var originRadius = (this.originOrbit.semiMinorAxis + this.originOrbit.semiMajorAxis) * 0.5;
- var targetRadius = (this.targetOrbit.semiMinorAxis + this.targetOrbit.semiMajorAxis) * 0.5;
- var angle = 180.0 * (1.0 - Math.Pow((originRadius + targetRadius) / (2.0 * targetRadius), 1.5));
+ double originRadius = (originOrbit.semiMinorAxis + originOrbit.semiMajorAxis) * 0.5;
+ double targetRadius = (targetOrbit.semiMinorAxis + targetOrbit.semiMajorAxis) * 0.5;
+ double angle = 180.0 * (1.0 - Math.Pow((originRadius + targetRadius) / (2.0 * targetRadius), 1.5));
angle = PhaseAngle - angle;
return RelativeInclination < 90.0 ? AngleHelper.Clamp360(angle) : AngleHelper.Clamp360(360.0 - (180.0 - angle));
}
private Vector3d GetAscendingNode()
{
- return Vector3d.Cross(this.targetOrbit.GetOrbitNormal(), this.originOrbit.GetOrbitNormal());
+ return Vector3d.Cross(targetOrbit.GetOrbitNormal(), originOrbit.GetOrbitNormal());
}
private Vector3d GetDescendingNode()
{
- return Vector3d.Cross(this.originOrbit.GetOrbitNormal(), this.targetOrbit.GetOrbitNormal());
- }
-
- #endregion
+ return Vector3d.Cross(originOrbit.GetOrbitNormal(), targetOrbit.GetOrbitNormal());
+ }
}
}
--- a/KerbalEngineer/Flight/Readouts/Surface/AtmosphericEfficiency.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/AtmosphericEfficiency.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,36 +17,26 @@
// 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.Surface
{
+ using Extensions;
+ using Sections;
+
public class AtmosphericEfficiency : ReadoutModule
{
- #region Constructors
-
public AtmosphericEfficiency()
{
- this.Name = "Atmos. Efficiency";
- this.Category = ReadoutCategory.GetCategory("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.";
- this.IsDefault = true;
+ Name = "Atmos. Efficiency";
+ Category = ReadoutCategory.GetCategory("Surface");
+ HelpString = "Shows you vessel's efficiency as a ratio of the current velocity and terminal velocity. Less than 100% means that you are losing efficiency due to gravity and greater than 100% is due to drag.";
+ IsDefault = false;
}
-
- #endregion
-
- #region Methods: public
public override void Draw(SectionModule section)
{
if (AtmosphericProcessor.ShowDetails)
{
- this.DrawLine(AtmosphericProcessor.Efficiency.ToPercent(), section.IsHud);
+ DrawLine(AtmosphericProcessor.Efficiency.ToPercent(), section.IsHud);
}
}
@@ -59,7 +49,5 @@
{
AtmosphericProcessor.RequestUpdate();
}
-
- #endregion
}
}
--- a/KerbalEngineer/Flight/Readouts/Surface/Longitude.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/Longitude.cs
@@ -17,35 +17,25 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using KerbalEngineer.Flight.Sections;
-
-#endregion
-
namespace KerbalEngineer.Flight.Readouts.Surface
{
+ using Helpers;
+ using Sections;
+
public class Longitude : ReadoutModule
{
- #region Constructors
-
public Longitude()
{
- this.Name = "Longitude";
- this.Category = ReadoutCategory.GetCategory("Surface");
- this.HelpString = "Shows the vessel's longitude around a celestial body. Longitude is the angle from the bodies prime meridian.";
- this.IsDefault = true;
+ 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.";
+ IsDefault = true;
}
-
- #endregion
-
- #region Methods: public
public override void Draw(SectionModule section)
{
- this.DrawLine(KSPUtil.PrintLongitude(FlightGlobals.ship_longitude), section.IsHud);
+ double angle = AngleHelper.Clamp180(FlightGlobals.ship_longitude);
+ DrawLine(Units.ToAngleDMS(angle) + (angle < 0.0 ? "W" : " E"), section.IsHud);
}
-
- #endregion
}
}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Surface/MachNumber.cs
@@ -1,1 +1,43 @@
+//
+// 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.Flight.Readouts.Surface
+{
+ using Extensions;
+ using Sections;
+
+ public class MachNumber : ReadoutModule
+ {
+ public MachNumber()
+ {
+ Name = "Mach Number";
+ Category = ReadoutCategory.GetCategory("Surface");
+ HelpString = "Shows the vessel's mach number.";
+ IsDefault = true;
+ }
+
+ public override void Draw(SectionModule section)
+ {
+ if (FlightGlobals.ActiveVessel.atmDensity > 0.0)
+ {
+ DrawLine(FlightGlobals.ActiveVessel.mach.ToMach(), section.IsHud);
+ }
+ }
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Thermal/ConvectionFlux.cs
@@ -1,1 +1,53 @@
+//
+// 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.Flight.Readouts.Thermal
+{
+ using Extensions;
+ using Sections;
+
+ public class ConvectionFlux : ReadoutModule
+ {
+ public ConvectionFlux()
+ {
+ Name = "Convection Flux";
+ Category = ReadoutCategory.GetCategory("Thermal");
+ HelpString = string.Empty;
+ IsDefault = true;
+ }
+
+ public override void Draw(SectionModule section)
+ {
+ if (ThermalProcessor.ShowDetails && FlightGlobals.ActiveVessel.atmDensity > 0.0)
+ {
+ DrawLine(ThermalProcessor.ConvectionFlux.ToFlux(), section.IsHud);
+ }
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(ThermalProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ ThermalProcessor.RequestUpdate();
+ }
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Thermal/CoolestPart.cs
@@ -1,1 +1,52 @@
+//
+// 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.Flight.Readouts.Thermal
+{
+ using Sections;
+
+ public class CoolestPart : ReadoutModule
+ {
+ public CoolestPart()
+ {
+ Name = "Coolest Part";
+ Category = ReadoutCategory.GetCategory("Thermal");
+ HelpString = string.Empty;
+ IsDefault = true;
+ }
+
+ public override void Draw(SectionModule section)
+ {
+ if (ThermalProcessor.ShowDetails)
+ {
+ DrawLine(ThermalProcessor.CoolestPartName, section.IsHud);
+ }
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(ThermalProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ ThermalProcessor.RequestUpdate();
+ }
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Thermal/CoolestTemperature.cs
@@ -1,1 +1,53 @@
+//
+// 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.Flight.Readouts.Thermal
+{
+ using Helpers;
+ using Sections;
+
+ public class CoolestTemperature : ReadoutModule
+ {
+ public CoolestTemperature()
+ {
+ Name = "Coolest Temperature";
+ Category = ReadoutCategory.GetCategory("Thermal");
+ HelpString = string.Empty;
+ IsDefault = true;
+ }
+
+ public override void Draw(SectionModule section)
+ {
+ if (ThermalProcessor.ShowDetails)
+ {
+ DrawLine(Units.ToTemperature(ThermalProcessor.CoolestTemperature, ThermalProcessor.CoolestTemperatureMax), section.IsHud);
+ }
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(ThermalProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ ThermalProcessor.RequestUpdate();
+ }
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Thermal/CriticalPart.cs
@@ -1,1 +1,52 @@
+//
+// 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.Flight.Readouts.Thermal
+{
+ using Sections;
+
+ public class CriticalPart : ReadoutModule
+ {
+ public CriticalPart()
+ {
+ Name = "Critical Part";
+ Category = ReadoutCategory.GetCategory("Thermal");
+ HelpString = string.Empty;
+ IsDefault = true;
+ }
+
+ public override void Draw(SectionModule section)
+ {
+ if (ThermalProcessor.ShowDetails)
+ {
+ DrawLine(ThermalProcessor.CriticalPartName, section.IsHud);
+ }
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(ThermalProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ ThermalProcessor.RequestUpdate();
+ }
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Thermal/CriticalPercentage.cs
@@ -1,1 +1,53 @@
+//
+// 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.Flight.Readouts.Thermal
+{
+ using Extensions;
+ using Sections;
+
+ public class CriticalPercentage : ReadoutModule
+ {
+ public CriticalPercentage()
+ {
+ Name = "Critical Percentage";
+ Category = ReadoutCategory.GetCategory("Thermal");
+ HelpString = string.Empty;
+ IsDefault = true;
+ }
+
+ public override void Draw(SectionModule section)
+ {
+ if (ThermalProcessor.ShowDetails)
+ {
+ DrawLine(ThermalProcessor.CriticalTemperaturePercentage.ToPercent(), section.IsHud);
+ }
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(ThermalProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ ThermalProcessor.RequestUpdate();
+ }
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Thermal/CriticalTemperature.cs
@@ -1,1 +1,53 @@
+//
+// 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.Flight.Readouts.Thermal
+{
+ using Helpers;
+ using Sections;
+
+ public class CriticalTemperature : ReadoutModule
+ {
+ public CriticalTemperature()
+ {
+ Name = "Critical Temperature";
+ Category = ReadoutCategory.GetCategory("Thermal");
+ HelpString = string.Empty;
+ IsDefault = true;
+ }
+
+ public override void Draw(SectionModule section)
+ {
+ if (ThermalProcessor.ShowDetails)
+ {
+ DrawLine(Units.ToTemperature(ThermalProcessor.CriticalTemperature, ThermalProcessor.CriticalTemperatureMax), section.IsHud);
+ }
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(ThermalProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ ThermalProcessor.RequestUpdate();
+ }
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Thermal/HottestPart.cs
@@ -1,1 +1,52 @@
+//
+// 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.Flight.Readouts.Thermal
+{
+ using Sections;
+
+ public class HottestPart : ReadoutModule
+ {
+ public HottestPart()
+ {
+ Name = "Hottest Part";
+ Category = ReadoutCategory.GetCategory("Thermal");
+ HelpString = string.Empty;
+ IsDefault = true;
+ }
+
+ public override void Draw(SectionModule section)
+ {
+ if (ThermalProcessor.ShowDetails)
+ {
+ DrawLine(ThermalProcessor.HottestPartName, section.IsHud);
+ }
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(ThermalProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ ThermalProcessor.RequestUpdate();
+ }
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Thermal/HottestTemperature.cs
@@ -1,1 +1,53 @@
+//
+// 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.Flight.Readouts.Thermal
+{
+ using Helpers;
+ using Sections;
+
+ public class HottestTemperature : ReadoutModule
+ {
+ public HottestTemperature()
+ {
+ Name = "Hottest Temperature";
+ Category = ReadoutCategory.GetCategory("Thermal");
+ HelpString = string.Empty;
+ IsDefault = true;
+ }
+
+ public override void Draw(SectionModule section)
+ {
+ if (ThermalProcessor.ShowDetails)
+ {
+ DrawLine(Units.ToTemperature(ThermalProcessor.HottestTemperature, ThermalProcessor.HottestTemperatureMax), section.IsHud);
+ }
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(ThermalProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ ThermalProcessor.RequestUpdate();
+ }
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Thermal/InternalFlux.cs
@@ -1,1 +1,53 @@
+//
+// 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.Flight.Readouts.Thermal
+{
+ using Extensions;
+ using Sections;
+
+ public class InternalFlux : ReadoutModule
+ {
+ public InternalFlux()
+ {
+ Name = "Internal Flux";
+ Category = ReadoutCategory.GetCategory("Thermal");
+ HelpString = string.Empty;
+ IsDefault = true;
+ }
+
+ public override void Draw(SectionModule section)
+ {
+ if (ThermalProcessor.ShowDetails)
+ {
+ DrawLine(ThermalProcessor.InternalFlux.ToFlux(), section.IsHud);
+ }
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(ThermalProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ ThermalProcessor.RequestUpdate();
+ }
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Thermal/RadiationFlux.cs
@@ -1,1 +1,53 @@
+//
+// 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.Flight.Readouts.Thermal
+{
+ using Extensions;
+ using Sections;
+
+ public class RadiationFlux : ReadoutModule
+ {
+ public RadiationFlux()
+ {
+ Name = "Radiation Flux";
+ Category = ReadoutCategory.GetCategory("Thermal");
+ HelpString = string.Empty;
+ IsDefault = true;
+ }
+
+ public override void Draw(SectionModule section)
+ {
+ if (ThermalProcessor.ShowDetails)
+ {
+ DrawLine(ThermalProcessor.RadiationFlux.ToFlux(), section.IsHud);
+ }
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(ThermalProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ ThermalProcessor.RequestUpdate();
+ }
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Thermal/ThermalProcessor.cs
@@ -1,1 +1,132 @@
+//
+// 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.Flight.Readouts.Thermal
+{
+ public class ThermalProcessor : IUpdatable, IUpdateRequest
+ {
+ private static readonly ThermalProcessor instance = new ThermalProcessor();
+
+ static ThermalProcessor()
+ {
+ HottestTemperature = 0.0;
+ HottestTemperatureMax = 0.0;
+ CoolestTemperature = 0.0;
+ CoolestTemperatureMax = 0.0;
+ CriticalTemperature = 0.0;
+ CriticalTemperatureMax = 0.0;
+ HottestPartName = string.Empty;
+ CoolestPartName = string.Empty;
+ CriticalPartName = string.Empty;
+ }
+
+ public static double ConvectionFlux { get; private set; }
+
+ public static string CoolestPartName { get; private set; }
+
+ public static double CoolestTemperature { get; private set; }
+
+ public static double CoolestTemperatureMax { get; private set; }
+
+ public static string CriticalPartName { get; private set; }
+
+ public static double CriticalTemperature { get; private set; }
+
+ public static double CriticalTemperatureMax { get; private set; }
+
+ public static double CriticalTemperaturePercentage { get; private set; }
+
+ public static string HottestPartName { get; private set; }
+
+ public static double HottestTemperature { get; private set; }
+
+ public static double HottestTemperatureMax { get; private set; }
+
+ public static ThermalProcessor Instance
+ {
+ get
+ {
+ return instance;
+ }
+ }
+
+ public static double InternalFlux { get; private set; }
+
+ public static double RadiationFlux { get; private set; }
+ public static bool ShowDetails { get; private set; }
+
+ public bool UpdateRequested { get; set; }
+
+ public static void RequestUpdate()
+ {
+ instance.UpdateRequested = true;
+ }
+
+ public void Update()
+ {
+ if (FlightGlobals.ActiveVessel.parts.Count == 0)
+ {
+ ShowDetails = false;
+ return;
+ }
+
+ ShowDetails = true;
+
+ ConvectionFlux = 0.0;
+ RadiationFlux = 0.0;
+ InternalFlux = 0.0;
+ HottestTemperature = 0.0;
+ CoolestTemperature = double.MaxValue;
+ CriticalTemperature = double.MaxValue;
+ CriticalTemperaturePercentage = 0.0;
+ HottestPartName = string.Empty;
+ CoolestPartName = string.Empty;
+ CriticalPartName = string.Empty;
+
+ for (int i = 0; i < FlightGlobals.ActiveVessel.parts.Count; ++i)
+ {
+ Part part = FlightGlobals.ActiveVessel.parts[i];
+
+ ConvectionFlux = ConvectionFlux + part.thermalConvectionFlux;
+ RadiationFlux = RadiationFlux + part.thermalRadiationFlux;
+ InternalFlux = InternalFlux + part.thermalInternalFluxPrevious;
+
+ if (part.temperature > HottestTemperature)
+ {
+ HottestTemperature = part.temperature;
+ HottestTemperatureMax = part.maxTemp;
+ HottestPartName = part.partInfo.title;
+ }
+ if (part.temperature < CoolestTemperature)
+ {
+ CoolestTemperature = part.temperature;
+ CoolestTemperatureMax = part.maxTemp;
+ CoolestPartName = part.partInfo.title;
+ }
+ if (part.temperature / part.maxTemp > CriticalTemperaturePercentage)
+ {
+ CriticalTemperature = part.temperature;
+ CriticalTemperatureMax = part.maxTemp;
+ CriticalTemperaturePercentage = part.temperature / part.maxTemp;
+ CriticalPartName = part.partInfo.title;
+ }
+ }
+ }
+ }
+}
--- a/KerbalEngineer/Flight/Sections/SectionLibrary.cs
+++ b/KerbalEngineer/Flight/Sections/SectionLibrary.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
@@ -19,22 +19,19 @@
#region Using Directives
-using System.Collections.Generic;
-using System.Linq;
-
-using KerbalEngineer.Flight.Readouts;
-using KerbalEngineer.Settings;
-
-using UnityEngine;
-
#endregion
namespace KerbalEngineer.Flight.Sections
{
+ using System.Collections.Generic;
+ using System.Linq;
+ using Readouts;
+ using Settings;
+ using UnityEngine;
+
public static class SectionLibrary
{
#region Constructors
-
/// <summary>
/// Sets up and populates the library with the stock sections on creation.
/// </summary>
@@ -71,7 +68,14 @@
ReadoutModules = ReadoutLibrary.GetCategory(ReadoutCategory.GetCategory("Rendezvous")).Where(r => r.IsDefault).ToList()
});
- var hud1 = new SectionModule
+ CustomSections.Add(new SectionModule
+ {
+ Name = "THERMAL",
+ Abbreviation = "HEAT",
+ ReadoutModules = ReadoutLibrary.GetCategory(ReadoutCategory.GetCategory("Thermal")).Where(r => r.IsDefault).ToList()
+ });
+
+ SectionModule hud1 = new SectionModule
{
Name = "HUD 1",
Abbreviation = "HUD 1",
@@ -90,7 +94,7 @@
hud1.IsHud = true;
CustomSections.Add(hud1);
- var hud2 = new SectionModule
+ SectionModule hud2 = new SectionModule
{
Name = "HUD 2",
Abbreviation = "HUD 2",
@@ -101,7 +105,8 @@
ReadoutLibrary.GetReadout("AltitudeTerrain"),
ReadoutLibrary.GetReadout("VerticalSpeed"),
ReadoutLibrary.GetReadout("HorizontalSpeed"),
- ReadoutLibrary.GetReadout("Biome")
+ ReadoutLibrary.GetReadout("Biome"),
+ ReadoutLibrary.GetReadout("MachNumber")
},
};
hud2.FloatingPositionX = Screen.width * 0.75f - (hud2.ReadoutModules.First().ContentWidth * 0.5f);
@@ -109,11 +114,9 @@
hud2.IsHud = true;
CustomSections.Add(hud2);
}
-
#endregion
#region Properties
-
/// <summary>
/// Gets and sets a list of custom sections.
/// </summary>
@@ -133,13 +136,11 @@
/// Gets and sets a list of stock sections
/// </summary>
public static List<SectionModule> StockSections { get; set; }
-
#endregion
#region Updating
#region Methods: public
-
/// <summary>
/// Fixed update all of the sections.
/// </summary>
@@ -160,17 +161,15 @@
UpdateSections(StockSections);
UpdateSections(CustomSections);
}
-
#endregion
#region Methods: private
-
/// <summary>
/// Fixed updates a list of sections.
/// </summary>
private static void FixedUpdateSections(IEnumerable<SectionModule> sections)
{
- foreach (var section in sections)
+ foreach (SectionModule section in sections)
{
if (section.IsVisible)
{
@@ -184,13 +183,13 @@
/// </summary>
private static void UpdateSections(IEnumerable<SectionModule> sections)
{
- foreach (var section in sections)
+ foreach (SectionModule section in sections)
{
if (section.IsVisible)
{
if (!section.IsFloating)
{
- foreach (var readout in section.ReadoutModules)
+ foreach (ReadoutModule readout in section.ReadoutModules)
{
if (readout.ResizeRequested)
{
@@ -203,7 +202,7 @@
}
else
{
- foreach (var readout in section.ReadoutModules)
+ foreach (ReadoutModule readout in section.ReadoutModules)
{
if (readout.ResizeRequested)
{
@@ -218,13 +217,11 @@
NumberOfSections++;
}
}
-
#endregion
#endregion
#region Saving and Loading
-
/// <summary>
/// Loads the state of all stored sections.
/// </summary>
@@ -243,11 +240,11 @@
}
});
- var handler = SettingHandler.Load("SectionLibrary.xml", new[] {typeof(List<SectionModule>)});
+ SettingHandler handler = SettingHandler.Load("SectionLibrary.xml", new[] { typeof(List<SectionModule>) });
StockSections = handler.Get("StockSections", StockSections);
CustomSections = handler.Get("CustomSections", CustomSections);
- foreach (var section in GetAllSections())
+ foreach (SectionModule section in GetAllSections())
{
section.ClearNullReadouts();
}
@@ -258,22 +255,20 @@
/// </summary>
public static void Save()
{
- var handler = new SettingHandler();
+ SettingHandler handler = new SettingHandler();
handler.Set("StockSections", StockSections);
handler.Set("CustomSections", CustomSections);
handler.Save("SectionLibrary.xml");
}
-
#endregion
#region Methods
-
/// <summary>
/// Gets a list containing all section modules.
/// </summary>
public static List<SectionModule> GetAllSections()
{
- var sections = new List<SectionModule>();
+ List<SectionModule> sections = new List<SectionModule>();
sections.AddRange(StockSections);
sections.AddRange(CustomSections);
return sections;
@@ -326,7 +321,6 @@
{
return StockSections.Remove(GetStockSection(name));
}
-
#endregion
}
}
--- a/KerbalEngineer/Helpers/AngleHelper.cs
+++ b/KerbalEngineer/Helpers/AngleHelper.cs
@@ -17,21 +17,30 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using UnityEngine;
-
-#endregion
-
namespace KerbalEngineer.Helpers
{
+ using UnityEngine;
+
public static class AngleHelper
{
- #region Methods: public
+ public static double Clamp180(double angle)
+ {
+ angle = Clamp360(angle);
+ if (angle > 180.0)
+ {
+ angle = angle - 360.0;
+ }
+ return angle;
+ }
- public static double Clamp360(double value)
+ public static double Clamp360(double angle)
{
- return ClampBetween(value, 0.0, 360.0);
+ angle = angle % 360.0;
+ if (angle < 0.0)
+ {
+ angle = angle + 360.0;
+ }
+ return angle;
}
public static double ClampBetween(double value, double minimum, double maximum)
@@ -51,8 +60,8 @@
public static double GetAngleBetweenVectors(Vector3d left, Vector3d right)
{
- var angle = Vector3d.Angle(left, right);
- var rotated = QuaternionD.AngleAxis(90.0, Vector3d.forward) * right;
+ double angle = Vector3d.Angle(left, right);
+ Vector3d rotated = QuaternionD.AngleAxis(90.0, Vector3d.forward) * right;
if (Vector3d.Angle(rotated, left) > 90.0)
{
@@ -60,7 +69,5 @@
}
return angle;
}
-
- #endregion
}
}
--- a/KerbalEngineer/Helpers/Units.cs
+++ b/KerbalEngineer/Helpers/Units.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
@@ -19,14 +19,10 @@
namespace KerbalEngineer.Helpers
{
- #region Using Directives
using System;
-
- #endregion
public static class Units
{
- #region Methods
public const double GRAVITY = 9.80665;
public static string Concat(int value1, int value2)
@@ -95,7 +91,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)
@@ -127,6 +123,11 @@
return value.ToString("N" + decimals) + "Mm";
}
+ public static string ToFlux(double value)
+ {
+ return value.ToString("#,0.00") + "W";
+ }
+
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";
@@ -139,6 +140,11 @@
return value1.ToString(format1) + " / " + value2.ToString(format2) + "kN";
}
+ public static string ToMach(double value)
+ {
+ return value.ToString("0.00") + "Ma";
+ }
+
public static string ToMass(double value, int decimals = 0)
{
if (value >= 1000.0)
@@ -182,6 +188,16 @@
return value.ToString("N" + decimals) + "m/s";
}
+ public static string ToTemperature(double value)
+ {
+ return value.ToString("#,0") + "K";
+ }
+
+ public static string ToTemperature(double value1, double value2)
+ {
+ return value1.ToString("#,0") + " / " + value2.ToString("#,0") + "K";
+ }
+
public static string ToTime(double value)
{
return TimeFormatter.ConvertToString(value);
@@ -191,6 +207,5 @@
{
return value.ToString((value < 100.0) ? (Math.Abs(value) < Double.Epsilon) ? "N0" : "N1" : "N0") + "kNm";
}
- #endregion
}
}
--- a/KerbalEngineer/KerbalEngineer.csproj
+++ b/KerbalEngineer/KerbalEngineer.csproj
@@ -48,6 +48,7 @@
<Compile Include="Editor\ResourceInfoItem.cs" />
<Compile Include="Extensions\FloatExtensions.cs" />
<Compile Include="Extensions\OrbitExtensions.cs" />
+ <Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Flight\ActionMenuGui.cs" />
<Compile Include="Flight\Presets\Preset.cs" />
<Compile Include="Flight\Readouts\Miscellaneous\SystemTime.cs" />
@@ -89,6 +90,18 @@
<Compile Include="Flight\Readouts\Surface\Biome.cs" />
<Compile Include="Flight\Readouts\Surface\HorizontalAcceleration.cs" />
<Compile Include="Flight\Readouts\Surface\VerticalAcceleration.cs" />
+ <Compile Include="Flight\Readouts\Surface\MachNumber.cs" />
+ <Compile Include="Flight\Readouts\Thermal\CriticalPart.cs" />
+ <Compile Include="Flight\Readouts\Thermal\CoolestPart.cs" />
+ <Compile Include="Flight\Readouts\Thermal\CoolestTemperature.cs" />
+ <Compile Include="Flight\Readouts\Thermal\CriticalPercentage.cs" />
+ <Compile Include="Flight\Readouts\Thermal\CriticalTemperature.cs" />
+ <Compile Include="Flight\Readouts\Thermal\InternalFlux.cs" />
+ <Compile Include="Flight\Readouts\Thermal\RadiationFlux.cs" />
+ <Compile Include="Flight\Readouts\Thermal\ConvectionFlux.cs" />
+ <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\AttitudeProcessor.cs" />
<Compile Include="Flight\Readouts\Vessel\DeltaVCurrentTotal.cs" />
<Compile Include="Flight\Readouts\Vessel\PitchRate.cs" />
@@ -208,7 +221,7 @@
</ItemGroup>
<ItemGroup>
<Reference Include="Assembly-CSharp">
- <HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\SteamApps\common\Kerbal Space Program\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
+ <HintPath>..\Game\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System">
@@ -220,7 +233,7 @@
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine">
- <HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\SteamApps\common\Kerbal Space Program\KSP_Data\Managed\UnityEngine.dll</HintPath>
+ <HintPath>..\Game\KSP_Data\Managed\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
--- a/KerbalEngineer/VesselSimulator/EngineSim.cs
+++ b/KerbalEngineer/VesselSimulator/EngineSim.cs
@@ -31,6 +31,7 @@
private static readonly Pool<EngineSim> pool = new Pool<EngineSim>(Create, Reset);
private readonly ResourceContainer resourceConsumptions = new ResourceContainer();
+ private readonly ResourceContainer resourceFlowModes = new ResourceContainer();
public double actualThrust = 0;
public bool isActive = false;
@@ -52,6 +53,7 @@
private static void Reset(EngineSim engineSim)
{
engineSim.resourceConsumptions.Reset();
+ engineSim.resourceFlowModes.Reset();
engineSim.actualThrust = 0;
engineSim.isActive = false;
engineSim.isp = 0;
@@ -86,11 +88,10 @@
List<Propellant> propellants,
bool active,
float resultingThrust,
- List<Transform> thrustTransforms)
+ List<Transform> thrustTransforms,
+ LogMsg log)
{
EngineSim engineSim = pool.Borrow();
-
- StringBuilder buffer = null;
engineSim.isp = 0.0;
engineSim.maxMach = 0.0f;
@@ -99,61 +100,75 @@
engineSim.isActive = active;
engineSim.thrustVec = vecThrust;
engineSim.resourceConsumptions.Reset();
+ engineSim.resourceFlowModes.Reset();
engineSim.appliedForces.Clear();
double flowRate = 0.0;
if (engineSim.partSim.hasVessel)
{
+ if (log != null) log.buf.AppendLine("hasVessel is true");
+
float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, engineSim.partSim.part.atmDensity, velCurve, machNumber, ref engineSim.maxMach);
engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere);
engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp);
engineSim.actualThrust = engineSim.isActive ? resultingThrust : 0.0;
+ if (log != null)
+ {
+ log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier);
+ log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp);
+ log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust);
+ log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust);
+ }
if (throttleLocked)
{
+ if (log != null) log.buf.AppendLine("throttleLocked is true, using thrust for flowRate");
flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
}
else
{
if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false)
{
+ if (log != null) log.buf.AppendLine("throttled up and not landed, using actualThrust for flowRate");
flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp);
}
else
{
+ if (log != null) log.buf.AppendLine("throttled down or landed, using thrust for flowRate");
flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
}
}
}
else
{
+ if (log != null) log.buf.AppendLine("hasVessel is false");
float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, CelestialBodies.SelectedBody.GetDensity(BuildAdvanced.Altitude), velCurve, machNumber, ref engineSim.maxMach);
engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere);
engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp);
+ engineSim.actualThrust = 0d;
+ if (log != null)
+ {
+ log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier);
+ log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp);
+ log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust);
+ log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust);
+ }
+
+ if (log != null) log.buf.AppendLine("no vessel, using thrust for flowRate");
flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
}
- if (SimManager.logOutput)
- {
- buffer = new StringBuilder(1024);
- buffer.AppendFormat("flowRate = {0:g6}\n", flowRate);
- }
-
- engineSim.thrust = flowRate * (engineSim.isp * IspG);
- // I did not look into the diff between those 2 so I made them equal...
- engineSim.actualThrust = engineSim.thrust;
+ if (log != null) log.buf.AppendFormat("flowRate = {0:g6}\n", flowRate);
float flowMass = 0f;
for (int i = 0; i < propellants.Count; ++i)
{
Propellant propellant = propellants[i];
- flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);
- }
-
- if (SimManager.logOutput)
- {
- buffer.AppendFormat("flowMass = {0:g6}\n", flowMass);
- }
+ if (!propellant.ignoreForIsp)
+ flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);
+ }
+
+ if (log != null) log.buf.AppendFormat("flowMass = {0:g6}\n", flowMass);
for (int i = 0; i < propellants.Count; ++i)
{
@@ -165,21 +180,14 @@
}
double consumptionRate = propellant.ratio * flowRate / flowMass;
- if (SimManager.logOutput)
- {
- buffer.AppendFormat(
+ if (log != null) log.buf.AppendFormat(
"Add consumption({0}, {1}:{2:d}) = {3:g6}\n",
ResourceContainer.GetResourceName(propellant.id),
theEngine.name,
theEngine.partId,
consumptionRate);
- }
engineSim.resourceConsumptions.Add(propellant.id, consumptionRate);
- }
-
- if (SimManager.logOutput)
- {
- MonoBehaviour.print(buffer);
+ engineSim.resourceFlowModes.Add(propellant.id, (double)propellant.GetFlowMode());
}
double thrustPerThrustTransform = engineSim.thrust / thrustTransforms.Count;
@@ -285,7 +293,7 @@
sourcePartSets.Add(type, sourcePartSet);
}
- switch (ResourceContainer.GetResourceFlowMode(type))
+ switch ((ResourceFlowMode)this.resourceFlowModes[type])
{
case ResourceFlowMode.NO_FLOW:
if (partSim.resources[type] > SimManager.RESOURCE_MIN && partSim.resourceFlowStates[type] != 0)
--- a/KerbalEngineer/VesselSimulator/PartSim.cs
+++ b/KerbalEngineer/VesselSimulator/PartSim.cs
@@ -34,9 +34,11 @@
private readonly List<AttachNodeSim> attachNodes = new List<AttachNodeSim>();
+ public double realMass;
public double baseMass;
+ public double baseMassForCoM;
public Vector3d centerOfMass;
- public double cost;
+ public double baseCost;
public int decoupledInStage;
public bool fuelCrossFeed;
public List<PartSim> fuelTargets = new List<PartSim>();
@@ -88,7 +90,9 @@
partSim.resourceDrains.Reset();
partSim.resourceFlowStates.Reset();
partSim.resources.Reset();
+ partSim.baseCost = 0d;
partSim.baseMass = 0d;
+ partSim.baseMassForCoM = 0d;
partSim.startMass = 0d;
}
@@ -100,15 +104,13 @@
public static PartSim New(Part thePart, int id, double atmosphere, LogMsg log)
{
PartSim partSim = pool.Borrow();
-
partSim.part = thePart;
partSim.centerOfMass = thePart.transform.TransformPoint(thePart.CoMOffset);
partSim.partId = id;
partSim.name = partSim.part.partInfo.name;
- if (log != null)
- log.buf.AppendLine("Create PartSim for " + partSim.name);
+ if (log != null) log.buf.AppendLine("Create PartSim for " + partSim.name);
partSim.parent = null;
partSim.parentAttach = partSim.part.attachMode;
@@ -121,23 +123,32 @@
partSim.inverseStage = partSim.part.inverseStage;
//MonoBehaviour.print("inverseStage = " + inverseStage);
- partSim.cost = partSim.part.GetCostWet();
+ partSim.baseCost = partSim.part.GetCostDry();
+
+ if (log != null)
+ {
+ log.buf.AppendLine("Parent part = " + (partSim.part.parent == null ? "null" : partSim.part.parent.partInfo.name));
+ log.buf.AppendLine("physicalSignificance = " + partSim.part.physicalSignificance);
+ log.buf.AppendLine("PhysicsSignificance = " + partSim.part.PhysicsSignificance);
+ }
// Work out if the part should have no physical significance
+ // The root part is never "no physics"
partSim.isNoPhysics = partSim.part.physicalSignificance == Part.PhysicalSignificance.NONE ||
- partSim.part.PhysicsSignificance == 1;
+ partSim.part.PhysicsSignificance == 1;
if (partSim.part.HasModule<LaunchClamp>())
{
- if (log != null)
- log.buf.AppendLine("Ignoring mass of launch clamp");
+ partSim.realMass = 0d;
+ if (log != null) log.buf.AppendLine("Ignoring mass of launch clamp");
}
else
{
- partSim.baseMass = partSim.part.mass;
- if (log != null)
- log.buf.AppendLine("Using part.mass of " + partSim.part.mass);
- }
+ partSim.realMass = partSim.part.mass;
+ if (log != null) log.buf.AppendLine("Using part.mass of " + partSim.part.mass);
+ }
+
+ partSim.moduleMass = partSim.part.GetModuleMass((float)partSim.realMass);
for (int i = 0; i < partSim.part.Resources.Count; i++)
{
@@ -155,12 +166,9 @@
}
else
{
- if (log != null)
- log.buf.AppendLine(resource.resourceName + " is NaN. Skipping.");
- }
- }
-
- partSim.startMass = partSim.GetMass(-1);
+ if (log != null) log.buf.AppendLine(resource.resourceName + " is NaN. Skipping.");
+ }
+ }
partSim.hasVessel = (partSim.part.vessel != null);
partSim.isLanded = partSim.hasVessel && partSim.part.vessel.Landed;
@@ -177,8 +185,7 @@
partSim.isEngine = partSim.hasMultiModeEngine || partSim.hasModuleEnginesFX || partSim.hasModuleEngines;
- if (log != null)
- log.buf.AppendLine("Created " + partSim.name + ". Decoupled in stage " + partSim.decoupledInStage);
+ if (log != null) log.buf.AppendLine("Created " + partSim.name + ". Decoupled in stage " + partSim.decoupledInStage);
return partSim;
}
@@ -226,10 +233,7 @@
ModuleEnginesFX engine = engines[i];
if (engine.engineID == mode)
{
- if (log != null)
- {
- log.buf.AppendLine("Module: " + engine.moduleName);
- }
+ if (log != null) log.buf.AppendLine("Module: " + engine.moduleName);
Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
@@ -251,7 +255,8 @@
engine.propellants,
engine.isOperational,
engine.resultingThrust,
- engine.thrustTransforms);
+ engine.thrustTransforms,
+ log);
allEngines.Add(engineSim);
}
}
@@ -264,10 +269,7 @@
for (int i = 0; i < engines.Count; ++i)
{
ModuleEngines engine = engines[i];
- if (log != null)
- {
- log.buf.AppendLine("Module: " + engine.moduleName);
- }
+ if (log != null) log.buf.AppendLine("Module: " + engine.moduleName);
Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
@@ -289,7 +291,8 @@
engine.propellants,
engine.isOperational,
engine.resultingThrust,
- engine.thrustTransforms);
+ engine.thrustTransforms,
+ log);
allEngines.Add(engineSim);
}
}
@@ -348,9 +351,13 @@
buffer.Append(name);
buffer.AppendFormat(":[id = {0:d}, decouple = {1:d}, invstage = {2:d}", partId, decoupledInStage, inverseStage);
- buffer.AppendFormat(", vesselName = '{0}'", vesselName);
- buffer.AppendFormat(", vesselType = {0}", SimManager.GetVesselTypeString(vesselType));
- buffer.AppendFormat(", initialVesselName = '{0}'", initialVesselName);
+ //buffer.AppendFormat(", vesselName = '{0}'", vesselName);
+ //buffer.AppendFormat(", vesselType = {0}", SimManager.GetVesselTypeString(vesselType));
+ //buffer.AppendFormat(", initialVesselName = '{0}'", initialVesselName);
+
+ buffer.AppendFormat(", isNoPhys = {0}", isNoPhysics);
+ buffer.AppendFormat(", baseMass = {0}", baseMass);
+ buffer.AppendFormat(", baseMassForCoM = {0}", baseMassForCoM);
buffer.AppendFormat(", fuelCF = {0}", fuelCrossFeed);
buffer.AppendFormat(", noCFNKey = '{0}'", noCrossFeedNodeKey);
@@ -386,9 +393,7 @@
{
PartSim partSim = allParts[i];
if (partSim.parent == this)
- {
partSim.DumpPartToBuffer(buffer, newPrefix, allParts);
- }
}
}
}
@@ -398,17 +403,18 @@
foreach (int type in types)
{
if (resources.HasType(type) && resourceFlowStates[type] != 0 && resources[type] > SimManager.RESOURCE_PART_EMPTY_THRESH)
- {
return false;
- }
}
return true;
}
- public double GetMass(int currentStage)
- {
- double mass = baseMass;
+ public double GetMass(int currentStage, bool forCoM = false)
+ {
+ if (decoupledInStage >= currentStage)
+ return 0d;
+
+ double mass = forCoM ? baseMassForCoM : baseMass;
for (int i = 0; i < resources.Types.Count; ++i)
{
@@ -422,7 +428,22 @@
return mass;
}
-
+
+ public double GetCost(int currentStage)
+ {
+ if (decoupledInStage >= currentStage)
+ return 0d;
+
+ double cost = baseCost;
+
+ for (int i = 0; i < resources.Types.Count; ++i)
+ {
+ cost += resources.GetResourceCost(resources.Types[i]);
+ }
+
+ return cost;
+ }
+
public void ReleasePart()
{
this.part = null;
@@ -442,14 +463,11 @@
// Rule 1: Each part can be only visited once, If it is visited for second time in particular search it returns as is.
if (visited.Contains(this))
{
- if (log != null)
- log.buf.AppendLine(indent + "Returning empty set, already visited (" + name + ":" + partId + ")");
-
+ if (log != null) log.buf.AppendLine(indent + "Returning empty set, already visited (" + name + ":" + partId + ")");
return;
}
- if (log != null)
- log.buf.AppendLine(indent + "Adding this to visited");
+ if (log != null) log.buf.AppendLine(indent + "Adding this to visited");
visited.Add(this);
@@ -466,13 +484,11 @@
{
if (visited.Contains(partSim))
{
- if (log != null)
- log.buf.AppendLine(indent + "Fuel target already visited, skipping (" + partSim.name + ":" + partSim.partId + ")");
+ if (log != null) log.buf.AppendLine(indent + "Fuel target already visited, skipping (" + partSim.name + ":" + partSim.partId + ")");
}
else
{
- if (log != null)
- log.buf.AppendLine(indent + "Adding fuel target as source (" + partSim.name + ":" + partSim.partId + ")");
+ if (log != null) log.buf.AppendLine(indent + "Adding fuel target as source (" + partSim.name + ":" + partSim.partId + ")");
partSim.GetSourceSet(type, allParts, visited, allSources, log, indent);
}
@@ -481,9 +497,7 @@
if (allSources.Count > lastCount)
{
- if (log != null)
- log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " fuel target sources (" + this.name + ":" + this.partId + ")");
-
+ if (log != null) log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " fuel target sources (" + this.name + ":" + this.partId + ")");
return;
}
@@ -512,13 +526,11 @@
{
if (visited.Contains(attachSim.attachedPartSim))
{
- if (log != null)
- log.buf.AppendLine(indent + "Attached part already visited, skipping (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
+ if (log != null) log.buf.AppendLine(indent + "Attached part already visited, skipping (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
}
else
{
- if (log != null)
- log.buf.AppendLine(indent + "Adding attached part as source (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
+ if (log != null) log.buf.AppendLine(indent + "Adding attached part as source (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
attachSim.attachedPartSim.GetSourceSet(type, allParts, visited, allSources, log, indent);
}
@@ -529,9 +541,7 @@
if (allSources.Count > lastCount)
{
- if (log != null)
- log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " attached sources (" + this.name + ":" + this.partId + ")");
-
+ if (log != null) log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " attached sources (" + this.name + ":" + this.partId + ")");
return;
}
}
@@ -546,16 +556,14 @@
{
allSources.Add(this);
- if (log != null)
- log.buf.AppendLine(indent + "Returning enabled tank as only source (" + name + ":" + partId + ")");
+ if (log != null) log.buf.AppendLine(indent + "Returning enabled tank as only source (" + name + ":" + partId + ")");
}
return;
}
else
{
- if (log != null)
- log.buf.AppendLine(indent + "Not fuel tank or disabled. HasType = " + resources.HasType(type) + " FlowState = " + resourceFlowStates[type]);
+ if (log != null) log.buf.AppendLine(indent + "Not fuel tank or disabled. HasType = " + resources.HasType(type) + " FlowState = " + resourceFlowStates[type]);
}
// Rule 7: If the part is radially attached to another part and it is child of that part in the ship's tree structure, it scans its
@@ -566,8 +574,7 @@
{
if (visited.Contains(parent))
{
- if (log != null)
- log.buf.AppendLine(indent + "Parent part already visited, skipping (" + parent.name + ":" + parent.partId + ")");
+ if (log != null) log.buf.AppendLine(indent + "Parent part already visited, skipping (" + parent.name + ":" + parent.partId + ")");
}
else
{
@@ -575,9 +582,7 @@
this.parent.GetSourceSet(type, allParts, visited, allSources, log, indent);
if (allSources.Count > lastCount)
{
- if (log != null)
- log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " parent sources (" + this.name + ":" + this.partId + ")");
-
+ if (log != null) log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " parent sources (" + this.name + ":" + this.partId + ")");
return;
}
}
@@ -585,8 +590,7 @@
}
// Rule 8: If all preceding rules failed, part returns empty list.
- if (log != null)
- log.buf.AppendLine(indent + "Returning empty set, no sources found (" + name + ":" + partId + ")");
+ if (log != null) log.buf.AppendLine(indent + "Returning empty set, no sources found (" + name + ":" + partId + ")");
return;
}
@@ -623,10 +627,7 @@
public void SetupAttachNodes(Dictionary<Part, PartSim> partSimLookup, LogMsg log)
{
- if (log != null)
- {
- log.buf.AppendLine("SetupAttachNodes for " + name + ":" + partId + "");
- }
+ if (log != null) log.buf.AppendLine("SetupAttachNodes for " + name + ":" + partId + "");
attachNodes.Clear();
@@ -634,29 +635,20 @@
{
AttachNode attachNode = part.attachNodes[i];
- if (log != null)
- {
- log.buf.AppendLine("AttachNode " + attachNode.id + " = " + (attachNode.attachedPart != null ? attachNode.attachedPart.partInfo.name : "null"));
- }
+ if (log != null) log.buf.AppendLine("AttachNode " + attachNode.id + " = " + (attachNode.attachedPart != null ? attachNode.attachedPart.partInfo.name : "null"));
if (attachNode.attachedPart != null && attachNode.id != "Strut")
{
PartSim attachedSim;
if (partSimLookup.TryGetValue(attachNode.attachedPart, out attachedSim))
{
- if (log != null)
- {
- log.buf.AppendLine("Adding attached node " + attachedSim.name + ":" + attachedSim.partId + "");
- }
+ if (log != null) log.buf.AppendLine("Adding attached node " + attachedSim.name + ":" + attachedSim.partId + "");
attachNodes.Add(AttachNodeSim.New(attachedSim, attachNode.id, attachNode.nodeType));
}
else
{
- if (log != null)
- {
- log.buf.AppendLine("No PartSim for attached part (" + attachNode.attachedPart.partInfo.name + ")");
- }
+ if (log != null) log.buf.AppendLine("No PartSim for attached part (" + attachNode.attachedPart.partInfo.name + ")");
}
}
}
@@ -670,38 +662,15 @@
PartSim targetSim;
if (partSimLookup.TryGetValue(p, out targetSim))
{
- if (log != null)
- {
- log.buf.AppendLine("Fuel target: " + targetSim.name + ":" + targetSim.partId);
- }
+ if (log != null) log.buf.AppendLine("Fuel target: " + targetSim.name + ":" + targetSim.partId);
fuelTargets.Add(targetSim);
}
else
{
- if (log != null)
- {
- log.buf.AppendLine("No PartSim for fuel target (" + p.name + ")");
- }
- }
- }
- }
-
- if (isNoPhysics)
- {
- if (log != null)
- log.buf.AppendLine("Moving NoPhysics part mass of " + this.baseMass + " to parent part");
-
- // Go up the parent chain until we find a part that is physically significant or we reach the root
- PartSim MassParent = parent;
- while (MassParent.isNoPhysics && (MassParent.parent != null))
- MassParent = MassParent.parent;
-
- // Apply this part's mass to the part we have found
- MassParent.baseMass += this.baseMass;
-
- // And zero out this part's mass
- this.baseMass = 0;
+ if (log != null) log.buf.AppendLine("No PartSim for fuel target (" + p.name + ")");
+ }
+ }
}
}
@@ -712,13 +681,11 @@
parent = null;
if (partSimLookup.TryGetValue(part.parent, out parent))
{
- if (log != null)
- log.buf.AppendLine("Parent part is " + parent.name + ":" + parent.partId);
+ if (log != null) log.buf.AppendLine("Parent part is " + parent.name + ":" + parent.partId);
}
else
{
- if (log != null)
- log.buf.AppendLine("No PartSim for parent part (" + part.parent.partInfo.name + ")");
+ if (log != null) log.buf.AppendLine("No PartSim for parent part (" + part.parent.partInfo.name + ")");
}
}
}
@@ -756,43 +723,27 @@
{
Transform trans = thrustTransforms[i];
- if (log != null)
- {
- log.buf.AppendFormat("Transform = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", trans.forward.x, trans.forward.y, trans.forward.z, trans.forward.magnitude);
- }
+ if (log != null) log.buf.AppendFormat("Transform = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", trans.forward.x, trans.forward.y, trans.forward.z, trans.forward.magnitude);
thrustvec -= trans.forward;
}
- if (log != null)
- {
- log.buf.AppendFormat("ThrustVec = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
- }
+ if (log != null) log.buf.AppendFormat("ThrustVec = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
thrustvec.Normalize();
- if (log != null)
- {
- log.buf.AppendFormat("ThrustVecN = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
- }
+ if (log != null) log.buf.AppendFormat("ThrustVecN = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
return thrustvec;
}
private int DecoupledInStage(Part thePart, int stage = -1)
{
- if (IsDecoupler(thePart))
- {
- if (thePart.inverseStage > stage)
- {
- stage = thePart.inverseStage;
- }
- }
+ if (IsDecoupler(thePart) && thePart.inverseStage > stage)
+ stage = thePart.inverseStage;
if (thePart.parent != null)
- {
stage = DecoupledInStage(thePart.parent, stage);
- }
return stage;
}
--- a/KerbalEngineer/VesselSimulator/ResourceContainer.cs
+++ b/KerbalEngineer/VesselSimulator/ResourceContainer.cs
@@ -150,6 +150,12 @@
return density == 0d ? 0d : this.resources[type] * density;
}
+ public double GetResourceCost(int type)
+ {
+ double unitCost = GetResourceUnitCost(type);
+ return unitCost == 0d ? 0d : this.resources[type] * unitCost;
+ }
+
public static ResourceFlowMode GetResourceFlowMode(int type)
{
return PartResourceLibrary.Instance.GetDefinition(type).resourceFlowMode;
@@ -157,7 +163,7 @@
public static ResourceTransferMode GetResourceTransferMode(int type)
{
- return PartResourceLibrary.Instance.GetDefinition(type).resourceTransferMode;;
+ return PartResourceLibrary.Instance.GetDefinition(type).resourceTransferMode;
}
public static float GetResourceDensity(int type)
@@ -169,5 +175,10 @@
{
return PartResourceLibrary.Instance.GetDefinition(type).name;
}
+
+ public static double GetResourceUnitCost(int type)
+ {
+ return PartResourceLibrary.Instance.GetDefinition(type).unitCost;
+ }
}
}
--- a/KerbalEngineer/VesselSimulator/Simulation.cs
+++ b/KerbalEngineer/VesselSimulator/Simulation.cs
@@ -119,7 +119,7 @@
for (int i = 0; i < allParts.Count; ++i)
{
PartSim partSim = allParts[i];
- vectorAverager.Add(partSim.centerOfMass, partSim.GetMass(currentStage));
+ vectorAverager.Add(partSim.centerOfMass, partSim.GetMass(currentStage, true));
}
return vectorAverager.Get();
@@ -139,6 +139,7 @@
log.buf.AppendLine("PrepareSimulation started");
dumpTree = true;
}
+ this._timer.Reset();
this._timer.Start();
// Store the parameters in members for ease of access in other functions
@@ -299,6 +300,7 @@
MonoBehaviour.print("RunSimulation started");
}
+ this._timer.Reset();
this._timer.Start();
LogMsg log = null;
@@ -382,13 +384,14 @@
// Create the array of stages that will be returned
Stage[] stages = new Stage[this.currentStage + 1];
+ int startStage = currentStage;
+
// Loop through the stages
while (this.currentStage >= 0)
{
if (log != null)
{
log.buf.AppendLine("Simulating stage " + this.currentStage);
- log.buf.AppendLine("ShipMass = " + this.ShipMass);
log.Flush();
this._timer.Reset();
this._timer.Start();
@@ -397,13 +400,18 @@
// Update active engines and resource drains
this.UpdateResourceDrains();
+ // Update the masses of the parts to correctly handle "no physics" parts
+ this.stageStartMass = this.UpdatePartMasses();
+
+ if (log != null)
+ this.allParts[0].DumpPartToBuffer(log.buf, "", this.allParts);
+
// Create the Stage object for this stage
Stage stage = new Stage();
this.stageTime = 0d;
this.vecStageDeltaV = Vector3.zero;
- this.stageStartMass = this.ShipMass;
this.stageStartCom = this.ShipCom;
this.stepStartMass = this.stageStartMass;
@@ -413,11 +421,11 @@
// Store various things in the Stage object
stage.thrust = this.totalStageThrust;
- //MonoBehaviour.print("stage.thrust = " + stage.thrust);
+ if (log != null) log.buf.AppendLine("stage.thrust = " + stage.thrust);
stage.thrustToWeight = this.totalStageThrust / (this.stageStartMass * this.gravity);
stage.maxThrustToWeight = stage.thrustToWeight;
- //MonoBehaviour.print("StageMass = " + stageStartMass);
- //MonoBehaviour.print("Initial maxTWR = " + stage.maxThrustToWeight);
+ if (log != null) log.buf.AppendLine("StageMass = " + stageStartMass);
+ if (log != null) log.buf.AppendLine("Initial maxTWR = " + stage.maxThrustToWeight);
stage.actualThrust = this.totalStageActualThrust;
stage.actualThrustToWeight = this.totalStageActualThrust / (this.stageStartMass * this.gravity);
@@ -442,22 +450,31 @@
stage.thrustOffsetAngle = Math.Asin(sinThrustOffsetAngle) * 180 / Math.PI;
- // Calculate the cost and mass of this stage and add all engines and tanks that are decoupled
- // in the next stage to the dontStageParts list
+ // Calculate the total cost of the vessel at this point
+ stage.totalCost = 0d;
for (int i = 0; i < allParts.Count; ++i)
{
- PartSim partSim = allParts[i];
-
- if (partSim.decoupledInStage == this.currentStage - 1)
- {
- stage.cost += partSim.cost;
- stage.mass += partSim.GetStartMass();
- }
-
- if (partSim.hasVessel == false && partSim.isFairing && partSim.inverseStage == currentStage)
- {
- stage.mass += partSim.moduleMass;
- }
+ if (this.currentStage > allParts[i].decoupledInStage)
+ stage.totalCost += allParts[i].GetCost(currentStage);
+ }
+
+ // The total mass is simply the mass at the start of the stage
+ stage.totalMass = this.stageStartMass;
+
+ // If we have done a previous stage
+ if (currentStage < startStage)
+ {
+ // Calculate what the previous stage's mass and cost were by subtraction
+ Stage prev = stages[currentStage + 1];
+ prev.cost = prev.totalCost - stage.totalCost;
+ prev.mass = prev.totalMass - stage.totalMass;
+ }
+
+ // The above code will never run for the last stage so set those directly
+ if (currentStage == 0)
+ {
+ stage.cost = stage.totalCost;
+ stage.mass = stage.totalMass;
}
this.dontStageParts = dontStagePartsLists[this.currentStage];
@@ -620,8 +637,6 @@
// For each stage we total up the cost, mass, deltaV and time for this stage and all the stages above
for (int j = i; j >= 0; j--)
{
- stages[i].totalCost += stages[j].cost;
- stages[i].totalMass += stages[j].mass;
stages[i].totalDeltaV += stages[j].deltaV;
stages[i].totalTime += stages[j].time;
stages[i].partCount = i > 0 ? stages[i].totalPartCount - stages[i - 1].totalPartCount : stages[i].totalPartCount;
@@ -648,6 +663,45 @@
FreePooledObject();
return stages;
+ }
+
+ public double UpdatePartMasses()
+ {
+ for (int i = 0; i < this.allParts.Count; i++)
+ {
+ this.allParts[i].baseMass = this.allParts[i].realMass;
+ this.allParts[i].baseMassForCoM = this.allParts[i].realMass;
+ }
+
+ 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;
+ }
+ }
+ }
+ }
+
+ double totalMass = 0d;
+ for (int i = 0; i < this.allParts.Count; i++)
+ {
+ totalMass += this.allParts[i].startMass = this.allParts[i].GetMass(currentStage);
+ }
+
+ return totalMass;
}
// Make sure we free them all, even if they should all be free already at this point
Binary files a/Output/KerbalEngineer/KerbalEngineer.dll and b/Output/KerbalEngineer/KerbalEngineer.dll differ