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
Binary files a/Assets/CurseLogo.png and b/Assets/CurseLogo.png differ
Binary files a/Assets/CurseLogo.psd and b/Assets/CurseLogo.psd differ
--- a/Documents/CHANGES.txt
+++ b/Documents/CHANGES.txt
@@ -1,12 +1,174 @@
-1.0.11.0
+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.
+
+1.0.16.5, 02-05-2015
+ Fixed: Delta-V not being correctly calculated.
+ Changed: Editor locking now uses the InputLockManager.
+
+1.0.16.4, 01-05-2015
+ Fixed: Physically insignificant part mass is now accounted for.
+ Changed: Module mass accounted for as it now makes its way onto the launch pad (e.g. fairings).
+
+ Various optimisations:
+ Object pooling.
+ Removed LINQ expressions.
+ Converted foreach to for loops.
+
+1.0.16.3, 27-04-2015
+ Fixed issue with the toolbar icons not being created.
+ Removed superfluous 'm/s' on the mach slider in the build engineer.
+
+1.0.16.2, 27-04-2015
+ Changed the atmospheric slider on the build engineer to default to 0km when changing bodies.
+
+1.0.16.1, 26-04-2015, KSP Build #828
+ Merged Sarbian's mach adjustments.
+ Fixed bugs relating to thrust and atmosphere/velocity curves.
+ Changed the atmospheric slider on the Build Engineer to work based on altitude.
+ Changed the atmospheric slider to clamp to the maximum altitude for the selected body.
+ Changed the velocity slider to clamp to the maximum usable mach value for the current vessel.
+
+1.0.16.0, 25-04-2015, KSP Build #821
+ Fixed errors relating to KSP 1.0 update.
+ Fixed fuel simulation to account for new thrust system.
+ Fixed atmospheric engines to use the new velocity curve.
+ Fixed atmospheric readouts to work with the new atmospheric model.
+
+1.0.15.2, 13-02-2015
+ Padishar's Fixes:
+ Fixed: Calculation of per-stage resource mass.
+
+1.0.15.1, 13-02-2015
+ Rebuild
+
+1.0.15.0, 08-02-2015
+ Padishar's Fixes:
+ Added: Support KIDS ISP thrust correction.
+ Fixed: Log spam for stage priority mode.
+ Fixed: Locked tanks preventing simulation from staging.
+ Fixed: No flow and all vessel modes to respect flow states.
+
+1.0.14.1, 28-12-2014
+ Fixed: Missing texture on the ER-7500 model.
+
+1.0.14.0, 28-12-2014
+ Added: Career mode that limits the Flight Engineer by:
+ - Requiring an Engineer Kerbal of any level, or placement of an Engineer Chip or ER-7500 part.
+ - Tracking station level 3 enables Flight Engineer everywhere.
+
+ Added: New readouts to the orbital category:
+ - Mean Anomaly at Epoc
+
+ Added: New readouts to the miscellaneous category:
+ - System Time
+
+ Added: Editor Overlay Tab's X position is now changable in the BuildOverlay.xml settings file.
+ Changed: Editor Overlay Tabs start position moved over as to not overlap the parts menu.
+ Fixed: Bug where STAGE_PRIORITY_FLOW resources would not be corrently disabled/enabled.
+ Fixed: Issue with the formatting large Mass and Cost values.
+ Fixed: Error when loading the Engineer7500 part model.
+
+1.0.13.1, 16-12-2014
+ Fixed: Issue with manoeuvre node readouts and low tier tracking station.
+
+1.0.13.0, 16-12-2014
+ Updated for KSP version 0.90
+
+ Added: New readouts to the vessel category:
+ - Heading Rate
+ - Pitch Rate
+ - Roll Rate
+
+ Changed: Simulation to look for fuel lines that use CModuleFuelLine module.
+ Fixed: Editor Overlay now loads the saved visibility value properly.
+ Fixed: Altitude (Terrain) will no longer give a reading below sea level.
+ Fixed: Suicide burn now uses radar altitude that clamps to sea level.
+
+1.0.12.0, 01-12-2014
+ Added: Setting in Build Engineer to enable/disable vectored thrust calculations.
+ Added: Thrust torque field in Build Engineer (courtesy of mic_e).
+ Added: New readouts to the vessel category:
+ - Thrust Offset Angle (courtesy of mic_e)
+ - Thrust Torque (courtesy of mic_e)
+ - Part Count: stage/total
+ - Heading
+ - Pitch
+ - Roll
+
+ Added: New readouts to the surface category:
+ - Situation
+
+ Added: New readouts to the miscellaneous category:
+ - Vectored Thrust Toggle
+
+ Fixed: The category selection within the section editors now do not always reset back to 'Orbital'.
+ Fixed: Issue where the vessel simulation can sometimes permanently freeze.
+ Fixed: Issue where the vessel simulation would not show updates when the delay was set lower than the frame rate.
+
+1.0.11.3, 11-11-2014
+ Changed: Gravity measurements for Isp to 9.82.
+
+1.0.11.2, 10-11-2014
+ Changed: Gravity measurements for Isp calculations from 9.81 to 9.8066 for accuracy.
+ Changed: Manoeuvre node burn times are now more accurate.
+ Fixed: Bug in the manoeuvre node burn time calculations where it was not averaging acceleration correctly.
+
+1.0.11.1, 07-11-2014
+ Changed: Build Engineer now shows stage part count as well as total.
+ Changed: Build Overlay Vessel tab data:
+ DeltaV: stage / total
+ Mass: stage / total
+ TWR: start (max) <- shows for bottom stage only.
+ Parts: stage / total
+
+ Fixed: Issue with the vessel tab vanishing from the editor.
+
+1.0.11.0, 06-11-2014
Added: New readouts to the orbital category:
- Current SOI
+ - Manoeuvre Node DeltaV (Prograde)
+ - Manoeuvre Node DeltaV (Normal)
+ - Manoeuvre Node DeltaV (Radial)
+ - Manoeuvre Node DeltaV (Total)
+ - Manoeuvre Node Burn Time
+ - Manoeuvre Node Half Burn Time
+ - Manoeuvre Node Angle to Prograde
+ - Manoeuvre Node Angle to Retrograde
+ - Time to Manoeuvre Node
+ - Time to Manoeuvre Burn
+
+ Added: Readout help strings by ClassyJakey.
+
+ Fixed: Issue with separators in HUDs.
+ Fixed: Issue with HUDs with backgrounds that have no displayed lines.
Padishar's Fixes:
Fixed: Issue with multicouplers when attached to parent by bottom node.
Fixed: Issue with sepratrons on solid rocket boosters.
-1.0.10.0
+1.0.10.0, 19-10-2014
UPDATE NOTICE: If you are updating from a previous version of Kerbal Engineer 1.0, please
delete the 'Settings/SectionLibrary.xml' file, or remove the old install first. This will
reset the Flight Engineer sections to their default values and enable the new HUD functionality.
@@ -25,7 +187,7 @@
Fixed: Bug in the phase angle calculations.
Fixed: Bug where the Build Engineer would stay locked after hiding with the shortcut key.
-1.0.9.3
+1.0.9.3, 08-10-2014
Added: Title of the build engineer in compact mode now shows if you are using atmospheric data.
Added: New readout to the surface category:
- Vertical Acceleration
@@ -35,16 +197,16 @@
Changed: Atmospheric settings (pressure/velocity) in the editor condensed onto a single line.
Fixed: Bug where the overlays in the editor would stay open outside of parts screen.
-1.0.9.2
+1.0.9.2, 07-10-2014
Updated for KSP v0.25.0
Changed: Prettyfied Latitude and Longitude readouts.
Changed: ModuleLandingGear now uses the physical significance flag.
Changed: Updated MiniAVC to 1.0.2.4.
-1.0.9.1
+1.0.9.1, 17-09-2014
Fixed: Part size bug caused by TweakScale's cost calculator.
-1.0.9.0
+1.0.9.0, 15-09-2014
Added: Build Engineer now also implements the '\' backslash show/hide shortcut.
Added: New readouts to the vessel category:
- Current Stage DeltaV
@@ -62,10 +224,10 @@
Fixed: Cost calculation now works with mods implementing IPartCostModifier.
-1.0.8.1
+1.0.8.1, 06-09-2014
Fixed: Bug which caused rendezvous readouts to freeze the game or show all zeros.
-1.0.8.0
+1.0.8.0, 06-09-2014
Added: New readouts to the vessel category:
- Intake Air (Usage)
@@ -76,14 +238,14 @@
Fixed: An issue where deltaV would not be calculated whilst flying.
Fixed: NullRef whilst loading the in flight Action Menu.
-1.0.7.1
+1.0.7.1, 02-09-2014
Changed: Reversed Intake Air readout from 'S/D' to 'D/S' for easier reading.
Changed: Increased Intake Air readout precision to 4 decimal places.
Fixed: Issue where Intake Air supply was not representative of total supply.
Fixed: Bug where actual thrust does not reset to zero on deactivated engines.
Fixed: Thrust now scales with velocity for atmospheric engines. (Padishar's fix)
-1.0.7.0
+1.0.7.0, 01-09-2014
Added: Part count information to the Build Engineer.
Added: Reset button to the G-Force readout.
Added: Preset system to the Flight Engineer.
@@ -119,7 +281,7 @@
Fixed: Issues with large value wrap around in the Flight Engineer.
Fixed: Bug in the phase angle calculation.
-1.0.6.0
+1.0.6.0, 23-08-2014
Added: Time and Angle to equatorial ascending/descending nodes in the orbital display.
Added: Time and Angle to relative ascending/descending nodes in the rendezvous display.
Added: Overlay tooltip information delay adjustment slider to the Build Engineer settings.
@@ -129,7 +291,7 @@
Changed: Licensing and readme structures are now more verbose to satisfy the new add-on rules.
Fixed: Updated MiniAVC to v1.0.2.1 (fixes remote check bug as well as other minor bugs).
-1.0.5.0
+1.0.5.0, 13-08-2014
Added: Acceleration readout to the Vessel category (current / maximum).
Added: Category library system for the Flight Engineer readouts.
Added: Drop-down category selection to better support the new system.
@@ -139,7 +301,7 @@
Fixed: Flight Engineer toolbar menu now hides when hiding the GUI with F2.
Fixed: Flight Engineer toolbar button now disables when in module mode and no engineer is running.
-1.0.4.0
+1.0.4.0, 12-08-2014
Added: Better stock toolbar support in the flight engineer.
Added: Dynamically generated celestial body library for supporting add-ons that modify the star system.
Changed: Reference bodies are now listed with a nestable menu system.
@@ -149,7 +311,7 @@
Changed: Increased Semi-major/minor axis precision to 3 decimal places.
Fixed: Impact altitude was mistakenly formatted as an angle, it is now formatted correctly as a distance.
-1.0.3.0
+1.0.3.0, 30-07-2014
Added: Integrated KSP-AVC support with MiniAVC.
Added: Setting to change the simulation delay in the Build Engineer.
Added: Setting to enable and disable the build overlay system.
@@ -160,7 +322,7 @@
Fixed: Flickering in VAB and Vessel display.
Fixed: Bug saving the GUI display size.
-1.0.2.0
+1.0.2.0, 27-07-2014
Added: Separator readout module under Misc in the Flight Engineer.
Added: Adjustable GUI display size.
Added: Display size can be adjusted in the Build Engineer settings.
@@ -170,7 +332,7 @@
Fixed: Engines that have a minimum thrust are now calculated properly. (Thanks to nosscire.)
Fixed: Compact collapse mode is now saved in the Build Engineer.
-1.0.1.0
+1.0.1.0, 26-07-2014
Added: Part-less Flight Engineer.
Added: Ability to collapse the Build Engineer into compact mode from left or right.
Added: Settings in Build Engineer for compact collapse mode and partless/module Flight Engineer.
@@ -183,10 +345,10 @@
Changed: ER7500 part has no physical significance.
Fixed: ActionMenu and DisplayStack destruction bug.
-1.0.0.1
+1.0.0.1, 24-07-2014
Added: Stock toolbar support in the Flight Engineer.
Changed: Orbital Period has higher precision.
Fixed: Various NullRefs in editor window and overlay.
-1.0.0.0
+1.0.0.0, 24-07-2014
Initial release for public testing.
--- a/KerbalEngineer/CelestialBodies.cs
+++ b/KerbalEngineer/CelestialBodies.cs
@@ -17,16 +17,12 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-#endregion
-
namespace KerbalEngineer
{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+
/*
*
* With thanks to Nathaniel R. Lewis (aka. Teknoman117) (linux.robotdude@gmail.com) for working out
@@ -36,8 +32,6 @@
public static class CelestialBodies
{
- #region Constructors
-
static CelestialBodies()
{
try
@@ -55,16 +49,8 @@
}
}
- #endregion
-
- #region Properties
-
public static BodyInfo SelectedBody { get; private set; }
public static BodyInfo SystemBody { get; private set; }
-
- #endregion
-
- #region Public Methods
/// <summary>
/// Gets a body given a supplied body name.
@@ -89,7 +75,7 @@
{
try
{
- var body = GetBodyInfo(bodyName);
+ BodyInfo body = GetBodyInfo(bodyName);
if (body != null)
{
if (SelectedBody != null)
@@ -108,33 +94,26 @@
return false;
}
- #endregion
-
- #region Nested type: BodyInfo
-
public class BodyInfo
{
- #region Constructors
-
public BodyInfo(CelestialBody body, BodyInfo parent = null)
{
try
{
// Set the body information.
- this.CelestialBody = body;
- this.Name = body.bodyName;
- this.Gravity = 9.81 * body.GeeASL;
- this.Atmosphere = body.atmosphere ? 101.325 * body.atmosphereMultiplier : 0;
- this.Parent = parent;
+ CelestialBody = body;
+ Name = body.bodyName;
+ Gravity = 9.81 * body.GeeASL;
+ Parent = parent;
// Set orbiting bodies information.
- this.Children = new List<BodyInfo>();
- foreach (var orbitingBody in body.orbitingBodies)
- {
- this.Children.Add(new BodyInfo(orbitingBody, this));
- }
-
- this.SelectedDepth = 0;
+ Children = new List<BodyInfo>();
+ foreach (CelestialBody orbitingBody in body.orbitingBodies)
+ {
+ Children.Add(new BodyInfo(orbitingBody, this));
+ }
+
+ SelectedDepth = 0;
}
catch (Exception ex)
{
@@ -142,37 +121,28 @@
}
}
- #endregion
-
- #region Properties
-
+ public CelestialBody CelestialBody { get; private set; }
+ public List<BodyInfo> Children { get; private set; }
+ public double Gravity { get; private set; }
public string Name { get; private set; }
- public double Gravity { get; private set; }
- public double Atmosphere { get; private set; }
public BodyInfo Parent { get; private set; }
- public List<BodyInfo> Children { get; private set; }
- public CelestialBody CelestialBody { get; private set; }
public bool Selected { get; private set; }
public int SelectedDepth { get; private set; }
- #endregion
-
- #region Public Methods
-
public BodyInfo GetBodyInfo(string bodyName)
{
try
{
// This is the searched body.
- if (String.Equals(this.Name, bodyName, StringComparison.CurrentCultureIgnoreCase))
+ if (String.Equals(Name, bodyName, StringComparison.CurrentCultureIgnoreCase))
{
return this;
}
// Check to see if any of this bodies children are the searched body.
- foreach (var child in this.Children)
- {
- var body = child.GetBodyInfo(bodyName);
+ foreach (BodyInfo child in Children)
+ {
+ BodyInfo body = child.GetBodyInfo(bodyName);
if (body != null)
{
return body;
@@ -188,33 +158,44 @@
return null;
}
+ public double GetDensity(double altitude)
+ {
+ return CelestialBody.GetDensity(GetPressure(altitude), GetTemperature(altitude));
+ }
+
+ public double GetPressure(double altitude)
+ {
+ return CelestialBody.GetPressure(altitude);
+ }
+
+ public double GetTemperature(double altitude)
+ {
+ return CelestialBody.GetTemperature(altitude);
+ }
+
+ public double GetAtmospheres(double altitude)
+ {
+ return GetPressure(altitude) * PhysicsGlobals.KpaToAtmospheres;
+ }
+
public void SetSelected(bool state, int depth = 0)
{
- this.Selected = state;
- this.SelectedDepth = depth;
- if (this.Parent != null)
- {
- this.Parent.SetSelected(state, depth + 1);
- }
- }
-
- #endregion
-
- #region Debugging
+ Selected = state;
+ SelectedDepth = depth;
+ if (Parent != null)
+ {
+ Parent.SetSelected(state, depth + 1);
+ }
+ }
public override string ToString()
{
- var log = "\n" + this.Name +
- "\n\tGravity: " + this.Gravity +
- "\n\tAtmosphere: " + this.Atmosphere +
- "\n\tSelected: " + this.Selected;
-
- return this.Children.Aggregate(log, (current, child) => current + "\n" + child);
- }
-
- #endregion
- }
-
- #endregion
+ string log = "\n" + Name +
+ "\n\tGravity: " + Gravity +
+ "\n\tSelected: " + Selected;
+
+ return Children.Aggregate(log, (current, child) => current + "\n" + child);
+ }
+ }
}
}
--- a/KerbalEngineer/Editor/BuildAdvanced.cs
+++ b/KerbalEngineer/Editor/BuildAdvanced.cs
@@ -17,33 +17,29 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using System;
-using System.Linq;
-
-using KerbalEngineer.Extensions;
-using KerbalEngineer.Flight;
-using KerbalEngineer.Helpers;
-using KerbalEngineer.Settings;
-using KerbalEngineer.UIControls;
-using KerbalEngineer.VesselSimulator;
-
-using UnityEngine;
-
-#endregion
-
namespace KerbalEngineer.Editor
{
+ #region Using Directives
+ using System;
+ using Extensions;
+ using Flight;
+ using Helpers;
+ using Settings;
+ using UIControls;
+ using UnityEngine;
+ using VesselSimulator;
+
+ #endregion
+
[KSPAddon(KSPAddon.Startup.EditorAny, false)]
public class BuildAdvanced : MonoBehaviour
{
#region Fields
+ public static float Altitude = 0.0f;
private GUIStyle areaSettingStyle;
private GUIStyle areaStyle;
- private float atmosphericPercentage = 1.0f;
- private float atmosphericVelocity;
+ private float atmosphericMach;
private GUIStyle bodiesButtonActiveStyle;
private GUIStyle bodiesButtonStyle;
private DropDown bodiesList;
@@ -56,6 +52,7 @@
private bool hasChanged;
private GUIStyle infoStyle;
private bool isEditorLocked;
+ private float maxMach;
private int numberOfStages;
private Rect position = new Rect(265.0f, 45.0f, 0, 0);
private GUIStyle settingAtmoStyle;
@@ -67,11 +64,9 @@
private GUIStyle titleStyle;
private bool visible = true;
private GUIStyle windowStyle;
-
#endregion
#region Properties
-
/// <summary>
/// Gets the current instance if started or returns null.
/// </summary>
@@ -82,8 +77,14 @@
/// </summary>
public bool CompactMode
{
- get { return this.compactMode; }
- set { this.compactMode = value; }
+ get
+ {
+ return compactMode;
+ }
+ set
+ {
+ compactMode = value;
+ }
}
/// <summary>
@@ -91,8 +92,14 @@
/// </summary>
public bool ShowAllStages
{
- get { return this.showAllStages; }
- set { this.showAllStages = value; }
+ get
+ {
+ return showAllStages;
+ }
+ set
+ {
+ showAllStages = value;
+ }
}
/// <summary>
@@ -100,8 +107,14 @@
/// </summary>
public bool ShowAtmosphericDetails
{
- get { return this.showAtmosphericDetails; }
- set { this.showAtmosphericDetails = value; }
+ get
+ {
+ return showAtmosphericDetails;
+ }
+ set
+ {
+ showAtmosphericDetails = value;
+ }
}
/// <summary>
@@ -109,8 +122,14 @@
/// </summary>
public bool ShowSettings
{
- get { return this.showSettings; }
- set { this.showSettings = value; }
+ get
+ {
+ return showSettings;
+ }
+ set
+ {
+ showSettings = value;
+ }
}
/// <summary>
@@ -118,26 +137,40 @@
/// </summary>
public bool Visible
{
- get { return this.visible; }
- set { this.visible = value; }
- }
-
+ get
+ {
+ return visible;
+ }
+ set
+ {
+ visible = value;
+ }
+ }
#endregion
- #region Methods: protected
+ #region Methods
+ private static Rect compactModeRect = new Rect(0.0f, 5.0f, 0.0f, 20.0f);
+ private static Stage stage;
+ private static int stagesCount;
+ private static int stagesLength;
+ private static string title;
protected void Awake()
{
try
{
Instance = this;
- this.bodiesList = this.gameObject.AddComponent<DropDown>();
- this.bodiesList.DrawCallback = this.DrawBodiesList;
- this.Load();
+ bodiesList = gameObject.AddComponent<DropDown>();
+ bodiesList.DrawCallback = DrawBodiesList;
+ Load();
+
+ SimManager.UpdateModSettings();
+ SimManager.OnReady -= GetStageInfo;
+ SimManager.OnReady += GetStageInfo;
}
catch (Exception ex)
{
- Logger.Exception(ex);
+ Logger.Exception(ex, "BuildAdvanced.Awake()");
}
}
@@ -148,22 +181,22 @@
{
try
{
- var handler = new SettingHandler();
- handler.Set("visible", this.visible);
- handler.Set("windowPositionX", this.position.x);
- handler.Set("windowPositionY", this.position.y);
- handler.Set("compactMode", this.compactMode);
- handler.Set("compactCollapseRight", this.compactCollapseRight);
- handler.Set("showAllStages", this.showAllStages);
- handler.Set("showAtmosphericDetails", this.showAtmosphericDetails);
- handler.Set("showSettings", this.showSettings);
+ SettingHandler handler = new SettingHandler();
+ handler.Set("visible", visible);
+ handler.Set("windowPositionX", position.x);
+ handler.Set("windowPositionY", position.y);
+ handler.Set("compactMode", compactMode);
+ handler.Set("compactCollapseRight", compactCollapseRight);
+ handler.Set("showAllStages", showAllStages);
+ handler.Set("showAtmosphericDetails", showAtmosphericDetails);
+ handler.Set("showSettings", showSettings);
handler.Set("selectedBodyName", CelestialBodies.SelectedBody.Name);
handler.Save("BuildAdvanced.xml");
- GuiDisplaySize.OnSizeChanged -= this.OnSizeChanged;
+ GuiDisplaySize.OnSizeChanged -= OnSizeChanged;
}
catch (Exception ex)
{
- Logger.Exception(ex);
+ Logger.Exception(ex, "BuildAdvanced.OnDestroy()");
}
}
@@ -171,56 +204,65 @@
{
try
{
- if (!this.visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0 || EditorLogic.fetch.editorScreen != EditorLogic.EditorScreen.Parts)
+ if (!visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0 || EditorLogic.fetch.editorScreen != EditorScreen.Parts)
{
return;
}
- if (SimManager.ResultsReady())
- {
- this.stages = SimManager.Stages;
- }
-
- SimManager.RequestSimulation();
-
- if (this.stages == null)
+ if (stages == null)
{
return;
}
// Change the window title based on whether in compact mode or not.
- var title = !this.compactMode ? "KERBAL ENGINEER REDUX " + EngineerGlobals.AssemblyVersion : "K.E.R. " + EngineerGlobals.AssemblyVersion + (this.showAtmosphericDetails ? " (ATMOS.)" : String.Empty);
+ title = !compactMode ? "KERBAL ENGINEER REDUX " + EngineerGlobals.AssemblyVersion : "K.E.R. " + EngineerGlobals.AssemblyVersion;
// Reset the window size when the staging or something else has changed.
- var stageCount = this.stages.Count(stage => this.showAllStages || stage.deltaV > 0);
- if (this.hasChanged || stageCount != this.numberOfStages)
- {
- this.hasChanged = false;
- this.numberOfStages = stageCount;
-
- this.position.width = 0;
- this.position.height = 0;
+ stagesLength = stages.Length;
+ if (showAllStages)
+ {
+ stagesCount = stagesLength;
+ }
+ if (showAllStages == false)
+ {
+ stagesCount = 0;
+ for (int i = 0; i < stagesLength; ++i)
+ {
+ if (stages[i].deltaV > 0.0f)
+ {
+ stagesCount = stagesCount + 1;
+ }
+ }
+ }
+
+ if (hasChanged || stagesCount != numberOfStages)
+ {
+ hasChanged = false;
+ numberOfStages = stagesCount;
+
+ position.width = 0;
+ position.height = 0;
}
GUI.skin = null;
- this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, title, this.windowStyle).ClampToScreen();
-
- if (this.compactCheck > 0 && this.compactCollapseRight)
- {
- this.position.x = this.compactRight - this.position.width;
- this.compactCheck--;
- }
- else if (this.compactCheck > 0)
- {
- this.compactCheck = 0;
+ position = GUILayout.Window(GetInstanceID(), position, Window, title, windowStyle).ClampToScreen();
+
+ if (compactCheck > 0 && compactCollapseRight)
+ {
+ position.x = compactRight - position.width;
+ compactCheck--;
+ }
+ else if (compactCheck > 0)
+ {
+ compactCheck = 0;
}
// Check editor lock to manage click-through.
- this.CheckEditorLock();
+ CheckEditorLock();
}
catch (Exception ex)
{
- Logger.Exception(ex);
+ Logger.Exception(ex, "BuildAdvanced.OnGUI()");
}
}
@@ -228,12 +270,12 @@
{
try
{
- this.InitialiseStyles();
- GuiDisplaySize.OnSizeChanged += this.OnSizeChanged;
+ InitialiseStyles();
+ GuiDisplaySize.OnSizeChanged += OnSizeChanged;
}
catch (Exception ex)
{
- Logger.Exception(ex);
+ Logger.Exception(ex, "BuildAdvanced.Start()");
}
}
@@ -243,56 +285,54 @@
{
if (Input.GetKeyDown(KeyBinder.EditorShowHide))
{
- this.visible = !this.visible;
- if (!this.visible)
+ visible = !visible;
+ if (!visible)
{
- this.EditorLock(false);
+ EditorLock(false);
}
}
- if (!this.visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0)
- {
- this.bodiesList.enabled = false;
+ if (!visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0)
+ {
+ bodiesList.enabled = false;
return;
}
// Configure the simulation parameters based on the selected reference body.
SimManager.Gravity = CelestialBodies.SelectedBody.Gravity;
- if (this.showAtmosphericDetails)
- {
- SimManager.Atmosphere = CelestialBodies.SelectedBody.Atmosphere * 0.01d * this.atmosphericPercentage;
+ if (showAtmosphericDetails)
+ {
+ SimManager.Atmosphere = CelestialBodies.SelectedBody.GetAtmospheres(Altitude);
}
else
{
SimManager.Atmosphere = 0;
}
- SimManager.Velocity = this.atmosphericVelocity;
+ SimManager.Mach = atmosphericMach;
+
+ SimManager.RequestSimulation();
SimManager.TryStartSimulation();
}
catch (Exception ex)
{
- Logger.Exception(ex, "BuildAdvanced->Update");
- }
- }
-
- #endregion
-
- #region Methods: private
+ Logger.Exception(ex, "BuildAdvanced.Update()");
+ }
+ }
/// <summary>
/// Checks whether the editor should be locked to stop click-through.
/// </summary>
private void CheckEditorLock()
{
- if ((this.position.MouseIsOver() || this.bodiesList.Position.MouseIsOver()) && !this.isEditorLocked)
- {
- this.EditorLock(true);
- }
- else if (!this.position.MouseIsOver() && !this.bodiesList.Position.MouseIsOver() && this.isEditorLocked)
- {
- this.EditorLock(false);
+ if ((position.MouseIsOver() || bodiesList.Position.MouseIsOver()) && !isEditorLocked)
+ {
+ EditorLock(true);
+ }
+ else if (!position.MouseIsOver() && !bodiesList.Position.MouseIsOver() && isEditorLocked)
+ {
+ EditorLock(false);
}
}
@@ -301,36 +341,43 @@
/// </summary>
private void DrawAtmosphericDetails()
{
- GUILayout.BeginHorizontal();
- GUILayout.BeginVertical();
- GUILayout.Label("Pressure: " + (this.atmosphericPercentage * 100.0f).ToString("F1") + "%", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
- GUI.skin = HighLogic.Skin;
- this.atmosphericPercentage = GUILayout.HorizontalSlider(this.atmosphericPercentage, 0, 1.0f);
- GUI.skin = null;
- GUILayout.EndVertical();
-
- GUILayout.Space(5.0f);
-
- GUILayout.BeginVertical();
- GUILayout.Label("Velocity: " + this.atmosphericVelocity.ToString("F1") + "m/s", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
- GUI.skin = HighLogic.Skin;
- this.atmosphericVelocity = GUILayout.HorizontalSlider(this.atmosphericVelocity, 0, 2500f);
- GUI.skin = null;
- GUILayout.EndVertical();
- GUILayout.EndHorizontal();
+ try
+ {
+ GUILayout.BeginHorizontal();
+ GUILayout.BeginVertical();
+ GUILayout.Label("Altitude: " + (Altitude * 0.001f).ToString("F1") + "km", settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
+ GUI.skin = HighLogic.Skin;
+ Altitude = GUILayout.HorizontalSlider(Altitude, 0.0f, (float)(CelestialBodies.SelectedBody.CelestialBody.atmosphereDepth));
+ GUI.skin = null;
+ GUILayout.EndVertical();
+
+ GUILayout.Space(5.0f);
+
+ GUILayout.BeginVertical();
+ GUILayout.Label("Mach: " + atmosphericMach.ToString("F2"), settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
+ GUI.skin = HighLogic.Skin;
+ atmosphericMach = GUILayout.HorizontalSlider(Mathf.Clamp(atmosphericMach, 0.0f, maxMach), 0.0f, maxMach);
+ GUI.skin = null;
+ GUILayout.EndVertical();
+ GUILayout.EndHorizontal();
+ }
+ catch (Exception ex)
+ {
+ Logger.Exception(ex, "BuildAdvanced.DrawAtmosphericDetails()");
+ }
}
private void DrawBodiesList()
{
if (CelestialBodies.SystemBody == CelestialBodies.SelectedBody)
{
- this.DrawBody(CelestialBodies.SystemBody);
+ DrawBody(CelestialBodies.SystemBody);
}
else
{
- foreach (var body in CelestialBodies.SystemBody.Children)
- {
- this.DrawBody(body);
+ foreach (CelestialBodies.BodyInfo body in CelestialBodies.SystemBody.Children)
+ {
+ DrawBody(body);
}
}
}
@@ -339,18 +386,19 @@
{
GUILayout.BeginHorizontal();
GUILayout.Space(20.0f * depth);
- if (GUILayout.Button(bodyInfo.Children.Count > 0 ? bodyInfo.Name + " [" + bodyInfo.Children.Count + "]" : bodyInfo.Name, bodyInfo.Selected && bodyInfo.SelectedDepth == 0 ? this.bodiesButtonActiveStyle : this.bodiesButtonStyle))
+ if (GUILayout.Button(bodyInfo.Children.Count > 0 ? bodyInfo.Name + " [" + bodyInfo.Children.Count + "]" : bodyInfo.Name, bodyInfo.Selected && bodyInfo.SelectedDepth == 0 ? bodiesButtonActiveStyle : bodiesButtonStyle))
{
CelestialBodies.SetSelectedBody(bodyInfo.Name);
- this.bodiesList.Resize = true;
+ Altitude = 0.0f;
+ bodiesList.Resize = true;
}
GUILayout.EndHorizontal();
if (bodyInfo.Selected)
{
- foreach (var body in bodyInfo.Children)
- {
- this.DrawBody(body, depth + 1);
+ for (int i = 0; i < bodyInfo.Children.Count; ++i)
+ {
+ DrawBody(bodyInfo.Children[i], depth + 1);
}
}
}
@@ -361,12 +409,13 @@
private void DrawBurnTime()
{
GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
- GUILayout.Label("BURN", this.titleStyle);
- foreach (var stage in this.stages)
- {
- if (this.showAllStages || stage.deltaV > 0)
- {
- GUILayout.Label(TimeFormatter.ConvertToString(stage.time), this.infoStyle);
+ GUILayout.Label("BURN", titleStyle);
+ for (int i = 0; i < stagesLength; ++i)
+ {
+ stage = stages[i];
+ if (showAllStages || stage.deltaV > 0.0)
+ {
+ GUILayout.Label(TimeFormatter.ConvertToString(stage.time), infoStyle);
}
}
GUILayout.EndVertical();
@@ -378,12 +427,13 @@
private void DrawCost()
{
GUILayout.BeginVertical(GUILayout.Width(110.0f * GuiDisplaySize.Offset));
- GUILayout.Label("COST", this.titleStyle);
- foreach (var stage in this.stages)
- {
- if (this.showAllStages || stage.deltaV > 0)
- {
- GUILayout.Label(Units.Concat(stage.cost, stage.totalCost), this.infoStyle);
+ GUILayout.Label("COST", titleStyle);
+ for (int i = 0; i < stagesLength; ++i)
+ {
+ stage = stages[i];
+ if (showAllStages || stage.deltaV > 0.0)
+ {
+ GUILayout.Label(Units.Cost(stage.cost, stage.totalCost), infoStyle);
}
}
GUILayout.EndVertical();
@@ -395,12 +445,13 @@
private void DrawDeltaV()
{
GUILayout.BeginVertical(GUILayout.Width(100.0f * GuiDisplaySize.Offset));
- GUILayout.Label("DELTA-V", this.titleStyle);
- foreach (var stage in this.stages)
- {
- if (this.showAllStages || stage.deltaV > 0)
- {
- GUILayout.Label(stage.deltaV.ToString("N0") + " / " + stage.inverseTotalDeltaV.ToString("N0") + "m/s", this.infoStyle);
+ GUILayout.Label("DELTA-V", titleStyle);
+ for (int i = 0; i < stagesLength; ++i)
+ {
+ stage = stages[i];
+ if (showAllStages || stage.deltaV > 0.0)
+ {
+ GUILayout.Label(stage.deltaV.ToString("N0") + " / " + stage.inverseTotalDeltaV.ToString("N0") + "m/s", infoStyle);
}
}
GUILayout.EndVertical();
@@ -412,12 +463,13 @@
private void DrawIsp()
{
GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
- GUILayout.Label("ISP", this.titleStyle);
- foreach (var stage in this.stages)
- {
- if (this.showAllStages || stage.deltaV > 0)
- {
- GUILayout.Label(stage.isp.ToString("F1") + "s", this.infoStyle);
+ GUILayout.Label("ISP", titleStyle);
+ for (int i = 0; i < stagesLength; ++i)
+ {
+ stage = stages[i];
+ if (showAllStages || stage.deltaV > 0.0)
+ {
+ GUILayout.Label(stage.isp.ToString("F1") + "s", infoStyle);
}
}
GUILayout.EndVertical();
@@ -429,12 +481,13 @@
private void DrawMass()
{
GUILayout.BeginVertical(GUILayout.Width(110.0f * GuiDisplaySize.Offset));
- GUILayout.Label("MASS", this.titleStyle);
- foreach (var stage in this.stages)
- {
- if (this.showAllStages || stage.deltaV > 0)
- {
- GUILayout.Label(Units.ToMass(stage.mass, stage.totalMass), this.infoStyle);
+ GUILayout.Label("MASS", titleStyle);
+ for (int i = 0; i < stagesLength; ++i)
+ {
+ stage = stages[i];
+ if (showAllStages || stage.deltaV > 0.0)
+ {
+ GUILayout.Label(Units.ToMass(stage.mass, stage.totalMass), infoStyle);
}
}
GUILayout.EndVertical();
@@ -446,12 +499,13 @@
private void DrawPartCount()
{
GUILayout.BeginVertical(GUILayout.Width(50.0f * GuiDisplaySize.Offset));
- GUILayout.Label("PARTS", this.titleStyle);
- foreach (var stage in this.stages)
- {
- if (this.showAllStages || stage.deltaV > 0)
- {
- GUILayout.Label(stage.partCount.ToString("N0"), this.infoStyle);
+ GUILayout.Label("PARTS", titleStyle);
+ for (int i = 0; i < stagesLength; ++i)
+ {
+ stage = stages[i];
+ if (showAllStages || stage.deltaV > 0.0)
+ {
+ GUILayout.Label(stage.partCount + " / " + stage.totalPartCount, infoStyle);
}
}
GUILayout.EndVertical();
@@ -463,39 +517,55 @@
private void DrawSettings()
{
GUILayout.BeginHorizontal();
- GUILayout.Label("Compact mode collapses to the:", this.settingStyle);
- this.compactCollapseRight = !GUILayout.Toggle(!this.compactCollapseRight, "LEFT", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
- this.compactCollapseRight = GUILayout.Toggle(this.compactCollapseRight, "RIGHT", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+ GUILayout.Label("Compact mode collapses to the:", settingStyle);
+ compactCollapseRight = !GUILayout.Toggle(!compactCollapseRight, "LEFT", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+ compactCollapseRight = GUILayout.Toggle(compactCollapseRight, "RIGHT", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
- GUILayout.Label("Build Engineer Overlay:", this.settingStyle);
- BuildOverlay.Visible = GUILayout.Toggle(BuildOverlay.Visible, "VISIBLE", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
- BuildOverlayPartInfo.NamesOnly = GUILayout.Toggle(BuildOverlayPartInfo.NamesOnly, "NAMES ONLY", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
- BuildOverlayPartInfo.ClickToOpen = GUILayout.Toggle(BuildOverlayPartInfo.ClickToOpen, "CLICK TO OPEN", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+ GUILayout.Label("Simulate using vectored thrust values:");
+ SimManager.vectoredThrust = GUILayout.Toggle(SimManager.vectoredThrust, "ENABLED", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
- GUILayout.Label("Flight Engineer activation mode:", this.settingStyle);
- FlightEngineerPartless.IsPartless = GUILayout.Toggle(FlightEngineerPartless.IsPartless, "PARTLESS", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
- FlightEngineerPartless.IsPartless = !GUILayout.Toggle(!FlightEngineerPartless.IsPartless, "MODULE", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+ GUILayout.Label("Verbose Simulation Log:");
+ SimManager.logOutput = GUILayout.Toggle(SimManager.logOutput, "ENABLED", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
- GUILayout.Label("GUI Size: " + GuiDisplaySize.Increment, this.settingStyle);
- if (GUILayout.Button("<", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)))
+ GUILayout.Label("Build Engineer Overlay:", settingStyle);
+ BuildOverlay.Visible = GUILayout.Toggle(BuildOverlay.Visible, "VISIBLE", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+ BuildOverlayPartInfo.NamesOnly = GUILayout.Toggle(BuildOverlayPartInfo.NamesOnly, "NAMES ONLY", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+ BuildOverlayPartInfo.ClickToOpen = GUILayout.Toggle(BuildOverlayPartInfo.ClickToOpen, "CLICK TO OPEN", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+ GUILayout.EndHorizontal();
+
+ GUILayout.BeginHorizontal();
+ GUILayout.Label("Flight Engineer activation mode:", settingStyle);
+ FlightEngineerCore.IsCareerMode = GUILayout.Toggle(FlightEngineerCore.IsCareerMode, "CAREER", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+ FlightEngineerCore.IsCareerMode = !GUILayout.Toggle(!FlightEngineerCore.IsCareerMode, "PARTLESS", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+ GUILayout.EndHorizontal();
+
+ GUILayout.BeginHorizontal();
+ GUILayout.Label("Flight Engineer Career Limitations:", settingStyle);
+ FlightEngineerCore.IsKerbalLimited = GUILayout.Toggle(FlightEngineerCore.IsKerbalLimited, "KERBAL", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+ FlightEngineerCore.IsTrackingStationLimited = GUILayout.Toggle(FlightEngineerCore.IsTrackingStationLimited, "TRACKING", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+ GUILayout.EndHorizontal();
+
+ GUILayout.BeginHorizontal();
+ GUILayout.Label("GUI Size: " + GuiDisplaySize.Increment, settingStyle);
+ if (GUILayout.Button("<", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)))
{
GuiDisplaySize.Increment--;
}
- if (GUILayout.Button(">", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)))
+ if (GUILayout.Button(">", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)))
{
GuiDisplaySize.Increment++;
}
GUILayout.EndHorizontal();
- GUILayout.Label("Minimum delay between simulations: " + SimManager.minSimTime + "ms", this.settingStyle);
+ GUILayout.Label("Minimum delay between simulations: " + SimManager.minSimTime.Milliseconds + "ms", settingStyle);
GUI.skin = HighLogic.Skin;
- SimManager.minSimTime = (long)GUILayout.HorizontalSlider(SimManager.minSimTime, 0, 2000.0f);
+ SimManager.minSimTime = new TimeSpan(0, 0, 0, 0, (int)GUILayout.HorizontalSlider(SimManager.minSimTime.Milliseconds, 0, 2000.0f));
GUI.skin = null;
}
@@ -505,12 +575,13 @@
private void DrawStageNumbers()
{
GUILayout.BeginVertical(GUILayout.Width(30.0f * GuiDisplaySize.Offset));
- GUILayout.Label(string.Empty, this.titleStyle);
- foreach (var stage in this.stages)
- {
- if (this.showAllStages || stage.deltaV > 0)
- {
- GUILayout.Label("S" + stage.number, this.titleStyle);
+ GUILayout.Label(string.Empty, titleStyle);
+ for (int i = 0; i < stagesLength; ++i)
+ {
+ stage = stages[i];
+ if (showAllStages || stage.deltaV > 0.0)
+ {
+ GUILayout.Label("S" + stage.number, titleStyle);
}
}
GUILayout.EndVertical();
@@ -522,12 +593,31 @@
private void DrawThrust()
{
GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
- GUILayout.Label("THRUST", this.titleStyle);
- foreach (var stage in this.stages)
- {
- if (this.showAllStages || stage.deltaV > 0)
- {
- GUILayout.Label(stage.thrust.ToForce(), this.infoStyle);
+ GUILayout.Label("THRUST", titleStyle);
+ for (int i = 0; i < stagesLength; ++i)
+ {
+ stage = stages[i];
+ if (showAllStages || stage.deltaV > 0.0)
+ {
+ GUILayout.Label(stage.thrust.ToForce(), infoStyle);
+ }
+ }
+ GUILayout.EndVertical();
+ }
+
+ /// <summary>
+ /// Draws the torque column.
+ /// </summary>
+ private void DrawTorque()
+ {
+ GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
+ GUILayout.Label("TORQUE", titleStyle);
+ for (int i = 0; i < stagesLength; ++i)
+ {
+ stage = stages[i];
+ if (showAllStages || stage.deltaV > 0.0)
+ {
+ GUILayout.Label(stage.maxThrustTorque.ToTorque(), infoStyle);
}
}
GUILayout.EndVertical();
@@ -539,12 +629,13 @@
private void DrawTwr()
{
GUILayout.BeginVertical(GUILayout.Width(100.0f * GuiDisplaySize.Offset));
- GUILayout.Label("TWR (MAX)", this.titleStyle);
- foreach (var stage in this.stages)
- {
- if (this.showAllStages || stage.deltaV > 0)
- {
- GUILayout.Label(stage.thrustToWeight.ToString("F2") + " (" + stage.maxThrustToWeight.ToString("F2") + ")", this.infoStyle);
+ GUILayout.Label("TWR (MAX)", titleStyle);
+ for (int i = 0; i < stagesLength; ++i)
+ {
+ stage = stages[i];
+ if (showAllStages || stage.deltaV > 0.0)
+ {
+ GUILayout.Label(stage.thrustToWeight.ToString("F2") + " (" + stage.maxThrustToWeight.ToString("F2") + ")", infoStyle);
}
}
GUILayout.EndVertical();
@@ -554,15 +645,24 @@
{
if (state)
{
- EditorLogic.fetch.Lock(true, true, true, "KER_BuildAdvanced");
+ InputLockManager.SetControlLock(ControlTypes.All, "KER_BuildAdvanced");
BuildOverlayPartInfo.Hidden = true;
- this.isEditorLocked = true;
+ isEditorLocked = true;
}
else
{
- EditorLogic.fetch.Unlock("KER_BuildAdvanced");
+ InputLockManager.SetControlLock(ControlTypes.None, "KER_BuildAdvanced");
BuildOverlayPartInfo.Hidden = false;
- this.isEditorLocked = false;
+ isEditorLocked = false;
+ }
+ }
+
+ private void GetStageInfo()
+ {
+ stages = SimManager.Stages;
+ if (stages != null && stages.Length > 0)
+ {
+ maxMach = stages[stages.Length - 1].maxMach;
}
}
@@ -571,22 +671,22 @@
/// </summary>
private void InitialiseStyles()
{
- this.windowStyle = new GUIStyle(HighLogic.Skin.window)
+ windowStyle = new GUIStyle(HighLogic.Skin.window)
{
alignment = TextAnchor.UpperLeft
};
- this.areaStyle = new GUIStyle(HighLogic.Skin.box)
+ areaStyle = new GUIStyle(HighLogic.Skin.box)
{
padding = new RectOffset(0, 0, 9, 0)
};
- this.areaSettingStyle = new GUIStyle(HighLogic.Skin.box)
+ areaSettingStyle = new GUIStyle(HighLogic.Skin.box)
{
padding = new RectOffset(10, 10, 10, 10)
};
- this.buttonStyle = new GUIStyle(HighLogic.Skin.button)
+ buttonStyle = new GUIStyle(HighLogic.Skin.button)
{
normal =
{
@@ -597,7 +697,7 @@
alignment = TextAnchor.MiddleCenter
};
- this.titleStyle = new GUIStyle(HighLogic.Skin.label)
+ titleStyle = new GUIStyle(HighLogic.Skin.label)
{
normal =
{
@@ -609,7 +709,7 @@
stretchWidth = true,
};
- this.infoStyle = new GUIStyle(HighLogic.Skin.label)
+ infoStyle = new GUIStyle(HighLogic.Skin.label)
{
fontSize = (int)(11 * GuiDisplaySize.Offset),
fontStyle = FontStyle.Bold,
@@ -617,21 +717,21 @@
stretchWidth = true
};
- this.settingStyle = new GUIStyle(this.titleStyle)
+ settingStyle = new GUIStyle(titleStyle)
{
alignment = TextAnchor.MiddleLeft,
stretchWidth = true,
stretchHeight = true
};
- this.settingAtmoStyle = new GUIStyle(this.titleStyle)
+ settingAtmoStyle = new GUIStyle(titleStyle)
{
margin = new RectOffset(),
padding = new RectOffset(),
alignment = TextAnchor.UpperLeft
};
- this.bodiesButtonStyle = new GUIStyle(HighLogic.Skin.button)
+ bodiesButtonStyle = new GUIStyle(HighLogic.Skin.button)
{
margin = new RectOffset(0, 0, 2, 0),
padding = new RectOffset(5, 5, 5, 5),
@@ -649,10 +749,10 @@
fixedHeight = 20.0f
};
- this.bodiesButtonActiveStyle = new GUIStyle(this.bodiesButtonStyle)
- {
- normal = this.bodiesButtonStyle.onNormal,
- hover = this.bodiesButtonStyle.onHover
+ bodiesButtonActiveStyle = new GUIStyle(bodiesButtonStyle)
+ {
+ normal = bodiesButtonStyle.onNormal,
+ hover = bodiesButtonStyle.onHover
};
}
@@ -663,27 +763,27 @@
{
try
{
- var handler = SettingHandler.Load("BuildAdvanced.xml");
- handler.Get("visible", ref this.visible);
- this.position.x = handler.Get("windowPositionX", this.position.x);
- this.position.y = handler.Get("windowPositionY", this.position.y);
- handler.Get("compactMode", ref this.compactMode);
- handler.Get("compactCollapseRight", ref this.compactCollapseRight);
- handler.Get("showAllStages", ref this.showAllStages);
- handler.Get("showAtmosphericDetails", ref this.showAtmosphericDetails);
- handler.Get("showSettings", ref this.showSettings);
+ SettingHandler handler = SettingHandler.Load("BuildAdvanced.xml");
+ handler.Get("visible", ref visible);
+ position.x = handler.Get("windowPositionX", position.x);
+ position.y = handler.Get("windowPositionY", position.y);
+ handler.Get("compactMode", ref compactMode);
+ handler.Get("compactCollapseRight", ref compactCollapseRight);
+ handler.Get("showAllStages", ref showAllStages);
+ handler.Get("showAtmosphericDetails", ref showAtmosphericDetails);
+ handler.Get("showSettings", ref showSettings);
CelestialBodies.SetSelectedBody(handler.Get("selectedBodyName", CelestialBodies.SelectedBody.Name));
}
catch (Exception ex)
{
- Logger.Exception(ex, "BuildAdvanced->Load");
+ Logger.Exception(ex, "BuildAdvanced.Load()");
}
}
private void OnSizeChanged()
{
- this.InitialiseStyles();
- this.hasChanged = true;
+ InitialiseStyles();
+ hasChanged = true;
}
/// <summary>
@@ -693,76 +793,87 @@
{
try
{
+ compactModeRect = new Rect(position.width - 70.0f * GuiDisplaySize.Offset, 5.0f, 65.0f * GuiDisplaySize.Offset, 20.0f);
+
// Draw the compact mode toggle.
- if (GUI.Toggle(new Rect(this.position.width - 70.0f * GuiDisplaySize.Offset, 5.0f, 65.0f * GuiDisplaySize.Offset, 20.0f), this.compactMode, "COMPACT", this.buttonStyle) != this.compactMode)
- {
- this.hasChanged = true;
- this.compactCheck = 2;
- this.compactRight = this.position.xMax;
- this.compactMode = !this.compactMode;
+ if (GUI.Toggle(compactModeRect, compactMode, "COMPACT", buttonStyle) != compactMode)
+ {
+ hasChanged = true;
+ compactCheck = 2;
+ compactRight = position.xMax;
+ compactMode = !compactMode;
}
// When not in compact mode draw the 'All Stages' and 'Atmospheric' toggles.
- if (!this.compactMode)
- {
- if (GUI.Toggle(new Rect(this.position.width - 143.0f * GuiDisplaySize.Offset, 5.0f, 70.0f * GuiDisplaySize.Offset, 20.0f), this.showSettings, "SETTINGS", this.buttonStyle) != this.showSettings)
+ if (!compactMode)
+ {
+ if (GUI.Toggle(new Rect(position.width - 143.0f * GuiDisplaySize.Offset, 5.0f, 70.0f * GuiDisplaySize.Offset, 20.0f), showSettings, "SETTINGS", buttonStyle) != showSettings)
{
- this.hasChanged = true;
- this.showSettings = !this.showSettings;
+ hasChanged = true;
+ showSettings = !showSettings;
}
- if (GUI.Toggle(new Rect(this.position.width - 226.0f * GuiDisplaySize.Offset, 5.0f, 80.0f * GuiDisplaySize.Offset, 20.0f), this.showAllStages, "ALL STAGES", this.buttonStyle) != this.showAllStages)
+ if (GUI.Toggle(new Rect(position.width - 226.0f * GuiDisplaySize.Offset, 5.0f, 80.0f * GuiDisplaySize.Offset, 20.0f), showAllStages, "ALL STAGES", buttonStyle) != showAllStages)
{
- this.hasChanged = true;
- this.showAllStages = !this.showAllStages;
+ hasChanged = true;
+ showAllStages = !showAllStages;
}
- if (GUI.Toggle(new Rect(this.position.width - 324.0f * GuiDisplaySize.Offset, 5.0f, 95.0f * GuiDisplaySize.Offset, 20.0f), this.showAtmosphericDetails, "ATMOSPHERIC", this.buttonStyle) != this.showAtmosphericDetails)
+ if (GUI.Toggle(new Rect(position.width - 324.0f * GuiDisplaySize.Offset, 5.0f, 95.0f * GuiDisplaySize.Offset, 20.0f), showAtmosphericDetails, "ATMOSPHERIC", buttonStyle) != showAtmosphericDetails)
{
- this.hasChanged = true;
- this.showAtmosphericDetails = !this.showAtmosphericDetails;
+ hasChanged = true;
+ showAtmosphericDetails = !showAtmosphericDetails;
}
- this.bodiesListPosition = new Rect(this.position.width - 452.0f * GuiDisplaySize.Offset, 5.0f, 125.0f * GuiDisplaySize.Offset, 20.0f);
- this.bodiesList.enabled = GUI.Toggle(this.bodiesListPosition, this.bodiesList.enabled, "BODY: " + CelestialBodies.SelectedBody.Name.ToUpper(), this.buttonStyle);
- this.bodiesList.SetPosition(this.bodiesListPosition.Translate(this.position));
+ bodiesListPosition = new Rect(position.width - 452.0f * GuiDisplaySize.Offset, 5.0f, 125.0f * GuiDisplaySize.Offset, 20.0f);
+ bodiesList.enabled = GUI.Toggle(bodiesListPosition, bodiesList.enabled, "BODY: " + CelestialBodies.SelectedBody.Name.ToUpper(), buttonStyle);
+ bodiesList.SetPosition(bodiesListPosition.Translate(position));
+ }
+ else
+ {
+ if (GUI.Toggle(new Rect(position.width - 133.0f * GuiDisplaySize.Offset, 5.0f, 60.0f * GuiDisplaySize.Offset, 20.0f), showAtmosphericDetails, "ATMO", buttonStyle) != showAtmosphericDetails)
+ {
+ hasChanged = true;
+ showAtmosphericDetails = !showAtmosphericDetails;
+ }
}
// Draw the main informational display box.
- if (!this.compactMode)
- {
- GUILayout.BeginHorizontal(this.areaStyle);
- this.DrawStageNumbers();
- this.DrawPartCount();
- this.DrawCost();
- this.DrawMass();
- this.DrawIsp();
- this.DrawThrust();
- this.DrawTwr();
- this.DrawDeltaV();
- this.DrawBurnTime();
+ if (!compactMode)
+ {
+ GUILayout.BeginHorizontal(areaStyle);
+ DrawStageNumbers();
+ DrawPartCount();
+ DrawCost();
+ DrawMass();
+ DrawIsp();
+ DrawThrust();
+ DrawTorque();
+ DrawTwr();
+ DrawDeltaV();
+ DrawBurnTime();
GUILayout.EndHorizontal();
- if (this.showAtmosphericDetails)
+ if (showAtmosphericDetails && !compactMode)
{
- GUILayout.BeginVertical(this.areaSettingStyle);
- this.DrawAtmosphericDetails();
+ GUILayout.BeginVertical(areaSettingStyle);
+ DrawAtmosphericDetails();
GUILayout.EndVertical();
}
- if (this.showSettings)
+ if (showSettings)
{
- GUILayout.BeginVertical(this.areaSettingStyle);
- this.DrawSettings();
+ GUILayout.BeginVertical(areaSettingStyle);
+ DrawSettings();
GUILayout.EndVertical();
}
}
else // Draw only a few details when in compact mode.
{
- GUILayout.BeginHorizontal(this.areaStyle);
- this.DrawStageNumbers();
- this.DrawTwr();
- this.DrawDeltaV();
+ GUILayout.BeginHorizontal(areaStyle);
+ DrawStageNumbers();
+ DrawTwr();
+ DrawDeltaV();
GUILayout.EndHorizontal();
}
@@ -770,10 +881,9 @@
}
catch (Exception ex)
{
- Logger.Exception(ex);
- }
- }
-
+ Logger.Exception(ex, "BuildAdvanced.Window()");
+ }
+ }
#endregion
}
}
--- a/KerbalEngineer/Editor/BuildOverlay.cs
+++ b/KerbalEngineer/Editor/BuildOverlay.cs
@@ -19,17 +19,21 @@
#region Using Directives
-using System;
-
-using KerbalEngineer.Helpers;
-using KerbalEngineer.Settings;
-
-using UnityEngine;
+
#endregion
namespace KerbalEngineer.Editor
{
+ #region Using Directives
+
+ using System;
+ using Helpers;
+ using Settings;
+ using UnityEngine;
+
+ #endregion
+
[KSPAddon(KSPAddon.Startup.EditorAny, false)]
public class BuildOverlay : MonoBehaviour
{
@@ -191,16 +195,17 @@
#endregion
- #region Methods: public
+ #region Methods
public static void Load()
{
var handler = SettingHandler.Load("BuildOverlay.xml");
- handler.GetSet("visible", Visible);
+ Visible = handler.GetSet("visible", Visible);
BuildOverlayPartInfo.NamesOnly = handler.GetSet("namesOnly", BuildOverlayPartInfo.NamesOnly);
BuildOverlayPartInfo.ClickToOpen = handler.GetSet("clickToOpen", BuildOverlayPartInfo.ClickToOpen);
buildOverlayVessel.Open = handler.GetSet("vesselOpen", buildOverlayVessel.Open);
buildOverlayResources.Open = handler.GetSet("resourcesOpen", buildOverlayResources.Open);
+ buildOverlayVessel.WindowX = handler.GetSet("vesselWindowX", buildOverlayVessel.WindowX);
handler.Save("BuildOverlay.xml");
}
@@ -212,12 +217,9 @@
handler.Set("clickToOpen", BuildOverlayPartInfo.ClickToOpen);
handler.Set("vesselOpen", buildOverlayVessel.Open);
handler.Set("resourcesOpen", buildOverlayResources.Open);
+ handler.Set("vesselWindowX", buildOverlayVessel.WindowX);
handler.Save("BuildOverlay.xml");
}
-
- #endregion
-
- #region Methods: protected
protected void Awake()
{
--- a/KerbalEngineer/Editor/BuildOverlayPartInfo.cs
+++ b/KerbalEngineer/Editor/BuildOverlayPartInfo.cs
@@ -17,27 +17,35 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-using KerbalEngineer.Extensions;
-using KerbalEngineer.Helpers;
-
-using UnityEngine;
-
-#endregion
-
namespace KerbalEngineer.Editor
{
+ using System;
+ using System.Collections.Generic;
+ using Extensions;
+ using Helpers;
+ using UnityEngine;
+
public class BuildOverlayPartInfo : MonoBehaviour
{
- #region Fields
-
private static bool clickToOpen = true;
+ private static ModuleGenerator.GeneratorResource generatorResource;
+ private static ModuleAlternator moduleAlternator;
+ private static ModuleDataTransmitter moduleDataTransmitter;
+ private static ModuleDeployableSolarPanel moduleDeployableSolarPanel;
+ private static ModuleGenerator moduleGenerator;
+ private static ModuleGimbal moduleGimbal;
+ private static ModuleParachute moduleParachute;
+ private static ModuleRCS moduleRcs;
+ private static ModuleReactionWheel moduleReactionWheel;
+ private static ModuleResource moduleResource;
+ private static ModuleScienceExperiment moduleScienceExperiment;
private static bool namesOnly;
+ private static Part part;
+ private static PartInfoItem partInfoItem;
+ private static PartResource partResource;
+ private static Propellant propellant;
+ private static PartExtensions.ProtoModuleDecoupler protoModuleDecoupler;
+ private static PartExtensions.ProtoModuleEngine protoModuleEngine;
private static bool visible = true;
private readonly List<PartInfoItem> infoItems = new List<PartInfoItem>();
@@ -47,44 +55,54 @@
private bool showInfo;
private bool skipFrame;
- #endregion
-
- #region Properties
-
public static bool ClickToOpen
{
- get { return clickToOpen; }
- set { clickToOpen = value; }
+ get
+ {
+ return clickToOpen;
+ }
+ set
+ {
+ clickToOpen = value;
+ }
}
public static bool Hidden { get; set; }
public static bool NamesOnly
{
- get { return namesOnly; }
- set { namesOnly = value; }
+ get
+ {
+ return namesOnly;
+ }
+ set
+ {
+ namesOnly = value;
+ }
}
public static bool Visible
{
- get { return visible; }
- set { visible = value; }
- }
-
- #endregion
-
- #region Methods: protected
+ get
+ {
+ return visible;
+ }
+ set
+ {
+ visible = value;
+ }
+ }
protected void OnGUI()
{
try
{
- if (!Visible || Hidden || this.selectedPart == null)
+ if (!Visible || Hidden || selectedPart == null)
{
return;
}
- this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, String.Empty, BuildOverlay.WindowStyle);
+ position = GUILayout.Window(GetInstanceID(), position, Window, String.Empty, BuildOverlay.WindowStyle);
}
catch (Exception ex)
@@ -97,67 +115,71 @@
{
try
{
- if (!Visible || Hidden || EditorLogic.startPod == null || EditorLogic.fetch.editorScreen != EditorLogic.EditorScreen.Parts)
+ if (!Visible || Hidden || EditorLogic.RootPart == null || EditorLogic.fetch.editorScreen != EditorScreen.Parts)
{
return;
}
- this.position.x = Mathf.Clamp(Input.mousePosition.x + 16.0f, 0.0f, Screen.width - this.position.width);
- this.position.y = Mathf.Clamp(Screen.height - Input.mousePosition.y, 0.0f, Screen.height - this.position.height);
- if (this.position.x < Input.mousePosition.x + 20.0f)
- {
- this.position.y = Mathf.Clamp(this.position.y + 20.0f, 0.0f, Screen.height - this.position.height);
- }
- if (this.position.x < Input.mousePosition.x + 16.0f && this.position.y < Screen.height - Input.mousePosition.y)
- {
- this.position.x = Input.mousePosition.x - 3 - this.position.width;
- }
-
- this.infoItems.Clear();
- var part = EditorLogic.fetch.ship.parts.Find(p => p.stackIcon.highlightIcon) ?? EditorLogic.SelectedPart;
+ position.x = Mathf.Clamp(Input.mousePosition.x + 16.0f, 0.0f, Screen.width - position.width);
+ position.y = Mathf.Clamp(Screen.height - Input.mousePosition.y, 0.0f, Screen.height - position.height);
+ if (position.x < Input.mousePosition.x + 20.0f)
+ {
+ position.y = Mathf.Clamp(position.y + 20.0f, 0.0f, Screen.height - position.height);
+ }
+ if (position.x < Input.mousePosition.x + 16.0f && position.y < Screen.height - Input.mousePosition.y)
+ {
+ position.x = Input.mousePosition.x - 3 - position.width;
+ }
+
+ part = EditorLogic.fetch.ship.parts.Find(p => p.stackIcon.highlightIcon) ?? EditorLogic.SelectedPart;
if (part != null)
{
- if (!part.Equals(this.selectedPart))
- {
- this.selectedPart = part;
- this.ResetInfo();
- }
- if (NamesOnly || this.skipFrame)
- {
- this.skipFrame = false;
+ if (!part.Equals(selectedPart))
+ {
+ selectedPart = part;
+ ResetInfo();
+ }
+ if (NamesOnly || skipFrame)
+ {
+ skipFrame = false;
return;
}
- this.SetCostInfo();
- this.SetMassItems();
- this.SetResourceItems();
- this.SetEngineInfo();
- this.SetAlternatorInfo();
- this.SetGimbalInfo();
- this.SetRcsInfo();
- this.SetParachuteInfo();
- this.SetSasInfo();
- this.SetReactionWheelInfo();
- this.SetSolarPanelInfo();
- this.SetGeneratorInfo();
- this.SetDecouplerInfo();
- this.SetTransmitterInfo();
- this.SetScienceExperimentInfo();
- this.SetScienceContainerInfo();
- this.SetSingleActivationInfo();
-
- if (!this.showInfo && Input.GetMouseButtonDown(2))
- {
- this.showInfo = true;
- }
- else if (ClickToOpen && this.showInfo && Input.GetMouseButtonDown(2))
- {
- this.ResetInfo();
+ if (!showInfo && Input.GetMouseButtonDown(2))
+ {
+ showInfo = true;
+ }
+ else if (ClickToOpen && showInfo && Input.GetMouseButtonDown(2))
+ {
+ ResetInfo();
+ }
+
+ if (showInfo)
+ {
+ PartInfoItem.Release(infoItems);
+ infoItems.Clear();
+ SetCostInfo();
+ SetMassItems();
+ SetResourceItems();
+ SetEngineInfo();
+ SetAlternatorInfo();
+ SetGimbalInfo();
+ SetRcsInfo();
+ SetParachuteInfo();
+ SetSasInfo();
+ SetReactionWheelInfo();
+ SetSolarPanelInfo();
+ SetGeneratorInfo();
+ SetDecouplerInfo();
+ SetTransmitterInfo();
+ SetScienceExperimentInfo();
+ SetScienceContainerInfo();
+ SetSingleActivationInfo();
}
}
else
{
- this.selectedPart = null;
+ selectedPart = null;
}
}
catch (Exception ex)
@@ -166,277 +188,277 @@
}
}
- #endregion
-
- #region Methods: private
-
private void ResetInfo()
{
- this.showInfo = !clickToOpen;
- this.skipFrame = true;
- this.position.width = namesOnly || clickToOpen ? 0.0f : 200.0f;
- this.position.height = 0.0f;
+ showInfo = !clickToOpen;
+ skipFrame = true;
+ position.width = namesOnly || clickToOpen ? 0.0f : 200.0f;
+ position.height = 0.0f;
}
private void SetAlternatorInfo()
{
- if (!this.selectedPart.HasModule<ModuleAlternator>())
- {
- return;
- }
-
- var alternator = this.selectedPart.GetModule<ModuleAlternator>();
- this.infoItems.Add(new PartInfoItem("Alternator"));
- foreach (var resource in alternator.outputResources)
- {
- this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
+ moduleAlternator = selectedPart.GetModule<ModuleAlternator>();
+ if (moduleAlternator != null)
+ {
+ infoItems.Add(PartInfoItem.Create("Alternator"));
+ for (int i = 0; i < moduleAlternator.outputResources.Count; ++i)
+ {
+ moduleResource = moduleAlternator.outputResources[i];
+ infoItems.Add(PartInfoItem.Create("\t" + moduleResource.name, moduleResource.rate.ToRate()));
+ }
}
}
private void SetCostInfo()
{
- this.infoItems.Add(new PartInfoItem("Cost", Units.Concat(this.selectedPart.GetCostDry(), this.selectedPart.GetCostWet())));
+ infoItems.Add(PartInfoItem.Create("Cost", Units.ConcatF(selectedPart.GetCostDry(), selectedPart.GetCostWet())));
}
private void SetDecouplerInfo()
{
- if (!this.selectedPart.IsDecoupler())
- {
- return;
- }
-
- var decoupler = this.selectedPart.GetProtoModuleDecoupler();
- this.infoItems.Add(new PartInfoItem("Ejection Force", decoupler.EjectionForce.ToForce()));
- if (decoupler.IsOmniDecoupler)
- {
- this.infoItems.Add(new PartInfoItem("Omni-directional"));
+ protoModuleDecoupler = selectedPart.GetProtoModuleDecoupler();
+ if (protoModuleDecoupler != null)
+ {
+ infoItems.Add(PartInfoItem.Create("Ejection Force", protoModuleDecoupler.EjectionForce.ToForce()));
+ if (protoModuleDecoupler.IsOmniDecoupler)
+ {
+ infoItems.Add(PartInfoItem.Create("Omni-directional"));
+ }
}
}
private void SetEngineInfo()
{
- if (!this.selectedPart.IsEngine())
- {
- return;
- }
-
- var engine = this.selectedPart.GetProtoModuleEngine();
- this.infoItems.Add(new PartInfoItem("Thrust", Units.ToForce(engine.MinimumThrust, engine.MaximumThrust)));
- this.infoItems.Add(new PartInfoItem("Isp", Units.Concat(engine.GetSpecificImpulse(1.0f), engine.GetSpecificImpulse(0.0f)) + "s"));
- if (engine.Propellants.Count > 0)
- {
- this.infoItems.Add(new PartInfoItem("Propellants"));
- var totalRatio = engine.Propellants.Sum(p => p.ratio);
- foreach (var propellant in engine.Propellants)
- {
- this.infoItems.Add(new PartInfoItem("\t" + propellant.name, (propellant.ratio / totalRatio).ToPercent()));
+ protoModuleEngine = selectedPart.GetProtoModuleEngine();
+ if (protoModuleEngine != null)
+ {
+ infoItems.Add(PartInfoItem.Create("Thrust", Units.ToForce(protoModuleEngine.MinimumThrust, protoModuleEngine.MaximumThrust)));
+ infoItems.Add(PartInfoItem.Create("Isp", Units.ConcatF(protoModuleEngine.GetSpecificImpulse(1.0f), protoModuleEngine.GetSpecificImpulse(0.0f)) + "s"));
+ if (protoModuleEngine.Propellants.Count > 0)
+ {
+ infoItems.Add(PartInfoItem.Create("Propellants"));
+
+ float totalRatio = 0.0f;
+ for (int i = 0; i < protoModuleEngine.Propellants.Count; ++i)
+ {
+ totalRatio = totalRatio + protoModuleEngine.Propellants[i].ratio;
+ }
+
+ for (int i = 0; i < protoModuleEngine.Propellants.Count; ++i)
+ {
+ propellant = protoModuleEngine.Propellants[i];
+ infoItems.Add(PartInfoItem.Create("\t" + propellant.name, (propellant.ratio / totalRatio).ToPercent()));
+ }
}
}
}
private void SetGeneratorInfo()
{
- if (!this.selectedPart.HasModule<ModuleGenerator>())
- {
- return;
- }
-
- var generator = this.selectedPart.GetModule<ModuleGenerator>();
- if (generator.inputList.Count > 0)
- {
- this.infoItems.Add(new PartInfoItem("Generator Input"));
- foreach (var resource in generator.inputList)
- {
- this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
- }
- }
- if (generator.outputList.Count > 0)
- {
- this.infoItems.Add(new PartInfoItem("Generator Output"));
- foreach (var resource in generator.outputList)
- {
- this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
- }
- }
- if (generator.isAlwaysActive)
- {
- this.infoItems.Add(new PartInfoItem("Generator is Always Active"));
+ moduleGenerator = selectedPart.GetModule<ModuleGenerator>();
+ if (moduleGenerator != null)
+ {
+ if (moduleGenerator.inputList.Count > 0)
+ {
+ infoItems.Add(PartInfoItem.Create("Generator Input"));
+ for (int i = 0; i < moduleGenerator.inputList.Count; ++i)
+ {
+ generatorResource = moduleGenerator.inputList[i];
+ infoItems.Add(PartInfoItem.Create("\t" + generatorResource.name, generatorResource.rate.ToRate()));
+ }
+ }
+ if (moduleGenerator.outputList.Count > 0)
+ {
+ infoItems.Add(PartInfoItem.Create("Generator Output"));
+ for (int i = 0; i < moduleGenerator.outputList.Count; ++i)
+ {
+ generatorResource = moduleGenerator.outputList[i];
+ infoItems.Add(PartInfoItem.Create("\t" + generatorResource.name, generatorResource.rate.ToRate()));
+ }
+ }
+ if (moduleGenerator.isAlwaysActive)
+ {
+ infoItems.Add(PartInfoItem.Create("Generator is Always Active"));
+ }
}
}
private void SetGimbalInfo()
{
- if (!this.selectedPart.HasModule<ModuleGimbal>())
- {
- return;
- }
-
- var gimbal = this.selectedPart.GetModule<ModuleGimbal>();
- this.infoItems.Add(new PartInfoItem("Thrust Vectoring", gimbal.gimbalRange.ToString("F2")));
+ moduleGimbal = selectedPart.GetModule<ModuleGimbal>();
+ if (moduleGimbal != null)
+ {
+ infoItems.Add(PartInfoItem.Create("Thrust Vectoring", moduleGimbal.gimbalRange.ToString("F2")));
+ }
}
private void SetMassItems()
{
- if (this.selectedPart.physicalSignificance == Part.PhysicalSignificance.FULL)
- {
- this.infoItems.Add(new PartInfoItem("Mass", Units.ToMass(this.selectedPart.GetDryMass(), this.selectedPart.GetWetMass())));
+ if (selectedPart.physicalSignificance == Part.PhysicalSignificance.FULL)
+ {
+ infoItems.Add(PartInfoItem.Create("Mass", Units.ToMass(selectedPart.GetDryMass(), selectedPart.GetWetMass())));
}
}
private void SetParachuteInfo()
{
- if (!this.selectedPart.HasModule<ModuleParachute>())
- {
- return;
- }
-
- var parachute = this.selectedPart.GetModule<ModuleParachute>();
- this.infoItems.Add(new PartInfoItem("Deployed Drag", Units.Concat(parachute.semiDeployedDrag, parachute.fullyDeployedDrag)));
- this.infoItems.Add(new PartInfoItem("Deployment Altitude", parachute.deployAltitude.ToDistance()));
- this.infoItems.Add(new PartInfoItem("Deployment Pressure", parachute.minAirPressureToOpen.ToString("F2")));
+ moduleParachute = selectedPart.GetModule<ModuleParachute>();
+ if (moduleParachute != null)
+ {
+ infoItems.Add(PartInfoItem.Create("Deployed Drag", Units.ConcatF(moduleParachute.semiDeployedDrag, moduleParachute.fullyDeployedDrag)));
+ infoItems.Add(PartInfoItem.Create("Deployment Altitude", moduleParachute.deployAltitude.ToDistance()));
+ infoItems.Add(PartInfoItem.Create("Deployment Pressure", moduleParachute.minAirPressureToOpen.ToString("F2")));
+ }
}
private void SetRcsInfo()
{
- if (!this.selectedPart.HasModule<ModuleRCS>())
- {
- return;
- }
-
- var rcs = this.selectedPart.GetModule<ModuleRCS>();
- this.infoItems.Add(new PartInfoItem("Thruster Power", rcs.thrusterPower.ToForce()));
- this.infoItems.Add(new PartInfoItem("Specific Impulse", Units.Concat(rcs.atmosphereCurve.Evaluate(1.0f), rcs.atmosphereCurve.Evaluate(0.0f)) + "s"));
+ moduleRcs = selectedPart.GetModule<ModuleRCS>();
+ if (moduleRcs != null)
+ {
+ infoItems.Add(PartInfoItem.Create("Thruster Power", moduleRcs.thrusterPower.ToForce()));
+ infoItems.Add(PartInfoItem.Create("Specific Impulse", Units.ConcatF(moduleRcs.atmosphereCurve.Evaluate(1.0f), moduleRcs.atmosphereCurve.Evaluate(0.0f)) + "s"));
+ }
}
private void SetReactionWheelInfo()
{
- if (!this.selectedPart.HasModule<ModuleReactionWheel>())
- {
- return;
- }
-
- var reactionWheel = this.selectedPart.GetModule<ModuleReactionWheel>();
- this.infoItems.Add(new PartInfoItem("Reaction Wheel Torque"));
- this.infoItems.Add(new PartInfoItem("\tPitch", reactionWheel.PitchTorque.ToForce()));
- this.infoItems.Add(new PartInfoItem("\tRoll", reactionWheel.RollTorque.ToForce()));
- this.infoItems.Add(new PartInfoItem("\tYaw", reactionWheel.YawTorque.ToForce()));
- foreach (var resource in reactionWheel.inputResources)
- {
- this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
+ moduleReactionWheel = selectedPart.GetModule<ModuleReactionWheel>();
+ if (moduleReactionWheel != null)
+ {
+ infoItems.Add(PartInfoItem.Create("Reaction Wheel Torque"));
+ infoItems.Add(PartInfoItem.Create("\tPitch", moduleReactionWheel.PitchTorque.ToTorque()));
+ infoItems.Add(PartInfoItem.Create("\tRoll", moduleReactionWheel.RollTorque.ToTorque()));
+ infoItems.Add(PartInfoItem.Create("\tYaw", moduleReactionWheel.YawTorque.ToTorque()));
+ for (int i = 0; i < moduleReactionWheel.inputResources.Count; ++i)
+ {
+ moduleResource = moduleReactionWheel.inputResources[i];
+ infoItems.Add(PartInfoItem.Create("\t" + moduleResource.name, moduleResource.rate.ToRate()));
+ }
}
}
private void SetResourceItems()
{
- if (this.selectedPart.Resources.list.Any(r => !r.hideFlow))
- {
- this.infoItems.Add(new PartInfoItem("Resources"));
- foreach (var resource in this.selectedPart.Resources.list.Where(r => !r.hideFlow))
- {
- this.infoItems.Add(resource.GetDensity() > 0
- ? new PartInfoItem("\t" + resource.info.name, "(" + resource.GetMass().ToMass() + ") " + resource.amount.ToString("F1"))
- : new PartInfoItem("\t" + resource.info.name, resource.amount.ToString("F1")));
+ bool visibleResources = false;
+ for (int i = 0; i < selectedPart.Resources.list.Count; ++i)
+ {
+ if (selectedPart.Resources.list[i].hideFlow == false)
+ {
+ visibleResources = true;
+ break;
+ }
+ }
+ if (visibleResources)
+ {
+ infoItems.Add(PartInfoItem.Create("Resources"));
+ for (int i = 0; i < selectedPart.Resources.list.Count; ++i)
+ {
+ partResource = selectedPart.Resources.list[i];
+
+ if (partResource.hideFlow == false)
+ {
+ infoItems.Add(partResource.GetDensity() > 0
+ ? PartInfoItem.Create("\t" + partResource.info.name, "(" + partResource.GetMass().ToMass() + ") " + partResource.amount.ToString("F1"))
+ : PartInfoItem.Create("\t" + partResource.info.name, partResource.amount.ToString("F1")));
+ }
}
}
}
private void SetSasInfo()
{
- if (this.selectedPart.HasModule<ModuleSAS>())
- {
- this.infoItems.Add(new PartInfoItem("SAS Equiped"));
+ if (selectedPart.HasModule<ModuleSAS>())
+ {
+ infoItems.Add(PartInfoItem.Create("SAS Equiped"));
}
}
private void SetScienceContainerInfo()
{
- if (this.selectedPart.HasModule<ModuleScienceContainer>())
- {
- this.infoItems.Add(new PartInfoItem("Science Container"));
+ if (selectedPart.HasModule<ModuleScienceContainer>())
+ {
+ infoItems.Add(PartInfoItem.Create("Science Container"));
}
}
private void SetScienceExperimentInfo()
{
- if (!this.selectedPart.HasModule<ModuleScienceExperiment>())
- {
- return;
- }
-
- var experiment = this.selectedPart.GetModule<ModuleScienceExperiment>();
- this.infoItems.Add(new PartInfoItem("Science Experiment", experiment.experimentActionName));
- this.infoItems.Add(new PartInfoItem("\tTransmit Efficiency", experiment.xmitDataScalar.ToPercent()));
- if (!experiment.rerunnable)
- {
- this.infoItems.Add(new PartInfoItem("\tSingle Usage"));
+ moduleScienceExperiment = selectedPart.GetModule<ModuleScienceExperiment>();
+ if (moduleScienceExperiment != null)
+ {
+ infoItems.Add(PartInfoItem.Create("Science Experiment", moduleScienceExperiment.experimentActionName));
+ infoItems.Add(PartInfoItem.Create("\tTransmit Efficiency", moduleScienceExperiment.xmitDataScalar.ToPercent()));
+ if (moduleScienceExperiment.rerunnable == false)
+ {
+ infoItems.Add(PartInfoItem.Create("\tSingle Usage"));
+ }
}
}
private void SetSingleActivationInfo()
{
- if (this.selectedPart.HasModule<ModuleAnimateGeneric>(m => m.isOneShot))
- {
- this.infoItems.Add(new PartInfoItem("Single Activation"));
+ if (selectedPart.HasModule<ModuleAnimateGeneric>(m => m.isOneShot))
+ {
+ infoItems.Add(PartInfoItem.Create("Single Activation"));
}
}
private void SetSolarPanelInfo()
{
- if (!this.selectedPart.HasModule<ModuleDeployableSolarPanel>())
- {
- return;
- }
-
- var solarPanel = this.selectedPart.GetModule<ModuleDeployableSolarPanel>();
- this.infoItems.Add(new PartInfoItem("Charge Rate", solarPanel.chargeRate.ToRate()));
- if (solarPanel.isBreakable)
- {
- this.infoItems.Add(new PartInfoItem("Breakable"));
- }
- if (solarPanel.sunTracking)
- {
- this.infoItems.Add(new PartInfoItem("Sun Tracking"));
+ moduleDeployableSolarPanel = selectedPart.GetModule<ModuleDeployableSolarPanel>();
+ if (moduleDeployableSolarPanel != null)
+ {
+ infoItems.Add(PartInfoItem.Create("Charge Rate", moduleDeployableSolarPanel.chargeRate.ToRate()));
+ if (moduleDeployableSolarPanel.isBreakable)
+ {
+ infoItems.Add(PartInfoItem.Create("Breakable"));
+ }
+ if (moduleDeployableSolarPanel.sunTracking)
+ {
+ infoItems.Add(PartInfoItem.Create("Sun Tracking"));
+ }
}
}
private void SetTransmitterInfo()
{
- if (!this.selectedPart.HasModule<ModuleDataTransmitter>())
- {
- return;
- }
-
- var transmitter = this.selectedPart.GetModule<ModuleDataTransmitter>();
- this.infoItems.Add(new PartInfoItem("Packet Size", transmitter.packetSize.ToString("F2") + " Mits"));
- this.infoItems.Add(new PartInfoItem("Bandwidth", (transmitter.packetInterval * transmitter.packetSize).ToString("F2") + "Mits/sec"));
- this.infoItems.Add(new PartInfoItem(transmitter.requiredResource, transmitter.packetResourceCost.ToString("F2") + "/Packet"));
+ moduleDataTransmitter = selectedPart.GetModule<ModuleDataTransmitter>();
+ if (moduleDataTransmitter != null)
+ {
+ infoItems.Add(PartInfoItem.Create("Packet Size", moduleDataTransmitter.packetSize.ToString("F2") + " Mits"));
+ infoItems.Add(PartInfoItem.Create("Bandwidth", (moduleDataTransmitter.packetInterval * moduleDataTransmitter.packetSize).ToString("F2") + "Mits/sec"));
+ infoItems.Add(PartInfoItem.Create(moduleDataTransmitter.requiredResource, moduleDataTransmitter.packetResourceCost.ToString("F2") + "/Packet"));
+ }
}
private void Window(int windowId)
{
try
{
- GUILayout.Label(this.selectedPart.partInfo.title, BuildOverlay.TitleStyle);
- if (this.showInfo)
- {
- foreach (var item in this.infoItems)
- {
+ GUILayout.Label(selectedPart.partInfo.title, BuildOverlay.TitleStyle);
+ if (showInfo)
+ {
+ for (int i = 0; i < infoItems.Count; ++i)
+ {
+ partInfoItem = infoItems[i];
GUILayout.Space(2.0f);
GUILayout.BeginHorizontal();
- if (item.Value != null)
+ if (partInfoItem.Value != null)
{
- GUILayout.Label(item.Name + ":", BuildOverlay.NameStyle);
+ GUILayout.Label(partInfoItem.Name + ":", BuildOverlay.NameStyle);
GUILayout.Space(25.0f);
- GUILayout.Label(item.Value, BuildOverlay.ValueStyle);
+ GUILayout.Label(partInfoItem.Value, BuildOverlay.ValueStyle);
}
else
{
- GUILayout.Label(item.Name, BuildOverlay.NameStyle);
+ GUILayout.Label(partInfoItem.Name, BuildOverlay.NameStyle);
}
GUILayout.EndHorizontal();
}
}
- else if (this.infoItems.Count > 0)
+ else if (clickToOpen && namesOnly == false)
{
GUILayout.Space(2.0f);
GUILayout.Label("Click middle mouse to show more info...", BuildOverlay.NameStyle);
@@ -447,7 +469,5 @@
Logger.Exception(ex);
}
}
-
- #endregion
}
}
--- a/KerbalEngineer/Editor/BuildOverlayResources.cs
+++ b/KerbalEngineer/Editor/BuildOverlayResources.cs
@@ -19,22 +19,18 @@
#region Using Directives
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-using KerbalEngineer.Extensions;
-
-using UnityEngine;
-
#endregion
namespace KerbalEngineer.Editor
{
+ using System;
+ using System.Collections.Generic;
+ using Extensions;
+ using UnityEngine;
+
public class BuildOverlayResources : MonoBehaviour
{
#region Fields
-
private static bool visible = true;
private readonly Dictionary<int, ResourceInfoItem> resources = new Dictionary<int, ResourceInfoItem>();
@@ -45,40 +41,48 @@
private Rect tabPosition;
private Vector2 tabSize;
private Rect windowPosition = new Rect(0.0f, 0.0f, BuildOverlay.MinimumWidth, 0.0f);
-
#endregion
#region Properties
-
public static bool Visible
{
- get { return visible; }
- set { visible = value; }
+ get
+ {
+ return visible;
+ }
+ set
+ {
+ visible = value;
+ }
}
public bool Open
{
- get { return this.open; }
- set { this.open = value; }
- }
-
+ get
+ {
+ return open;
+ }
+ set
+ {
+ open = value;
+ }
+ }
#endregion
#region Methods: protected
-
protected void OnGUI()
{
try
{
- if (!BuildOverlay.Visible || this.resources.Count == 0 || EditorLogic.fetch.editorScreen != EditorLogic.EditorScreen.Parts)
+ if (!Visible || resources.Count == 0 || EditorLogic.fetch.editorScreen != EditorScreen.Parts)
{
return;
}
- this.open = GUI.Toggle(this.tabPosition, this.open, this.tabContent, BuildOverlay.TabStyle);
- if (this.openPercent > 0.0)
- {
- this.windowPosition = GUILayout.Window(this.GetInstanceID(), this.windowPosition, this.Window, String.Empty, BuildOverlay.WindowStyle);
+ open = GUI.Toggle(tabPosition, open, tabContent, BuildOverlay.TabStyle);
+ if (openPercent > 0.0)
+ {
+ windowPosition = GUILayout.Window(GetInstanceID(), windowPosition, Window, String.Empty, BuildOverlay.WindowStyle);
}
}
catch (Exception ex)
@@ -91,8 +95,8 @@
{
try
{
- this.tabContent = new GUIContent("RESOURCES");
- this.tabSize = BuildOverlay.TabStyle.CalcSize(this.tabContent);
+ tabContent = new GUIContent("RESOURCES");
+ tabSize = BuildOverlay.TabStyle.CalcSize(tabContent);
}
catch (Exception ex)
{
@@ -104,71 +108,79 @@
{
try
{
- if (!BuildOverlay.Visible)
+ if (!Visible)
{
return;
}
- this.SetResources();
- this.SetSlidePosition();
- }
- catch (Exception ex)
- {
- Logger.Exception(ex);
- }
- }
-
+ SetResources();
+ SetSlidePosition();
+ }
+ catch (Exception ex)
+ {
+ Logger.Exception(ex);
+ }
+ }
#endregion
#region Methods: private
+ private static Part part;
+ private static PartResource partResource;
private void SetResources()
{
- var previousCount = this.resources.Count;
- this.resources.Clear();
- foreach (var resource in EditorLogic.fetch.ship.parts.SelectMany(p => p.Resources.list).Where(r => r.amount > 0.0))
- {
- if (this.resources.ContainsKey(resource.info.id))
- {
- this.resources[resource.info.id].Amount += resource.amount;
- }
- else
- {
- this.resources.Add(resource.info.id, new ResourceInfoItem(resource));
- }
- }
-
- if (this.resources.Count < previousCount)
- {
- this.windowPosition.height = 0;
+ int previousCount = resources.Count;
+ resources.Clear();
+
+ for (int i = 0; i < EditorLogic.fetch.ship.parts.Count; ++i)
+ {
+ part = EditorLogic.fetch.ship.parts[i];
+ for (int j = 0; j < part.Resources.list.Count; ++j)
+ {
+ partResource = part.Resources.list[j];
+
+ if (resources.ContainsKey(partResource.info.id))
+ {
+ resources[partResource.info.id].Amount += partResource.amount;
+ }
+ else
+ {
+ resources.Add(partResource.info.id, new ResourceInfoItem(partResource));
+ }
+ }
+ }
+
+ if (resources.Count < previousCount)
+ {
+ windowPosition.height = 0;
}
}
private void SetSlidePosition()
{
- if (this.open && this.openPercent < 1.0f)
- {
- this.openPercent = Mathf.Clamp(this.openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
- }
- else if (!this.open && this.openPercent > 0.0f)
- {
- this.openPercent = Mathf.Clamp(this.openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
- }
-
- this.windowPosition.x = BuildOverlay.BuildOverlayVessel.WindowPosition.xMax + 5.0f;
- this.windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - this.windowPosition.height, this.openPercent);
- this.tabPosition.width = this.tabSize.x;
- this.tabPosition.height = this.tabSize.y;
- this.tabPosition.x = this.windowPosition.x;
- this.tabPosition.y = this.windowPosition.y - this.tabPosition.height;
+ if (open && openPercent < 1.0f)
+ {
+ openPercent = Mathf.Clamp(openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
+ }
+ else if (!open && openPercent > 0.0f)
+ {
+ openPercent = Mathf.Clamp(openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
+ }
+
+ windowPosition.x = BuildOverlay.BuildOverlayVessel.WindowPosition.xMax + 5.0f;
+ windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - windowPosition.height, openPercent);
+ tabPosition.width = tabSize.x;
+ tabPosition.height = tabSize.y;
+ tabPosition.x = windowPosition.x;
+ tabPosition.y = windowPosition.y - tabPosition.height;
}
private void Window(int windowId)
{
try
{
- var firstItem = true;
- foreach (var resource in this.resources)
+ bool firstItem = true;
+ foreach (KeyValuePair<int, ResourceInfoItem> resource in resources)
{
if (!firstItem)
{
@@ -197,7 +209,6 @@
Logger.Exception(ex);
}
}
-
#endregion
}
}
--- a/KerbalEngineer/Editor/BuildOverlayVessel.cs
+++ b/KerbalEngineer/Editor/BuildOverlayVessel.cs
@@ -18,23 +18,26 @@
//
#region Using Directives
-
-using System;
-using System.Collections.Generic;
-
-using KerbalEngineer.Extensions;
-using KerbalEngineer.VesselSimulator;
-
-using UnityEngine;
-
#endregion
namespace KerbalEngineer.Editor
{
+ #region Using Directives
+ using System;
+ using System.Collections.Generic;
+ using Helpers;
+ using UnityEngine;
+ using VesselSimulator;
+
+ #endregion
+
public class BuildOverlayVessel : MonoBehaviour
{
+ #region Constants
+ private const float Width = 175.0f;
+ #endregion
+
#region Fields
-
private static bool visible = true;
private readonly List<PartInfoItem> infoItems = new List<PartInfoItem>();
@@ -45,46 +48,82 @@
private GUIContent tabContent;
private Rect tabPosition;
private Vector2 tabSize;
- private Rect windowPosition = new Rect(300.0f, 0.0f, BuildOverlay.MinimumWidth, 0.0f);
-
+ private Rect windowPosition = new Rect(330.0f, 0.0f, Width, 0.0f);
#endregion
#region Properties
-
public static bool Visible
{
- get { return visible; }
- set { visible = value; }
+ get
+ {
+ return visible;
+ }
+ set
+ {
+ visible = value;
+ }
}
public bool Open
{
- get { return this.open; }
- set { this.open = value; }
+ get
+ {
+ return open;
+ }
+ set
+ {
+ open = value;
+ }
}
public Rect WindowPosition
{
- get { return this.windowPosition; }
- }
-
- #endregion
-
- #region Methods: protected
+ get
+ {
+ return windowPosition;
+ }
+ }
+
+ public float WindowX
+ {
+ get
+ {
+ return windowPosition.x;
+ }
+ set
+ {
+ windowPosition.x = value;
+ }
+ }
+ #endregion
+
+ #region Methods
+ protected void Awake()
+ {
+ try
+ {
+ SimManager.OnReady -= GetStageInfo;
+ SimManager.OnReady += GetStageInfo;
+ }
+ catch (Exception ex)
+ {
+ Logger.Exception(ex);
+ }
+ }
protected void OnGUI()
{
try
{
- if (!Visible || EditorLogic.startPod == null || this.lastStage == null || EditorLogic.fetch.editorScreen != EditorLogic.EditorScreen.Parts)
+ if (!Visible || EditorLogic.RootPart == null || EditorLogic.fetch.editorScreen != EditorScreen.Parts)
{
return;
}
- this.open = GUI.Toggle(this.tabPosition, this.open, this.tabContent, BuildOverlay.TabStyle);
- if (this.openPercent > 0.0)
- {
- this.windowPosition = GUILayout.Window(this.GetInstanceID(), this.windowPosition, this.VesselWindow, String.Empty, BuildOverlay.WindowStyle);
+ open = GUI.Toggle(tabPosition, open, tabContent, BuildOverlay.TabStyle);
+ if (openPercent > 0.0)
+ {
+ windowPosition = GUILayout.Window(GetInstanceID(), windowPosition, VesselWindow, String.Empty, BuildOverlay.WindowStyle);
}
}
catch (Exception ex)
@@ -97,8 +136,8 @@
{
try
{
- this.tabContent = new GUIContent("VESSEL");
- this.tabSize = BuildOverlay.TabStyle.CalcSize(this.tabContent);
+ tabContent = new GUIContent("VESSEL");
+ tabSize = BuildOverlay.TabStyle.CalcSize(tabContent);
}
catch (Exception ex)
{
@@ -110,44 +149,49 @@
{
try
{
- if (!BuildOverlay.Visible || EditorLogic.startPod == null)
+ if (!Visible || EditorLogic.RootPart == null)
{
return;
}
- if (this.openPercent > 0.0)
- {
- this.SetVesselInfo();
- }
-
- this.SetSlidePosition();
- }
- catch (Exception ex)
- {
- Logger.Exception(ex);
- }
- }
-
- #endregion
-
- #region Methods: private
+ if (openPercent > 0.0)
+ {
+ SetVesselInfo();
+ }
+
+ SetSlidePosition();
+ }
+ catch (Exception ex)
+ {
+ Logger.Exception(ex);
+ }
+ }
+
+ private void GetStageInfo()
+ {
+ lastStage = SimManager.LastStage;
+ }
private void SetSlidePosition()
{
- if (this.open && this.openPercent < 1.0f)
- {
- this.openPercent = Mathf.Clamp(this.openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
- }
- else if (!this.open && this.openPercent > 0.0f)
- {
- this.openPercent = Mathf.Clamp(this.openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
- }
-
- this.windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - this.windowPosition.height, this.openPercent);
- this.tabPosition.width = this.tabSize.x;
- this.tabPosition.height = this.tabSize.y;
- this.tabPosition.x = this.windowPosition.x;
- this.tabPosition.y = this.windowPosition.y - this.tabPosition.height;
+ if (open && openPercent < 1.0f)
+ {
+ openPercent = Mathf.Clamp(openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
+ }
+ else if (!open && openPercent > 0.0f)
+ {
+ openPercent = Mathf.Clamp(openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
+ }
+
+ windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - windowPosition.height, openPercent);
+ if (windowPosition.width < Width)
+ {
+ windowPosition.width = Width;
+ }
+ tabPosition.width = tabSize.x;
+ tabPosition.height = tabSize.y;
+ tabPosition.x = windowPosition.x;
+ tabPosition.y = windowPosition.y - tabPosition.height;
}
private void SetVesselInfo()
@@ -156,7 +200,7 @@
if (BuildAdvanced.Instance.ShowAtmosphericDetails)
{
- SimManager.Atmosphere = CelestialBodies.SelectedBody.Atmosphere * 0.01;
+ SimManager.Atmosphere = CelestialBodies.SelectedBody.GetAtmospheres(BuildAdvanced.Altitude);
}
else
{
@@ -166,18 +210,14 @@
SimManager.RequestSimulation();
SimManager.TryStartSimulation();
- if (SimManager.ResultsReady())
- {
- this.lastStage = SimManager.LastStage;
- }
-
- if (this.lastStage != null)
- {
- this.infoItems.Clear();
- this.infoItems.Add(new PartInfoItem("Delta-V", this.lastStage.totalDeltaV.ToString("N0") + "m/s"));
- this.infoItems.Add(new PartInfoItem("Mass", this.lastStage.totalMass.ToMass()));
- this.infoItems.Add(new PartInfoItem("TWR", this.lastStage.thrustToWeight.ToString("F2")));
- this.infoItems.Add(new PartInfoItem("Parts", this.lastStage.partCount.ToString("N0")));
+ if (lastStage != null)
+ {
+ PartInfoItem.Release(infoItems);
+ infoItems.Clear();
+ infoItems.Add(PartInfoItem.Create("Delta-V", lastStage.deltaV.ToString("N0") + " / " + lastStage.totalDeltaV.ToString("N0") + "m/s"));
+ infoItems.Add(PartInfoItem.Create("Mass", Units.ToMass(lastStage.mass, lastStage.totalMass)));
+ infoItems.Add(PartInfoItem.Create("TWR", lastStage.thrustToWeight.ToString("F2") + " (" + lastStage.maxThrustToWeight.ToString("F2") + ")"));
+ infoItems.Add(PartInfoItem.Create("Parts", lastStage.partCount + " / " + lastStage.totalPartCount));
}
}
@@ -185,8 +225,8 @@
{
try
{
- var firstItem = true;
- foreach (var item in this.infoItems)
+ bool firstItem = true;
+ foreach (PartInfoItem item in infoItems)
{
if (!firstItem)
{
@@ -198,7 +238,7 @@
if (item.Value != null)
{
GUILayout.Label(item.Name + ":", BuildOverlay.NameStyle);
- GUILayout.Space(50.0f);
+ GUILayout.FlexibleSpace();
GUILayout.Label(item.Value, BuildOverlay.ValueStyle);
}
else
@@ -213,7 +253,6 @@
Logger.Exception(ex);
}
}
-
#endregion
}
}
--- a/KerbalEngineer/Editor/BuildToolbar.cs
+++ b/KerbalEngineer/Editor/BuildToolbar.cs
@@ -42,6 +42,14 @@
{
GameEvents.onGUIApplicationLauncherReady.Add(this.OnGuiAppLauncherReady);
Logger.Log("BuildToolbar->Awake");
+ }
+
+ private void Start()
+ {
+ if (button == null)
+ {
+ OnGuiAppLauncherReady();
+ }
}
private void OnDestroy()
--- a/KerbalEngineer/Editor/PartInfoItem.cs
+++ b/KerbalEngineer/Editor/PartInfoItem.cs
@@ -19,29 +19,69 @@
namespace KerbalEngineer.Editor
{
+ using System.Collections.Generic;
+ using VesselSimulator;
+
public class PartInfoItem
{
- #region Constructors
-
- public PartInfoItem(string name)
- {
- this.Name = name;
- }
-
- public PartInfoItem(string name, string value)
- {
- this.Name = name;
- this.Value = value;
- }
-
- #endregion
-
- #region Properties
+ private static readonly Pool<PartInfoItem> pool = new Pool<PartInfoItem>(Create, Reset);
public string Name { get; set; }
public string Value { get; set; }
- #endregion
+ private static PartInfoItem Create()
+ {
+ return new PartInfoItem();
+ }
+
+ public void Release()
+ {
+ pool.Release(this);
+ }
+
+ public static void Release(List<PartInfoItem> objList)
+ {
+ for (int i = 0; i < objList.Count; ++i)
+ {
+ objList[i].Release();
+ }
+ }
+
+ private static void Reset(PartInfoItem obj)
+ {
+ obj.Name = string.Empty;
+ obj.Value = string.Empty;
+ }
+
+ public static PartInfoItem Create(string name)
+ {
+ return New(name);
+ }
+
+ public static PartInfoItem Create(string name, string value)
+ {
+ return New(name, value);
+ }
+
+ public static PartInfoItem New(string name)
+ {
+ PartInfoItem obj = pool.Borrow();
+
+ obj.Name = name;
+ obj.Value = string.Empty;
+
+ return obj;
+ }
+
+ public static PartInfoItem New(string name, string value)
+ {
+ PartInfoItem obj = pool.Borrow();
+
+ obj.Name = name;
+ obj.Value = value;
+
+ return obj;
+ }
}
}
--- a/KerbalEngineer/EngineerGlobals.cs
+++ b/KerbalEngineer/EngineerGlobals.cs
@@ -33,7 +33,7 @@
/// <summary>
/// Current version of the Kerbal Engineer assembly.
/// </summary>
- public const string AssemblyVersion = "1.0.11";
+ public const string AssemblyVersion = "1.0.16.6";
#endregion
--- 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,17 +17,16 @@
// 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;
+ }
public static string ToAcceleration(this double value)
{
@@ -44,9 +43,19 @@
return Units.ToDistance(value);
}
+ public static string ToFlux(this double 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)
@@ -69,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,9 +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 ToMach(this float value)
+ {
+ return Units.ToMach(value);
}
public static string ToMass(this float value)
@@ -69,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/OrbitExtensions.cs
+++ b/KerbalEngineer/Extensions/OrbitExtensions.cs
@@ -51,13 +51,18 @@
public static double GetAngleToPrograde(this Orbit orbit)
{
+ return GetAngleToPrograde(orbit, Planetarium.GetUniversalTime());
+ }
+
+ public static double GetAngleToPrograde(this Orbit orbit, double universalTime)
+ {
if (orbit.referenceBody == CelestialBodies.SystemBody.CelestialBody)
{
return 0.0;
}
- var angle = AngleHelper.GetAngleBetweenVectors(orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()),
- Vector3d.Exclude(orbit.GetOrbitNormal(), orbit.referenceBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime())));
+ var angle = AngleHelper.GetAngleBetweenVectors(orbit.getRelativePositionAtUT(universalTime),
+ Vector3d.Exclude(orbit.GetOrbitNormal(), orbit.referenceBody.orbit.getRelativePositionAtUT(universalTime)));
angle = AngleHelper.Clamp360(angle - 90.0);
@@ -66,13 +71,18 @@
public static double GetAngleToRetrograde(this Orbit orbit)
{
+ return GetAngleToRetrograde(orbit, Planetarium.GetUniversalTime());
+ }
+
+ public static double GetAngleToRetrograde(this Orbit orbit, double universalTime)
+ {
if (orbit.referenceBody == CelestialBodies.SystemBody.CelestialBody)
{
return 0.0;
}
- var angle = AngleHelper.GetAngleBetweenVectors(orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()),
- Vector3d.Exclude(orbit.GetOrbitNormal(), orbit.referenceBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime())));
+ var angle = AngleHelper.GetAngleBetweenVectors(orbit.getRelativePositionAtUT(universalTime),
+ Vector3d.Exclude(orbit.GetOrbitNormal(), orbit.referenceBody.orbit.getRelativePositionAtUT(universalTime)));
angle = AngleHelper.Clamp360(angle + 90.0);
--- a/KerbalEngineer/Extensions/PartExtensions.cs
+++ b/KerbalEngineer/Extensions/PartExtensions.cs
@@ -17,19 +17,17 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-#endregion
-
namespace KerbalEngineer.Extensions
{
+ using System;
+ using System.Collections.Generic;
+ using CompoundParts;
+
public static class PartExtensions
{
- #region Methods: public
+ //private static Part cachePart;
+ //private static PartModule cachePartModule;
+ //private static PartResource cachePartResource;
/// <summary>
/// Gets whether the part contains a specific resource.
@@ -44,7 +42,14 @@
/// </summary>
public static bool ContainsResources(this Part part)
{
- return part.Resources.list.Count(p => p.amount > 0d) > 0;
+ for (int i = 0; i < part.Resources.list.Count; ++i)
+ {
+ if (part.Resources.list[i].amount > 0.0)
+ {
+ return true;
+ }
+ }
+ return false;
}
/// <summary>
@@ -52,13 +57,16 @@
/// </summary>
public static bool EngineHasFuel(this Part part)
{
- if (part.HasModule<ModuleEngines>())
- {
- return part.GetModuleEngines().getFlameoutState;
- }
- if (part.HasModule<MultiModeEngine>())
- {
- return part.GetModuleMultiModeEngine().getFlameoutState;
+ PartModule cachePartModule = GetModule<ModuleEngines>(part);
+ if (cachePartModule != null)
+ {
+ return (cachePartModule as ModuleEngines).getFlameoutState;
+ }
+
+ cachePartModule = GetModuleMultiModeEngine(part);
+ if (cachePartModule != null)
+ {
+ return (cachePartModule as ModuleEnginesFX).getFlameoutState;
}
return false;
@@ -69,7 +77,7 @@
/// </summary>
public static double GetCostDry(this Part part)
{
- return part.partInfo.cost - GetResourceCostMax(part) + part.GetModuleCosts();
+ return part.partInfo.cost - GetResourceCostMax(part) + part.GetModuleCosts(0.0f);
}
/// <summary>
@@ -77,7 +85,23 @@
/// </summary>
public static double GetCostMax(this Part part)
{
- return part.partInfo.cost + part.GetModuleCosts();
+ return part.partInfo.cost + part.GetModuleCosts(0.0f);
+ }
+
+ /// <summary>
+ /// Gets the cost of the part modules
+ /// Same as stock but without mem allocation
+ /// </summary>
+ public static double GetModuleCostsNoAlloc(this Part part, float defaultCost)
+ {
+ float cost = 0f;
+ for (int i = 0; i < part.Modules.Count; i++)
+ {
+ PartModule pm = part.Modules[i];
+ if (pm is IPartCostModifier)
+ cost += (pm as IPartCostModifier).GetModuleCost(defaultCost);
+ }
+ return cost;
}
/// <summary>
@@ -85,7 +109,7 @@
/// </summary>
public static double GetCostWet(this Part part)
{
- return part.partInfo.cost - GetResourceCostInverted(part) + part.GetModuleCosts();
+ return part.partInfo.cost - GetResourceCostInverted(part) + part.GetModuleCostsNoAlloc(0.0f); // part.GetModuleCosts allocate 44B per call.
}
/// <summary>
@@ -101,20 +125,19 @@
/// </summary>
public static double GetMaxThrust(this Part part)
{
- if (part.HasModule<ModuleEngines>())
- {
- return part.GetModuleEngines().maxThrust;
- }
- if (part.HasModule<MultiModeEngine>())
- {
- return part.GetModuleMultiModeEngine().maxThrust;
- }
- if (part.HasModule<ModuleEnginesFX>())
- {
- return part.GetModuleEnginesFx().maxThrust;
- }
-
- return 0d;
+ PartModule cachePartModule = GetModule<ModuleEngines>(part);
+ if (cachePartModule != null)
+ {
+ return (cachePartModule as ModuleEngines).maxThrust;
+ }
+
+ cachePartModule = GetModuleMultiModeEngine(part) ?? GetModule<ModuleEnginesFX>(part);
+ if (cachePartModule != null)
+ {
+ return (cachePartModule as ModuleEnginesFX).maxThrust;
+ }
+
+ return 0.0;
}
/// <summary>
@@ -122,7 +145,13 @@
/// </summary>
public static T GetModule<T>(this Part part) where T : PartModule
{
- return part.Modules.OfType<T>().FirstOrDefault();
+ for (int i = 0; i < part.Modules.Count; i++)
+ {
+ PartModule pm = part.Modules[i];
+ if (pm is T)
+ return (T)pm;
+ }
+ return null;
}
/// <summary>
@@ -130,7 +159,7 @@
/// </summary>
public static T GetModule<T>(this Part part, string className) where T : PartModule
{
- return (T)Convert.ChangeType(part.Modules[className], typeof(T));
+ return part.Modules[className] as T;
}
/// <summary>
@@ -138,7 +167,7 @@
/// </summary>
public static T GetModule<T>(this Part part, int classId) where T : PartModule
{
- return (T)Convert.ChangeType(part.Modules[classId], typeof(T));
+ return part.Modules[classId] as T;
}
/// <summary>
@@ -146,7 +175,7 @@
/// </summary>
public static ModuleAlternator GetModuleAlternator(this Part part)
{
- return part.GetModule<ModuleAlternator>();
+ return GetModule<ModuleAlternator>(part);
}
/// <summary>
@@ -154,7 +183,7 @@
/// </summary>
public static ModuleDeployableSolarPanel GetModuleDeployableSolarPanel(this Part part)
{
- return part.GetModule<ModuleDeployableSolarPanel>();
+ return GetModule<ModuleDeployableSolarPanel>(part);
}
/// <summary>
@@ -162,12 +191,12 @@
/// </summary>
public static ModuleEngines GetModuleEngines(this Part part)
{
- return part.GetModule<ModuleEngines>();
+ return GetModule<ModuleEngines>(part);
}
public static ModuleEnginesFX GetModuleEnginesFx(this Part part)
{
- return part.GetModule<ModuleEnginesFX>();
+ return GetModule<ModuleEnginesFX>(part);
}
/// <summary>
@@ -175,7 +204,7 @@
/// </summary>
public static ModuleGenerator GetModuleGenerator(this Part part)
{
- return part.GetModule<ModuleGenerator>();
+ return GetModule<ModuleGenerator>(part);
}
/// <summary>
@@ -183,7 +212,7 @@
/// </summary>
public static ModuleGimbal GetModuleGimbal(this Part part)
{
- return part.GetModule<ModuleGimbal>();
+ return GetModule<ModuleGimbal>(part);
}
/// <summary>
@@ -191,8 +220,17 @@
/// </summary>
public static ModuleEnginesFX GetModuleMultiModeEngine(this Part part)
{
- var mode = part.GetModule<MultiModeEngine>().mode;
- return part.Modules.OfType<ModuleEnginesFX>().FirstOrDefault(engine => engine.engineID == mode);
+ 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;
+ }
+ }
+ return null;
}
/// <summary>
@@ -200,12 +238,12 @@
/// </summary>
public static ModuleParachute GetModuleParachute(this Part part)
{
- return part.GetModule<ModuleParachute>();
+ return GetModule<ModuleParachute>(part);
}
public static ModuleRCS GetModuleRcs(this Part part)
{
- return part.GetModule<ModuleRCS>();
+ return GetModule<ModuleRCS>(part);
}
/// <summary>
@@ -213,19 +251,30 @@
/// </summary>
public static List<T> GetModules<T>(this Part part) where T : PartModule
{
- return part.Modules.OfType<T>().ToList();
+ List<T> list = new List<T>();
+ for (int i = 0; i < part.Modules.Count; ++i)
+ {
+ T module = part.Modules[i] as T;
+ if (module != null)
+ {
+ list.Add(module);
+ }
+ }
+ return list;
}
public static ProtoModuleDecoupler GetProtoModuleDecoupler(this Part part)
{
- if (HasModule<ModuleDecouple>(part))
- {
- return new ProtoModuleDecoupler(GetModule<ModuleDecouple>(part));
- }
- if (HasModule<ModuleAnchoredDecoupler>(part))
- {
- return new ProtoModuleDecoupler(GetModule<ModuleAnchoredDecoupler>(part));
- }
+ PartModule cachePartModule = GetModule<ModuleDecouple>(part);
+ if (cachePartModule == null)
+ {
+ cachePartModule = GetModule<ModuleAnchoredDecoupler>(part);
+ }
+ if (cachePartModule != null)
+ {
+ return new ProtoModuleDecoupler(cachePartModule);
+ }
+
return null;
}
@@ -234,18 +283,18 @@
/// </summary>
public static ProtoModuleEngine GetProtoModuleEngine(this Part part)
{
- if (HasModule<ModuleEngines>(part))
- {
- return new ProtoModuleEngine(GetModule<ModuleEngines>(part));
- }
- if (HasModule<MultiModeEngine>(part))
- {
- return new ProtoModuleEngine(GetModuleMultiModeEngine(part));
- }
- if (HasModule<ModuleEnginesFX>(part))
- {
- return new ProtoModuleEngine(GetModule<ModuleEnginesFX>(part));
- }
+ PartModule cachePartModule = GetModule<ModuleEngines>(part);
+ if (cachePartModule != null)
+ {
+ return new ProtoModuleEngine(cachePartModule);
+ }
+
+ cachePartModule = GetModuleMultiModeEngine(part) ?? GetModule<ModuleEnginesFX>(part);
+ if (cachePartModule != null)
+ {
+ return new ProtoModuleEngine(cachePartModule);
+ }
+
return null;
}
@@ -254,7 +303,13 @@
/// </summary>
public static double GetResourceCost(this Part part)
{
- return part.Resources.list.Sum(r => r.amount * r.info.unitCost);
+ double cost = 0.0;
+ for (int i = 0; i < part.Resources.list.Count; ++i)
+ {
+ PartResource cachePartResource = part.Resources.list[i];
+ cost = cost + (cachePartResource.amount * cachePartResource.info.unitCost);
+ }
+ return cost;
}
/// <summary>
@@ -262,7 +317,13 @@
/// </summary>
public static double GetResourceCostInverted(this Part part)
{
- return part.Resources.list.Sum(r => (r.maxAmount - r.amount) * r.info.unitCost);
+ double sum = 0;
+ for (int i = 0; i < part.Resources.list.Count; i++)
+ {
+ PartResource r = part.Resources.list[i];
+ sum += (r.maxAmount - r.amount) * r.info.unitCost;
+ }
+ return sum;
}
/// <summary>
@@ -270,7 +331,13 @@
/// </summary>
public static double GetResourceCostMax(this Part part)
{
- return part.Resources.list.Sum(r => r.maxAmount * r.info.unitCost);
+ double cost = 0.0;
+ for (int i = 0; i < part.Resources.list.Count; ++i)
+ {
+ PartResource cachePartResource = part.Resources.list[i];
+ cost = cost + (cachePartResource.maxAmount * cachePartResource.info.unitCost);
+ }
+ return cost;
}
/// <summary>
@@ -278,20 +345,19 @@
/// </summary>
public static double GetSpecificImpulse(this Part part, float atmosphere)
{
- if (part.HasModule<ModuleEngines>())
- {
- return part.GetModuleEngines().atmosphereCurve.Evaluate(atmosphere);
- }
- if (part.HasModule<MultiModeEngine>())
- {
- return part.GetModuleMultiModeEngine().atmosphereCurve.Evaluate(atmosphere);
- }
- if (part.HasModule<ModuleEnginesFX>())
- {
- return part.GetModuleEnginesFx().atmosphereCurve.Evaluate(atmosphere);
- }
-
- return 0d;
+ PartModule cachePartModule = GetModule<ModuleEngines>(part);
+ if (cachePartModule != null)
+ {
+ return (cachePartModule as ModuleEngines).atmosphereCurve.Evaluate(atmosphere);
+ }
+
+ cachePartModule = GetModuleMultiModeEngine(part) ?? GetModule<ModuleEnginesFX>(part);
+ if (cachePartModule != null)
+ {
+ return (cachePartModule as ModuleEnginesFX).atmosphereCurve.Evaluate(atmosphere);
+ }
+
+ return 0.0;
}
/// <summary>
@@ -307,7 +373,12 @@
/// </summary>
public static bool HasModule<T>(this Part part) where T : PartModule
{
- return part.Modules.OfType<T>().Any();
+ for (int i = 0; i < part.Modules.Count; i++)
+ {
+ if (part.Modules[i] is T)
+ return true;
+ }
+ return false;
}
/// <summary>
@@ -315,7 +386,13 @@
/// </summary>
public static bool HasModule<T>(this Part part, Func<T, bool> predicate) where T : PartModule
{
- return part.Modules.OfType<T>().Any(predicate);
+ for (int i = 0; i < part.Modules.Count; i++)
+ {
+ PartModule pm = part.Modules[i];
+ if (pm is T && predicate(pm as T))
+ return true;
+ }
+ return false;
}
/// <summary>
@@ -339,7 +416,8 @@
/// </summary>
public static bool HasOneShotAnimation(this Part part)
{
- return part.HasModule<ModuleAnimateGeneric>() && part.GetModule<ModuleAnimateGeneric>().isOneShot;
+ PartModule cachePartModule = GetModule<ModuleAnimateGeneric>(part);
+ return cachePartModule != null && (cachePartModule as ModuleAnimateGeneric).isOneShot;
}
/// <summary>
@@ -347,7 +425,7 @@
/// </summary>
public static bool IsCommandModule(this Part part)
{
- return part.HasModule<ModuleCommand>();
+ return HasModule<ModuleCommand>(part);
}
/// <summary>
@@ -355,7 +433,7 @@
/// </summary>
public static bool IsDecoupledInStage(this Part part, int stage)
{
- if ((part.IsDecoupler() || part.IsLaunchClamp()) && part.inverseStage == stage)
+ if ((IsDecoupler(part) || IsLaunchClamp(part)) && part.inverseStage == stage)
{
return true;
}
@@ -363,7 +441,7 @@
{
return false;
}
- return part.parent.IsDecoupledInStage(stage);
+ return IsDecoupledInStage(part.parent, stage);
}
/// <summary>
@@ -371,7 +449,7 @@
/// </summary>
public static bool IsDecoupler(this Part part)
{
- return part.HasModule<ModuleDecouple>() || part.HasModule<ModuleAnchoredDecoupler>();
+ return HasModule<ModuleDecouple>(part) || HasModule<ModuleAnchoredDecoupler>(part);
}
/// <summary>
@@ -379,7 +457,7 @@
/// </summary>
public static bool IsEngine(this Part part)
{
- return part.HasModule<ModuleEngines>() || part.HasModule<ModuleEnginesFX>();
+ return HasModule<ModuleEngines>(part) || HasModule<ModuleEnginesFX>(part);
}
/// <summary>
@@ -387,7 +465,7 @@
/// </summary>
public static bool IsFuelLine(this Part part)
{
- return (part is FuelLine);
+ return HasModule<CModuleFuelLine>(part);
}
/// <summary>
@@ -395,7 +473,7 @@
/// </summary>
public static bool IsGenerator(this Part part)
{
- return part.HasModule<ModuleGenerator>();
+ return HasModule<ModuleGenerator>(part);
}
/// <summary>
@@ -403,7 +481,7 @@
/// </summary>
public static bool IsLaunchClamp(this Part part)
{
- return part.HasModule<LaunchClamp>();
+ return HasModule<LaunchClamp>(part);
}
/// <summary>
@@ -411,7 +489,7 @@
/// </summary>
public static bool IsParachute(this Part part)
{
- return part.HasModule<ModuleParachute>();
+ return HasModule<ModuleParachute>(part);
}
/// <summary>
@@ -419,13 +497,13 @@
/// </summary>
public static bool IsPrimary(this Part part, List<Part> partsList, PartModule module)
{
- foreach (var vesselPart in partsList)
- {
+ for (int i = 0; i < partsList.Count; i++)
+ {
+ var vesselPart = partsList[i];
if (!vesselPart.HasModule(module.ClassID))
{
continue;
}
-
if (vesselPart == part)
{
return true;
@@ -438,7 +516,7 @@
public static bool IsRcsModule(this Part part)
{
- return part.HasModule<ModuleRCS>();
+ return HasModule<ModuleRCS>(part);
}
/// <summary>
@@ -446,7 +524,7 @@
/// </summary>
public static bool IsSepratron(this Part part)
{
- return (part.IsSolidRocket() && part.ActivatesEvenIfDisconnected && part.IsDecoupledInStage(part.inverseStage));
+ return IsSolidRocket(part) && part.ActivatesEvenIfDisconnected && IsDecoupledInStage(part, part.inverseStage);
}
/// <summary>
@@ -454,7 +532,7 @@
/// </summary>
public static bool IsSolarPanel(this Part part)
{
- return part.HasModule<ModuleDeployableSolarPanel>();
+ return HasModule<ModuleDeployableSolarPanel>(part);
}
/// <summary>
@@ -462,160 +540,106 @@
/// </summary>
public static bool IsSolidRocket(this Part part)
{
- return part.HasModule<ModuleEngines>() && part.GetModuleEngines().throttleLocked;
- }
-
- #endregion
-
- #region Nested Type: ProtoModuleDecoupler
+ return (part.HasModule<ModuleEngines>() && part.GetModuleEngines().throttleLocked) || (part.HasModule<ModuleEnginesFX>() && part.GetModuleEnginesFx().throttleLocked);
+ }
public class ProtoModuleDecoupler
{
- #region Fields
-
private readonly PartModule module;
- #endregion
-
- #region Constructors
-
public ProtoModuleDecoupler(PartModule module)
{
this.module = module;
if (this.module is ModuleDecouple)
{
- this.SetModuleDecouple();
+ SetModuleDecouple();
}
else if (this.module is ModuleAnchoredDecoupler)
{
- this.SetModuleAnchoredDecoupler();
- }
- }
-
- #endregion
-
- #region Properties
+ SetModuleAnchoredDecoupler();
+ }
+ }
public double EjectionForce { get; private set; }
public bool IsOmniDecoupler { get; private set; }
- #endregion
-
- #region Methods: private
-
private void SetModuleAnchoredDecoupler()
{
- var decoupler = this.module as ModuleAnchoredDecoupler;
+ ModuleAnchoredDecoupler decoupler = module as ModuleAnchoredDecoupler;
if (decoupler == null)
{
return;
}
- this.EjectionForce = decoupler.ejectionForce;
+ EjectionForce = decoupler.ejectionForce;
}
private void SetModuleDecouple()
{
- var decoupler = this.module as ModuleDecouple;
+ ModuleDecouple decoupler = module as ModuleDecouple;
if (decoupler == null)
{
return;
}
- this.EjectionForce = decoupler.ejectionForce;
- this.IsOmniDecoupler = decoupler.isOmniDecoupler;
- }
-
- #endregion
- }
-
- #endregion
-
- #region Nested Type: ProtoModuleEngine
+ EjectionForce = decoupler.ejectionForce;
+ IsOmniDecoupler = decoupler.isOmniDecoupler;
+ }
+ }
public class ProtoModuleEngine
{
- #region Fields
-
private readonly PartModule module;
- #endregion
-
- #region Constructors
-
public ProtoModuleEngine(PartModule module)
{
this.module = module;
if (module is ModuleEngines)
{
- this.SetModuleEngines();
- }
- else if (module is ModuleEnginesFX)
- {
- this.SetModuleEnginesFx();
- }
- }
-
- #endregion
-
- #region Properties
+ SetModuleEngines();
+ }
+ }
public double MaximumThrust { get; private set; }
public double MinimumThrust { get; private set; }
public List<Propellant> Propellants { get; private set; }
- #endregion
-
- #region Methods: public
-
public float GetSpecificImpulse(float atmosphere)
{
- if (this.module is ModuleEngines)
- {
- return (this.module as ModuleEngines).atmosphereCurve.Evaluate(atmosphere);
- }
- if (this.module is ModuleEnginesFX)
- {
- return (this.module as ModuleEnginesFX).atmosphereCurve.Evaluate(atmosphere);
+ if (module is ModuleEngines)
+ {
+ return (module as ModuleEngines).atmosphereCurve.Evaluate(atmosphere);
}
return 0.0f;
}
- #endregion
-
- #region Methods: private
-
private void SetModuleEngines()
{
- var engine = this.module as ModuleEngines;
+ ModuleEngines engine = module as ModuleEngines;
if (engine == null)
{
return;
}
- this.MaximumThrust = engine.maxThrust * (engine.thrustPercentage * 0.01);
- this.MinimumThrust = engine.minThrust;
- this.Propellants = engine.propellants;
+ MaximumThrust = engine.maxThrust * (engine.thrustPercentage * 0.01);
+ MinimumThrust = engine.minThrust;
+ Propellants = engine.propellants;
}
private void SetModuleEnginesFx()
{
- var engine = this.module as ModuleEnginesFX;
+ ModuleEnginesFX engine = module as ModuleEnginesFX;
if (engine == null)
{
return;
}
- this.MaximumThrust = engine.maxThrust * (engine.thrustPercentage * 0.01);
- this.MinimumThrust = engine.minThrust;
- this.Propellants = engine.propellants;
- }
-
- #endregion
- }
-
- #endregion
+ 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/ActionMenu.cs
+++ b/KerbalEngineer/Flight/ActionMenu.cs
@@ -55,6 +55,14 @@
Logger.Log("ActionMenu was created.");
}
+ protected void Start()
+ {
+ if (button == null)
+ {
+ OnGuiAppLauncherReady();
+ }
+ }
+
protected void OnDestroy()
{
try
@@ -62,7 +70,10 @@
GameEvents.onGUIApplicationLauncherReady.Remove(this.OnGuiAppLauncherReady);
GameEvents.onHideUI.Remove(this.OnHide);
GameEvents.onShowUI.Remove(this.OnShow);
- ApplicationLauncher.Instance.RemoveModApplication(this.button);
+ if (button != null)
+ {
+ ApplicationLauncher.Instance.RemoveModApplication(this.button);
+ }
}
catch (Exception ex)
{
@@ -79,11 +90,11 @@
{
return;
}
- if (FlightEngineerCore.Instance != null && this.button.State == RUIToggleButton.ButtonState.DISABLED)
+ if (FlightEngineerCore.IsDisplayable && this.button.State == RUIToggleButton.ButtonState.DISABLED)
{
this.button.Enable();
}
- else if (FlightEngineerCore.Instance == null && this.button.State != RUIToggleButton.ButtonState.DISABLED)
+ else if (!FlightEngineerCore.IsDisplayable && this.button.State != RUIToggleButton.ButtonState.DISABLED)
{
this.button.Disable();
}
--- a/KerbalEngineer/Flight/ActionMenuGui.cs
+++ b/KerbalEngineer/Flight/ActionMenuGui.cs
@@ -132,7 +132,7 @@
{
try
{
- if (this.Hidden)
+ if (this.Hidden || !FlightEngineerCore.IsDisplayable)
{
return;
}
--- a/KerbalEngineer/Flight/DisplayStack.cs
+++ b/KerbalEngineer/Flight/DisplayStack.cs
@@ -33,6 +33,8 @@
namespace KerbalEngineer.Flight
{
+ using Upgradeables;
+
/// <summary>
/// Graphical controller for displaying stacked sections.
/// </summary>
@@ -150,7 +152,7 @@
{
try
{
- if (FlightEngineerCore.Instance == null)
+ if (!FlightEngineerCore.IsDisplayable)
{
return;
}
@@ -177,7 +179,7 @@
{
try
{
- if (FlightEngineerCore.Instance == null)
+ if (!FlightEngineerCore.IsDisplayable)
{
return;
}
--- a/KerbalEngineer/Flight/FlightEngineerCore.cs
+++ b/KerbalEngineer/Flight/FlightEngineerCore.cs
@@ -19,21 +19,28 @@
#region Using Directives
-using System;
-using System.Collections.Generic;
-
-using KerbalEngineer.Flight.Readouts;
-using KerbalEngineer.Flight.Sections;
-
-using UnityEngine;
-
#endregion
namespace KerbalEngineer.Flight
{
+ #region Using Directives
+
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using Extensions;
+ using Readouts;
+ using Sections;
+ using Settings;
+ using UnityEngine;
+ using VesselSimulator;
+
+ #endregion
+
/// <summary>
/// Core management system for the Flight Engineer.
/// </summary>
+ [KSPAddon(KSPAddon.Startup.Flight, false)]
public sealed class FlightEngineerCore : MonoBehaviour
{
#region Instance
@@ -45,7 +52,210 @@
#endregion
+ #region Fields
+
+ private static bool isCareerMode = true;
+ private static bool isKerbalLimited = true;
+ private static bool isTrackingStationLimited = true;
+
+ #endregion
+
#region Constructors
+
+ static FlightEngineerCore()
+ {
+ try
+ {
+ var handler = SettingHandler.Load("FlightEngineerCore.xml");
+ handler.Get("isCareerMode", ref isCareerMode);
+ handler.Get("isKerbalLimited", ref isKerbalLimited);
+ handler.Get("isTrackingStationLimited", ref isTrackingStationLimited);
+ }
+ catch (Exception ex)
+ {
+ Logger.Exception(ex);
+ }
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets and sets whether to the Flight Engineer should be run using career limitations.
+ /// </summary>
+ public static bool IsCareerMode
+ {
+ get { return isCareerMode; }
+ set
+ {
+ try
+ {
+ if (isCareerMode != value)
+ {
+ var handler = SettingHandler.Load("FlightEngineerCore.xml");
+ handler.Set("isCareerMode", value);
+ handler.Save("FlightEngineerCore.xml");
+ }
+ isCareerMode = value;
+ }
+ catch (Exception ex)
+ {
+ Logger.Exception(ex);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the FlightEngineer should be displayed.
+ /// </summary>
+ public static bool IsDisplayable
+ {
+ get
+ {
+ if (isCareerMode)
+ {
+ if (isKerbalLimited && FlightGlobals.ActiveVessel.GetVesselCrew().Exists(c => c.experienceTrait.TypeName == "Engineer"))
+ {
+ return true;
+ }
+ if (isTrackingStationLimited && ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.TrackingStation) == 1.0f)
+ {
+ return true;
+ }
+ return FlightGlobals.ActiveVessel.parts.Any(p => p.HasModule<FlightEngineerModule>());
+ }
+
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Gets and sets whether to the Flight Engineer should be kerbal limited.
+ /// </summary>
+ public static bool IsKerbalLimited
+ {
+ get { return isKerbalLimited; }
+ set
+ {
+ try
+ {
+ if (isKerbalLimited != value)
+ {
+ var handler = SettingHandler.Load("FlightEngineerCore.xml");
+ handler.Set("isKerbalLimited", value);
+ handler.Save("FlightEngineerCore.xml");
+ }
+ isKerbalLimited = value;
+ }
+ catch (Exception ex)
+ {
+ Logger.Exception(ex);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets and sets whether to the Flight Engineer should be tracking station limited.
+ /// </summary>
+ public static bool IsTrackingStationLimited
+ {
+ get { return isTrackingStationLimited; }
+ set
+ {
+ try
+ {
+ if (isTrackingStationLimited != value)
+ {
+ var handler = SettingHandler.Load("FlightEngineerCore.xml");
+ handler.Set("isTrackingStationLimited", value);
+ handler.Save("FlightEngineerCore.xml");
+ }
+ isTrackingStationLimited = value;
+ }
+ catch (Exception ex)
+ {
+ Logger.Exception(ex);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the editor windows for sections with open editors.
+ /// </summary>
+ public List<SectionEditor> SectionEditors { get; private set; }
+
+ /// <summary>
+ /// Gets the section windows for floating sections.
+ /// </summary>
+ public List<SectionWindow> SectionWindows { get; private set; }
+
+ /// <summary>
+ /// Gets the list of currently running updatable modules.
+ /// </summary>
+ public List<IUpdatable> UpdatableModules { get; private set; }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Creates a section editor, adds it to the FlightEngineerCore and returns a reference to it.
+ /// </summary>
+ public SectionEditor AddSectionEditor(SectionModule section)
+ {
+ try
+ {
+ var editor = this.gameObject.AddComponent<SectionEditor>();
+ editor.ParentSection = section;
+ editor.Position = new Rect(section.EditorPositionX, section.EditorPositionY, SectionEditor.Width, SectionEditor.Height);
+ this.SectionEditors.Add(editor);
+ return editor;
+ }
+ catch (Exception ex)
+ {
+ Logger.Exception(ex);
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Creates a section window, adds it to the FlightEngineerCore and returns a reference to it.
+ /// </summary>
+ public SectionWindow AddSectionWindow(SectionModule section)
+ {
+ try
+ {
+ var window = this.gameObject.AddComponent<SectionWindow>();
+ window.ParentSection = section;
+ window.WindowPosition = new Rect(section.FloatingPositionX, section.FloatingPositionY, 0, 0);
+ this.SectionWindows.Add(window);
+ return window;
+ }
+ catch (Exception ex)
+ {
+ Logger.Exception(ex);
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Adds an updatable object to be automatically updated every frame and will ignore duplicate objects.
+ /// </summary>
+ public void AddUpdatable(IUpdatable updatable)
+ {
+ try
+ {
+ if (!this.UpdatableModules.Contains(updatable))
+ {
+ this.UpdatableModules.Add(updatable);
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.Exception(ex);
+ }
+ }
/// <summary>
/// Create base Flight Engineer child objects.
@@ -59,11 +269,58 @@
this.SectionWindows = new List<SectionWindow>();
this.SectionEditors = new List<SectionEditor>();
this.UpdatableModules = new List<IUpdatable>();
+
+ SimManager.UpdateModSettings();
+
Logger.Log("FlightEngineerCore->Awake");
}
catch (Exception ex)
{
- Logger.Exception(ex, "FlightEngineerCore->Awake");
+ Logger.Exception(ex);
+ }
+ }
+
+ /// <summary>
+ /// Fixed update all required Flight Engineer objects.
+ /// </summary>
+ private void FixedUpdate()
+ {
+ try
+ {
+ SectionLibrary.FixedUpdate();
+ }
+ catch (Exception ex)
+ {
+ Logger.Exception(ex);
+ }
+ }
+
+ /// <summary>
+ /// Force the destruction of child objects on core destruction.
+ /// </summary>
+ private void OnDestroy()
+ {
+ try
+ {
+ SectionLibrary.Save();
+
+ foreach (var window in this.SectionWindows)
+ {
+ print("[FlightEngineer]: Destroying Floating Window for " + window.ParentSection.Name);
+ Destroy(window);
+ }
+
+ foreach (var editor in this.SectionEditors)
+ {
+ print("[FlightEngineer]: Destroying Editor Window for " + editor.ParentSection.Name);
+ Destroy(editor);
+ }
+
+ Logger.Log("FlightEngineerCore->OnDestroy");
+ }
+ catch (Exception ex)
+ {
+ Logger.Exception(ex);
}
}
@@ -80,44 +337,6 @@
}
catch (Exception ex)
{
- Logger.Exception(ex, "FlightEngineerCore->Start");
- }
- }
-
- #endregion
-
- #region Properties
-
- /// <summary>
- /// Gets the section windows for floating sections.
- /// </summary>
- public List<SectionWindow> SectionWindows { get; private set; }
-
- /// <summary>
- /// Gets the editor windows for sections with open editors.
- /// </summary>
- public List<SectionEditor> SectionEditors { get; private set; }
-
- /// <summary>
- /// Gets the list of currently running updatable modules.
- /// </summary>
- public List<IUpdatable> UpdatableModules { get; private set; }
-
- #endregion
-
- #region Updating
-
- /// <summary>
- /// Fixed update all required Flight Engineer objects.
- /// </summary>
- private void FixedUpdate()
- {
- try
- {
- SectionLibrary.FixedUpdate();
- }
- catch (Exception ex)
- {
Logger.Exception(ex);
}
}
@@ -134,7 +353,7 @@
}
catch (Exception ex)
{
- Logger.Exception(ex, "FlightEngineerCore->Update");
+ Logger.Exception(ex);
}
}
@@ -164,102 +383,7 @@
}
catch (Exception ex)
{
- Logger.Exception(ex, "FlightEngineerCore->UpdateModules");
- }
- }
-
- #endregion
-
- #region Destruction
-
- /// <summary>
- /// Force the destruction of child objects on core destruction.
- /// </summary>
- private void OnDestroy()
- {
- try
- {
- SectionLibrary.Save();
-
- foreach (var window in this.SectionWindows)
- {
- print("[FlightEngineer]: Destroying Floating Window for " + window.ParentSection.Name);
- Destroy(window);
- }
-
- foreach (var editor in this.SectionEditors)
- {
- print("[FlightEngineer]: Destroying Editor Window for " + editor.ParentSection.Name);
- Destroy(editor);
- }
-
- Logger.Log("FlightEngineerCore->OnDestroy");
- }
- catch (Exception ex)
- {
- Logger.Exception(ex, "FlightEngineerCore->OnDestroy");
- }
- }
-
- #endregion
-
- #region Methods
-
- /// <summary>
- /// Creates a section window, adds it to the FlightEngineerCore and returns a reference to it.
- /// </summary>
- public SectionWindow AddSectionWindow(SectionModule section)
- {
- try
- {
- var window = this.gameObject.AddComponent<SectionWindow>();
- window.ParentSection = section;
- window.WindowPosition = new Rect(section.FloatingPositionX, section.FloatingPositionY, 0, 0);
- this.SectionWindows.Add(window);
- return window;
- }
- catch (Exception ex)
- {
- Logger.Exception(ex, "FlightEngineerCore->AddSectionWindow");
- return null;
- }
- }
-
- /// <summary>
- /// Creates a section editor, adds it to the FlightEngineerCore and returns a reference to it.
- /// </summary>
- public SectionEditor AddSectionEditor(SectionModule section)
- {
- try
- {
- var editor = this.gameObject.AddComponent<SectionEditor>();
- editor.ParentSection = section;
- editor.Position = new Rect(section.EditorPositionX, section.EditorPositionY, SectionEditor.Width, SectionEditor.Height);
- this.SectionEditors.Add(editor);
- return editor;
- }
- catch (Exception ex)
- {
- Logger.Exception(ex, "FlightEngineerCore->AddSectionEditor");
- return null;
- }
- }
-
- /// <summary>
- /// Adds an updatable object to be automatically updated every frame and will ignore duplicate objects.
- /// </summary>
- public void AddUpdatable(IUpdatable updatable)
- {
- try
- {
- if (!this.UpdatableModules.Contains(updatable))
- {
- this.UpdatableModules.Add(updatable);
- }
- }
- catch (Exception ex)
- {
- Logger.Exception(ex, "FlightEngineerCore->AddUpdatable");
+ Logger.Exception(ex);
}
}
--- a/KerbalEngineer/Flight/FlightEngineerModule.cs
+++ b/KerbalEngineer/Flight/FlightEngineerModule.cs
@@ -19,9 +19,6 @@
#region Using Directives
-using System;
-using System.Linq;
-
#endregion
namespace KerbalEngineer.Flight
@@ -29,73 +26,5 @@
/// <summary>
/// Module that can be attached to parts, giving them FlightEngineerCore management.
/// </summary>
- public sealed class FlightEngineerModule : PartModule
- {
- #region Fields
-
- /// <summary>
- /// Contains the current FlightEngineerCore through the lifespan of this part.
- /// </summary>
- private FlightEngineerCore flightEngineerCore;
-
- #endregion
-
- #region Updating
-
- /// <summary>
- /// Logic to create and destroy the FlightEngineerCore.
- /// </summary>
- private void Update()
- {
- try
- {
- if (!HighLogic.LoadedSceneIsFlight || FlightEngineerPartless.IsPartless)
- {
- return;
- }
-
- if (this.vessel == FlightGlobals.ActiveVessel)
- {
- // Checks for an existing instance of FlightEngineerCore, and if this part is the first part containing FlightEngineerModule within the vessel.
- if (flightEngineerCore == null && this.part == this.vessel.parts.FirstOrDefault(p => p.Modules.Contains("FlightEngineerModule")))
- {
- this.flightEngineerCore = this.gameObject.AddComponent<FlightEngineerCore>();
- }
- }
- else if (flightEngineerCore != null)
- {
- // Using DestroyImmediate to force early destruction and keep saving/loading in synch when switching vessels.
- DestroyImmediate(flightEngineerCore);
- }
- }
- catch (Exception ex)
- {
- Logger.Exception(ex, "FlightEngineerModule->Update");
- }
- }
-
- #endregion
-
- #region Destruction
-
- /// <summary>
- /// Force the destruction of the FlightEngineerCore on part destruction.
- /// </summary>
- private void OnDestroy()
- {
- try
- {
- if (flightEngineerCore != null)
- {
- DestroyImmediate(flightEngineerCore);
- }
- }
- catch (Exception ex)
- {
- Logger.Exception(ex, "FlightEngineerModule->OnDestroy");
- }
- }
-
- #endregion
- }
+ public class FlightEngineerModule : PartModule { }
}
--- a/KerbalEngineer/Flight/FlightEngineerPartless.cs
+++ /dev/null
@@ -1,101 +1,1 @@
-//
-// Kerbal Engineer Redux
-//
-// Copyright (C) 2014 CYBUTEK
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-#region Using Directives
-
-using System;
-
-using KerbalEngineer.Settings;
-
-using UnityEngine;
-
-#endregion
-
-namespace KerbalEngineer.Flight
-{
- [KSPAddon(KSPAddon.Startup.Flight, false)]
- public class FlightEngineerPartless : MonoBehaviour
- {
- #region Fields
-
- private FlightEngineerCore flightEngineerCore;
-
- #endregion
-
- #region Initialisation
-
- static FlightEngineerPartless()
- {
- try
- {
- var handler = SettingHandler.Load("FlightEngineerPartless.xml");
- handler.Get("isPartless", ref isPartless);
- }
- catch (Exception ex)
- {
- Logger.Exception(ex, "FlightEngineerPartless->FlightEngineerPartless");
- }
- }
-
- private void Awake()
- {
- try
- {
- if (isPartless)
- {
- this.flightEngineerCore = this.gameObject.AddComponent<FlightEngineerCore>();
- }
- }
- catch (Exception ex)
- {
- Logger.Exception(ex, "FlightEngineerPartless->Awake");
- }
- }
-
- #endregion
-
- #region Properties
-
- private static bool isPartless = true;
-
- public static bool IsPartless
- {
- get { return isPartless; }
- set
- {
- try
- {
- if (isPartless != value)
- {
- var handler = SettingHandler.Load("FlightEngineerPartless.xml");
- handler.Set("isPartless", value);
- handler.Save("FlightEngineerPartless.xml");
- }
- isPartless = value;
- }
- catch (Exception ex)
- {
- Logger.Exception(ex, "FlightEngineerPartless->IsPartless");
- }
- }
- }
-
- #endregion
- }
-}
--- a/KerbalEngineer/Flight/Readouts/Miscellaneous/Separator.cs
+++ b/KerbalEngineer/Flight/Readouts/Miscellaneous/Separator.cs
@@ -19,7 +19,10 @@
#region Using Directives
+using System;
+
using KerbalEngineer.Flight.Sections;
+using KerbalEngineer.Helpers;
using UnityEngine;
@@ -31,7 +34,8 @@
{
#region Fields
- private readonly Texture2D texture;
+ private GUIStyle boxStyle;
+ private GUIStyle boxStyleHud;
#endregion
@@ -41,13 +45,13 @@
{
this.Name = "Separator";
this.Category = ReadoutCategory.GetCategory("Miscellaneous");
- this.HelpString = string.Empty;
+ this.HelpString = String.Empty;
this.IsDefault = false;
this.Cloneable = true;
- this.texture = new Texture2D(1, 1, TextureFormat.RGBA32, false);
- this.texture.SetPixel(0, 0, new Color(1.0f, 1.0f, 1.0f, 0.5f));
- this.texture.Apply();
+ this.InitialiseStyles();
+
+ GuiDisplaySize.OnSizeChanged += this.InitialiseStyles;
}
#endregion
@@ -56,8 +60,29 @@
public override void Draw(SectionModule section)
{
- GUILayout.Box(string.Empty, GUIStyle.none, new[] {GUILayout.Width(this.ContentWidth), GUILayout.Height(1.0f)});
- GUI.DrawTexture(GUILayoutUtility.GetLastRect(), this.texture, ScaleMode.StretchToFill);
+ GUILayout.Box(String.Empty, section.IsHud ? this.boxStyleHud : this.boxStyle);
+ }
+
+ #endregion
+
+ #region Methods: private
+
+ private void InitialiseStyles()
+ {
+ this.boxStyle = new GUIStyle
+ {
+ normal =
+ {
+ background = TextureHelper.CreateTextureFromColour(new Color(1.0f, 1.0f, 1.0f, 0.5f))
+ },
+ fixedHeight = 1.0f,
+ stretchWidth = true
+ };
+
+ this.boxStyleHud = new GUIStyle(this.boxStyle)
+ {
+ margin = new RectOffset(0, 0, (int)(8 * GuiDisplaySize.Offset), 0)
+ };
}
#endregion
--- a/KerbalEngineer/Flight/Readouts/Miscellaneous/SimulationDelay.cs
+++ b/KerbalEngineer/Flight/Readouts/Miscellaneous/SimulationDelay.cs
@@ -28,6 +28,8 @@
namespace KerbalEngineer.Flight.Readouts.Miscellaneous
{
+ using System;
+
public class SimulationDelay : ReadoutModule
{
#region Constructors
@@ -49,7 +51,7 @@
GUILayout.BeginHorizontal();
GUILayout.Label("Sim Delay", this.NameStyle);
GUI.skin = HighLogic.Skin;
- SimManager.minSimTime = (long)GUILayout.HorizontalSlider(SimManager.minSimTime, 0, 1000.0f);
+ SimManager.minSimTime = new TimeSpan(0, 0, 0, 0, (int)GUILayout.HorizontalSlider(SimManager.minSimTime.Milliseconds, 0, 1000.0f));
GUI.skin = null;
GUILayout.EndHorizontal();
}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Miscellaneous/SystemTime.cs
@@ -1,1 +1,59 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+#region Using Directives
+
+using System;
+
+using KerbalEngineer.Flight.Sections;
+using KerbalEngineer.Helpers;
+
+using UnityEngine;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Miscellaneous
+{
+ public class SystemTime : ReadoutModule
+ {
+
+
+ #region Constructors
+
+ public SystemTime()
+ {
+ this.Name = "System Time";
+ this.Category = ReadoutCategory.GetCategory("Miscellaneous");
+ this.HelpString = String.Empty;
+ this.IsDefault = false;
+ }
+
+ #endregion
+
+ #region Methods: public
+
+ public override void Draw(SectionModule section)
+ {
+ this.DrawLine(DateTime.Now.ToLongTimeString(), section.IsHud);
+ }
+
+ #endregion
+
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Miscellaneous/VectoredThrustToggle.cs
@@ -1,1 +1,56 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+namespace KerbalEngineer.Flight.Readouts.Miscellaneous
+{
+ #region Using Directives
+
+ using Sections;
+ using UnityEngine;
+ using VesselSimulator;
+
+ #endregion
+
+ public class VectoredThrustToggle : ReadoutModule
+ {
+ #region Constructors
+
+ public VectoredThrustToggle()
+ {
+ this.Name = "Vectored Thrust";
+ this.Category = ReadoutCategory.GetCategory("Miscellaneous");
+ this.HelpString = "Shows a control that will allow you to adjust whether the vessel simulation should account for vectored thrust.";
+ this.IsDefault = false;
+ }
+
+ #endregion
+
+ #region Methods
+
+ public override void Draw(SectionModule section)
+ {
+ GUILayout.BeginHorizontal();
+ GUILayout.Label("Vectored Thrust: ", this.NameStyle);
+ SimManager.vectoredThrust = GUILayout.Toggle(SimManager.vectoredThrust, "ENABLED", this.ButtonStyle);
+ GUILayout.EndHorizontal();
+ }
+
+ #endregion
+ }
+}
--- a/KerbalEngineer/Flight/Readouts/Orbital/CurrentSoi.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/CurrentSoi.cs
@@ -31,7 +31,7 @@
public class CurrentSoi : ReadoutModule
{
#region Constructors
-
+
public CurrentSoi()
{
this.Name = "Current SOI";
--- a/KerbalEngineer/Flight/Readouts/Orbital/Eccentricity.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/Eccentricity.cs
@@ -43,7 +43,7 @@
public override void Draw(SectionModule section)
{
- this.DrawLine(FlightGlobals.ship_orbit.eccentricity.ToString("F3"), section.IsHud);
+ this.DrawLine(FlightGlobals.ship_orbit.eccentricity.ToString("F5"), section.IsHud);
}
#endregion
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/ManoeuvreProcessor.cs
@@ -1,1 +1,188 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+#region Using Directives
+
+using System;
+
+using KerbalEngineer.Extensions;
+using KerbalEngineer.Flight.Readouts.Vessel;
+
+using UnityEngine;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Orbital.ManoeuvreNode
+{
+ public class ManoeuvreProcessor : IUpdatable, IUpdateRequest
+ {
+ #region Fields
+
+ private static readonly ManoeuvreProcessor instance = new ManoeuvreProcessor();
+
+ #endregion
+
+ #region Properties
+
+ public static double AngleToPrograde { get; private set; }
+
+ public static double AngleToRetrograde { get; private set; }
+
+ public static double AvailableDeltaV { get; private set; }
+
+ public static double BurnTime { get; private set; }
+
+ public static int FinalStage { get; private set; }
+
+ public static double HalfBurnTime { get; private set; }
+
+ public static bool HasDeltaV { get; private set; }
+
+ public static ManoeuvreProcessor Instance
+ {
+ get { return instance; }
+ }
+
+ public static double NormalDeltaV { get; private set; }
+
+ public static double ProgradeDeltaV { get; private set; }
+
+ public static double RadialDeltaV { get; private set; }
+
+ public static bool ShowDetails { get; set; }
+
+ public static double TotalDeltaV { get; private set; }
+
+ public static double UniversalTime { get; private set; }
+
+ public bool UpdateRequested { get; set; }
+
+ #endregion
+
+ #region Methods: public
+
+ public static void RequestUpdate()
+ {
+ instance.UpdateRequested = true;
+ SimulationProcessor.RequestUpdate();
+ }
+
+ public static void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(SimulationProcessor.Instance);
+ FlightEngineerCore.Instance.AddUpdatable(instance);
+ }
+
+ public void Update()
+ {
+ // Extra tests for low level tracking station not supporting patched conics and maneuver nodes
+ if (FlightGlobals.ActiveVessel.patchedConicSolver == null ||
+ FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes == null ||
+ FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes.Count == 0 ||
+ !SimulationProcessor.ShowDetails)
+ {
+ ShowDetails = false;
+ return;
+ }
+
+ var node = FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes[0];
+ var deltaV = node.DeltaV;
+
+ ProgradeDeltaV = deltaV.z;
+ NormalDeltaV = deltaV.y;
+ RadialDeltaV = deltaV.x;
+ TotalDeltaV = node.GetBurnVector(FlightGlobals.ship_orbit).magnitude;
+
+ UniversalTime = FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes[0].UT;
+ AngleToPrograde = FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes[0].patch.GetAngleToPrograde(UniversalTime);
+ AngleToRetrograde = FlightGlobals.ActiveVessel.patchedConicSolver.maneuverNodes[0].patch.GetAngleToRetrograde(UniversalTime);
+
+ var burnTime = 0.0;
+ var midPointTime = 0.0;
+ HasDeltaV = GetBurnTime(TotalDeltaV, ref burnTime, ref midPointTime);
+ AvailableDeltaV = SimulationProcessor.LastStage.totalDeltaV;
+
+ BurnTime = burnTime;
+ HalfBurnTime = midPointTime;
+
+ ShowDetails = true;
+ }
+
+ #endregion
+
+ #region Methods: private
+
+ private static bool GetBurnTime(double deltaV, ref double burnTime, ref double midPointTime)
+ {
+ var setMidPoint = false;
+ var deltaVMidPoint = deltaV * 0.5;
+
+ for (var i = SimulationProcessor.Stages.Length - 1; i > -1; i--)
+ {
+ var stage = SimulationProcessor.Stages[i];
+ var stageDeltaV = stage.deltaV;
+ var startMass = stage.totalMass;
+
+ ProcessStageDrain:
+ if (deltaV <= Double.Epsilon)
+ {
+ break;
+ }
+ if (stageDeltaV <= Double.Epsilon)
+ {
+ continue;
+ }
+
+ FinalStage = i;
+
+ double deltaVDrain;
+ if (deltaVMidPoint > 0.0)
+ {
+ deltaVDrain = deltaV.Clamp(0.0, stageDeltaV.Clamp(0.0, deltaVMidPoint));
+ deltaVMidPoint -= deltaVDrain;
+ setMidPoint = deltaVMidPoint <= Double.Epsilon;
+ }
+ else
+ {
+ deltaVDrain = deltaV.Clamp(0.0, stageDeltaV);
+ }
+
+ var exhaustVelocity = stage.isp * 9.82;
+ var flowRate = stage.thrust / exhaustVelocity;
+ var endMass = Math.Exp(Math.Log(startMass) - deltaVDrain / exhaustVelocity);
+ var deltaMass = (startMass - endMass) * Math.Exp(-(deltaVDrain * 0.001) / exhaustVelocity);
+ burnTime += deltaMass / flowRate;
+
+ deltaV -= deltaVDrain;
+ stageDeltaV -= deltaVDrain;
+ startMass -= deltaMass;
+
+ if (setMidPoint)
+ {
+ midPointTime = burnTime;
+ setMidPoint = false;
+ goto ProcessStageDrain;
+ }
+ }
+ return deltaV <= Double.Epsilon;
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeAngleToPrograde.cs
@@ -1,1 +1,69 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+#region Using Directives
+
+using System;
+
+using KerbalEngineer.Extensions;
+using KerbalEngineer.Flight.Sections;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Orbital.ManoeuvreNode
+{
+ public class NodeAngleToPrograde : ReadoutModule
+ {
+ #region Constructors
+
+ public NodeAngleToPrograde()
+ {
+ this.Name = "Manoeuvre Node Angle to Prograde";
+ this.Category = ReadoutCategory.GetCategory("Orbital");
+ this.HelpString = String.Empty;
+ this.IsDefault = true;
+ }
+
+ #endregion
+
+ #region Methods: public
+
+ public override void Draw(SectionModule section)
+ {
+ if (!ManoeuvreProcessor.ShowDetails)
+ {
+ return;
+ }
+
+ this.DrawLine("Node Angle to Prograde", ManoeuvreProcessor.AngleToPrograde.ToAngle(), section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ ManoeuvreProcessor.Reset();
+ }
+
+ public override void Update()
+ {
+ ManoeuvreProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeAngleToRetrograde.cs
@@ -1,1 +1,69 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+#region Using Directives
+
+using System;
+
+using KerbalEngineer.Extensions;
+using KerbalEngineer.Flight.Sections;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Orbital.ManoeuvreNode
+{
+ public class NodeAngleToRetrograde : ReadoutModule
+ {
+ #region Constructors
+
+ public NodeAngleToRetrograde()
+ {
+ this.Name = "Manoeuvre Node Angle to Retrograde";
+ this.Category = ReadoutCategory.GetCategory("Orbital");
+ this.HelpString = String.Empty;
+ this.IsDefault = true;
+ }
+
+ #endregion
+
+ #region Methods: public
+
+ public override void Draw(SectionModule section)
+ {
+ if (!ManoeuvreProcessor.ShowDetails)
+ {
+ return;
+ }
+
+ this.DrawLine("Node Angle to Retrograde", ManoeuvreProcessor.AngleToRetrograde.ToAngle(), section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ ManoeuvreProcessor.Reset();
+ }
+
+ public override void Update()
+ {
+ ManoeuvreProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeBurnTime.cs
@@ -1,1 +1,69 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+#region Using Directives
+
+using System;
+
+using KerbalEngineer.Flight.Sections;
+using KerbalEngineer.Helpers;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Orbital.ManoeuvreNode
+{
+ public class NodeBurnTime : ReadoutModule
+ {
+ #region Constructors
+
+ public NodeBurnTime()
+ {
+ this.Name = "Manoeuvre Node Burn Time";
+ this.Category = ReadoutCategory.GetCategory("Orbital");
+ this.HelpString = String.Empty;
+ this.IsDefault = true;
+ }
+
+ #endregion
+
+ #region Methods: public
+
+ public override void Draw(SectionModule section)
+ {
+ if (!ManoeuvreProcessor.ShowDetails)
+ {
+ return;
+ }
+
+ this.DrawLine("Node Burn Time", TimeFormatter.ConvertToString(ManoeuvreProcessor.BurnTime), section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ ManoeuvreProcessor.Reset();
+ }
+
+ public override void Update()
+ {
+ ManoeuvreProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeHalfBurnTime.cs
@@ -1,1 +1,69 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+#region Using Directives
+
+using System;
+
+using KerbalEngineer.Flight.Sections;
+using KerbalEngineer.Helpers;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Orbital.ManoeuvreNode
+{
+ public class NodeHalfBurnTime : ReadoutModule
+ {
+ #region Constructors
+
+ public NodeHalfBurnTime()
+ {
+ this.Name = "Manoeuvre Node Half Burn Time";
+ this.Category = ReadoutCategory.GetCategory("Orbital");
+ this.HelpString = String.Empty;
+ this.IsDefault = true;
+ }
+
+ #endregion
+
+ #region Methods: public
+
+ public override void Draw(SectionModule section)
+ {
+ if (!ManoeuvreProcessor.ShowDetails)
+ {
+ return;
+ }
+
+ this.DrawLine("Node Burn Time (½)", TimeFormatter.ConvertToString(ManoeuvreProcessor.HalfBurnTime), section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ ManoeuvreProcessor.Reset();
+ }
+
+ public override void Update()
+ {
+ ManoeuvreProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeNormalDeltaV.cs
@@ -1,1 +1,69 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+#region Using Directives
+
+using System;
+
+using KerbalEngineer.Extensions;
+using KerbalEngineer.Flight.Sections;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Orbital.ManoeuvreNode
+{
+ public class NodeNormalDeltaV : ReadoutModule
+ {
+ #region Constructors
+
+ public NodeNormalDeltaV()
+ {
+ this.Name = "Manoeuvre Node DeltaV (Normal)";
+ this.Category = ReadoutCategory.GetCategory("Orbital");
+ this.HelpString = String.Empty;
+ this.IsDefault = true;
+ }
+
+ #endregion
+
+ #region Methods: public
+
+ public override void Draw(SectionModule section)
+ {
+ if (!ManoeuvreProcessor.ShowDetails)
+ {
+ return;
+ }
+
+ this.DrawLine("Node DeltaV (Normal)", ManoeuvreProcessor.NormalDeltaV.ToSpeed(), section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ ManoeuvreProcessor.Reset();
+ }
+
+ public override void Update()
+ {
+ ManoeuvreProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeProgradeDeltaV.cs
@@ -1,1 +1,69 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+#region Using Directives
+
+using System;
+
+using KerbalEngineer.Extensions;
+using KerbalEngineer.Flight.Sections;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Orbital.ManoeuvreNode
+{
+ public class NodeProgradeDeltaV : ReadoutModule
+ {
+ #region Constructors
+
+ public NodeProgradeDeltaV()
+ {
+ this.Name = "Manoeuvre Node DeltaV (Prograde)";
+ this.Category = ReadoutCategory.GetCategory("Orbital");
+ this.HelpString = String.Empty;
+ this.IsDefault = true;
+ }
+
+ #endregion
+
+ #region Methods: public
+
+ public override void Draw(SectionModule section)
+ {
+ if (!ManoeuvreProcessor.ShowDetails)
+ {
+ return;
+ }
+
+ this.DrawLine("Node DeltaV (Prograde)", ManoeuvreProcessor.ProgradeDeltaV.ToSpeed(), section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ ManoeuvreProcessor.Reset();
+ }
+
+ public override void Update()
+ {
+ ManoeuvreProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeRadialDeltaV.cs
@@ -1,1 +1,69 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+#region Using Directives
+
+using System;
+
+using KerbalEngineer.Extensions;
+using KerbalEngineer.Flight.Sections;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Orbital.ManoeuvreNode
+{
+ public class NodeRadialDeltaV : ReadoutModule
+ {
+ #region Constructors
+
+ public NodeRadialDeltaV()
+ {
+ this.Name = "Manoeuvre Node DeltaV (Radial)";
+ this.Category = ReadoutCategory.GetCategory("Orbital");
+ this.HelpString = String.Empty;
+ this.IsDefault = true;
+ }
+
+ #endregion
+
+ #region Methods: public
+
+ public override void Draw(SectionModule section)
+ {
+ if (!ManoeuvreProcessor.ShowDetails)
+ {
+ return;
+ }
+
+ this.DrawLine("Node DeltaV (Radial)", ManoeuvreProcessor.RadialDeltaV.ToSpeed(), section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ ManoeuvreProcessor.Reset();
+ }
+
+ public override void Update()
+ {
+ ManoeuvreProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeTimeToHalfBurn.cs
@@ -1,1 +1,69 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+#region Using Directives
+
+using System;
+
+using KerbalEngineer.Flight.Sections;
+using KerbalEngineer.Helpers;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Orbital.ManoeuvreNode
+{
+ public class NodeTimeToHalfBurn : ReadoutModule
+ {
+ #region Constructors
+
+ public NodeTimeToHalfBurn()
+ {
+ this.Name = "Time to Manoeuvre Burn";
+ this.Category = ReadoutCategory.GetCategory("Orbital");
+ this.HelpString = String.Empty;
+ this.IsDefault = true;
+ }
+
+ #endregion
+
+ #region Methods: public
+
+ public override void Draw(SectionModule section)
+ {
+ if (!ManoeuvreProcessor.ShowDetails)
+ {
+ return;
+ }
+
+ this.DrawLine("Time to Node Burn", TimeFormatter.ConvertToString(ManoeuvreProcessor.UniversalTime - ManoeuvreProcessor.HalfBurnTime - Planetarium.GetUniversalTime()), section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ ManoeuvreProcessor.Reset();
+ }
+
+ public override void Update()
+ {
+ ManoeuvreProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeTimeToManoeuvre.cs
@@ -1,1 +1,69 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+#region Using Directives
+
+using System;
+
+using KerbalEngineer.Flight.Sections;
+using KerbalEngineer.Helpers;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Orbital.ManoeuvreNode
+{
+ public class NodeTimeToManoeuvre : ReadoutModule
+ {
+ #region Constructors
+
+ public NodeTimeToManoeuvre()
+ {
+ this.Name = "Time to Manoeuvre Node";
+ this.Category = ReadoutCategory.GetCategory("Orbital");
+ this.HelpString = String.Empty;
+ this.IsDefault = true;
+ }
+
+ #endregion
+
+ #region Methods: public
+
+ public override void Draw(SectionModule section)
+ {
+ if (!ManoeuvreProcessor.ShowDetails)
+ {
+ return;
+ }
+
+ this.DrawLine("Time to Node", TimeFormatter.ConvertToString(ManoeuvreProcessor.UniversalTime - Planetarium.GetUniversalTime()), section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ ManoeuvreProcessor.Reset();
+ }
+
+ public override void Update()
+ {
+ ManoeuvreProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Orbital/ManoeuvreNode/NodeTotalDeltaV.cs
@@ -1,1 +1,69 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+#region Using Directives
+
+using System;
+
+using KerbalEngineer.Extensions;
+using KerbalEngineer.Flight.Sections;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Orbital.ManoeuvreNode
+{
+ public class NodeTotalDeltaV : ReadoutModule
+ {
+ #region Constructors
+
+ public NodeTotalDeltaV()
+ {
+ this.Name = "Manoeuvre Node DeltaV (Total)";
+ this.Category = ReadoutCategory.GetCategory("Orbital");
+ this.HelpString = String.Empty;
+ this.IsDefault = true;
+ }
+
+ #endregion
+
+ #region Methods: public
+
+ public override void Draw(SectionModule section)
+ {
+ if (!ManoeuvreProcessor.ShowDetails)
+ {
+ return;
+ }
+
+ this.DrawLine("Node DeltaV (Total)", ManoeuvreProcessor.TotalDeltaV.ToSpeed() + " (" + (ManoeuvreProcessor.HasDeltaV ? "S" + ManoeuvreProcessor.FinalStage : "X") + ")", section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ ManoeuvreProcessor.Reset();
+ }
+
+ public override void Update()
+ {
+ ManoeuvreProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Orbital/MeanAnomalyAtEpoc.cs
@@ -1,1 +1,54 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+#region Using Directives
+
+using System;
+
+using KerbalEngineer.Extensions;
+using KerbalEngineer.Flight.Sections;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Orbital
+{
+ public class MeanAnomalyAtEpoc : ReadoutModule
+ {
+ #region Constructors
+
+ public MeanAnomalyAtEpoc()
+ {
+ this.Name = "Mean Anomaly at Epoc";
+ this.Category = ReadoutCategory.GetCategory("Orbital");
+ this.HelpString = String.Empty;
+ this.IsDefault = false;
+ }
+
+ #endregion
+
+ #region Methods: public
+
+ public override void Draw(SectionModule section)
+ {
+ this.DrawLine(FlightGlobals.ship_orbit.meanAnomalyAtEpoch.ToAngle(), section.IsHud);
+ }
+
+ #endregion
+ }
+}
--- a/KerbalEngineer/Flight/Readouts/ReadoutCategory.cs
+++ b/KerbalEngineer/Flight/Readouts/ReadoutCategory.cs
@@ -56,6 +56,7 @@
public static ReadoutCategory Selected { get; set; }
public string Description { get; set; }
+
public string Name { get; set; }
#endregion
--- 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
@@ -17,41 +17,31 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-using KerbalEngineer.Flight.Readouts.Miscellaneous;
-using KerbalEngineer.Flight.Readouts.Orbital;
-using KerbalEngineer.Flight.Readouts.Rendezvous;
-using KerbalEngineer.Flight.Readouts.Surface;
-using KerbalEngineer.Flight.Readouts.Vessel;
-using KerbalEngineer.Settings;
-
-using AltitudeSeaLevel = KerbalEngineer.Flight.Readouts.Surface.AltitudeSeaLevel;
-using ApoapsisHeight = KerbalEngineer.Flight.Readouts.Orbital.ApoapsisHeight;
-using OrbitalPeriod = KerbalEngineer.Flight.Readouts.Orbital.OrbitalPeriod;
-using PeriapsisHeight = KerbalEngineer.Flight.Readouts.Orbital.PeriapsisHeight;
-using SemiMajorAxis = KerbalEngineer.Flight.Readouts.Orbital.SemiMajorAxis;
-using SemiMinorAxis = KerbalEngineer.Flight.Readouts.Orbital.SemiMinorAxis;
-using TimeToApoapsis = KerbalEngineer.Flight.Readouts.Orbital.TimeToApoapsis;
-using TimeToPeriapsis = KerbalEngineer.Flight.Readouts.Orbital.TimeToPeriapsis;
-
-#endregion
-
namespace KerbalEngineer.Flight.Readouts
{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using Miscellaneous;
+ using Orbital;
+ using Orbital.ManoeuvreNode;
+ using Rendezvous;
+ using Settings;
+ using Surface;
+ using Thermal;
+ using Vessel;
+ using AltitudeSeaLevel = Surface.AltitudeSeaLevel;
+ using ApoapsisHeight = Orbital.ApoapsisHeight;
+ using OrbitalPeriod = Orbital.OrbitalPeriod;
+ using PeriapsisHeight = Orbital.PeriapsisHeight;
+ using SemiMajorAxis = Orbital.SemiMajorAxis;
+ using SemiMinorAxis = Orbital.SemiMinorAxis;
+ using TimeToApoapsis = Orbital.TimeToApoapsis;
+ using TimeToPeriapsis = Orbital.TimeToPeriapsis;
+
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.
@@ -64,7 +54,9 @@
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");
// Orbital
readouts.Add(new ApoapsisHeight());
@@ -85,11 +77,22 @@
readouts.Add(new ArgumentOfPeriapsis());
readouts.Add(new TrueAnomaly());
readouts.Add(new MeanAnomaly());
+ readouts.Add(new MeanAnomalyAtEpoc());
readouts.Add(new EccentricAnomaly());
readouts.Add(new SemiMajorAxis());
readouts.Add(new SemiMinorAxis());
readouts.Add(new AngleToPrograde());
readouts.Add(new AngleToRetrograde());
+ readouts.Add(new NodeProgradeDeltaV());
+ readouts.Add(new NodeNormalDeltaV());
+ readouts.Add(new NodeRadialDeltaV());
+ readouts.Add(new NodeTotalDeltaV());
+ readouts.Add(new NodeBurnTime());
+ readouts.Add(new NodeHalfBurnTime());
+ readouts.Add(new NodeTimeToManoeuvre());
+ readouts.Add(new NodeTimeToHalfBurn());
+ readouts.Add(new NodeAngleToPrograde());
+ readouts.Add(new NodeAngleToRetrograde());
// Surface
readouts.Add(new AltitudeSeaLevel());
@@ -98,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());
@@ -121,6 +125,8 @@
readouts.Add(new Mass());
readouts.Add(new Thrust());
readouts.Add(new ThrustToWeight());
+ readouts.Add(new ThrustOffsetAngle());
+ readouts.Add(new ThrustTorque());
readouts.Add(new SurfaceThrustToWeight());
readouts.Add(new Acceleration());
readouts.Add(new SuicideBurnAltitude());
@@ -130,6 +136,13 @@
readouts.Add(new IntakeAirDemand());
readouts.Add(new IntakeAirSupply());
readouts.Add(new IntakeAirDemandSupply());
+ readouts.Add(new PartCount());
+ readouts.Add(new Heading());
+ readouts.Add(new Pitch());
+ readouts.Add(new Roll());
+ readouts.Add(new HeadingRate());
+ readouts.Add(new PitchRate());
+ readouts.Add(new RollRate());
// Rendezvous
readouts.Add(new TargetSelector());
@@ -152,11 +165,25 @@
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());
readouts.Add(new SimulationDelay());
readouts.Add(new TimeReference());
+ readouts.Add(new VectoredThrustToggle());
+ readouts.Add(new SystemTime());
LoadHelpStrings();
}
@@ -166,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: public
+ get
+ {
+ return readouts;
+ }
+ set
+ {
+ readouts = value;
+ }
+ }
/// <summary>
/// Gets a list of readout modules which are associated with the specified category.
@@ -204,16 +229,12 @@
/// </summary>
public static void Reset()
{
- foreach (var readout in readouts)
+ foreach (ReadoutModule readout in readouts)
{
readout.Reset();
}
}
- #endregion
-
- #region Methods: private
-
/// <summary>
/// Loads the help strings from file.
/// </summary>
@@ -221,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);
}
@@ -233,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
@@ -89,6 +91,11 @@
public bool IsDefault { get; set; }
/// <summary>
+ /// Gets the number of drawn lines.
+ /// </summary>
+ public int LineCount { get; private set; }
+
+ /// <summary>
/// Gets and sets the message style.
/// </summary>
public GUIStyle MessageStyle { get; set; }
@@ -139,6 +146,7 @@
public void LineCountEnd()
{
+ this.LineCount = this.lineCountEnd;
if (this.lineCountEnd.CompareTo(this.lineCountStart) < 0)
{
this.ResizeRequested = true;
@@ -172,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();
@@ -192,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/AltitudeTerrain.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/AltitudeTerrain.cs
@@ -19,13 +19,17 @@
#region Using Directives
-using KerbalEngineer.Extensions;
-using KerbalEngineer.Flight.Sections;
-
#endregion
namespace KerbalEngineer.Flight.Readouts.Surface
{
+ #region Using Directives
+
+ using Extensions;
+ using Sections;
+
+ #endregion
+
public class AltitudeTerrain : ReadoutModule
{
#region Constructors
@@ -40,11 +44,18 @@
#endregion
- #region Methods: public
+ #region Methods
public override void Draw(SectionModule section)
{
- this.DrawLine((FlightGlobals.ship_altitude - FlightGlobals.ActiveVessel.terrainAltitude).ToDistance(), section.IsHud);
+ if (FlightGlobals.ActiveVessel.terrainAltitude > 0.0)
+ {
+ this.DrawLine((FlightGlobals.ship_altitude - FlightGlobals.ActiveVessel.terrainAltitude).ToDistance(), section.IsHud);
+ }
+ else
+ {
+ this.DrawLine((FlightGlobals.ship_altitude).ToDistance(), section.IsHud);
+ }
}
#endregion
--- 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/AtmosphericProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/AtmosphericProcessor.cs
@@ -29,6 +29,8 @@
namespace KerbalEngineer.Flight.Readouts.Surface
{
+ using UnityEngine;
+
public class AtmosphericProcessor : IUpdatable, IUpdateRequest
{
#region Instance
@@ -46,7 +48,10 @@
/// </summary>
public static AtmosphericProcessor Instance
{
- get { return instance; }
+ get
+ {
+ return instance;
+ }
}
#endregion
@@ -122,13 +127,13 @@
}
else
{
- 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.ship_position).magnitude;
- var atmo = FlightGlobals.ActiveVessel.atmDensity;
- var coef = FlightGlobals.DragMultiplier;
-
- TerminalVelocity = Math.Sqrt((2 * mass * grav) / (atmo * drag * coef));
+ var m = FlightGlobals.ActiveVessel.parts.Sum(part => part.GetWetMass()) * 1000.0;
+ var g = FlightGlobals.getGeeForceAtPosition(FlightGlobals.ship_position).magnitude;
+ var a = FlightGlobals.ActiveVessel.parts.Sum(part => part.DragCubes.AreaDrag) * PhysicsGlobals.DragCubeMultiplier;
+ var p = FlightGlobals.ActiveVessel.atmDensity;
+ var c = PhysicsGlobals.DragMultiplier;
+
+ TerminalVelocity = Math.Sqrt((2.0 * m * g) / (p * a * c));
}
Efficiency = FlightGlobals.ship_srfSpeed / TerminalVelocity;
--- a/KerbalEngineer/Flight/Readouts/Surface/Latitude.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/Latitude.cs
@@ -20,6 +20,7 @@
#region Using Directives
using KerbalEngineer.Flight.Sections;
+using KerbalEngineer.Helpers;
#endregion
@@ -43,7 +44,7 @@
public override void Draw(SectionModule section)
{
- this.DrawLine(KSPUtil.PrintLatitude(FlightGlobals.ship_latitude), section.IsHud);
+ this.DrawLine(Units.ToAngleDMS(FlightGlobals.ship_latitude) + (FlightGlobals.ship_latitude < 0 ? " S" : " N"), section.IsHud);
}
#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;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/AttitudeProcessor.cs
@@ -1,1 +1,133 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+ #region Using Directives
+
+ using UnityEngine;
+
+ #endregion
+
+ public class AttitudeProcessor : IUpdatable, IUpdateRequest
+ {
+ #region Fields
+
+ private static readonly AttitudeProcessor instance = new AttitudeProcessor();
+
+ private Vector3 centreOfMass = Vector3.zero;
+
+ private double heading;
+ private double headingRate;
+ private Vector3 north = Vector3.zero;
+ private double pitch;
+ private double pitchRate;
+ private double previousHeading;
+ private double previousPitch;
+ private double previousRoll;
+ private double roll;
+ private double rollRate;
+ private Quaternion surfaceRotation;
+ private Vector3 up = Vector3.zero;
+
+ #endregion
+
+ #region Properties
+
+ public static double Heading
+ {
+ get { return instance.heading; }
+ }
+
+ public static double HeadingRate
+ {
+ get { return instance.headingRate; }
+ }
+
+ public static AttitudeProcessor Instance
+ {
+ get { return instance; }
+ }
+
+ public static double Pitch
+ {
+ get { return instance.pitch; }
+ }
+
+ public static double PitchRate
+ {
+ get { return instance.pitchRate; }
+ }
+
+ public static double Roll
+ {
+ get { return instance.roll; }
+ }
+
+ public static double RollRate
+ {
+ get { return instance.rollRate; }
+ }
+
+ public bool UpdateRequested { get; set; }
+
+ #endregion
+
+ #region Methods
+
+ public static void RequestUpdate()
+ {
+ instance.UpdateRequested = true;
+ }
+
+ public void Update()
+ {
+ this.surfaceRotation = this.GetSurfaceRotation();
+
+ this.previousHeading = this.heading;
+ this.previousPitch = this.pitch;
+ this.previousRoll = this.roll;
+
+ // This code was derived from MechJeb2's implementation for getting the vessel's surface relative rotation.
+ this.heading = this.surfaceRotation.eulerAngles.y;
+ this.pitch = this.surfaceRotation.eulerAngles.x > 180.0f
+ ? 360.0f - this.surfaceRotation.eulerAngles.x
+ : -this.surfaceRotation.eulerAngles.x;
+ this.roll = this.surfaceRotation.eulerAngles.z > 180.0f
+ ? this.surfaceRotation.eulerAngles.z - 360.0f
+ : this.surfaceRotation.eulerAngles.z;
+
+ this.headingRate = this.heading - this.previousHeading;
+ this.pitchRate = this.pitch - this.previousPitch;
+ this.rollRate = this.roll - this.previousRoll;
+ }
+
+ private Quaternion GetSurfaceRotation()
+ {
+ // This code was derived from MechJeb2's implementation for getting the vessel's surface relative rotation.
+ this.centreOfMass = FlightGlobals.ActiveVessel.findWorldCenterOfMass();
+ this.up = (this.centreOfMass - FlightGlobals.ActiveVessel.mainBody.position).normalized;
+ this.north = Vector3.ProjectOnPlane((FlightGlobals.ActiveVessel.mainBody.position + FlightGlobals.ActiveVessel.mainBody.transform.up * (float)FlightGlobals.ActiveVessel.mainBody.Radius) - this.centreOfMass, this.up).normalized;
+
+ return Quaternion.Inverse(Quaternion.Euler(90.0f, 0.0f, 0.0f) * Quaternion.Inverse(FlightGlobals.ActiveVessel.transform.rotation) * Quaternion.LookRotation(this.north, this.up));
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Heading.cs
@@ -1,1 +1,62 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+ #region Using Directives
+
+ using Helpers;
+ using Sections;
+
+ #endregion
+
+ public class Heading : ReadoutModule
+ {
+ #region Constructors
+
+ public Heading()
+ {
+ this.Name = "Heading";
+ this.Category = ReadoutCategory.GetCategory("Vessel");
+ this.HelpString = string.Empty;
+ this.IsDefault = false;
+ }
+
+ #endregion
+
+ #region Methods
+
+ public override void Draw(SectionModule section)
+ {
+ this.DrawLine(Units.ToAngle(AttitudeProcessor.Heading), section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(AttitudeProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ AttitudeProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/HeadingRate.cs
@@ -1,1 +1,62 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+ #region Using Directives
+
+ using Helpers;
+ using Sections;
+
+ #endregion
+
+ public class HeadingRate : ReadoutModule
+ {
+ #region Constructors
+
+ public HeadingRate()
+ {
+ this.Name = "Heading Rate";
+ this.Category = ReadoutCategory.GetCategory("Vessel");
+ this.HelpString = string.Empty;
+ this.IsDefault = false;
+ }
+
+ #endregion
+
+ #region Methods
+
+ public override void Draw(SectionModule section)
+ {
+ this.DrawLine(Units.ToAngle(AttitudeProcessor.HeadingRate) + "/sec", section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(AttitudeProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ AttitudeProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/PartCount.cs
@@ -1,1 +1,65 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+ #region Using Directives
+
+ using Helpers;
+ using Sections;
+
+ #endregion
+
+ public class PartCount : ReadoutModule
+ {
+ #region Constructors
+
+ public PartCount()
+ {
+ this.Name = "Part Count";
+ this.Category = ReadoutCategory.GetCategory("Vessel");
+ this.HelpString = string.Empty;
+ this.IsDefault = true;
+ }
+
+ #endregion
+
+ #region Methods
+
+ public override void Draw(SectionModule section)
+ {
+ if (SimulationProcessor.ShowDetails)
+ {
+ this.DrawLine(Units.ConcatF(SimulationProcessor.LastStage.partCount, SimulationProcessor.LastStage.totalPartCount, 0), section.IsHud);
+ }
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(SimulationProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ SimulationProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Pitch.cs
@@ -1,1 +1,62 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+ #region Using Directives
+
+ using Helpers;
+ using Sections;
+
+ #endregion
+
+ public class Pitch : ReadoutModule
+ {
+ #region Constructors
+
+ public Pitch()
+ {
+ this.Name = "Pitch";
+ this.Category = ReadoutCategory.GetCategory("Vessel");
+ this.HelpString = string.Empty;
+ this.IsDefault = false;
+ }
+
+ #endregion
+
+ #region Methods
+
+ public override void Draw(SectionModule section)
+ {
+ this.DrawLine(Units.ToAngle(AttitudeProcessor.Pitch), section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(AttitudeProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ AttitudeProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/PitchRate.cs
@@ -1,1 +1,62 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+ #region Using Directives
+
+ using Helpers;
+ using Sections;
+
+ #endregion
+
+ public class PitchRate : ReadoutModule
+ {
+ #region Constructors
+
+ public PitchRate()
+ {
+ this.Name = "Pitch Rate";
+ this.Category = ReadoutCategory.GetCategory("Vessel");
+ this.HelpString = string.Empty;
+ this.IsDefault = false;
+ }
+
+ #endregion
+
+ #region Methods
+
+ public override void Draw(SectionModule section)
+ {
+ this.DrawLine(Units.ToAngle(AttitudeProcessor.PitchRate) + "/sec", section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(AttitudeProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ AttitudeProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Roll.cs
@@ -1,1 +1,62 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+ #region Using Directives
+
+ using Helpers;
+ using Sections;
+
+ #endregion
+
+ public class Roll : ReadoutModule
+ {
+ #region Constructors
+
+ public Roll()
+ {
+ this.Name = "Roll";
+ this.Category = ReadoutCategory.GetCategory("Vessel");
+ this.HelpString = string.Empty;
+ this.IsDefault = false;
+ }
+
+ #endregion
+
+ #region Methods
+
+ public override void Draw(SectionModule section)
+ {
+ this.DrawLine(Units.ToAngle(AttitudeProcessor.Roll), section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(AttitudeProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ AttitudeProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/RollRate.cs
@@ -1,1 +1,62 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+ #region Using Directives
+
+ using Helpers;
+ using Sections;
+
+ #endregion
+
+ public class RollRate : ReadoutModule
+ {
+ #region Constructors
+
+ public RollRate()
+ {
+ this.Name = "Roll Rate";
+ this.Category = ReadoutCategory.GetCategory("Vessel");
+ this.HelpString = string.Empty;
+ this.IsDefault = false;
+ }
+
+ #endregion
+
+ #region Methods
+
+ public override void Draw(SectionModule section)
+ {
+ this.DrawLine(Units.ToAngle(AttitudeProcessor.RollRate) + "/sec", section.IsHud);
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(AttitudeProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ AttitudeProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
--- a/KerbalEngineer/Flight/Readouts/Vessel/SimulationProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/SimulationProcessor.cs
@@ -19,14 +19,19 @@
#region Using Directives
-using System;
-using KerbalEngineer.VesselSimulator;
#endregion
namespace KerbalEngineer.Flight.Readouts.Vessel
{
+ #region Using Directives
+
+ using System;
+ using VesselSimulator;
+
+ #endregion
+
public class SimulationProcessor : IUpdatable, IUpdateRequest
{
#region Instance
@@ -34,6 +39,15 @@
#region Fields
private static readonly SimulationProcessor instance = new SimulationProcessor();
+
+ #endregion
+
+ #region Constructors
+
+ static SimulationProcessor()
+ {
+ SimManager.OnReady += GetStageInfo;
+ }
#endregion
@@ -72,7 +86,13 @@
#endregion
- #region Methods: public
+ #region Methods
+
+ private static void GetStageInfo()
+ {
+ Stages = SimManager.Stages;
+ LastStage = SimManager.LastStage;
+ }
public static void RequestUpdate()
{
@@ -82,14 +102,12 @@
public void Update()
{
SimManager.RequestSimulation();
+ SimManager.TryStartSimulation();
if (!SimManager.ResultsReady())
{
return;
}
-
- Stages = SimManager.Stages;
- LastStage = SimManager.LastStage;
if (Stages != null && LastStage != null)
{
@@ -101,11 +119,8 @@
SimManager.Gravity = FlightGlobals.ActiveVessel.mainBody.gravParameter /
Math.Pow(FlightGlobals.ActiveVessel.mainBody.Radius +
FlightGlobals.ActiveVessel.mainBody.GetAltitude(FlightGlobals.ActiveVessel.CoM), 2);
- SimManager.Velocity = FlightGlobals.ActiveVessel.srfSpeed;
+ SimManager.Mach = FlightGlobals.ActiveVessel.mach;
}
- // Cybutek: We should be allowing this to be set too but not sure where you want to put the control
- //SimManager.vectoredThrust = vectoredThrust;
- SimManager.TryStartSimulation();
}
#endregion
--- a/KerbalEngineer/Flight/Readouts/Vessel/SuicideBurnProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/SuicideBurnProcessor.cs
@@ -19,12 +19,18 @@
#region Using Directives
-using System;
+
#endregion
namespace KerbalEngineer.Flight.Readouts.Vessel
{
+ #region Using Directives
+
+ using System;
+
+ #endregion
+
public class SuicideBurnProcessor : IUpdatable, IUpdateRequest
{
#region Fields
@@ -55,7 +61,7 @@
#endregion
- #region Methods: public
+ #region Methods
public static void RequestUpdate()
{
@@ -79,7 +85,9 @@
this.gravity = FlightGlobals.currentMainBody.gravParameter / Math.Pow(FlightGlobals.currentMainBody.Radius, 2.0);
this.acceleration = SimulationProcessor.LastStage.thrust / SimulationProcessor.LastStage.totalMass;
- this.radarAltitude = FlightGlobals.ship_altitude - FlightGlobals.ActiveVessel.terrainAltitude;
+ this.radarAltitude = FlightGlobals.ActiveVessel.terrainAltitude > 0.0
+ ? FlightGlobals.ship_altitude - FlightGlobals.ActiveVessel.terrainAltitude
+ : FlightGlobals.ship_altitude;
DeltaV = Math.Sqrt((2 * this.gravity * this.radarAltitude) + Math.Pow(FlightGlobals.ship_verticalSpeed, 2.0));
Altitude = Math.Pow(DeltaV, 2.0) / (2.0 * this.acceleration);
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/ThrustOffsetAngle.cs
@@ -1,1 +1,66 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+#region Using Directives
+
+using KerbalEngineer.Flight.Sections;
+using KerbalEngineer.Helpers;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+ public class ThrustOffsetAngle : ReadoutModule
+ {
+ #region Constructors
+
+ public ThrustOffsetAngle()
+ {
+ this.Name = "Thrust offset angle";
+ this.Category = ReadoutCategory.GetCategory("Vessel");
+ this.HelpString = "Thrust angle offset due to vessel asymmetries and gimballing";
+ this.IsDefault = true;
+ }
+
+ #endregion
+
+ #region Methods: public
+
+ public override void Draw(SectionModule section)
+ {
+ if (SimulationProcessor.ShowDetails)
+ {
+ this.DrawLine(Units.ToAngle(SimulationProcessor.LastStage.thrustOffsetAngle, 1), section.IsHud);
+ }
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(SimulationProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ SimulationProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
+
--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Vessel/ThrustTorque.cs
@@ -1,1 +1,66 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+#region Using Directives
+
+using KerbalEngineer.Flight.Sections;
+using KerbalEngineer.Helpers;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Vessel
+{
+ public class ThrustTorque : ReadoutModule
+ {
+ #region Constructors
+
+ public ThrustTorque()
+ {
+ this.Name = "Thrust torque";
+ this.Category = ReadoutCategory.GetCategory("Vessel");
+ this.HelpString = "Thrust torque due to vessel asymmetries and gimballing";
+ this.IsDefault = true;
+ }
+
+ #endregion
+
+ #region Methods: public
+
+ public override void Draw(SectionModule section)
+ {
+ if (SimulationProcessor.ShowDetails)
+ {
+ this.DrawLine(Units.ToTorque(SimulationProcessor.LastStage.maxThrustTorque), section.IsHud);
+ }
+ }
+
+ public override void Reset()
+ {
+ FlightEngineerCore.Instance.AddUpdatable(SimulationProcessor.Instance);
+ }
+
+ public override void Update()
+ {
+ SimulationProcessor.RequestUpdate();
+ }
+
+ #endregion
+ }
+}
+
--- a/KerbalEngineer/Flight/Sections/SectionEditor.cs
+++ b/KerbalEngineer/Flight/Sections/SectionEditor.cs
@@ -119,7 +119,7 @@
try
{
this.InitialiseStyles();
- ReadoutCategory.Selected = ReadoutCategory.GetCategory("Orbital");
+ //ReadoutCategory.Selected = ReadoutCategory.GetCategory("Orbital");
RenderingManager.AddToPostDrawQueue(0, this.Draw);
}
catch (Exception ex)
--- 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/Flight/Sections/SectionModule.cs
+++ b/KerbalEngineer/Flight/Sections/SectionModule.cs
@@ -168,6 +168,11 @@
public bool IsVisible { get; set; }
/// <summary>
+ /// Gets the number of drawn readout lines.
+ /// </summary>
+ public int LineCount { get; private set; }
+
+ /// <summary>
/// Gets and sets the name of the section.
/// </summary>
public string Name { get; set; }
@@ -351,6 +356,7 @@
GUILayout.BeginVertical(this.boxStyle);
}
+ this.LineCount = 0;
if (this.ReadoutModules.Count > 0)
{
foreach (var readout in this.ReadoutModules)
@@ -358,11 +364,13 @@
readout.LineCountStart();
readout.Draw(this);
readout.LineCountEnd();
+ this.LineCount += readout.LineCount;
}
}
else
{
GUILayout.Label("No readouts are installed.", this.messageStyle);
+ this.LineCount = 1;
}
if (!this.IsHud)
--- a/KerbalEngineer/Flight/Sections/SectionWindow.cs
+++ b/KerbalEngineer/Flight/Sections/SectionWindow.cs
@@ -60,8 +60,8 @@
#region Fields
+ private GUIStyle hudWindowBgStyle;
private GUIStyle hudWindowStyle;
- private GUIStyle hudWindowBgStyle;
private GUIStyle windowStyle;
#endregion
@@ -118,7 +118,7 @@
/// </summary>
private void Draw()
{
- if (this.ParentSection == null || !this.ParentSection.IsVisible || (DisplayStack.Instance.Hidden && !this.ParentSection.IsHud))
+ if (this.ParentSection == null || !this.ParentSection.IsVisible || (DisplayStack.Instance.Hidden && !this.ParentSection.IsHud) || !FlightEngineerCore.IsDisplayable)
{
return;
}
@@ -130,9 +130,11 @@
this.resizeRequested = false;
}
GUI.skin = null;
- this.windowPosition = GUILayout.Window(this.windowId, this.windowPosition, this.Window, string.Empty,
- (!this.ParentSection.IsHud || this.ParentSection.IsEditorVisible) ? this.windowStyle
- : this.ParentSection.IsHudBackground ? this.hudWindowBgStyle : this.hudWindowStyle).ClampToScreen();
+ this.windowPosition = GUILayout.Window(this.windowId, this.windowPosition, this.Window, string.Empty,
+ (!this.ParentSection.IsHud || this.ParentSection.IsEditorVisible) ? this.windowStyle
+ : this.ParentSection.IsHudBackground && this.ParentSection.LineCount > 0
+ ? this.hudWindowBgStyle
+ : this.hudWindowStyle).ClampToScreen();
this.ParentSection.FloatingPositionX = this.windowPosition.x;
this.ParentSection.FloatingPositionY = this.windowPosition.y;
}
--- 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
}
}
--- /dev/null
+++ b/KerbalEngineer/Helpers/Averager.cs
@@ -1,1 +1,79 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+using System;
+
+namespace KerbalEngineer
+{
+ public class VectorAverager
+ {
+ private Vector3d sum = Vector3d.zero;
+ private uint count = 0;
+
+ public void Add(Vector3d v) {
+ sum += v;
+ count += 1;
+ }
+
+ public Vector3d Get() {
+ if (count > 0) {
+ return sum / count;
+ } else {
+ return Vector3d.zero;
+ }
+ }
+
+ public void Reset()
+ {
+ sum = Vector3d.zero;
+ count = 0;
+ }
+ }
+
+ public class WeightedVectorAverager
+ {
+ private Vector3d sum = Vector3d.zero;
+ private double totalweight = 0;
+
+ public void Add(Vector3d v, double weight) {
+ sum += v * weight;
+ totalweight += weight;
+ }
+
+ public Vector3d Get() {
+ if (totalweight > 0) {
+ return sum / totalweight;
+ } else {
+ return Vector3d.zero;
+ }
+ }
+
+ public double GetTotalWeight() {
+ return totalweight;
+ }
+
+ public void Reset()
+ {
+ sum = Vector3d.zero;
+ totalweight = 0.0;
+ }
+ }
+}
+
+
--- /dev/null
+++ b/KerbalEngineer/Helpers/ForceAccumulator.cs
@@ -1,1 +1,130 @@
+//
+// Kerbal Engineer Redux
+//
+// Copyright (C) 2014 CYBUTEK
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+using System;
+using System.Collections.Generic;
+using KerbalEngineer.VesselSimulator;
+
+namespace KerbalEngineer
+{
+ // a (force, application point) tuple
+ public class AppliedForce
+ {
+ private static readonly Pool<AppliedForce> pool = new Pool<AppliedForce>(Create, Reset);
+
+ public Vector3d vector;
+ public Vector3d applicationPoint;
+
+ static private AppliedForce Create()
+ {
+ return new AppliedForce();
+ }
+
+ static private void Reset(AppliedForce appliedForce) { }
+
+ static public AppliedForce New(Vector3d vector, Vector3d applicationPoint)
+ {
+ AppliedForce force = pool.Borrow();
+ force.vector = vector;
+ force.applicationPoint = applicationPoint;
+ return force;
+ }
+
+ public void Release()
+ {
+ pool.Release(this);
+ }
+
+
+ }
+
+ // This class was mostly adapted from FARCenterQuery, part of FAR, by ferram4, GPLv3
+ // https://github.com/ferram4/Ferram-Aerospace-Research/blob/master/FerramAerospaceResearch/FARCenterQuery.cs
+ // Also see https://en.wikipedia.org/wiki/Resultant_force
+
+ // It accumulates forces and their points of applications, and provides methods for
+ // calculating the effective torque at any position, as well as the minimum-torque net force application point.
+ //
+ // The latter is a non-trivial issue; there is a 1-dimensional line of physically-equivalent solutions parallel
+ // to the resulting force vector; the solution closest to the weighted average of force positions is chosen.
+ // In the case of non-parallel forces, there usually is an infinite number of such lines, all of which have
+ // some amount of residual torque. The line with the least amount of residual torque is chosen.
+ public class ForceAccumulator
+ {
+ // Total force.
+ private Vector3d totalForce = Vector3d.zero;
+ // Torque needed to compensate if force were applied at origin.
+ private Vector3d totalZeroOriginTorque = Vector3d.zero;
+
+ // Weighted average of force application points.
+ private WeightedVectorAverager avgApplicationPoint = new WeightedVectorAverager();
+
+ // Feed an force to the accumulator.
+ public void AddForce(Vector3d applicationPoint, Vector3d force)
+ {
+ totalForce += force;
+ totalZeroOriginTorque += Vector3d.Cross(applicationPoint, force);
+ avgApplicationPoint.Add(applicationPoint, force.magnitude);
+ }
+
+ public Vector3d GetAverageForceApplicationPoint() {
+ return avgApplicationPoint.Get();
+ }
+
+ public void AddForce(AppliedForce force) {
+ AddForce(force.applicationPoint, force.vector);
+ }
+
+ // Residual torque for given force application point.
+ public Vector3d TorqueAt(Vector3d origin)
+ {
+ return totalZeroOriginTorque - Vector3d.Cross(origin, totalForce);
+ }
+
+ // Total force vector.
+ public Vector3d GetTotalForce()
+ {
+ return totalForce;
+ }
+
+ // Returns the minimum-residual-torque force application point that is closest to origin.
+ // Note that TorqueAt(GetMinTorquePos()) is always parallel to totalForce.
+ public Vector3d GetMinTorqueForceApplicationPoint(Vector3d origin)
+ {
+ double fmag = totalForce.sqrMagnitude;
+ if (fmag <= 0) {
+ return origin;
+ }
+
+ return origin + Vector3d.Cross(totalForce, TorqueAt(origin)) / fmag;
+ }
+
+ public Vector3d GetMinTorqueForceApplicationPoint()
+ {
+ return GetMinTorqueForceApplicationPoint(avgApplicationPoint.Get());
+ }
+
+ public void Reset()
+ {
+ totalForce = Vector3d.zero;
+ totalZeroOriginTorque = Vector3d.zero;
+ avgApplicationPoint.Reset();
+ }
+ }
+}
--- /dev/null
+++ b/KerbalEngineer/Helpers/Pool.cs
@@ -1,1 +1,53 @@
+using System.Collections.Generic;
+namespace KerbalEngineer
+{
+ /// <summary>
+ /// Pool of object
+ /// </summary>
+ public class Pool<T> {
+
+ private readonly Stack<T> values = new Stack<T>();
+
+ private readonly CreateDelegate<T> create;
+ private readonly ResetDelegate<T> reset;
+
+ public delegate R CreateDelegate<out R>();
+ public delegate void ResetDelegate<in T1>(T1 a);
+
+ /// <summary>
+ /// Creates an empty pool with the specified object creation and reset delegates.
+ /// </summary>
+ public Pool(CreateDelegate<T> create, ResetDelegate<T> reset) {
+ this.create = create;
+ this.reset = reset;
+ }
+
+ /// <summary>
+ /// Borrows an object from the pool.
+ /// </summary>
+ public T Borrow() {
+ lock (values) {
+ return values.Count > 0 ? values.Pop() : create();
+ }
+ }
+
+ /// <summary>
+ /// Release an object, reset it and returns it to the pool.
+ /// </summary>
+ public void Release(T value) {
+ reset(value);
+ lock (values) {
+ values.Push(value);
+ }
+ }
+
+ /// <summary>
+ /// Current size of the pool.
+ /// </summary>
+ public int Count()
+ {
+ return values.Count;
+ }
+ }
+}
--- 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
@@ -17,28 +17,57 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using System;
-
-#endregion
-
namespace KerbalEngineer.Helpers
{
+ using System;
+
public static class Units
{
- #region Methods: public
-
- public static string Concat(double value1, double value2, int decimals = 1)
+ public const double GRAVITY = 9.80665;
+
+ public static string Concat(int value1, int value2)
+ {
+ return value1 + " / " + value2;
+ }
+
+ public static string ConcatF(double value1, double value2, int decimals = 1)
{
return value1.ToString("F" + decimals) + " / " + value2.ToString("F" + decimals);
}
- public static string Concat(double value1, double value2, double value3, int decimals = 1)
+ public static string ConcatF(double value1, double value2, double value3, int decimals = 1)
{
return value1.ToString("F" + decimals) + " / " + value2.ToString("F" + decimals) + " / " + value3.ToString("F" + decimals);
}
+ public static string ConcatN(double value1, double value2, int decimals = 1)
+ {
+ return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals);
+ }
+
+ public static string ConcatN(double value1, double value2, double value3, int decimals = 1)
+ {
+ return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals) + " / " + value3.ToString("N" + decimals);
+ }
+
+ public static string Cost(double value, int decimals = 1)
+ {
+ if (value >= 1000000.0)
+ {
+ return (value / 1000.0).ToString("N" + decimals) + "K";
+ }
+ return value.ToString("N" + decimals);
+ }
+
+ public static string Cost(double value1, double value2, int decimals = 1)
+ {
+ if (value1 >= 1000000.0 || value2 >= 1000000.0)
+ {
+ return (value1 / 1000.0).ToString("N" + decimals) + " / " + (value2 / 1000.0).ToString("N" + decimals) + "K";
+ }
+ return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals);
+ }
+
public static string ToAcceleration(double value, int decimals = 2)
{
return value.ToString("N" + decimals) + "m/s²";
@@ -52,6 +81,17 @@
public static string ToAngle(double value, int decimals = 5)
{
return value.ToString("F" + decimals) + "°";
+ }
+
+ public static string ToAngleDMS(double value)
+ {
+ double absAngle = Math.Abs(value);
+ int deg = (int)Math.Floor(absAngle);
+ double rem = absAngle - deg;
+ 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);
}
public static string ToDistance(double value, int decimals = 1)
@@ -83,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";
@@ -90,19 +135,34 @@
public static string ToForce(double value1, double value2)
{
- var format1 = (value1 < 100000.0) ? (value1 < 10000.0) ? (value1 < 100.0) ? (Math.Abs(value1) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0";
- var format2 = (value2 < 100000.0) ? (value2 < 10000.0) ? (value2 < 100.0) ? (Math.Abs(value2) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0";
+ string format1 = (value1 < 100000.0) ? (value1 < 10000.0) ? (value1 < 100.0) ? (Math.Abs(value1) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0";
+ string format2 = (value2 < 100000.0) ? (value2 < 10000.0) ? (value2 < 100.0) ? (Math.Abs(value2) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0";
return value1.ToString(format1) + " / " + value2.ToString(format2) + "kN";
}
+ 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)
+ {
+ return value.ToString("N" + decimals + 2) + "t";
+ }
+
value *= 1000.0;
return value.ToString("N" + decimals) + "kg";
}
public static string ToMass(double value1, double value2, int decimals = 0)
{
+ if (value1 >= 1000.0f || value2 >= 1000.0f)
+ {
+ return value1.ToString("N" + decimals + 2) + " / " + value2.ToString("N" + decimals + 2) + "t";
+ }
+
value1 *= 1000.0;
value2 *= 1000.0;
return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals) + "kg";
@@ -128,11 +188,24 @@
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);
}
- #endregion
+ public static string ToTorque(double value)
+ {
+ return value.ToString((value < 100.0) ? (Math.Abs(value) < Double.Epsilon) ? "N0" : "N1" : "N0") + "kNm";
+ }
}
}
--- a/KerbalEngineer/KerbalEngineer.csproj
+++ b/KerbalEngineer/KerbalEngineer.csproj
@@ -48,9 +48,11 @@
<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\FlightEngineerPartless.cs" />
<Compile Include="Flight\Presets\Preset.cs" />
+ <Compile Include="Flight\Readouts\Miscellaneous\SystemTime.cs" />
+ <Compile Include="Flight\Readouts\Miscellaneous\VectoredThrustToggle.cs" />
<Compile Include="Flight\Readouts\Miscellaneous\TimeReference.cs" />
<Compile Include="Flight\Readouts\Miscellaneous\Separator.cs" />
<Compile Include="Flight\Readouts\Miscellaneous\GuiSizeAdjustor.cs" />
@@ -58,6 +60,18 @@
<Compile Include="Flight\Readouts\Orbital\AngleToEquatorialAscendingNode.cs" />
<Compile Include="Flight\Readouts\Orbital\AngleToRetrograde.cs" />
<Compile Include="Flight\Readouts\Orbital\AngleToPrograde.cs" />
+ <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeRadialDeltaV.cs" />
+ <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\ManoeuvreProcessor.cs" />
+ <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeTimeToHalfBurn.cs" />
+ <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeTimeToManoeuvre.cs" />
+ <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeHalfBurnTime.cs" />
+ <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeBurnTime.cs" />
+ <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeAngleToRetrograde.cs" />
+ <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeNormalDeltaV.cs" />
+ <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeAngleToPrograde.cs" />
+ <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeTotalDeltaV.cs" />
+ <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeProgradeDeltaV.cs" />
+ <Compile Include="Flight\Readouts\Orbital\MeanAnomalyAtEpoc.cs" />
<Compile Include="Flight\Readouts\Orbital\MeanAnomaly.cs" />
<Compile Include="Flight\Readouts\Orbital\EccentricAnomaly.cs" />
<Compile Include="Flight\Readouts\Orbital\ArgumentOfPeriapsis.cs" />
@@ -76,7 +90,27 @@
<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" />
+ <Compile Include="Flight\Readouts\Vessel\HeadingRate.cs" />
+ <Compile Include="Flight\Readouts\Vessel\RollRate.cs" />
+ <Compile Include="Flight\Readouts\Vessel\Roll.cs" />
+ <Compile Include="Flight\Readouts\Vessel\Pitch.cs" />
+ <Compile Include="Flight\Readouts\Vessel\Heading.cs" />
+ <Compile Include="Flight\Readouts\Vessel\PartCount.cs" />
<Compile Include="Flight\Readouts\Vessel\SuicideBurnDeltaV.cs" />
<Compile Include="Flight\Readouts\Vessel\SuicideBurnAltitude.cs" />
<Compile Include="Flight\Readouts\Vessel\SuicideBurnDistance.cs" />
@@ -92,8 +126,12 @@
<Compile Include="Flight\Readouts\Vessel\SuicideBurnProcessor.cs" />
<Compile Include="Flight\Readouts\Vessel\SurfaceThrustToWeight.cs" />
<Compile Include="Flight\Readouts\Surface\Situation.cs" />
+ <Compile Include="Flight\Readouts\Vessel\ThrustOffsetAngle.cs" />
+ <Compile Include="Flight\Readouts\Vessel\ThrustTorque.cs" />
<Compile Include="GuiDisplaySize.cs" />
<Compile Include="Helpers\AngleHelper.cs" />
+ <Compile Include="Helpers\Averager.cs" />
+ <Compile Include="Helpers\ForceAccumulator.cs" />
<Compile Include="Helpers\TextureHelper.cs" />
<Compile Include="Helpers\Units.cs" />
<Compile Include="Helpers\TimeFormatter.cs" />
@@ -174,6 +212,7 @@
<Compile Include="UIControls\WindowObject.cs" />
<Compile Include="VesselSimulator\AttachNodeSim.cs" />
<Compile Include="VesselSimulator\EngineSim.cs" />
+ <Compile Include="Helpers\Pool.cs" />
<Compile Include="VesselSimulator\PartSim.cs" />
<Compile Include="VesselSimulator\ResourceContainer.cs" />
<Compile Include="VesselSimulator\SimManager.cs" />
@@ -198,6 +237,7 @@
<Private>False</Private>
</Reference>
</ItemGroup>
+ <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="PostBuildMacros">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
--- a/KerbalEngineer/VesselSimulator/AttachNodeSim.cs
+++ b/KerbalEngineer/VesselSimulator/AttachNodeSim.cs
@@ -19,42 +19,62 @@
#region Using Directives
-using System;
-using System.Text;
-
#endregion
namespace KerbalEngineer.VesselSimulator
{
+ using System;
+ using System.Text;
+
internal class AttachNodeSim
{
+
+ private static readonly Pool<AttachNodeSim> pool = new Pool<AttachNodeSim>(Create, Reset);
+
public PartSim attachedPartSim;
public String id;
public AttachNode.NodeType nodeType;
- public AttachNodeSim(PartSim partSim, String newId, AttachNode.NodeType newNodeType)
+ private static AttachNodeSim Create()
{
- this.attachedPartSim = partSim;
- this.nodeType = newNodeType;
- this.id = newId;
+ return new AttachNodeSim();
+ }
+
+ public static AttachNodeSim New(PartSim partSim, String newId, AttachNode.NodeType newNodeType)
+ {
+ AttachNodeSim nodeSim = pool.Borrow();
+
+ nodeSim.attachedPartSim = partSim;
+ nodeSim.nodeType = newNodeType;
+ nodeSim.id = newId;
+
+ return nodeSim;
+ }
+
+ static private void Reset(AttachNodeSim attachNodeSim) { }
+
+
+ public void Release()
+ {
+ pool.Release(this);
}
public void DumpToBuffer(StringBuilder buffer)
{
- if (this.attachedPartSim == null)
+ if (attachedPartSim == null)
{
buffer.Append("<staged>:<n>");
}
else
{
- buffer.Append(this.attachedPartSim.name);
+ buffer.Append(attachedPartSim.name);
buffer.Append(":");
- buffer.Append(this.attachedPartSim.partId);
+ buffer.Append(attachedPartSim.partId);
}
buffer.Append("#");
- buffer.Append(this.nodeType);
+ buffer.Append(nodeType);
buffer.Append(":");
- buffer.Append(this.id);
+ buffer.Append(id);
}
}
}
--- a/KerbalEngineer/VesselSimulator/EngineSim.cs
+++ b/KerbalEngineer/VesselSimulator/EngineSim.cs
@@ -17,297 +17,330 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using UnityEngine;
-
-#endregion
-
namespace KerbalEngineer.VesselSimulator
{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+ using Editor;
+ using Helpers;
+ using UnityEngine;
+
public class EngineSim
{
+ private static readonly Pool<EngineSim> pool = new Pool<EngineSim>(Create, Reset);
+
private readonly ResourceContainer resourceConsumptions = new ResourceContainer();
public double actualThrust = 0;
public bool isActive = false;
public double isp = 0;
public PartSim partSim;
+ public List<AppliedForce> appliedForces = new List<AppliedForce>();
+ public float maxMach;
public double thrust = 0;
// Add thrust vector to account for directional losses
public Vector3 thrustVec;
- public EngineSim(PartSim theEngine,
+ private static EngineSim Create()
+ {
+ return new EngineSim();
+ }
+
+ private static void Reset(EngineSim engineSim)
+ {
+ engineSim.resourceConsumptions.Reset();
+ engineSim.actualThrust = 0;
+ engineSim.isActive = false;
+ engineSim.isp = 0;
+ for (int i = 0; i < engineSim.appliedForces.Count; i++)
+ {
+ engineSim.appliedForces[i].Release();
+ }
+ engineSim.appliedForces.Clear();
+ engineSim.thrust = 0;
+ engineSim.maxMach = 0f;
+ }
+
+ public void Release()
+ {
+ pool.Release(this);
+ }
+
+ public static EngineSim New(PartSim theEngine,
double atmosphere,
- double velocity,
- float maxThrust,
- float minThrust,
+ float machNumber,
+ float maxFuelFlow,
+ float minFuelFlow,
float thrustPercentage,
- float requestedThrust,
Vector3 vecThrust,
- float realIsp,
FloatCurve atmosphereCurve,
- FloatCurve velocityCurve,
+ bool atmChangeFlow,
+ FloatCurve atmCurve,
+ FloatCurve velCurve,
+ float currentThrottle,
+ float IspG,
bool throttleLocked,
List<Propellant> propellants,
bool active,
- bool correctThrust)
- {
- StringBuilder buffer = null;
- //MonoBehaviour.print("Create EngineSim for " + theEngine.name);
- //MonoBehaviour.print("maxThrust = " + maxThrust);
- //MonoBehaviour.print("minThrust = " + minThrust);
- //MonoBehaviour.print("thrustPercentage = " + thrustPercentage);
- //MonoBehaviour.print("requestedThrust = " + requestedThrust);
- //MonoBehaviour.print("velocity = " + velocity);
-
- this.partSim = theEngine;
-
- this.isActive = active;
- this.thrust = (maxThrust - minThrust) * (thrustPercentage / 100f) + minThrust;
- //MonoBehaviour.print("thrust = " + thrust);
-
- this.thrustVec = vecThrust;
-
- double flowRate = 0d;
- if (this.partSim.hasVessel)
- {
- //MonoBehaviour.print("hasVessel is true");
- this.actualThrust = isActive ? requestedThrust : 0.0;
- if (velocityCurve != null)
- {
- this.actualThrust *= velocityCurve.Evaluate((float)velocity);
- //MonoBehaviour.print("actualThrust at velocity = " + actualThrust);
- }
-
- this.isp = atmosphereCurve.Evaluate((float)this.partSim.part.staticPressureAtm);
- if (this.isp == 0d)
- {
- MonoBehaviour.print("Isp at " + this.partSim.part.staticPressureAtm + " is zero. Flow rate will be NaN");
- }
-
- if (correctThrust && realIsp == 0)
- {
- float ispsl = atmosphereCurve.Evaluate(0);
- if (ispsl != 0)
+ float resultingThrust,
+ List<Transform> thrustTransforms,
+ LogMsg log)
+ {
+ EngineSim engineSim = pool.Borrow();
+
+ engineSim.isp = 0.0;
+ engineSim.maxMach = 0.0f;
+ engineSim.actualThrust = 0.0;
+ engineSim.partSim = theEngine;
+ engineSim.isActive = active;
+ engineSim.thrustVec = vecThrust;
+ engineSim.resourceConsumptions.Reset();
+ engineSim.appliedForces.Clear();
+
+ double flowRate = 0.0;
+ if (engineSim.partSim.hasVessel)
+ {
+ 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 (throttleLocked)
+ {
+ flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
+ }
+ else
+ {
+ if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false)
{
- this.thrust = this.thrust * this.isp / ispsl;
+ flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp);
}
else
{
- MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust.");
+ flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
}
- //MonoBehaviour.print("corrected thrust = " + thrust);
- }
-
- if (velocityCurve != null)
- {
- this.thrust *= velocityCurve.Evaluate((float)velocity);
- //MonoBehaviour.print("thrust at velocity = " + thrust);
- }
-
- if (throttleLocked)
- {
- //MonoBehaviour.print("throttleLocked is true");
- flowRate = this.thrust / (this.isp * 9.81d);
- }
- else
- {
- if (this.partSim.isLanded)
- {
- //MonoBehaviour.print("partSim.isLanded is true, mainThrottle = " + FlightInputHandler.state.mainThrottle);
- flowRate = Math.Max(0.000001d, this.thrust * FlightInputHandler.state.mainThrottle) / (this.isp * 9.81d);
- }
- else
- {
- if (requestedThrust > 0)
- {
- if (velocityCurve != null)
+ }
+ }
+ else
+ {
+ 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);
+ flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
+ }
+
+ if (log != null) log.buf.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;
+
+ float flowMass = 0f;
+ for (int i = 0; i < propellants.Count; ++i)
+ {
+ Propellant propellant = propellants[i];
+ 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)
+ {
+ Propellant propellant = propellants[i];
+
+ if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir")
+ {
+ continue;
+ }
+
+ double consumptionRate = propellant.ratio * flowRate / flowMass;
+ 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);
+ }
+
+ double thrustPerThrustTransform = engineSim.thrust / thrustTransforms.Count;
+ for (int i = 0; i < thrustTransforms.Count; i++)
+ {
+ Transform thrustTransform = thrustTransforms[i];
+ Vector3d direction = thrustTransform.forward.normalized;
+ Vector3d position = thrustTransform.position;
+
+ AppliedForce appliedForce = AppliedForce.New(direction * thrustPerThrustTransform, position);
+ engineSim.appliedForces.Add(appliedForce);
+ }
+
+ return engineSim;
+ }
+
+ public ResourceContainer ResourceConsumptions
+ {
+ get
+ {
+ return resourceConsumptions;
+ }
+ }
+
+ public static double GetExhaustVelocity(double isp)
+ {
+ return isp * Units.GRAVITY;
+ }
+
+ public static float GetFlowModifier(bool atmChangeFlow, FloatCurve atmCurve, double atmDensity, FloatCurve velCurve, float machNumber, ref float maxMach)
+ {
+ float flowModifier = 1.0f;
+ if (atmChangeFlow)
+ {
+ flowModifier = (float)(atmDensity / 1.225);
+ if (atmCurve != null)
+ {
+ flowModifier = atmCurve.Evaluate(flowModifier);
+ }
+ }
+ if (velCurve != null)
+ {
+ flowModifier = flowModifier * velCurve.Evaluate(machNumber);
+ maxMach = velCurve.maxTime;
+ }
+ if (flowModifier < float.Epsilon)
+ {
+ flowModifier = float.Epsilon;
+ }
+ return flowModifier;
+ }
+
+ public static double GetFlowRate(double thrust, double isp)
+ {
+ return thrust / GetExhaustVelocity(isp);
+ }
+
+ public static float GetThrottlePercent(float currentThrottle, float thrustPercentage)
+ {
+ return currentThrottle * GetThrustPercent(thrustPercentage);
+ }
+
+ public static double GetThrust(double flowRate, double isp)
+ {
+ return flowRate * GetExhaustVelocity(isp);
+ }
+
+ public static float GetThrustPercent(float thrustPercentage)
+ {
+ return thrustPercentage * 0.01f;
+ }
+
+ public void DumpEngineToBuffer(StringBuilder buffer, String prefix)
+ {
+ buffer.Append(prefix);
+ buffer.AppendFormat("[thrust = {0:g6}, actual = {1:g6}, isp = {2:g6}\n", thrust, actualThrust, isp);
+ }
+
+ // A dictionary to hold a set of parts for each resource
+ Dictionary<int, HashSet<PartSim>> sourcePartSets = new Dictionary<int, HashSet<PartSim>>();
+
+ Dictionary<int, HashSet<PartSim>> stagePartSets = new Dictionary<int, HashSet<PartSim>>();
+
+ HashSet<PartSim> visited = new HashSet<PartSim>();
+
+ public bool SetResourceDrains(List<PartSim> allParts, List<PartSim> allFuelLines, HashSet<PartSim> drainingParts)
+ {
+ LogMsg log = null;
+
+ foreach (HashSet<PartSim> sourcePartSet in sourcePartSets.Values)
+ {
+ sourcePartSet.Clear();
+ }
+
+ for (int index = 0; index < this.resourceConsumptions.Types.Count; index++)
+ {
+ int type = this.resourceConsumptions.Types[index];
+
+ HashSet<PartSim> sourcePartSet;
+ if (!sourcePartSets.TryGetValue(type, out sourcePartSet))
+ {
+ sourcePartSet = new HashSet<PartSim>();
+ sourcePartSets.Add(type, sourcePartSet);
+ }
+
+ switch (ResourceContainer.GetResourceFlowMode(type))
+ {
+ case ResourceFlowMode.NO_FLOW:
+ if (partSim.resources[type] > SimManager.RESOURCE_MIN && partSim.resourceFlowStates[type] != 0)
+ {
+ //sourcePartSet = new HashSet<PartSim>();
+ //MonoBehaviour.print("SetResourceDrains(" + name + ":" + partId + ") setting sources to just this");
+ sourcePartSet.Add(partSim);
+ }
+ break;
+
+ case ResourceFlowMode.ALL_VESSEL:
+ for (int i = 0; i < allParts.Count; i++)
+ {
+ PartSim aPartSim = allParts[i];
+ if (aPartSim.resources[type] > SimManager.RESOURCE_MIN && aPartSim.resourceFlowStates[type] != 0)
{
- requestedThrust *= velocityCurve.Evaluate((float)velocity);
- //MonoBehaviour.print("requestedThrust at velocity = " + requestedThrust);
- }
-
- //MonoBehaviour.print("requestedThrust > 0");
- flowRate = requestedThrust / (this.isp * 9.81d);
- }
- else
- {
- //MonoBehaviour.print("requestedThrust <= 0");
- flowRate = this.thrust / (this.isp * 9.81d);
- }
- }
- }
- }
- else
- {
- //MonoBehaviour.print("hasVessel is false");
- this.isp = atmosphereCurve.Evaluate((float)atmosphere);
- if (this.isp == 0d)
- {
- MonoBehaviour.print("Isp at " + atmosphere + " is zero. Flow rate will be NaN");
- }
- if (correctThrust)
- {
- float ispsl = atmosphereCurve.Evaluate(0);
- if (ispsl != 0)
- {
- this.thrust = this.thrust * this.isp / ispsl;
- }
- else
- {
- MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust.");
- }
- //MonoBehaviour.print("corrected thrust = " + thrust);
- }
-
- if (velocityCurve != null)
- {
- this.thrust *= velocityCurve.Evaluate((float)velocity);
- //MonoBehaviour.print("thrust at velocity = " + thrust);
- }
-
- flowRate = this.thrust / (this.isp * 9.81d);
- }
-
- if (SimManager.logOutput)
- {
- buffer = new StringBuilder(1024);
- buffer.AppendFormat("flowRate = {0:g6}\n", flowRate);
- }
-
- float flowMass = 0f;
- foreach (Propellant propellant in propellants)
- {
- flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);
- }
-
- if (SimManager.logOutput)
- {
- buffer.AppendFormat("flowMass = {0:g6}\n", flowMass);
- }
-
- foreach (Propellant propellant in propellants)
- {
- if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir")
- {
- continue;
- }
-
- double consumptionRate = propellant.ratio * flowRate / flowMass;
- if (SimManager.logOutput)
- {
- buffer.AppendFormat("Add consumption({0}, {1}:{2:d}) = {3:g6}\n", ResourceContainer.GetResourceName(propellant.id), theEngine.name, theEngine.partId, consumptionRate);
- }
- this.resourceConsumptions.Add(propellant.id, consumptionRate);
- }
-
- if (SimManager.logOutput)
- {
- MonoBehaviour.print(buffer);
- }
- }
-
- public ResourceContainer ResourceConsumptions
- {
- get { return this.resourceConsumptions; }
- }
-
- public bool SetResourceDrains(List<PartSim> allParts, List<PartSim> allFuelLines, HashSet<PartSim> drainingParts)
- {
- LogMsg log = null;
-
- // A dictionary to hold a set of parts for each resource
- Dictionary<int, HashSet<PartSim>> sourcePartSets = new Dictionary<int, HashSet<PartSim>>();
-
- foreach (int type in this.resourceConsumptions.Types)
- {
- HashSet<PartSim> sourcePartSet = null;
- switch (ResourceContainer.GetResourceFlowMode(type))
- {
- case ResourceFlowMode.NO_FLOW:
- if (this.partSim.resources[type] > SimManager.RESOURCE_MIN)
- {
- sourcePartSet = new HashSet<PartSim>();
- //MonoBehaviour.print("SetResourceDrains(" + name + ":" + partId + ") setting sources to just this");
- sourcePartSet.Add(this.partSim);
- }
- break;
-
- case ResourceFlowMode.ALL_VESSEL:
- foreach (PartSim aPartSim in allParts)
- {
- if (aPartSim.resources[type] > SimManager.RESOURCE_MIN)
- {
- if (sourcePartSet == null)
- {
- sourcePartSet = new HashSet<PartSim>();
- }
-
sourcePartSet.Add(aPartSim);
}
}
break;
case ResourceFlowMode.STAGE_PRIORITY_FLOW:
- {
- Dictionary<int, HashSet<PartSim>> stagePartSets = new Dictionary<int, HashSet<PartSim>>();
- int maxStage = -1;
- foreach (PartSim aPartSim in allParts)
- {
- if (aPartSim.resources[type] > SimManager.RESOURCE_MIN)
+
+ foreach (HashSet<PartSim> stagePartSet in stagePartSets.Values)
+ {
+ stagePartSet.Clear();
+ }
+ var maxStage = -1;
+
+ //Logger.Log(type);
+ for (int i = 0; i < allParts.Count; i++)
+ {
+ var aPartSim = allParts[i];
+ if (aPartSim.resources[type] <= SimManager.RESOURCE_MIN || aPartSim.resourceFlowStates[type] == 0)
{
- //int stage = aPartSim.decoupledInStage; // Use the number of the stage the tank is decoupled in
- int stage = aPartSim.DecouplerCount(); // Use the count of decouplers between tank and root
- if (stage > maxStage)
- {
- maxStage = stage;
- }
- if (stagePartSets.ContainsKey(stage))
- {
- sourcePartSet = stagePartSets[stage];
- }
- else
- {
- sourcePartSet = new HashSet<PartSim>();
- stagePartSets.Add(stage, sourcePartSet);
- }
-
- sourcePartSet.Add(aPartSim);
+ continue;
}
- }
-
- while (maxStage >= 0)
- {
- if (stagePartSets.ContainsKey(maxStage))
+
+ int stage = aPartSim.DecouplerCount();
+ if (stage > maxStage)
{
- if (stagePartSets[maxStage].Count() > 0)
- {
- sourcePartSet = stagePartSets[maxStage];
- break;
- }
+ maxStage = stage;
}
- maxStage--;
- }
- }
+
+ if (!stagePartSets.TryGetValue(stage, out sourcePartSet))
+ {
+ sourcePartSet = new HashSet<PartSim>();
+ stagePartSets.Add(stage, sourcePartSet);
+ }
+ sourcePartSet.Add(aPartSim);
+ }
+
+ for (int j = 0; j <= maxStage; j++)
+ {
+ HashSet<PartSim> stagePartSet;
+ if (stagePartSets.TryGetValue(j, out stagePartSet) && stagePartSet.Count > 0)
+ {
+ sourcePartSet = stagePartSet;
+ }
+ }
break;
case ResourceFlowMode.STACK_PRIORITY_SEARCH:
- HashSet<PartSim> visited = new HashSet<PartSim>();
+ visited.Clear();
if (SimManager.logOutput)
{
log = new LogMsg();
- log.buf.AppendLine("Find " + ResourceContainer.GetResourceName(type) + " sources for " + this.partSim.name + ":" + this.partSim.partId);
- }
- sourcePartSet = this.partSim.GetSourceSet(type, allParts, visited, log, "");
+ log.buf.AppendLine("Find " + ResourceContainer.GetResourceName(type) + " sources for " + partSim.name + ":" + partSim.partId);
+ }
+ partSim.GetSourceSet(type, allParts, visited, sourcePartSet, log, "");
if (SimManager.logOutput)
{
MonoBehaviour.print(log.buf);
@@ -315,11 +348,12 @@
break;
default:
- MonoBehaviour.print("SetResourceDrains(" + this.partSim.name + ":" + this.partSim.partId + ") Unexpected flow type for " + ResourceContainer.GetResourceName(type) + ")");
+ MonoBehaviour.print("SetResourceDrains(" + partSim.name + ":" + partSim.partId + ") Unexpected flow type for " + ResourceContainer.GetResourceName(type) + ")");
break;
}
- if (sourcePartSet != null && sourcePartSet.Count > 0)
+
+ if (sourcePartSet.Count > 0)
{
sourcePartSets[type] = sourcePartSet;
if (SimManager.logOutput)
@@ -334,47 +368,44 @@
}
}
}
-
+
// If we don't have sources for all the needed resources then return false without setting up any drains
- foreach (int type in this.resourceConsumptions.Types)
- {
- if (!sourcePartSets.ContainsKey(type))
+ for (int i = 0; i < this.resourceConsumptions.Types.Count; i++)
+ {
+ int type = this.resourceConsumptions.Types[i];
+ HashSet<PartSim> sourcePartSet;
+ if (!sourcePartSets.TryGetValue(type, out sourcePartSet) || sourcePartSet.Count == 0)
{
if (SimManager.logOutput)
{
MonoBehaviour.print("No source of " + ResourceContainer.GetResourceName(type));
}
- this.isActive = false;
+ isActive = false;
return false;
}
}
-
// Now we set the drains on the members of the sets and update the draining parts set
- foreach (int type in this.resourceConsumptions.Types)
- {
+ for (int i = 0; i < this.resourceConsumptions.Types.Count; i++)
+ {
+ int type = this.resourceConsumptions.Types[i];
HashSet<PartSim> sourcePartSet = sourcePartSets[type];
// Loop through the members of the set
- double amount = this.resourceConsumptions[type] / sourcePartSet.Count;
+ double amount = resourceConsumptions[type] / sourcePartSet.Count;
foreach (PartSim partSim in sourcePartSet)
{
if (SimManager.logOutput)
{
- MonoBehaviour.print("Adding drain of " + amount + " " + ResourceContainer.GetResourceName(type) + " to " + partSim.name + ":" + partSim.partId);
+ MonoBehaviour.print(
+ "Adding drain of " + amount + " " + ResourceContainer.GetResourceName(type) + " to " + partSim.name + ":" +
+ partSim.partId);
}
partSim.resourceDrains.Add(type, amount);
drainingParts.Add(partSim);
}
}
-
return true;
- }
-
- public void DumpEngineToBuffer(StringBuilder buffer, String prefix)
- {
- buffer.Append(prefix);
- buffer.AppendFormat("[thrust = {0:g6}, actual = {1:g6}, isp = {2:g6}\n", this.thrust, this.actualThrust, this.isp);
}
}
}
--- a/KerbalEngineer/VesselSimulator/PartSim.cs
+++ b/KerbalEngineer/VesselSimulator/PartSim.cs
@@ -17,25 +17,27 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using KerbalEngineer.Extensions;
-
-using UnityEngine;
-
-#endregion
namespace KerbalEngineer.VesselSimulator
{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using CompoundParts;
+ using Extensions;
+ using UnityEngine;
+
public class PartSim
{
+ private static readonly Pool<PartSim> pool = new Pool<PartSim>(Create, Reset);
+
private readonly List<AttachNodeSim> attachNodes = new List<AttachNodeSim>();
- public double baseMass = 0d;
+
+ public double realMass;
+ public double baseMass;
+ public double baseMassForCoM;
+ public Vector3d centerOfMass;
public double cost;
public int decoupledInStage;
public bool fuelCrossFeed;
@@ -54,7 +56,10 @@
public bool isLanded;
public bool isNoPhysics;
public bool isSepratron;
+ public bool isFairing;
public bool localCorrectThrust;
+ public float moduleMass;
+ public int stageIndex;
public String name;
public String noCrossFeedNodeKey;
public PartSim parent;
@@ -67,211 +72,227 @@
public double startMass = 0d;
public String vesselName;
public VesselType vesselType;
-
- public PartSim(Part thePart, int id, double atmosphere, LogMsg log)
- {
- this.part = thePart;
- this.partId = id;
- this.name = this.part.partInfo.name;
+
+
+ private static PartSim Create()
+ {
+ return new PartSim();
+ }
+
+ private static void Reset(PartSim partSim)
+ {
+ for (int i = 0; i < partSim.attachNodes.Count; i++)
+ {
+ partSim.attachNodes[i].Release();
+ }
+ partSim.attachNodes.Clear();
+ partSim.fuelTargets.Clear();
+ partSim.resourceDrains.Reset();
+ partSim.resourceFlowStates.Reset();
+ partSim.resources.Reset();
+ partSim.baseMass = 0d;
+ partSim.baseMassForCoM = 0d;
+ partSim.startMass = 0d;
+ }
+
+ public void Release()
+ {
+ pool.Release(this);
+ }
+
+ 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);
+
+ partSim.parent = null;
+ partSim.parentAttach = partSim.part.attachMode;
+ partSim.fuelCrossFeed = partSim.part.fuelCrossFeed;
+ partSim.noCrossFeedNodeKey = partSim.part.NoCrossFeedNodeKey;
+ partSim.decoupledInStage = partSim.DecoupledInStage(partSim.part);
+ partSim.isFuelLine = partSim.part.HasModule<CModuleFuelLine>();
+ partSim.isFuelTank = partSim.part is FuelTank;
+ partSim.isSepratron = partSim.IsSepratron();
+ partSim.inverseStage = partSim.part.inverseStage;
+ //MonoBehaviour.print("inverseStage = " + inverseStage);
+
+ partSim.cost = partSim.part.GetCostWet();
if (log != null)
{
- log.buf.AppendLine("Create PartSim for " + this.name);
- }
-
- this.parent = null;
- this.parentAttach = part.attachMode;
- this.fuelCrossFeed = this.part.fuelCrossFeed;
- this.noCrossFeedNodeKey = this.part.NoCrossFeedNodeKey;
- this.decoupledInStage = this.DecoupledInStage(this.part);
- this.isFuelLine = this.part is FuelLine;
- this.isFuelTank = this.part is FuelTank;
- this.isSepratron = this.IsSepratron();
- this.inverseStage = this.part.inverseStage;
- //MonoBehaviour.print("inverseStage = " + inverseStage);
-
- this.cost = this.part.GetCostWet();
+ 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
- this.isNoPhysics = this.part.HasModule<LaunchClamp>() ||
- this.part.physicalSignificance == Part.PhysicalSignificance.NONE ||
- this.part.PhysicsSignificance == 1;
-
- if (!this.isNoPhysics)
- {
- this.baseMass = this.part.mass;
- }
-
- if (SimManager.logOutput)
- {
- MonoBehaviour.print((this.isNoPhysics ? "Ignoring" : "Using") + " part.mass of " + this.part.mass);
- }
-
- foreach (PartResource resource in this.part.Resources)
- {
+ // The root part is never "no physics"
+ partSim.isNoPhysics = partSim.part.physicalSignificance == Part.PhysicalSignificance.NONE ||
+ partSim.part.PhysicsSignificance == 1;
+
+ if (partSim.part.HasModule<LaunchClamp>())
+ {
+ partSim.realMass = 0d;
+ if (log != null) log.buf.AppendLine("Ignoring mass of launch clamp");
+ }
+ else
+ {
+ partSim.realMass = partSim.part.mass;
+ if (log != null) log.buf.AppendLine("Using part.mass of " + partSim.part.mass);
+ }
+
+ for (int i = 0; i < partSim.part.Resources.Count; i++)
+ {
+ PartResource resource = partSim.part.Resources[i];
+
// Make sure it isn't NaN as this messes up the part mass and hence most of the values
// This can happen if a resource capacity is 0 and tweakable
if (!Double.IsNaN(resource.amount))
{
- if (SimManager.logOutput)
- {
- MonoBehaviour.print(resource.resourceName + " = " + resource.amount);
- }
-
- this.resources.Add(resource.info.id, resource.amount);
- this.resourceFlowStates.Add(resource.info.id, resource.flowState ? 1 : 0);
+ if (log != null)
+ log.buf.AppendLine(resource.resourceName + " = " + resource.amount);
+
+ partSim.resources.Add(resource.info.id, resource.amount);
+ partSim.resourceFlowStates.Add(resource.info.id, resource.flowState ? 1 : 0);
}
else
{
- MonoBehaviour.print(resource.resourceName + " is NaN. Skipping.");
- }
- }
-
- this.startMass = this.GetMass();
-
- this.hasVessel = (this.part.vessel != null);
- this.isLanded = this.hasVessel && this.part.vessel.Landed;
- if (this.hasVessel)
- {
- this.vesselName = this.part.vessel.vesselName;
- this.vesselType = this.part.vesselType;
- }
- this.initialVesselName = this.part.initialVesselName;
-
- this.hasMultiModeEngine = this.part.HasModule<MultiModeEngine>();
- this.hasModuleEnginesFX = this.part.HasModule<ModuleEnginesFX>();
- this.hasModuleEngines = this.part.HasModule<ModuleEngines>();
-
- this.isEngine = this.hasMultiModeEngine || this.hasModuleEnginesFX || this.hasModuleEngines;
-
- if (SimManager.logOutput)
- {
- MonoBehaviour.print("Created " + this.name + ". Decoupled in stage " + this.decoupledInStage);
+ 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;
+ if (partSim.hasVessel)
+ {
+ partSim.vesselName = partSim.part.vessel.vesselName;
+ partSim.vesselType = partSim.part.vesselType;
+ }
+ partSim.initialVesselName = partSim.part.initialVesselName;
+
+ partSim.hasMultiModeEngine = partSim.part.HasModule<MultiModeEngine>();
+ partSim.hasModuleEnginesFX = partSim.part.HasModule<ModuleEnginesFX>();
+ partSim.hasModuleEngines = partSim.part.HasModule<ModuleEngines>();
+
+ partSim.isEngine = partSim.hasMultiModeEngine || partSim.hasModuleEnginesFX || partSim.hasModuleEngines;
+
+ if (log != null) log.buf.AppendLine("Created " + partSim.name + ". Decoupled in stage " + partSim.decoupledInStage);
+
+ return partSim;
+ }
+
+ public ResourceContainer ResourceDrains
+ {
+ get
+ {
+ return resourceDrains;
}
}
public ResourceContainer Resources
{
- get { return this.resources; }
- }
-
- public ResourceContainer ResourceDrains
- {
- get { return this.resourceDrains; }
- }
-
- public void CreateEngineSims(List<EngineSim> allEngines, double atmosphere, double velocity, bool vectoredThrust, LogMsg log)
- {
- bool correctThrust = SimManager.DoesEngineUseCorrectedThrust(this.part);
+ get
+ {
+ return resources;
+ }
+ }
+
+ public void CreateEngineSims(List<EngineSim> allEngines, double atmosphere, double mach, bool vectoredThrust, bool fullThrust, LogMsg log)
+ {
+ bool correctThrust = SimManager.DoesEngineUseCorrectedThrust(part);
if (log != null)
{
log.buf.AppendLine("CreateEngineSims for " + this.name);
-
- foreach (PartModule partMod in this.part.Modules)
- {
+ for (int i = 0; i < this.part.Modules.Count; i++)
+ {
+ PartModule partMod = this.part.Modules[i];
log.buf.AppendLine("Module: " + partMod.moduleName);
}
log.buf.AppendLine("correctThrust = " + correctThrust);
}
- if (this.hasMultiModeEngine)
+ if (hasMultiModeEngine)
{
// A multi-mode engine has multiple ModuleEnginesFX but only one is active at any point
// The mode of the engine is the engineID of the ModuleEnginesFX that is active
- string mode = this.part.GetModule<MultiModeEngine>().mode;
-
- foreach (ModuleEnginesFX engine in this.part.GetModules<ModuleEnginesFX>())
- {
+ string mode = part.GetModule<MultiModeEngine>().mode;
+
+ List<ModuleEnginesFX> engines = part.GetModules<ModuleEnginesFX>();
+ for (int i = 0; i < engines.Count; ++i)
+ {
+ 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);
- EngineSim engineSim = new EngineSim(this,
- atmosphere,
- velocity,
- engine.maxThrust,
- engine.minThrust,
- engine.thrustPercentage,
- engine.requestedThrust,
- thrustvec,
- engine.realIsp,
- engine.atmosphereCurve,
- engine.useVelocityCurve ? engine.velocityCurve : null,
- engine.throttleLocked,
- engine.propellants,
- engine.isOperational,
- correctThrust);
+ EngineSim engineSim = EngineSim.New(
+ this,
+ atmosphere,
+ (float)mach,
+ engine.maxFuelFlow,
+ engine.minFuelFlow,
+ engine.thrustPercentage,
+ thrustvec,
+ engine.atmosphereCurve,
+ engine.atmChangeFlow,
+ engine.useAtmCurve ? engine.atmCurve : null,
+ engine.useVelCurve ? engine.velCurve : null,
+ engine.currentThrottle,
+ engine.g,
+ engine.throttleLocked || fullThrust,
+ engine.propellants,
+ engine.isOperational,
+ engine.resultingThrust,
+ engine.thrustTransforms,
+ log);
allEngines.Add(engineSim);
}
}
}
else
{
- if (this.hasModuleEnginesFX)
- {
- foreach (ModuleEnginesFX engine in this.part.GetModules<ModuleEnginesFX>())
- {
- if (log != null)
- {
- log.buf.AppendLine("Module: " + engine.moduleName);
- }
+ if (hasModuleEngines)
+ {
+ List<ModuleEngines> engines = part.GetModules<ModuleEngines>();
+ for (int i = 0; i < engines.Count; ++i)
+ {
+ ModuleEngines engine = engines[i];
+ if (log != null) log.buf.AppendLine("Module: " + engine.moduleName);
Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
- EngineSim engineSim = new EngineSim(this,
- atmosphere,
- velocity,
- engine.maxThrust,
- engine.minThrust,
- engine.thrustPercentage,
- engine.requestedThrust,
- thrustvec,
- engine.realIsp,
- engine.atmosphereCurve,
- engine.useVelocityCurve ? engine.velocityCurve : null,
- engine.throttleLocked,
- engine.propellants,
- engine.isOperational,
- correctThrust);
+ EngineSim engineSim = EngineSim.New(
+ this,
+ atmosphere,
+ (float)mach,
+ engine.maxFuelFlow,
+ engine.minFuelFlow,
+ engine.thrustPercentage,
+ thrustvec,
+ engine.atmosphereCurve,
+ engine.atmChangeFlow,
+ engine.useAtmCurve ? engine.atmCurve : null,
+ engine.useVelCurve ? engine.velCurve : null,
+ engine.currentThrottle,
+ engine.g,
+ engine.throttleLocked || fullThrust,
+ engine.propellants,
+ engine.isOperational,
+ engine.resultingThrust,
+ engine.thrustTransforms,
+ log);
allEngines.Add(engineSim);
}
}
-
- if (this.hasModuleEngines)
- {
- foreach (ModuleEngines engine in this.part.GetModules<ModuleEngines>())
- {
- if (log != null)
- {
- log.buf.AppendLine("Module: " + engine.moduleName);
- }
-
- Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
-
- EngineSim engineSim = new EngineSim(this,
- atmosphere,
- velocity,
- engine.maxThrust,
- engine.minThrust,
- engine.thrustPercentage,
- engine.requestedThrust,
- thrustvec,
- engine.realIsp,
- engine.atmosphereCurve,
- engine.useVelocityCurve ? engine.velocityCurve : null,
- engine.throttleLocked,
- engine.propellants,
- engine.isOperational,
- correctThrust);
- allEngines.Add(engineSim);
- }
- }
}
if (log != null)
@@ -280,179 +301,128 @@
}
}
- private Vector3 CalculateThrustVector(List<Transform> thrustTransforms, LogMsg log)
- {
- if (thrustTransforms == null)
- {
- return Vector3.forward;
- }
-
- Vector3 thrustvec = Vector3.zero;
- foreach (Transform trans in thrustTransforms)
- {
- 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);
- }
-
- 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);
- }
-
- return thrustvec;
- }
-
- public void SetupParent(Dictionary<Part, PartSim> partSimLookup, LogMsg log)
- {
- if (this.part.parent != null)
- {
- this.parent = null;
- if (partSimLookup.TryGetValue(this.part.parent, out this.parent))
- {
- if (log != null)
- {
- log.buf.AppendLine("Parent part is " + this.parent.name + ":" + this.parent.partId);
- }
- }
- else
- {
- if (log != null)
- {
- log.buf.AppendLine("No PartSim for parent part (" + this.part.parent.partInfo.name + ")");
- }
- }
- }
- }
-
- public void SetupAttachNodes(Dictionary<Part, PartSim> partSimLookup, LogMsg log)
- {
- if (log != null)
- {
- log.buf.AppendLine("SetupAttachNodes for " + this.name + ":" + this.partId + "");
- }
-
- this.attachNodes.Clear();
- foreach (AttachNode attachNode in this.part.attachNodes)
- {
- 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 + "");
- }
-
- this.attachNodes.Add(new AttachNodeSim(attachedSim, attachNode.id, attachNode.nodeType));
- }
- else
- {
- if (log != null)
- {
- log.buf.AppendLine("No PartSim for attached part (" + attachNode.attachedPart.partInfo.name + ")");
- }
- }
- }
- }
-
- foreach (Part p in this.part.fuelLookupTargets)
- {
- if (p != null)
- {
- PartSim targetSim;
- if (partSimLookup.TryGetValue(p, out targetSim))
- {
- if (log != null)
- {
- log.buf.AppendLine("Fuel target: " + targetSim.name + ":" + targetSim.partId);
- }
-
- this.fuelTargets.Add(targetSim);
- }
- else
- {
- if (log != null)
- {
- log.buf.AppendLine("No PartSim for fuel target (" + p.name + ")");
- }
- }
- }
- }
- }
-
- private int DecoupledInStage(Part thePart, int stage = -1)
- {
- if (this.IsDecoupler(thePart))
- {
- if (thePart.inverseStage > stage)
- {
- stage = thePart.inverseStage;
- }
- }
-
- if (thePart.parent != null)
- {
- stage = this.DecoupledInStage(thePart.parent, stage);
- }
-
- return stage;
- }
-
- private bool IsDecoupler(Part thePart)
- {
- return thePart.HasModule<ModuleDecouple>() ||
- thePart.HasModule<ModuleAnchoredDecoupler>();
- }
-
- private bool IsActiveDecoupler(Part thePart)
- {
- return thePart.FindModulesImplementing<ModuleDecouple>().Any(mod => !mod.isDecoupled) ||
- thePart.FindModulesImplementing<ModuleAnchoredDecoupler>().Any(mod => !mod.isDecoupled);
- }
-
- private bool IsSepratron()
- {
- if (!this.part.ActivatesEvenIfDisconnected)
- {
- return false;
- }
-
- if (this.part is SolidRocket)
- {
- return true;
- }
-
- var modList = this.part.Modules.OfType<ModuleEngines>();
- if (modList.Count() == 0)
- {
- return false;
- }
-
- if (modList.First().throttleLocked)
- {
- return true;
- }
-
- return false;
- }
-
+ public int DecouplerCount()
+ {
+ int count = 0;
+ PartSim partSim = this;
+ while (partSim != null)
+ {
+ if (partSim.isDecoupler)
+ {
+ count++;
+ }
+
+ partSim = partSim.parent;
+ }
+ return count;
+ }
+
+ public void DrainResources(double time)
+ {
+ //MonoBehaviour.print("DrainResources(" + name + ":" + partId + ", " + time + ")");
+ for (int i = 0; i < resourceDrains.Types.Count; ++i)
+ {
+ int type = resourceDrains.Types[i];
+
+ //MonoBehaviour.print("draining " + (time * resourceDrains[type]) + " " + ResourceContainer.GetResourceName(type));
+ resources.Add(type, -time * resourceDrains[type]);
+ //MonoBehaviour.print(ResourceContainer.GetResourceName(type) + " left = " + resources[type]);
+ }
+ }
+
+ public String DumpPartAndParentsToBuffer(StringBuilder buffer, String prefix)
+ {
+ if (parent != null)
+ {
+ prefix = parent.DumpPartAndParentsToBuffer(buffer, prefix) + " ";
+ }
+
+ DumpPartToBuffer(buffer, prefix);
+
+ return prefix;
+ }
+
+ public void DumpPartToBuffer(StringBuilder buffer, String prefix, List<PartSim> allParts = null)
+ {
+ buffer.Append(prefix);
+ 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(", isNoPhys = {0}", isNoPhysics);
+ buffer.AppendFormat(", baseMass = {0}", baseMass);
+ buffer.AppendFormat(", baseMassForCoM = {0}", baseMassForCoM);
+
+ buffer.AppendFormat(", fuelCF = {0}", fuelCrossFeed);
+ buffer.AppendFormat(", noCFNKey = '{0}'", noCrossFeedNodeKey);
+
+ buffer.AppendFormat(", isSep = {0}", isSepratron);
+
+ for (int i = 0; i < resources.Types.Count; i++)
+ {
+ int type = resources.Types[i];
+ buffer.AppendFormat(", {0} = {1:g6}", ResourceContainer.GetResourceName(type), resources[type]);
+ }
+
+ if (attachNodes.Count > 0)
+ {
+ buffer.Append(", attached = <");
+ attachNodes[0].DumpToBuffer(buffer);
+ for (int i = 1; i < attachNodes.Count; i++)
+ {
+ buffer.Append(", ");
+ attachNodes[i].DumpToBuffer(buffer);
+ }
+ buffer.Append(">");
+ }
+
+ // Add more info here
+
+ buffer.Append("]\n");
+
+ if (allParts != null)
+ {
+ String newPrefix = prefix + " ";
+ for (int i = 0; i < allParts.Count; i++)
+ {
+ PartSim partSim = allParts[i];
+ if (partSim.parent == this)
+ partSim.DumpPartToBuffer(buffer, newPrefix, allParts);
+ }
+ }
+ }
+
+ public bool EmptyOf(HashSet<int> types)
+ {
+ 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, bool forCoM = false)
+ {
+ double mass = forCoM ? baseMassForCoM : baseMass;
+
+ for (int i = 0; i < resources.Types.Count; ++i)
+ {
+ mass += resources.GetResourceMass(resources.Types[i]);
+ }
+
+ if (hasVessel == false && isFairing && inverseStage < currentStage)
+ {
+ mass = mass + moduleMass;
+ }
+
+ return mass;
+ }
+
public void ReleasePart()
{
this.part = null;
@@ -461,67 +431,55 @@
// All functions below this point must not rely on the part member (it may be null)
//
- public HashSet<PartSim> GetSourceSet(int type, List<PartSim> allParts, HashSet<PartSim> visited, LogMsg log, String indent)
+ public void GetSourceSet(int type, List<PartSim> allParts, HashSet<PartSim> visited, HashSet<PartSim> allSources, LogMsg log, String indent)
{
if (log != null)
{
- log.buf.AppendLine(indent + "GetSourceSet(" + ResourceContainer.GetResourceName(type) + ") for " + this.name + ":" + this.partId);
+ log.buf.AppendLine(indent + "GetSourceSet(" + ResourceContainer.GetResourceName(type) + ") for " + name + ":" + partId);
indent += " ";
}
- HashSet<PartSim> allSources = new HashSet<PartSim>();
- HashSet<PartSim> partSources = null;
-
- // Rule 1: Each part can be only visited once, If it is visited for second time in particular search it returns empty list.
+ // 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 (" + this.name + ":" + this.partId + ")");
- }
-
- return allSources;
- }
-
- //if (log != null)
- // log.buf.AppendLine(indent + "Adding this to visited");
+ 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");
visited.Add(this);
// Rule 2: Part performs scan on start of every fuel pipe ending in it. This scan is done in order in which pipes were installed.
// Then it makes an union of fuel tank sets each pipe scan returned. If the resulting list is not empty, it is returned as result.
- //MonoBehaviour.print("foreach fuel line");
-
- foreach (PartSim partSim in this.fuelTargets)
- {
- if (visited.Contains(partSim))
- {
- //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 + ")");
-
- partSources = partSim.GetSourceSet(type, allParts, visited, log, indent);
- if (partSources.Count > 0)
- {
- allSources.UnionWith(partSources);
- partSources.Clear();
- }
- }
- }
-
- if (allSources.Count > 0)
- {
- if (log != null)
- {
- log.buf.AppendLine(indent + "Returning " + allSources.Count + " fuel target sources (" + this.name + ":" + this.partId + ")");
- }
-
- return allSources;
- }
+ //MonoBehaviour.print("for each fuel line");
+
+ int lastCount = allSources.Count;
+
+ for (int i = 0; i < this.fuelTargets.Count; i++)
+ {
+ PartSim partSim = this.fuelTargets[i];
+ if (partSim != null)
+ {
+ if (visited.Contains(partSim))
+ {
+ 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 + ")");
+
+ partSim.GetSourceSet(type, allParts, visited, allSources, log, indent);
+ }
+ }
+ }
+
+ if (allSources.Count > lastCount)
+ {
+ if (log != null) log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " fuel target sources (" + this.name + ":" + this.partId + ")");
+ return;
+ }
+
// Rule 3: This rule has been removed and merged with rules 4 and 7 to fix issue with fuel tanks with disabled crossfeed
@@ -530,47 +488,40 @@
// skip the points on the side where multiple points are. [Experiment]
// Again, the part creates union of scan lists from each of its neighbor and if it is not empty, returns this list.
// The order in which mount points of a part are scanned appears to be fixed and defined by the part specification file. [Experiment]
- if (this.fuelCrossFeed)
- {
- //MonoBehaviour.print("foreach attach node");
- foreach (AttachNodeSim attachSim in this.attachNodes)
- {
+ if (fuelCrossFeed)
+ {
+ lastCount = allSources.Count;
+ //MonoBehaviour.print("for each attach node");
+ for (int i = 0; i < this.attachNodes.Count; i++)
+ {
+ AttachNodeSim attachSim = this.attachNodes[i];
if (attachSim.attachedPartSim != null)
{
if (attachSim.nodeType == AttachNode.NodeType.Stack)
{
- if (!(this.noCrossFeedNodeKey != null && this.noCrossFeedNodeKey.Length > 0 && attachSim.id.Contains(this.noCrossFeedNodeKey)))
+ if (
+ !(this.noCrossFeedNodeKey != null && this.noCrossFeedNodeKey.Length > 0 &&
+ attachSim.id.Contains(this.noCrossFeedNodeKey)))
{
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 + ")");
-
- partSources = attachSim.attachedPartSim.GetSourceSet(type, allParts, visited, log, indent);
- if (partSources.Count > 0)
- {
- allSources.UnionWith(partSources);
- partSources.Clear();
- }
+ 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);
}
}
}
}
}
- if (allSources.Count > 0)
- {
- if (log != null)
- {
- log.buf.AppendLine(indent + "Returning " + allSources.Count + " attached sources (" + this.name + ":" + this.partId + ")");
- }
-
- return allSources;
+ if (allSources.Count > lastCount)
+ {
+ if (log != null) log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " attached sources (" + this.name + ":" + this.partId + ")");
+ return;
}
}
@@ -578,76 +529,143 @@
// type was not disabled [Experiment]) and it contains fuel, it returns itself.
// Rule 6: If the part is fuel container for searched type of fuel (i.e. it has capability to contain that type of fuel and the fuel
// type was not disabled) but it does not contain the requested fuel, it returns empty list. [Experiment]
- if (this.resources.HasType(type) && this.resourceFlowStates[type] != 0)
- {
- if (this.resources[type] > SimManager.RESOURCE_MIN)
+ if (resources.HasType(type) && resourceFlowStates[type] != 0)
+ {
+ if (resources[type] > SimManager.RESOURCE_MIN)
{
allSources.Add(this);
- if (log != null)
- {
- log.buf.AppendLine(indent + "Returning enabled tank as only source (" + this.name + ":" + this.partId + ")");
- }
- }
-
- return allSources;
+ 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]);
}
// 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
// parent and returns whatever the parent scan returned. [Experiment] [Experiment]
- if (this.parent != null && this.parentAttach == AttachModes.SRF_ATTACH)
- {
- if (this.fuelCrossFeed)
- {
- if (visited.Contains(this.parent))
- {
- //if (log != null)
- // log.buf.AppendLine(indent + "Parent part already visited, skipping (" + parent.name + ":" + parent.partId + ")");
+ if (parent != null && parentAttach == AttachModes.SRF_ATTACH)
+ {
+ if (fuelCrossFeed)
+ {
+ if (visited.Contains(parent))
+ {
+ if (log != null) log.buf.AppendLine(indent + "Parent part already visited, skipping (" + parent.name + ":" + parent.partId + ")");
}
else
{
- allSources = this.parent.GetSourceSet(type, allParts, visited, log, indent);
- if (allSources.Count > 0)
+ lastCount = allSources.Count;
+ this.parent.GetSourceSet(type, allParts, visited, allSources, log, indent);
+ if (allSources.Count > lastCount)
{
- if (log != null)
- {
- log.buf.AppendLine(indent + "Returning " + allSources.Count + " parent sources (" + this.name + ":" + this.partId + ")");
- }
-
- return allSources;
+ if (log != null) log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " parent sources (" + this.name + ":" + this.partId + ")");
+ return;
}
}
}
}
// 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 + ")");
-
- return allSources;
+ if (log != null) log.buf.AppendLine(indent + "Returning empty set, no sources found (" + name + ":" + partId + ")");
+
+ return;
+ }
+
+ public double GetStartMass()
+ {
+ return startMass;
}
public void RemoveAttachedParts(HashSet<PartSim> partSims)
{
// Loop through the attached parts
- foreach (AttachNodeSim attachSim in this.attachNodes)
- {
+ for (int i = 0; i < this.attachNodes.Count; i++)
+ {
+ AttachNodeSim attachSim = this.attachNodes[i];
// If the part is in the set then "remove" it by clearing the PartSim reference
if (partSims.Contains(attachSim.attachedPartSim))
{
attachSim.attachedPartSim = null;
}
}
- }
-
- public void DrainResources(double time)
- {
- //MonoBehaviour.print("DrainResources(" + name + ":" + partId + ", " + time + ")");
- foreach (int type in this.resourceDrains.Types)
- {
- //MonoBehaviour.print("draining " + (time * resourceDrains[type]) + " " + ResourceContainer.GetResourceName(type));
- this.resources.Add(type, -time * this.resourceDrains[type]);
- //MonoBehaviour.print(ResourceContainer.GetResourceName(type) + " left = " + resources[type]);
+
+ // Loop through the fuel targets (fuel line sources)
+ for (int i = 0; i < this.fuelTargets.Count; i++)
+ {
+ PartSim fuelTargetSim = this.fuelTargets[i];
+ // If the part is in the set then "remove" it by clearing the PartSim reference
+ if (fuelTargetSim != null && partSims.Contains(fuelTargetSim))
+ {
+ this.fuelTargets[i] = null;
+ }
+ }
+ }
+
+ public void SetupAttachNodes(Dictionary<Part, PartSim> partSimLookup, LogMsg log)
+ {
+ if (log != null) log.buf.AppendLine("SetupAttachNodes for " + name + ":" + partId + "");
+
+ attachNodes.Clear();
+
+ for (int i = 0; i < part.attachNodes.Count; ++i)
+ {
+ AttachNode attachNode = part.attachNodes[i];
+
+ 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 + "");
+
+ 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 + ")");
+ }
+ }
+ }
+
+ for (int i = 0; i < part.fuelLookupTargets.Count; ++i)
+ {
+ Part p = part.fuelLookupTargets[i];
+
+ if (p != null)
+ {
+ PartSim targetSim;
+ if (partSimLookup.TryGetValue(p, out targetSim))
+ {
+ 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 + ")");
+ }
+ }
+ }
+ }
+
+ public void SetupParent(Dictionary<Part, PartSim> partSimLookup, LogMsg log)
+ {
+ if (part.parent != null)
+ {
+ parent = null;
+ if (partSimLookup.TryGetValue(part.parent, out parent))
+ {
+ 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 + ")");
+ }
}
}
@@ -656,11 +674,13 @@
//MonoBehaviour.print("TimeToDrainResource(" + name + ":" + partId + ")");
double time = double.MaxValue;
- foreach (int type in this.resourceDrains.Types)
- {
- if (this.resourceDrains[type] > 0)
- {
- time = Math.Min(time, this.resources[type] / this.resourceDrains[type]);
+ for (int i = 0; i < resourceDrains.Types.Count; ++i)
+ {
+ int type = resourceDrains.Types[i];
+
+ if (resourceDrains[type] > 0)
+ {
+ time = Math.Min(time, resources[type] / resourceDrains[type]);
//MonoBehaviour.print("type = " + ResourceContainer.GetResourceName(type) + " amount = " + resources[type] + " rate = " + resourceDrains[type] + " time = " + time);
}
}
@@ -670,98 +690,84 @@
return time;
}
- public int DecouplerCount()
- {
- int count = 0;
- PartSim partSim = this;
- while (partSim != null)
- {
- if (partSim.isDecoupler)
- {
- count++;
- }
-
- partSim = partSim.parent;
- }
- return count;
- }
-
- public double GetStartMass()
- {
- return this.startMass;
- }
-
- public double GetMass()
- {
- double mass = this.baseMass;
-
- foreach (int type in this.resources.Types)
- {
- mass += this.resources.GetResourceMass(type);
- }
-
- return mass;
- }
-
- public String DumpPartAndParentsToBuffer(StringBuilder buffer, String prefix)
- {
- if (this.parent != null)
- {
- prefix = this.parent.DumpPartAndParentsToBuffer(buffer, prefix) + " ";
- }
-
- this.DumpPartToBuffer(buffer, prefix);
-
- return prefix;
- }
-
- public void DumpPartToBuffer(StringBuilder buffer, String prefix, List<PartSim> allParts = null)
- {
- buffer.Append(prefix);
- buffer.Append(this.name);
- buffer.AppendFormat(":[id = {0:d}, decouple = {1:d}, invstage = {2:d}", this.partId, this.decoupledInStage, this.inverseStage);
-
- buffer.AppendFormat(", vesselName = '{0}'", this.vesselName);
- buffer.AppendFormat(", vesselType = {0}", SimManager.GetVesselTypeString(this.vesselType));
- buffer.AppendFormat(", initialVesselName = '{0}'", this.initialVesselName);
-
- buffer.AppendFormat(", fuelCF = {0}", this.fuelCrossFeed);
- buffer.AppendFormat(", noCFNKey = '{0}'", this.noCrossFeedNodeKey);
-
- buffer.AppendFormat(", isSep = {0}", this.isSepratron);
-
- foreach (int type in this.resources.Types)
- {
- buffer.AppendFormat(", {0} = {1:g6}", ResourceContainer.GetResourceName(type), this.resources[type]);
- }
-
- if (this.attachNodes.Count > 0)
- {
- buffer.Append(", attached = <");
- this.attachNodes[0].DumpToBuffer(buffer);
- for (int i = 1; i < this.attachNodes.Count; i++)
- {
- buffer.Append(", ");
- this.attachNodes[i].DumpToBuffer(buffer);
- }
- buffer.Append(">");
- }
-
- // Add more info here
-
- buffer.Append("]\n");
-
- if (allParts != null)
- {
- String newPrefix = prefix + " ";
- foreach (PartSim partSim in allParts)
- {
- if (partSim.parent == this)
- {
- partSim.DumpPartToBuffer(buffer, newPrefix, allParts);
- }
- }
- }
+ private Vector3 CalculateThrustVector(List<Transform> thrustTransforms, LogMsg log)
+ {
+ if (thrustTransforms == null)
+ {
+ return Vector3.forward;
+ }
+
+ Vector3 thrustvec = Vector3.zero;
+ for (int i = 0; i < thrustTransforms.Count; ++i)
+ {
+ 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);
+
+ 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);
+
+ 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);
+
+ return thrustvec;
+ }
+
+ private int DecoupledInStage(Part thePart, int stage = -1)
+ {
+ if (IsDecoupler(thePart) && thePart.inverseStage > stage)
+ stage = thePart.inverseStage;
+
+ if (thePart.parent != null)
+ stage = DecoupledInStage(thePart.parent, stage);
+
+ return stage;
+ }
+
+ private bool IsActiveDecoupler(Part thePart)
+ {
+ return thePart.FindModulesImplementing<ModuleDecouple>().Any(mod => !mod.isDecoupled) ||
+ thePart.FindModulesImplementing<ModuleAnchoredDecoupler>().Any(mod => !mod.isDecoupled);
+ }
+
+ private bool IsDecoupler(Part thePart)
+ {
+ return thePart.HasModule<ModuleDecouple>() ||
+ thePart.HasModule<ModuleAnchoredDecoupler>();
+ }
+
+ private bool IsFairing(Part thePart)
+ {
+ return thePart.HasModule<ModuleProceduralFairing>();
+ }
+
+ private bool IsSepratron()
+ {
+ if (!part.ActivatesEvenIfDisconnected)
+ {
+ return false;
+ }
+
+ if (part is SolidRocket)
+ {
+ return true;
+ }
+
+ IEnumerable<ModuleEngines> modList = part.Modules.OfType<ModuleEngines>();
+ if (modList.Count() == 0)
+ {
+ return false;
+ }
+
+ if (modList.First().throttleLocked)
+ {
+ return true;
+ }
+
+ return false;
}
}
}
--- a/KerbalEngineer/VesselSimulator/ResourceContainer.cs
+++ b/KerbalEngineer/VesselSimulator/ResourceContainer.cs
@@ -19,6 +19,7 @@
#region Using Directives
+using System;
using System.Collections;
using System.Collections.Generic;
@@ -30,15 +31,17 @@
{
public class ResourceContainer
{
- private Hashtable resources = new Hashtable();
+ private Dictionary<int, double> resources = new Dictionary<int, double>();
+ private List<int> types = new List<int>();
public double this[int type]
{
get
{
- if (this.resources.ContainsKey(type))
+ double value;
+ if (this.resources.TryGetValue(type, out value))
{
- return (double)this.resources[type];
+ return value;
}
return 0d;
@@ -52,6 +55,7 @@
else
{
this.resources.Add(type, value);
+ this.types.Add(type);
}
}
}
@@ -60,13 +64,6 @@
{
get
{
- List<int> types = new List<int>();
-
- foreach (int key in this.resources.Keys)
- {
- types.Add(key);
- }
-
return types;
}
}
@@ -92,7 +89,7 @@
{
foreach (int type in this.resources.Keys)
{
- if ((double)this.resources[type] > SimManager.RESOURCE_MIN)
+ if (this.resources[type] > SimManager.RESOURCE_MIN)
{
return false;
}
@@ -111,7 +108,7 @@
{
foreach (int type in types)
{
- if (this.HasType(type) && (double)this.resources[type] > SimManager.RESOURCE_MIN)
+ if (this.HasType(type) && this.resources[type] > SimManager.RESOURCE_MIN)
{
return false;
}
@@ -124,17 +121,19 @@
{
if (this.resources.ContainsKey(type))
{
- this.resources[type] = (double)this.resources[type] + amount;
+ this.resources[type] = this.resources[type] + amount;
}
else
{
this.resources.Add(type, amount);
+ this.types.Add(type);
}
}
public void Reset()
{
- this.resources = new Hashtable();
+ this.resources.Clear();
+ this.types.Clear();
}
public void Debug()
@@ -148,7 +147,7 @@
public double GetResourceMass(int type)
{
double density = GetResourceDensity(type);
- return density == 0d ? 0d : (double)this.resources[type] * density;
+ return density == 0d ? 0d : this.resources[type] * density;
}
public static ResourceFlowMode GetResourceFlowMode(int type)
@@ -158,7 +157,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)
--- a/KerbalEngineer/VesselSimulator/SimManager.cs
+++ b/KerbalEngineer/VesselSimulator/SimManager.cs
@@ -17,251 +17,192 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Reflection;
-using System.Threading;
-
-using UnityEngine;
-
-#endregion
-
namespace KerbalEngineer.VesselSimulator
{
+ #region Using Directives
+
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Reflection;
+ using System.Threading;
+ using UnityEngine;
+
+ #endregion
+
public class SimManager
{
+ #region Constants
+
public const double RESOURCE_MIN = 0.0001;
+ public const double RESOURCE_PART_EMPTY_THRESH = 0.01;
+
+ #endregion
+
+ #region Fields
+
+ public static bool dumpTree = false;
+ public static bool logOutput = false;
+ public static TimeSpan minSimTime = new TimeSpan(0, 0, 0, 0, 150);
+ public static bool vectoredThrust = false;
+ private static readonly object locker = new object();
+ private static readonly Stopwatch timer = new Stopwatch();
private static bool bRequested;
private static bool bRunning;
- private static readonly Stopwatch timer = new Stopwatch();
- private static long delayBetweenSims;
-
- public static bool dumpTree = false;
- public static bool logOutput = false;
- public static bool vectoredThrust = false;
- public static long minSimTime = 150;
+ private static TimeSpan delayBetweenSims;
// Support for RealFuels using reflection to check localCorrectThrust without dependency
- private static bool hasCheckedForRealFuels;
+
+ private static bool hasCheckedForMods;
private static bool hasInstalledRealFuels;
-
- private static FieldInfo RF_ModuleEngineConfigs_locaCorrectThrust;
- private static FieldInfo RF_ModuleHybridEngine_locaCorrectThrust;
- private static FieldInfo RF_ModuleHybridEngines_locaCorrectThrust;
+ private static FieldInfo RF_ModuleEngineConfigs_localCorrectThrust;
+ private static FieldInfo RF_ModuleHybridEngine_localCorrectThrust;
+ private static FieldInfo RF_ModuleHybridEngines_localCorrectThrust;
+ private static bool hasInstalledKIDS;
+ private static MethodInfo KIDS_Utils_GetIspMultiplier;
+ private static bool bKIDSThrustISP = false;
+ private static List<Part> parts = new List<Part>();
+
+ private static Simulation simulation = new Simulation();
+ #endregion
+
+ #region Delegates
+
+ public delegate void ReadyEvent();
+
+ #endregion
+
+ #region Events
+
+ public static event ReadyEvent OnReady;
+
+ #endregion
+
+ #region Properties
+
+ public static double Atmosphere { get; set; }
+
+ public static double Gravity { get; set; }
+
+ public static Stage LastStage { get; private set; }
+
public static Stage[] Stages { get; private set; }
- public static Stage LastStage { get; private set; }
+
+ public static double Mach { get; set; }
+
public static String failMessage { get; private set; }
- public static double Gravity { get; set; }
- public static double Atmosphere { get; set; }
- public static double Velocity { get; set; }
-
- private static void GetRealFuelsTypes()
- {
- hasCheckedForRealFuels = true;
-
- foreach (AssemblyLoader.LoadedAssembly assembly in AssemblyLoader.loadedAssemblies)
+
+ #endregion
+
+ #region Methods
+
+ private static void CheckForMods()
+ {
+ hasCheckedForMods = true;
+
+ foreach (var assembly in AssemblyLoader.loadedAssemblies)
{
MonoBehaviour.print("Assembly:" + assembly.assembly);
- if (assembly.assembly.ToString().Split(',')[0] == "RealFuels")
+ var name = assembly.assembly.ToString().Split(',')[0];
+
+ if (name == "RealFuels")
{
MonoBehaviour.print("Found RealFuels mod");
- Type RF_ModuleEngineConfigs_Type = assembly.assembly.GetType("RealFuels.ModuleEngineConfigs");
+ var RF_ModuleEngineConfigs_Type = assembly.assembly.GetType("RealFuels.ModuleEngineConfigs");
if (RF_ModuleEngineConfigs_Type != null)
{
- RF_ModuleEngineConfigs_locaCorrectThrust = RF_ModuleEngineConfigs_Type.GetField("localCorrectThrust");
- }
-
- Type RF_ModuleHybridEngine_Type = assembly.assembly.GetType("RealFuels.ModuleHybridEngine");
+ RF_ModuleEngineConfigs_localCorrectThrust = RF_ModuleEngineConfigs_Type.GetField("localCorrectThrust");
+ }
+
+ var RF_ModuleHybridEngine_Type = assembly.assembly.GetType("RealFuels.ModuleHybridEngine");
if (RF_ModuleHybridEngine_Type != null)
{
- RF_ModuleHybridEngine_locaCorrectThrust = RF_ModuleHybridEngine_Type.GetField("localCorrectThrust");
- }
-
- Type RF_ModuleHybridEngines_Type = assembly.assembly.GetType("RealFuels.ModuleHybridEngines");
+ RF_ModuleHybridEngine_localCorrectThrust = RF_ModuleHybridEngine_Type.GetField("localCorrectThrust");
+ }
+
+ var RF_ModuleHybridEngines_Type = assembly.assembly.GetType("RealFuels.ModuleHybridEngines");
if (RF_ModuleHybridEngines_Type != null)
{
- RF_ModuleHybridEngines_locaCorrectThrust = RF_ModuleHybridEngines_Type.GetField("localCorrectThrust");
+ RF_ModuleHybridEngines_localCorrectThrust = RF_ModuleHybridEngines_Type.GetField("localCorrectThrust");
}
hasInstalledRealFuels = true;
break;
}
+ else if (name == "KerbalIspDifficultyScaler")
+ {
+ var KIDS_Utils_Type = assembly.assembly.GetType("KerbalIspDifficultyScaler.KerbalIspDifficultyScalerUtils");
+ if (KIDS_Utils_Type != null)
+ {
+ KIDS_Utils_GetIspMultiplier = KIDS_Utils_Type.GetMethod("GetIspMultiplier");
+ }
+
+ hasInstalledKIDS = true;
+ }
}
}
public static bool DoesEngineUseCorrectedThrust(Part theEngine)
{
- if (!hasInstalledRealFuels /*|| HighLogic.LoadedSceneIsFlight*/)
- {
- return false;
- }
-
- // Look for any of the Real Fuels engine modules and call the relevant method to find out
- if (RF_ModuleEngineConfigs_locaCorrectThrust != null && theEngine.Modules.Contains("ModuleEngineConfigs"))
- {
- PartModule modEngineConfigs = theEngine.Modules["ModuleEngineConfigs"];
- if (modEngineConfigs != null)
- {
- // Check the localCorrectThrust
- if ((bool)RF_ModuleEngineConfigs_locaCorrectThrust.GetValue(modEngineConfigs))
- {
- return true;
- }
- }
- }
-
- if (RF_ModuleHybridEngine_locaCorrectThrust != null && theEngine.Modules.Contains("ModuleHybridEngine"))
- {
- PartModule modHybridEngine = theEngine.Modules["ModuleHybridEngine"];
- if (modHybridEngine != null)
- {
- // Check the localCorrectThrust
- if ((bool)RF_ModuleHybridEngine_locaCorrectThrust.GetValue(modHybridEngine))
- {
- return true;
- }
- }
- }
-
- if (RF_ModuleHybridEngines_locaCorrectThrust != null && theEngine.Modules.Contains("ModuleHybridEngines"))
- {
- PartModule modHybridEngines = theEngine.Modules["ModuleHybridEngines"];
- if (modHybridEngines != null)
- {
- // Check the localCorrectThrust
- if ((bool)RF_ModuleHybridEngines_locaCorrectThrust.GetValue(modHybridEngines))
- {
- return true;
- }
- }
+ if (hasInstalledRealFuels)
+ {
+ // Look for any of the Real Fuels engine modules and call the relevant method to find out
+ if (RF_ModuleEngineConfigs_localCorrectThrust != null && theEngine.Modules.Contains("ModuleEngineConfigs"))
+ {
+ var modEngineConfigs = theEngine.Modules["ModuleEngineConfigs"];
+ if (modEngineConfigs != null)
+ {
+ // Return the localCorrectThrust
+ return (bool)RF_ModuleEngineConfigs_localCorrectThrust.GetValue(modEngineConfigs);
+ }
+ }
+
+ if (RF_ModuleHybridEngine_localCorrectThrust != null && theEngine.Modules.Contains("ModuleHybridEngine"))
+ {
+ var modHybridEngine = theEngine.Modules["ModuleHybridEngine"];
+ if (modHybridEngine != null)
+ {
+ // Return the localCorrectThrust
+ return (bool)RF_ModuleHybridEngine_localCorrectThrust.GetValue(modHybridEngine);
+ }
+ }
+
+ if (RF_ModuleHybridEngines_localCorrectThrust != null && theEngine.Modules.Contains("ModuleHybridEngines"))
+ {
+ var modHybridEngines = theEngine.Modules["ModuleHybridEngines"];
+ if (modHybridEngines != null)
+ {
+ // Return the localCorrectThrust
+ return (bool)RF_ModuleHybridEngines_localCorrectThrust.GetValue(modHybridEngines);
+ }
+ }
+ }
+
+ if (hasInstalledKIDS && HighLogic.LoadedSceneIsEditor)
+ {
+ return bKIDSThrustISP;
}
return false;
}
- public static void RequestSimulation()
- {
- if (!hasCheckedForRealFuels)
- {
- GetRealFuelsTypes();
- }
-
- bRequested = true;
- if (!timer.IsRunning)
- {
- timer.Start();
- }
- }
-
- public static void TryStartSimulation()
- {
- if (bRequested && !bRunning && (HighLogic.LoadedSceneIsEditor || FlightGlobals.ActiveVessel != null) && timer.ElapsedMilliseconds > delayBetweenSims)
- {
- bRequested = false;
- timer.Reset();
- StartSimulation();
- }
- }
-
- public static bool ResultsReady()
- {
- return !bRunning;
- }
-
- private static void ClearResults()
- {
- failMessage = "";
- Stages = null;
- LastStage = null;
- }
-
- private static void StartSimulation()
- {
- try
- {
- bRunning = true;
- ClearResults();
- timer.Start();
-
- List<Part> parts = HighLogic.LoadedSceneIsEditor ? EditorLogic.SortedShipList : FlightGlobals.ActiveVessel.Parts;
-
- // Create the Simulation object in this thread
- Simulation sim = new Simulation();
-
- // This call doesn't ever fail at the moment but we'll check and return a sensible error for display
- if (sim.PrepareSimulation(parts, Gravity, Atmosphere, Velocity, dumpTree, vectoredThrust))
- {
- ThreadPool.QueueUserWorkItem(RunSimulation, sim);
- }
- else
- {
- failMessage = "PrepareSimulation failed";
- bRunning = false;
- logOutput = false;
- }
- }
- catch (Exception e)
- {
- MonoBehaviour.print("Exception in StartSimulation: " + e);
- failMessage = e.ToString();
- bRunning = false;
- logOutput = false;
- }
- dumpTree = false;
- }
-
- private static void RunSimulation(object simObject)
- {
- try
- {
- Stages = (simObject as Simulation).RunSimulation();
- if (Stages != null)
- {
- if (logOutput)
- {
- foreach (Stage stage in Stages)
- {
- stage.Dump();
- }
- }
- LastStage = Stages.Last();
- }
- }
- catch (Exception e)
- {
- MonoBehaviour.print("Exception in RunSimulation: " + e);
- Stages = null;
- LastStage = null;
- failMessage = e.ToString();
- }
-
- timer.Stop();
-#if TIMERS
- MonoBehaviour.print("Total simulation time: " + timer.ElapsedMilliseconds + "ms");
-#else
- if (logOutput)
- {
- MonoBehaviour.print("Total simulation time: " + timer.ElapsedMilliseconds + "ms");
- }
-#endif
- delayBetweenSims = minSimTime - timer.ElapsedMilliseconds;
- if (delayBetweenSims < 0)
- {
- delayBetweenSims = 0;
- }
-
- timer.Reset();
- timer.Start();
-
- bRunning = false;
- logOutput = false;
+ public static void UpdateModSettings()
+ {
+ if (!hasCheckedForMods)
+ {
+ CheckForMods();
+ }
+
+ if (hasInstalledKIDS)
+ {
+ // (out ispMultiplierVac, out ispMultiplierAtm, out extendToZeroIsp, out thrustCorrection, out ispCutoff, out thrustCutoff);
+ object[] parameters = new object[6];
+ KIDS_Utils_GetIspMultiplier.Invoke(null, parameters);
+ bKIDSThrustISP = (bool)parameters[3];
+ }
}
public static String GetVesselTypeString(VesselType vesselType)
@@ -293,5 +234,166 @@
}
return "Undefined";
}
+
+ public static void RequestSimulation()
+ {
+ if (!hasCheckedForMods)
+ {
+ CheckForMods();
+ }
+
+ lock (locker)
+ {
+ bRequested = true;
+ if (!timer.IsRunning)
+ {
+ timer.Start();
+ }
+ }
+ }
+
+ public static bool ResultsReady()
+ {
+ lock (locker)
+ {
+ return !bRunning;
+ }
+ }
+
+ public static void TryStartSimulation()
+ {
+ lock (locker)
+ {
+ if (!bRequested || bRunning || (timer.Elapsed < delayBetweenSims && timer.Elapsed >= TimeSpan.Zero) || (!HighLogic.LoadedSceneIsEditor && FlightGlobals.ActiveVessel == null))
+ {
+ return;
+ }
+
+ bRequested = false;
+ timer.Reset();
+ }
+
+ StartSimulation();
+ }
+
+ private static void ClearResults()
+ {
+ failMessage = "";
+ Stages = null;
+ LastStage = null;
+ }
+
+ private static void RunSimulation(object simObject)
+ {
+ try
+ {
+ Stages = (simObject as Simulation).RunSimulation();
+
+ if (Stages != null && Stages.Length > 0)
+ {
+ if (logOutput)
+ {
+ foreach (var stage in Stages)
+ {
+ stage.Dump();
+ }
+ }
+ LastStage = Stages[Stages.Length - 1];
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Exception(e, "SimManager.RunSimulation()");
+ Stages = null;
+ LastStage = null;
+ failMessage = e.ToString();
+ }
+ lock (locker)
+ {
+ timer.Stop();
+#if TIMERS
+ MonoBehaviour.print("Total simulation time: " + timer.ElapsedMilliseconds + "ms");
+#else
+ if (logOutput)
+ {
+ MonoBehaviour.print("Total simulation time: " + timer.ElapsedMilliseconds + "ms");
+ }
+#endif
+
+ delayBetweenSims = minSimTime - timer.Elapsed;
+ if (delayBetweenSims < TimeSpan.Zero)
+ {
+ delayBetweenSims = TimeSpan.Zero;
+ }
+
+ timer.Reset();
+ timer.Start();
+
+ bRunning = false;
+ if (OnReady != null)
+ {
+ OnReady();
+ }
+ }
+
+ logOutput = false;
+ }
+
+ private static void StartSimulation()
+ {
+ try
+ {
+ lock (locker)
+ {
+ bRunning = true;
+ }
+
+ ClearResults();
+
+ lock (locker)
+ {
+ timer.Start();
+ }
+
+ if (HighLogic.LoadedSceneIsEditor)
+ {
+ parts = EditorLogic.fetch.ship.parts;
+ }
+ else
+ {
+ parts = FlightGlobals.ActiveVessel.Parts;
+ Atmosphere = FlightGlobals.ActiveVessel.staticPressurekPa * PhysicsGlobals.KpaToAtmospheres;
+ }
+
+ // This call doesn't ever fail at the moment but we'll check and return a sensible error for display
+ if (simulation.PrepareSimulation(parts, Gravity, Atmosphere, Mach, dumpTree, vectoredThrust))
+ {
+ ThreadPool.QueueUserWorkItem(RunSimulation, simulation);
+ //RunSimulation(simulation);
+ }
+ else
+ {
+ failMessage = "PrepareSimulation failed";
+ lock (locker)
+ {
+ bRunning = false;
+ }
+ logOutput = false;
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Exception(e, "SimManager.StartSimulation()");
+ failMessage = e.ToString();
+ lock (locker)
+ {
+ bRunning = false;
+ }
+ logOutput = false;
+ }
+ dumpTree = false;
+ }
+
+ #endregion
}
}
--- a/KerbalEngineer/VesselSimulator/Simulation.cs
+++ b/KerbalEngineer/VesselSimulator/Simulation.cs
@@ -30,28 +30,35 @@
namespace KerbalEngineer.VesselSimulator
{
+ using CompoundParts;
+ using Extensions;
+ using Helpers;
+
public class Simulation
{
- private const double STD_GRAVITY = 9.81d;
- private const double SECONDS_PER_DAY = 86400d;
+ private const double SECONDS_PER_DAY = 86400;
private readonly Stopwatch _timer = new Stopwatch();
- private List<EngineSim> activeEngines;
- private List<EngineSim> allEngines;
- private List<PartSim> allFuelLines;
- private List<PartSim> allParts;
+ private List<EngineSim> activeEngines = new List<EngineSim>();
+ private List<EngineSim> allEngines = new List<EngineSim>();
+ private List<PartSim> allFuelLines = new List<PartSim>();
+ private List<PartSim> allParts = new List<PartSim>();
private double atmosphere;
private int currentStage;
private double currentisp;
+ private HashSet<PartSim> decoupledParts = new HashSet<PartSim>();
private bool doingCurrent;
private List<PartSim> dontStageParts;
+ private List<List<PartSim>> dontStagePartsLists = new List<List<PartSim>>();
private HashSet<PartSim> drainingParts;
private HashSet<int> drainingResources;
private double gravity;
+ private Dictionary<Part, PartSim> partSimLookup;
private int lastStage;
- private List<Part> partList;
+ private List<Part> partList = new List<Part>();
private double simpleTotalThrust;
private double stageStartMass;
+ private Vector3d stageStartCom;
private double stageTime;
private double stepEndMass;
private double stepStartMass;
@@ -59,95 +66,113 @@
private double totalStageFlowRate;
private double totalStageIspFlowRate;
private double totalStageThrust;
+ private ForceAccumulator totalStageThrustForce = new ForceAccumulator();
private Vector3 vecActualThrust;
private Vector3 vecStageDeltaV;
private Vector3 vecThrust;
- private double velocity;
+ private double mach;
+ private float maxMach;
public String vesselName;
public VesselType vesselType;
+ private WeightedVectorAverager vectorAverager = new WeightedVectorAverager();
+ private static ModuleProceduralFairing moduleProceduralFairing;
public Simulation()
{
- if (SimManager.logOutput)
- {
- MonoBehaviour.print("Simulation created");
- }
- }
-
- private double ShipStartMass
- {
- get
- {
- double mass = 0d;
-
- foreach (PartSim partSim in this.allParts)
- {
- mass += partSim.GetStartMass();
- }
-
- return mass;
- }
- }
-
- private double ShipMass
- {
- get
- {
- double mass = 0d;
-
- foreach (PartSim partSim in this.allParts)
- {
- mass += partSim.GetMass();
- }
-
- return mass;
- }
- }
-
- // This function prepares the simulation by creating all the necessary data structures it will
- // need during the simulation. All required data is copied from the core game data structures
- // so that the simulation itself can be run in a background thread without having issues with
- // the core game changing the data while the simulation is running.
- public bool PrepareSimulation(List<Part> parts, double theGravity, double theAtmosphere = 0, double theVelocity = 0, bool dumpTree = false, bool vectoredThrust = false)
- {
- LogMsg log = null;
- if (SimManager.logOutput)
- {
- log = new LogMsg();
- log.buf.AppendLine("PrepareSimulation started");
- dumpTree = true;
- }
- this._timer.Start();
-
- // Store the parameters in members for ease of access in other functions
- this.partList = parts;
- this.gravity = theGravity;
- this.atmosphere = theAtmosphere;
- this.velocity = theVelocity;
- this.lastStage = Staging.lastStage;
- //MonoBehaviour.print("lastStage = " + lastStage);
-
- // Create the lists for our simulation parts
this.allParts = new List<PartSim>();
this.allFuelLines = new List<PartSim>();
this.drainingParts = new HashSet<PartSim>();
this.allEngines = new List<EngineSim>();
this.activeEngines = new List<EngineSim>();
this.drainingResources = new HashSet<int>();
+ this.totalStageThrustForce = new ForceAccumulator();
// A dictionary for fast lookup of Part->PartSim during the preparation phase
- Dictionary<Part, PartSim> partSimLookup = new Dictionary<Part, PartSim>();
+ partSimLookup = new Dictionary<Part, PartSim>();
+
+ if (SimManager.logOutput)
+ {
+ MonoBehaviour.print("Simulation created");
+ }
+ }
+
+ private double ShipMass
+ {
+ get
+ {
+ double mass = 0d;
+
+ for (int i = 0; i < allParts.Count; ++i) {
+ mass += allParts[i].GetMass(currentStage);
+ }
+
+ return mass;
+ }
+ }
+
+ private Vector3d ShipCom
+ {
+ get
+ {
+ vectorAverager.Reset();
+
+ for (int i = 0; i < allParts.Count; ++i)
+ {
+ PartSim partSim = allParts[i];
+ vectorAverager.Add(partSim.centerOfMass, partSim.GetMass(currentStage, true));
+ }
+
+ return vectorAverager.Get();
+ }
+ }
+
+ // This function prepares the simulation by creating all the necessary data structures it will
+ // need during the simulation. All required data is copied from the core game data structures
+ // so that the simulation itself can be run in a background thread without having issues with
+ // the core game changing the data while the simulation is running.
+ public bool PrepareSimulation(List<Part> parts, double theGravity, double theAtmosphere = 0, double theMach = 0, bool dumpTree = false, bool vectoredThrust = false, bool fullThrust = false)
+ {
+ LogMsg log = null;
+ if (SimManager.logOutput)
+ {
+ log = new LogMsg();
+ log.buf.AppendLine("PrepareSimulation started");
+ dumpTree = true;
+ }
+ this._timer.Start();
+
+ // Store the parameters in members for ease of access in other functions
+ this.partList = parts;
+ this.gravity = theGravity;
+ this.atmosphere = theAtmosphere;
+ this.mach = theMach;
+ this.lastStage = Staging.lastStage;
+ this.maxMach = 1.0f;
+ //MonoBehaviour.print("lastStage = " + lastStage);
+
+ // Clear the lists for our simulation parts
+ allParts.Clear();
+ allFuelLines.Clear();
+ drainingParts.Clear();
+ allEngines.Clear();
+ activeEngines.Clear();
+ drainingResources.Clear();
+
+ // A dictionary for fast lookup of Part->PartSim during the preparation phase
+ partSimLookup.Clear();
if (this.partList.Count > 0 && this.partList[0].vessel != null)
{
this.vesselName = this.partList[0].vessel.vesselName;
this.vesselType = this.partList[0].vessel.vesselType;
}
-
+ //MonoBehaviour.print("PrepareSimulation pool size = " + PartSim.pool.Count());
// First we create a PartSim for each Part (giving each a unique id)
int partId = 1;
- foreach (Part part in this.partList)
- {
+ for (int i = 0; i < partList.Count; ++i)
+ {
+ Part part = partList[i];
+
// If the part is already in the lookup dictionary then log it and skip to the next part
if (partSimLookup.ContainsKey(part))
{
@@ -159,7 +184,7 @@
}
// Create the PartSim
- PartSim partSim = new PartSim(part, partId, this.atmosphere, log);
+ PartSim partSim = PartSim.New(part, partId, this.atmosphere, log);
// Add it to the Part lookup dictionary and the necessary lists
partSimLookup.Add(part, partSim);
@@ -170,30 +195,39 @@
}
if (partSim.isEngine)
{
- partSim.CreateEngineSims(this.allEngines, this.atmosphere, this.velocity, vectoredThrust, log);
+ partSim.CreateEngineSims(this.allEngines, this.atmosphere, this.mach, vectoredThrust, fullThrust, log);
}
partId++;
+ }
+
+ for (int i = 0; i < allEngines.Count; ++i)
+ {
+ maxMach = Mathf.Max(maxMach, allEngines[i].maxMach);
}
this.UpdateActiveEngines();
// Now that all the PartSims have been created we can do any set up that needs access to other parts
// First we set up all the parent links
- foreach (PartSim partSim in this.allParts)
- {
+ for (int i = 0; i < this.allParts.Count; i++)
+ {
+ PartSim partSim = this.allParts[i];
partSim.SetupParent(partSimLookup, log);
}
// Then, in the VAB/SPH, we add the parent of each fuel line to the fuelTargets list of their targets
if (HighLogic.LoadedSceneIsEditor)
{
- foreach (PartSim partSim in this.allFuelLines)
- {
- if ((partSim.part as FuelLine).target != null)
+ for (int i = 0; i < allFuelLines.Count; ++i)
+ {
+ PartSim partSim = allFuelLines[i];
+
+ CModuleFuelLine fuelLine = partSim.part.GetModule<CModuleFuelLine>();
+ if (fuelLine.target != null)
{
PartSim targetSim;
- if (partSimLookup.TryGetValue((partSim.part as FuelLine).target, out targetSim))
+ if (partSimLookup.TryGetValue(fuelLine.target, out targetSim))
{
if (log != null)
{
@@ -221,8 +255,10 @@
}
//MonoBehaviour.print("SetupAttachNodes and count stages");
- foreach (PartSim partSim in this.allParts)
- {
+ for (int i = 0; i < allParts.Count; ++i)
+ {
+ PartSim partSim = allParts[i];
+
partSim.SetupAttachNodes(partSimLookup, log);
if (partSim.decoupledInStage >= this.lastStage)
{
@@ -232,9 +268,9 @@
// And finally release the Part references from all the PartSims
//MonoBehaviour.print("ReleaseParts");
- foreach (PartSim partSim in this.allParts)
- {
- partSim.ReleasePart();
+ for (int i = 0; i < allParts.Count; ++i)
+ {
+ allParts[i].ReleasePart();
}
// And dereference the core's part list
@@ -254,7 +290,7 @@
return true;
}
-
+
// This function runs the simulation and returns a newly created array of Stage objects
public Stage[] RunSimulation()
{
@@ -262,6 +298,7 @@
{
MonoBehaviour.print("RunSimulation started");
}
+
this._timer.Start();
LogMsg log = null;
@@ -273,13 +310,14 @@
// Start with the last stage to simulate
// (this is in a member variable so it can be accessed by AllowedToStage and ActivateStage)
this.currentStage = this.lastStage;
-
// Work out which engines would be active if just doing the staging and if this is different to the
// currently active engines then generate an extra stage
// Loop through all the engines
bool anyActive = false;
- foreach (EngineSim engine in this.allEngines)
- {
+ for (int i = 0; i < allEngines.Count; ++i)
+ {
+ EngineSim engine = allEngines[i];
+
if (log != null)
{
log.buf.AppendLine("Testing engine mod of " + engine.partSim.name + ":" + engine.partSim.partId);
@@ -334,7 +372,7 @@
}
// Create a list of lists of PartSims that prevent decoupling
- List<List<PartSim>> dontStagePartsLists = this.BuildDontStageLists(log);
+ BuildDontStageLists(log);
if (log != null)
{
@@ -356,6 +394,12 @@
this._timer.Start();
}
+ // Update the masses of the parts to correctly handle "no physics" parts
+ this.UpdatePartMasses();
+
+ if (log != null)
+ this.allParts[0].DumpPartToBuffer(log.buf, "", this.allParts);
+
// Update active engines and resource drains
this.UpdateResourceDrains();
@@ -364,7 +408,10 @@
this.stageTime = 0d;
this.vecStageDeltaV = Vector3.zero;
+
this.stageStartMass = this.ShipMass;
+ this.stageStartCom = this.ShipCom;
+
this.stepStartMass = this.stageStartMass;
this.stepEndMass = 0;
@@ -372,23 +419,51 @@
// 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);
+ // calculate torque and associates
+ stage.maxThrustTorque = this.totalStageThrustForce.TorqueAt(this.stageStartCom).magnitude;
+
+ // torque divided by thrust. imagine that all engines are at the end of a lever that tries to turn the ship.
+ // this numerical value, in meters, would represent the length of that lever.
+ double torqueLeverArmLength = (stage.thrust <= 0) ? 0 : stage.maxThrustTorque / stage.thrust;
+
+ // how far away are the engines from the CoM, actually?
+ double thrustDistance = (this.stageStartCom - this.totalStageThrustForce.GetAverageForceApplicationPoint()).magnitude;
+
+ // the combination of the above two values gives an approximation of the offset angle.
+ double sinThrustOffsetAngle = 0;
+ if (thrustDistance > 1e-7) {
+ sinThrustOffsetAngle = torqueLeverArmLength / thrustDistance;
+ if (sinThrustOffsetAngle > 1) {
+ sinThrustOffsetAngle = 1;
+ }
+ }
+
+ 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
- foreach (PartSim partSim in this.allParts)
- {
+ 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;
+ }
}
this.dontStageParts = dontStagePartsLists[this.currentStage];
@@ -400,8 +475,9 @@
if (this.dontStageParts.Count > 0)
{
log.buf.AppendLine("Parts preventing staging:");
- foreach (PartSim partSim in this.dontStageParts)
- {
+ for (int i = 0; i < this.dontStageParts.Count; i++)
+ {
+ PartSim partSim = this.dontStageParts[i];
partSim.DumpPartToBuffer(log.buf, "");
}
}
@@ -412,6 +488,7 @@
log.Flush();
}
+
// Now we will loop until we are allowed to stage
int loopCounter = 0;
@@ -419,7 +496,6 @@
{
loopCounter++;
//MonoBehaviour.print("loop = " + loopCounter);
-
// Calculate how long each draining tank will take to drain and run for the minimum time
double resourceDrainTime = double.MaxValue;
PartSim partMinDrain = null;
@@ -437,7 +513,6 @@
{
MonoBehaviour.print("Drain time = " + resourceDrainTime + " (" + partMinDrain.name + ":" + partMinDrain.partId + ")");
}
-
foreach (PartSim partSim in this.drainingParts)
{
partSim.DrainResources(resourceDrainTime);
@@ -461,7 +536,7 @@
// If we have drained anything and the masses make sense then add this step's deltaV to the stage total
if (resourceDrainTime > 0d && this.stepStartMass > this.stepEndMass && this.stepStartMass > 0d && this.stepEndMass > 0d)
{
- this.vecStageDeltaV += this.vecThrust * (float)((this.currentisp * STD_GRAVITY * Math.Log(this.stepStartMass / this.stepEndMass)) / this.simpleTotalThrust);
+ this.vecStageDeltaV += this.vecThrust * (float)((this.currentisp * Units.GRAVITY * Math.Log(this.stepStartMass / this.stepEndMass)) / this.simpleTotalThrust);
}
// Update the active engines and resource drains for the next step
@@ -469,7 +544,7 @@
// Recalculate the current thrust and isp for the next step
this.CalculateThrustAndISP();
-
+
// Check if we actually changed anything
if (this.stepStartMass == this.stepEndMass)
{
@@ -484,6 +559,10 @@
MonoBehaviour.print("stageStartMass = " + this.stageStartMass);
MonoBehaviour.print("stepStartMass = " + this.stepStartMass);
MonoBehaviour.print("StepEndMass = " + this.stepEndMass);
+ Logger.Log("exceeded loop count");
+ Logger.Log("stageStartMass = " + this.stageStartMass);
+ Logger.Log("stepStartMass = " + this.stepStartMass);
+ Logger.Log("StepEndMass = " + this.stepEndMass);
break;
}
@@ -491,16 +570,18 @@
this.stepStartMass = this.stepEndMass;
}
+
// Store more values in the Stage object and stick it in the array
// Store the magnitude of the deltaV vector
stage.deltaV = this.vecStageDeltaV.magnitude;
+ stage.resourceMass = this.stageStartMass - this.stepEndMass;
// Recalculate effective stage isp from the stage deltaV (flip the standard deltaV calculation around)
// Note: If the mass doesn't change then this is a divide by zero
if (this.stageStartMass != this.stepStartMass)
{
- stage.isp = stage.deltaV / (STD_GRAVITY * Math.Log(this.stageStartMass / this.stepStartMass));
+ stage.isp = stage.deltaV / (Units.GRAVITY * Math.Log(this.stageStartMass / this.stepStartMass));
}
else
{
@@ -510,7 +591,8 @@
// Zero stage time if more than a day (this should be moved into the window code)
stage.time = (this.stageTime < SECONDS_PER_DAY) ? this.stageTime : 0d;
stage.number = this.doingCurrent ? -1 : this.currentStage; // Set the stage number to -1 if doing current engines
- stage.partCount = this.allParts.Count;
+ stage.totalPartCount = this.allParts.Count;
+ stage.maxMach = maxMach;
stages[this.currentStage] = stage;
// Now activate the next stage
@@ -548,6 +630,7 @@
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;
}
// We also total up the deltaV for stage and all stages below
for (int j = i; j < stages.Length; j++)
@@ -568,29 +651,93 @@
this._timer.Stop();
MonoBehaviour.print("RunSimulation: " + this._timer.ElapsedMilliseconds + "ms");
}
-
+ FreePooledObject();
+
return stages;
}
- private List<List<PartSim>> BuildDontStageLists(LogMsg log)
+ public void 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;
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < this.allParts.Count; i++)
+ this.allParts[i].startMass = this.allParts[i].GetMass(currentStage);
+ }
+
+ // Make sure we free them all, even if they should all be free already at this point
+ public void FreePooledObject()
+ {
+ //MonoBehaviour.print("FreePooledObject pool size before = " + PartSim.pool.Count() + " for " + allParts.Count + " parts");
+ foreach (PartSim part in allParts)
+ {
+ part.Release();
+ }
+ //MonoBehaviour.print("FreePooledObject pool size after = " + PartSim.pool.Count());
+
+ //MonoBehaviour.print("FreePooledObject pool size before = " + EngineSim.pool.Count() + " for " + allEngines.Count + " engines");
+ foreach (EngineSim engine in allEngines)
+ {
+ engine.Release();
+ }
+ //MonoBehaviour.print("FreePooledObject pool size after = " + EngineSim.pool.Count());
+ }
+
+ private void BuildDontStageLists(LogMsg log)
{
if (log != null)
{
log.buf.AppendLine("Creating list with capacity of " + (this.currentStage + 1));
}
- List<List<PartSim>> lists = new List<List<PartSim>>();
+
+ dontStagePartsLists.Clear();
for (int i = 0; i <= this.currentStage; i++)
{
- lists.Add(new List<PartSim>());
- }
-
- foreach (PartSim partSim in this.allParts)
- {
+ if (i < dontStagePartsLists.Count)
+ {
+ dontStagePartsLists[i].Clear();
+ }
+ else
+ {
+ dontStagePartsLists.Add(new List<PartSim>());
+ }
+ }
+
+ for (int i = 0; i < allParts.Count; ++i)
+ {
+ PartSim partSim = allParts[i];
+
if (partSim.isEngine || !partSim.Resources.Empty)
{
if (log != null)
{
- log.buf.AppendLine(partSim.name + ":" + partSim.partId + " is engine or tank, decoupled = " + partSim.decoupledInStage);
+ log.buf.AppendLine(
+ partSim.name + ":" + partSim.partId + " is engine or tank, decoupled = " + partSim.decoupledInStage);
}
if (partSim.decoupledInStage < -1 || partSim.decoupledInStage > this.currentStage - 1)
@@ -602,28 +749,27 @@
}
else
{
- lists[partSim.decoupledInStage + 1].Add(partSim);
+ dontStagePartsLists[partSim.decoupledInStage + 1].Add(partSim);
}
}
}
for (int i = 1; i <= this.lastStage; i++)
{
- if (lists[i].Count == 0)
- {
- lists[i] = lists[i - 1];
- }
- }
-
- return lists;
+ if (dontStagePartsLists[i].Count == 0)
+ {
+ dontStagePartsLists[i] = dontStagePartsLists[i - 1];
+ }
+ }
}
// This function simply rebuilds the active engines by testing the isActive flag of all the engines
private void UpdateActiveEngines()
{
this.activeEngines.Clear();
- foreach (EngineSim engine in this.allEngines)
- {
+ for (int i = 0; i < allEngines.Count; ++i)
+ {
+ EngineSim engine = allEngines[i];
if (engine.isActive)
{
this.activeEngines.Add(engine);
@@ -641,21 +787,27 @@
this.totalStageActualThrust = 0d;
this.totalStageFlowRate = 0d;
this.totalStageIspFlowRate = 0d;
+ this.totalStageThrustForce.Reset();
// Loop through all the active engines totalling the thrust, actual thrust and mass flow rates
// The thrust is totalled as vectors
- foreach (EngineSim engine in this.activeEngines)
- {
+ for (int i = 0; i < activeEngines.Count; ++i)
+ {
+ EngineSim engine = activeEngines[i];
+
this.simpleTotalThrust += engine.thrust;
this.vecThrust += ((float)engine.thrust * engine.thrustVec);
this.vecActualThrust += ((float)engine.actualThrust * engine.thrustVec);
this.totalStageFlowRate += engine.ResourceConsumptions.Mass;
this.totalStageIspFlowRate += engine.ResourceConsumptions.Mass * engine.isp;
- }
-
+
+ for (int j = 0; j < engine.appliedForces.Count; ++j)
+ {
+ this.totalStageThrustForce.AddForce(engine.appliedForces[j]);
+ }
+ }
//MonoBehaviour.print("vecThrust = " + vecThrust.ToString() + " magnitude = " + vecThrust.magnitude);
-
this.totalStageThrust = this.vecThrust.magnitude;
this.totalStageActualThrust = this.vecActualThrust.magnitude;
@@ -690,15 +842,17 @@
this.drainingParts.Clear();
// Loop through all the active engine modules
- foreach (EngineSim engine in this.activeEngines)
- {
+ for (int i = 0; i < activeEngines.Count; ++i)
+ {
+ EngineSim engine = activeEngines[i];
+
// Set the resource drains for this engine
if (engine.SetResourceDrains(this.allParts, this.allFuelLines, this.drainingParts))
{
// If it is active then add the consumed resource types to the set
- foreach (int type in engine.ResourceConsumptions.Types)
- {
- this.drainingResources.Add(type);
+ for (int j = 0; j < engine.ResourceConsumptions.Types.Count; ++j)
+ {
+ drainingResources.Add(engine.ResourceConsumptions.Types[j]);
}
}
}
@@ -711,8 +865,9 @@
StringBuilder buffer = new StringBuilder(1024);
buffer.AppendFormat("Active engines = {0:d}\n", this.activeEngines.Count);
int i = 0;
- foreach (EngineSim engine in this.activeEngines)
- {
+ for (int j = 0; j < this.activeEngines.Count; j++)
+ {
+ EngineSim engine = this.activeEngines[j];
engine.DumpEngineToBuffer(buffer, "Engine " + (i++) + ":");
}
MonoBehaviour.print(buffer);
@@ -732,29 +887,32 @@
if (this.activeEngines.Count > 0)
{
- foreach (PartSim partSim in this.dontStageParts)
- {
+ for (int i = 0; i < dontStageParts.Count; ++i)
+ {
+ PartSim partSim = dontStageParts[i];
+
if (SimManager.logOutput)
{
partSim.DumpPartToBuffer(buffer, "Testing: ");
}
//buffer.AppendFormat("isSepratron = {0}\n", partSim.isSepratron ? "true" : "false");
- if (!partSim.isSepratron && !partSim.Resources.EmptyOf(this.drainingResources))
+ if (!partSim.isSepratron && !partSim.EmptyOf(this.drainingResources))
{
if (SimManager.logOutput)
{
partSim.DumpPartToBuffer(buffer, "Decoupled part not empty => false: ");
MonoBehaviour.print(buffer);
}
-
return false;
}
if (partSim.isEngine)
{
- foreach (EngineSim engine in this.activeEngines)
- {
+ for (int j = 0; j < activeEngines.Count; ++j)
+ {
+ EngineSim engine = activeEngines[j];
+
if (engine.partSim == partSim)
{
if (SimManager.logOutput)
@@ -792,9 +950,11 @@
private void ActivateStage()
{
// Build a set of all the parts that will be decoupled
- HashSet<PartSim> decoupledParts = new HashSet<PartSim>();
- foreach (PartSim partSim in this.allParts)
- {
+ decoupledParts.Clear();
+ for (int i = 0; i < allParts.Count; ++i)
+ {
+ PartSim partSim = allParts[i];
+
if (partSim.decoupledInStage >= this.currentStage)
{
decoupledParts.Add(partSim);
@@ -805,14 +965,17 @@
{
// Remove it from the all parts list
this.allParts.Remove(partSim);
+ partSim.Release();
if (partSim.isEngine)
{
// If it is an engine then loop through all the engine modules and remove all the ones from this engine part
for (int i = this.allEngines.Count - 1; i >= 0; i--)
{
- if (this.allEngines[i].partSim == partSim)
+ EngineSim engine = this.allEngines[i];
+ if (engine.partSim == partSim)
{
this.allEngines.RemoveAt(i);
+ engine.Release();
}
}
}
@@ -824,15 +987,16 @@
}
// Loop through all the (remaining) parts
- foreach (PartSim partSim in this.allParts)
- {
+ for (int i = 0; i < allParts.Count; ++i)
+ {
// Ask the part to remove all the parts that are decoupled
- partSim.RemoveAttachedParts(decoupledParts);
+ allParts[i].RemoveAttachedParts(decoupledParts);
}
// Now we loop through all the engines and activate those that are ignited in this stage
- foreach (EngineSim engine in this.allEngines)
- {
+ for (int i = 0; i < allEngines.Count; ++i)
+ {
+ EngineSim engine = allEngines[i];
if (engine.partSim.inverseStage == this.currentStage)
{
engine.isActive = true;
@@ -866,3 +1030,4 @@
}
}
}
+
--- a/KerbalEngineer/VesselSimulator/Stage.cs
+++ b/KerbalEngineer/VesselSimulator/Stage.cs
@@ -29,23 +29,29 @@
{
public class Stage
{
- public double actualThrust = 0f;
- public double actualThrustToWeight = 0f;
- public double cost = 0d;
- public double deltaV = 0f;
- public double inverseTotalDeltaV = 0f;
- public double isp = 0f;
- public double mass = 0f;
- public double maxThrustToWeight = 0f;
+ public double actualThrust = 0.0;
+ public double actualThrustToWeight = 0.0;
+ public double cost = 0.0;
+ public double deltaV = 0.0;
+ public double inverseTotalDeltaV = 0.0;
+ public double isp = 0.0;
+ public double mass = 0.0;
+ public double rcsMass = 0.0;
+ public double maxThrustToWeight = 0.0;
public int number = 0;
- public double thrust = 0f;
- public double thrustToWeight = 0f;
- public double time = 0f;
- public double totalCost = 0;
- public double totalDeltaV = 0f;
- public double totalMass = 0f;
- public double totalTime = 0f;
+ public double thrust = 0.0;
+ public double thrustToWeight = 0.0;
+ public double time = 0.0;
+ public double totalCost = 0.0;
+ public double totalDeltaV = 0.0;
+ public double totalMass = 0.0;
+ public double totalTime = 0.0;
+ public int totalPartCount = 0;
public int partCount = 0;
+ public double resourceMass = 0.0;
+ public double maxThrustTorque = 0.0;
+ public double thrustOffsetAngle = 0.0;
+ public float maxMach = 0.0f;
public void Dump()
{
@@ -63,6 +69,8 @@
str.AppendFormat("thrustToWeight: {0:g6}\n", this.thrustToWeight);
str.AppendFormat("maxTWR : {0:g6}\n", this.maxThrustToWeight);
str.AppendFormat("actualTWR : {0:g6}\n", this.actualThrustToWeight);
+ str.AppendFormat("ThrustTorque : {0:g6}\n", this.maxThrustTorque);
+ str.AppendFormat("ThrustOffset : {0:g6}\n", this.thrustOffsetAngle);
str.AppendFormat("deltaV : {0:g6}\n", this.deltaV);
str.AppendFormat("totalDeltaV : {0:g6}\n", this.totalDeltaV);
str.AppendFormat("invTotDeltaV : {0:g6}\n", this.inverseTotalDeltaV);
Binary files a/Output/KerbalEngineer/KerbalEngineer.dll and b/Output/KerbalEngineer/KerbalEngineer.dll differ
--- a/Output/KerbalEngineer/KerbalEngineer.version
+++ b/Output/KerbalEngineer/KerbalEngineer.version
@@ -5,13 +5,13 @@
{
"MAJOR":1,
"MINOR":0,
- "PATCH":11,
- "BUILD":0
+ "PATCH":16,
+ "BUILD":6
},
"KSP_VERSION":
{
- "MAJOR":0,
- "MINOR":25,
- "PATCH":0
+ "MAJOR":1,
+ "MINOR":0,
+ "PATCH":2
}
}
Binary files /dev/null and b/Output/KerbalEngineer/Parts/Engineer7500/model000.mbm differ
--- a/Output/KerbalEngineer/Parts/Engineer7500/part.cfg
+++ b/Output/KerbalEngineer/Parts/Engineer7500/part.cfg
@@ -7,7 +7,6 @@
// --- asset parameters ---
mesh = model.mu
- texture = model000.mbm
rescaleFactor = 0.8
PhysicsSignificance = 1
Binary files a/Output/KerbalEngineer/Parts/Engineer7500/textures/model000.mbm and /dev/null differ
--- /dev/null
+++ b/Output/KerbalEngineer/Settings/HelpStrings.xml
@@ -1,1 +1,319 @@
-
+<?xml version="1.0" encoding="utf-8"?>
+<ArrayOfSettingItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <SettingItem>
+ <Name>Orbital.ApoapsisHeight</Name>
+ <Value xsi:type="string">Shows the vessel's apoapsis height relative to sea level. (Apoapsis is the highest point of an orbit.)</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.PeriapsisHeight</Name>
+ <Value xsi:type="string">Shows the vessel's periapsis height relative to sea level. (Periapsis is the lowest point of an orbit.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.TimeToApoapsis</Name>
+ <Value xsi:type="string">Shows the time until the vessel reaches apoapsis, the highest point of the orbit.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.TimeToPeriapsis</Name>
+ <Value xsi:type="string">Shows the time until the vessel reaches periapsis, the lowest point of the orbit.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.Inclination</Name>
+ <Value xsi:type="string">Shows the vessel's orbital inclination.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.TimeToEquatorialAscendingNode</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.TimeToEquatorialDescendingNode</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.AngleToEquatorialAscendingNode</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.AngleToEquatorialDescendingNode</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.Eccentricity</Name>
+ <Value xsi:type="string">Shows the vessel's orbital eccentricity.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.OrbitalSpeed</Name>
+ <Value xsi:type="string">Shows the vessel's orbital speed.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.OrbitalPeriod</Name>
+ <Value xsi:type="string">Shows the amount of time it will take to complete a full orbit.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.LongitudeOfAscendingNode</Name>
+ <Value xsi:type="string">Shows the vessel's longitude of the ascending node.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.LongitudeOfPeriapsis</Name>
+ <Value xsi:type="string">Shows the vessel's longitude of periapsis.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.ArgumentOfPeriapsis</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.TrueAnomaly</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.MeanAnomaly</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.EccentricAnomaly</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.SemiMajorAxis</Name>
+ <Value xsi:type="string">Shows the distance from the centre of an orbit to the farthest edge.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.SemiMinorAxis</Name>
+ <Value xsi:type="string">Shows the distance from the centre of an orbit to the nearest edge.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.AngleToPrograde</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Orbital.AngleToRetrograde</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.AltitudeSeaLevel</Name>
+ <Value xsi:type="string">Shows the vessel's altitude above sea level.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.AltitudeTerrain</Name>
+ <Value xsi:type="string">Shows the vessel's altitude above the terrain.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.VerticalSpeed</Name>
+ <Value xsi:type="string">Shows the vessel's vertical speed up and down.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.VerticalAcceleration</Name>
+ <Value xsi:type="string">Shows the vessel's vertical acceleration up and down.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.HorizontalSpeed</Name>
+ <Value xsi:type="string">Shows the vessel's horizontal speed across a celestial body's surface.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.HorizontalAcceleration</Name>
+ <Value xsi:type="string">Shows the vessel's horizontal acceleration across a celestial body's surface.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.Latitude</Name>
+ <Value xsi:type="string">Shows the vessel's latitude position around the celestial body. Latitude is the angle from the equator to poles.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.Longitude</Name>
+ <Value xsi:type="string">Shows the vessel's longitude around a celestial body. Longitude is the angle from the bodies prime meridian.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.GeeForce</Name>
+ <Value xsi:type="string">Shows the current g-force and maximum g-force experienced.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.TerminalVelocity</Name>
+ <Value xsi:type="string">Shows the velocity where the efforts of thrust and drag are equalled out.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.AtmosphericEfficiency</Name>
+ <Value xsi:type="string">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.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.Biome</Name>
+ <Value xsi:type="string">Shows the biome which the vessel is currently flying over.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.Slope</Name>
+ <Value xsi:type="string">Shows the slope of the terrain below your vessel.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.ImpactTime</Name>
+ <Value xsi:type="string">Shows how much time until your ship impacts the surface.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.ImpactLongitude</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.ImpactLatitude</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.ImpactAltitude</Name>
+ <Value xsi:type="string">The altitude of which you will impact the surface.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Surface.ImpactBiome</Name>
+ <Value xsi:type="string">Shows the biome you will impact in.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.DeltaVStaged</Name>
+ <Value xsi:type="string">Shows the vessel's delta velocity for each stage.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.DeltaVCurrent</Name>
+ <Value xsi:type="string">Shows the vessel's current stage delta velocity.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.DeltaVTotal</Name>
+ <Value xsi:type="string">Shows the vessel's total delta velocity.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.SpecificImpulse</Name>
+ <Value xsi:type="string">The ISP of your vessel.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.Mass</Name>
+ <Value xsi:type="string">The total mass of your vessel.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.Thrust</Name>
+ <Value xsi:type="string">The thrust of your vessel.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.ThrustToWeight</Name>
+ <Value xsi:type="string">Shows the vessel's actual and total thrust to weight ratio.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.SurfaceThrustToWeight</Name>
+ <Value xsi:type="string">Shows the vessel's surface thrust to weight ratio.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.Acceleration</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.SuicideBurnAltitude</Name>
+ <Value xsi:type="string">Shows the altitude when to start a suicide burn.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.SuicideBurnDistance</Name>
+ <Value xsi:type="string">Shows the distance to the point at which to start a suicide burn.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.SuicideBurnDeltaV</Name>
+ <Value xsi:type="string">Shows the DeltaV of a suicide burn.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.IntakeAirUsage</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.IntakeAirDemand</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.IntakeAirSupply</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Vessel.IntakeAirDemandSupply</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.TargetSelector</Name>
+ <Value xsi:type="string">A tool to allow easy browsing, searching and selection of targets.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.PhaseAngle</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.InterceptAngle</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.RelativeVelocity</Name>
+ <Value xsi:type="string">Shows the relative velocity between your vessel and the target object.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.RelativeSpeed</Name>
+ <Value xsi:type="string">Shows the difference in orbital speed between your vessel and the target object.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.RelativeInclination</Name>
+ <Value xsi:type="string">Shows the relative inclination between your vessel and the target object.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.TimeToRelativeAscendingNode</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.TimeToRelativeDescendingNode</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.AngleToRelativeAscendingNode</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.AngleToRelativeDescendingNode</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.AltitudeSeaLevel</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.ApoapsisHeight</Name>
+ <Value xsi:type="string">Shows the altitude of your apoapsis</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.PeriapsisHeight</Name>
+ <Value xsi:type="string">Shows the altitude of your periapsis</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.TimeToApoapsis</Name>
+ <Value xsi:type="string">The time until you reach your apoapsis</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.TimeToPeriapsis</Name>
+ <Value xsi:type="string">The time until you reach your periapsis</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.Distance</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.OrbitalPeriod</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.SemiMajorAxis</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Rendezvous.SemiMinorAxis</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Miscellaneous.Separator</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Miscellaneous.GuiSizeAdjustor</Name>
+ <Value xsi:type="string">Shows a control that will allow you to adjust the GUI size.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Miscellaneous.SimulationDelay</Name>
+ <Value xsi:type="string">Controls the minimum delay between processing vessel simulations.</Value>
+ </SettingItem>
+ <SettingItem>
+ <Name>Miscellaneous.TimeReference</Name>
+ <Value xsi:type="string"></Value>
+ </SettingItem>
+</ArrayOfSettingItem>