Moved all VOID_Data entries to a common VOID_Data class file, then organized and formatted it.
Moved all VOID_Data entries to a common VOID_Data class file, then organized and formatted it.

<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug_win</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug_win</Configuration>
<ProductVersion>8.0.30703</ProductVersion> <ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{45ACC1CC-942C-4A66-BFC7-8BE375938B18}</ProjectGuid> <ProjectGuid>{45ACC1CC-942C-4A66-BFC7-8BE375938B18}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RootNamespace>VOID</RootNamespace> <RootNamespace>VOID</RootNamespace>
<AssemblyName>VOID</AssemblyName> <AssemblyName>VOID</AssemblyName>
<CodePage>65001</CodePage> <CodePage>65001</CodePage>
<UseMSBuildEngine>False</UseMSBuildEngine> <UseMSBuildEngine>False</UseMSBuildEngine>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ReleaseVersion>0.11</ReleaseVersion> <ReleaseVersion>0.11</ReleaseVersion>
<SynchReleaseVersion>false</SynchReleaseVersion> <SynchReleaseVersion>false</SynchReleaseVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_win|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_win|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath> <OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG; TRACE</DefineConstants> <DefineConstants>DEBUG; TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause> <ConsolePause>false</ConsolePause>
<CustomCommands> <CustomCommands>
<CustomCommands> <CustomCommands>
<Command type="AfterBuild" command="xcopy /Y ${TargetFile} ..\..\..\Games\KSP_win\GameData\VOID\Plugins\" /> <Command type="AfterBuild" command="xcopy /Y ${TargetFile} ..\..\..\Games\KSP_win\GameData\VOID\Plugins\" />
</CustomCommands> </CustomCommands>
</CustomCommands> </CustomCommands>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_win|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_win|AnyCPU' ">
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Release</OutputPath> <OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause> <ConsolePause>false</ConsolePause>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<CustomCommands> <CustomCommands>
<CustomCommands> <CustomCommands>
<Command type="AfterBuild" command="xcopy /Y ${TargetFile} ..\..\..\Games\KSP_win\GameData\VOID\Plugins\" /> <Command type="AfterBuild" command="xcopy /Y ${TargetFile} ..\..\..\Games\KSP_win\GameData\VOID\Plugins\" />
</CustomCommands> </CustomCommands>
</CustomCommands> </CustomCommands>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_linux|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_linux|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath> <OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG; TRACE</DefineConstants> <DefineConstants>DEBUG; TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause> <ConsolePause>false</ConsolePause>
<CustomCommands> <CustomCommands>
<CustomCommands> <CustomCommands>
<Command type="AfterBuild" command="cp -afv ${TargetFile} /opt/games/KSP_linux/GameData/${ProjectName}/Plugins/" /> <Command type="AfterBuild" command="cp -afv ${TargetFile} /opt/games/KSP_linux/GameData/${ProjectName}/Plugins/" />
</CustomCommands> </CustomCommands>
</CustomCommands> </CustomCommands>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_linux|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_linux|AnyCPU' ">
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Release</OutputPath> <OutputPath>bin\Release</OutputPath>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause> <ConsolePause>false</ConsolePause>
<CustomCommands> <CustomCommands>
<CustomCommands> <CustomCommands>
<Command type="AfterBuild" command="cp -afv ${TargetFile} /opt/games/KSP_linux/GameData/${ProjectName}/Plugins/" /> <Command type="AfterBuild" command="cp -afv ${TargetFile} /opt/games/KSP_linux/GameData/${ProjectName}/Plugins/" />
</CustomCommands> </CustomCommands>
</CustomCommands> </CustomCommands>
</PropertyGroup> </PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup> <ItemGroup>
<Compile Include="IVOID_Module.cs" /> <Compile Include="IVOID_Module.cs" />
<Compile Include="VOIDFlightMaster.cs" /> <Compile Include="VOIDFlightMaster.cs" />
<Compile Include="VOID_Core.cs" /> <Compile Include="VOID_Core.cs" />
<Compile Include="VOID_Module.cs" /> <Compile Include="VOID_Module.cs" />
<Compile Include="VOID_HUD.cs" /> <Compile Include="VOID_HUD.cs" />
<Compile Include="VOID_SaveValue.cs" /> <Compile Include="VOID_SaveValue.cs" />
<Compile Include="VOID_Orbital.cs" /> <Compile Include="VOID_Orbital.cs" />
<Compile Include="VOID_SurfAtmo.cs" /> <Compile Include="VOID_SurfAtmo.cs" />
<Compile Include="VOID_VesselInfo.cs" /> <Compile Include="VOID_VesselInfo.cs" />
<Compile Include="VOID_Transfer.cs" /> <Compile Include="VOID_Transfer.cs" />
<Compile Include="VOID_CBInfoBrowser.cs" /> <Compile Include="VOID_CBInfoBrowser.cs" />
<Compile Include="VOID_Rendezvous.cs" /> <Compile Include="VOID_Rendezvous.cs" />
<Compile Include="VOID_VesselRegister.cs" /> <Compile Include="VOID_VesselRegister.cs" />
<Compile Include="VOID_DataLogger.cs" /> <Compile Include="VOID_DataLogger.cs" />
<Compile Include="VOID_EditorCore.cs" /> <Compile Include="VOID_EditorCore.cs" />
<Compile Include="VOID_EditorHUD.cs" /> <Compile Include="VOID_EditorHUD.cs" />
<Compile Include="VOID_DataValue.cs" /> <Compile Include="VOID_DataValue.cs" />
<Compile Include="VOIDEditorMaster.cs" /> <Compile Include="VOIDEditorMaster.cs" />
<Compile Include="VOID_Tools.cs" /> <Compile Include="VOID_Tools.cs" />
<Compile Include="VOID_Localization.cs" /> <Compile Include="VOID_Localization.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="VOID_HUDAdvanced.cs" /> <Compile Include="VOID_HUDAdvanced.cs" />
<Compile Include="VOID_TWR.cs" /> <Compile Include="VOID_TWR.cs" />
<Compile Include="VOID_CareerStatus.cs" /> <Compile Include="VOID_CareerStatus.cs" />
<Compile Include="VOID_StageInfo.cs" /> <Compile Include="VOID_StageInfo.cs" />
<Compile Include="VOID_Styles.cs" /> <Compile Include="VOID_Styles.cs" />
  <Compile Include="VOID_Data.cs" />
</ItemGroup> </ItemGroup>
<ProjectExtensions> <ProjectExtensions>
<MonoDevelop> <MonoDevelop>
<Properties> <Properties>
<Policies> <Policies>
<TextStylePolicy FileWidth="120" TabsToSpaces="False" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" /> <TextStylePolicy FileWidth="120" TabsToSpaces="False" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
</Policies> </Policies>
</Properties> </Properties>
</MonoDevelop> </MonoDevelop>
</ProjectExtensions> </ProjectExtensions>
<ItemGroup> <ItemGroup>
<Reference Include="System"> <Reference Include="System">
<HintPath>..\_KSPAssemblies\System.dll</HintPath> <HintPath>..\_KSPAssemblies\System.dll</HintPath>
</Reference> </Reference>
<Reference Include="Assembly-CSharp"> <Reference Include="Assembly-CSharp">
<HintPath>..\_KSPAssemblies\Assembly-CSharp.dll</HintPath> <HintPath>..\_KSPAssemblies\Assembly-CSharp.dll</HintPath>
</Reference> </Reference>
<Reference Include="UnityEngine"> <Reference Include="UnityEngine">
<HintPath>..\_KSPAssemblies\UnityEngine.dll</HintPath> <HintPath>..\_KSPAssemblies\UnityEngine.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ToadicusTools\ToadicusTools.csproj"> <ProjectReference Include="..\ToadicusTools\ToadicusTools.csproj">
<Project>{D48A5542-6655-4149-BC27-B27DF0466F1C}</Project> <Project>{D48A5542-6655-4149-BC27-B27DF0466F1C}</Project>
<Name>ToadicusTools</Name> <Name>ToadicusTools</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\VesselSimulator\VesselSimulator.csproj"> <ProjectReference Include="..\VesselSimulator\VesselSimulator.csproj">
<Project>{30FD6C0B-D36E-462F-B0FF-F0FAC9C666CF}</Project> <Project>{30FD6C0B-D36E-462F-B0FF-F0FAC9C666CF}</Project>
<Name>VesselSimulator</Name> <Name>VesselSimulator</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
</Project> </Project>
   
// VOID // VOID
// //
// VOID_CareerStatus.cs // VOID_CareerStatus.cs
// //
// Copyright © 2014, toadicus // Copyright © 2014, toadicus
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 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 // this list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be used // 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. // 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, // 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 // 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, // 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 // 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, // 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 // 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. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
using KSP; using KSP;
using System; using System;
using System.Text; using System.Text;
using ToadicusTools; using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_CareerStatus : VOID_WindowModule public class VOID_CareerStatus : VOID_WindowModule
{ {
public static VOID_CareerStatus Instance public static VOID_CareerStatus Instance
{ {
get; get;
private set; private set;
} }
   
public static string formatDelta(double delta) public static string formatDelta(double delta)
{ {
if (delta > 0) if (delta > 0)
{ {
return string.Format("<color='green'>{0:#,#.##}↑</color>", delta); return string.Format("<color='green'>{0:#,#.##}↑</color>", delta);
} }
else if (delta < 0) else if (delta < 0)
{ {
return string.Format("<color='red'>{0:#,#.##}↓</color>", delta); return string.Format("<color='red'>{0:#,#.##}↓</color>", delta);
} }
else else
{ {
return string.Intern("0"); return string.Intern("0");
} }
} }
   
public static string formatDelta(float delta) public static string formatDelta(float delta)
{ {
return formatDelta((double)delta); return formatDelta((double)delta);
} }
   
private GUIContent fundsContent; private GUIContent fundsContent;
private GUIContent repContent; private GUIContent repContent;
private GUIContent scienceContent; private GUIContent scienceContent;
   
private Texture2D fundsIconGreen; private Texture2D fundsIconGreen;
private Texture2D fundsIconRed; private Texture2D fundsIconRed;
private Texture2D reputationIconGreen; private Texture2D reputationIconGreen;
private Texture2D reputationIconRed; private Texture2D reputationIconRed;
private Texture2D scienceIcon; private Texture2D scienceIcon;
   
public override bool toggleActive public override bool toggleActive
{ {
get get
{ {
switch (HighLogic.CurrentGame.Mode) switch (HighLogic.CurrentGame.Mode)
{ {
case Game.Modes.CAREER: case Game.Modes.CAREER:
case Game.Modes.SCIENCE_SANDBOX: case Game.Modes.SCIENCE_SANDBOX:
return base.toggleActive; return base.toggleActive;
default: default:
return false; return false;
} }
} }
set set
{ {
switch (HighLogic.CurrentGame.Mode) switch (HighLogic.CurrentGame.Mode)
{ {
case Game.Modes.CAREER: case Game.Modes.CAREER:
case Game.Modes.SCIENCE_SANDBOX: case Game.Modes.SCIENCE_SANDBOX:
base.toggleActive = value; base.toggleActive = value;
break; break;
default: default:
return; return;
} }
} }
} }
   
public double lastFundsChange public double lastFundsChange
{ {
get; get;
private set; private set;
} }
   
public float lastRepChange public float lastRepChange
{ {
get; get;
private set; private set;
} }
   
public float lastScienceChange public float lastScienceChange
{ {
get; get;
private set; private set;
} }
   
public double currentFunds public double currentFunds
{ {
get; get;
private set; private set;
} }
   
public float currentReputation public float currentReputation
{ {
get; get;
private set; private set;
} }
   
public float currentScience public float currentScience
{ {
get; get;
private set; private set;
} }
   
public override void ModuleWindow(int _) public override void ModuleWindow(int _)
{ {
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label(VOID_Data.fundingStatus.Label); GUILayout.Label(VOID_Data.fundingStatus.Label);
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
this.fundsContent.text = VOID_Data.fundingStatus.Value; this.fundsContent.text = VOID_Data.fundingStatus.Value;
GUILayout.Label(this.fundsContent, GUILayout.ExpandWidth(false)); GUILayout.Label(this.fundsContent, GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label(VOID_Data.reputationStatus.Label); GUILayout.Label(VOID_Data.reputationStatus.Label);
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
this.repContent.text = VOID_Data.reputationStatus.Value; this.repContent.text = VOID_Data.reputationStatus.Value;
GUILayout.Label(this.repContent, GUILayout.ExpandWidth(false)); GUILayout.Label(this.repContent, GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label(VOID_Data.scienceStatus.Label); GUILayout.Label(VOID_Data.scienceStatus.Label);
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
this.scienceContent.text = VOID_Data.scienceStatus.Value; this.scienceContent.text = VOID_Data.scienceStatus.Value;
GUILayout.Label(this.scienceContent, GUILayout.ExpandWidth(false)); GUILayout.Label(this.scienceContent, GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.EndVertical(); GUILayout.EndVertical();
   
GUI.DragWindow(); GUI.DragWindow();
} }
   
// TODO: Update event handlers to do something useful with the new "reasons" parameter. // TODO: Update event handlers to do something useful with the new "reasons" parameter.
private void onFundsChange(double newValue, TransactionReasons reasons) private void onFundsChange(double newValue, TransactionReasons reasons)
{ {
this.lastFundsChange = newValue - this.currentFunds; this.lastFundsChange = newValue - this.currentFunds;
this.currentFunds = newValue; this.currentFunds = newValue;
} }
   
private void onRepChange(float newValue, TransactionReasons reasons) private void onRepChange(float newValue, TransactionReasons reasons)
{ {
this.lastRepChange = newValue - this.currentReputation; this.lastRepChange = newValue - this.currentReputation;
this.currentReputation = newValue; this.currentReputation = newValue;
} }
   
private void onScienceChange(float newValue, TransactionReasons reasons) private void onScienceChange(float newValue, TransactionReasons reasons)
{ {
this.lastScienceChange = newValue - this.currentScience; this.lastScienceChange = newValue - this.currentScience;
this.currentScience = newValue; this.currentScience = newValue;
} }
   
/* /*
* MissionRecoveryDialog::fundsIconGreen.name: UiElements_05 * MissionRecoveryDialog::fundsIconGreen.name: UiElements_05
* MissionRecoveryDialog::fundsIconRed.name: UiElements_06 * MissionRecoveryDialog::fundsIconRed.name: UiElements_06
* MissionRecoveryDialog::reputationIconGreen.name: UiElements_07 * MissionRecoveryDialog::reputationIconGreen.name: UiElements_07
* MissionRecoveryDialog::reputationIconRed.name: UiElements_08 * MissionRecoveryDialog::reputationIconRed.name: UiElements_08
* MissionRecoveryDialog::scienceIcon.name: UiElements_12 * MissionRecoveryDialog::scienceIcon.name: UiElements_12
* */ * */
public VOID_CareerStatus() : base() public VOID_CareerStatus() : base()
{ {
VOID_CareerStatus.Instance = this; VOID_CareerStatus.Instance = this;
   
this._Name = "Career Status"; this._Name = "Career Status";
   
GameEvents.OnFundsChanged.Add(this.onFundsChange); GameEvents.OnFundsChanged.Add(this.onFundsChange);
GameEvents.OnReputationChanged.Add(this.onRepChange); GameEvents.OnReputationChanged.Add(this.onRepChange);
GameEvents.OnScienceChanged.Add(this.onScienceChange); GameEvents.OnScienceChanged.Add(this.onScienceChange);
   
bool texturesLoaded; bool texturesLoaded;
   
texturesLoaded = IOTools.LoadTexture(out this.fundsIconGreen, "VOID/Textures/fundsgreen.png", 10, 18); 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.fundsIconRed, "VOID/Textures/fundsred.png", 10, 18);
texturesLoaded &= IOTools.LoadTexture(out this.reputationIconGreen, "VOID/Textures/repgreen.png", 16, 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.reputationIconRed, "VOID/Textures/repred.png", 16, 18);
texturesLoaded &= IOTools.LoadTexture(out this.scienceIcon, "VOID/Textures/science.png", 16, 18); texturesLoaded &= IOTools.LoadTexture(out this.scienceIcon, "VOID/Textures/science.png", 16, 18);
   
this.fundsContent = new GUIContent(); this.fundsContent = new GUIContent();
this.repContent = new GUIContent(); this.repContent = new GUIContent();
this.scienceContent = new GUIContent(); this.scienceContent = new GUIContent();
   
if (texturesLoaded) if (texturesLoaded)
{ {
this.fundsContent.image = this.fundsIconGreen; this.fundsContent.image = this.fundsIconGreen;
this.repContent.image = this.reputationIconGreen; this.repContent.image = this.reputationIconGreen;
this.scienceContent.image = this.scienceIcon; this.scienceContent.image = this.scienceIcon;
} }
   
this.currentFunds = Funding.Instance != null ? Funding.Instance.Funds : double.NaN; this.currentFunds = Funding.Instance != null ? Funding.Instance.Funds : double.NaN;
this.currentReputation = Reputation.Instance != null ? Reputation.Instance.reputation : float.NaN; this.currentReputation = Reputation.Instance != null ? Reputation.Instance.reputation : float.NaN;
this.currentScience = ResearchAndDevelopment.Instance != null ? this.currentScience = ResearchAndDevelopment.Instance != null ?
ResearchAndDevelopment.Instance.Science : float.NaN; ResearchAndDevelopment.Instance.Science : float.NaN;
} }
   
~VOID_CareerStatus() ~VOID_CareerStatus()
{ {
GameEvents.OnFundsChanged.Remove(this.onFundsChange); GameEvents.OnFundsChanged.Remove(this.onFundsChange);
GameEvents.OnReputationChanged.Remove(this.onRepChange); GameEvents.OnReputationChanged.Remove(this.onRepChange);
GameEvents.OnScienceChanged.Remove(this.onScienceChange); GameEvents.OnScienceChanged.Remove(this.onScienceChange);
   
VOID_CareerStatus.Instance = null; VOID_CareerStatus.Instance = null;
} }
} }
   
public static partial class VOID_Data  
{  
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)  
);  
}  
);  
}  
} }
   
   
// VOID // VOID
// //
// VOID_Core.cs // VOID_Core.cs
// //
// Copyright © 2014, toadicus // Copyright © 2014, toadicus
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 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 // this list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be used // 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. // 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, // 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 // 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, // 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 // 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, // 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 // 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. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
using Engineer.VesselSimulator; using Engineer.VesselSimulator;
using KSP; using KSP;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using ToadicusTools; using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_Core : VOID_Module, IVOID_Module public class VOID_Core : VOID_Module, IVOID_Module
{ {
#region Singleton Members #region Singleton Members
/* /*
* Static Members * Static Members
* */ * */
protected static bool _initialized = false; protected static bool _initialized = false;
   
public static bool Initialized public static bool Initialized
{ {
get get
{ {
return _initialized; return _initialized;
} }
} }
   
protected static VOID_Core _instance; protected static VOID_Core _instance;
   
public static VOID_Core Instance public static VOID_Core Instance
{ {
get get
{ {
if (_instance == null) if (_instance == null)
{ {
_instance = new VOID_Core(); _instance = new VOID_Core();
_initialized = true; _initialized = true;
} }
return _instance; return _instance;
} }
} }
   
public static void Reset() public static void Reset()
{ {
_instance.StopGUI(); _instance.StopGUI();
_instance.Dispose(); _instance.Dispose();
_instance = null; _instance = null;
_initialized = false; _initialized = false;
} }
#endregion #endregion
   
public static readonly double Constant_G = 6.674e-11; public static readonly double Constant_G = 6.674e-11;
   
/* /*
* Fields * Fields
* */ * */
protected string VoidName = "VOID"; protected string VoidName = "VOID";
protected string VoidVersion; protected string VoidVersion;
   
protected bool _factoryReset = false; protected bool _factoryReset = false;
   
[AVOID_SaveValue("configValue")] [AVOID_SaveValue("configValue")]
protected VOID_SaveValue<int> configVersion = 1; protected VOID_SaveValue<int> configVersion = 1;
   
protected List<IVOID_Module> _modules = new List<IVOID_Module>(); protected List<IVOID_Module> _modules = new List<IVOID_Module>();
protected bool _modulesLoaded = false; protected bool _modulesLoaded = false;
   
[AVOID_SaveValue("mainWindowPos")] [AVOID_SaveValue("mainWindowPos")]
protected VOID_SaveValue<Rect> mainWindowPos = new Rect(475, 575, 10f, 10f); protected VOID_SaveValue<Rect> mainWindowPos = new Rect(475, 575, 10f, 10f);
[AVOID_SaveValue("mainGuiMinimized")] [AVOID_SaveValue("mainGuiMinimized")]
protected VOID_SaveValue<bool> mainGuiMinimized = false; protected VOID_SaveValue<bool> mainGuiMinimized = false;
   
[AVOID_SaveValue("configWindowPos")] [AVOID_SaveValue("configWindowPos")]
protected VOID_SaveValue<Rect> configWindowPos = new Rect(825, 625, 10f, 10f); protected VOID_SaveValue<Rect> configWindowPos = new Rect(825, 625, 10f, 10f);
[AVOID_SaveValue("configWindowMinimized")] [AVOID_SaveValue("configWindowMinimized")]
   
protected VOID_SaveValue<bool> configWindowMinimized = true; protected VOID_SaveValue<bool> configWindowMinimized = true;
[AVOID_SaveValue("VOIDIconPos")] [AVOID_SaveValue("VOIDIconPos")]
protected VOID_SaveValue<Rect> VOIDIconPos = new Rect(Screen.width / 2 - 200, Screen.height - 32, 32f, 32f); protected VOID_SaveValue<Rect> VOIDIconPos = new Rect(Screen.width / 2 - 200, Screen.height - 32, 32f, 32f);
   
protected Texture2D VOIDIconTexture; protected Texture2D VOIDIconTexture;
protected string VOIDIconOnActivePath; protected string VOIDIconOnActivePath;
protected string VOIDIconOnInactivePath; protected string VOIDIconOnInactivePath;
protected string VOIDIconOffActivePath; protected string VOIDIconOffActivePath;
protected string VOIDIconOffInactivePath; protected string VOIDIconOffInactivePath;
   
protected bool VOIDIconLocked = true; protected bool VOIDIconLocked = true;
   
protected GUIStyle iconStyle; protected GUIStyle iconStyle;
   
protected int windowBaseID = -96518722; protected int windowBaseID = -96518722;
protected int _windowID = 0; protected int _windowID = 0;
   
protected bool GUIStylesLoaded = false; protected bool GUIStylesLoaded = false;
protected Dictionary<string, GUIStyle> _LabelStyles = new Dictionary<string, GUIStyle>(); protected Dictionary<string, GUIStyle> _LabelStyles = new Dictionary<string, GUIStyle>();
   
protected CelestialBody _Kerbin; protected CelestialBody _Kerbin;
   
[AVOID_SaveValue("togglePower")] [AVOID_SaveValue("togglePower")]
public VOID_SaveValue<bool> togglePower = true; public VOID_SaveValue<bool> togglePower = true;
public bool powerAvailable = true; public bool powerAvailable = true;
   
[AVOID_SaveValue("consumeResource")] [AVOID_SaveValue("consumeResource")]
protected VOID_SaveValue<bool> consumeResource = false; protected VOID_SaveValue<bool> consumeResource = false;
   
[AVOID_SaveValue("resourceName")] [AVOID_SaveValue("resourceName")]
protected VOID_SaveValue<string> resourceName = "ElectricCharge"; protected VOID_SaveValue<string> resourceName = "ElectricCharge";
   
[AVOID_SaveValue("resourceRate")] [AVOID_SaveValue("resourceRate")]
protected VOID_SaveValue<float> resourceRate = 0.2f; protected VOID_SaveValue<float> resourceRate = 0.2f;
   
[AVOID_SaveValue("updatePeriod")] [AVOID_SaveValue("updatePeriod")]
protected VOID_SaveValue<double> _updatePeriod = 1001f / 15000f; protected VOID_SaveValue<double> _updatePeriod = 1001f / 15000f;
protected float _updateTimer = 0f; protected float _updateTimer = 0f;
protected string stringFrequency; protected string stringFrequency;
   
[AVOID_SaveValue("vesselSimActive")] [AVOID_SaveValue("vesselSimActive")]
protected VOID_SaveValue<bool> vesselSimActive; protected VOID_SaveValue<bool> vesselSimActive;
   
// Vessel Type Housekeeping // Vessel Type Housekeeping
protected List<VesselType> _allVesselTypes = new List<VesselType>(); protected List<VesselType> _allVesselTypes = new List<VesselType>();
protected bool vesselTypesLoaded = false; protected bool vesselTypesLoaded = false;
public float saveTimer = 0; public float saveTimer = 0;
   
protected string defaultSkin = "KSP window 2"; protected string defaultSkin = "KSP window 2";
   
[AVOID_SaveValue("defaultSkin")] [AVOID_SaveValue("defaultSkin")]
protected VOID_SaveValue<string> _skinName; protected VOID_SaveValue<string> _skinName;
protected int _skinIdx; protected int _skinIdx;
   
protected Dictionary<string, GUISkin> validSkins; protected Dictionary<string, GUISkin> validSkins;
protected string[] skinNames; protected string[] skinNames;
protected string[] forbiddenSkins = protected string[] forbiddenSkins =
{ {
"PlaqueDialogSkin", "PlaqueDialogSkin",
"FlagBrowserSkin", "FlagBrowserSkin",
"SSUITextAreaDefault", "SSUITextAreaDefault",
"ExperimentsDialogSkin", "ExperimentsDialogSkin",
"ExpRecoveryDialogSkin", "ExpRecoveryDialogSkin",
"KSP window 5", "KSP window 5",
"KSP window 6", "KSP window 6",
"PartTooltipSkin", "PartTooltipSkin",
"KSCContextMenuSkin" "KSCContextMenuSkin"
}; };
protected bool skinsLoaded = false; protected bool skinsLoaded = false;
   
public bool configDirty; public bool configDirty;
   
[AVOID_SaveValue("UseBlizzyToolbar")] [AVOID_SaveValue("UseBlizzyToolbar")]
protected VOID_SaveValue<bool> _UseToolbarManager; protected VOID_SaveValue<bool> _UseToolbarManager;
internal IButton ToolbarButton; internal IButton ToolbarButton;
   
internal ApplicationLauncherButton AppLauncherButton; internal ApplicationLauncherButton AppLauncherButton;
   
/* /*
* Properties * Properties
* */ * */
public bool factoryReset public bool factoryReset
{ {
get get
{ {
return this._factoryReset; return this._factoryReset;
} }
} }
   
public List<IVOID_Module> Modules public List<IVOID_Module> Modules
{ {
get get
{ {
return this._modules; return this._modules;
} }
} }
   
public GUISkin Skin public GUISkin Skin
{ {
get get
{ {
if (this.skinsLoaded) if (this.skinsLoaded)
{ {
try try
{ {
return this.validSkins[this._skinName]; return this.validSkins[this._skinName];
} }
catch catch
{ {
} }
} }
   
return AssetBase.GetGUISkin(this.defaultSkin); return AssetBase.GetGUISkin(this.defaultSkin);
} }
} }
   
public int windowID public int windowID
{ {
get get
{ {
if (this._windowID == 0) if (this._windowID == 0)
{ {
this._windowID = this.windowBaseID; this._windowID = this.windowBaseID;
} }
return this._windowID++; return this._windowID++;
} }
} }
   
public Dictionary<string, GUIStyle> LabelStyles public Dictionary<string, GUIStyle> LabelStyles
{ {
get get
{ {
return this._LabelStyles; return this._LabelStyles;
} }
} }
   
public List<CelestialBody> allBodies public List<CelestialBody> allBodies
{ {
get get
{ {
return FlightGlobals.Bodies; return FlightGlobals.Bodies;
} }
} }
   
public List<CelestialBody> sortedBodyList public List<CelestialBody> sortedBodyList
{ {
get; get;
private set; private set;
} }
   
public CelestialBody Kerbin public CelestialBody Kerbin
{ {
get get
{ {
if (this._Kerbin == null) if (this._Kerbin == null)
{ {
if (FlightGlobals.Bodies != null) if (FlightGlobals.Bodies != null)
{ {
this._Kerbin = FlightGlobals.Bodies.First(b => b.name == "Kerbin"); this._Kerbin = FlightGlobals.Bodies.First(b => b.name == "Kerbin");
} }
} }
   
return this._Kerbin; return this._Kerbin;
} }
} }
   
public List<VesselType> allVesselTypes public List<VesselType> allVesselTypes
{ {
get get
{ {
return this._allVesselTypes; return this._allVesselTypes;
} }
} }
   
public float updateTimer public float updateTimer
{ {
get get
{ {
return this._updateTimer; return this._updateTimer;
} }
} }
   
public double updatePeriod public double updatePeriod
{ {
get get
{ {
return this._updatePeriod; return this._updatePeriod;
} }
} }
   
public Stage[] Stages public Stage[] Stages
{ {
get; get;
protected set; protected set;
} }
   
public Stage LastStage public Stage LastStage
{ {
get; get;
protected set; protected set;
} }
   
protected IconState powerState protected IconState powerState
{ {
get get
{ {
if (this.togglePower && this.powerAvailable) if (this.togglePower && this.powerAvailable)
{ {
return IconState.PowerOn; return IconState.PowerOn;
} }
else else
{ {
return IconState.PowerOff; return IconState.PowerOff;
} }
   
} }
} }
   
protected IconState activeState protected IconState activeState
{ {
get get
{ {
if (this.mainGuiMinimized) if (this.mainGuiMinimized)
{ {
return IconState.Inactive; return IconState.Inactive;
} }
else else
{ {
return IconState.Active; return IconState.Active;
} }
   
} }
} }
   
protected bool UseToolbarManager protected bool UseToolbarManager
{ {
get get
{ {
return _UseToolbarManager & ToolbarManager.ToolbarAvailable; return _UseToolbarManager & ToolbarManager.ToolbarAvailable;
} }
set set
{ {
if (this._UseToolbarManager == value) if (this._UseToolbarManager == value)
{ {
return; return;
} }
   
if (value == false && this.ToolbarButton != null) if (value == false && this.ToolbarButton != null)
{ {
this.ToolbarButton.Destroy(); this.ToolbarButton.Destroy();
this.ToolbarButton = null; this.ToolbarButton = null;
} }
if (value == true) if (value == true)
{ {
if (this.AppLauncherButton != null) if (this.AppLauncherButton != null)
{ {
ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton); ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton);
this.AppLauncherButton = null; this.AppLauncherButton = null;
} }
   
this.InitializeToolbarButton(); this.InitializeToolbarButton();
} }
   
_UseToolbarManager.value = value; _UseToolbarManager.value = value;
} }
} }
   
protected virtual ApplicationLauncher.AppScenes appIconVisibleScenes protected virtual ApplicationLauncher.AppScenes appIconVisibleScenes
{ {
get get
{ {
return ApplicationLauncher.AppScenes.FLIGHT; return ApplicationLauncher.AppScenes.FLIGHT;
} }
} }
   
/* /*
* Methods * Methods
* */ * */
public override void DrawGUI() public override void DrawGUI()
{ {
this._windowID = this.windowBaseID; this._windowID = this.windowBaseID;
   
if (!this._modulesLoaded) if (!this._modulesLoaded)
{ {
this.LoadModulesOfType<IVOID_Module>(); this.LoadModulesOfType<IVOID_Module>();
} }
   
if (!this.skinsLoaded) if (!this.skinsLoaded)
{ {
this.LoadSkins(); this.LoadSkins();
} }
   
GUI.skin = this.Skin; GUI.skin = this.Skin;
   
if (!this.GUIStylesLoaded) if (!this.GUIStylesLoaded)
{ {
this.LoadGUIStyles(); this.LoadGUIStyles();
   
Tools.PostDebugMessage( Tools.PostDebugMessage(
this, this,
"ToolbarAvailable: {0}, UseToobarManager: {1}", "ToolbarAvailable: {0}, UseToobarManager: {1}",
ToolbarManager.ToolbarAvailable, ToolbarManager.ToolbarAvailable,
this.UseToolbarManager); this.UseToolbarManager);
} }
   
if (!this.UseToolbarManager) if (!this.UseToolbarManager)
{ {
if (this.AppLauncherButton == null) if (this.AppLauncherButton == null)
{ {
Tools.PostDebugMessage(this, Tools.PostDebugMessage(this,
"UseToolbarManager = false (ToolbarAvailable = {0}) and " + "UseToolbarManager = false (ToolbarAvailable = {0}) and " +
"AppLauncherButton is null, making AppLauncher button.", "AppLauncherButton is null, making AppLauncher button.",
ToolbarManager.ToolbarAvailable ToolbarManager.ToolbarAvailable
); );
this.InitializeAppLauncherButton(); this.InitializeAppLauncherButton();
} }
} }
else if (this.ToolbarButton == null) else if (this.ToolbarButton == null)
{ {
Tools.PostDebugMessage(this, Tools.PostDebugMessage(this,
"UseToolbarManager = true (ToolbarAvailable = {0}) and " + "UseToolbarManager = true (ToolbarAvailable = {0}) and " +
"ToolbarButton is null, making Toolbar button.", "ToolbarButton is null, making Toolbar button.",
ToolbarManager.ToolbarAvailable ToolbarManager.ToolbarAvailable
); );
this.InitializeToolbarButton(); this.InitializeToolbarButton();
} }
   
if (!this.mainGuiMinimized) if (!this.mainGuiMinimized)
{ {
   
Rect _mainWindowPos = this.mainWindowPos; Rect _mainWindowPos = this.mainWindowPos;
   
_mainWindowPos = GUILayout.Window( _mainWindowPos = GUILayout.Window(
this.windowID, this.windowID,
_mainWindowPos, _mainWindowPos,
VOID_Tools.GetWindowHandler(this.VOIDMainWindow), VOID_Tools.GetWindowHandler(this.VOIDMainWindow),
string.Join(" ", new string[] { this.VoidName, this.VoidVersion }), string.Join(" ", new string[] { this.VoidName, this.VoidVersion }),
GUILayout.Width(250), GUILayout.Width(250),
GUILayout.Height(50) GUILayout.Height(50)
); );
   
if (HighLogic.LoadedSceneIsEditor) if (HighLogic.LoadedSceneIsEditor)
{ {
_mainWindowPos = Tools.ClampRectToEditorPad(_mainWindowPos); _mainWindowPos = Tools.ClampRectToEditorPad(_mainWindowPos);
} }
else else
{ {
_mainWindowPos = Tools.ClampRectToScreen(_mainWindowPos); _mainWindowPos = Tools.ClampRectToScreen(_mainWindowPos);
} }
   
if (_mainWindowPos != this.mainWindowPos) if (_mainWindowPos != this.mainWindowPos)
{ {
this.mainWindowPos = _mainWindowPos; this.mainWindowPos = _mainWindowPos;
} }
} }
   
if (!this.configWindowMinimized && !this.mainGuiMinimized) if (!this.configWindowMinimized && !this.mainGuiMinimized)
{ {
Rect _configWindowPos = this.configWindowPos; Rect _configWindowPos = this.configWindowPos;
   
_configWindowPos = GUILayout.Window( _configWindowPos = GUILayout.Window(
this.windowID, this.windowID,
_configWindowPos, _configWindowPos,
VOID_Tools.GetWindowHandler(this.VOIDConfigWindow), VOID_Tools.GetWindowHandler(this.VOIDConfigWindow),
string.Join(" ", new string[] { this.VoidName, "Configuration" }), string.Join(" ", new string[] { this.VoidName, "Configuration" }),
GUILayout.Width(250), GUILayout.Width(250),
GUILayout.Height(50) GUILayout.Height(50)
); );
   
if (HighLogic.LoadedSceneIsEditor) if (HighLogic.LoadedSceneIsEditor)
{ {
_configWindowPos = Tools.ClampRectToEditorPad(_configWindowPos); _configWindowPos = Tools.ClampRectToEditorPad(_configWindowPos);
} }
else else
{ {
_configWindowPos = Tools.ClampRectToScreen(_configWindowPos); _configWindowPos = Tools.ClampRectToScreen(_configWindowPos);
} }
   
if (_configWindowPos != this.configWindowPos) if (_configWindowPos != this.configWindowPos)
{ {
this.configWindowPos = _configWindowPos; this.configWindowPos = _configWindowPos;
} }
} }
} }
   
public virtual void OnGUI() public virtual void OnGUI()
{ {
if (Event.current.type == EventType.Repaint) if (Event.current.type == EventType.Repaint)
{ {
return; return;
} }
   
/* /*
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"Event.current.type: {0}" + "Event.current.type: {0}" +
"\nthis.VOIDIconLocked: {1}" + "\nthis.VOIDIconLocked: {1}" +
"\nEvent.current.mousePosition: {2}" + "\nEvent.current.mousePosition: {2}" +
"\nVOIDIconPos: ({3}, {4}),({5}, {6})", "\nVOIDIconPos: ({3}, {4}),({5}, {6})",
Event.current.type, Event.current.type,
this.VOIDIconLocked, this.VOIDIconLocked,
Event.current.mousePosition, Event.current.mousePosition,
this.VOIDIconPos.value.xMin, this.VOIDIconPos.value.xMin,
this.VOIDIconPos.value.yMin, this.VOIDIconPos.value.yMin,
this.VOIDIconPos.value.xMax, this.VOIDIconPos.value.xMax,
this.VOIDIconPos.value.yMax this.VOIDIconPos.value.yMax
)); ));
*/ */
   
if (!this.VOIDIconLocked && if (!this.VOIDIconLocked &&
VOIDIconPos.value.Contains(Event.current.mousePosition) VOIDIconPos.value.Contains(Event.current.mousePosition)
&& Event.current.type == EventType.mouseDrag) && Event.current.type == EventType.mouseDrag)
{ {
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"Event.current.type: {0}" + "Event.current.type: {0}" +
"\ndelta.x: {1}; delta.y: {2}", "\ndelta.x: {1}; delta.y: {2}",
Event.current.type, Event.current.type,
Event.current.delta.x, Event.current.delta.x,
Event.current.delta.y Event.current.delta.y
)); ));
   
Rect tmp = new Rect(VOIDIconPos); Rect tmp = new Rect(VOIDIconPos);
   
tmp.x = Event.current.mousePosition.x - tmp.width / 2; tmp.x = Event.current.mousePosition.x - tmp.width / 2;
tmp.y = Event.current.mousePosition.y - tmp.height / 2; tmp.y = Event.current.mousePosition.y - tmp.height / 2;
   
if (tmp.x > Screen.width - tmp.width) if (tmp.x > Screen.width - tmp.width)
{ {
tmp.x = Screen.width - tmp.width; tmp.x = Screen.width - tmp.width;
} }
   
if (tmp.y > Screen.height - tmp.height) if (tmp.y > Screen.height - tmp.height)
{ {
tmp.y = Screen.height - tmp.height; tmp.y = Screen.height - tmp.height;
} }
   
VOIDIconPos = tmp; VOIDIconPos = tmp;
} }
} }
   
public virtual void Update() public virtual void Update()
{ {
this.LoadBeforeUpdate(); this.LoadBeforeUpdate();
   
if (this.vessel != null && this.vesselSimActive) if (this.vessel != null && this.vesselSimActive)
{ {
Tools.PostDebugMessage(this, "Updating SimManager."); Tools.PostDebugMessage(this, "Updating SimManager.");
this.UpdateSimManager(); this.UpdateSimManager();
} }
   
if (!this.guiRunning) if (!this.guiRunning)
{ {
this.StartGUI(); this.StartGUI();
} }
   
if (!HighLogic.LoadedSceneIsFlight && this.guiRunning) if (!HighLogic.LoadedSceneIsFlight && this.guiRunning)
{ {
this.StopGUI(); this.StopGUI();
} }
   
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
if (!module.guiRunning && module.toggleActive) if (!module.guiRunning && module.toggleActive)
{ {
module.StartGUI(); module.StartGUI();
} }
if (module.guiRunning && !module.toggleActive || if (module.guiRunning && !module.toggleActive ||
!this.togglePower || !this.togglePower ||
!HighLogic.LoadedSceneIsFlight || !HighLogic.LoadedSceneIsFlight ||
this.factoryReset) this.factoryReset)
{ {
module.StopGUI(); module.StopGUI();
} }
   
if (module is IVOID_BehaviorModule) if (module is IVOID_BehaviorModule)
{ {
((IVOID_BehaviorModule)module).Update(); ((IVOID_BehaviorModule)module).Update();
} }
} }
   
this.CheckAndSave(); this.CheckAndSave();
this._updateTimer += Time.deltaTime; this._updateTimer += Time.deltaTime;
} }
   
public virtual void FixedUpdate() public virtual void FixedUpdate()
{ {
bool newPowerState = this.powerAvailable; bool newPowerState = this.powerAvailable;
   
if (this.togglePower && this.consumeResource && if (this.togglePower && this.consumeResource &&
this.vessel.vesselType != VesselType.EVA && this.vessel.vesselType != VesselType.EVA &&
TimeWarp.deltaTime != 0) TimeWarp.deltaTime != 0)
{ {
float powerReceived = this.vessel.rootPart.RequestResource( float powerReceived = this.vessel.rootPart.RequestResource(
this.resourceName, this.resourceName,
this.resourceRate * TimeWarp.fixedDeltaTime this.resourceRate * TimeWarp.fixedDeltaTime
); );
   
if (powerReceived > 0) if (powerReceived > 0)
{ {
newPowerState = true; newPowerState = true;
} }
else else
{ {
newPowerState = false; newPowerState = false;
} }
   
if (this.powerAvailable != newPowerState) if (this.powerAvailable != newPowerState)
{ {
this.powerAvailable = newPowerState; this.powerAvailable = newPowerState;
this.SetIconTexture(this.powerState | this.activeState); this.SetIconTexture(this.powerState | this.activeState);
} }
} }
   
foreach (IVOID_BehaviorModule module in foreach (IVOID_BehaviorModule module in
this._modules.OfType<IVOID_BehaviorModule>().Where(m => !m.GetType().IsAbstract)) this._modules.OfType<IVOID_BehaviorModule>().Where(m => !m.GetType().IsAbstract))
{ {
module.FixedUpdate(); module.FixedUpdate();
} }
} }
   
public void ResetGUI() public void ResetGUI()
{ {
this.StopGUI(); this.StopGUI();
   
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
module.StopGUI(); module.StopGUI();
module.StartGUI(); module.StartGUI();
} }
   
this.StartGUI(); this.StartGUI();
} }
   
public void VOIDMainWindow(int _) public void VOIDMainWindow(int _)
{ {
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
if (this.powerAvailable || HighLogic.LoadedSceneIsEditor) if (this.powerAvailable || HighLogic.LoadedSceneIsEditor)
{ {
if (!HighLogic.LoadedSceneIsEditor) if (!HighLogic.LoadedSceneIsEditor)
{ {
string str = string.Intern("ON"); string str = string.Intern("ON");
if (togglePower) if (togglePower)
str = string.Intern("OFF"); str = string.Intern("OFF");
if (GUILayout.Button("Power " + str)) if (GUILayout.Button("Power " + str))
{ {
togglePower.value = !togglePower; togglePower.value = !togglePower;
this.SetIconTexture(this.powerState | this.activeState); this.SetIconTexture(this.powerState | this.activeState);
} }
} }
   
if (togglePower || HighLogic.LoadedSceneIsEditor) if (togglePower || HighLogic.LoadedSceneIsEditor)
{ {
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
module.toggleActive = GUILayout.Toggle(module.toggleActive, module.Name); module.toggleActive = GUILayout.Toggle(module.toggleActive, module.Name);
} }
} }
} }
else else
{ {
GUILayout.Label("-- POWER LOST --", VOID_Styles.labelRed); GUILayout.Label("-- POWER LOST --", VOID_Styles.labelRed);
} }
   
this.configWindowMinimized.value = !GUILayout.Toggle(!this.configWindowMinimized, "Configuration"); this.configWindowMinimized.value = !GUILayout.Toggle(!this.configWindowMinimized, "Configuration");
   
GUILayout.EndVertical(); GUILayout.EndVertical();
GUI.DragWindow(); GUI.DragWindow();
} }
   
public void VOIDConfigWindow(int _) public void VOIDConfigWindow(int _)
{ {
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
this.DrawConfigurables(); this.DrawConfigurables();
   
GUILayout.EndVertical(); GUILayout.EndVertical();
GUI.DragWindow(); GUI.DragWindow();
} }
   
public override void DrawConfigurables() public override void DrawConfigurables()
{ {
GUIContent _content; GUIContent _content;
   
if (HighLogic.LoadedSceneIsFlight) if (HighLogic.LoadedSceneIsFlight)
{ {
this.consumeResource.value = GUILayout.Toggle(this.consumeResource, "Consume Resources"); this.consumeResource.value = GUILayout.Toggle(this.consumeResource, "Consume Resources");
   
this.VOIDIconLocked = GUILayout.Toggle(this.VOIDIconLocked, "Lock Icon Position"); this.VOIDIconLocked = GUILayout.Toggle(this.VOIDIconLocked, "Lock Icon Position");
} }
   
this.UseToolbarManager = GUILayout.Toggle(this.UseToolbarManager, "Use Blizzy's Toolbar If Available"); this.UseToolbarManager = GUILayout.Toggle(this.UseToolbarManager, "Use Blizzy's Toolbar If Available");
   
this.vesselSimActive.value = GUILayout.Toggle(this.vesselSimActive.value, this.vesselSimActive.value = GUILayout.Toggle(this.vesselSimActive.value,
"Enable Engineering Calculations"); "Enable Engineering Calculations");
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
   
GUILayout.Label("Skin:", GUILayout.ExpandWidth(false)); GUILayout.Label("Skin:", GUILayout.ExpandWidth(false));
   
_content = new GUIContent(); _content = new GUIContent();
   
_content.text = "◄"; _content.text = "◄";
_content.tooltip = "Select previous skin"; _content.tooltip = "Select previous skin";
if (GUILayout.Button(_content, GUILayout.ExpandWidth(true))) if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
{ {
this._skinIdx--; this._skinIdx--;
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}", "{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",
this.GetType().Name, this.GetType().Name,
this._skinName, this._skinName,
this.validSkins.Count this.validSkins.Count
)); ));
} }
   
_content.text = this.Skin.name; _content.text = this.Skin.name;
_content.tooltip = "Current skin"; _content.tooltip = "Current skin";
GUILayout.Label(_content, VOID_Styles.labelCenter, GUILayout.ExpandWidth(true)); GUILayout.Label(_content, VOID_Styles.labelCenter, GUILayout.ExpandWidth(true));
   
_content.text = "►"; _content.text = "►";
_content.tooltip = "Select next skin"; _content.tooltip = "Select next skin";
if (GUILayout.Button(_content, GUILayout.ExpandWidth(true))) if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
{ {
this._skinIdx++; this._skinIdx++;
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}", "{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",
this.GetType().Name, this.GetType().Name,
this._skinName, this._skinName,
this.validSkins.Count this.validSkins.Count
)); ));
} }
   
this._skinIdx %= this.skinNames.Length; this._skinIdx %= this.skinNames.Length;
if (this._skinIdx < 0) if (this._skinIdx < 0)
{ {
this._skinIdx += this.skinNames.Length; this._skinIdx += this.skinNames.Length;
} }
   
if (this._skinName != skinNames[this._skinIdx]) if (this._skinName != skinNames[this._skinIdx])
{ {
this._skinName.value = skinNames[this._skinIdx]; this._skinName.value = skinNames[this._skinIdx];
this.GUIStylesLoaded = false; this.GUIStylesLoaded = false;
} }
   
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
GUILayout.Label("Update Rate (Hz):"); GUILayout.Label("Update Rate (Hz):");
if (this.stringFrequency == null) if (this.stringFrequency == null)
{ {
this.stringFrequency = (1f / this.updatePeriod).ToString(); this.stringFrequency = (1f / this.updatePeriod).ToString();
} }
this.stringFrequency = GUILayout.TextField(this.stringFrequency.ToString(), 5, GUILayout.ExpandWidth(true)); this.stringFrequency = GUILayout.TextField(this.stringFrequency.ToString(), 5, GUILayout.ExpandWidth(true));
   
if (GUILayout.Button("Apply")) if (GUILayout.Button("Apply"))
{ {
double updateFreq = 1f / this.updatePeriod; double updateFreq = 1f / this.updatePeriod;
double.TryParse(stringFrequency, out updateFreq); double.TryParse(stringFrequency, out updateFreq);
this._updatePeriod = 1 / updateFreq; this._updatePeriod = 1 / updateFreq;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
foreach (IVOID_Module mod in this.Modules) foreach (IVOID_Module mod in this.Modules)
{ {
mod.DrawConfigurables(); mod.DrawConfigurables();
} }
   
this._factoryReset = GUILayout.Toggle(this._factoryReset, "Factory Reset"); this._factoryReset = GUILayout.Toggle(this._factoryReset, "Factory Reset");
} }
   
protected void UpdateSimManager() protected void UpdateSimManager()
{ {
if (SimManager.ResultsReady()) if (SimManager.ResultsReady())
{ {
Tools.PostDebugMessage(this, "VesselSimulator results ready, setting Stages."); Tools.PostDebugMessage(this, "VesselSimulator results ready, setting Stages.");
   
this.Stages = SimManager.Stages; this.Stages = SimManager.Stages;
   
if (this.Stages != null) if (this.Stages != null)
{ {
this.LastStage = this.Stages.Last(); this.LastStage = this.Stages.Last();
} }
   
if (HighLogic.LoadedSceneIsEditor) if (HighLogic.LoadedSceneIsEditor)
{ {
SimManager.Gravity = VOID_Data.KerbinGee; SimManager.Gravity = VOID_Data.KerbinGee;
} }
else else
{ {
double radius = this.vessel.Radius(); double radius = this.vessel.Radius();
SimManager.Gravity = this.vessel.mainBody.gravParameter / (radius * radius); SimManager.Gravity = this.vessel.mainBody.gravParameter / (radius * radius);
} }
   
SimManager.minSimTime = (long)(this.updatePeriod * 1000); SimManager.minSimTime = (long)(this.updatePeriod * 1000);
   
SimManager.TryStartSimulation(); SimManager.TryStartSimulation();
} }
#if DEBUG #if DEBUG
else else
{ {
Tools.PostDebugMessage(this, "VesselSimulator results not ready."); Tools.PostDebugMessage(this, "VesselSimulator results not ready.");
} }
#endif #endif
} }
   
protected void LoadModulesOfType<T>() protected void LoadModulesOfType<T>()
{ {
StringBuilder sb = new StringBuilder("Loading modules..."); StringBuilder sb = new StringBuilder("Loading modules...");
sb.AppendLine(); sb.AppendLine();
   
foreach (AssemblyLoader.LoadedAssembly assy in AssemblyLoader.loadedAssemblies) foreach (AssemblyLoader.LoadedAssembly assy in AssemblyLoader.loadedAssemblies)
{ {
foreach (Type loadedType in assy.assembly.GetExportedTypes()) foreach (Type loadedType in assy.assembly.GetExportedTypes())
{ {
if ( if (
loadedType.IsInterface || loadedType.IsInterface ||
loadedType.IsAbstract || loadedType.IsAbstract ||
!typeof(T).IsAssignableFrom(loadedType) || !typeof(T).IsAssignableFrom(loadedType) ||
this.GetType().IsAssignableFrom(loadedType) this.GetType().IsAssignableFrom(loadedType)
) )
{ {
continue; continue;
} }
   
// HACK: This stops editor modules from loading in flight. It is a dirty hack and should be fixed. // 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)) if (!HighLogic.LoadedSceneIsEditor && typeof(IVOID_EditorModule).IsAssignableFrom(loadedType))
{ {
continue; continue;
} }
   
sb.AppendFormat("Loading IVOID_Module type {0}...", loadedType.Name); sb.AppendFormat("Loading IVOID_Module type {0}...", loadedType.Name);
   
try try
{ {
this.LoadModule(loadedType); this.LoadModule(loadedType);
sb.AppendLine("Success."); sb.AppendLine("Success.");
} }
catch (Exception ex) catch (Exception ex)
{ {
sb.AppendFormat("Failed, caught {0}", ex.GetType().Name); sb.AppendFormat("Failed, caught {0}", ex.GetType().Name);
sb.AppendLine(); sb.AppendLine();
   
#if DEBUG #if DEBUG
Debug.LogException(ex); Debug.LogException(ex);
#endif #endif
} }
} }
} }
   
this._modulesLoaded = true; this._modulesLoaded = true;
   
sb.AppendFormat("Loaded {0} modules.", this.Modules.Count); sb.AppendFormat("Loaded {0} modules.", this.Modules.Count);
sb.AppendLine(); sb.AppendLine();
} }
   
protected void LoadModule(Type T) protected void LoadModule(Type T)
{ {
var existingModules = this._modules.Where(mod => mod.GetType().Name == T.Name); var existingModules = this._modules.Where(mod => mod.GetType().Name == T.Name);
if (existingModules.Any()) if (existingModules.Any())
{ {
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: refusing to load {1}: already loaded", "{0}: refusing to load {1}: already loaded",
this.GetType().Name, this.GetType().Name,
T.Name T.Name
)); ));
return; return;
} }
IVOID_Module module = Activator.CreateInstance(T) as IVOID_Module; IVOID_Module module = Activator.CreateInstance(T) as IVOID_Module;
module.LoadConfig(); module.LoadConfig();
this._modules.Add(module); this._modules.Add(module);
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: loaded module {1}.", "{0}: loaded module {1}.",
this.GetType().Name, this.GetType().Name,
T.Name T.Name
)); ));
} }
   
protected void LoadSkins() protected void LoadSkins()
{ {
Tools.PostDebugMessage("AssetBase has skins: \n" + Tools.PostDebugMessage("AssetBase has skins: \n" +
string.Join("\n\t", string.Join("\n\t",
Resources.FindObjectsOfTypeAll(typeof(GUISkin)) Resources.FindObjectsOfTypeAll(typeof(GUISkin))
.Select(s => s.ToString()) .Select(s => s.ToString())
.ToArray() .ToArray()
) )
); );
   
this.validSkins = Resources.FindObjectsOfTypeAll(typeof(GUISkin)) this.validSkins = Resources.FindObjectsOfTypeAll(typeof(GUISkin))
.Where(s => !this.forbiddenSkins.Contains(s.name)) .Where(s => !this.forbiddenSkins.Contains(s.name))
.Select(s => s as GUISkin) .Select(s => s as GUISkin)
.GroupBy(s => s.name) .GroupBy(s => s.name)
.Select(g => g.First()) .Select(g => g.First())
.ToDictionary(s => s.name); .ToDictionary(s => s.name);
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: loaded {1} GUISkins.", "{0}: loaded {1} GUISkins.",
this.GetType().Name, this.GetType().Name,
this.validSkins.Count this.validSkins.Count
)); ));
   
this.skinNames = this.validSkins.Keys.ToArray(); this.skinNames = this.validSkins.Keys.ToArray();
Array.Sort(this.skinNames); Array.Sort(this.skinNames);
   
int defaultIdx = int.MinValue; int defaultIdx = int.MinValue;
   
for (int i = 0; i < this.skinNames.Length; i++) for (int i = 0; i < this.skinNames.Length; i++)
{ {
if (this.skinNames[i] == this._skinName) if (this.skinNames[i] == this._skinName)
{ {
this._skinIdx = i; this._skinIdx = i;
} }
if (this.skinNames[i] == this.defaultSkin) if (this.skinNames[i] == this.defaultSkin)
{ {
defaultIdx = i; defaultIdx = i;
} }
if (this._skinIdx != int.MinValue && defaultIdx != int.MinValue) if (this._skinIdx != int.MinValue && defaultIdx != int.MinValue)
{ {
break; break;
} }
} }
   
if (this._skinIdx == int.MinValue) if (this._skinIdx == int.MinValue)
{ {
this._skinIdx = defaultIdx; this._skinIdx = defaultIdx;
} }
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: _skinIdx = {1}.", "{0}: _skinIdx = {1}.",
this.GetType().Name, this.GetType().Name,
this._skinName.ToString() this._skinName.ToString()
)); ));
   
this.skinsLoaded = true; this.skinsLoaded = true;
} }
   
protected void LoadGUIStyles() protected void LoadGUIStyles()
{ {
VOID_Styles.OnSkinChanged(); VOID_Styles.OnSkinChanged();
   
this.GUIStylesLoaded = true; this.GUIStylesLoaded = true;
} }
   
protected void LoadVesselTypes() protected void LoadVesselTypes()
{ {
this._allVesselTypes = Enum.GetValues(typeof(VesselType)).OfType<VesselType>().ToList(); this._allVesselTypes = Enum.GetValues(typeof(VesselType)).OfType<VesselType>().ToList();
this.vesselTypesLoaded = true; this.vesselTypesLoaded = true;
} }
   
protected void LoadBeforeUpdate() protected void LoadBeforeUpdate()
{ {
if (!this.vesselTypesLoaded) if (!this.vesselTypesLoaded)
{ {
this.LoadVesselTypes(); this.LoadVesselTypes();
} }
   
if (this.sortedBodyList == null && FlightGlobals.Bodies != null && FlightGlobals.Bodies.Count > 0) if (this.sortedBodyList == null && FlightGlobals.Bodies != null && FlightGlobals.Bodies.Count > 0)
{ {
this.sortedBodyList = new List<CelestialBody>(FlightGlobals.Bodies); this.sortedBodyList = new List<CelestialBody>(FlightGlobals.Bodies);
this.sortedBodyList.Sort(new CBListComparer()); this.sortedBodyList.Sort(new CBListComparer());
this.sortedBodyList.Reverse(); this.sortedBodyList.Reverse();
   
Debug.Log(string.Format("sortedBodyList: {0}", string.Join("\n\t", this.sortedBodyList.Select(b => b.bodyName).ToArray()))); Debug.Log(string.Format("sortedBodyList: {0}", string.Join("\n\t", this.sortedBodyList.Select(b => b.bodyName).ToArray())));
} }
   
} }
   
protected void InitializeToolbarButton() protected void InitializeToolbarButton()
{ {
// Do nothing if (the Toolbar is not available. // Do nothing if (the Toolbar is not available.
if (!ToolbarManager.ToolbarAvailable) if (!ToolbarManager.ToolbarAvailable)
{ {
Tools.PostDebugMessage(this, "Refusing to make a ToolbarButton: ToolbarAvailable = false"); Tools.PostDebugMessage(this, "Refusing to make a ToolbarButton: ToolbarAvailable = false");
return; return;
} }
   
this.ToolbarButton = ToolbarManager.Instance.add(this.VoidName, "coreToggle"); this.ToolbarButton = ToolbarManager.Instance.add(this.VoidName, "coreToggle");
this.ToolbarButton.Text = this.VoidName; this.ToolbarButton.Text = this.VoidName;
this.SetIconTexture(this.powerState | this.activeState); 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, GameScenes.SPH);
   
this.ToolbarButton.OnClick += this.ToolbarButton.OnClick +=
(e) => (e) =>
{ {
this.ToggleMainWindow(); this.ToggleMainWindow();
}; };
   
Tools.PostDebugMessage(string.Format("{0}: Toolbar Button initialized.", this.GetType().Name)); Tools.PostDebugMessage(string.Format("{0}: Toolbar Button initialized.", this.GetType().Name));
} }
   
protected void InitializeAppLauncherButton() protected void InitializeAppLauncherButton()
{ {
if (ApplicationLauncher.Ready) if (ApplicationLauncher.Ready)
{ {
this.AppLauncherButton = ApplicationLauncher.Instance.AddModApplication( this.AppLauncherButton = ApplicationLauncher.Instance.AddModApplication(
this.ToggleMainWindow, this.ToggleMainWindow, this.ToggleMainWindow, this.ToggleMainWindow,
this.appIconVisibleScenes, this.appIconVisibleScenes,
this.VOIDIconTexture this.VOIDIconTexture
); );
   
Tools.PostDebugMessage( Tools.PostDebugMessage(
this, this,
"AppLauncherButton initialized in {0}", "AppLauncherButton initialized in {0}",
Enum.GetName( Enum.GetName(
typeof(GameScenes), typeof(GameScenes),
HighLogic.LoadedScene HighLogic.LoadedScene
) )
); );
} }
} }
   
protected void ToggleMainWindow() protected void ToggleMainWindow()
{ {
this.mainGuiMinimized = !this.mainGuiMinimized; this.mainGuiMinimized = !this.mainGuiMinimized;
this.SetIconTexture(this.powerState | this.activeState); this.SetIconTexture(this.powerState | this.activeState);
} }
   
protected void SetIconTexture(IconState state) protected void SetIconTexture(IconState state)
{ {
switch (state) switch (state)
{ {
case (IconState.PowerOff | IconState.Inactive): case (IconState.PowerOff | IconState.Inactive):
this.SetIconTexture(this.VOIDIconOffInactivePath); this.SetIconTexture(this.VOIDIconOffInactivePath);
break; break;
case (IconState.PowerOff | IconState.Active): case (IconState.PowerOff | IconState.Active):
this.SetIconTexture(this.VOIDIconOffActivePath); this.SetIconTexture(this.VOIDIconOffActivePath);
break; break;
case (IconState.PowerOn | IconState.Inactive): case (IconState.PowerOn | IconState.Inactive):
this.SetIconTexture(this.VOIDIconOnInactivePath); this.SetIconTexture(this.VOIDIconOnInactivePath);
break; break;
case (IconState.PowerOn | IconState.Active): case (IconState.PowerOn | IconState.Active):
this.SetIconTexture(this.VOIDIconOnActivePath); this.SetIconTexture(this.VOIDIconOnActivePath);
break; break;
default: default:
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }
   
protected void SetIconTexture(string texturePath) protected void SetIconTexture(string texturePath)
{ {
if (this.ToolbarButton != null) if (this.ToolbarButton != null)
{ {
this.ToolbarButton.TexturePath = texturePath; this.ToolbarButton.TexturePath = texturePath;
} }
   
this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath.Replace("icon", "appIcon"), false); this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath.Replace("icon", "appIcon"), false);
   
if (this.AppLauncherButton != null) if (this.AppLauncherButton != null)
{ {
this.AppLauncherButton.SetTexture(VOIDIconTexture); this.AppLauncherButton.SetTexture(VOIDIconTexture);
} }
} }
   
protected void CheckAndSave() protected void CheckAndSave()
{ {
this.saveTimer += Time.deltaTime; this.saveTimer += Time.deltaTime;
   
if (this.saveTimer > 2f) if (this.saveTimer > 2f)
{ {
if (!this.configDirty) if (!this.configDirty)
{ {
return; return;
} }
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Time to save, checking if configDirty: {1}", "{0}: Time to save, checking if configDirty: {1}",
this.GetType().Name, this.GetType().Name,
this.configDirty this.configDirty
)); ));
   
this.SaveConfig(); this.SaveConfig();
this.saveTimer = 0; this.saveTimer = 0;
} }
} }
   
public override void LoadConfig() public override void LoadConfig()
{ {
base.LoadConfig(); base.LoadConfig();
   
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
module.LoadConfig(); module.LoadConfig();
} }
} }
   
public void SaveConfig() public void SaveConfig()
{ {
var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Core>(); var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Core>();
config.load(); config.load();
   
this._SaveToConfig(config); this._SaveToConfig(config);
   
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
module._SaveToConfig(config); module._SaveToConfig(config);
} }
   
config.save(); config.save();
   
this.configDirty = false; this.configDirty = false;
} }
   
protected VOID_Core() protected VOID_Core()
{ {
this._Name = "VOID Core"; this._Name = "VOID Core";
   
System.Version version = this.GetType().Assembly.GetName().Version; System.Version version = this.GetType().Assembly.GetName().Version;
   
this.VoidVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.MajorRevision); this.VoidVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.MajorRevision);
   
this.toggleActive = true; this.toggleActive = true;
   
this._skinName = this.defaultSkin; this._skinName = this.defaultSkin;
this._skinIdx = int.MinValue; this._skinIdx = int.MinValue;
   
this.VOIDIconOnInactivePath = "VOID/Textures/void_icon_light_glow"; this.VOIDIconOnInactivePath = "VOID/Textures/void_icon_light_glow";
this.VOIDIconOnActivePath = "VOID/Textures/void_icon_dark_glow"; this.VOIDIconOnActivePath = "VOID/Textures/void_icon_dark_glow";
this.VOIDIconOffInactivePath = "VOID/Textures/void_icon_light"; this.VOIDIconOffInactivePath = "VOID/Textures/void_icon_light";
this.VOIDIconOffActivePath = "VOID/Textures/void_icon_dark"; this.VOIDIconOffActivePath = "VOID/Textures/void_icon_dark";
   
this.vesselSimActive = true; this.vesselSimActive = true;
   
this.UseToolbarManager = false; this.UseToolbarManager = false;
   
this.LoadConfig(); this.LoadConfig();
   
this.SetIconTexture(this.powerState | this.activeState); this.SetIconTexture(this.powerState | this.activeState);
} }
   
public virtual void Dispose() public virtual void Dispose()
{ {
if (this.AppLauncherButton != null) if (this.AppLauncherButton != null)
{ {
ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton); ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton);
this.AppLauncherButton = null; this.AppLauncherButton = null;
} }
if (this.ToolbarButton != null) if (this.ToolbarButton != null)
{ {
this.ToolbarButton.Destroy(); this.ToolbarButton.Destroy();
this.ToolbarButton = null; this.ToolbarButton = null;
} }
} }
   
protected enum IconState protected enum IconState
{ {
PowerOff = 1, PowerOff = 1,
PowerOn = 2, PowerOn = 2,
Inactive = 4, Inactive = 4,
Active = 8 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  
{  
if (kerbinGee == default(double))  
{  
kerbinGee = core.Kerbin.gravParameter / (core.Kerbin.Radius * core.Kerbin.Radius);  
}  
   
return kerbinGee;  
}  
}  
   
private static double kerbinGee;  
}  
} }
   
   
file:b/VOID_Data.cs (new)
  // 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 Engineer.VesselSimulator;
  using KSP;
  using System;
  using System.Collections.Generic;
  using ToadicusTools;
  using UnityEngine;
 
  namespace VOID
  {
  public static class VOID_Data
  {
  #region Constants
 
  private static double kerbinGee;
 
  public static double KerbinGee
  {
  get
  {
  if (kerbinGee == default(double))
  {
  kerbinGee = core.Kerbin.gravParameter / (core.Kerbin.Radius * core.Kerbin.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<double>(() => core.vessel.atmDensity * 1000f),
  "g/m³"
  );
 
  public static readonly VOID_FloatValue atmLimit =
  new VOID_FloatValue(
  "Atmosphere Limit",
  new Func<float>(() => core.vessel.mainBody.maxAtmosphereAltitude),
  "m"
  );
 
  public static readonly VOID_DoubleValue atmPressure =
  new VOID_DoubleValue(
  "Pressure",
  new Func<double>(() => core.vessel.staticPressure),
  "atm"
  );
 
  public static readonly VOID_FloatValue temperature =
  new VOID_FloatValue(
  "Temperature",
  new Func<float>(() => 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<float>(() => core.vessel.ctrlState.mainThrottle * 100f),
  "%"
  );
 
  #endregion
 
  #region Engineering
 
  public static readonly VOID_IntValue partCount =
  new VOID_IntValue(
  "Parts",
  new Func<int>(() => 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.totalMass - core.LastStage.totalBaseMass;
  },
  "tons"
  );
 
  public static readonly VOID_DoubleValue stageResourceMass =
  new VOID_DoubleValue(
  "Resource Mass (Stage)",
  delegate()
  {
  if (core.LastStage == null)
  {
  return double.NaN;
  }
 
  return core.LastStage.mass - core.LastStage.baseMass;
  },
  "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<PartModule> engineModules = core.vessel.getModulesOfType<PartModule>();
 
  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<Propellant> propellantList = null;
 
  if (part.tryGetFirstModuleOfType<ModuleEngines>(out engineModule))
  {
  propellantList = engineModule.propellants;
  }
  else if (part.tryGetFirstModuleOfType<ModuleEnginesFX>(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<ModuleResourceIntake>(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<string>(() => VOID_Tools.GetLatitudeString(core.vessel))
  );
 
  public static readonly VOID_StrValue surfLongitude =
  new VOID_StrValue(
  "Longitude",
  new Func<string>(() => 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 surfVelocity =
  new VOID_DoubleValue(
  "Surface velocity",
  new Func<double>(() => core.vessel.srf_velocity.magnitude),
  "m/s"
  );
 
  public static readonly VOID_DoubleValue vertVelocity =
  new VOID_DoubleValue(
  "Vertical speed",
  new Func<double>(() => core.vessel.verticalSpeed),
  "m/s"
  );
 
  public static readonly VOID_DoubleValue horzVelocity =
  new VOID_DoubleValue(
  "Horizontal speed",
  new Func<double>(() => core.vessel.horizontalSrfSpeed),
  "m/s"
  );
 
  public static readonly VOID_DoubleValue geeForce =
  new VOID_DoubleValue(
  "G-force",
  new Func<double>(() => core.vessel.geeForce),
  "gees"
  );
 
 
  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 vesselAccel =
  new VOID_DoubleValue(
  "Acceleration",
  () => geeForce * KerbinGee,
  "m/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_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 (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_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.ConvertInterval(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.ConvertInterval(interval));
  }
  );
 
  #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<double>(() => core.vessel.orbit.altitude),
  "m"
  );
 
  public static readonly VOID_DoubleValue orbitVelocity =
  new VOID_DoubleValue(
  VOID_Localization.void_velocity,
  new Func<double>(() => core.vessel.orbit.vel.magnitude),
  "m/s"
  );
 
  public static readonly VOID_DoubleValue orbitApoAlt =
  new VOID_DoubleValue(
  VOID_Localization.void_apoapsis,
  new Func<double>(() => core.vessel.orbit.ApA),
  "m"
  );
 
  public static readonly VOID_DoubleValue oribtPeriAlt =
  new VOID_DoubleValue(
  VOID_Localization.void_periapsis,
  new Func<double>(() => core.vessel.orbit.PeA),
  "m"
  );
 
  public static readonly VOID_StrValue timeToApo =
  new VOID_StrValue(
  "Time to Apoapsis",
  new Func<string>(() => VOID_Tools.ConvertInterval(core.vessel.orbit.timeToAp))
  );
 
  public static readonly VOID_StrValue timeToPeri =
  new VOID_StrValue(
  "Time to Periapsis",
  new Func<string>(() => VOID_Tools.ConvertInterval(core.vessel.orbit.timeToPe))
  );
 
  public static readonly VOID_DoubleValue orbitInclination =
  new VOID_DoubleValue(
  "Inclination",
  new Func<double>(() => 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<string>(() => VOID_Tools.ConvertInterval(core.vessel.orbit.period))
  );
 
  public static readonly VOID_DoubleValue semiMajorAxis =
  new VOID_DoubleValue(
  "Semi-Major Axis",
  new Func<double>(() => core.vessel.orbit.semiMajorAxis),
  "m"
  );
 
  public static readonly VOID_DoubleValue eccentricity =
  new VOID_DoubleValue(
  "Eccentricity",
  new Func<double>(() => core.vessel.orbit.eccentricity),
  ""
  );
 
  public static readonly VOID_DoubleValue meanAnomaly =
  new VOID_DoubleValue(
  "Mean Anomaly",
  new Func<double>(() => core.vessel.orbit.meanAnomaly * 180d / Math.PI),
  "°"
  );
 
  public static readonly VOID_DoubleValue trueAnomaly =
  new VOID_DoubleValue(
  "True Anomaly",
  new Func<double>(() => core.vessel.orbit.trueAnomaly),
  "°"
  );
 
  public static readonly VOID_DoubleValue eccAnomaly =
  new VOID_DoubleValue(
  "Eccentric Anomaly",
  new Func<double>(() => core.vessel.orbit.eccentricAnomaly * 180d / Math.PI),
  "°"
  );
 
  public static readonly VOID_DoubleValue longitudeAscNode =
  new VOID_DoubleValue(
  "Long. Ascending Node",
  new Func<double>(() => core.vessel.orbit.LAN),
  "°"
  );
 
  public static readonly VOID_DoubleValue argumentPeriapsis =
  new VOID_DoubleValue(
  "Argument of Periapsis",
  new Func<double>(() => core.vessel.orbit.argumentOfPeriapsis),
  "°"
  );
 
  public static readonly VOID_DoubleValue localSiderealLongitude =
  new VOID_DoubleValue(
  "Local Sidereal Longitude",
  new Func<double>(() => 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<string>(() => core.vessel.GetExperimentSituation().HumanString())
  );
 
  public static readonly VOID_StrValue currBiome =
  new VOID_StrValue(
  "Biome",
  new Func<string>(() => VOID_Tools.GetBiome(core.vessel).name)
  );
 
  #endregion
 
  #region Surface
 
  public static readonly VOID_DoubleValue terrainElevation =
  new VOID_DoubleValue(
  "Terrain elevation",
  new Func<double>(() => 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));
  }
  }
  }
 
 
// VOID // VOID
// //
// VOID_HUD.cs // VOID_HUD.cs
// //
// Copyright © 2014, toadicus // Copyright © 2014, toadicus
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 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 // this list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be used // 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. // 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, // 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 // 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, // 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 // 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, // 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 // 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. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
using Engineer.VesselSimulator; using Engineer.VesselSimulator;
using KSP; using KSP;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using ToadicusTools; using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_HUD : VOID_Module, IVOID_Module public class VOID_HUD : VOID_Module, IVOID_Module
{ {
/* /*
* Fields * Fields
* */ * */
[AVOID_SaveValue("colorIndex")] [AVOID_SaveValue("colorIndex")]
protected VOID_SaveValue<int> _colorIndex; protected VOID_SaveValue<int> _colorIndex;
   
protected List<Color> textColors; protected List<Color> textColors;
   
protected Rect leftHUDdefaultPos; protected Rect leftHUDdefaultPos;
protected Rect rightHUDdefaultPos; protected Rect rightHUDdefaultPos;
   
[AVOID_SaveValue("leftHUDPos")] [AVOID_SaveValue("leftHUDPos")]
protected VOID_SaveValue<Rect> leftHUDPos; protected VOID_SaveValue<Rect> leftHUDPos;
[AVOID_SaveValue("rightHUDPos")] [AVOID_SaveValue("rightHUDPos")]
protected VOID_SaveValue<Rect> rightHUDPos; protected VOID_SaveValue<Rect> rightHUDPos;
   
[AVOID_SaveValue("positionsLocked")] [AVOID_SaveValue("positionsLocked")]
protected VOID_SaveValue<bool> positionsLocked; protected VOID_SaveValue<bool> positionsLocked;
   
/* /*
* Properties * Properties
* */ * */
public int ColorIndex public int ColorIndex
{ {
get get
{ {
return this._colorIndex; return this._colorIndex;
} }
set set
{ {
if (this._colorIndex >= this.textColors.Count - 1) if (this._colorIndex >= this.textColors.Count - 1)
{ {
this._colorIndex = 0; this._colorIndex = 0;
return; return;
} }
   
this._colorIndex = value; this._colorIndex = value;
} }
} }
   
/* /*
* Methods * Methods
* */ * */
public VOID_HUD() : base() public VOID_HUD() : base()
{ {
this._Name = "Heads-Up Display"; this._Name = "Heads-Up Display";
   
this.toggleActive = true; this.toggleActive = true;
   
this._colorIndex = 0; this._colorIndex = 0;
   
this.textColors = new List<Color>(); this.textColors = new List<Color>();
   
this.textColors.Add(Color.green); this.textColors.Add(Color.green);
this.textColors.Add(Color.black); this.textColors.Add(Color.black);
this.textColors.Add(Color.white); this.textColors.Add(Color.white);
this.textColors.Add(Color.red); this.textColors.Add(Color.red);
this.textColors.Add(Color.blue); this.textColors.Add(Color.blue);
this.textColors.Add(Color.yellow); this.textColors.Add(Color.yellow);
this.textColors.Add(Color.gray); this.textColors.Add(Color.gray);
this.textColors.Add(Color.cyan); this.textColors.Add(Color.cyan);
this.textColors.Add(Color.magenta); this.textColors.Add(Color.magenta);
   
this.leftHUDdefaultPos = new Rect(Screen.width * .375f - 300f, 0f, 300f, 90f); this.leftHUDdefaultPos = new Rect(Screen.width * .375f - 300f, 0f, 300f, 90f);
this.leftHUDPos = new Rect(this.leftHUDdefaultPos); this.leftHUDPos = new Rect(this.leftHUDdefaultPos);
   
this.rightHUDdefaultPos = new Rect(Screen.width * .625f, 0f, 300f, 90f); this.rightHUDdefaultPos = new Rect(Screen.width * .625f, 0f, 300f, 90f);
this.rightHUDPos = new Rect(this.rightHUDdefaultPos); this.rightHUDPos = new Rect(this.rightHUDdefaultPos);
   
this.positionsLocked = true; this.positionsLocked = true;
   
Tools.PostDebugMessage ("VOID_HUD: Constructed."); Tools.PostDebugMessage ("VOID_HUD: Constructed.");
} }
   
protected void leftHUDWindow(int id) protected void leftHUDWindow(int id)
{ {
StringBuilder leftHUD; StringBuilder leftHUD;
   
leftHUD = new StringBuilder(); leftHUD = new StringBuilder();
   
this.core.LabelStyles["hud"].alignment = TextAnchor.UpperRight; this.core.LabelStyles["hud"].alignment = TextAnchor.UpperRight;
   
if (this.core.powerAvailable) if (this.core.powerAvailable)
{ {
leftHUD.AppendFormat("Primary: {0} Inc: {1}", leftHUD.AppendFormat("Primary: {0} Inc: {1}",
VOID_Data.primaryName.ValueUnitString(), VOID_Data.primaryName.ValueUnitString(),
VOID_Data.orbitInclination.ValueUnitString("F3") VOID_Data.orbitInclination.ValueUnitString("F3")
); );
leftHUD.AppendFormat("\nObt Alt: {0} Obt Vel: {1}", leftHUD.AppendFormat("\nObt Alt: {0} Obt Vel: {1}",
VOID_Data.orbitAltitude.ToSIString(), VOID_Data.orbitAltitude.ToSIString(),
VOID_Data.orbitVelocity.ToSIString() VOID_Data.orbitVelocity.ToSIString()
); );
leftHUD.AppendFormat("\nAp: {0} ETA {1}", leftHUD.AppendFormat("\nAp: {0} ETA {1}",
VOID_Data.orbitApoAlt.ToSIString(), VOID_Data.orbitApoAlt.ToSIString(),
VOID_Data.timeToApo.ValueUnitString() VOID_Data.timeToApo.ValueUnitString()
); );
leftHUD.AppendFormat("\nPe: {0} ETA {1}", leftHUD.AppendFormat("\nPe: {0} ETA {1}",
VOID_Data.oribtPeriAlt.ToSIString(), VOID_Data.oribtPeriAlt.ToSIString(),
VOID_Data.timeToPeri.ValueUnitString() VOID_Data.timeToPeri.ValueUnitString()
); );
leftHUD.AppendFormat("\nTot Δv: {0} Stg Δv: {1}", leftHUD.AppendFormat("\nTot Δv: {0} Stg Δv: {1}",
VOID_Data.totalDeltaV.ToSIString(2), VOID_Data.totalDeltaV.ToSIString(2),
VOID_Data.stageDeltaV.ToSIString(2) VOID_Data.stageDeltaV.ToSIString(2)
); );
} }
else else
{ {
this.core.LabelStyles["hud"].normal.textColor = Color.red; this.core.LabelStyles["hud"].normal.textColor = Color.red;
leftHUD.Append(string.Intern("-- POWER LOST --")); leftHUD.Append(string.Intern("-- POWER LOST --"));
} }
   
GUILayout.Label(leftHUD.ToString(), this.core.LabelStyles["hud"], GUILayout.ExpandWidth(true)); GUILayout.Label(leftHUD.ToString(), this.core.LabelStyles["hud"], GUILayout.ExpandWidth(true));
   
if (!this.positionsLocked) if (!this.positionsLocked)
{ {
GUI.DragWindow(); GUI.DragWindow();
} }
   
GUI.BringWindowToBack(id); GUI.BringWindowToBack(id);
} }
   
protected void rightHUDWindow(int id) protected void rightHUDWindow(int id)
{ {
StringBuilder rightHUD; StringBuilder rightHUD;
   
rightHUD = new StringBuilder(); rightHUD = new StringBuilder();
   
this.core.LabelStyles["hud"].alignment = TextAnchor.UpperLeft; this.core.LabelStyles["hud"].alignment = TextAnchor.UpperLeft;
   
if (this.core.powerAvailable) if (this.core.powerAvailable)
{ {
rightHUD.AppendFormat("Biome: {0} Sit: {1}", rightHUD.AppendFormat("Biome: {0} Sit: {1}",
VOID_Data.currBiome.ValueUnitString(), VOID_Data.currBiome.ValueUnitString(),
VOID_Data.expSituation.ValueUnitString() VOID_Data.expSituation.ValueUnitString()
); );
rightHUD.AppendFormat("\nSrf Alt: {0} Srf Vel: {1}", rightHUD.AppendFormat("\nSrf Alt: {0} Srf Vel: {1}",
VOID_Data.trueAltitude.ToSIString(), VOID_Data.trueAltitude.ToSIString(),
VOID_Data.surfVelocity.ToSIString() VOID_Data.surfVelocity.ToSIString()
); );
rightHUD.AppendFormat("\nVer: {0} Hor: {1}", rightHUD.AppendFormat("\nVer: {0} Hor: {1}",
VOID_Data.vertVelocity.ToSIString(), VOID_Data.vertVelocity.ToSIString(),
VOID_Data.horzVelocity.ToSIString() VOID_Data.horzVelocity.ToSIString()
); );
rightHUD.AppendFormat("\nLat: {0} Lon: {1}", rightHUD.AppendFormat("\nLat: {0} Lon: {1}",
VOID_Data.surfLatitude.ValueUnitString(), VOID_Data.surfLatitude.ValueUnitString(),
VOID_Data.surfLongitude.ValueUnitString() VOID_Data.surfLongitude.ValueUnitString()
); );
rightHUD.AppendFormat("\nHdg: {0} Pit: {1}", rightHUD.AppendFormat("\nHdg: {0} Pit: {1}",
VOID_Data.vesselHeading.ValueUnitString(), VOID_Data.vesselHeading.ValueUnitString(),
VOID_Data.vesselPitch.ToSIString(2) VOID_Data.vesselPitch.ToSIString(2)
); );
   
if ( if (
this.core.vessel.mainBody == this.core.Kerbin && this.core.vessel.mainBody == this.core.Kerbin &&
( (
this.core.vessel.situation == Vessel.Situations.FLYING || this.core.vessel.situation == Vessel.Situations.FLYING ||
this.core.vessel.situation == Vessel.Situations.SUB_ORBITAL || this.core.vessel.situation == Vessel.Situations.SUB_ORBITAL ||
this.core.vessel.situation == Vessel.Situations.LANDED || this.core.vessel.situation == Vessel.Situations.LANDED ||
this.core.vessel.situation == Vessel.Situations.SPLASHED this.core.vessel.situation == Vessel.Situations.SPLASHED
) )
) )
{ {
rightHUD.AppendFormat("\nRange to KSC: {0}", VOID_Data.downrangeDistance.ValueUnitString(2)); rightHUD.AppendFormat("\nRange to KSC: {0}", VOID_Data.downrangeDistance.ValueUnitString(2));
} }
} }
else else
{ {
this.core.LabelStyles["hud"].normal.textColor = Color.red; this.core.LabelStyles["hud"].normal.textColor = Color.red;
rightHUD.Append(string.Intern("-- POWER LOST --")); rightHUD.Append(string.Intern("-- POWER LOST --"));
} }
   
   
GUILayout.Label(rightHUD.ToString(), this.core.LabelStyles["hud"], GUILayout.ExpandWidth(true)); GUILayout.Label(rightHUD.ToString(), this.core.LabelStyles["hud"], GUILayout.ExpandWidth(true));
   
if (!this.positionsLocked) if (!this.positionsLocked)
{ {
GUI.DragWindow(); GUI.DragWindow();
} }
   
GUI.BringWindowToBack(id); GUI.BringWindowToBack(id);
} }
   
public override void DrawGUI() public override void DrawGUI()
{ {
if (!this.core.LabelStyles.ContainsKey("hud")) if (!this.core.LabelStyles.ContainsKey("hud"))
{ {
this.core.LabelStyles["hud"] = new GUIStyle(GUI.skin.label); this.core.LabelStyles["hud"] = new GUIStyle(GUI.skin.label);
} }
   
this.core.LabelStyles["hud"].normal.textColor = textColors [ColorIndex]; this.core.LabelStyles["hud"].normal.textColor = textColors [ColorIndex];
   
GUI.skin = this.core.Skin; GUI.skin = this.core.Skin;
   
if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate)) if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate))
{ {
SimManager.RequestSimulation(); SimManager.RequestSimulation();
} }
   
this.leftHUDPos.value = GUI.Window( this.leftHUDPos.value = GUI.Window(
this.core.windowID, this.core.windowID,
this.leftHUDPos, this.leftHUDPos,
VOID_Tools.GetWindowHandler(this.leftHUDWindow), VOID_Tools.GetWindowHandler(this.leftHUDWindow),
GUIContent.none, GUIContent.none,
GUIStyle.none GUIStyle.none
); );
   
this.rightHUDPos.value = GUI.Window( this.rightHUDPos.value = GUI.Window(
this.core.windowID, this.core.windowID,
this.rightHUDPos, this.rightHUDPos,
VOID_Tools.GetWindowHandler(this.rightHUDWindow), VOID_Tools.GetWindowHandler(this.rightHUDWindow),
GUIContent.none, GUIContent.none,
GUIStyle.none GUIStyle.none
); );
} }
   
public override void DrawConfigurables() public override void DrawConfigurables()
{ {
if (GUILayout.Button (string.Intern("Change HUD color"), GUILayout.ExpandWidth (false))) if (GUILayout.Button (string.Intern("Change HUD color"), GUILayout.ExpandWidth (false)))
{ {
++this.ColorIndex; ++this.ColorIndex;
} }
   
if (GUILayout.Button(string.Intern("Reset HUD Positions"), GUILayout.ExpandWidth(false))) if (GUILayout.Button(string.Intern("Reset HUD Positions"), GUILayout.ExpandWidth(false)))
{ {
this.leftHUDPos = new Rect(this.leftHUDdefaultPos); this.leftHUDPos = new Rect(this.leftHUDdefaultPos);
this.rightHUDPos = new Rect(this.rightHUDdefaultPos); this.rightHUDPos = new Rect(this.rightHUDdefaultPos);
} }
   
this.positionsLocked = GUILayout.Toggle(this.positionsLocked, this.positionsLocked = GUILayout.Toggle(this.positionsLocked,
string.Intern("Lock HUD Positions"), string.Intern("Lock HUD Positions"),
GUILayout.ExpandWidth(false)); GUILayout.ExpandWidth(false));
} }
} }
   
public static partial class VOID_Data  
{  
public static readonly VOID_StrValue expSituation = new VOID_StrValue(  
"Situation",  
new Func<string> (() => core.vessel.GetExperimentSituation().HumanString())  
);  
   
public static readonly VOID_DoubleValue vesselPitch = new VOID_DoubleValue(  
"Pitch",  
() => core.vessel.getSurfacePitch(),  
"°"  
);  
   
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"  
);  
}  
} }
   
// VOID // VOID
// //
// VOID_HUD.cs // VOID_HUD.cs
// //
// Copyright © 2014, toadicus // Copyright © 2014, toadicus
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 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 // this list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be used // 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. // 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, // 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 // 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, // 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 // 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, // 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 // 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. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
using Engineer.VesselSimulator; using Engineer.VesselSimulator;
using KSP; using KSP;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using ToadicusTools; using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_HUDAdvanced : VOID_Module, IVOID_Module public class VOID_HUDAdvanced : VOID_Module, IVOID_Module
{ {
/* /*
* Fields * Fields
* */ * */
protected VOID_HUD primaryHUD; protected VOID_HUD primaryHUD;
   
protected Rect leftHUDdefaultPos; protected Rect leftHUDdefaultPos;
protected Rect rightHUDdefaultPos; protected Rect rightHUDdefaultPos;
   
[AVOID_SaveValue("leftHUDPos")] [AVOID_SaveValue("leftHUDPos")]
protected VOID_SaveValue<Rect> leftHUDPos; protected VOID_SaveValue<Rect> leftHUDPos;
[AVOID_SaveValue("rightHUDPos")] [AVOID_SaveValue("rightHUDPos")]
protected VOID_SaveValue<Rect> rightHUDPos; protected VOID_SaveValue<Rect> rightHUDPos;
   
[AVOID_SaveValue("positionsLocked")] [AVOID_SaveValue("positionsLocked")]
protected VOID_SaveValue<bool> positionsLocked; protected VOID_SaveValue<bool> positionsLocked;
   
/* /*
* Properties * Properties
* */ * */
public int ColorIndex public int ColorIndex
{ {
get get
{ {
if (this.primaryHUD == null) if (this.primaryHUD == null)
{ {
return 0; return 0;
} }
   
return this.primaryHUD.ColorIndex; return this.primaryHUD.ColorIndex;
} }
} }
   
/* /*
* Methods * Methods
* */ * */
public VOID_HUDAdvanced() : base() public VOID_HUDAdvanced() : base()
{ {
this._Name = "Advanced Heads-Up Display"; this._Name = "Advanced Heads-Up Display";
   
this.toggleActive = true; this.toggleActive = true;
   
this.leftHUDdefaultPos = new Rect( this.leftHUDdefaultPos = new Rect(
Screen.width * .5f - (float)GameSettings.UI_SIZE * .25f - 300f, Screen.width * .5f - (float)GameSettings.UI_SIZE * .25f - 300f,
Screen.height - 200f, Screen.height - 200f,
300f, 90f 300f, 90f
); );
this.leftHUDPos = new Rect(this.leftHUDdefaultPos); this.leftHUDPos = new Rect(this.leftHUDdefaultPos);
   
this.rightHUDdefaultPos = new Rect( this.rightHUDdefaultPos = new Rect(
Screen.width * .5f + (float)GameSettings.UI_SIZE * .25f, Screen.width * .5f + (float)GameSettings.UI_SIZE * .25f,
Screen.height - 200f, Screen.height - 200f,
300f, 90f 300f, 90f
); );
this.rightHUDPos = new Rect(this.rightHUDdefaultPos); this.rightHUDPos = new Rect(this.rightHUDdefaultPos);
   
this.positionsLocked = true; this.positionsLocked = true;
   
Tools.PostDebugMessage (this, "Constructed."); Tools.PostDebugMessage (this, "Constructed.");
} }
   
protected void leftHUDWindow(int id) protected void leftHUDWindow(int id)
{ {
StringBuilder leftHUD; StringBuilder leftHUD;
   
leftHUD = new StringBuilder(); leftHUD = new StringBuilder();
   
this.core.LabelStyles["hud"].alignment = TextAnchor.UpperRight; this.core.LabelStyles["hud"].alignment = TextAnchor.UpperRight;
   
if (this.core.powerAvailable) if (this.core.powerAvailable)
{ {
leftHUD.AppendFormat( leftHUD.AppendFormat(
string.Intern("Mass: {0}\n"), string.Intern("Mass: {0}\n"),
VOID_Data.totalMass.ToSIString(2) VOID_Data.totalMass.ToSIString(2)
); );
   
if (VOID_Data.vesselCrewCapacity > 0) if (VOID_Data.vesselCrewCapacity > 0)
{ {
leftHUD.AppendFormat( leftHUD.AppendFormat(
string.Intern("Crew: {0} / {1}\n"), string.Intern("Crew: {0} / {1}\n"),
VOID_Data.vesselCrewCount.Value, VOID_Data.vesselCrewCount.Value,
VOID_Data.vesselCrewCapacity.Value VOID_Data.vesselCrewCapacity.Value
); );
} }
   
leftHUD.AppendFormat( leftHUD.AppendFormat(
string.Intern("Acc: {0} T:W: {1}\n"), string.Intern("Acc: {0} T:W: {1}\n"),
VOID_Data.vesselAccel.ToSIString(2), VOID_Data.vesselAccel.ToSIString(2),
VOID_Data.currThrustWeight.Value.ToString("f2") VOID_Data.currThrustWeight.Value.ToString("f2")
); );
   
leftHUD.AppendFormat( leftHUD.AppendFormat(
string.Intern("Ang Vel: {0}\n"), string.Intern("Ang Vel: {0}\n"),
VOID_Data.vesselAngularVelocity.ToSIString(2) VOID_Data.vesselAngularVelocity.ToSIString(2)
); );
   
if (VOID_Data.stageNominalThrust != 0d) if (VOID_Data.stageNominalThrust != 0d)
{ {
leftHUD.AppendFormat( leftHUD.AppendFormat(
string.Intern("Thrust Offset: {0}\n"), string.Intern("Thrust Offset: {0}\n"),
VOID_Data.vesselThrustOffset.Value.ToString("F1") VOID_Data.vesselThrustOffset.Value.ToString("F1")
); );
} }
} }
else else
{ {
this.core.LabelStyles["hud"].normal.textColor = Color.red; this.core.LabelStyles["hud"].normal.textColor = Color.red;
leftHUD.Append(string.Intern("-- POWER LOST --")); leftHUD.Append(string.Intern("-- POWER LOST --"));
} }
   
GUILayout.Label(leftHUD.ToString(), this.core.LabelStyles["hud"], GUILayout.ExpandWidth(true)); GUILayout.Label(leftHUD.ToString(), this.core.LabelStyles["hud"], GUILayout.ExpandWidth(true));
   
if (!this.positionsLocked) if (!this.positionsLocked)
{ {
GUI.DragWindow(); GUI.DragWindow();
} }
   
GUI.BringWindowToBack(id); GUI.BringWindowToBack(id);
} }
   
protected void rightHUDWindow(int id) protected void rightHUDWindow(int id)
{ {
StringBuilder rightHUD; StringBuilder rightHUD;
   
rightHUD = new StringBuilder(); rightHUD = new StringBuilder();
   
this.core.LabelStyles["hud"].alignment = TextAnchor.UpperLeft; this.core.LabelStyles["hud"].alignment = TextAnchor.UpperLeft;
   
if (this.core.powerAvailable) if (this.core.powerAvailable)
{ {
rightHUD.AppendFormat( rightHUD.AppendFormat(
"Burn Δv (Rem/Tot): {0} / {1}\n", "Burn Δv (Rem/Tot): {0} / {1}\n",
VOID_Data.currManeuverDVRemaining.ValueUnitString("f2"), VOID_Data.currManeuverDVRemaining.ValueUnitString("f2"),
VOID_Data.currManeuverDeltaV.ValueUnitString("f2") VOID_Data.currManeuverDeltaV.ValueUnitString("f2")
); );
   
if (VOID_Data.upcomingManeuverNodes > 1) if (VOID_Data.upcomingManeuverNodes > 1)
{ {
rightHUD.AppendFormat("Next Burn Δv: {0}\n", rightHUD.AppendFormat("Next Burn Δv: {0}\n",
VOID_Data.nextManeuverDeltaV.ValueUnitString("f2") VOID_Data.nextManeuverDeltaV.ValueUnitString("f2")
); );
} }
   
rightHUD.AppendFormat("Burn Time (Rem/Total): {0} / {1}\n", rightHUD.AppendFormat("Burn Time (Rem/Total): {0} / {1}\n",
VOID_Tools.ConvertInterval(VOID_Data.currentNodeBurnRemaining.Value), VOID_Tools.ConvertInterval(VOID_Data.currentNodeBurnRemaining.Value),
VOID_Tools.ConvertInterval(VOID_Data.currentNodeBurnDuration.Value) VOID_Tools.ConvertInterval(VOID_Data.currentNodeBurnDuration.Value)
); );
   
if (VOID_Data.burnTimeDoneAtNode.Value != string.Empty) if (VOID_Data.burnTimeDoneAtNode.Value != string.Empty)
{ {
rightHUD.AppendFormat("{0} (done @ node)\n", rightHUD.AppendFormat("{0} (done @ node)\n",
VOID_Data.burnTimeDoneAtNode.Value VOID_Data.burnTimeDoneAtNode.Value
); );
   
rightHUD.AppendFormat("{0} (½ done @ node)", rightHUD.AppendFormat("{0} (½ done @ node)",
VOID_Data.burnTimeHalfDoneAtNode.Value VOID_Data.burnTimeHalfDoneAtNode.Value
); );
} }
else else
{ {
rightHUD.Append("Node is past"); rightHUD.Append("Node is past");
} }
} }
else else
{ {
this.core.LabelStyles["hud"].normal.textColor = Color.red; this.core.LabelStyles["hud"].normal.textColor = Color.red;
rightHUD.Append(string.Intern("-- POWER LOST --")); rightHUD.Append(string.Intern("-- POWER LOST --"));
} }
   
GUILayout.Label(rightHUD.ToString(), this.core.LabelStyles["hud"], GUILayout.ExpandWidth(true)); GUILayout.Label(rightHUD.ToString(), this.core.LabelStyles["hud"], GUILayout.ExpandWidth(true));
   
if (!this.positionsLocked) if (!this.positionsLocked)
{ {
GUI.DragWindow(); GUI.DragWindow();
} }
   
GUI.BringWindowToBack(id); GUI.BringWindowToBack(id);
} }
   
public override void DrawGUI() public override void DrawGUI()
{ {
if (this.primaryHUD == null) if (this.primaryHUD == null)
{ {
foreach (IVOID_Module module in this.core.Modules) foreach (IVOID_Module module in this.core.Modules)
{ {
if (module is VOID_HUD) if (module is VOID_HUD)
{ {
this.primaryHUD = module as VOID_HUD; this.primaryHUD = module as VOID_HUD;
} }
} }
} }
else else
{ {
if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate)) if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate))
{ {
SimManager.RequestSimulation(); SimManager.RequestSimulation();
} }
   
this.leftHUDPos.value = GUI.Window( this.leftHUDPos.value = GUI.Window(
this.core.windowID, this.core.windowID,
this.leftHUDPos, this.leftHUDPos,
VOID_Tools.GetWindowHandler(this.leftHUDWindow), VOID_Tools.GetWindowHandler(this.leftHUDWindow),
GUIContent.none, GUIContent.none,
GUIStyle.none GUIStyle.none
); );
   
if (VOID_Data.upcomingManeuverNodes > 0) if (VOID_Data.upcomingManeuverNodes > 0)
{ {
this.rightHUDPos.value = GUI.Window( this.rightHUDPos.value = GUI.Window(
this.core.windowID, this.core.windowID,
this.rightHUDPos, this.rightHUDPos,
VOID_Tools.GetWindowHandler(this.rightHUDWindow), VOID_Tools.GetWindowHandler(this.rightHUDWindow),
GUIContent.none, GUIContent.none,
GUIStyle.none GUIStyle.none
); );
} }
} }
} }
   
public override void DrawConfigurables() public override void DrawConfigurables()
{ {
this.positionsLocked = GUILayout.Toggle(this.positionsLocked, this.positionsLocked = GUILayout.Toggle(this.positionsLocked,
string.Intern("Lock Advanced HUD Positions"), string.Intern("Lock Advanced HUD Positions"),
GUILayout.ExpandWidth(false)); 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<PartModule> engineModules = core.vessel.getModulesOfType<PartModule>();  
   
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 (core.LastStage == null)  
{  
return double.NaN;  
}  
   
if (core.LastStage.actualThrust == 0d)  
{  
return core.LastStage.thrust;  
}  
else  
{  
return core.LastStage.actualThrust;  
}  
},  
"kN"  
);  
   
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 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 (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_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.ConvertInterval(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.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 * (1d - Math.Exp(-deltaV * massFlow / thrust));  
}  
}  
} }
   
// VOID // VOID
// //
// VOID_Orbital.cs // VOID_Orbital.cs
// //
// Copyright © 2014, toadicus // Copyright © 2014, toadicus
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 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 // this list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be used // 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. // 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, // 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 // 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, // 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 // 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, // 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 // 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. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
using KSP; using KSP;
using System; using System;
using ToadicusTools; using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_Orbital : VOID_WindowModule public class VOID_Orbital : VOID_WindowModule
{ {
[AVOID_SaveValue("toggleExtended")] [AVOID_SaveValue("toggleExtended")]
protected VOID_SaveValue<bool> toggleExtended = false; protected VOID_SaveValue<bool> toggleExtended = false;
   
[AVOID_SaveValue("precisionValues")] [AVOID_SaveValue("precisionValues")]
protected long _precisionValues = 230584300921369395; protected long _precisionValues = 230584300921369395;
protected IntCollection precisionValues; protected IntCollection precisionValues;
   
public VOID_Orbital() public VOID_Orbital()
{ {
this._Name = "Orbital Information"; this._Name = "Orbital Information";
   
this.WindowPos.x = Screen.width - 520f; this.WindowPos.x = Screen.width - 520f;
this.WindowPos.y = 250f; this.WindowPos.y = 250f;
} }
   
public override void ModuleWindow(int _) public override void ModuleWindow(int _)
{ {
int idx = 0; int idx = 0;
   
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
VOID_Data.primaryName.DoGUIHorizontal (); VOID_Data.primaryName.DoGUIHorizontal ();
   
this.precisionValues [idx]= (ushort)VOID_Data.orbitAltitude.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.orbitAltitude.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
this.precisionValues [idx]= (ushort)VOID_Data.orbitVelocity.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.orbitVelocity.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
this.precisionValues [idx]= (ushort)VOID_Data.orbitApoAlt.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.orbitApoAlt.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
VOID_Data.timeToApo.DoGUIHorizontal(); VOID_Data.timeToApo.DoGUIHorizontal();
   
this.precisionValues [idx]= (ushort)VOID_Data.oribtPeriAlt.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.oribtPeriAlt.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
VOID_Data.timeToPeri.DoGUIHorizontal(); VOID_Data.timeToPeri.DoGUIHorizontal();
   
VOID_Data.orbitInclination.DoGUIHorizontal("F3"); VOID_Data.orbitInclination.DoGUIHorizontal("F3");
   
this.precisionValues [idx]= (ushort)VOID_Data.gravityAccel.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.gravityAccel.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
this.toggleExtended.value = GUILayout.Toggle(this.toggleExtended, "Extended info"); this.toggleExtended.value = GUILayout.Toggle(this.toggleExtended, "Extended info");
   
if (this.toggleExtended) if (this.toggleExtended)
{ {
VOID_Data.orbitPeriod.DoGUIHorizontal(); VOID_Data.orbitPeriod.DoGUIHorizontal();
   
this.precisionValues [idx]= (ushort)VOID_Data.semiMajorAxis.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.semiMajorAxis.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
VOID_Data.eccentricity.DoGUIHorizontal("F4"); VOID_Data.eccentricity.DoGUIHorizontal("F4");
   
VOID_Data.meanAnomaly.DoGUIHorizontal("F3"); VOID_Data.meanAnomaly.DoGUIHorizontal("F3");
   
VOID_Data.trueAnomaly.DoGUIHorizontal("F3"); VOID_Data.trueAnomaly.DoGUIHorizontal("F3");
   
VOID_Data.eccAnomaly.DoGUIHorizontal("F3"); VOID_Data.eccAnomaly.DoGUIHorizontal("F3");
   
VOID_Data.longitudeAscNode.DoGUIHorizontal("F3"); VOID_Data.longitudeAscNode.DoGUIHorizontal("F3");
   
VOID_Data.argumentPeriapsis.DoGUIHorizontal("F3"); VOID_Data.argumentPeriapsis.DoGUIHorizontal("F3");
   
VOID_Data.localSiderealLongitude.DoGUIHorizontal("F3"); VOID_Data.localSiderealLongitude.DoGUIHorizontal("F3");
} }
   
GUILayout.EndVertical(); GUILayout.EndVertical();
GUI.DragWindow(); GUI.DragWindow();
} }
   
public override void LoadConfig () public override void LoadConfig ()
{ {
base.LoadConfig (); base.LoadConfig ();
   
this.precisionValues = new IntCollection (4, this._precisionValues); this.precisionValues = new IntCollection (4, this._precisionValues);
} }
   
public override void _SaveToConfig (KSP.IO.PluginConfiguration config) public override void _SaveToConfig (KSP.IO.PluginConfiguration config)
{ {
this._precisionValues = this.precisionValues.collection; this._precisionValues = this.precisionValues.collection;
   
base._SaveToConfig (config); 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<double> (() => core.vessel.orbit.altitude),  
"m"  
);  
   
public static readonly VOID_DoubleValue orbitVelocity = new VOID_DoubleValue (  
VOID_Localization.void_velocity,  
new Func<double> (() => core.vessel.orbit.vel.magnitude),  
"m/s"  
);  
   
public static readonly VOID_DoubleValue orbitApoAlt = new VOID_DoubleValue(  
VOID_Localization.void_apoapsis,  
new Func<double>(() => core.vessel.orbit.ApA),  
"m"  
);  
   
public static readonly VOID_DoubleValue oribtPeriAlt = new VOID_DoubleValue(  
VOID_Localization.void_periapsis,  
new Func<double>(() => core.vessel.orbit.PeA),  
"m"  
);  
   
public static readonly VOID_StrValue timeToApo = new VOID_StrValue(  
"Time to Apoapsis",  
new Func<string>(() => VOID_Tools.ConvertInterval(core.vessel.orbit.timeToAp))  
);  
   
public static readonly VOID_StrValue timeToPeri = new VOID_StrValue(  
"Time to Periapsis",  
new Func<string>(() => VOID_Tools.ConvertInterval(core.vessel.orbit.timeToPe))  
);  
   
public static readonly VOID_DoubleValue orbitInclination = new VOID_DoubleValue(  
"Inclination",  
new Func<double>(() => 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<string>(() => VOID_Tools.ConvertInterval(core.vessel.orbit.period))  
);  
   
public static readonly VOID_DoubleValue semiMajorAxis = new VOID_DoubleValue(  
"Semi-Major Axis",  
new Func<double>(() => core.vessel.orbit.semiMajorAxis),  
"m"  
);  
   
public static readonly VOID_DoubleValue eccentricity = new VOID_DoubleValue(  
"Eccentricity",  
new Func<double>(() => core.vessel.orbit.eccentricity),  
""  
);  
   
public static readonly VOID_DoubleValue meanAnomaly = new VOID_DoubleValue(  
"Mean Anomaly",  
new Func<double>(() => core.vessel.orbit.meanAnomaly * 180d / Math.PI),  
"°"  
);  
   
public static readonly VOID_DoubleValue trueAnomaly = new VOID_DoubleValue(  
"True Anomaly",  
new Func<double>(() => core.vessel.orbit.trueAnomaly),  
"°"  
);  
   
public static readonly VOID_DoubleValue eccAnomaly = new VOID_DoubleValue(  
"Eccentric Anomaly",  
new Func<double>(() => core.vessel.orbit.eccentricAnomaly * 180d / Math.PI),  
"°"  
);  
   
public static readonly VOID_DoubleValue longitudeAscNode = new VOID_DoubleValue(  
"Long. Ascending Node",  
new Func<double>(() => core.vessel.orbit.LAN),  
"°"  
);  
   
public static readonly VOID_DoubleValue argumentPeriapsis = new VOID_DoubleValue(  
"Argument of Periapsis",  
new Func<double>(() => core.vessel.orbit.argumentOfPeriapsis),  
"°"  
);  
   
public static readonly VOID_DoubleValue localSiderealLongitude = new VOID_DoubleValue(  
"Local Sidereal Longitude",  
new Func<double>(() => VOID_Tools.FixDegreeDomain(  
core.vessel.longitude + core.vessel.orbit.referenceBody.rotationAngle)),  
"°"  
);  
}  
} }
   
   
// VOID // VOID
// //
// VOID_SurfAtmo.cs // VOID_SurfAtmo.cs
// //
// Copyright © 2014, toadicus // Copyright © 2014, toadicus
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 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 // this list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be used // 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. // 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, // 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 // 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, // 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 // 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, // 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 // 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. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
using KSP; using KSP;
using System; using System;
using ToadicusTools; using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_SurfAtmo : VOID_WindowModule public class VOID_SurfAtmo : VOID_WindowModule
{ {
[AVOID_SaveValue("precisionValues")] [AVOID_SaveValue("precisionValues")]
protected long _precisionValues = 230584300921369395; protected long _precisionValues = 230584300921369395;
protected IntCollection precisionValues; protected IntCollection precisionValues;
   
public VOID_SurfAtmo() public VOID_SurfAtmo()
{ {
this._Name = "Surface & Atmospheric Information"; this._Name = "Surface & Atmospheric Information";
   
this.WindowPos.x = Screen.width - 260f; this.WindowPos.x = Screen.width - 260f;
this.WindowPos.y = 85; this.WindowPos.y = 85;
} }
   
public override void ModuleWindow(int _) public override void ModuleWindow(int _)
{ {
int idx = 0; int idx = 0;
   
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
this.precisionValues [idx]= (ushort)VOID_Data.trueAltitude.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.trueAltitude.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
VOID_Data.surfLatitude.DoGUIHorizontal (); VOID_Data.surfLatitude.DoGUIHorizontal ();
   
VOID_Data.surfLongitude.DoGUIHorizontal (); VOID_Data.surfLongitude.DoGUIHorizontal ();
   
VOID_Data.vesselHeading.DoGUIHorizontal (); VOID_Data.vesselHeading.DoGUIHorizontal ();
   
this.precisionValues [idx]= (ushort)VOID_Data.terrainElevation.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.terrainElevation.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
this.precisionValues[idx] = (ushort)VOID_Data.downrangeDistance.DoGUIHorizontal(this.precisionValues[idx]); this.precisionValues[idx] = (ushort)VOID_Data.downrangeDistance.DoGUIHorizontal(this.precisionValues[idx]);
idx++; idx++;
   
this.precisionValues [idx]= (ushort)VOID_Data.surfVelocity.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.surfVelocity.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
this.precisionValues [idx]= (ushort)VOID_Data.vertVelocity.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.vertVelocity.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
this.precisionValues [idx]= (ushort)VOID_Data.horzVelocity.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.horzVelocity.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
VOID_Data.temperature.DoGUIHorizontal ("F2"); VOID_Data.temperature.DoGUIHorizontal ("F2");
   
this.precisionValues [idx]= (ushort)VOID_Data.atmDensity.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.atmDensity.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
VOID_Data.atmPressure.DoGUIHorizontal ("F2"); VOID_Data.atmPressure.DoGUIHorizontal ("F2");
   
this.precisionValues [idx]= (ushort)VOID_Data.atmLimit.DoGUIHorizontal (this.precisionValues [idx]); this.precisionValues [idx]= (ushort)VOID_Data.atmLimit.DoGUIHorizontal (this.precisionValues [idx]);
idx++; idx++;
   
// Toadicus edit: added Biome // Toadicus edit: added Biome
VOID_Data.currBiome.DoGUIHorizontal (); VOID_Data.currBiome.DoGUIHorizontal ();
   
GUILayout.EndVertical(); GUILayout.EndVertical();
GUI.DragWindow(); GUI.DragWindow();
} }
   
public override void LoadConfig () public override void LoadConfig ()
{ {
base.LoadConfig (); base.LoadConfig ();
   
this.precisionValues = new IntCollection (4, this._precisionValues); this.precisionValues = new IntCollection (4, this._precisionValues);
} }
   
public override void _SaveToConfig (KSP.IO.PluginConfiguration config) public override void _SaveToConfig (KSP.IO.PluginConfiguration config)
{ {
this._precisionValues = this.precisionValues.collection; this._precisionValues = this.precisionValues.collection;
   
base._SaveToConfig (config); 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<string> (() => VOID_Tools.GetLatitudeString(core.vessel))  
);  
   
public static readonly VOID_StrValue surfLongitude = new VOID_StrValue(  
"Longitude",  
new Func<string> (() => 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<double> (() => core.vessel.terrainAltitude),  
"m"  
);  
   
public static readonly VOID_DoubleValue surfVelocity = new VOID_DoubleValue(  
"Surface velocity",  
new Func<double> (() => core.vessel.srf_velocity.magnitude),  
"m/s"  
);  
   
public static readonly VOID_DoubleValue vertVelocity = new VOID_DoubleValue(  
"Vertical speed",  
new Func<double> (() => core.vessel.verticalSpeed),  
"m/s"  
);  
   
public static readonly VOID_DoubleValue horzVelocity = new VOID_DoubleValue(  
"Horizontal speed",  
new Func<double> (() => core.vessel.horizontalSrfSpeed),  
"m/s"  
);  
   
public static readonly VOID_FloatValue temperature = new VOID_FloatValue(  
"Temperature",  
new Func<float> (() => core.vessel.flightIntegrator.getExternalTemperature()),  
"°C"  
);  
   
public static readonly VOID_DoubleValue atmDensity = new VOID_DoubleValue (  
"Atmosphere Density",  
new Func<double> (() => core.vessel.atmDensity * 1000f),  
"g/m³"  
);  
   
public static readonly VOID_DoubleValue atmPressure = new VOID_DoubleValue (  
"Pressure",  
new Func<double> (() => core.vessel.staticPressure),  
"atm"  
);  
   
public static readonly VOID_FloatValue atmLimit = new VOID_FloatValue(  
"Atmosphere Limit",  
new Func<float> (() => core.vessel.mainBody.maxAtmosphereAltitude),  
"m"  
);  
   
public static readonly VOID_StrValue currBiome = new VOID_StrValue(  
"Biome",  
new Func<string> (() => VOID_Tools.GetBiome(core.vessel).name)  
);  
   
}  
} }
// VOID © 2014 toadicus // VOID © 2014 toadicus
// //
// This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a // 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/ // copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/
   
using KSP; using KSP;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using ToadicusTools; using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_TWR : VOID_WindowModule public class VOID_TWR : VOID_WindowModule
{ {
public VOID_TWR() : base() public VOID_TWR() : base()
{ {
this._Name = "IP Thrust-to-Weight Ratios"; this._Name = "IP Thrust-to-Weight Ratios";
} }
   
public override void ModuleWindow(int _) public override void ModuleWindow(int _)
{ {
if ( if (
HighLogic.LoadedSceneIsEditor || HighLogic.LoadedSceneIsEditor ||
(TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.WarpMode == TimeWarp.Modes.LOW) ||
(TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate) (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate)
) )
{ {
Engineer.VesselSimulator.SimManager.RequestSimulation(); Engineer.VesselSimulator.SimManager.RequestSimulation();
} }
   
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
if (core.sortedBodyList == null) if (core.sortedBodyList == null)
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
   
GUILayout.Label("Unavailable"); GUILayout.Label("Unavailable");
   
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
else else
{ {
foreach (CelestialBody body in core.sortedBodyList) foreach (CelestialBody body in core.sortedBodyList)
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
   
GUILayout.Label(body.bodyName); GUILayout.Label(body.bodyName);
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
GUILayout.Label( GUILayout.Label(
(VOID_Data.nominalThrustWeight.Value / body.GeeASL).ToString("0.0##"), (VOID_Data.nominalThrustWeight.Value / body.GeeASL).ToString("0.0##"),
GUILayout.ExpandWidth(true) GUILayout.ExpandWidth(true)
); );
   
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
} }
   
GUILayout.EndVertical(); GUILayout.EndVertical();
   
GUI.DragWindow(); GUI.DragWindow();
} }
} }
   
public class VOID_EditorTWR : VOID_TWR, IVOID_EditorModule {} 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;  
},  
""  
);  
}  
} }
   
   
// VOID // VOID
// //
// VOID_VesselInfo.cs // VOID_VesselInfo.cs
// //
// Copyright © 2014, toadicus // Copyright © 2014, toadicus
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 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 // this list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be used // 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. // 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, // 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 // 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, // 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 // 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, // 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 // 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. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
using Engineer.VesselSimulator; using Engineer.VesselSimulator;
using Engineer.Extensions; using Engineer.Extensions;
using KSP; using KSP;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using ToadicusTools; using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_VesselInfo : VOID_WindowModule public class VOID_VesselInfo : VOID_WindowModule
{ {
public VOID_VesselInfo() : base() public VOID_VesselInfo() : base()
{ {
this._Name = "Vessel Information"; this._Name = "Vessel Information";
   
this.WindowPos.x = Screen.width - 260; this.WindowPos.x = Screen.width - 260;
this.WindowPos.y = 450; this.WindowPos.y = 450;
} }
   
public override void ModuleWindow(int _) public override void ModuleWindow(int _)
{ {
if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate)) if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate))
{ {
SimManager.RequestSimulation(); SimManager.RequestSimulation();
} }
   
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
GUILayout.Label( GUILayout.Label(
vessel.vesselName, vessel.vesselName,
VOID_Styles.labelCenterBold, VOID_Styles.labelCenterBold,
GUILayout.ExpandWidth(true)); GUILayout.ExpandWidth(true));
   
VOID_Data.geeForce.DoGUIHorizontal ("F2"); VOID_Data.geeForce.DoGUIHorizontal ("F2");
   
VOID_Data.partCount.DoGUIHorizontal (); VOID_Data.partCount.DoGUIHorizontal ();
   
VOID_Data.totalMass.DoGUIHorizontal ("F3"); VOID_Data.totalMass.DoGUIHorizontal ("F3");
   
VOID_Data.stageResourceMass.DoGUIHorizontal("F2"); VOID_Data.stageResourceMass.DoGUIHorizontal("F2");
   
VOID_Data.resourceMass.DoGUIHorizontal("F2"); VOID_Data.resourceMass.DoGUIHorizontal("F2");
   
VOID_Data.stageDeltaV.DoGUIHorizontal (3, false); VOID_Data.stageDeltaV.DoGUIHorizontal (3, false);
   
VOID_Data.totalDeltaV.DoGUIHorizontal (3, false); VOID_Data.totalDeltaV.DoGUIHorizontal (3, false);
   
VOID_Data.mainThrottle.DoGUIHorizontal ("F0"); VOID_Data.mainThrottle.DoGUIHorizontal ("F0");
   
VOID_Data.currmaxThrust.DoGUIHorizontal (); VOID_Data.currmaxThrust.DoGUIHorizontal ();
   
VOID_Data.currmaxThrustWeight.DoGUIHorizontal (); VOID_Data.currmaxThrustWeight.DoGUIHorizontal ();
   
VOID_Data.surfaceThrustWeight.DoGUIHorizontal ("F2"); VOID_Data.surfaceThrustWeight.DoGUIHorizontal ("F2");
   
VOID_Data.intakeAirStatus.DoGUIHorizontal(); VOID_Data.intakeAirStatus.DoGUIHorizontal();
   
GUILayout.EndVertical(); GUILayout.EndVertical();
   
GUI.DragWindow(); GUI.DragWindow();
} }
} }
   
public static partial class VOID_Data  
{  
public static readonly VOID_DoubleValue geeForce = new VOID_DoubleValue(  
"G-force",  
new Func<double>(() => core.vessel.geeForce),  
"gees"  
);  
   
public static readonly VOID_IntValue partCount = new VOID_IntValue(  
"Parts",  
new Func<int>(() => core.vessel.Parts.Count),  
""  
);  
   
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"  
);  
   
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.totalMass - core.LastStage.totalBaseMass;  
},  
"tons"  
);  
   
public static readonly VOID_DoubleValue stageResourceMass = new VOID_DoubleValue(  
"Resource Mass (Stage)",  
delegate()  
{  
if (core.LastStage == null)  
{  
return double.NaN;  
}  
   
return core.LastStage.mass - core.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 (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"  
);  
   
public static readonly VOID_FloatValue mainThrottle = new VOID_FloatValue(  
"Throttle",  
new Func<float>(() => core.vessel.ctrlState.mainThrottle * 100f),  
"%"  
);  
   
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 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_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_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_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<Propellant> propellantList = null;  
   
if (part.tryGetFirstModuleOfType<ModuleEngines>(out engineModule))  
{  
propellantList = engineModule.propellants;  
}  
else if (part.tryGetFirstModuleOfType<ModuleEnginesFX>(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<ModuleResourceIntake>(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);  
}  
);  
}  
} }