From: Andy Wilkinson Date: Sat, 03 Jan 2015 16:16:05 +0000 Subject: Removed .dll from version control. X-Git-Tag: 0.18 X-Git-Url: http://git.toad.homelinux.net/projects/VOID.git/commitdiff/c2afc5b --- Removed .dll from version control. --- --- /dev/null +++ b/GameData/VOID/Textures/ATM_VOID.cfg @@ -1,1 +1,16 @@ +ACTIVE_TEXTURE_MANAGER_CONFIG +{ + folder = VOID + enabled = true + OVERRIDES + { + VOID/.* + { + compress = true + mipmaps = false + scale = 1 + max_size = 0 + } + } +} --- a/IVOID_Module.cs +++ b/IVOID_Module.cs @@ -51,6 +51,7 @@ { void Update(); void FixedUpdate(); + void OnDestroy(); } public interface IVOID_EditorModule : IVOID_Module {} --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -39,7 +39,7 @@ // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. -[assembly: AssemblyVersion("0.13.*")] +[assembly: AssemblyVersion("0.16.4.*")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. //[assembly: AssemblyDelaySign(false)] --- a/VOID.csproj +++ b/VOID.csproj @@ -26,7 +26,7 @@ false - + @@ -39,7 +39,7 @@ TRACE - + @@ -54,7 +54,7 @@ false - + @@ -67,7 +67,7 @@ false - + @@ -96,6 +96,11 @@ + + + + + @@ -127,5 +132,8 @@ VesselSimulator + + + --- a/VOIDEditorMaster.cs +++ b/VOIDEditorMaster.cs @@ -40,7 +40,7 @@ // /////////////////////////////////////////////////////////////////////////////// -using Engineer.VesselSimulator; +using KerbalEngineer.VesselSimulator; using KSP; using System; using ToadicusTools; @@ -105,6 +105,26 @@ this.Core.OnGUI(); } + + public void OnDestroy() + { + if (this.Core == null) + { + return; + } + + this.Core.OnDestroy(); + } + + public void OnApplicationQuit() + { + if (this.Core == null) + { + return; + } + + this.Core.OnApplicationQuit(); + } } } --- a/VOIDFlightMaster.cs +++ b/VOIDFlightMaster.cs @@ -42,7 +42,7 @@ using System; using UnityEngine; -using Engineer.VesselSimulator; +using KerbalEngineer.VesselSimulator; using ToadicusTools; namespace VOID @@ -104,6 +104,26 @@ this.Core.OnGUI(); } + + public void OnDestroy() + { + if (this.Core == null) + { + return; + } + + this.Core.OnDestroy(); + } + + public void OnApplicationQuit() + { + if (this.Core == null) + { + return; + } + + this.Core.OnApplicationQuit(); + } } } --- a/VOID_CBInfoBrowser.cs +++ b/VOID_CBInfoBrowser.cs @@ -51,6 +51,9 @@ [AVOID_SaveValue("togglePhysical")] protected VOID_SaveValue togglePhysical = false; + [AVOID_SaveValue("toggleScience")] + protected VOID_SaveValue toggleScience = false; + public VOID_CBInfoBrowser() { this._Name = "Celestial Body Information Browser"; @@ -81,7 +84,7 @@ selectedBodyIdx1--; if (selectedBodyIdx1 < 0) selectedBodyIdx1 = this.core.allBodies.Count - 1; } - GUILayout.Label(this.core.allBodies[selectedBodyIdx1].bodyName, this.core.LabelStyles["center_bold"], GUILayout.ExpandWidth(true)); + GUILayout.Label(this.core.allBodies[selectedBodyIdx1].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); if (GUILayout.Button(">", GUILayout.ExpandWidth(false))) { selectedBodyIdx1++; @@ -97,7 +100,7 @@ selectedBodyIdx2--; if (selectedBodyIdx2 < 0) selectedBodyIdx2 = this.core.allBodies.Count - 1; } - GUILayout.Label(this.core.allBodies[selectedBodyIdx2].bodyName, this.core.LabelStyles["center_bold"], GUILayout.ExpandWidth(true)); + GUILayout.Label(this.core.allBodies[selectedBodyIdx2].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); if (GUILayout.Button(">", GUILayout.ExpandWidth(false))) { selectedBodyIdx2++; @@ -208,87 +211,153 @@ GUILayout.EndHorizontal(); } + if (GUILayout.Button("Scientific Parameters", GUILayout.ExpandWidth(true))) + { + toggleScience.value = !toggleScience; + } + + if (toggleScience) + { + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + + //begin physical info value label column + GUILayout.BeginVertical(GUILayout.Width(150)); + + + /* + * public float RecoveryValue = 1f; + + public float InSpaceHighDataValue = 1f; + + public float spaceAltitudeThreshold = 250000f; + + public float flyingAltitudeThreshold = 18000f; + + public float InSpaceLowDataValue = 1f; + + public float SplashedDataValue = 1f; + + public float LandedDataValue = 1f; + + public float FlyingHighDataValue = 1f; + + public float FlyingLowDataValue = 1f; + */ + + GUILayout.Label("Surface Multiplier:"); + GUILayout.Label("Ocean Multiplier:"); + GUILayout.Label("Flying-Low Multiplier:"); + GUILayout.Label("Flying-High Multiplier:"); + GUILayout.Label("Low Orbit Multiplier:"); + GUILayout.Label("High Orbit Multiplier:"); + GUILayout.Label("'Flying-High' Altitude:"); + GUILayout.Label("'High Orbit' Altitude:"); + GUILayout.Label("Recovery Multiplier:"); + + //end physical info value label column + GUILayout.EndVertical(); + + //begin primary physical values column + GUILayout.BeginVertical(GUILayout.Width(150)); + + this.cbColumnScience(selectedBody1); + + //end primary physical column + GUILayout.EndVertical(); + + //begin secondary physical values column + GUILayout.BeginVertical(GUILayout.Width(150)); + + this.cbColumnScience(selectedBody2); + + //end target physical values column + GUILayout.EndVertical(); + + //end physical value horizontal chunk + GUILayout.EndHorizontal(); + } + GUI.DragWindow(); } private void body_OP_show_orbital_info(CelestialBody body) { - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label((body.orbit.ApA / 1000).ToString("##,#") + "km", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label(VOID_Tools.ConvertInterval(body.orbit.timeToAp), this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label((body.orbit.PeA / 1000).ToString("##,#") + "km", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label(VOID_Tools.ConvertInterval(body.orbit.timeToPe), this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label((body.orbit.semiMajorAxis / 1000).ToString("##,#") + "km", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label(body.orbit.eccentricity.ToString("F4") + "", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label(VOID_Tools.ConvertInterval(body.orbit.period), this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label(VOID_Tools.ConvertInterval(body.rotationPeriod), this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label((body.orbit.orbitalSpeed / 1000).ToString("F2") + "km/s", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label((body.orbit.ApA / 1000).ToString("##,#") + "km", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label(VOID_Tools.FormatInterval(body.orbit.timeToAp), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label((body.orbit.PeA / 1000).ToString("##,#") + "km", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label(VOID_Tools.FormatInterval(body.orbit.timeToPe), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label((body.orbit.semiMajorAxis / 1000).ToString("##,#") + "km", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label(body.orbit.eccentricity.ToString("F4") + "", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label(VOID_Tools.FormatInterval(body.orbit.period), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label(VOID_Tools.FormatInterval(body.rotationPeriod), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label((body.orbit.orbitalSpeed / 1000).ToString("F2") + "km/s", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); // Toadicus edit: convert mean anomaly into degrees. - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label((body.orbit.meanAnomaly * 180d / Math.PI).ToString("F3") + "°", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label(body.orbit.trueAnomaly.ToString("F3") + "°", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label((body.orbit.meanAnomaly * 180d / Math.PI).ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label(body.orbit.trueAnomaly.ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); // Toadicus edit: convert eccentric anomaly into degrees. - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label((body.orbit.eccentricAnomaly * 180d / Math.PI).ToString("F3") + "°", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label(body.orbit.inclination.ToString("F3") + "°", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label(body.orbit.LAN.ToString("F3") + "°", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label(body.orbit.argumentOfPeriapsis.ToString("F3") + "°", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - if (body.bodyName == "Sun") GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label((body.orbit.eccentricAnomaly * 180d / Math.PI).ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label(body.orbit.inclination.ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label(body.orbit.LAN.ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label(body.orbit.argumentOfPeriapsis.ToString("F3") + "°", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + if (body.bodyName == "Sun") GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); else { string body_tidally_locked = "No"; if (body.tidallyLocked) body_tidally_locked = "Yes"; - GUILayout.Label(body_tidally_locked, this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); + GUILayout.Label(body_tidally_locked, VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); } } private void body_OP_show_physical_info(CelestialBody body) { - GUILayout.Label((body.Radius / 1000).ToString("##,#") + "km", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - GUILayout.Label((((body.Radius * body.Radius) * 4 * Math.PI) / 1000).ToString("0.00e+00") + "km²", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); + GUILayout.Label((body.Radius / 1000).ToString("##,#") + "km", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + GUILayout.Label((((body.Radius * body.Radius) * 4 * Math.PI) / 1000).ToString("0.00e+00") + "km²", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); // divide by 1000 to convert m to km - GUILayout.Label((((4d / 3) * Math.PI * (body.Radius * body.Radius * body.Radius)) / 1000).ToString("0.00e+00") + "km³", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - GUILayout.Label(body.Mass.ToString("0.00e+00") + "kg", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); + GUILayout.Label((((4d / 3) * Math.PI * (body.Radius * body.Radius * body.Radius)) / 1000).ToString("0.00e+00") + "km³", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + GUILayout.Label(body.Mass.ToString("0.00e+00") + "kg", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); double p = body.Mass / ((body.Radius * body.Radius * body.Radius) * (4d / 3) * Math.PI); - GUILayout.Label(p.ToString("##,#") + "kg/m³", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - if (body.bodyName == "Sun") GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - else GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - - GUILayout.Label(body.orbitingBodies.Count.ToString(), this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); + GUILayout.Label(p.ToString("##,#") + "kg/m³", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + if (body.bodyName == "Sun") GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + else GUILayout.Label(Tools.MuMech_ToSI(body.sphereOfInfluence), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + + GUILayout.Label(body.orbitingBodies.Count.ToString(), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); //show # artificial satellites int num_art_sats = 0; @@ -297,31 +366,87 @@ if (v.mainBody == body && v.situation.ToString() == "ORBITING") num_art_sats++; } - GUILayout.Label(num_art_sats.ToString(), this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); + GUILayout.Label(num_art_sats.ToString(), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); double g_ASL = (VOID_Core.Constant_G * body.Mass) / (body.Radius * body.Radius); - GUILayout.Label(Tools.MuMech_ToSI(g_ASL) + "m/s²", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); + GUILayout.Label(Tools.MuMech_ToSI(g_ASL) + "m/s²", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.atmosphere) { GUILayout.Label("≈ " + Tools.MuMech_ToSI(body.maxAtmosphereAltitude) + "m", - this.core.LabelStyles["right"], + VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); string O2 = "No"; if (body.atmosphereContainsOxygen == true) O2 = "Yes"; - GUILayout.Label(O2, this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); + GUILayout.Label(O2, VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); } else { - GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); - GUILayout.Label("N/A", this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); + GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + GUILayout.Label("N/A", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); } string ocean = "No"; if (body.ocean == true) ocean = "Yes"; - GUILayout.Label(ocean, this.core.LabelStyles["right"], GUILayout.ExpandWidth(true)); + GUILayout.Label(ocean, VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); + } + + private void cbColumnScience(CelestialBody body) + { + /*GUILayout.Label("Surface Science Multiplier:"); + GUILayout.Label("Ocean Science Multiplier:"); + GUILayout.Label("Low-Atmosphere Science Multiplier:"); + GUILayout.Label("High-Atmosphere Science Multiplier:"); + GUILayout.Label("Low Orbit Science Multiplier:"); + GUILayout.Label("High Orbit Science Multiplier:"); + GUILayout.Label("'In Space' Altitude:"); + GUILayout.Label("'Flying' Altitude:"); + GUILayout.Label("Recovery Multiplier:");*/ + + var scienceValues = body.scienceValues; + + GUILayout.Label(scienceValues.LandedDataValue.ToString("0.0#"), + VOID_Styles.labelRight, + GUILayout.ExpandWidth(true)); + + GUILayout.Label( + body.ocean ? scienceValues.SplashedDataValue.ToString("0.0#") : "N/A", + VOID_Styles.labelRight, + GUILayout.ExpandWidth(true)); + + GUILayout.Label( + body.atmosphere ? scienceValues.FlyingLowDataValue.ToString("0.0#") : "N/A", + VOID_Styles.labelRight, + GUILayout.ExpandWidth(true)); + + GUILayout.Label( + body.atmosphere ? scienceValues.FlyingHighDataValue.ToString("0.0#") : "N/A", + VOID_Styles.labelRight, + GUILayout.ExpandWidth(true)); + + GUILayout.Label(scienceValues.InSpaceLowDataValue.ToString("0.0#"), + VOID_Styles.labelRight, + GUILayout.ExpandWidth(true)); + + GUILayout.Label(scienceValues.InSpaceHighDataValue.ToString("0.0#"), + VOID_Styles.labelRight, + GUILayout.ExpandWidth(true)); + + GUILayout.Label( + body.atmosphere ? scienceValues.flyingAltitudeThreshold.ToString("N0") : "N/A", + VOID_Styles.labelRight, + GUILayout.ExpandWidth(true)); + + GUILayout.Label( + scienceValues.spaceAltitudeThreshold.ToString("N0"), + VOID_Styles.labelRight, + GUILayout.ExpandWidth(true)); + + GUILayout.Label(scienceValues.RecoveryValue.ToString("0.0#"), + VOID_Styles.labelRight, + GUILayout.ExpandWidth(true)); } } } --- /dev/null +++ b/VOID_CareerStatus.cs @@ -1,1 +1,241 @@ - +// VOID +// +// VOID_CareerStatus.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +using KSP; +using System; +using System.Text; +using ToadicusTools; +using UnityEngine; + +namespace VOID +{ + public class VOID_CareerStatus : VOID_WindowModule + { + public static VOID_CareerStatus Instance + { + get; + private set; + } + + public static string formatDelta(double delta) + { + if (delta > 0) + { + return string.Format("{0:#,#.##}↑", delta); + } + else if (delta < 0) + { + return string.Format("{0:#,#.##}↓", delta); + } + else + { + return string.Intern("0"); + } + } + + public static string formatDelta(float delta) + { + return formatDelta((double)delta); + } + + private GUIContent fundsContent; + private GUIContent repContent; + private GUIContent scienceContent; + + private Texture2D fundsIconGreen; + private Texture2D fundsIconRed; + private Texture2D reputationIconGreen; + private Texture2D reputationIconRed; + private Texture2D scienceIcon; + + public override bool toggleActive + { + get + { + switch (HighLogic.CurrentGame.Mode) + { + case Game.Modes.CAREER: + case Game.Modes.SCIENCE_SANDBOX: + return base.toggleActive; + default: + return false; + } + } + set + { + switch (HighLogic.CurrentGame.Mode) + { + case Game.Modes.CAREER: + case Game.Modes.SCIENCE_SANDBOX: + base.toggleActive = value; + break; + default: + return; + } + } + } + + public double lastFundsChange + { + get; + private set; + } + + public float lastRepChange + { + get; + private set; + } + + public float lastScienceChange + { + get; + private set; + } + + public double currentFunds + { + get; + private set; + } + + public float currentReputation + { + get; + private set; + } + + public float currentScience + { + get; + private set; + } + + public override void ModuleWindow(int _) + { + GUILayout.BeginVertical(); + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + GUILayout.Label(VOID_Data.fundingStatus.Label); + GUILayout.FlexibleSpace(); + this.fundsContent.text = VOID_Data.fundingStatus.Value; + GUILayout.Label(this.fundsContent, GUILayout.ExpandWidth(false)); + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + GUILayout.Label(VOID_Data.reputationStatus.Label); + GUILayout.FlexibleSpace(); + this.repContent.text = VOID_Data.reputationStatus.Value; + GUILayout.Label(this.repContent, GUILayout.ExpandWidth(false)); + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + GUILayout.Label(VOID_Data.scienceStatus.Label); + GUILayout.FlexibleSpace(); + this.scienceContent.text = VOID_Data.scienceStatus.Value; + GUILayout.Label(this.scienceContent, GUILayout.ExpandWidth(false)); + GUILayout.EndHorizontal(); + + GUILayout.EndVertical(); + + GUI.DragWindow(); + } + + // TODO: Update event handlers to do something useful with the new "reasons" parameter. + private void onFundsChange(double newValue, TransactionReasons reasons) + { + this.lastFundsChange = newValue - this.currentFunds; + this.currentFunds = newValue; + } + + private void onRepChange(float newValue, TransactionReasons reasons) + { + this.lastRepChange = newValue - this.currentReputation; + this.currentReputation = newValue; + } + + private void onScienceChange(float newValue, TransactionReasons reasons) + { + this.lastScienceChange = newValue - this.currentScience; + this.currentScience = newValue; + } + + /* + * MissionRecoveryDialog::fundsIconGreen.name: UiElements_05 + * MissionRecoveryDialog::fundsIconRed.name: UiElements_06 + * MissionRecoveryDialog::reputationIconGreen.name: UiElements_07 + * MissionRecoveryDialog::reputationIconRed.name: UiElements_08 + * MissionRecoveryDialog::scienceIcon.name: UiElements_12 + * */ + public VOID_CareerStatus() : base() + { + VOID_CareerStatus.Instance = this; + + this._Name = "Career Status"; + + GameEvents.OnFundsChanged.Add(this.onFundsChange); + GameEvents.OnReputationChanged.Add(this.onRepChange); + GameEvents.OnScienceChanged.Add(this.onScienceChange); + + bool texturesLoaded; + + texturesLoaded = IOTools.LoadTexture(out this.fundsIconGreen, "VOID/Textures/fundsgreen.png", 10, 18); + texturesLoaded &= IOTools.LoadTexture(out this.fundsIconRed, "VOID/Textures/fundsred.png", 10, 18); + texturesLoaded &= IOTools.LoadTexture(out this.reputationIconGreen, "VOID/Textures/repgreen.png", 16, 18); + texturesLoaded &= IOTools.LoadTexture(out this.reputationIconRed, "VOID/Textures/repred.png", 16, 18); + texturesLoaded &= IOTools.LoadTexture(out this.scienceIcon, "VOID/Textures/science.png", 16, 18); + + this.fundsContent = new GUIContent(); + this.repContent = new GUIContent(); + this.scienceContent = new GUIContent(); + + if (texturesLoaded) + { + this.fundsContent.image = this.fundsIconGreen; + this.repContent.image = this.reputationIconGreen; + this.scienceContent.image = this.scienceIcon; + } + + this.currentFunds = Funding.Instance != null ? Funding.Instance.Funds : double.NaN; + this.currentReputation = Reputation.Instance != null ? Reputation.Instance.reputation : float.NaN; + this.currentScience = ResearchAndDevelopment.Instance != null ? + ResearchAndDevelopment.Instance.Science : float.NaN; + } + + ~VOID_CareerStatus() + { + GameEvents.OnFundsChanged.Remove(this.onFundsChange); + GameEvents.OnReputationChanged.Remove(this.onRepChange); + GameEvents.OnScienceChanged.Remove(this.onScienceChange); + + VOID_CareerStatus.Instance = null; + } + } +} + + --- a/VOID_Core.cs +++ b/VOID_Core.cs @@ -26,11 +26,12 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -using Engineer.VesselSimulator; +using KerbalEngineer.VesselSimulator; using KSP; using System; using System.Collections.Generic; using System.Linq; +using System.Text; using ToadicusTools; using UnityEngine; @@ -70,6 +71,7 @@ public static void Reset() { _instance.StopGUI(); + _instance.Dispose(); _instance = null; _initialized = false; } @@ -118,9 +120,8 @@ protected int _windowID = 0; protected bool GUIStylesLoaded = false; - protected Dictionary _LabelStyles = new Dictionary(); - - protected CelestialBody _Kerbin; + + protected CelestialBody _homeBody; [AVOID_SaveValue("togglePower")] public VOID_SaveValue togglePower = true; @@ -165,7 +166,8 @@ "ExpRecoveryDialogSkin", "KSP window 5", "KSP window 6", - "PartTooltipSkin" + "PartTooltipSkin", + "KSCContextMenuSkin" }; protected bool skinsLoaded = false; @@ -174,6 +176,14 @@ [AVOID_SaveValue("UseBlizzyToolbar")] protected VOID_SaveValue _UseToolbarManager; internal IButton ToolbarButton; + + internal ApplicationLauncherButton AppLauncherButton; + + /* + * Events + * */ + public delegate void VOIDEventHandler(object sender); + public event VOIDEventHandler onApplicationQuit; /* * Properties @@ -225,14 +235,6 @@ } } - public Dictionary LabelStyles - { - get - { - return this._LabelStyles; - } - } - public List allBodies { get @@ -241,19 +243,25 @@ } } - public CelestialBody Kerbin - { - get - { - if (this._Kerbin == null) - { - if (FlightGlobals.Bodies != null) + public List sortedBodyList + { + get; + private set; + } + + public CelestialBody HomeBody + { + get + { + if (this._homeBody == null) + { + if (Planetarium.fetch != null) { - this._Kerbin = FlightGlobals.Bodies.First(b => b.name == "Kerbin"); + this._homeBody = Planetarium.fetch.Home; } } - return this._Kerbin; + return this._homeBody; } } @@ -279,6 +287,18 @@ { return this._updatePeriod; } + } + + public Stage[] Stages + { + get; + protected set; + } + + public Stage LastStage + { + get; + protected set; } protected IconState powerState @@ -333,10 +353,24 @@ } if (value == true) { + if (this.AppLauncherButton != null) + { + ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton); + this.AppLauncherButton = null; + } + this.InitializeToolbarButton(); } _UseToolbarManager.value = value; + } + } + + protected virtual ApplicationLauncher.AppScenes appIconVisibleScenes + { + get + { + return ApplicationLauncher.AppScenes.FLIGHT; } } @@ -362,17 +396,33 @@ if (!this.GUIStylesLoaded) { this.LoadGUIStyles(); + + Tools.PostDebugMessage( + this, + "ToolbarAvailable: {0}, UseToobarManager: {1}", + ToolbarManager.ToolbarAvailable, + this.UseToolbarManager); } if (!this.UseToolbarManager) { - if (GUI.Button(VOIDIconPos, VOIDIconTexture, this.iconStyle) && this.VOIDIconLocked) - { - this.ToggleMainWindow(); + if (this.AppLauncherButton == null) + { + Tools.PostDebugMessage(this, + "UseToolbarManager = false (ToolbarAvailable = {0}) and " + + "AppLauncherButton is null, making AppLauncher button.", + ToolbarManager.ToolbarAvailable + ); + this.InitializeAppLauncherButton(); } } else if (this.ToolbarButton == null) { + Tools.PostDebugMessage(this, + "UseToolbarManager = true (ToolbarAvailable = {0}) and " + + "ToolbarButton is null, making Toolbar button.", + ToolbarManager.ToolbarAvailable + ); this.InitializeToolbarButton(); } @@ -390,7 +440,14 @@ GUILayout.Height(50) ); - _mainWindowPos = Tools.ClampRectToScreen(_mainWindowPos); + if (HighLogic.LoadedSceneIsEditor) + { + _mainWindowPos = Tools.ClampRectToEditorPad(_mainWindowPos); + } + else + { + _mainWindowPos = Tools.ClampRectToScreen(_mainWindowPos); + } if (_mainWindowPos != this.mainWindowPos) { @@ -411,7 +468,14 @@ GUILayout.Height(50) ); - _configWindowPos = Tools.ClampRectToScreen(_configWindowPos); + if (HighLogic.LoadedSceneIsEditor) + { + _configWindowPos = Tools.ClampRectToEditorPad(_configWindowPos); + } + else + { + _configWindowPos = Tools.ClampRectToScreen(_configWindowPos); + } if (_configWindowPos != this.configWindowPos) { @@ -420,7 +484,7 @@ } } - public void OnGUI() + public virtual void OnGUI() { if (Event.current.type == EventType.Repaint) { @@ -474,20 +538,14 @@ } } - public void Update() + public virtual void Update() { this.LoadBeforeUpdate(); if (this.vessel != null && this.vesselSimActive) { - double radius = this.vessel.Radius(); - SimManager.Gravity = this.vessel.mainBody.gravParameter / - (radius * radius); - SimManager.TryStartSimulation(); - } - else if (!this.vesselSimActive) - { - SimManager.ClearResults(); + Tools.PostDebugMessage(this, "Updating SimManager."); + this.UpdateSimManager(); } if (!this.guiRunning) @@ -524,7 +582,7 @@ this._updateTimer += Time.deltaTime; } - public void FixedUpdate() + public virtual void FixedUpdate() { bool newPowerState = this.powerAvailable; @@ -553,11 +611,29 @@ } } - foreach (IVOID_BehaviorModule module in - this._modules.OfType().Where(m => !m.GetType().IsAbstract)) - { - module.FixedUpdate(); - } + foreach (IVOID_Module module in this.Modules) + { + if (module is IVOID_BehaviorModule) + { + ((IVOID_BehaviorModule)module).FixedUpdate(); + } + } + } + + public void OnDestroy() + { + foreach (IVOID_Module module in this.Modules) + { + if (module is IVOID_BehaviorModule) + { + ((IVOID_BehaviorModule)module).OnDestroy(); + } + } + } + + public void OnApplicationQuit() + { + this.onApplicationQuit(this); } public void ResetGUI() @@ -601,7 +677,7 @@ } else { - GUILayout.Label("-- POWER LOST --", this.LabelStyles["red"]); + GUILayout.Label("-- POWER LOST --", VOID_Styles.labelRed); } this.configWindowMinimized.value = !GUILayout.Toggle(!this.configWindowMinimized, "Configuration"); @@ -646,7 +722,6 @@ _content.tooltip = "Select previous skin"; if (GUILayout.Button(_content, GUILayout.ExpandWidth(true))) { - this.GUIStylesLoaded = false; this._skinIdx--; Tools.PostDebugMessage(string.Format( "{0}: new this._skinIdx = {1} :: skin_list.Count = {2}", @@ -658,13 +733,12 @@ _content.text = this.Skin.name; _content.tooltip = "Current skin"; - GUILayout.Label(_content, this.LabelStyles["center"], GUILayout.ExpandWidth(true)); + GUILayout.Label(_content, VOID_Styles.labelCenter, GUILayout.ExpandWidth(true)); _content.text = "►"; _content.tooltip = "Select next skin"; if (GUILayout.Button(_content, GUILayout.ExpandWidth(true))) { - this.GUIStylesLoaded = false; this._skinIdx++; Tools.PostDebugMessage(string.Format( "{0}: new this._skinIdx = {1} :: skin_list.Count = {2}", @@ -683,6 +757,7 @@ if (this._skinName != skinNames[this._skinIdx]) { this._skinName.value = skinNames[this._skinIdx]; + this.GUIStylesLoaded = false; } GUILayout.EndHorizontal(); @@ -694,7 +769,7 @@ this.stringFrequency = (1f / this.updatePeriod).ToString(); } this.stringFrequency = GUILayout.TextField(this.stringFrequency.ToString(), 5, GUILayout.ExpandWidth(true)); - // GUILayout.FlexibleSpace(); + if (GUILayout.Button("Apply")) { double updateFreq = 1f / this.updatePeriod; @@ -711,45 +786,89 @@ this._factoryReset = GUILayout.Toggle(this._factoryReset, "Factory Reset"); } + protected void UpdateSimManager() + { + if (SimManager.ResultsReady()) + { + Tools.PostDebugMessage(this, "VesselSimulator results ready, setting Stages."); + + this.Stages = SimManager.Stages; + + if (this.Stages != null) + { + this.LastStage = this.Stages.Last(); + } + + if (HighLogic.LoadedSceneIsEditor) + { + SimManager.Gravity = VOID_Data.KerbinGee; + } + else + { + double radius = this.vessel.Radius(); + SimManager.Gravity = this.vessel.mainBody.gravParameter / (radius * radius); + } + + SimManager.minSimTime = new TimeSpan(0, 0, 0, 0, (int)(this.updatePeriod * 1000d)); + + SimManager.TryStartSimulation(); + } + #if DEBUG + else + { + Tools.PostDebugMessage(this, "VesselSimulator results not ready."); + } + #endif + } + protected void LoadModulesOfType() { - var types = AssemblyLoader.loadedAssemblies - .Select(a => a.assembly.GetExportedTypes()) - .SelectMany(t => t) - .Where(v => typeof(T).IsAssignableFrom(v) - && !(v.IsInterface || v.IsAbstract) && - !typeof(VOID_Core).IsAssignableFrom(v) - ); - - Tools.PostDebugMessage(string.Format( - "{0}: Found {1} modules to check.", - this.GetType().Name, - types.Count() - )); - foreach (var voidType in types) - { - if (!HighLogic.LoadedSceneIsEditor && - typeof(IVOID_EditorModule).IsAssignableFrom(voidType)) - { - continue; - } - - Tools.PostDebugMessage(string.Format( - "{0}: found Type {1}", - this.GetType().Name, - voidType.Name - )); - - this.LoadModule(voidType); + StringBuilder sb = new StringBuilder("Loading modules..."); + sb.AppendLine(); + + foreach (AssemblyLoader.LoadedAssembly assy in AssemblyLoader.loadedAssemblies) + { + foreach (Type loadedType in assy.assembly.GetExportedTypes()) + { + if ( + loadedType.IsInterface || + loadedType.IsAbstract || + !typeof(T).IsAssignableFrom(loadedType) || + this.GetType().IsAssignableFrom(loadedType) + ) + { + continue; + } + + // HACK: This stops editor modules from loading in flight. It is a dirty hack and should be fixed. + if (!HighLogic.LoadedSceneIsEditor && typeof(IVOID_EditorModule).IsAssignableFrom(loadedType)) + { + continue; + } + + sb.AppendFormat("Loading IVOID_Module type {0}...", loadedType.Name); + + try + { + this.LoadModule(loadedType); + sb.AppendLine("Success."); + } + catch (Exception ex) + { + sb.AppendFormat("Failed, caught {0}", ex.GetType().Name); + sb.AppendLine(); + + #if DEBUG + Debug.LogException(ex); + #endif + } + } } this._modulesLoaded = true; - Tools.PostDebugMessage(string.Format( - "{0}: Loaded {1} modules.", - this.GetType().Name, - this.Modules.Count - )); + sb.AppendFormat("Loaded {0} modules.", this.Modules.Count); + sb.AppendLine(); } protected void LoadModule(Type T) @@ -835,32 +954,7 @@ protected void LoadGUIStyles() { - this.LabelStyles["link"] = new GUIStyle(GUI.skin.label); - this.LabelStyles["link"].fontStyle = FontStyle.Bold; - - this.LabelStyles["center"] = new GUIStyle(GUI.skin.label); - this.LabelStyles["center"].normal.textColor = Color.white; - this.LabelStyles["center"].alignment = TextAnchor.UpperCenter; - - this.LabelStyles["center_bold"] = new GUIStyle(GUI.skin.label); - this.LabelStyles["center_bold"].normal.textColor = Color.white; - this.LabelStyles["center_bold"].alignment = TextAnchor.UpperCenter; - this.LabelStyles["center_bold"].fontStyle = FontStyle.Bold; - - this.LabelStyles["right"] = new GUIStyle(GUI.skin.label); - this.LabelStyles["right"].normal.textColor = Color.white; - this.LabelStyles["right"].alignment = TextAnchor.UpperRight; - - this.LabelStyles["red"] = new GUIStyle(GUI.skin.label); - this.LabelStyles["red"].normal.textColor = Color.red; - this.LabelStyles["red"].alignment = TextAnchor.MiddleCenter; - - this.iconStyle = new GUIStyle(GUI.skin.button); - this.iconStyle.padding = new RectOffset(0, 0, 0, 0); - // this.iconStyle.margin = new RectOffset(0, 0, 0, 0); - // this.iconStyle.contentOffset = new Vector2(0, 0); - this.iconStyle.overflow = new RectOffset(0, 0, 0, 0); - // this.iconStyle.border = new RectOffset(0, 0, 0, 0); + VOID_Styles.OnSkinChanged(); this.GUIStylesLoaded = true; } @@ -877,13 +971,24 @@ { this.LoadVesselTypes(); } + + if (this.sortedBodyList == null && FlightGlobals.Bodies != null && FlightGlobals.Bodies.Count > 0) + { + this.sortedBodyList = new List(FlightGlobals.Bodies); + this.sortedBodyList.Sort(new CBListComparer()); + this.sortedBodyList.Reverse(); + + Debug.Log(string.Format("sortedBodyList: {0}", string.Join("\n\t", this.sortedBodyList.Select(b => b.bodyName).ToArray()))); + } + } protected void InitializeToolbarButton() { - // Do nothing if the Toolbar is not available. + // Do nothing if (the Toolbar is not available. if (!ToolbarManager.ToolbarAvailable) { + Tools.PostDebugMessage(this, "Refusing to make a ToolbarButton: ToolbarAvailable = false"); return; } @@ -891,7 +996,7 @@ this.ToolbarButton.Text = this.VoidName; this.SetIconTexture(this.powerState | this.activeState); - this.ToolbarButton.Visibility = new GameScenesVisibility(GameScenes.EDITOR, GameScenes.FLIGHT, GameScenes.SPH); + this.ToolbarButton.Visibility = new GameScenesVisibility(GameScenes.EDITOR, GameScenes.FLIGHT); this.ToolbarButton.OnClick += (e) => @@ -900,6 +1005,27 @@ }; Tools.PostDebugMessage(string.Format("{0}: Toolbar Button initialized.", this.GetType().Name)); + } + + protected void InitializeAppLauncherButton() + { + if (ApplicationLauncher.Ready) + { + this.AppLauncherButton = ApplicationLauncher.Instance.AddModApplication( + this.ToggleMainWindow, this.ToggleMainWindow, + this.appIconVisibleScenes, + this.VOIDIconTexture + ); + + Tools.PostDebugMessage( + this, + "AppLauncherButton initialized in {0}", + Enum.GetName( + typeof(GameScenes), + HighLogic.LoadedScene + ) + ); + } } protected void ToggleMainWindow() @@ -936,7 +1062,12 @@ this.ToolbarButton.TexturePath = texturePath; } - this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath, false); + this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath.Replace("icon", "appIcon"), false); + + if (this.AppLauncherButton != null) + { + this.AppLauncherButton.SetTexture(VOIDIconTexture); + } } protected void CheckAndSave() @@ -996,7 +1127,7 @@ this.VoidVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.MajorRevision); - this._Active.value = true; + this.toggleActive = true; this._skinName = this.defaultSkin; this._skinIdx = int.MinValue; @@ -1008,11 +1139,25 @@ this.vesselSimActive = true; - this.UseToolbarManager = false; + this.UseToolbarManager = ToolbarManager.ToolbarAvailable; this.LoadConfig(); this.SetIconTexture(this.powerState | this.activeState); + } + + public virtual void Dispose() + { + if (this.AppLauncherButton != null) + { + ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton); + this.AppLauncherButton = null; + } + if (this.ToolbarButton != null) + { + this.ToolbarButton.Destroy(); + this.ToolbarButton = null; + } } protected enum IconState @@ -1023,32 +1168,6 @@ Active = 8 } } - - public static partial class VOID_Data - { - public static VOID_Core core - { - get - { - if (HighLogic.LoadedSceneIsEditor) - { - return VOID_EditorCore.Instance; - } - else - { - return VOID_Core.Instance; - } - } - } - - public static double KerbinGee - { - get - { - return core.Kerbin.gravParameter / (core.Kerbin.Radius * core.Kerbin.Radius); - } - } - } } --- /dev/null +++ b/VOID_Data.cs @@ -1,1 +1,1181 @@ - +// VOID +// +// VOID_Data.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +using KerbalEngineer.VesselSimulator; +using KSP; +using System; +using System.Collections.Generic; +using ToadicusTools; +using UnityEngine; + +namespace VOID +{ + public static class VOID_Data + { + private static Dictionary dataValues = new Dictionary(); + public static Dictionary DataValues + { + get + { + return dataValues; + } + } + + #region Constants + + private static double kerbinGee; + + public static double KerbinGee + { + get + { + if (kerbinGee == default(double)) + { + kerbinGee = core.HomeBody.gravParameter / (core.HomeBody.Radius * core.HomeBody.Radius); + } + + return kerbinGee; + } + } + + #endregion + + #region Core Data + + public static VOID_Core core + { + get + { + if (HighLogic.LoadedSceneIsEditor) + { + return VOID_EditorCore.Instance; + } + else + { + return VOID_Core.Instance; + } + } + } + + #endregion + + #region Atmosphere + + public static readonly VOID_DoubleValue atmDensity = + new VOID_DoubleValue( + "Atmosphere Density", + new Func(() => core.vessel.atmDensity * 1000f), + "g/m³" + ); + + public static readonly VOID_FloatValue atmLimit = + new VOID_FloatValue( + "Atmosphere Limit", + new Func(() => core.vessel.mainBody.maxAtmosphereAltitude), + "m" + ); + + public static readonly VOID_DoubleValue atmPressure = + new VOID_DoubleValue( + "Pressure", + new Func(() => core.vessel.staticPressure), + "atm" + ); + + public static readonly VOID_FloatValue temperature = + new VOID_FloatValue( + "Temperature", + new Func(() => core.vessel.flightIntegrator.getExternalTemperature()), + "°C" + ); + + #endregion + + #region Attitude + + public static readonly VOID_StrValue vesselHeading = + new VOID_StrValue( + "Heading", + delegate() + { + double heading = core.vessel.getSurfaceHeading(); + string cardinal = VOID_Tools.get_heading_text(heading); + + return string.Format( + "{0}° {1}", + heading.ToString("F2"), + cardinal + ); + } + ); + + public static readonly VOID_DoubleValue vesselPitch = + new VOID_DoubleValue( + "Pitch", + () => core.vessel.getSurfacePitch(), + "°" + ); + + #endregion + + #region Career + + public static readonly VOID_StrValue fundingStatus = + new VOID_StrValue( + string.Intern("Funds"), + delegate() + { + if (VOID_CareerStatus.Instance == null) + { + return string.Empty; + } + + return string.Format("{0} ({1})", + VOID_CareerStatus.Instance.currentFunds.ToString("#,#.##"), + VOID_CareerStatus.formatDelta(VOID_CareerStatus.Instance.lastFundsChange) + ); + } + ); + + public static readonly VOID_StrValue reputationStatus = + new VOID_StrValue( + string.Intern("Reputation"), + delegate() + { + if (VOID_CareerStatus.Instance == null) + { + return string.Empty; + } + + return string.Format("{0} ({1})", + VOID_CareerStatus.Instance.currentReputation.ToString("#,#.##"), + VOID_CareerStatus.formatDelta(VOID_CareerStatus.Instance.lastRepChange) + ); + } + ); + + public static readonly VOID_StrValue scienceStatus = + new VOID_StrValue( + string.Intern("Science"), + delegate() + { + if (VOID_CareerStatus.Instance == null) + { + return string.Empty; + } + + return string.Format("{0} ({1})", + VOID_CareerStatus.Instance.currentScience.ToString("#,#.##"), + VOID_CareerStatus.formatDelta(VOID_CareerStatus.Instance.lastScienceChange) + ); + } + ); + + #endregion + + #region Control + + public static readonly VOID_FloatValue mainThrottle = + new VOID_FloatValue( + "Throttle", + new Func(() => core.vessel.ctrlState.mainThrottle * 100f), + "%" + ); + + #endregion + + #region Engineering + + public static readonly VOID_IntValue partCount = + new VOID_IntValue( + "Parts", + new Func(() => core.vessel.Parts.Count), + "" + ); + + #region Mass + + public static readonly VOID_StrValue comboResourceMass = + new VOID_StrValue( + "Resource Mass (curr / total)", + delegate() + { + return string.Format("{0} / {1}", + stageResourceMass.ValueUnitString("F3"), + resourceMass.ValueUnitString("F3") + ); + } + ); + + public static readonly VOID_DoubleValue resourceMass = + new VOID_DoubleValue( + "Resource Mass", + delegate() + { + if (core.Stages == null || core.LastStage == null) + { + return double.NaN; + } + + return core.LastStage.resourceMass; + }, + "tons" + ); + + public static readonly VOID_DoubleValue stageResourceMass = + new VOID_DoubleValue( + "Resource Mass (Stage)", + delegate() + { + if (core.LastStage == null) + { + return double.NaN; + } + + return core.LastStage.resourceMass; + }, + "tons" + ); + + public static readonly VOID_DoubleValue totalMass = + new VOID_DoubleValue( + "Total Mass", + delegate() + { + if (core.Stages == null || core.LastStage == null) + { + return double.NaN; + } + + return core.LastStage.totalMass; + }, + "tons" + ); + + #endregion + + #region DeltaV + + public static readonly VOID_DoubleValue stageDeltaV = + new VOID_DoubleValue( + "DeltaV (Current Stage)", + delegate() + { + if (core.Stages == null || core.LastStage == null) + return double.NaN; + return core.LastStage.deltaV; + }, + "m/s" + ); + + public static readonly VOID_DoubleValue totalDeltaV = + new VOID_DoubleValue( + "DeltaV (Total)", + delegate() + { + if (core.Stages == null || core.LastStage == null) + return double.NaN; + return core.LastStage.totalDeltaV; + }, + "m/s" + ); + + #endregion + + #region Propulsion + + public static readonly VOID_StrValue currmaxThrustWeight = + new VOID_StrValue( + "T:W (curr/max)", + delegate() + { + if (core.Stages == null || core.LastStage == null) + return "N/A"; + + return string.Format( + "{0} / {1}", + (VOID_Data.currThrustWeight.Value).ToString("F2"), + (VOID_Data.maxThrustWeight.Value).ToString("F2") + ); + } + ); + + public static readonly VOID_StrValue currmaxThrust = + new VOID_StrValue( + "Thrust (curr/max)", + delegate() + { + if (core.Stages == null || core.LastStage == null) + return "N/A"; + + double currThrust = core.LastStage.actualThrust; + double maxThrust = core.LastStage.thrust; + + return string.Format( + "{0} / {1}", + currThrust.ToString("F1"), + maxThrust.ToString("F1") + ); + } + ); + + public static readonly VOID_DoubleValue stageMassFlow = + new VOID_DoubleValue( + "Stage Mass Flow", + delegate() + { + if (core.LastStage == null) + { + return double.NaN; + } + + double stageIsp = core.LastStage.isp; + double stageThrust = stageNominalThrust; + + Tools.PostDebugMessage(typeof(VOID_Data), "calculating stageMassFlow from:\n" + + "\tstageIsp: {0}\n" + + "\tstageThrust: {1}\n" + + "\tKerbinGee: {2}\n", + stageIsp, + stageThrust, + KerbinGee + ); + + return stageThrust / (stageIsp * KerbinGee); + }, + "Mg/s" + ); + + public static readonly VOID_DoubleValue stageNominalThrust = + new VOID_DoubleValue( + "Nominal Stage Thrust", + delegate() + { + if (core.LastStage == null) + { + return double.NaN; + } + + if (core.LastStage.actualThrust == 0d) + { + return core.LastStage.thrust; + } + else + { + return core.LastStage.actualThrust; + } + }, + "kN" + ); + + #endregion + + #region Kinetics + + public static readonly VOID_DoubleValue currThrustWeight = + new VOID_DoubleValue( + "T:W Ratio", + delegate() + { + if (core.LastStage == null) + { + return double.NaN; + } + + return core.LastStage.actualThrustToWeight; + }, + "" + ); + + + + public static readonly VOID_DoubleValue maxThrustWeight = + new VOID_DoubleValue( + "T:W Ratio", + delegate() + { + if (core.LastStage == null) + { + return double.NaN; + } + + return core.LastStage.thrustToWeight; + }, + "" + ); + + public static readonly VOID_DoubleValue nominalThrustWeight = + new VOID_DoubleValue( + "Thrust-to-Weight Ratio", + delegate() + { + if (HighLogic.LoadedSceneIsEditor || currThrustWeight.Value == 0d) + { + return maxThrustWeight.Value; + } + + return currThrustWeight.Value; + }, + "" + ); + + public static readonly VOID_DoubleValue surfaceThrustWeight = + new VOID_DoubleValue( + "Max T:W @ surface", + delegate() + { + if (core.Stages == null || core.LastStage == null) + return double.NaN; + + double maxThrust = core.LastStage.thrust; + double mass = core.LastStage.totalMass; + double gravity = (VOID_Core.Constant_G * core.vessel.mainBody.Mass) / + (core.vessel.mainBody.Radius * core.vessel.mainBody.Radius); + double weight = mass * gravity; + + return maxThrust / weight; + }, + "" + ); + + public static readonly VOID_Vector3dValue vesselThrustOffset = + new VOID_Vector3dValue( + "Thrust Offset", + delegate() + { + if (core.vessel == null) + { + return Vector3d.zero; + } + + List engineModules = core.vessel.getModulesOfType(); + + Vector3d thrustPos = Vector3d.zero; + Vector3d thrustDir = Vector3d.zero; + float thrust = 0; + + foreach (PartModule engine in engineModules) + { + float moduleThrust = 0; + + switch (engine.moduleName) + { + case "ModuleEngines": + case "ModuleEnginesFX": + break; + default: + continue; + } + + if (!engine.isEnabled) + { + continue; + } + + CenterOfThrustQuery cotQuery = new CenterOfThrustQuery(); + + if (engine is ModuleEngines) + { + ModuleEngines engineModule = engine as ModuleEngines; + + moduleThrust = engineModule.finalThrust; + + engineModule.OnCenterOfThrustQuery(cotQuery); + } + else // engine is ModuleEnginesFX + { + ModuleEnginesFX engineFXModule = engine as ModuleEnginesFX; + + moduleThrust = engineFXModule.finalThrust; + + engineFXModule.OnCenterOfThrustQuery(cotQuery); + } + + if (moduleThrust != 0d) + { + cotQuery.thrust = moduleThrust; + } + + thrustPos += cotQuery.pos * cotQuery.thrust; + thrustDir += cotQuery.dir * cotQuery.thrust; + thrust += cotQuery.thrust; + } + + if (thrust != 0) + { + thrustPos /= thrust; + thrustDir /= thrust; + } + + Transform vesselTransform = core.vessel.transform; + + thrustPos = vesselTransform.InverseTransformPoint(thrustPos); + thrustDir = vesselTransform.InverseTransformDirection(thrustDir); + + Vector3d thrustOffset = VectorTools.PointDistanceToLine( + thrustPos, thrustDir.normalized, core.vessel.findLocalCenterOfMass()); + + Tools.PostDebugMessage(typeof(VOID_Data), "vesselThrustOffset:\n" + + "\tthrustPos: {0}\n" + + "\tthrustDir: {1}\n" + + "\tthrustOffset: {2}\n" + + "\tvessel.CoM: {3}", + thrustPos, + thrustDir.normalized, + thrustOffset, + core.vessel.findWorldCenterOfMass() + ); + + return thrustOffset; + }, + "m" + ); + + #endregion + + #region Air Breathing + + public static readonly VOID_StrValue intakeAirStatus = + new VOID_StrValue( + "Intake Air (Curr / Req)", + delegate() + { + double currentAmount; + double currentRequirement; + + currentAmount = 0d; + currentRequirement = 0d; + + foreach (Part part in core.vessel.Parts) + { + if (part.enabled) + { + ModuleEngines engineModule; + ModuleEnginesFX enginesFXModule; + List propellantList = null; + + if (part.tryGetFirstModuleOfType(out engineModule)) + { + propellantList = engineModule.propellants; + } + else if (part.tryGetFirstModuleOfType(out enginesFXModule)) + { + propellantList = enginesFXModule.propellants; + } + + if (propellantList != null) + { + foreach (Propellant propellant in propellantList) + { + if (propellant.name == "IntakeAir") + { + currentRequirement += propellant.currentRequirement / TimeWarp.fixedDeltaTime; + break; + } + } + } + } + + ModuleResourceIntake intakeModule; + + if (part.enabled && part.tryGetFirstModuleOfType(out intakeModule)) + { + if (intakeModule.resourceName == "IntakeAir") + { + currentAmount += intakeModule.airFlow; + } + } + } + + if (currentAmount == 0 && currentRequirement == 0) + { + return "N/A"; + } + + return string.Format("{0:F3} / {1:F3}", currentAmount, currentRequirement); + } + ); + + #endregion + + #region Crew + + public static readonly VOID_IntValue vesselCrewCount = + new VOID_IntValue( + "Crew Onboard", + delegate() + { + if (core.vessel != null) + { + return core.vessel.GetCrewCount(); + } + else + { + return 0; + } + }, + "" + ); + + public static readonly VOID_IntValue vesselCrewCapacity = + new VOID_IntValue( + "Crew Capacity", + delegate() + { + if (core.vessel != null) + { + return core.vessel.GetCrewCapacity(); + } + else + { + return 0; + } + }, + "" + ); + + #endregion + + #endregion + + #region Location + + public static readonly VOID_DoubleValue downrangeDistance = + new VOID_DoubleValue( + "Downrange Distance", + delegate() + { + + if (core.vessel == null || + Planetarium.fetch == null || + core.vessel.mainBody != Planetarium.fetch.Home) + { + return double.NaN; + } + + double vesselLongitude = core.vessel.longitude * Math.PI / 180d; + double vesselLatitude = core.vessel.latitude * Math.PI / 180d; + + const double kscLongitude = 285.442323427289 * Math.PI / 180d; + const double kscLatitude = -0.0972112860655246 * Math.PI / 180d; + + double diffLon = vesselLongitude - kscLongitude; + double diffLat = vesselLatitude - kscLatitude; + + double sinHalfDiffLat = Math.Sin(diffLat / 2d); + double sinHalfDiffLon = Math.Sin(diffLon / 2d); + + double cosVesselLon = Math.Cos(vesselLongitude); + double cosKSCLon = Math.Cos(kscLongitude); + + double haversine = + sinHalfDiffLat * sinHalfDiffLat + + cosVesselLon * cosKSCLon * sinHalfDiffLon * sinHalfDiffLon; + + double arc = 2d * Math.Atan2(Math.Sqrt(haversine), Math.Sqrt(1d - haversine)); + + return core.vessel.mainBody.Radius * arc; + }, + "m" + ); + + public static readonly VOID_StrValue surfLatitude = + new VOID_StrValue( + "Latitude", + new Func(() => VOID_Tools.GetLatitudeString(core.vessel)) + ); + + public static readonly VOID_StrValue surfLongitude = + new VOID_StrValue( + "Longitude", + new Func(() => VOID_Tools.GetLongitudeString(core.vessel)) + ); + + public static readonly VOID_DoubleValue trueAltitude = + new VOID_DoubleValue( + "Altitude (true)", + delegate() + { + double alt_true = core.vessel.orbit.altitude - core.vessel.terrainAltitude; + // HACK: This assumes that on worlds with oceans, all water is fixed at 0 m, + // and water covers the whole surface at 0 m. + if (core.vessel.terrainAltitude < 0 && core.vessel.mainBody.ocean) + alt_true = core.vessel.orbit.altitude; + return alt_true; + }, + "m" + ); + + #endregion + + #region Kinematics + + public static readonly VOID_DoubleValue geeForce = + new VOID_DoubleValue( + "G-force", + new Func(() => core.vessel.geeForce), + "gees" + ); + + public static readonly VOID_DoubleValue horzVelocity = + new VOID_DoubleValue( + "Horizontal speed", + new Func(() => core.vessel.horizontalSrfSpeed), + "m/s" + ); + + public static readonly VOID_DoubleValue surfVelocity = + new VOID_DoubleValue( + "Surface velocity", + new Func(() => core.vessel.srf_velocity.magnitude), + "m/s" + ); + + public static readonly VOID_DoubleValue vertVelocity = + new VOID_DoubleValue( + "Vertical speed", + new Func(() => core.vessel.verticalSpeed), + "m/s" + ); + + public static readonly VOID_DoubleValue vesselAccel = + new VOID_DoubleValue( + "Acceleration", + () => geeForce * KerbinGee, + "m/s²" + ); + + public static readonly VOID_DoubleValue vesselAngularVelocity = + new VOID_DoubleValue( + "Angular Velocity", + delegate() + { + if (core.vessel != null) + { + return core.vessel.angularVelocity.magnitude; + } + else + { + return double.NaN; + } + }, + "rad/s" + ); + + #endregion + + #region Navigation + + public static int upcomingManeuverNodes + { + get + { + if (core.vessel == null || + core.vessel.patchedConicSolver == null || + core.vessel.patchedConicSolver.maneuverNodes == null) + { + return 0; + } + + return core.vessel.patchedConicSolver.maneuverNodes.Count; + } + } + + public static readonly VOID_StrValue burnTimeDoneAtNode = + new VOID_StrValue( + "Full burn time to be half done at node", + delegate() + { + if (core.LastStage == null && upcomingManeuverNodes < 1) + { + return "N/A"; + } + + ManeuverNode node = core.vessel.patchedConicSolver.maneuverNodes[0]; + + if ((node.UT - Planetarium.GetUniversalTime()) < 0) + { + return string.Empty; + } + + double interval = (node.UT - currentNodeBurnDuration) - Planetarium.GetUniversalTime(); + + if (double.IsNaN(interval)) + { + return string.Intern("NaN"); + } + + int sign = Math.Sign(interval); + interval = Math.Abs(interval); + + string format; + + if (sign >= 0) + { + format = string.Intern("T - {0}"); + } + else + { + format = string.Intern("T + {0}"); + } + + return string.Format(format, VOID_Tools.FormatInterval(interval)); + } + ); + + public static readonly VOID_StrValue burnTimeHalfDoneAtNode = + new VOID_StrValue( + "Full burn time to be half done at node", + delegate() + { + if (core.LastStage == null && upcomingManeuverNodes < 1) + { + return "N/A"; + } + + ManeuverNode node = core.vessel.patchedConicSolver.maneuverNodes[0]; + + if ((node.UT - Planetarium.GetUniversalTime()) < 0) + { + return string.Empty; + } + + double interval = (node.UT - currentNodeHalfBurnDuration) - Planetarium.GetUniversalTime(); + + if (double.IsNaN(interval)) + { + return string.Intern("NaN"); + } + + int sign = Math.Sign(interval); + interval = Math.Abs(interval); + + string format; + + if (sign >= 0) + { + format = string.Intern("T - {0}"); + } + else + { + format = string.Intern("T + {0}"); + } + + return string.Format(format, VOID_Tools.FormatInterval(interval)); + } + ); + + public static readonly VOID_DoubleValue currManeuverDeltaV = + new VOID_DoubleValue( + "Current Maneuver Delta-V", + delegate() + { + if (upcomingManeuverNodes > 0) + { + return core.vessel.patchedConicSolver.maneuverNodes[0].DeltaV.magnitude; + } + else + { + return double.NaN; + } + }, + "m/s" + ); + + public static readonly VOID_DoubleValue currManeuverDVRemaining = + new VOID_DoubleValue( + "Remaining Maneuver Delta-V", + delegate() + { + if (upcomingManeuverNodes > 0) + { + return core.vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(core.vessel.orbit).magnitude; + } + else + { + return double.NaN; + } + }, + "m/s" + ); + + public static readonly VOID_DoubleValue currentNodeBurnDuration = + new VOID_DoubleValue( + "Total Burn Time", + delegate() + { + if (core.LastStage == null || currManeuverDeltaV.Value == double.NaN) + { + return double.NaN; + } + + double stageThrust = stageNominalThrust; + + return burnTime(currManeuverDeltaV.Value, totalMass, stageMassFlow, stageThrust); + }, + "s" + ); + + public static readonly VOID_DoubleValue currentNodeBurnRemaining = + new VOID_DoubleValue( + "Burn Time Remaining", + delegate() + { + if (core.LastStage == null || currManeuverDVRemaining == double.NaN) + { + return double.NaN; + } + + double stageThrust = stageNominalThrust; + + return burnTime(currManeuverDVRemaining, totalMass, stageMassFlow, stageThrust); + }, + "s" + ); + + public static readonly VOID_DoubleValue currentNodeHalfBurnDuration = + new VOID_DoubleValue( + "Half Burn Time", + delegate() + { + if (core.LastStage == null || currManeuverDeltaV.Value == double.NaN) + { + return double.NaN; + } + + double stageThrust = stageNominalThrust; + + return burnTime(currManeuverDeltaV.Value / 2d, totalMass, stageMassFlow, stageThrust); + }, + "s" + ); + + public static readonly VOID_DoubleValue nextManeuverDeltaV = + new VOID_DoubleValue( + "Current Maneuver Delta-V", + delegate() + { + if (upcomingManeuverNodes > 1) + { + return core.vessel.patchedConicSolver.maneuverNodes[1].DeltaV.magnitude; + } + else + { + return double.NaN; + } + }, + "m/s" + ); + + #endregion + + #region Orbits + + public static readonly VOID_StrValue primaryName = + new VOID_StrValue( + VOID_Localization.void_primary, + delegate() + { + if (core.vessel == null) + { + return string.Empty; + } + return core.vessel.mainBody.name; + } + ); + + public static readonly VOID_DoubleValue orbitAltitude = + new VOID_DoubleValue( + "Altitude (ASL)", + new Func(() => core.vessel.orbit.altitude), + "m" + ); + + public static readonly VOID_DoubleValue orbitVelocity = + new VOID_DoubleValue( + VOID_Localization.void_velocity, + new Func(() => core.vessel.orbit.vel.magnitude), + "m/s" + ); + + public static readonly VOID_DoubleValue orbitApoAlt = + new VOID_DoubleValue( + VOID_Localization.void_apoapsis, + new Func(() => core.vessel.orbit.ApA), + "m" + ); + + public static readonly VOID_DoubleValue oribtPeriAlt = + new VOID_DoubleValue( + VOID_Localization.void_periapsis, + new Func(() => core.vessel.orbit.PeA), + "m" + ); + + public static readonly VOID_StrValue timeToApo = + new VOID_StrValue( + "Time to Apoapsis", + new Func(() => VOID_Tools.FormatInterval(core.vessel.orbit.timeToAp)) + ); + + public static readonly VOID_StrValue timeToPeri = + new VOID_StrValue( + "Time to Periapsis", + new Func(() => VOID_Tools.FormatInterval(core.vessel.orbit.timeToPe)) + ); + + public static readonly VOID_DoubleValue orbitInclination = + new VOID_DoubleValue( + "Inclination", + new Func(() => core.vessel.orbit.inclination), + "°" + ); + + public static readonly VOID_DoubleValue gravityAccel = + new VOID_DoubleValue( + "Gravity", + delegate() + { + double orbitRadius = core.vessel.mainBody.Radius + + core.vessel.mainBody.GetAltitude(core.vessel.findWorldCenterOfMass()); + return (VOID_Core.Constant_G * core.vessel.mainBody.Mass) / + (orbitRadius * orbitRadius); + }, + "m/s²" + ); + + public static readonly VOID_StrValue orbitPeriod = + new VOID_StrValue( + "Period", + new Func(() => VOID_Tools.FormatInterval(core.vessel.orbit.period)) + ); + + public static readonly VOID_DoubleValue semiMajorAxis = + new VOID_DoubleValue( + "Semi-Major Axis", + new Func(() => core.vessel.orbit.semiMajorAxis), + "m" + ); + + public static readonly VOID_DoubleValue eccentricity = + new VOID_DoubleValue( + "Eccentricity", + new Func(() => core.vessel.orbit.eccentricity), + "" + ); + + public static readonly VOID_DoubleValue meanAnomaly = + new VOID_DoubleValue( + "Mean Anomaly", + new Func(() => core.vessel.orbit.meanAnomaly * 180d / Math.PI), + "°" + ); + + public static readonly VOID_DoubleValue trueAnomaly = + new VOID_DoubleValue( + "True Anomaly", + new Func(() => core.vessel.orbit.trueAnomaly), + "°" + ); + + public static readonly VOID_DoubleValue eccAnomaly = + new VOID_DoubleValue( + "Eccentric Anomaly", + new Func(() => core.vessel.orbit.eccentricAnomaly * 180d / Math.PI), + "°" + ); + + public static readonly VOID_DoubleValue longitudeAscNode = + new VOID_DoubleValue( + "Long. Ascending Node", + new Func(() => core.vessel.orbit.LAN), + "°" + ); + + public static readonly VOID_DoubleValue argumentPeriapsis = + new VOID_DoubleValue( + "Argument of Periapsis", + new Func(() => core.vessel.orbit.argumentOfPeriapsis), + "°" + ); + + public static readonly VOID_DoubleValue localSiderealLongitude = + new VOID_DoubleValue( + "Local Sidereal Longitude", + new Func(() => VOID_Tools.FixDegreeDomain( + core.vessel.longitude + core.vessel.orbit.referenceBody.rotationAngle)), + "°" + ); + + #endregion + + #region Science + + public static readonly VOID_StrValue expSituation = + new VOID_StrValue( + "Situation", + new Func(() => core.vessel.GetExperimentSituation().HumanString()) + ); + + public static readonly VOID_StrValue currBiome = + new VOID_StrValue( + "Biome", + new Func(() => VOID_Tools.GetBiome(core.vessel).name) + ); + + #endregion + + #region Surface + + public static readonly VOID_DoubleValue terrainElevation = + new VOID_DoubleValue( + "Terrain elevation", + new Func(() => core.vessel.terrainAltitude), + "m" + ); + + #endregion + + private static double burnTime(double deltaV, double initialMass, double massFlow, double thrust) + { + Tools.PostDebugMessage(typeof(VOID_Data), "calculating burnTime from:\n" + + "\tdeltaV: {0}\n" + + "\tinitialMass: {1}\n" + + "\tmassFlow: {2}\n" + + "\tthrust: {3}\n", + deltaV, + initialMass, + massFlow, + thrust + ); + return initialMass / massFlow * (1d - Math.Exp(-deltaV * massFlow / thrust)); + } + } +} + + --- a/VOID_DataLogger.cs +++ b/VOID_DataLogger.cs @@ -29,6 +29,8 @@ using KSP; using System; using System.Collections.Generic; +using System.IO; +using System.Text; using ToadicusTools; using UnityEngine; @@ -39,208 +41,455 @@ /* * Fields * */ - protected bool stopwatch1_running; - - protected bool csv_logging; - protected bool first_write; - - protected double stopwatch1; - - protected string csv_log_interval_str; - - protected float csv_log_interval; - - protected double csvWriteTimer; - protected double csvCollectTimer; - - protected List csvList = new List(); + #region Fields + + protected bool _loggingActive; + protected bool firstWrite; + + [AVOID_SaveValue("logInterval")] + protected VOID_SaveValue logInterval; + protected string logIntervalStr; + + protected float csvCollectTimer; + + protected List csvBytes; + + protected string _fileName; + protected FileStream _outputFile; + + protected uint outstandingWrites; + + protected System.Text.UTF8Encoding _utf8Encoding; + + #endregion /* * Properties * */ + #region Properties + + // TODO: Add configurable or incremental file names. + protected bool loggingActive + { + get + { + return this._loggingActive; + } + set + { + if (value != this._loggingActive) + { + if (value) + { + this.csvCollectTimer = 0f; + } + else + { + this.CloseFileIfOpen(); + } + + this._loggingActive = value; + } + } + } + + protected string fileName + { + get + { + if (this._fileName == null || this._fileName == string.Empty) + { + this._fileName = KSP.IO.IOUtils.GetFilePathFor( + typeof(VOID_Core), + string.Format( + "{0}_{1}", + this.vessel.vesselName, + "data.csv" + ), + null + ); + } + + return this._fileName; + } + } + + protected FileStream outputFile + { + get + { + if (this._outputFile == null) + { + Tools.DebugLogger logger = Tools.DebugLogger.New(this); + logger.AppendFormat("Initializing output file '{0}' with mode ", this.fileName); + + if (File.Exists(this.fileName)) + { + logger.Append("append"); + this._outputFile = new FileStream( + this.fileName, + FileMode.Append, + FileAccess.Write, + FileShare.Read, + 512, + true + ); + } + else + { + logger.Append("create"); + this._outputFile = new FileStream( + this.fileName, + FileMode.Create, + FileAccess.Write, + FileShare.Read, + 512, + true + ); + + byte[] byteOrderMark = utf8Encoding.GetPreamble(); + + logger.Append(" and writing preamble"); + this._outputFile.Write(byteOrderMark, 0, byteOrderMark.Length); + } + + logger.Append('.'); + + logger.AppendFormat(" File is {0}opened asynchronously.", this._outputFile.IsAsync ? "" : "not "); + + logger.Print(); + } + + return this._outputFile; + } + } + + public UTF8Encoding utf8Encoding + { + get + { + if (this._utf8Encoding == null) + { + this._utf8Encoding = new UTF8Encoding(true); + } + + return this._utf8Encoding; + } + } + + #endregion /* * Methods * */ - public VOID_DataLogger() - { - this._Name = "CSV Data Logger"; - - this.stopwatch1_running = false; - - this.csv_logging = false; - this.first_write = true; - - this.stopwatch1 = 0; - this.csv_log_interval_str = "0.5"; - - this.csvWriteTimer = 0; - this.csvCollectTimer = 0; - - this.WindowPos.x = Screen.width - 520; - this.WindowPos.y = 85; - } - - public override void ModuleWindow(int _) - { - GUIStyle txt_white = new GUIStyle(GUI.skin.label); - txt_white.normal.textColor = txt_white.focused.textColor = Color.white; - txt_white.alignment = TextAnchor.UpperRight; - GUIStyle txt_green = new GUIStyle(GUI.skin.label); - txt_green.normal.textColor = txt_green.focused.textColor = Color.green; - txt_green.alignment = TextAnchor.UpperRight; - GUIStyle txt_yellow = new GUIStyle(GUI.skin.label); - txt_yellow.normal.textColor = txt_yellow.focused.textColor = Color.yellow; - txt_yellow.alignment = TextAnchor.UpperRight; - - GUILayout.BeginVertical(); - - GUILayout.Label("System time: " + DateTime.Now.ToString("HH:mm:ss")); - GUILayout.Label(VOID_Tools.ConvertInterval(stopwatch1)); - - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - if (GUILayout.Button("Start")) - { - if (stopwatch1_running == false) stopwatch1_running = true; - } - if (GUILayout.Button("Stop")) - { - if (stopwatch1_running == true) stopwatch1_running = false; - } - if (GUILayout.Button("Reset")) - { - if (stopwatch1_running == true) stopwatch1_running = false; - stopwatch1 = 0; - } - GUILayout.EndHorizontal(); - - GUIStyle label_style = txt_white; - string log_label = "Inactive"; - if (csv_logging && vessel.situation.ToString() == "PRELAUNCH") - { - log_label = "Awaiting launch"; - label_style = txt_yellow; - } - if (csv_logging && vessel.situation.ToString() != "PRELAUNCH") - { - log_label = "Active"; - label_style = txt_green; - } - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - csv_logging = GUILayout.Toggle(csv_logging, "Data logging: ", GUILayout.ExpandWidth(false)); - GUILayout.Label(log_label, label_style, GUILayout.ExpandWidth(true)); - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - GUILayout.Label("Interval: ", GUILayout.ExpandWidth(false)); - csv_log_interval_str = GUILayout.TextField(csv_log_interval_str, GUILayout.ExpandWidth(true)); - GUILayout.Label("s", GUILayout.ExpandWidth(false)); - GUILayout.EndHorizontal(); - - float new_log_interval; - if (Single.TryParse(csv_log_interval_str, out new_log_interval)) csv_log_interval = new_log_interval; - - GUILayout.EndVertical(); - GUI.DragWindow(); - } - + #region Monobehaviour Lifecycle public void Update() { + if (this.csvBytes != null && this.csvBytes.Count > 0) + { + // csvList is not empty, write it + this.AsyncWriteData(); + } + // CSV Logging // from ISA MapSat - if (csv_logging) + if (loggingActive) { //data logging is on //increment timers - csvWriteTimer += Time.deltaTime; - csvCollectTimer += Time.deltaTime; - - if (csvCollectTimer >= csv_log_interval && vessel.situation != Vessel.Situations.PRELAUNCH) + this.csvCollectTimer += Time.deltaTime; + + if (this.csvCollectTimer >= this.logInterval) { //data logging is on, vessel is not prelaunch, and interval has passed //write a line to the list - line_to_csvList(); //write to the csv + this.CollectLogData(); } - - if (csvList.Count != 0 && csvWriteTimer >= 15f) - { - // csvList is not empty and interval between writings to file has elapsed - //write it - string[] csvData; - csvData = (string[])csvList.ToArray(); - Innsewerants_writeData(csvData); - csvList.Clear(); - csvWriteTimer = 0f; - } - } - else - { - //data logging is off - //reset any timers and clear anything from csvList - csvWriteTimer = 0f; - csvCollectTimer = 0f; - if (csvList.Count > 0) csvList.Clear(); - } - - if (stopwatch1_running) - { - stopwatch1 += Time.deltaTime; } } public void FixedUpdate() {} - private void Innsewerants_writeData(string[] csvArray) - { - var efile = KSP.IO.File.AppendText(vessel.vesselName + "_data.csv", null); - foreach (string line in csvArray) - { - efile.Write(line); - } - efile.Close(); - } - - private void line_to_csvList() - { + public void OnDestroy() + { + Tools.DebugLogger logger = Tools.DebugLogger.New(this); + + logger.Append("Destroying..."); + + this.CloseFileIfOpen(); + + logger.Append(" Done."); + logger.Print(false); + } + + #endregion + + #region VOID_Module Overrides + + public override void LoadConfig() + { + base.LoadConfig(); + + this.logIntervalStr = this.logInterval.value.ToString("#.0##"); + } + + public override void ModuleWindow(int _) + { + GUILayout.BeginVertical(); + + GUILayout.Label( + string.Format("System time: {0}", DateTime.Now.ToString("HH:mm:ss")), + GUILayout.ExpandWidth(true) + ); + GUILayout.Label( + string.Format("Kerbin time: {0}", VOID_Tools.FormatDate(Planetarium.GetUniversalTime())), + GUILayout.ExpandWidth(true) + ); + + GUIStyle activeLabelStyle = VOID_Styles.labelRed; + string activeLabelText = "Inactive"; + if (loggingActive) + { + activeLabelText = "Active"; + activeLabelStyle = VOID_Styles.labelGreen; + } + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + + this.loggingActive = GUILayout.Toggle(loggingActive, "Data logging: ", GUILayout.ExpandWidth(false)); + GUILayout.Label(activeLabelText, activeLabelStyle, GUILayout.ExpandWidth(true)); + + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + + GUILayout.Label("Interval: ", GUILayout.ExpandWidth(false)); + + logIntervalStr = GUILayout.TextField(logIntervalStr, GUILayout.ExpandWidth(true)); + GUILayout.Label("s", GUILayout.ExpandWidth(false)); + + GUILayout.EndHorizontal(); + + float newLogInterval; + if (float.TryParse(logIntervalStr, out newLogInterval)) + { + logInterval.value = newLogInterval; + this.logIntervalStr = this.logInterval.value.ToString("#.0##"); + } + + GUILayout.EndVertical(); + + GUI.DragWindow(); + } + + #endregion + + #region Data Collection + + private void CollectLogData() + { + if (this.csvBytes == null) + { + this.csvBytes = new List(); + } + //called if logging is on and interval has passed //writes one line to the csvList - string line = ""; - if (first_write && !KSP.IO.File.Exists(vessel.vesselName + "_data.csv", null)) - { - first_write = false; - line += "Mission Elapsed Time (s);Altitude ASL (m);Altitude above terrain (m);Orbital Velocity (m/s);Surface Velocity (m/s);Vertical Speed (m/s);Horizontal Speed (m/s);Gee Force (gees);Temperature (°C);Gravity (m/s²);Atmosphere Density (g/m³);\n"; - } + StringBuilder line = new StringBuilder(); + + if (firstWrite) + { + firstWrite = false; + line.Append( + "\"Kerbin Universal Time (s)\"," + + "\"Mission Elapsed Time (s)\t\"," + + "\"Altitude ASL (m)\"," + + "\"Altitude above terrain (m)\"," + + "\"Surface Latitude (°)\"," + + "\"Surface Longitude (°)\"," + + "\"Orbital Velocity (m/s)\"," + + "\"Surface Velocity (m/s)\"," + + "\"Vertical Speed (m/s)\"," + + "\"Horizontal Speed (m/s)\"," + + "\"Gee Force (gees)\"," + + "\"Temperature (°C)\"," + + "\"Gravity (m/s²)\"," + + "\"Atmosphere Density (g/m³)\"," + + "\"Downrange Distance (m)\"," + + "\n" + ); + } + + // Universal time + line.Append(Planetarium.GetUniversalTime().ToString("F2")); + line.Append(','); + //Mission time - line += vessel.missionTime.ToString("F3") + ";"; + line.Append(vessel.missionTime.ToString("F3")); + line.Append(','); + //Altitude ASL - line += vessel.orbit.altitude.ToString("F3") + ";"; + line.Append(VOID_Data.orbitAltitude.Value.ToString("F3")); + line.Append(','); + //Altitude (true) - double alt_true = vessel.orbit.altitude - vessel.terrainAltitude; - if (vessel.terrainAltitude < 0) alt_true = vessel.orbit.altitude; - line += alt_true.ToString("F3") + ";"; + line.Append(VOID_Data.trueAltitude.Value.ToString("F3")); + line.Append(','); + + // Surface Latitude + line.Append('"'); + line.Append(VOID_Data.surfLatitude.Value); + line.Append('"'); + line.Append(','); + + // Surface Longitude + line.Append('"'); + line.Append(VOID_Data.surfLongitude.Value); + line.Append('"'); + line.Append(','); + //Orbital velocity - line += vessel.orbit.vel.magnitude.ToString("F3") + ";"; + line.Append(VOID_Data.orbitVelocity.Value.ToString("F3")); + line.Append(','); + //surface velocity - line += vessel.srf_velocity.magnitude.ToString("F3") + ";"; + line.Append(VOID_Data.surfVelocity.Value.ToString("F3")); + line.Append(','); + //vertical speed - line += vessel.verticalSpeed.ToString("F3") + ";"; + line.Append(VOID_Data.vertVelocity.Value.ToString("F3")); + line.Append(','); + //horizontal speed - line += vessel.horizontalSrfSpeed.ToString("F3") + ";"; + line.Append(VOID_Data.horzVelocity.Value.ToString("F3")); + line.Append(','); + //gee force - line += vessel.geeForce.ToString("F3") + ";"; + line.Append(VOID_Data.geeForce.Value.ToString("F3")); + line.Append(','); + //temperature - line += vessel.flightIntegrator.getExternalTemperature().ToString("F2") + ";"; + line.Append(VOID_Data.temperature.Value.ToString("F2")); + line.Append(','); + //gravity - double r_vessel = vessel.mainBody.Radius + vessel.mainBody.GetAltitude(vessel.findWorldCenterOfMass()); - double g_vessel = (VOID_Core.Constant_G * vessel.mainBody.Mass) / (r_vessel * r_vessel); - line += g_vessel.ToString("F3") + ";"; + line.Append(VOID_Data.gravityAccel.Value.ToString("F3")); + line.Append(','); + //atm density - line += (vessel.atmDensity * 1000).ToString("F3") + ";"; - line += "\n"; - if (csvList.Contains(line) == false) csvList.Add(line); - csvCollectTimer = 0f; - } + line.Append(VOID_Data.atmDensity.Value.ToString("G3")); + line.Append(','); + + // Downrange Distance + line.Append((VOID_Data.downrangeDistance.Value.ToString("G3"))); + + line.Append('\n'); + + csvBytes.AddRange(this.utf8Encoding.GetBytes(line.ToString())); + + this.csvCollectTimer = 0f; + } + + #endregion + + #region File IO Methods + + protected void AsyncWriteCallback(IAsyncResult result) + { + Tools.PostDebugMessage(this, "Got async callback, IsCompleted = {0}", result.IsCompleted); + + this.outputFile.EndWrite(result); + this.outstandingWrites--; + } + + private void AsyncWriteData() + { + WriteState state = new WriteState(); + + state.bytes = this.csvBytes.ToArray(); + state.stream = this.outputFile; + + this.outstandingWrites++; + var writeCallback = new AsyncCallback(this.AsyncWriteCallback); + + this.outputFile.BeginWrite(state.bytes, 0, state.bytes.Length, writeCallback, state); + + this.csvBytes.Clear(); + } + + private void CloseFileIfOpen() + { + Tools.DebugLogger logger = Tools.DebugLogger.New(this); + + logger.AppendFormat("Cleaning up file {0}...", this.fileName); + + if (this.csvBytes != null && this.csvBytes.Count > 0) + { + logger.Append(" Writing remaining data..."); + this.AsyncWriteData(); + } + + logger.Append(" Waiting for writes to finish."); + while (this.outstandingWrites > 0) + { + logger.Append('.'); + System.Threading.Thread.Sleep(10); + } + + if (this._outputFile != null) + { + this._outputFile.Close(); + this._outputFile = null; + logger.Append(" File closed."); + } + + logger.Print(false); + } + + #endregion + + #region Constructors & Destructors + + public VOID_DataLogger() + { + this._Name = "CSV Data Logger"; + + this.loggingActive = false; + this.firstWrite = true; + + this.logInterval = 0.5f; + this.csvCollectTimer = 0f; + + this.outstandingWrites = 0; + + this.WindowPos.x = Screen.width - 520f; + this.WindowPos.y = 85f; + + this.core.onApplicationQuit += delegate(object sender) + { + this.CloseFileIfOpen(); + }; + } + + ~VOID_DataLogger() + { + this.OnDestroy(); + } + + #endregion + + #region Subclasses + + private class WriteState + { + public byte[] bytes; + public FileStream stream; + } + + #endregion } } + + --- a/VOID_DataValue.cs +++ b/VOID_DataValue.cs @@ -34,6 +34,10 @@ { public interface IVOID_DataValue { + string Label { get; } + string Units { get; } + object Value { get; } + void Refresh(); string ValueUnitString(); void DoGUIHorizontal(); @@ -64,6 +68,14 @@ * */ public string Label { get; protected set; } public string Units { get; protected set; } + + object IVOID_DataValue.Value + { + get + { + return (object)this.Value; + } + } public T Value { @@ -90,6 +102,8 @@ this.Units = Units; this.ValueFunc = ValueFunc; this.lastUpdate = 0; + + VOID_Data.DataValues[this.GetHashCode()] = this; } public void Refresh() @@ -115,6 +129,21 @@ GUILayout.FlexibleSpace (); GUILayout.Label (this.ValueUnitString(), GUILayout.ExpandWidth (false)); GUILayout.EndHorizontal (); + } + + public override int GetHashCode() + { + int hash; + unchecked + { + hash = 79999; + + hash = hash * 104399 + this.Label.GetHashCode(); + hash = hash * 104399 + this.ValueFunc.GetHashCode(); + hash = hash * 104399 + this.Units.GetHashCode(); + } + + return hash; } public override string ToString() --- a/VOID_EditorCore.cs +++ b/VOID_EditorCore.cs @@ -26,7 +26,7 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -using Engineer.VesselSimulator; +using KerbalEngineer.VesselSimulator; using KSP; using System; using System.Collections.Generic; @@ -69,8 +69,17 @@ if (_initialized) { _instance.StopGUI(); + _instance.Dispose(); _instance = null; _initialized = false; + } + } + + protected override ApplicationLauncher.AppScenes appIconVisibleScenes + { + get + { + return ApplicationLauncher.AppScenes.VAB | ApplicationLauncher.AppScenes.SPH; } } @@ -79,7 +88,7 @@ this._Name = "VOID Editor Core"; } - public new void OnGUI() {} + public override void OnGUI() {} public override void DrawGUI() { @@ -90,7 +99,7 @@ Rect _iconPos = Tools.DockToWindow (this.VOIDIconPos, this.mainWindowPos); - _iconPos = Tools.ClampRectToScreen (_iconPos, (int)_iconPos.width, (int)_iconPos.height); + _iconPos = Tools.ClampRectToEditorPad (_iconPos); if (_iconPos != this.VOIDIconPos) { @@ -100,11 +109,13 @@ base.DrawGUI(); } - public new void Update() + public override void Update() { + this.LoadBeforeUpdate(); + foreach (IVOID_EditorModule module in this.Modules) { - if (EditorLogic.startPod == null) + if (EditorLogic.RootPart == null) { module.StopGUI(); continue; @@ -119,7 +130,7 @@ } } - if (EditorLogic.startPod == null || !HighLogic.LoadedSceneIsEditor) + if (EditorLogic.RootPart == null || !HighLogic.LoadedSceneIsEditor) { this.StopGUI(); return; @@ -131,18 +142,14 @@ if (EditorLogic.SortedShipList.Count > 0 && this.vesselSimActive) { - SimManager.Gravity = VOID_Data.KerbinGee; - SimManager.TryStartSimulation(); - } - else if (!this.vesselSimActive) - { - SimManager.ClearResults(); + Tools.PostDebugMessage(this, "Updating SimManager."); + this.UpdateSimManager(); } this.CheckAndSave (); } - public new void FixedUpdate() {} + public override void FixedUpdate() {} } } --- a/VOID_EditorHUD.cs +++ b/VOID_EditorHUD.cs @@ -26,7 +26,7 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -using Engineer.VesselSimulator; +using KerbalEngineer.VesselSimulator; using KSP; using System; using System.Collections.Generic; @@ -37,41 +37,20 @@ namespace VOID { - public class VOID_EditorHUD : VOID_Module, IVOID_EditorModule + public class VOID_EditorHUD : VOID_HUDModule, IVOID_EditorModule { /* * Fields * */ - [AVOID_SaveValue("colorIndex")] - protected VOID_SaveValue _colorIndex = 0; - - protected List textColors = new List(); - - protected GUIStyle labelStyle; - + protected HUDWindow ehudWindow; protected EditorVesselOverlays _vesselOverlays; + + [AVOID_SaveValue("snapToLeft")] + protected VOID_SaveValue snapToLeft; /* * Properties * */ - public int ColorIndex - { - get - { - return this._colorIndex; - } - set - { - if (this._colorIndex >= this.textColors.Count - 1) - { - this._colorIndex = 0; - return; - } - - this._colorIndex = value; - } - } - protected EditorVesselOverlays vesselOverlays { get @@ -120,60 +99,33 @@ { this._Name = "Heads-Up Display"; - this._Active.value = true; - - this.textColors.Add(Color.green); - this.textColors.Add(Color.black); - this.textColors.Add(Color.white); - this.textColors.Add(Color.red); - this.textColors.Add(Color.blue); - this.textColors.Add(Color.yellow); - this.textColors.Add(Color.gray); - this.textColors.Add(Color.cyan); - this.textColors.Add(Color.magenta); - - this.labelStyle = new GUIStyle (); - // this.labelStyle.alignment = TextAnchor.UpperRight; - this.labelStyle.normal.textColor = this.textColors [this.ColorIndex]; + this.toggleActive = true; + + this.snapToLeft.value = true; + + this.ehudWindow = new HUDWindow( + "editorHUD", + this.ehudWindowFunc, + new Rect(EditorPanels.Instance.partsPanelWidth + 10f, 125f, 300f, 64f) + ); + this.Windows.Add(this.ehudWindow); Tools.PostDebugMessage (this.GetType().Name + ": Constructed."); } - public override void DrawGUI() - { - SimManager.RequestSimulation(); - - if (SimManager.LastStage == null) + public void ehudWindowFunc(int id) + { + StringBuilder hudString = new StringBuilder(); + + if (this.core.LastStage == null) { return; } - float hudLeft; - StringBuilder hudString; - - if (EditorLogic.fetch.editorScreen == EditorLogic.EditorScreen.Parts) - { - hudLeft = EditorPanels.Instance.partsPanelWidth + 10; - } - else if (EditorLogic.fetch.editorScreen == EditorLogic.EditorScreen.Actions) - { - hudLeft = EditorPanels.Instance.actionsPanelWidth + 10; - } - else - { - return; - } - - Rect hudPos = new Rect (hudLeft, 48, 300, 32); - - hudString = new StringBuilder(); - - // GUI.skin = AssetBase.GetGUISkin("KSP window 2"); - - labelStyle.normal.textColor = textColors [ColorIndex]; + VOID_Styles.labelHud.alignment = TextAnchor.UpperLeft; hudString.Append("Total Mass: "); - hudString.Append(SimManager.LastStage.totalMass.ToString("F3")); + hudString.Append(this.core.LastStage.totalMass.ToString("F3")); hudString.Append('t'); hudString.Append(' '); @@ -184,22 +136,30 @@ hudString.Append('\n'); hudString.Append("Total Delta-V: "); - hudString.Append(Tools.MuMech_ToSI(SimManager.LastStage.totalDeltaV)); + hudString.Append(Tools.MuMech_ToSI(this.core.LastStage.totalDeltaV)); hudString.Append("m/s"); hudString.Append('\n'); hudString.Append("Bottom Stage Delta-V"); - hudString.Append(Tools.MuMech_ToSI(SimManager.LastStage.deltaV)); + hudString.Append(Tools.MuMech_ToSI(this.core.LastStage.deltaV)); hudString.Append("m/s"); hudString.Append('\n'); hudString.Append("Bottom Stage T/W Ratio: "); - hudString.Append(SimManager.LastStage.thrustToWeight.ToString("F3")); + hudString.Append(this.core.LastStage.thrustToWeight.ToString("F3")); + + Tools.PostDebugMessage(this, + "CoMmarker.gameObject.activeInHierarchy: {0};" + + "CoTmarker.gameObject.activeInHierarchy: {1}", + this.CoMmarker.gameObject.activeInHierarchy, + this.CoTmarker.gameObject.activeInHierarchy + ); if (this.CoMmarker.gameObject.activeInHierarchy && this.CoTmarker.gameObject.activeInHierarchy) { + Tools.PostDebugMessage(this, "CoM and CoT markers are active, doing thrust offset."); hudString.Append('\n'); hudString.Append("Thrust Offset: "); @@ -209,19 +169,77 @@ this.CoMmarker.posMarkerObject.transform.position - this.CoTmarker.posMarkerObject.transform.position ).ToString("F3")); } - - GUI.Label ( - hudPos, + #if DEBUG + else + { + Tools.PostDebugMessage(this, "CoM and CoT markers are not active, thrust offset skipped."); + } + #endif + + GUILayout.Label( hudString.ToString(), - labelStyle); - } - - public override void DrawConfigurables() - { - if (GUILayout.Button ("Change HUD color", GUILayout.ExpandWidth (false))) - { - ++this.ColorIndex; - } + VOID_Styles.labelHud, + GUILayout.ExpandWidth(true), + GUILayout.ExpandHeight(true) + ); + + if (!this.positionsLocked) + { + GUI.DragWindow(); + } + + GUI.BringWindowToBack(id); + } + + public override void DrawGUI() + { + float hudLeft; + + if (EditorLogic.fetch.editorScreen == EditorScreen.Parts) + { + hudLeft = EditorPanels.Instance.partsPanelWidth + 10f; + hudLeft += EditorPartList.Instance.transformTopLeft.position.x - + EditorPartList.Instance.transformTopLeft.parent.parent.position.x - + 72f; + } + else if (EditorLogic.fetch.editorScreen == EditorScreen.Actions) + { + hudLeft = EditorPanels.Instance.actionsPanelWidth + 10f; + } + else + { + return; + } + + Tools.PostDebugMessage(this, + "EditorPartList topLeft.parent.parent.position: {0}\n" + + "EditorPartList topLeft.parent.position: {1}\n" + + "EditorPartList topLeft.position: {2}\n" + + "snapToEdge: {3} (pos.Xmin: {4}; hudLeft: {5})", + EditorPartList.Instance.transformTopLeft.parent.parent.position, + EditorPartList.Instance.transformTopLeft.parent.position, + EditorPartList.Instance.transformTopLeft.position, + this.snapToLeft, this.ehudWindow.WindowPos.xMin, hudLeft + ); + + base.DrawGUI(); + + Rect hudPos = this.ehudWindow.WindowPos; + + if (this.snapToLeft && this.positionsLocked) + { + hudPos.xMin = hudLeft; + } + else + { + hudPos.xMin = Mathf.Max(hudLeft, hudPos.xMin); + } + + hudPos.width = this.ehudWindow.defaultWindowPos.width; + + this.ehudWindow.WindowPos = hudPos; + + this.snapToLeft = Mathf.Abs(this.ehudWindow.WindowPos.xMin - hudLeft) < 15f; } } } --- a/VOID_HUD.cs +++ b/VOID_HUD.cs @@ -26,7 +26,7 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -using Engineer.VesselSimulator; +using KerbalEngineer.VesselSimulator; using KSP; using System; using System.Collections.Generic; @@ -36,47 +36,17 @@ namespace VOID { - public class VOID_HUD : VOID_Module, IVOID_Module + public class VOID_HUD : VOID_HUDModule, IVOID_Module { /* * Fields * */ - [AVOID_SaveValue("colorIndex")] - protected VOID_SaveValue _colorIndex; - - protected List textColors; - - protected Rect leftHUDdefaultPos; - protected Rect rightHUDdefaultPos; - - [AVOID_SaveValue("leftHUDPos")] - protected VOID_SaveValue leftHUDPos; - [AVOID_SaveValue("rightHUDPos")] - protected VOID_SaveValue rightHUDPos; - - [AVOID_SaveValue("positionsLocked")] - protected VOID_SaveValue positionsLocked; + protected HUDWindow leftHUD; + protected HUDWindow rightHUD; /* * Properties * */ - public int ColorIndex - { - get - { - return this._colorIndex; - } - set - { - if (this._colorIndex >= this.textColors.Count - 1) - { - this._colorIndex = 0; - return; - } - - this._colorIndex = value; - } - } /* * Methods @@ -85,29 +55,13 @@ { this._Name = "Heads-Up Display"; - this._Active.value = true; + this.toggleActive = true; - this._colorIndex = 0; + this.leftHUD = new HUDWindow("leftHUD", this.leftHUDWindow, new Rect(Screen.width * .375f - 300f, 0f, 300f, 90f)); + this.Windows.Add(this.leftHUD); - this.textColors = new List(); - - this.textColors.Add(Color.green); - this.textColors.Add(Color.black); - this.textColors.Add(Color.white); - this.textColors.Add(Color.red); - this.textColors.Add(Color.blue); - this.textColors.Add(Color.yellow); - this.textColors.Add(Color.gray); - this.textColors.Add(Color.cyan); - this.textColors.Add(Color.magenta); - - this.leftHUDdefaultPos = new Rect(Screen.width * .375f - 300f, 0f, 300f, 90f); - this.leftHUDPos = new Rect(this.leftHUDdefaultPos); - - this.rightHUDdefaultPos = new Rect(Screen.width * .625f, 0f, 300f, 90f); - this.rightHUDPos = new Rect(this.rightHUDdefaultPos); - - this.positionsLocked = true; + this.rightHUD = new HUDWindow("rightHUD", this.rightHUDWindow, new Rect(Screen.width * .625f, 0f, 300f, 90f)); + this.Windows.Add(this.rightHUD); Tools.PostDebugMessage ("VOID_HUD: Constructed."); } @@ -118,7 +72,7 @@ leftHUD = new StringBuilder(); - this.core.LabelStyles["hud"].alignment = TextAnchor.UpperRight; + VOID_Styles.labelHud.alignment = TextAnchor.UpperRight; if (this.core.powerAvailable) { @@ -145,11 +99,16 @@ } else { - this.core.LabelStyles["hud"].normal.textColor = Color.red; + VOID_Styles.labelHud.normal.textColor = Color.red; leftHUD.Append(string.Intern("-- POWER LOST --")); } - GUILayout.Label(leftHUD.ToString(), this.core.LabelStyles["hud"], GUILayout.ExpandWidth(true)); + GUILayout.Label( + leftHUD.ToString(), + VOID_Styles.labelHud, + GUILayout.ExpandWidth(true), + GUILayout.ExpandHeight(true) + ); if (!this.positionsLocked) { @@ -165,7 +124,7 @@ rightHUD = new StringBuilder(); - this.core.LabelStyles["hud"].alignment = TextAnchor.UpperLeft; + VOID_Styles.labelHud.alignment = TextAnchor.UpperLeft; if (this.core.powerAvailable) { @@ -189,15 +148,33 @@ VOID_Data.vesselHeading.ValueUnitString(), VOID_Data.vesselPitch.ToSIString(2) ); + + if ( + this.core.vessel.mainBody == this.core.HomeBody && + ( + this.core.vessel.situation == Vessel.Situations.FLYING || + this.core.vessel.situation == Vessel.Situations.SUB_ORBITAL || + this.core.vessel.situation == Vessel.Situations.LANDED || + this.core.vessel.situation == Vessel.Situations.SPLASHED + ) + ) + { + rightHUD.AppendFormat("\nRange to KSC: {0}", VOID_Data.downrangeDistance.ValueUnitString(2)); + } } else { - this.core.LabelStyles["hud"].normal.textColor = Color.red; + VOID_Styles.labelHud.normal.textColor = Color.red; rightHUD.Append(string.Intern("-- POWER LOST --")); } - GUILayout.Label(rightHUD.ToString(), this.core.LabelStyles["hud"], GUILayout.ExpandWidth(true)); + GUILayout.Label( + rightHUD.ToString(), + VOID_Styles.labelHud, + GUILayout.ExpandWidth(true), + GUILayout.ExpandHeight(true) + ); if (!this.positionsLocked) { @@ -206,69 +183,6 @@ GUI.BringWindowToBack(id); } - - public override void DrawGUI() - { - if (!this.core.LabelStyles.ContainsKey("hud")) - { - this.core.LabelStyles["hud"] = new GUIStyle(GUI.skin.label); - } - - this.core.LabelStyles["hud"].normal.textColor = textColors [ColorIndex]; - - if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate)) - { - SimManager.RequestSimulation(); - } - - this.leftHUDPos.value = GUI.Window( - this.core.windowID, - this.leftHUDPos, - this.leftHUDWindow, - GUIContent.none, - GUIStyle.none - ); - - this.rightHUDPos.value = GUI.Window( - this.core.windowID, - this.rightHUDPos, - this.rightHUDWindow, - GUIContent.none, - GUIStyle.none - ); - } - - public override void DrawConfigurables() - { - if (GUILayout.Button (string.Intern("Change HUD color"), GUILayout.ExpandWidth (false))) - { - ++this.ColorIndex; - } - - if (GUILayout.Button(string.Intern("Reset HUD Positions"), GUILayout.ExpandWidth(false))) - { - this.leftHUDPos = new Rect(this.leftHUDdefaultPos); - this.rightHUDPos = new Rect(this.rightHUDdefaultPos); - } - - this.positionsLocked = GUILayout.Toggle(this.positionsLocked, - string.Intern("Lock HUD Positions"), - GUILayout.ExpandWidth(false)); - } - } - - public static partial class VOID_Data - { - public static readonly VOID_StrValue expSituation = new VOID_StrValue( - "Situation", - new Func (() => core.vessel.GetExperimentSituation().HumanString()) - ); - - public static readonly VOID_DoubleValue vesselPitch = new VOID_DoubleValue( - "Pitch", - () => core.vessel.getSurfacePitch(), - "°" - ); } } --- a/VOID_HUDAdvanced.cs +++ b/VOID_HUDAdvanced.cs @@ -26,7 +26,7 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -using Engineer.VesselSimulator; +using KerbalEngineer.VesselSimulator; using KSP; using System; using System.Collections.Generic; @@ -37,37 +37,33 @@ namespace VOID { - public class VOID_HUDAdvanced : VOID_Module, IVOID_Module + public class VOID_HUDAdvanced : VOID_HUDModule, IVOID_Module { /* * Fields * */ protected VOID_HUD primaryHUD; - protected Rect leftHUDdefaultPos; - protected Rect rightHUDdefaultPos; - - [AVOID_SaveValue("leftHUDPos")] - protected VOID_SaveValue leftHUDPos; - [AVOID_SaveValue("rightHUDPos")] - protected VOID_SaveValue rightHUDPos; - - [AVOID_SaveValue("positionsLocked")] - protected VOID_SaveValue positionsLocked; + protected HUDWindow leftHUD; + protected HUDWindow rightHUD; /* * Properties * */ - public int ColorIndex + public override int ColorIndex { get { - if (this.primaryHUD == null) - { - return 0; - } - - return this.primaryHUD.ColorIndex; + if (this.primaryHUD != null) + { + return this.primaryHUD.ColorIndex; + } + + return base.ColorIndex; + } + set + { + base.ColorIndex = value; } } @@ -78,21 +74,26 @@ { this._Name = "Advanced Heads-Up Display"; - this._Active.value = true; - - this.leftHUDdefaultPos = new Rect( - Screen.width * .5f - (float)GameSettings.UI_SIZE * .25f - 300f, - Screen.height - 200f, - 300f, 90f - ); - this.leftHUDPos = new Rect(this.leftHUDdefaultPos); - - this.rightHUDdefaultPos = new Rect( - Screen.width * .5f + (float)GameSettings.UI_SIZE * .25f, - Screen.height - 200f, - 300f, 90f - ); - this.rightHUDPos = new Rect(this.rightHUDdefaultPos); + this.toggleActive = true; + + this.leftHUD = new HUDWindow("leftHUD", + this.leftHUDWindow, + new Rect( + Screen.width * .5f - (float)GameSettings.UI_SIZE * .25f - 300f, + Screen.height - 200f, + 300f, 90f) + ); + this.Windows.Add(this.leftHUD); + + this.rightHUD = new HUDWindow( + "rightHUD", + this.rightHUDWindow, + new Rect( + Screen.width * .5f + (float)GameSettings.UI_SIZE * .25f, + Screen.height - 200f, + 300f, 90f) + ); + this.Windows.Add(this.rightHUD); this.positionsLocked = true; @@ -105,7 +106,7 @@ leftHUD = new StringBuilder(); - this.core.LabelStyles["hud"].alignment = TextAnchor.UpperRight; + VOID_Styles.labelHud.alignment = TextAnchor.UpperRight; if (this.core.powerAvailable) { @@ -144,11 +145,16 @@ } else { - this.core.LabelStyles["hud"].normal.textColor = Color.red; + VOID_Styles.labelHud.normal.textColor = Color.red; leftHUD.Append(string.Intern("-- POWER LOST --")); } - GUILayout.Label(leftHUD.ToString(), this.core.LabelStyles["hud"], GUILayout.ExpandWidth(true)); + GUILayout.Label( + leftHUD.ToString(), + VOID_Styles.labelHud, + GUILayout.ExpandWidth(true), + GUILayout.ExpandHeight(true) + ); if (!this.positionsLocked) { @@ -164,7 +170,7 @@ rightHUD = new StringBuilder(); - this.core.LabelStyles["hud"].alignment = TextAnchor.UpperLeft; + VOID_Styles.labelHud.alignment = TextAnchor.UpperLeft; if (this.core.powerAvailable) { @@ -182,8 +188,8 @@ } rightHUD.AppendFormat("Burn Time (Rem/Total): {0} / {1}\n", - VOID_Tools.ConvertInterval(VOID_Data.currentNodeBurnRemaining.Value), - VOID_Tools.ConvertInterval(VOID_Data.currentNodeBurnDuration.Value) + VOID_Tools.FormatInterval(VOID_Data.currentNodeBurnRemaining.Value), + VOID_Tools.FormatInterval(VOID_Data.currentNodeBurnDuration.Value) ); if (VOID_Data.burnTimeDoneAtNode.Value != string.Empty) @@ -203,11 +209,16 @@ } else { - this.core.LabelStyles["hud"].normal.textColor = Color.red; + VOID_Styles.labelHud.normal.textColor = Color.red; rightHUD.Append(string.Intern("-- POWER LOST --")); } - GUILayout.Label(rightHUD.ToString(), this.core.LabelStyles["hud"], GUILayout.ExpandWidth(true)); + GUILayout.Label( + rightHUD.ToString(), + VOID_Styles.labelHud, + GUILayout.ExpandWidth(true), + GUILayout.ExpandHeight(true) + ); if (!this.positionsLocked) { @@ -229,440 +240,33 @@ } } } - else - { - if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate)) - { - SimManager.RequestSimulation(); - } - - this.leftHUDPos.value = GUI.Window( - this.core.windowID, - this.leftHUDPos, - VOID_Tools.GetWindowHandler(this.leftHUDWindow), - GUIContent.none, - GUIStyle.none - ); - - if (VOID_Data.upcomingManeuverNodes > 0) - { - this.rightHUDPos.value = GUI.Window( - this.core.windowID, - this.rightHUDPos, - VOID_Tools.GetWindowHandler(this.rightHUDWindow), - GUIContent.none, - GUIStyle.none - ); - } - } + + if (VOID_Data.upcomingManeuverNodes < 1 && this.Windows.Contains(this.rightHUD)) + { + this.Windows.Remove(this.rightHUD); + } + else if (VOID_Data.upcomingManeuverNodes > 0 && !this.Windows.Contains(this.rightHUD)) + { + this.Windows.Add(this.rightHUD); + } + + base.DrawGUI(); } public override void DrawConfigurables() { + if (GUILayout.Button(string.Intern("Reset Advanced HUD Positions"), GUILayout.ExpandWidth(false))) + { + foreach (HUDWindow window in this.Windows) + { + window.WindowPos = new Rect(window.defaultWindowPos); + } + } + this.positionsLocked = GUILayout.Toggle(this.positionsLocked, string.Intern("Lock Advanced HUD Positions"), GUILayout.ExpandWidth(false)); } } - - public static partial class VOID_Data - { - public static int upcomingManeuverNodes - { - get - { - if (core.vessel == null || - core.vessel.patchedConicSolver == null || - core.vessel.patchedConicSolver.maneuverNodes == null - ) - { - return 0; - } - - return core.vessel.patchedConicSolver.maneuverNodes.Count; - } - } - - public static readonly VOID_Vector3dValue vesselThrustOffset = new VOID_Vector3dValue( - "Thrust Offset", - delegate() - { - if (core.vessel == null) - { - return Vector3d.zero; - } - - List engineModules = core.vessel.getModulesOfType(); - - Vector3d thrustPos = Vector3d.zero; - Vector3d thrustDir = Vector3d.zero; - float thrust = 0; - - foreach (PartModule engine in engineModules) - { - float moduleThrust = 0; - - switch (engine.moduleName) - { - case "ModuleEngines": - case "ModuleEnginesFX": - break; - default: - continue; - } - - if (!engine.isEnabled) - { - continue; - } - - CenterOfThrustQuery cotQuery = new CenterOfThrustQuery(); - - if (engine is ModuleEngines) - { - ModuleEngines engineModule = engine as ModuleEngines; - - moduleThrust = engineModule.finalThrust; - - engineModule.OnCenterOfThrustQuery(cotQuery); - } - else // engine is ModuleEnginesFX - { - ModuleEnginesFX engineFXModule = engine as ModuleEnginesFX; - - moduleThrust = engineFXModule.finalThrust; - - engineFXModule.OnCenterOfThrustQuery(cotQuery); - } - - if (moduleThrust != 0d) - { - cotQuery.thrust = moduleThrust; - } - - thrustPos += cotQuery.pos * cotQuery.thrust; - thrustDir += cotQuery.dir * cotQuery.thrust; - thrust += cotQuery.thrust; - } - - if (thrust != 0) - { - thrustPos /= thrust; - thrustDir /= thrust; - } - - Transform vesselTransform = core.vessel.transform; - - thrustPos = vesselTransform.InverseTransformPoint(thrustPos); - thrustDir = vesselTransform.InverseTransformDirection(thrustDir); - - Vector3d thrustOffset = VectorTools.PointDistanceToLine( - thrustPos, thrustDir.normalized, core.vessel.findLocalCenterOfMass()); - - Tools.PostDebugMessage(typeof(VOID_Data), "vesselThrustOffset:\n" + - "\tthrustPos: {0}\n" + - "\tthrustDir: {1}\n" + - "\tthrustOffset: {2}\n" + - "\tvessel.CoM: {3}", - thrustPos, - thrustDir.normalized, - thrustOffset, - core.vessel.findWorldCenterOfMass() - ); - - return thrustOffset; - }, - "m" - ); - - public static readonly VOID_DoubleValue vesselAccel = new VOID_DoubleValue( - "Acceleration", - () => geeForce * KerbinGee, - "m/s²" - ); - - public static readonly VOID_IntValue vesselCrewCount = new VOID_IntValue( - "Crew Onboard", - delegate() - { - if (core.vessel != null) - { - return core.vessel.GetCrewCount(); - } - else - { - return 0; - } - }, - "" - ); - - public static readonly VOID_IntValue vesselCrewCapacity = new VOID_IntValue( - "Crew Capacity", - delegate() - { - if (core.vessel != null) - { - return core.vessel.GetCrewCapacity(); - } - else - { - return 0; - } - }, - "" - ); - - public static readonly VOID_DoubleValue vesselAngularVelocity = new VOID_DoubleValue( - "Angular Velocity", - delegate() - { - if (core.vessel != null) - { - return core.vessel.angularVelocity.magnitude; - } - else - { - return double.NaN; - } - }, - "rad/s" - ); - - public static readonly VOID_DoubleValue stageNominalThrust = new VOID_DoubleValue( - "Nominal Stage Thrust", - delegate() - { - if (SimManager.LastStage == null) - { - return double.NaN; - } - - if (SimManager.LastStage.actualThrust == 0d) - { - return SimManager.LastStage.thrust; - } - else - { - return SimManager.LastStage.actualThrust; - } - }, - "kN" - ); - - public static readonly VOID_DoubleValue stageMassFlow = new VOID_DoubleValue( - "Stage Mass Flow", - delegate() - { - if (SimManager.LastStage == null) - { - return double.NaN; - } - - double stageIsp = SimManager.LastStage.isp; - double stageThrust = stageNominalThrust; - - Tools.PostDebugMessage(typeof(VOID_Data), "calculating stageMassFlow from:\n" + - "\tstageIsp: {0}\n" + - "\tstageThrust: {1}\n" + - "\tKerbinGee: {2}\n", - stageIsp, - stageThrust, - KerbinGee - ); - - return stageThrust / (stageIsp * KerbinGee); - }, - "Mg/s" - ); - - public static readonly VOID_DoubleValue currManeuverDeltaV = new VOID_DoubleValue( - "Current Maneuver Delta-V", - delegate() - { - if (upcomingManeuverNodes > 0) - { - return core.vessel.patchedConicSolver.maneuverNodes[0].DeltaV.magnitude; - } - else - { - return double.NaN; - } - }, - "m/s" - ); - - public static readonly VOID_DoubleValue currManeuverDVRemaining = new VOID_DoubleValue( - "Remaining Maneuver Delta-V", - delegate() - { - if (upcomingManeuverNodes > 0) - { - return core.vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(core.vessel.orbit).magnitude; - } - else - { - return double.NaN; - } - }, - "m/s" - ); - - public static readonly VOID_DoubleValue nextManeuverDeltaV = new VOID_DoubleValue( - "Current Maneuver Delta-V", - delegate() - { - if (upcomingManeuverNodes > 1) - { - return core.vessel.patchedConicSolver.maneuverNodes[1].DeltaV.magnitude; - } - else - { - return double.NaN; - } - }, - "m/s" - ); - - public static readonly VOID_DoubleValue currentNodeBurnDuration = new VOID_DoubleValue( - "Total Burn Time", - delegate() - { - if (SimManager.LastStage == null || currManeuverDeltaV.Value == double.NaN) - { - return double.NaN; - } - - double stageThrust = stageNominalThrust; - - return burnTime(currManeuverDeltaV.Value, totalMass, stageMassFlow, stageThrust); - }, - "s" - ); - - public static readonly VOID_DoubleValue currentNodeBurnRemaining = new VOID_DoubleValue( - "Burn Time Remaining", - delegate() - { - if (SimManager.LastStage == null || currManeuverDVRemaining == double.NaN) - { - return double.NaN; - } - - double stageThrust = stageNominalThrust; - - return burnTime(currManeuverDVRemaining, totalMass, stageMassFlow, stageThrust); - }, - "s" - ); - - public static readonly VOID_DoubleValue currentNodeHalfBurnDuration = new VOID_DoubleValue( - "Half Burn Time", - delegate() - { - if (SimManager.LastStage == null || currManeuverDeltaV.Value == double.NaN) - { - return double.NaN; - } - - double stageThrust = stageNominalThrust; - - return burnTime(currManeuverDeltaV.Value / 2d, totalMass, stageMassFlow, stageThrust); - }, - "s" - ); - - public static readonly VOID_StrValue burnTimeDoneAtNode = new VOID_StrValue( - "Full burn time to be half done at node", - delegate() - { - if (SimManager.LastStage == null && upcomingManeuverNodes < 1) - { - return "N/A"; - } - - ManeuverNode node = core.vessel.patchedConicSolver.maneuverNodes[0]; - - if ((node.UT - Planetarium.GetUniversalTime()) < 0) - { - return string.Empty; - } - - double interval = (node.UT - currentNodeBurnDuration) - Planetarium.GetUniversalTime(); - - if (double.IsNaN(interval)) - { - return string.Intern("NaN"); - } - - int sign = Math.Sign(interval); - interval = Math.Abs(interval); - - string format; - - if (sign >= 0) - { - format = string.Intern("T - {0}"); - } - else - { - format = string.Intern("T + {0}"); - } - - return string.Format(format, VOID_Tools.ConvertInterval(interval)); - } - ); - - public static readonly VOID_StrValue burnTimeHalfDoneAtNode = new VOID_StrValue( - "Full burn time to be half done at node", - delegate() - { - if (SimManager.LastStage == null && upcomingManeuverNodes < 1) - { - return "N/A"; - } - - ManeuverNode node = core.vessel.patchedConicSolver.maneuverNodes[0]; - - if ((node.UT - Planetarium.GetUniversalTime()) < 0) - { - return string.Empty; - } - - double interval = (node.UT - currentNodeHalfBurnDuration) - Planetarium.GetUniversalTime(); - - int sign = Math.Sign(interval); - interval = Math.Abs(interval); - - string format; - - if (sign >= 0) - { - format = string.Intern("T - {0}"); - } - else - { - format = string.Intern("T + {0}"); - } - - return string.Format(format, VOID_Tools.ConvertInterval(interval)); - } - ); - - private static double burnTime(double deltaV, double initialMass, double massFlow, double thrust) - { - Tools.PostDebugMessage(typeof(VOID_Data), "calculating burnTime from:\n" + - "\tdeltaV: {0}\n" + - "\tinitialMass: {1}\n" + - "\tmassFlow: {2}\n" + - "\tthrust: {3}\n", - deltaV, - initialMass, - massFlow, - thrust - ); - return initialMass / massFlow * (Math.Exp(deltaV * massFlow / thrust) - 1d); - } - } } --- /dev/null +++ b/VOID_HUDModule.cs @@ -1,1 +1,217 @@ - +// VOID +// +// VOID_HUDModule.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +using KerbalEngineer.VesselSimulator; +using KSP; +using System; +using System.Collections.Generic; +using System.Text; +using ToadicusTools; +using UnityEngine; + +namespace VOID +{ + public abstract class VOID_HUDModule : VOID_Module + { + [AVOID_SaveValue("colorIndex")] + protected VOID_SaveValue _colorIndex; + + protected List textColors; + + [AVOID_SaveValue("positionsLocked")] + protected VOID_SaveValue positionsLocked; + + public virtual int ColorIndex + { + get + { + return this._colorIndex; + } + set + { + if (this._colorIndex >= this.textColors.Count - 1) + { + this._colorIndex = 0; + return; + } + + this._colorIndex = value; + } + } + + public virtual List Windows + { + get; + protected set; + } + + public VOID_HUDModule() : base() + { + this._colorIndex = 0; + + this.textColors = new List(); + + this.textColors.Add(Color.green); + this.textColors.Add(Color.black); + this.textColors.Add(Color.white); + this.textColors.Add(Color.red); + this.textColors.Add(Color.blue); + this.textColors.Add(Color.yellow); + this.textColors.Add(Color.gray); + this.textColors.Add(Color.cyan); + this.textColors.Add(Color.magenta); + + this.positionsLocked = true; + + this.Windows = new List(); + } + + public override void DrawGUI() + { + VOID_Styles.labelHud.normal.textColor = textColors [ColorIndex]; + + GUI.skin = this.core.Skin; + + if (HighLogic.LoadedSceneIsEditor || + (TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate) + ) + { + SimManager.RequestSimulation(); + } + + foreach (HUDWindow window in this.Windows) + { + window.WindowPos = GUILayout.Window( + this.core.windowID, + window.WindowPos, + VOID_Tools.GetWindowHandler(window.WindowFunction), + GUIContent.none, + GUIStyle.none + ); + } + } + + public override void DrawConfigurables() + { + if (GUILayout.Button (string.Intern("Change HUD color"), GUILayout.ExpandWidth (false))) + { + ++this.ColorIndex; + } + + if (GUILayout.Button(string.Intern("Reset HUD Positions"), GUILayout.ExpandWidth(false))) + { + foreach (HUDWindow window in this.Windows) + { + window.WindowPos = new Rect(window.defaultWindowPos); + } + } + + this.positionsLocked = GUILayout.Toggle(this.positionsLocked, + string.Intern("Lock HUD Positions"), + GUILayout.ExpandWidth(false)); + } + + public override void LoadConfig() + { + base.LoadConfig(); + + var config = KSP.IO.PluginConfiguration.CreateForType(); + config.load(); + + foreach (HUDWindow window in this.Windows) + { + string saveName = string.Format("{0}_{1}", this.GetType().Name, window.WindowName); + Rect loadedPos = config.GetValue(saveName, window.defaultWindowPos); + + window.WindowPos = loadedPos; + } + } + + public override void _SaveToConfig(KSP.IO.PluginConfiguration config) + { + base._SaveToConfig(config); + + foreach (HUDWindow window in this.Windows) + { + string saveName = string.Format("{0}_{1}", this.GetType().Name, window.WindowName); + config.SetValue(saveName, window.WindowPos); + } + } + } + + public class HUDWindow + { + public readonly Rect defaultWindowPos; + + private Rect _windowPos; + + public Action WindowFunction + { + get; + private set; + } + + public Rect WindowPos + { + get + { + return this._windowPos; + } + set + { + if (value != this._windowPos) + { + this._windowPos = value; + + if (VOID_Data.core != null) + { + VOID_Data.core.configDirty = true; + } + } + } + } + + public string WindowName + { + get; + private set; + } + + private HUDWindow() {} + + public HUDWindow(string name, Action windowFunc, Rect defaultPos) + { + this.WindowName = name; + this.WindowFunction = windowFunc; + this.defaultWindowPos = defaultPos; + this.WindowPos = new Rect(this.defaultWindowPos); + } + } +} + + --- a/VOID_Module.cs +++ b/VOID_Module.cs @@ -215,9 +215,21 @@ public abstract class VOID_WindowModule : VOID_Module { [AVOID_SaveValue("WindowPos")] - protected Rect WindowPos = new Rect(Screen.width / 2, Screen.height / 2, 250f, 50f); - protected float defWidth = 250f; - protected float defHeight = 50f; + protected Rect WindowPos; + protected float defWidth; + protected float defHeight; + + protected string inputLockName; + + public VOID_WindowModule() : base() + { + this.defWidth = 250f; + this.defHeight = 50f; + + this.inputLockName = string.Concat(this.Name, "_edlock"); + + this.WindowPos = new Rect(Screen.width / 2, Screen.height / 2, this.defWidth, this.defHeight); + } public abstract void ModuleWindow(int _); @@ -231,10 +243,60 @@ this.core.windowID, _Pos, VOID_Tools.GetWindowHandler(this.ModuleWindow), - this.Name + this.Name, + GUILayout.Width(this.defWidth), + GUILayout.Height(this.defHeight) ); - _Pos = Tools.ClampRectToScreen (_Pos); + bool cursorInWindow = _Pos.Contains(Mouse.screenPos); + + switch (HighLogic.LoadedScene) + { + case GameScenes.EDITOR: + if (cursorInWindow) + { + InputLockManager.SetControlLock( + ControlTypes.EDITOR_ICON_HOVER | ControlTypes.EDITOR_ICON_PICK | + ControlTypes.EDITOR_PAD_PICK_COPY | ControlTypes.EDITOR_PAD_PICK_COPY, + this.inputLockName + ); + EditorLogic.fetch.Lock(false, false, false, this.inputLockName); + } + else + { + EditorLogic.fetch.Unlock(this.inputLockName); + } + break; + case GameScenes.FLIGHT: + if (cursorInWindow) + { + InputLockManager.SetControlLock(ControlTypes.CAMERACONTROLS, this.inputLockName); + } + else if (InputLockManager.GetControlLock(this.inputLockName) != ControlTypes.None) + { + InputLockManager.RemoveControlLock(this.inputLockName); + } + break; + case GameScenes.SPACECENTER: + if (cursorInWindow) + { + InputLockManager.SetControlLock(ControlTypes.KSC_FACILITIES, this.inputLockName); + } + else if (InputLockManager.GetControlLock(this.inputLockName) != ControlTypes.None) + { + InputLockManager.RemoveControlLock(this.inputLockName); + } + break; + } + + if (HighLogic.LoadedSceneIsEditor) + { + _Pos = Tools.ClampRectToEditorPad(_Pos); + } + else + { + _Pos = Tools.ClampRectToScreen(_Pos); + } if (_Pos != this.WindowPos) { --- a/VOID_Orbital.cs +++ b/VOID_Orbital.cs @@ -121,128 +121,6 @@ base._SaveToConfig (config); } } - - - public static partial class VOID_Data - { - public static readonly VOID_StrValue primaryName = new VOID_StrValue ( - VOID_Localization.void_primary, - delegate() - { - if (core.vessel == null) - { - return string.Empty; - } - return core.vessel.mainBody.name; - } - ); - - public static readonly VOID_DoubleValue orbitAltitude = new VOID_DoubleValue ( - "Altitude (ASL)", - new Func (() => core.vessel.orbit.altitude), - "m" - ); - - public static readonly VOID_DoubleValue orbitVelocity = new VOID_DoubleValue ( - VOID_Localization.void_velocity, - new Func (() => core.vessel.orbit.vel.magnitude), - "m/s" - ); - - public static readonly VOID_DoubleValue orbitApoAlt = new VOID_DoubleValue( - VOID_Localization.void_apoapsis, - new Func(() => core.vessel.orbit.ApA), - "m" - ); - - public static readonly VOID_DoubleValue oribtPeriAlt = new VOID_DoubleValue( - VOID_Localization.void_periapsis, - new Func(() => core.vessel.orbit.PeA), - "m" - ); - - public static readonly VOID_StrValue timeToApo = new VOID_StrValue( - "Time to Apoapsis", - new Func(() => VOID_Tools.ConvertInterval(core.vessel.orbit.timeToAp)) - ); - - public static readonly VOID_StrValue timeToPeri = new VOID_StrValue( - "Time to Periapsis", - new Func(() => VOID_Tools.ConvertInterval(core.vessel.orbit.timeToPe)) - ); - - public static readonly VOID_DoubleValue orbitInclination = new VOID_DoubleValue( - "Inclination", - new Func(() => core.vessel.orbit.inclination), - "°" - ); - - public static readonly VOID_DoubleValue gravityAccel = new VOID_DoubleValue( - "Gravity", - delegate() - { - double orbitRadius = core.vessel.mainBody.Radius + - core.vessel.mainBody.GetAltitude(core.vessel.findWorldCenterOfMass()); - return (VOID_Core.Constant_G * core.vessel.mainBody.Mass) / - (orbitRadius * orbitRadius); - }, - "m/s²" - ); - - public static readonly VOID_StrValue orbitPeriod = new VOID_StrValue( - "Period", - new Func(() => VOID_Tools.ConvertInterval(core.vessel.orbit.period)) - ); - - public static readonly VOID_DoubleValue semiMajorAxis = new VOID_DoubleValue( - "Semi-Major Axis", - new Func(() => core.vessel.orbit.semiMajorAxis), - "m" - ); - - public static readonly VOID_DoubleValue eccentricity = new VOID_DoubleValue( - "Eccentricity", - new Func(() => core.vessel.orbit.eccentricity), - "" - ); - - public static readonly VOID_DoubleValue meanAnomaly = new VOID_DoubleValue( - "Mean Anomaly", - new Func(() => core.vessel.orbit.meanAnomaly * 180d / Math.PI), - "°" - ); - - public static readonly VOID_DoubleValue trueAnomaly = new VOID_DoubleValue( - "True Anomaly", - new Func(() => core.vessel.orbit.trueAnomaly), - "°" - ); - - public static readonly VOID_DoubleValue eccAnomaly = new VOID_DoubleValue( - "Eccentric Anomaly", - new Func(() => core.vessel.orbit.eccentricAnomaly * 180d / Math.PI), - "°" - ); - - public static readonly VOID_DoubleValue longitudeAscNode = new VOID_DoubleValue( - "Long. Ascending Node", - new Func(() => core.vessel.orbit.LAN), - "°" - ); - - public static readonly VOID_DoubleValue argumentPeriapsis = new VOID_DoubleValue( - "Argument of Periapsis", - new Func(() => core.vessel.orbit.argumentOfPeriapsis), - "°" - ); - - public static readonly VOID_DoubleValue localSiderealLongitude = new VOID_DoubleValue( - "Local Sidereal Longitude", - new Func(() => VOID_Tools.FixDegreeDomain( - core.vessel.longitude + core.vessel.orbit.referenceBody.rotationAngle)), - "°" - ); - } } --- a/VOID_Rendezvous.cs +++ b/VOID_Rendezvous.cs @@ -67,7 +67,7 @@ //display both //Show Target Info - GUILayout.Label("Target:", this.core.LabelStyles["center_bold"]); + GUILayout.Label("Target:", VOID_Styles.labelCenterBold); if (FlightGlobals.fetch.VesselTarget != null) { //a KSP Target (body or vessel) is selected @@ -94,13 +94,13 @@ else { //no KSP Target selected - GUILayout.Label("No Target Selected", this.core.LabelStyles["center_bold"]); + GUILayout.Label("No Target Selected", VOID_Styles.labelCenterBold); } //Show Vessel Register vessel info if (untoggleRegisterInfo == false && this.RegisterModule != default(IVOID_Module)) { - GUILayout.Label("Vessel Register:", this.core.LabelStyles["center_bold"]); + GUILayout.Label("Vessel Register:", VOID_Styles.labelCenterBold); if (this.RegisterModule.selectedVessel != null) { rendezvessel = this.RegisterModule.selectedVessel; @@ -122,7 +122,7 @@ { //vesreg Vessel is null //targ = null; - GUILayout.Label("No Vessel Selected", this.core.LabelStyles["center_bold"]); + GUILayout.Label("No Vessel Selected", VOID_Styles.labelCenterBold); } } @@ -130,7 +130,7 @@ GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label(" ", GUILayout.ExpandWidth(true)); - if (GUILayout.Button("Close", GUILayout.ExpandWidth(false))) this._Active = false; + if (GUILayout.Button("Close", GUILayout.ExpandWidth(false))) this.toggleActive = false; GUILayout.EndHorizontal(); GUILayout.EndVertical(); @@ -143,7 +143,7 @@ { //Display vessel rendezvous info GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - GUILayout.Label(v.vesselName, this.core.LabelStyles["center_bold"], GUILayout.ExpandWidth(true)); + GUILayout.Label(v.vesselName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); GUILayout.EndHorizontal(); if (v.situation == Vessel.Situations.ESCAPING || v.situation == Vessel.Situations.FLYING || v.situation == Vessel.Situations.ORBITING || v.situation == Vessel.Situations.SUB_ORBITAL) @@ -196,7 +196,7 @@ // Toadicus edit: added local sidereal longitude. GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label("Local Sidereal Longitude:"); - GUILayout.Label(LSL.ToString("F3") + "°", this.core.LabelStyles["right"]); + GUILayout.Label(LSL.ToString("F3") + "°", VOID_Styles.labelRight); GUILayout.EndHorizontal(); toggleExtendedOrbital.value = GUILayout.Toggle(toggleExtendedOrbital, "Extended info"); @@ -205,7 +205,7 @@ { GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label("Period:"); - GUILayout.Label(VOID_Tools.ConvertInterval(v.orbit.period), GUILayout.ExpandWidth(false)); + GUILayout.Label(VOID_Tools.FormatInterval(v.orbit.period), GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); @@ -267,7 +267,7 @@ else if (cb != null && v == null) { //Display CelstialBody rendezvous info - GUILayout.Label(cb.bodyName, this.core.LabelStyles["center_bold"]); + GUILayout.Label(cb.bodyName, VOID_Styles.labelCenterBold); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label("Ap/Pe:"); --- /dev/null +++ b/VOID_StageInfo.cs @@ -1,1 +1,218 @@ - +// VOID © 2014 toadicus +// +// This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a +// copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ + +using KerbalEngineer.VesselSimulator; +using KSP; +using System; +using System.Collections.Generic; +using System.Linq; +using ToadicusTools; +using UnityEngine; + +namespace VOID +{ + public class VOID_StageInfo : VOID_WindowModule + { + private Table stageTable; + + private Table.Column stageNumberCol; + private Table.Column stageDeltaVCol; + private Table.Column stageTotalDVCol; + private Table.Column stageInvertDVCol; + private Table.Column stageMassCol; + private Table.Column stageTotalMassCol; + private Table.Column stageThrustCol; + private Table.Column stageTWRCol; + + private bool stylesApplied; + private bool showBodyList; + + private Rect bodyListPos; + + private CelestialBody selectedBody; + [AVOID_SaveValue("bodyIdx")] + private VOID_SaveValue bodyIdx; + private int lastIdx; + + public VOID_StageInfo() : base() + { + this._Name = "Stage Information"; + this.defWidth = 200f; + this.bodyIdx = 4; + + this.stylesApplied = false; + this.showBodyList = false; + + this.bodyListPos = new Rect(); + + this.stageTable = new Table(); + + this.stageNumberCol = new Table.Column("Stage", 40f); + this.stageTable.Add(this.stageNumberCol); + + this.stageDeltaVCol = new Table.Column("DeltaV [m/s]", 60f); + this.stageDeltaVCol.Format = "S2"; + this.stageTable.Add(this.stageDeltaVCol); + + this.stageTotalDVCol = new Table.Column("Total ΔV [m/s]", 60f); + this.stageTotalDVCol.Format = "S2"; + this.stageTable.Add(this.stageTotalDVCol); + + this.stageInvertDVCol = new Table.Column("Invert ΔV [m/s]", 60f); + this.stageInvertDVCol.Format = "S2"; + this.stageTable.Add(this.stageInvertDVCol); + + this.stageMassCol = new Table.Column("Mass [Mg]", 60f); + this.stageMassCol.Format = "#.#"; + this.stageTable.Add(this.stageMassCol); + + this.stageTotalMassCol = new Table.Column("Total [Mg]", 60f); + this.stageTotalMassCol.Format = "#.#"; + this.stageTable.Add(this.stageTotalMassCol); + + this.stageThrustCol = new Table.Column("Thrust [N]", 60f); + this.stageThrustCol.Format = "S2"; + this.stageTable.Add(this.stageThrustCol); + + this.stageTWRCol = new Table.Column("T/W Ratio", 60f); + this.stageTWRCol.Format = "#.#"; + this.stageTable.Add(this.stageTWRCol); + } + + public override void DrawGUI() + { + base.DrawGUI(); + + if (this.showBodyList) + { + GUILayout.Window(core.windowID, this.bodyListPos, this.BodyPickerWindow, string.Empty); + } + } + + public override void ModuleWindow(int _) + { + if ( + HighLogic.LoadedSceneIsEditor || + (TimeWarp.WarpMode == TimeWarp.Modes.LOW) || + (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate) + ) + { + KerbalEngineer.VesselSimulator.SimManager.RequestSimulation(); + } + + if (!this.stylesApplied) + { + this.stageTable.ApplyCellStyle(VOID_Styles.labelCenter); + this.stageTable.ApplyHeaderStyle(VOID_Styles.labelCenterBold); + } + + this.stageTable.ClearColumns(); + + if (core.Stages == null || core.Stages.Length == 0) + { + GUILayout.BeginVertical(); + + GUILayout.Label("No stage data!"); + + GUILayout.EndVertical(); + + return; + } + + foreach (Stage stage in core.Stages) + { + if (stage.deltaV == 0 && stage.mass == 0) + { + continue; + } + + this.stageNumberCol.Add(stage.number); + + this.stageDeltaVCol.Add(stage.deltaV); + this.stageTotalDVCol.Add(stage.totalDeltaV); + this.stageInvertDVCol.Add(stage.inverseTotalDeltaV); + + this.stageMassCol.Add(stage.mass); + this.stageTotalMassCol.Add(stage.totalMass); + + this.stageThrustCol.Add(stage.thrust * 1000f); + this.stageTWRCol.Add(stage.thrustToWeight / (this.selectedBody ?? core.HomeBody).GeeASL); + } + + this.stageTable.Render(); + + if (core.sortedBodyList != null) + { + GUILayout.BeginHorizontal(); + + if (GUILayout.Button("◄")) + { + this.bodyIdx--; + } + + this.showBodyList = GUILayout.Toggle(this.showBodyList, (this.selectedBody ?? core.HomeBody).bodyName, GUI.skin.button); + Rect bodyButtonPos = GUILayoutUtility.GetLastRect(); + + if (Event.current.type == EventType.Repaint) + { + this.bodyListPos.width = bodyButtonPos.width; + this.bodyListPos.x = bodyButtonPos.xMin + this.WindowPos.xMin; + this.bodyListPos.y = bodyButtonPos.yMax + this.WindowPos.yMin; + } + + if (GUILayout.Button("►")) + { + this.bodyIdx++; + } + + this.bodyIdx %= core.sortedBodyList.Count; + + if (this.bodyIdx < 0) + { + this.bodyIdx += core.sortedBodyList.Count; + } + + if (this.lastIdx != this.bodyIdx) + { + this.lastIdx = this.bodyIdx; + this.selectedBody = core.sortedBodyList[this.bodyIdx]; + } + + GUILayout.EndHorizontal(); + } + + GUILayout.BeginHorizontal(); + + if ( + GUILayout.Button("Engineering data powered by VesselSimulator from KER.", + VOID_Styles.labelLink) + ) + { + Application.OpenURL("http://forum.kerbalspaceprogram.com/threads/18230"); + } + + GUILayout.EndHorizontal(); + + GUI.DragWindow(); + } + + private void BodyPickerWindow(int _) + { + foreach (CelestialBody body in core.sortedBodyList) + { + if (GUILayout.Button(body.bodyName, VOID_Styles.labelDefault)) + { + Debug.Log("Picked new body focus: " + body.bodyName); + this.bodyIdx = core.sortedBodyList.IndexOf(body); + this.showBodyList = false; + } + } + } + } + + public class VOID_StageInfoEditor : VOID_StageInfo, IVOID_EditorModule {} +} + + --- /dev/null +++ b/VOID_Styles.cs @@ -1,1 +1,129 @@ +// VOID +// +// cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using System; +using UnityEngine; + +namespace VOID +{ + public static class VOID_Styles + { + public static bool Ready + { + get; + private set; + } + + public static GUIStyle labelDefault + { + get; + private set; + } + + public static GUIStyle labelLink + { + get; + private set; + } + + public static GUIStyle labelCenter + { + get; + private set; + } + + public static GUIStyle labelCenterBold + { + get; + private set; + } + + public static GUIStyle labelGreen + { + get; + private set; + } + + public static GUIStyle labelHud + { + get; + private set; + } + + public static GUIStyle labelRight + { + get; + private set; + } + + public static GUIStyle labelRed + { + get; + private set; + } + + public static void OnSkinChanged() + { + labelDefault = new GUIStyle(GUI.skin.label); + + labelLink = new GUIStyle(GUI.skin.label); + labelLink.fontStyle = FontStyle.Italic; + labelLink.fontSize = (int)((float)labelLink.fontSize * .8f); + + labelCenter = new GUIStyle(GUI.skin.label); + labelCenter.normal.textColor = Color.white; + labelCenter.alignment = TextAnchor.UpperCenter; + + labelCenterBold = new GUIStyle(GUI.skin.label); + labelCenterBold.normal.textColor = Color.white; + labelCenterBold.alignment = TextAnchor.UpperCenter; + labelCenterBold.fontStyle = FontStyle.Bold; + + labelHud = new GUIStyle(labelDefault); + + labelRight = new GUIStyle(GUI.skin.label); + labelRight.normal.textColor = Color.white; + labelRight.alignment = TextAnchor.UpperRight; + + labelRed = new GUIStyle(GUI.skin.label); + labelRed.normal.textColor = Color.red; + + labelGreen = new GUIStyle(GUI.skin.label); + labelGreen.normal.textColor = Color.green; + + Ready = true; + } + + static VOID_Styles() + { + Ready = false; + } + } +} + + --- a/VOID_SurfAtmo.cs +++ b/VOID_SurfAtmo.cs @@ -65,6 +65,9 @@ this.precisionValues [idx]= (ushort)VOID_Data.terrainElevation.DoGUIHorizontal (this.precisionValues [idx]); idx++; + this.precisionValues[idx] = (ushort)VOID_Data.downrangeDistance.DoGUIHorizontal(this.precisionValues[idx]); + idx++; + this.precisionValues [idx]= (ushort)VOID_Data.surfVelocity.DoGUIHorizontal (this.precisionValues [idx]); idx++; @@ -76,7 +79,8 @@ VOID_Data.temperature.DoGUIHorizontal ("F2"); - VOID_Data.atmDensity.DoGUIHorizontal (3); + this.precisionValues [idx]= (ushort)VOID_Data.atmDensity.DoGUIHorizontal (this.precisionValues [idx]); + idx++; VOID_Data.atmPressure.DoGUIHorizontal ("F2"); @@ -104,100 +108,4 @@ base._SaveToConfig (config); } } - - public static partial class VOID_Data - { - public static readonly VOID_DoubleValue trueAltitude = new VOID_DoubleValue( - "Altitude (true)", - delegate() - { - double alt_true = core.vessel.orbit.altitude - core.vessel.terrainAltitude; - // HACK: This assumes that on worlds with oceans, all water is fixed at 0 m, - // and water covers the whole surface at 0 m. - if (core.vessel.terrainAltitude < 0 && core.vessel.mainBody.ocean ) - alt_true = core.vessel.orbit.altitude; - return alt_true; - }, - "m" - ); - - public static readonly VOID_StrValue surfLatitude = new VOID_StrValue( - "Latitude", - new Func (() => VOID_Tools.GetLatitudeString(core.vessel)) - ); - - public static readonly VOID_StrValue surfLongitude = new VOID_StrValue( - "Longitude", - new Func (() => VOID_Tools.GetLongitudeString(core.vessel)) - ); - - public static readonly VOID_StrValue vesselHeading = new VOID_StrValue( - "Heading", - delegate() - { - double heading = core.vessel.getSurfaceHeading(); - string cardinal = VOID_Tools.get_heading_text(heading); - - return string.Format( - "{0}° {1}", - heading.ToString("F2"), - cardinal - ); - } - ); - - public static readonly VOID_DoubleValue terrainElevation = new VOID_DoubleValue( - "Terrain elevation", - new Func (() => core.vessel.terrainAltitude), - "m" - ); - - public static readonly VOID_DoubleValue surfVelocity = new VOID_DoubleValue( - "Surface velocity", - new Func (() => core.vessel.srf_velocity.magnitude), - "m/s" - ); - - public static readonly VOID_DoubleValue vertVelocity = new VOID_DoubleValue( - "Vertical speed", - new Func (() => core.vessel.verticalSpeed), - "m/s" - ); - - public static readonly VOID_DoubleValue horzVelocity = new VOID_DoubleValue( - "Horizontal speed", - new Func (() => core.vessel.horizontalSrfSpeed), - "m/s" - ); - - public static readonly VOID_FloatValue temperature = new VOID_FloatValue( - "Temperature", - new Func (() => core.vessel.flightIntegrator.getExternalTemperature()), - "°C" - ); - - public static readonly VOID_DoubleValue atmDensity = new VOID_DoubleValue ( - "Atmosphere Density", - new Func (() => core.vessel.atmDensity * 1000f), - "g/m³" - ); - - public static readonly VOID_DoubleValue atmPressure = new VOID_DoubleValue ( - "Pressure", - new Func (() => core.vessel.staticPressure), - "atm" - ); - - public static readonly VOID_FloatValue atmLimit = new VOID_FloatValue( - "Atmosphere Limit", - new Func (() => core.vessel.mainBody.maxAtmosphereAltitude), - "m" - ); - - public static readonly VOID_StrValue currBiome = new VOID_StrValue( - "Biome", - new Func (() => VOID_Tools.GetBiome(core.vessel).name) - ); - - } } --- a/VOID_TWR.cs +++ b/VOID_TWR.cs @@ -14,8 +14,6 @@ { public class VOID_TWR : VOID_WindowModule { - private List sortedBodyList; - public VOID_TWR() : base() { this._Name = "IP Thrust-to-Weight Ratios"; @@ -29,31 +27,22 @@ (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate) ) { - Engineer.VesselSimulator.SimManager.RequestSimulation(); + KerbalEngineer.VesselSimulator.SimManager.RequestSimulation(); } GUILayout.BeginVertical(); - if (this.sortedBodyList == null) + if (core.sortedBodyList == null) { - if (FlightGlobals.Bodies != null && FlightGlobals.Bodies.Count > 0) - { - this.sortedBodyList = new List(FlightGlobals.Bodies); - this.sortedBodyList.Sort(new CBListComparer()); - this.sortedBodyList.Reverse(); + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - Debug.Log(string.Format("sortedBodyList: {0}", string.Join("\n\t", this.sortedBodyList.Select(b => b.bodyName).ToArray()))); - } - else - { - GUILayout.BeginHorizontal(); - GUILayout.Label("Unavailable."); - GUILayout.EndHorizontal(); - } + GUILayout.Label("Unavailable"); + + GUILayout.EndHorizontal(); } else { - foreach (CelestialBody body in this.sortedBodyList) + foreach (CelestialBody body in core.sortedBodyList) { GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); @@ -75,23 +64,6 @@ } public class VOID_EditorTWR : VOID_TWR, IVOID_EditorModule {} - - public static partial class VOID_Data - { - public static readonly VOID_DoubleValue nominalThrustWeight = new VOID_DoubleValue( - "Thrust-to-Weight Ratio", - delegate() - { - if (HighLogic.LoadedSceneIsEditor || currThrustWeight.Value == 0d) - { - return maxThrustWeight.Value; - } - - return currThrustWeight.Value; - }, - "" - ); - } } --- a/VOID_Tools.cs +++ b/VOID_Tools.cs @@ -95,13 +95,13 @@ #endregion #region VESSEL_EXTENSIONS_SCIENCE - public static CBAttributeMap.MapAttribute GetBiome(this Vessel vessel) - { - CBAttributeMap.MapAttribute mapAttribute; + public static CBAttributeMapSO.MapAttribute GetBiome(this Vessel vessel) + { + CBAttributeMapSO.MapAttribute mapAttribute; try { - CBAttributeMap BiomeMap = vessel.mainBody.BiomeMap; + CBAttributeMapSO BiomeMap = vessel.mainBody.BiomeMap; double lat = vessel.latitude * Math.PI / 180d; double lon = vessel.longitude * Math.PI / 180d; @@ -162,7 +162,7 @@ } catch (NullReferenceException) { - mapAttribute = new CBAttributeMap.MapAttribute(); + mapAttribute = new CBAttributeMapSO.MapAttribute(); mapAttribute.name = "N/A"; } @@ -334,15 +334,31 @@ { func(id); } - catch (ArgumentException ex) + #if DEBUG + catch (ArgumentException) + #else + catch (ArgumentException) + #endif { Debug.LogWarning( - string.Format("[{0}]: ArgumentException caught during window call.", func.Target.GetType().Name) - ); + string.Format("[{0}]: ArgumentException caught during window call. This is not a bug.", + func.Target.GetType().Name + )); + /*#if DEBUG Debug.LogException(ex); #endif*/ } + catch (Exception ex) + { + Debug.LogError( + string.Format("[{0}]: {1} caught during window call.\nMessage:\n{2}\nStackTrace:\n{3}", + func.Target.GetType().Name, + ex.GetType().Name, + ex.Message, + ex.StackTrace + )); + } }; } @@ -350,78 +366,171 @@ } /// - /// Converts the interval given in seconds to a human-friendly - /// time period in [years], [days], hours, minutes, and seconds. + /// Formats the interval given in seconds as a human-friendly + /// time period in [[[[years, ]days, ]hours, ]minutes, and ]seconds. /// /// Uses sidereal days, since "6 hours per day" is the Kerbal standard. /// /// Human readable interval /// - public static string ConvertInterval(double seconds) - { - double SecondsPerMinute = 60d; - double SecondsPerHour = 3600d; - double SecondsPerDay; - double SecondsPerYear; - - if (GameSettings.KERBIN_TIME) - { - SecondsPerDay = 21600d; - SecondsPerYear = 9203545d; - } - else - { - SecondsPerDay = 86164.1d; - SecondsPerYear = 31558149d; - } - - int years; - int days; - int hours; - int minutes; - - years = (int)(seconds / SecondsPerYear); - - seconds %= SecondsPerYear; - - days = (int)(seconds / SecondsPerDay); - - seconds %= SecondsPerDay; - - hours = (int)(seconds / SecondsPerHour); - - seconds %= SecondsPerHour; - - minutes = (int)(seconds / SecondsPerMinute); - - seconds %= SecondsPerMinute; - - string format_1 = string.Intern("{0:D1}y {1:D1}d {2:D2}h {3:D2}m {4:00.0}s"); - string format_2 = string.Intern("{0:D1}d {1:D2}h {2:D2}m {3:00.0}s"); - string format_3 = string.Intern("{0:D2}h {1:D2}m {2:00.0}s"); - string format_4 = string.Intern("{0:D2}m {1:00.0}s"); - string format_5 = string.Intern("{0:00.0}s"); - - if (years > 0) - { - return string.Format(format_1, years, days, hours, minutes, seconds); - } - else if (days > 0) - { - return string.Format(format_2, days, hours, minutes, seconds); - } - else if (hours > 0) - { - return string.Format(format_3, hours, minutes, seconds); - } - else if (minutes > 0) - { - return string.Format(format_4, minutes, seconds); - } - else - { - return string.Format(format_5, seconds); - } + public static string FormatInterval(double seconds) + { + return UnpackedTime.FromSeconds(seconds).FormatAsSpan(); + } + + /// + /// Formats the date given in seconds since epoch as a human-friendly + /// date in the format YY, DD, HH:MM:SS + /// + /// The date. + /// Seconds. + public static string FormatDate(double seconds) + { + return UnpackedTime.FromSeconds(seconds).FormatAsDate(); + } + + public class UnpackedTime + { + public const double SecondsPerMinute = 60d; + public const double SecondsPerHour = 3600d; + + public static double SecondsPerDay + { + get + { + if (GameSettings.KERBIN_TIME) + { + return 21600d; + } + else + { + return 86164.1d; + } + } + } + + public static double SecondsPerYear + { + get + { + if (GameSettings.KERBIN_TIME) + { + return 9203545d; + } + else + { + return 31558149d; + } + } + } + + public static UnpackedTime FromSeconds(double seconds) + { + UnpackedTime time = new UnpackedTime(); + + time.years = (int)(seconds / SecondsPerYear); + + seconds %= SecondsPerYear; + + time.days = (int)(seconds / SecondsPerDay); + + seconds %= SecondsPerDay; + + time.hours = (int)(seconds / SecondsPerHour); + + seconds %= SecondsPerHour; + + time.minutes = (int)(seconds / SecondsPerMinute); + + seconds %= SecondsPerMinute; + + time.seconds = seconds; + + return time; + } + + public static explicit operator UnpackedTime(double seconds) + { + return FromSeconds(seconds); + } + + public static implicit operator double(UnpackedTime time) + { + return time.ToSeconds(); + } + + public static UnpackedTime operator+ (UnpackedTime lhs, UnpackedTime rhs) + { + return FromSeconds(lhs.ToSeconds() + rhs.ToSeconds()); + } + + public static UnpackedTime operator- (UnpackedTime lhs, UnpackedTime rhs) + { + return FromSeconds(lhs.ToSeconds() - rhs.ToSeconds()); + } + + public int years; + public int days; + public int hours; + public int minutes; + public double seconds; + + public double ToSeconds() + { + return (double)years * SecondsPerYear + + (double)days * SecondsPerDay + + (double)hours * SecondsPerHour + + (double)minutes * SecondsPerMinute + + seconds; + } + + public string FormatAsSpan() + { + string format_1 = "{0:D1}y {1:D1}d {2:D2}h {3:D2}m {4:00.0}s"; + string format_2 = "{0:D1}d {1:D2}h {2:D2}m {3:00.0}s"; + string format_3 = "{0:D2}h {1:D2}m {2:00.0}s"; + string format_4 = "{0:D2}m {1:00.0}s"; + string format_5 = "{0:00.0}s"; + + if (this.years > 0) + { + return string.Format(format_1, this.years, this.days, this.hours, this.minutes, this.seconds); + } + else if (this.days > 0) + { + return string.Format(format_2, this.days, this.hours, this.minutes, this.seconds); + } + else if (this.hours > 0) + { + return string.Format(format_3, this.hours, this.minutes, this.seconds); + } + else if (this.minutes > 0) + { + return string.Format(format_4, this.minutes, this.seconds); + } + else + { + return string.Format(format_5, this.seconds); + } + } + + public string FormatAsDate() + { + string format = "Y{0:D1}, D{1:D1} {2:D2}:{3:D2}:{4:00.0}s"; + + return string.Format(format, years, days, hours, minutes, seconds); + } + + public UnpackedTime(int years, int days, int hours, int minutes, double seconds) + { + this.years = years; + this.days = days; + this.hours = hours; + this.minutes = minutes; + this.seconds = seconds; + } + + public UnpackedTime() : this(0, 0, 0, 0, 0d) {} } public static string UppercaseFirst(string s) --- a/VOID_Transfer.cs +++ b/VOID_Transfer.cs @@ -39,7 +39,7 @@ { protected List selectedBodies = new List(); - public VOID_Transfer() + public VOID_Transfer() : base() { this._Name = "Transfer Angle Information"; --- a/VOID_VesselInfo.cs +++ b/VOID_VesselInfo.cs @@ -26,8 +26,8 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -using Engineer.VesselSimulator; -using Engineer.Extensions; +using KerbalEngineer.VesselSimulator; +using KerbalEngineer.Extensions; using KSP; using System; using System.Collections.Generic; @@ -57,7 +57,7 @@ GUILayout.Label( vessel.vesselName, - core.LabelStyles["center_bold"], + VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); VOID_Data.geeForce.DoGUIHorizontal ("F2"); @@ -66,7 +66,9 @@ VOID_Data.totalMass.DoGUIHorizontal ("F3"); - VOID_Data.comboResourceMass.DoGUIHorizontal (); + VOID_Data.stageResourceMass.DoGUIHorizontal("F2"); + + VOID_Data.resourceMass.DoGUIHorizontal("F2"); VOID_Data.stageDeltaV.DoGUIHorizontal (3, false); @@ -87,240 +89,5 @@ GUI.DragWindow(); } } - - public static partial class VOID_Data - { - public static readonly VOID_DoubleValue geeForce = new VOID_DoubleValue( - "G-force", - new Func(() => core.vessel.geeForce), - "gees" - ); - - public static readonly VOID_IntValue partCount = new VOID_IntValue( - "Parts", - new Func(() => core.vessel.Parts.Count), - "" - ); - - public static readonly VOID_DoubleValue totalMass = new VOID_DoubleValue( - "Total Mass", - delegate() - { - if (SimManager.Stages == null || SimManager.LastStage == null) - { - return double.NaN; - } - - return SimManager.LastStage.totalMass; - }, - "tons" - ); - - public static readonly VOID_DoubleValue resourceMass = new VOID_DoubleValue( - "Resource Mass", - delegate() - { - if (SimManager.Stages == null || SimManager.LastStage == null) - { - return double.NaN; - } - - return SimManager.LastStage.totalMass - SimManager.LastStage.totalBaseMass; - }, - "tons" - ); - - public static readonly VOID_DoubleValue stageResourceMass = new VOID_DoubleValue( - "Resource Mass (Current Stage)", - delegate() - { - if (SimManager.LastStage == null) - { - return double.NaN; - } - - return SimManager.LastStage.mass - SimManager.LastStage.baseMass; - }, - "tons" - ); - - public static readonly VOID_StrValue comboResourceMass = new VOID_StrValue( - "Resource Mass (curr / total)", - delegate() - { - return string.Format("{0} / {1}", - stageResourceMass.ValueUnitString("F3"), - resourceMass.ValueUnitString("F3") - ); - } - ); - - public static readonly VOID_DoubleValue stageDeltaV = new VOID_DoubleValue( - "DeltaV (Current Stage)", - delegate() - { - if (SimManager.Stages == null || SimManager.LastStage == null) - return double.NaN; - return SimManager.LastStage.deltaV; - }, - "m/s" - ); - - public static readonly VOID_DoubleValue totalDeltaV = new VOID_DoubleValue( - "DeltaV (Total)", - delegate() - { - if (SimManager.Stages == null || SimManager.LastStage == null) - return double.NaN; - return SimManager.LastStage.totalDeltaV; - }, - "m/s" - ); - - public static readonly VOID_FloatValue mainThrottle = new VOID_FloatValue( - "Throttle", - new Func(() => core.vessel.ctrlState.mainThrottle * 100f), - "%" - ); - - public static readonly VOID_StrValue currmaxThrust = new VOID_StrValue( - "Thrust (curr/max)", - delegate() - { - if (SimManager.Stages == null || SimManager.LastStage == null) - return "N/A"; - - double currThrust = SimManager.LastStage.actualThrust; - double maxThrust = SimManager.LastStage.thrust; - - return string.Format( - "{0} / {1}", - currThrust.ToString("F1"), - maxThrust.ToString("F1") - ); - } - ); - - public static readonly VOID_DoubleValue currThrustWeight = new VOID_DoubleValue( - "T:W Ratio", - delegate() - { - if (SimManager.LastStage == null) - { - return double.NaN; - } - - return SimManager.LastStage.actualThrustToWeight; - }, - "" - ); - - public static readonly VOID_DoubleValue maxThrustWeight = new VOID_DoubleValue( - "T:W Ratio", - delegate() - { - if (SimManager.LastStage == null) - { - return double.NaN; - } - - return SimManager.LastStage.thrustToWeight; - }, - "" - ); - - public static readonly VOID_StrValue currmaxThrustWeight = new VOID_StrValue( - "T:W (curr/max)", - delegate() - { - if (SimManager.Stages == null || SimManager.LastStage == null) - return "N/A"; - - return string.Format( - "{0} / {1}", - (VOID_Data.currThrustWeight.Value).ToString("F2"), - (VOID_Data.maxThrustWeight.Value).ToString("F2") - ); - } - ); - - public static readonly VOID_DoubleValue surfaceThrustWeight = new VOID_DoubleValue( - "Max T:W @ surface", - delegate() - { - if (SimManager.Stages == null || SimManager.LastStage == null) - return double.NaN; - - double maxThrust = SimManager.LastStage.thrust; - double mass = SimManager.LastStage.totalMass; - double gravity = (VOID_Core.Constant_G * core.vessel.mainBody.Mass) / - (core.vessel.mainBody.Radius * core.vessel.mainBody.Radius); - double weight = mass * gravity; - - return maxThrust / weight; - }, - "" - ); - - public static readonly VOID_StrValue intakeAirStatus = new VOID_StrValue( - "Intake Air (Curr / Req)", - delegate() - { - double currentAmount; - double currentRequirement; - - currentAmount = 0d; - currentRequirement = 0d; - - foreach (Part part in core.vessel.Parts) - { - if (part.enabled) - { - ModuleEngines engineModule; - ModuleEnginesFX enginesFXModule; - List propellantList = null; - - if (part.tryGetFirstModuleOfType(out engineModule)) - { - propellantList = engineModule.propellants; - } - else if (part.tryGetFirstModuleOfType(out enginesFXModule)) - { - propellantList = enginesFXModule.propellants; - } - - if (propellantList != null) - { - foreach (Propellant propellant in propellantList) - { - if (propellant.name == "IntakeAir") - { - currentRequirement += propellant.currentRequirement / TimeWarp.fixedDeltaTime; - break; - } - } - } - } - - ModuleResourceIntake intakeModule; - - if (part.enabled && part.tryGetFirstModuleOfType(out intakeModule)) - { - if (intakeModule.resourceName == "IntakeAir") - { - currentAmount += intakeModule.airFlow; - } - } - } - - if (currentAmount == 0 && currentRequirement == 0) - { - return "N/A"; - } - - return string.Format("{0:F3} / {1:F3}", currentAmount, currentRequirement); - } - ); - } } --- a/VOID_VesselRegister.cs +++ b/VOID_VesselRegister.cs @@ -58,7 +58,7 @@ } } - public VOID_VesselRegister() + public VOID_VesselRegister() : base() { this._Name = "Vessel Register"; @@ -82,7 +82,7 @@ selectedBodyIdx--; if (selectedBodyIdx < 0) selectedBodyIdx = this.core.allBodies.Count - 1; } - GUILayout.Label(this.core.allBodies[selectedBodyIdx].bodyName, this.core.LabelStyles["center_bold"], GUILayout.ExpandWidth(true)); + GUILayout.Label(this.core.allBodies[selectedBodyIdx].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); if (GUILayout.Button(">")) { selectedBodyIdx++; @@ -98,7 +98,7 @@ selectedVesselTypeIdx--; if (selectedVesselTypeIdx < 0) selectedVesselTypeIdx = this.core.allVesselTypes.Count - 1; } - GUILayout.Label(this.core.allVesselTypes[selectedVesselTypeIdx].ToString(), this.core.LabelStyles["center_bold"], GUILayout.ExpandWidth(true)); + GUILayout.Label(this.core.allVesselTypes[selectedVesselTypeIdx].ToString(), VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); if (GUILayout.Button(">")) { selectedVesselTypeIdx++; @@ -116,7 +116,7 @@ GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label( VOID_Tools.UppercaseFirst(vesselSituation) + " " + selectedVesselType.ToString() + "s @ " + seletedBody.bodyName, - this.core.LabelStyles["center"], + VOID_Styles.labelCenter, GUILayout.ExpandWidth(true)); GUILayout.EndHorizontal(); @@ -142,7 +142,7 @@ if (_selectedVessel != v) { _selectedVessel = v; //set clicked vessel as selected_vessel - this._Active.value = true; //turn bool on to open the window if closed + this.toggleActive = true; //turn bool on to open the window if closed } else {